Skip to content

Commit

Permalink
Identity staking follow up (#2976)
Browse files Browse the repository at this point in the history
* refactoring score-staking event, adding new event

* exporting primitives types

* adding new parentchain event and filters

* injecting ocall_api and state_handler to the parentchain event handler

* adding missing dependencies

* adding key helper

* passing block_header to handle_events

* updating generics for the event handler

* adding ParentchainEventProcessingError variant

* fixing generics

* draft logic of the staking updates logic, getting necessary data from
the parentchain storage and idgraphs

* adding dependency to send extrinsics from the event handler

* refactoring collected data to make it easier to operate

* refactoring how idgraphs are collected

* tentative logic to update scores

* updating TODO

* fixing staking amount calculation

* cleaning up unused code

* updating pallet events and fixing pallet tests

* updating parentchain events

* adding new field for id_graph rewards

* adding update_token_staking_amount call to pallet score-staking

* adding missing dependencies

* updating score-staking mock

* adding tests

* fixing Cargo.toml format issue

* adding extrinsic to complete reward distribution

* adding tests

* updating node-api metadata, including staking-score calls

* updating metadata mocks

* injecting node metadata repository to ParentchainEventHandler

* sending extrinsics to the parentchain to update staking scores and
complete rewards distribution

* making score-staking pallet loosely coupled to teebag

* updating mock

* updating runtimes

* removing TODO

* updating commend

* updating precompiles mock

* fixing precompiles tests

* fixing clippy issues

* adding trusted calls to avoid sending duplicated extrinsics on
multiworker setup

* updating event_handler to submit the new trusted calls

* cleaning up dependencies that are not needed anymore

* more clean up

* adding NodeMetadataProvider trait to extend trait bounds

* exposing compose_call from api-client-types

* refactoring to send calls in batches

* updating pallet to only update non distributed staking amounts

* removing added trusted calls

* updating event

* injecting node_metadata_repository to the event handler

* refactoring event handler

* fixing precompiles tests

* making use of the existing EnsureEnclaveSigner struct

* fixing mocks

* making the distribution directly instead of storing the amount to token_staking_amount

* fixing precompiles tests

* reverting try_successful_origin

* reverting it in identity-management as well

* fixing precompiles mock

* fixing precompiles score-staking mock
  • Loading branch information
silva-fj committed Sep 18, 2024
1 parent 867777f commit 2f55394
Show file tree
Hide file tree
Showing 34 changed files with 916 additions and 151 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

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

5 changes: 5 additions & 0 deletions pallets/score-staking/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ serde = { workspace = true }
frame-benchmarking = { workspace = true, optional = true }
frame-support = { workspace = true }
frame-system = { workspace = true }
pallet-timestamp = { workspace = true }
sp-core = { workspace = true }
sp-runtime = { workspace = true }
sp-std = { workspace = true }

core-primitives = { workspace = true }
pallet-parachain-staking = { workspace = true }
pallet-teebag = { workspace = true }

[dev-dependencies]
sp-io = { workspace = true }
Expand All @@ -42,12 +44,15 @@ std = [
"pallet-balances/std",
"core-primitives/std",
"pallet-parachain-staking/std",
"pallet-teebag/std",
"pallet-timestamp/std",
]
runtime-benchmarks = [
"frame-benchmarking/runtime-benchmarks",
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"pallet-timestamp/runtime-benchmarks",
]
try-runtime = [
"frame-support/try-runtime",
Expand Down
88 changes: 79 additions & 9 deletions pallets/score-staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ pub mod pallet {
type AdminOrigin: EnsureOrigin<Self::RuntimeOrigin>;
/// AccountId converter
type AccountIdConvert: AccountIdConvert<Self>;
// For extrinsics that should only be called by origins from TEE
type TEECallOrigin: EnsureOrigin<Self::RuntimeOrigin>;
}

#[pallet::error]
Expand Down Expand Up @@ -150,20 +152,45 @@ pub mod pallet {
ScoreUserCountUnderflow,
// when the score user count would exceed `MaxScoreUserCount`
MaxScoreUserCountReached,
// the token staking amount has been updated already for the round
TokenStakingAmountAlreadyUpdated,
}

#[pallet::event]
#[pallet::generate_deposit(pub (crate) fn deposit_event)]
pub enum Event<T: Config> {
PoolStarted { start_block: BlockNumberFor<T> },
PoolStarted {
start_block: BlockNumberFor<T>,
},
PoolStopped {},
ScoreFeederSet { new_score_feeder: Option<T::AccountId> },
RoundConfigSet { new_config: RoundSetting },
ScoreUpdated { who: Identity, new_score: Score },
ScoreRemoved { who: Identity },
ScoreFeederSet {
new_score_feeder: Option<T::AccountId>,
},
RoundConfigSet {
new_config: RoundSetting,
},
ScoreUpdated {
who: Identity,
new_score: Score,
},
ScoreRemoved {
who: Identity,
},
ScoreCleared {},
RewardCalculated { total: BalanceOf<T>, distributed: BalanceOf<T> },
RewardClaimed { who: T::AccountId, amount: BalanceOf<T> },
TokenStakingAmountUpdated {
account: T::AccountId,
amount: BalanceOf<T>,
},
RewardDistributionStarted {
total: BalanceOf<T>,
distributed: BalanceOf<T>,
round_index: RoundIndex,
},
RewardDistributionCompleted {},
RewardClaimed {
who: T::AccountId,
amount: BalanceOf<T>,
},
}

#[pallet::storage]
Expand Down Expand Up @@ -242,7 +269,8 @@ pub mod pallet {

// We are about to start a new round
// 1. update round info
r.index = r.index.saturating_add(1);
let round_index = r.index.saturating_add(1);
r.index = round_index;
r.start_block = now;
Round::<T>::put(r);
weight = weight.saturating_add(T::DbWeight::get().reads_writes(1, 1));
Expand Down Expand Up @@ -279,9 +307,10 @@ pub mod pallet {
weight = weight.saturating_add(T::DbWeight::get().reads_writes(2, 1));
}

Self::deposit_event(Event::<T>::RewardCalculated {
Self::deposit_event(Event::<T>::RewardDistributionStarted {
total: round_reward,
distributed: all_user_reward,
round_index,
});

weight
Expand Down Expand Up @@ -445,6 +474,47 @@ pub mod pallet {
let payment = Scores::<T>::get(&account).ok_or(Error::<T>::UserNotExist)?;
Self::claim(origin, payment.unpaid_reward)
}

#[pallet::call_index(9)]
#[pallet::weight((195_000_000, DispatchClass::Normal))]
pub fn update_token_staking_amount(
origin: OriginFor<T>,
account: T::AccountId,
amount: BalanceOf<T>,
round_index: RoundIndex,
) -> DispatchResultWithPostInfo {
let _ = T::TEECallOrigin::ensure_origin(origin)?;

match Scores::<T>::get(&account) {
Some(mut s) => {
if round_index <= s.last_token_distributed_round {
return Err(Error::<T>::TokenStakingAmountAlreadyUpdated.into());
}
let last_round = Round::<T>::get();
s.last_round_reward += amount;
s.total_reward += amount;
s.unpaid_reward += amount;
s.last_token_distributed_round = last_round.index;
Scores::<T>::insert(account.clone(), s);
Self::deposit_event(Event::TokenStakingAmountUpdated {
account: account.clone(),
amount,
});
Ok(Pays::No.into())
},
None => Err(Error::<T>::UserNotExist.into()),
}
}

#[pallet::call_index(10)]
#[pallet::weight((195_000_000, DispatchClass::Normal))]
pub fn complete_reward_distribution(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
let _ = T::TEECallOrigin::ensure_origin(origin)?;

Self::deposit_event(Event::RewardDistributionCompleted {});

Ok(Pays::No.into())
}
}
}

Expand Down
74 changes: 73 additions & 1 deletion pallets/score-staking/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@
use crate::{
self as pallet_score_staking, AccountIdConvert, Config, Perbill, PoolState, RoundSetting,
};
use core::marker::PhantomData;
use frame_support::{
assert_ok, construct_runtime, ord_parameter_types, parameter_types,
assert_ok, construct_runtime, ord_parameter_types,
pallet_prelude::EnsureOrigin,
parameter_types,
traits::{OnFinalize, OnInitialize},
};
use frame_system::{EnsureRoot, EnsureSignedBy};
Expand Down Expand Up @@ -51,6 +54,7 @@ construct_runtime!(
Balances: pallet_balances,
ParachainStaking: pallet_parachain_staking,
ScoreStaking: pallet_score_staking,
Teebag: pallet_teebag,
}
);

Expand Down Expand Up @@ -166,6 +170,66 @@ impl pallet_score_staking::Config for Test {
type YearlyIssuance = ConstU128<{ 100_000_000 * UNIT }>;
type YearlyInflation = DefaultYearlyInflation;
type MaxScoreUserCount = ConstU32<2>;
type TEECallOrigin = EnsureEnclaveSigner<Self>;
}

parameter_types! {
pub const MinimumPeriod: u64 = 6000 / 2;
}

pub type Moment = u64;

impl pallet_timestamp::Config for Test {
type Moment = Moment;
type OnTimestampSet = ();
type MinimumPeriod = MinimumPeriod;
type WeightInfo = ();
}

parameter_types! {
pub const MomentsPerDay: u64 = 86_400_000; // [ms/d]
}

impl pallet_teebag::Config for Test {
type RuntimeEvent = RuntimeEvent;
type MomentsPerDay = MomentsPerDay;
type SetAdminOrigin = EnsureRoot<Self::AccountId>;
type MaxEnclaveIdentifier = ConstU32<1>;
type MaxAuthorizedEnclave = ConstU32<2>;
type WeightInfo = ();
}

pub struct EnsureEnclaveSigner<T>(PhantomData<T>);
impl<T> EnsureOrigin<T::RuntimeOrigin> for EnsureEnclaveSigner<T>
where
T: frame_system::Config + pallet_teebag::Config + pallet_timestamp::Config<Moment = u64>,
<T as frame_system::Config>::AccountId: From<[u8; 32]>,
<T as frame_system::Config>::Hash: From<[u8; 32]>,
{
type Success = T::AccountId;
fn try_origin(o: T::RuntimeOrigin) -> Result<Self::Success, T::RuntimeOrigin> {
o.into().and_then(|o| match o {
frame_system::RawOrigin::Signed(who)
if pallet_teebag::EnclaveRegistry::<T>::contains_key(&who) =>
{
Ok(who)
},
r => Err(T::RuntimeOrigin::from(r)),
})
}

#[cfg(feature = "runtime-benchmarks")]
fn try_successful_origin() -> Result<T::RuntimeOrigin, ()> {
use pallet_teebag::test_util::{get_signer, TEST8_MRENCLAVE, TEST8_SIGNER_PUB};
let signer: <T as frame_system::Config>::AccountId = get_signer(TEST8_SIGNER_PUB);
if !pallet_teebag::EnclaveRegistry::<T>::contains_key(signer.clone()) {
assert_ok!(pallet_teebag::Pallet::<T>::add_enclave(
&signer,
&pallet_teebag::Enclave::default().with_mrenclave(TEST8_MRENCLAVE),
));
}
Ok(frame_system::RawOrigin::Signed(signer).into())
}
}

pub fn alice() -> AccountId {
Expand All @@ -186,6 +250,14 @@ pub fn new_test_ext(fast_round: bool) -> sp_io::TestExternalities {
.assimilate_storage(&mut t)
.unwrap();

pallet_teebag::GenesisConfig::<Test> {
allow_sgx_debug_mode: true,
admin: Some(AccountKeyring::Alice.to_account_id()),
mode: pallet_teebag::OperationalMode::Production,
}
.assimilate_storage(&mut t)
.unwrap();

pallet_score_staking::GenesisConfig::<Test> {
state: PoolState::Stopped,
marker: Default::default(),
Expand Down
Loading

0 comments on commit 2f55394

Please sign in to comment.