mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-29 16:07:57 +00:00
Approve multiple candidates with a single signature (#1191)
Initial implementation for the plan discussed here: https://github.com/paritytech/polkadot-sdk/issues/701 Built on top of https://github.com/paritytech/polkadot-sdk/pull/1178 v0: https://github.com/paritytech/polkadot/pull/7554, ## Overall idea When approval-voting checks a candidate and is ready to advertise the approval, defer it in a per-relay chain block until we either have MAX_APPROVAL_COALESCE_COUNT candidates to sign or a candidate has stayed MAX_APPROVALS_COALESCE_TICKS in the queue, in both cases we sign what candidates we have available. This should allow us to reduce the number of approvals messages we have to create/send/verify. The parameters are configurable, so we should find some values that balance: - Security of the network: Delaying broadcasting of an approval shouldn't but the finality at risk and to make sure that never happens we won't delay sending a vote if we are past 2/3 from the no-show time. - Scalability of the network: MAX_APPROVAL_COALESCE_COUNT = 1 & MAX_APPROVALS_COALESCE_TICKS =0, is what we have now and we know from the measurements we did on versi, it bottlenecks approval-distribution/approval-voting when increase significantly the number of validators and parachains - Block storage: In case of disputes we have to import this votes on chain and that increase the necessary storage with MAX_APPROVAL_COALESCE_COUNT * CandidateHash per vote. Given that disputes are not the normal way of the network functioning and we will limit MAX_APPROVAL_COALESCE_COUNT in the single digits numbers, this should be good enough. Alternatively, we could try to create a better way to store this on-chain through indirection, if that's needed. ## Other fixes: - Fixed the fact that we were sending random assignments to non-validators, that was wrong because those won't do anything with it and they won't gossip it either because they do not have a grid topology set, so we would waste the random assignments. - Added metrics to be able to debug potential no-shows and mis-processing of approvals/assignments. ## TODO: - [x] Get feedback, that this is moving in the right direction. @ordian @sandreim @eskimor @burdges, let me know what you think. - [x] More and more testing. - [x] Test in versi. - [x] Make MAX_APPROVAL_COALESCE_COUNT & MAX_APPROVAL_COALESCE_WAIT_MILLIS a parachain host configuration. - [x] Make sure the backwards compatibility works correctly - [x] Make sure this direction is compatible with other streams of work: https://github.com/paritytech/polkadot-sdk/issues/635 & https://github.com/paritytech/polkadot-sdk/issues/742 - [x] Final versi burn-in before merging --------- Signed-off-by: Alexandru Gheorghe <alexandru.gheorghe@parity.io>
This commit is contained in:
committed by
GitHub
parent
d18a682bf7
commit
a84dd0dba5
@@ -20,12 +20,13 @@ use schnellru::{ByLength, LruMap};
|
||||
use sp_consensus_babe::Epoch;
|
||||
|
||||
use polkadot_primitives::{
|
||||
async_backing, slashing, vstaging, AuthorityDiscoveryId, BlockNumber, CandidateCommitments,
|
||||
CandidateEvent, CandidateHash, CommittedCandidateReceipt, CoreState, DisputeState,
|
||||
ExecutorParams, GroupRotationInfo, Hash, Id as ParaId, InboundDownwardMessage,
|
||||
InboundHrmpMessage, OccupiedCoreAssumption, PersistedValidationData, PvfCheckStatement,
|
||||
ScrapedOnChainVotes, SessionIndex, SessionInfo, ValidationCode, ValidationCodeHash,
|
||||
ValidatorId, ValidatorIndex, ValidatorSignature,
|
||||
async_backing, slashing,
|
||||
vstaging::{self, ApprovalVotingParams},
|
||||
AuthorityDiscoveryId, BlockNumber, CandidateCommitments, CandidateEvent, CandidateHash,
|
||||
CommittedCandidateReceipt, CoreState, DisputeState, ExecutorParams, GroupRotationInfo, Hash,
|
||||
Id as ParaId, InboundDownwardMessage, InboundHrmpMessage, OccupiedCoreAssumption,
|
||||
PersistedValidationData, PvfCheckStatement, ScrapedOnChainVotes, SessionIndex, SessionInfo,
|
||||
ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, ValidatorSignature,
|
||||
};
|
||||
|
||||
/// For consistency we have the same capacity for all caches. We use 128 as we'll only need that
|
||||
@@ -68,6 +69,7 @@ pub(crate) struct RequestResultCache {
|
||||
para_backing_state: LruMap<(Hash, ParaId), Option<async_backing::BackingState>>,
|
||||
async_backing_params: LruMap<Hash, async_backing::AsyncBackingParams>,
|
||||
node_features: LruMap<SessionIndex, vstaging::NodeFeatures>,
|
||||
approval_voting_params: LruMap<SessionIndex, ApprovalVotingParams>,
|
||||
}
|
||||
|
||||
impl Default for RequestResultCache {
|
||||
@@ -98,6 +100,7 @@ impl Default for RequestResultCache {
|
||||
unapplied_slashes: LruMap::new(ByLength::new(DEFAULT_CACHE_CAP)),
|
||||
key_ownership_proof: LruMap::new(ByLength::new(DEFAULT_CACHE_CAP)),
|
||||
minimum_backing_votes: LruMap::new(ByLength::new(DEFAULT_CACHE_CAP)),
|
||||
approval_voting_params: LruMap::new(ByLength::new(DEFAULT_CACHE_CAP)),
|
||||
disabled_validators: LruMap::new(ByLength::new(DEFAULT_CACHE_CAP)),
|
||||
para_backing_state: LruMap::new(ByLength::new(DEFAULT_CACHE_CAP)),
|
||||
async_backing_params: LruMap::new(ByLength::new(DEFAULT_CACHE_CAP)),
|
||||
@@ -507,6 +510,21 @@ impl RequestResultCache {
|
||||
) {
|
||||
self.async_backing_params.insert(key, value);
|
||||
}
|
||||
|
||||
pub(crate) fn approval_voting_params(
|
||||
&mut self,
|
||||
key: (Hash, SessionIndex),
|
||||
) -> Option<&ApprovalVotingParams> {
|
||||
self.approval_voting_params.get(&key.1).map(|v| &*v)
|
||||
}
|
||||
|
||||
pub(crate) fn cache_approval_voting_params(
|
||||
&mut self,
|
||||
session_index: SessionIndex,
|
||||
value: ApprovalVotingParams,
|
||||
) {
|
||||
self.approval_voting_params.insert(session_index, value);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) enum RequestResult {
|
||||
@@ -554,6 +572,7 @@ pub(crate) enum RequestResult {
|
||||
slashing::OpaqueKeyOwnershipProof,
|
||||
Option<()>,
|
||||
),
|
||||
ApprovalVotingParams(Hash, SessionIndex, ApprovalVotingParams),
|
||||
DisabledValidators(Hash, Vec<ValidatorIndex>),
|
||||
ParaBackingState(Hash, ParaId, Option<async_backing::BackingState>),
|
||||
AsyncBackingParams(Hash, async_backing::AsyncBackingParams),
|
||||
|
||||
@@ -165,6 +165,8 @@ where
|
||||
KeyOwnershipProof(relay_parent, validator_id, key_ownership_proof) => self
|
||||
.requests_cache
|
||||
.cache_key_ownership_proof((relay_parent, validator_id), key_ownership_proof),
|
||||
RequestResult::ApprovalVotingParams(_relay_parent, session_index, params) =>
|
||||
self.requests_cache.cache_approval_voting_params(session_index, params),
|
||||
SubmitReportDisputeLost(_, _, _, _) => {},
|
||||
DisabledValidators(relay_parent, disabled_validators) =>
|
||||
self.requests_cache.cache_disabled_validators(relay_parent, disabled_validators),
|
||||
@@ -300,6 +302,9 @@ where
|
||||
Request::SubmitReportDisputeLost(dispute_proof, key_ownership_proof, sender)
|
||||
},
|
||||
),
|
||||
Request::ApprovalVotingParams(session_index, sender) =>
|
||||
query!(approval_voting_params(session_index), sender)
|
||||
.map(|sender| Request::ApprovalVotingParams(session_index, sender)),
|
||||
Request::DisabledValidators(sender) => query!(disabled_validators(), sender)
|
||||
.map(|sender| Request::DisabledValidators(sender)),
|
||||
Request::ParaBackingState(para, sender) => query!(para_backing_state(para), sender)
|
||||
@@ -571,6 +576,14 @@ where
|
||||
ver = Request::KEY_OWNERSHIP_PROOF_RUNTIME_REQUIREMENT,
|
||||
sender
|
||||
),
|
||||
Request::ApprovalVotingParams(session_index, sender) => {
|
||||
query!(
|
||||
ApprovalVotingParams,
|
||||
approval_voting_params(session_index),
|
||||
ver = Request::APPROVAL_VOTING_PARAMS_REQUIREMENT,
|
||||
sender
|
||||
)
|
||||
},
|
||||
Request::SubmitReportDisputeLost(dispute_proof, key_ownership_proof, sender) => query!(
|
||||
SubmitReportDisputeLost,
|
||||
submit_report_dispute_lost(dispute_proof, key_ownership_proof),
|
||||
|
||||
@@ -20,12 +20,13 @@ use polkadot_node_primitives::{BabeAllowedSlots, BabeEpoch, BabeEpochConfigurati
|
||||
use polkadot_node_subsystem::SpawnGlue;
|
||||
use polkadot_node_subsystem_test_helpers::make_subsystem_context;
|
||||
use polkadot_primitives::{
|
||||
async_backing, slashing, vstaging::NodeFeatures, AuthorityDiscoveryId, BlockNumber,
|
||||
CandidateCommitments, CandidateEvent, CandidateHash, CommittedCandidateReceipt, CoreState,
|
||||
DisputeState, ExecutorParams, GroupRotationInfo, Id as ParaId, InboundDownwardMessage,
|
||||
InboundHrmpMessage, OccupiedCoreAssumption, PersistedValidationData, PvfCheckStatement,
|
||||
ScrapedOnChainVotes, SessionIndex, SessionInfo, Slot, ValidationCode, ValidationCodeHash,
|
||||
ValidatorId, ValidatorIndex, ValidatorSignature,
|
||||
async_backing, slashing,
|
||||
vstaging::{ApprovalVotingParams, NodeFeatures},
|
||||
AuthorityDiscoveryId, BlockNumber, CandidateCommitments, CandidateEvent, CandidateHash,
|
||||
CommittedCandidateReceipt, CoreState, DisputeState, ExecutorParams, GroupRotationInfo,
|
||||
Id as ParaId, InboundDownwardMessage, InboundHrmpMessage, OccupiedCoreAssumption,
|
||||
PersistedValidationData, PvfCheckStatement, ScrapedOnChainVotes, SessionIndex, SessionInfo,
|
||||
Slot, ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, ValidatorSignature,
|
||||
};
|
||||
use sp_api::ApiError;
|
||||
use sp_core::testing::TaskExecutor;
|
||||
@@ -242,6 +243,15 @@ impl RuntimeApiSubsystemClient for MockSubsystemClient {
|
||||
todo!("Not required for tests")
|
||||
}
|
||||
|
||||
/// Approval voting configuration parameters
|
||||
async fn approval_voting_params(
|
||||
&self,
|
||||
_: Hash,
|
||||
_: SessionIndex,
|
||||
) -> Result<ApprovalVotingParams, ApiError> {
|
||||
todo!("Not required for tests")
|
||||
}
|
||||
|
||||
async fn current_epoch(&self, _: Hash) -> Result<sp_consensus_babe::Epoch, ApiError> {
|
||||
Ok(self.babe_epoch.as_ref().unwrap().clone())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user