diff --git a/polkadot/runtime/src/attestations.rs b/polkadot/runtime/src/attestations.rs index 528f010c53484d2add79718dcc5a2c73b802c696..c00cca74f6a88aba3402162f8dbd13a5b8bb22a3 100644 --- a/polkadot/runtime/src/attestations.rs +++ b/polkadot/runtime/src/attestations.rs @@ -60,12 +60,39 @@ pub struct BlockAttestations<T: Trait> { #[cfg_attr(feature = "std", derive(Debug))] pub struct MoreAttestations; +/// Something which processes rewards for received attestations. +pub trait RewardAttestation { + /// Reward immediate attestations on parachain blocks. The argument is an iterable of + /// validator indices of the attesting validators. + fn reward_immediate(validator_indices: impl IntoIterator<Item=u32>); +} + +impl RewardAttestation for () { + fn reward_immediate(validator_indices: impl IntoIterator<Item=u32>) { + // ensure side-effecting iterators do work. + for _ in validator_indices {} + } +} + +impl<T: staking::Trait> RewardAttestation for staking::Module<T> { + fn reward_immediate(validator_indices: impl IntoIterator<Item=u32>) { + // The number of points to reward for a validity statement. + // https://research.web3.foundation/en/latest/polkadot/Token%20Economics/#payment-details + const STAKING_REWARD_POINTS: u32 = 20; + + Self::reward_by_indices(validator_indices.into_iter().map(|i| (i, STAKING_REWARD_POINTS))) + } +} + pub trait Trait: session::Trait { /// How many blocks ago we're willing to accept attestations for. type AttestationPeriod: Get<Self::BlockNumber>; /// Get a list of the validators' underlying identities. type ValidatorIdentities: Get<Vec<Self::AccountId>>; + + /// Hook for rewarding validators upon attesting. + type RewardAttestation: RewardAttestation; } decl_storage! { @@ -118,16 +145,19 @@ impl<T: Trait> Module<T> { let mut valid = Vec::new(); let invalid = Vec::new(); - for (auth_index, _) in head.validator_indices - .iter() - .enumerate() - .filter(|(_, bit)| *bit) { - let stash_id = validators.get(auth_index) - .expect("auth_index checked to be within bounds in `check_candidates`; qed") - .clone(); - - valid.push(stash_id); + let attesting_indices = head.validator_indices + .iter() + .enumerate() + .filter(|(_, bit)| *bit) + .inspect(|&(auth_index, _)| { + if let Some(stash_id) = validators.get(auth_index) { + valid.push(stash_id.clone()); + } + }) + .map(|(i, _)| i as u32); + + T::RewardAttestation::reward_immediate(attesting_indices); } let summary = BlockAttestations { diff --git a/polkadot/runtime/src/lib.rs b/polkadot/runtime/src/lib.rs index fff19c6fd7b3256d7002ea67f014e97bbd375725..84d4ae6219546d3b9ab681e98929571553715d18 100644 --- a/polkadot/runtime/src/lib.rs +++ b/polkadot/runtime/src/lib.rs @@ -429,6 +429,7 @@ parameter_types! { impl attestations::Trait for Runtime { type AttestationPeriod = AttestationPeriod; type ValidatorIdentities = parachains::ValidatorIdentities<Runtime>; + type RewardAttestation = Staking; } impl parachains::Trait for Runtime { diff --git a/polkadot/runtime/src/parachains.rs b/polkadot/runtime/src/parachains.rs index 53050c1799de74f090a68f73f28aa170bbbc8433..b6b52351c53e19275a57f9098551ef1db2590db2 100644 --- a/polkadot/runtime/src/parachains.rs +++ b/polkadot/runtime/src/parachains.rs @@ -321,7 +321,6 @@ decl_module! { } let para_blocks = Self::check_candidates(&heads, &active_parachains)?; - let current_number = <system::Module<T>>::block_number(); <attestations::Module<T>>::note_included(&heads, para_blocks); @@ -1019,6 +1018,7 @@ mod tests { impl attestations::Trait for Test { type AttestationPeriod = AttestationPeriod; type ValidatorIdentities = ValidatorIdentities<Test>; + type RewardAttestation = (); } impl Trait for Test {