From 2e4ce7f55894032064dce0d8ed9abe0a190df33f Mon Sep 17 00:00:00 2001
From: thiolliere <gui.thiolliere@gmail.com>
Date: Wed, 14 Aug 2019 14:41:20 +0200
Subject: [PATCH] Reward validity statements from validators (#356)

* impl reward

* typo

* more clean RewardAttestation trait

* reward by index

* address grumble
---
 polkadot/runtime/src/attestations.rs | 48 ++++++++++++++++++++++------
 polkadot/runtime/src/lib.rs          |  1 +
 polkadot/runtime/src/parachains.rs   |  2 +-
 3 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/polkadot/runtime/src/attestations.rs b/polkadot/runtime/src/attestations.rs
index 528f010c534..c00cca74f6a 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 fff19c6fd7b..84d4ae62195 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 53050c1799d..b6b52351c53 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 {
-- 
GitLab