mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 15:11:02 +00:00
Reward validators for participating in parachains (#2089)
* plumbing for rewarding backers * give validators reward points for participating * fix tests * add bitfield rewarding * add mocks for backing rewards * add testing for backing & availability rewards * implement RewardValidators on top of staking * add to test-runtime and rococo * add to test-runtime & rococo * point to source on rewards values * fix common tests * do not reward availability anymore
This commit is contained in:
committed by
GitHub
parent
34e5812171
commit
f4e930529b
@@ -62,6 +62,8 @@ pub struct CandidatePendingAvailability<H, N> {
|
||||
descriptor: CandidateDescriptor<H>,
|
||||
/// The received availability votes. One bit per validator.
|
||||
availability_votes: BitVec<BitOrderLsb0, u8>,
|
||||
/// The backers of the candidate pending availability.
|
||||
backers: BitVec<BitOrderLsb0, u8>,
|
||||
/// The block number of the relay-parent of the receipt.
|
||||
relay_parent_number: N,
|
||||
/// The block number of the relay-chain block this was backed in.
|
||||
@@ -85,6 +87,16 @@ impl<H, N> CandidatePendingAvailability<H, N> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A hook for applying validator rewards
|
||||
pub trait RewardValidators {
|
||||
// Reward the validators with the given indices for issuing backing statements.
|
||||
fn reward_backing(validators: impl IntoIterator<Item=ValidatorIndex>);
|
||||
// Reward the validators with the given indices for issuing availability bitfields.
|
||||
// Validators are sent to this hook when they have contributed to the availability
|
||||
// of a candidate by setting a bit in their bitfield.
|
||||
fn reward_bitfields(validators: impl IntoIterator<Item=ValidatorIndex>);
|
||||
}
|
||||
|
||||
pub trait Config:
|
||||
frame_system::Config
|
||||
+ paras::Config
|
||||
@@ -94,6 +106,7 @@ pub trait Config:
|
||||
+ configuration::Config
|
||||
{
|
||||
type Event: From<Event<Self>> + Into<<Self as frame_system::Config>::Event>;
|
||||
type RewardValidators: RewardValidators;
|
||||
}
|
||||
|
||||
decl_storage! {
|
||||
@@ -341,6 +354,8 @@ impl<T: Config> Module<T> {
|
||||
Self::enact_candidate(
|
||||
pending_availability.relay_parent_number,
|
||||
receipt,
|
||||
pending_availability.backers,
|
||||
pending_availability.availability_votes,
|
||||
);
|
||||
|
||||
freed_cores.push(pending_availability.core);
|
||||
@@ -375,9 +390,9 @@ impl<T: Config> Module<T> {
|
||||
let check_cx = CandidateCheckContext::<T>::new();
|
||||
|
||||
// do all checks before writing storage.
|
||||
let core_indices = {
|
||||
let core_indices_and_backers = {
|
||||
let mut skip = 0;
|
||||
let mut core_indices = Vec::with_capacity(candidates.len());
|
||||
let mut core_indices_and_backers = Vec::with_capacity(candidates.len());
|
||||
let mut last_core = None;
|
||||
|
||||
let mut check_assignment_in_order = |assignment: &CoreAssignment| -> DispatchResult {
|
||||
@@ -408,6 +423,7 @@ impl<T: Config> Module<T> {
|
||||
'a:
|
||||
for (candidate_idx, candidate) in candidates.iter().enumerate() {
|
||||
let para_id = candidate.descriptor().para_id;
|
||||
let mut backers = bitvec::bitvec![BitOrderLsb0, u8; 0; validators.len()];
|
||||
|
||||
// we require that the candidate is in the context of the parent block.
|
||||
ensure!(
|
||||
@@ -504,9 +520,19 @@ impl<T: Config> Module<T> {
|
||||
),
|
||||
Err(()) => { Err(Error::<T>::InvalidBacking)?; }
|
||||
}
|
||||
|
||||
for (bit_idx, _) in candidate
|
||||
.validator_indices.iter()
|
||||
.enumerate().filter(|(_, signed)| **signed)
|
||||
{
|
||||
let val_idx = group_vals.get(bit_idx)
|
||||
.expect("this query done above; qed");
|
||||
|
||||
backers.set(*val_idx as _, true);
|
||||
}
|
||||
}
|
||||
|
||||
core_indices.push(assignment.core);
|
||||
core_indices_and_backers.push((assignment.core, backers));
|
||||
continue 'a;
|
||||
}
|
||||
}
|
||||
@@ -525,11 +551,12 @@ impl<T: Config> Module<T> {
|
||||
check_assignment_in_order(assignment)?;
|
||||
}
|
||||
|
||||
core_indices
|
||||
core_indices_and_backers
|
||||
};
|
||||
|
||||
// one more sweep for actually writing to storage.
|
||||
for (candidate, core) in candidates.into_iter().zip(core_indices.iter().cloned()) {
|
||||
let core_indices = core_indices_and_backers.iter().map(|&(ref c, _)| c.clone()).collect();
|
||||
for (candidate, (core, backers)) in candidates.into_iter().zip(core_indices_and_backers) {
|
||||
let para_id = candidate.descriptor().para_id;
|
||||
|
||||
// initialize all availability votes to 0.
|
||||
@@ -551,6 +578,7 @@ impl<T: Config> Module<T> {
|
||||
descriptor,
|
||||
availability_votes,
|
||||
relay_parent_number: check_cx.relay_parent_number,
|
||||
backers,
|
||||
backed_in_number: check_cx.now,
|
||||
});
|
||||
<PendingAvailabilityCommitments>::insert(¶_id, commitments);
|
||||
@@ -589,11 +617,23 @@ impl<T: Config> Module<T> {
|
||||
fn enact_candidate(
|
||||
relay_parent_number: T::BlockNumber,
|
||||
receipt: CommittedCandidateReceipt<T::Hash>,
|
||||
backers: BitVec<BitOrderLsb0, u8>,
|
||||
availability_votes: BitVec<BitOrderLsb0, u8>,
|
||||
) -> Weight {
|
||||
let plain = receipt.to_plain();
|
||||
let commitments = receipt.commitments;
|
||||
let config = <configuration::Module<T>>::config();
|
||||
|
||||
T::RewardValidators::reward_backing(backers.iter().enumerate()
|
||||
.filter(|(_, backed)| **backed)
|
||||
.map(|(i, _)| i as _)
|
||||
);
|
||||
|
||||
T::RewardValidators::reward_bitfields(availability_votes.iter().enumerate()
|
||||
.filter(|(_, voted)| **voted)
|
||||
.map(|(i, _)| i as _)
|
||||
);
|
||||
|
||||
// initial weight is config read.
|
||||
let mut weight = T::DbWeight::get().reads_writes(1, 0);
|
||||
if let Some(new_code) = commitments.new_validation_code {
|
||||
@@ -690,6 +730,8 @@ impl<T: Config> Module<T> {
|
||||
Self::enact_candidate(
|
||||
pending.relay_parent_number,
|
||||
candidate,
|
||||
pending.backers,
|
||||
pending.availability_votes,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -988,6 +1030,18 @@ mod tests {
|
||||
bitvec::bitvec![BitOrderLsb0, u8; 0; Validators::get().len()]
|
||||
}
|
||||
|
||||
fn default_backing_bitfield() -> BitVec<BitOrderLsb0, u8> {
|
||||
bitvec::bitvec![BitOrderLsb0, u8; 0; Validators::get().len()]
|
||||
}
|
||||
|
||||
fn backing_bitfield(v: &[usize]) -> BitVec<BitOrderLsb0, u8> {
|
||||
let mut b = default_backing_bitfield();
|
||||
for i in v {
|
||||
b.set(*i, true);
|
||||
}
|
||||
b
|
||||
}
|
||||
|
||||
fn validator_pubkeys(val_ids: &[Sr25519Keyring]) -> Vec<ValidatorId> {
|
||||
val_ids.iter().map(|v| v.public().into()).collect()
|
||||
}
|
||||
@@ -1062,6 +1116,7 @@ mod tests {
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: 0,
|
||||
backed_in_number: 0,
|
||||
backers: default_backing_bitfield(),
|
||||
});
|
||||
PendingAvailabilityCommitments::insert(chain_a, default_candidate.commitments.clone());
|
||||
|
||||
@@ -1071,6 +1126,7 @@ mod tests {
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: 0,
|
||||
backed_in_number: 0,
|
||||
backers: default_backing_bitfield(),
|
||||
});
|
||||
PendingAvailabilityCommitments::insert(chain_b, default_candidate.commitments);
|
||||
|
||||
@@ -1234,6 +1290,7 @@ mod tests {
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: 0,
|
||||
backed_in_number: 0,
|
||||
backers: default_backing_bitfield(),
|
||||
});
|
||||
PendingAvailabilityCommitments::insert(chain_a, default_candidate.commitments);
|
||||
|
||||
@@ -1268,6 +1325,7 @@ mod tests {
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: 0,
|
||||
backed_in_number: 0,
|
||||
backers: default_backing_bitfield(),
|
||||
});
|
||||
|
||||
*bare_bitfield.0.get_mut(0).unwrap() = true;
|
||||
@@ -1339,6 +1397,7 @@ mod tests {
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: 0,
|
||||
backed_in_number: 0,
|
||||
backers: backing_bitfield(&[3, 4]),
|
||||
});
|
||||
PendingAvailabilityCommitments::insert(chain_a, candidate_a.commitments);
|
||||
|
||||
@@ -1354,6 +1413,7 @@ mod tests {
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: 0,
|
||||
backed_in_number: 0,
|
||||
backers: backing_bitfield(&[0, 2]),
|
||||
});
|
||||
PendingAvailabilityCommitments::insert(chain_b, candidate_b.commitments);
|
||||
|
||||
@@ -1424,6 +1484,25 @@ mod tests {
|
||||
|
||||
// and check that chain head was enacted.
|
||||
assert_eq!(Paras::para_head(&chain_a), Some(vec![1, 2, 3, 4].into()));
|
||||
|
||||
// Check that rewards are applied.
|
||||
{
|
||||
let rewards = crate::mock::availability_rewards();
|
||||
|
||||
assert_eq!(rewards.len(), 4);
|
||||
assert_eq!(rewards.get(&0).unwrap(), &1);
|
||||
assert_eq!(rewards.get(&1).unwrap(), &1);
|
||||
assert_eq!(rewards.get(&2).unwrap(), &1);
|
||||
assert_eq!(rewards.get(&3).unwrap(), &1);
|
||||
}
|
||||
|
||||
{
|
||||
let rewards = crate::mock::backing_rewards();
|
||||
|
||||
assert_eq!(rewards.len(), 2);
|
||||
assert_eq!(rewards.get(&3).unwrap(), &1);
|
||||
assert_eq!(rewards.get(&4).unwrap(), &1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1764,6 +1843,7 @@ mod tests {
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: 3,
|
||||
backed_in_number: 4,
|
||||
backers: default_backing_bitfield(),
|
||||
});
|
||||
<PendingAvailabilityCommitments>::insert(&chain_a, candidate.commitments);
|
||||
|
||||
@@ -2051,6 +2131,7 @@ mod tests {
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: System::block_number() - 1,
|
||||
backed_in_number: System::block_number(),
|
||||
backers: backing_bitfield(&[0, 1]),
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -2066,6 +2147,7 @@ mod tests {
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: System::block_number() - 1,
|
||||
backed_in_number: System::block_number(),
|
||||
backers: backing_bitfield(&[2, 3]),
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -2081,6 +2163,7 @@ mod tests {
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: System::block_number() - 1,
|
||||
backed_in_number: System::block_number(),
|
||||
backers: backing_bitfield(&[4]),
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -2175,6 +2258,7 @@ mod tests {
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: System::block_number() - 1,
|
||||
backed_in_number: System::block_number(),
|
||||
backers: backing_bitfield(&[0, 1, 2]),
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -2249,6 +2333,7 @@ mod tests {
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: 5,
|
||||
backed_in_number: 6,
|
||||
backers: default_backing_bitfield(),
|
||||
});
|
||||
<PendingAvailabilityCommitments>::insert(&chain_a, candidate.commitments.clone());
|
||||
|
||||
@@ -2258,6 +2343,7 @@ mod tests {
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: 6,
|
||||
backed_in_number: 7,
|
||||
backers: default_backing_bitfield(),
|
||||
});
|
||||
<PendingAvailabilityCommitments>::insert(&chain_b, candidate.commitments);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user