Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -361,13 +361,27 @@ impl RuntimeApiSubsystemClient for BlockChainRpcClient {
Vec<(
polkadot_primitives::SessionIndex,
polkadot_primitives::CandidateHash,
slashing::PendingSlashes,
slashing::LegacyPendingSlashes,
)>,
ApiError,
> {
Ok(self.rpc_client.parachain_host_unapplied_slashes(at).await?)
}

async fn unapplied_slashes_v2(
&self,
at: Hash,
) -> Result<
Vec<(
polkadot_primitives::SessionIndex,
polkadot_primitives::CandidateHash,
slashing::PendingSlashes,
)>,
ApiError,
> {
Ok(self.rpc_client.parachain_host_unapplied_slashes_v2(at).await?)
}

async fn key_ownership_proof(
&self,
at: Hash,
Expand Down
11 changes: 10 additions & 1 deletion cumulus/client/relay-chain-rpc-interface/src/rpc_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -424,11 +424,20 @@ impl RelayChainRpcClient {
pub async fn parachain_host_unapplied_slashes(
&self,
at: RelayHash,
) -> Result<Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)>, RelayChainError> {
) -> Result<Vec<(SessionIndex, CandidateHash, slashing::LegacyPendingSlashes)>, RelayChainError> {
self.call_remote_runtime_function("ParachainHost_unapplied_slashes", at, None::<()>)
.await
}

/// Returns a list of validators that lost a past session dispute and need to be slashed.
pub async fn parachain_host_unapplied_slashes_v2(
&self,
at: RelayHash,
) -> Result<Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)>, RelayChainError> {
self.call_remote_runtime_function("ParachainHost_unapplied_slashes_v2", at, None::<()>)
.await
}

/// Returns a merkle proof of a validator session key in a past session.
///
/// This is a staging method! Do not use on production runtimes!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ async fn assert_unapplied_slashes_request(virtual_overseer: &mut VirtualOverseer
overseer_recv(virtual_overseer).await,
AllMessages::RuntimeApi(RuntimeApiMessage::Request(
_hash,
RuntimeApiRequest::UnappliedSlashes(tx),
RuntimeApiRequest::UnappliedSlashesV2(tx),
)) => {
tx.send(Ok(Vec::new())).unwrap();
}
Expand Down
2 changes: 1 addition & 1 deletion polkadot/node/core/dispute-coordinator/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ impl TestState {
},
AllMessages::RuntimeApi(RuntimeApiMessage::Request(
_new_leaf,
RuntimeApiRequest::UnappliedSlashes(tx),
RuntimeApiRequest::UnappliedSlashesV2(tx),
)) => {
tx.send(Ok(Vec::new())).unwrap();
},
Expand Down
27 changes: 23 additions & 4 deletions polkadot/node/core/runtime-api/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ pub(crate) struct RequestResultCache {
LruMap<(Hash, ParaId, OccupiedCoreAssumption), Option<ValidationCodeHash>>,
version: LruMap<Hash, u32>,
disputes: LruMap<Hash, Vec<(SessionIndex, CandidateHash, DisputeState<BlockNumber>)>>,
unapplied_slashes: LruMap<Hash, Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)>>,
unapplied_slashes:
LruMap<Hash, Vec<(SessionIndex, CandidateHash, slashing::LegacyPendingSlashes)>>,
unapplied_slashes_v2:
LruMap<Hash, Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)>>,
key_ownership_proof: LruMap<(Hash, ValidatorId), Option<slashing::OpaqueKeyOwnershipProof>>,
minimum_backing_votes: LruMap<SessionIndex, u32>,
disabled_validators: LruMap<Hash, Vec<ValidatorIndex>>,
Expand Down Expand Up @@ -105,6 +108,7 @@ impl Default for RequestResultCache {
version: LruMap::new(ByLength::new(DEFAULT_CACHE_CAP)),
disputes: LruMap::new(ByLength::new(DEFAULT_CACHE_CAP)),
unapplied_slashes: LruMap::new(ByLength::new(DEFAULT_CACHE_CAP)),
unapplied_slashes_v2: 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)),
Expand Down Expand Up @@ -431,18 +435,32 @@ impl RequestResultCache {
pub(crate) fn unapplied_slashes(
&mut self,
relay_parent: &Hash,
) -> Option<&Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)>> {
) -> Option<&Vec<(SessionIndex, CandidateHash, slashing::LegacyPendingSlashes)>> {
self.unapplied_slashes.get(relay_parent).map(|v| &*v)
}

pub(crate) fn cache_unapplied_slashes(
&mut self,
relay_parent: Hash,
value: Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)>,
value: Vec<(SessionIndex, CandidateHash, slashing::LegacyPendingSlashes)>,
) {
self.unapplied_slashes.insert(relay_parent, value);
}

pub(crate) fn unapplied_slashes_v2(
&mut self,
relay_parent: &Hash,
) -> Option<&Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)>> {
self.unapplied_slashes_v2.get(relay_parent).map(|v| &*v)
}

pub(crate) fn cache_unapplied_slashes_v2(
&mut self,
relay_parent: Hash,
value: Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)>,
) {
self.unapplied_slashes_v2.insert(relay_parent, value);
}
pub(crate) fn key_ownership_proof(
&mut self,
key: (Hash, ValidatorId),
Expand Down Expand Up @@ -647,7 +665,7 @@ pub(crate) enum RequestResult {
ValidationCodeHash(Hash, ParaId, OccupiedCoreAssumption, Option<ValidationCodeHash>),
Version(Hash, u32),
Disputes(Hash, Vec<(SessionIndex, CandidateHash, DisputeState<BlockNumber>)>),
UnappliedSlashes(Hash, Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)>),
UnappliedSlashes(Hash, Vec<(SessionIndex, CandidateHash, slashing::LegacyPendingSlashes)>),
KeyOwnershipProof(Hash, ValidatorId, Option<slashing::OpaqueKeyOwnershipProof>),
// This is a request with side-effects.
#[allow(dead_code)]
Expand All @@ -663,4 +681,5 @@ pub(crate) enum RequestResult {
SchedulingLookahead(SessionIndex, u32),
ValidationCodeBombLimit(SessionIndex, u32),
ParaIds(SessionIndex, Vec<ParaId>),
UnappliedSlashesV2(Hash, Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)>),
}
11 changes: 11 additions & 0 deletions polkadot/node/core/runtime-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,9 @@ where
self.requests_cache.cache_disputes(relay_parent, disputes),
UnappliedSlashes(relay_parent, unapplied_slashes) =>
self.requests_cache.cache_unapplied_slashes(relay_parent, unapplied_slashes),
UnappliedSlashesV2(relay_parent, unapplied_slashes_v2) => self
.requests_cache
.cache_unapplied_slashes_v2(relay_parent, unapplied_slashes_v2),
KeyOwnershipProof(relay_parent, validator_id, key_ownership_proof) => self
.requests_cache
.cache_key_ownership_proof((relay_parent, validator_id), key_ownership_proof),
Expand Down Expand Up @@ -313,6 +316,8 @@ where
query!(disputes(), sender).map(|sender| Request::Disputes(sender)),
Request::UnappliedSlashes(sender) =>
query!(unapplied_slashes(), sender).map(|sender| Request::UnappliedSlashes(sender)),
Request::UnappliedSlashesV2(sender) => query!(unapplied_slashes_v2(), sender)
.map(|sender| Request::UnappliedSlashesV2(sender)),
Request::KeyOwnershipProof(validator_id, sender) =>
query!(key_ownership_proof(validator_id), sender)
.map(|sender| Request::KeyOwnershipProof(validator_id, sender)),
Expand Down Expand Up @@ -721,5 +726,11 @@ where
sender,
result = (index)
),
Request::UnappliedSlashesV2(sender) => query!(
UnappliedSlashesV2,
unapplied_slashes_v2(),
ver = Request::UNAPPLIED_SLASHES_V2_RUNTIME_REQUIREMENT,
sender
),
}
}
2 changes: 1 addition & 1 deletion polkadot/node/core/runtime-api/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ impl RuntimeApiSubsystemClient for MockSubsystemClient {
async fn unapplied_slashes(
&self,
_: Hash,
) -> Result<Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)>, ApiError> {
) -> Result<Vec<(SessionIndex, CandidateHash, slashing::LegacyPendingSlashes)>, ApiError> {
todo!("Not required for tests")
}

Expand Down
5 changes: 5 additions & 0 deletions polkadot/node/service/src/fake_runtime_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,11 @@ sp_api::impl_runtime_apis! {
}

fn unapplied_slashes(
) -> Vec<(SessionIndex, CandidateHash, slashing::LegacyPendingSlashes)> {
unimplemented!()
}

fn unapplied_slashes_v2(
) -> Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)> {
unimplemented!()
}
Expand Down
10 changes: 9 additions & 1 deletion polkadot/node/subsystem-types/src/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -739,7 +739,7 @@ pub enum RuntimeApiRequest {
/// Returns a list of validators that lost a past session dispute and need to be slashed.
/// `V5`
UnappliedSlashes(
RuntimeApiSender<Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)>>,
RuntimeApiSender<Vec<(SessionIndex, CandidateHash, slashing::LegacyPendingSlashes)>>,
),
/// Returns a merkle proof of a validator session key.
/// `V5`
Expand Down Expand Up @@ -784,6 +784,11 @@ pub enum RuntimeApiRequest {
/// Get the paraids at the relay parent.
/// `V14`
ParaIds(SessionIndex, RuntimeApiSender<Vec<ParaId>>),
/// Returns a list of validators that lost a past session dispute and need to be slashed (v2).
/// `V14`
UnappliedSlashesV2(
RuntimeApiSender<Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)>>,
),
}

impl RuntimeApiRequest {
Expand Down Expand Up @@ -836,6 +841,9 @@ impl RuntimeApiRequest {

/// `ParaIds`
pub const PARAIDS_RUNTIME_REQUIREMENT: u32 = 14;

/// `UnappliedSlashesV2`
pub const UNAPPLIED_SLASHES_V2_RUNTIME_REQUIREMENT: u32 = 14;
}

/// A message to the Runtime API subsystem.
Expand Down
15 changes: 14 additions & 1 deletion polkadot/node/subsystem-types/src/runtime_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,12 @@ pub trait RuntimeApiSubsystemClient {
async fn unapplied_slashes(
&self,
at: Hash,
) -> Result<Vec<(SessionIndex, CandidateHash, slashing::LegacyPendingSlashes)>, ApiError>;

/// Returns a list of validators that lost a past session dispute and need to be slashed (v2).
async fn unapplied_slashes_v2(
&self,
at: Hash,
) -> Result<Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)>, ApiError>;

/// Returns a merkle proof of a validator session key in a past session.
Expand Down Expand Up @@ -564,10 +570,17 @@ where
async fn unapplied_slashes(
&self,
at: Hash,
) -> Result<Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)>, ApiError> {
) -> Result<Vec<(SessionIndex, CandidateHash, slashing::LegacyPendingSlashes)>, ApiError> {
self.client.runtime_api().unapplied_slashes(at)
}

async fn unapplied_slashes_v2(
&self,
at: Hash,
) -> Result<Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)>, ApiError> {
self.client.runtime_api().unapplied_slashes_v2(at)
}

async fn key_ownership_proof(
&self,
at: Hash,
Expand Down
3 changes: 2 additions & 1 deletion polkadot/node/subsystem-util/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,8 @@ specialize_requests! {
-> Option<ValidationCodeHash>; ValidationCodeHash;
fn request_on_chain_votes() -> Option<ScrapedOnChainVotes>; FetchOnChainVotes;
fn request_session_executor_params(session_index: SessionIndex) -> Option<ExecutorParams>;SessionExecutorParams;
fn request_unapplied_slashes() -> Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)>; UnappliedSlashes;
fn request_unapplied_slashes() -> Vec<(SessionIndex, CandidateHash, slashing::LegacyPendingSlashes)>; UnappliedSlashes;
fn request_unapplied_slashes_v2() -> Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)>; UnappliedSlashesV2;
fn request_key_ownership_proof(validator_id: ValidatorId) -> Option<slashing::OpaqueKeyOwnershipProof>; KeyOwnershipProof;
fn request_submit_report_dispute_lost(dp: slashing::DisputeProof, okop: slashing::OpaqueKeyOwnershipProof) -> Option<()>; SubmitReportDisputeLost;
fn request_disabled_validators() -> Vec<ValidatorIndex>; DisabledValidators;
Expand Down
29 changes: 27 additions & 2 deletions polkadot/node/subsystem-util/src/runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ use crate::{
request_disabled_validators, request_from_runtime, request_key_ownership_proof,
request_node_features, request_on_chain_votes, request_session_executor_params,
request_session_index_for_child, request_session_info, request_submit_report_dispute_lost,
request_unapplied_slashes, request_validation_code_by_hash, request_validator_groups,
request_unapplied_slashes, request_unapplied_slashes_v2, request_validation_code_by_hash,
request_validator_groups,
};

/// Errors that can happen on runtime fetches.
Expand Down Expand Up @@ -424,14 +425,38 @@ where
}

/// Fetch a list of `PendingSlashes` from the runtime.
/// Will fallback to `unapplied_slashes` if the runtime does not
/// support `unapplied_slashes_v2`.
pub async fn get_unapplied_slashes<Sender>(
sender: &mut Sender,
relay_parent: Hash,
) -> Result<Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)>>
where
Sender: SubsystemSender<RuntimeApiMessage>,
{
recv_runtime(request_unapplied_slashes(relay_parent, sender).await).await
match recv_runtime(request_unapplied_slashes_v2(relay_parent, sender).await).await {
Ok(v2) => Ok(v2),
Err(Error::RuntimeRequest(RuntimeApiError::NotSupported { .. })) => {
// Fallback to legacy unapplied_slashes
let legacy =
recv_runtime(request_unapplied_slashes(relay_parent, sender).await).await?;
// Convert legacy slashes to PendingSlashes
Ok(legacy
.into_iter()
.map(|(session, candidate_hash, legacy_slash)| {
(
session,
candidate_hash,
slashing::PendingSlashes {
keys: legacy_slash.keys,
kind: legacy_slash.kind.into(),
},
)
})
.collect())
},
Err(e) => Err(e),
}
}

/// Generate validator key ownership proof.
Expand Down
8 changes: 6 additions & 2 deletions polkadot/primitives/src/runtime_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,9 @@ sp_api::decl_runtime_apis! {
fn session_executor_params(session_index: SessionIndex) -> Option<ExecutorParams>;

/// Returns a list of validators that lost a past session dispute and need to be slashed.
/// NOTE: This function is only available since parachain host version 5.
fn unapplied_slashes() -> Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)>;
///
/// Deprecated. Use `unapplied_slashes_v2` instead.
fn unapplied_slashes() -> Vec<(SessionIndex, CandidateHash, slashing::LegacyPendingSlashes)>;

/// Returns a merkle proof of a validator session key.
/// NOTE: This function is only available since parachain host version 5.
Expand Down Expand Up @@ -316,5 +317,8 @@ sp_api::decl_runtime_apis! {
#[api_version(14)]
fn para_ids() -> Vec<ppp::Id>;

/***** Added in v14 *****/
/// Returns a list of validators that lost a past session dispute and need to be slashed.
fn unapplied_slashes_v2() -> Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)>;
}
}
15 changes: 15 additions & 0 deletions polkadot/primitives/src/v9/slashing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,21 @@ pub struct DisputeProof {
pub validator_id: ValidatorId,
}

/// Slashes that are waiting to be applied once we have validator key
/// identification.
///
/// Legacy version. We need to keep this around for backwards compatibility.
/// Once old nodes are no longer supported, we can remove it along with the
/// `UnappliedSlashes` runtime API.
#[derive(Encode, Decode, TypeInfo, Debug, Clone)]
pub struct LegacyPendingSlashes {
/// Indices and keys of the validators who lost a dispute and are pending
/// slashes.
pub keys: BTreeMap<ValidatorIndex, ValidatorId>,
/// The dispute outcome.
pub kind: SlashingOffenceKind,
}

/// Slashes that are waiting to be applied once we have validator key
/// identification.
#[derive(Encode, Decode, TypeInfo, Debug, Clone)]
Expand Down
15 changes: 15 additions & 0 deletions polkadot/runtime/parachains/src/runtime_api_impl/v13.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,21 @@ pub fn session_executor_params<T: session_info::Config>(

/// Implementation of `unapplied_slashes` runtime API
pub fn unapplied_slashes<T: disputes::slashing::Config>(
) -> Vec<(SessionIndex, CandidateHash, slashing::LegacyPendingSlashes)> {
disputes::slashing::Pallet::<T>::unapplied_slashes()
.into_iter()
.filter_map(|(session, candidate_hash, pending_slash)| {
let legacy_pending_slash = slashing::LegacyPendingSlashes {
keys: pending_slash.keys,
kind: pending_slash.kind.try_into().ok()?,
};
Some((session, candidate_hash, legacy_pending_slash))
})
.collect()
}

/// Implementation of `unapplied_slashes_v2` runtime API
pub fn unapplied_slashes_v2<T: disputes::slashing::Config>(
) -> Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)> {
disputes::slashing::Pallet::<T>::unapplied_slashes()
}
Expand Down
11 changes: 9 additions & 2 deletions polkadot/runtime/parachains/src/runtime_api_impl/vstaging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,18 @@

//! Put implementations of functions from staging APIs here.

use crate::{initializer, paras};
use crate::{disputes, initializer, paras};
use alloc::vec::Vec;

use polkadot_primitives::Id as ParaId;
use polkadot_primitives::{slashing, CandidateHash, Id as ParaId, SessionIndex};

/// Implementation of `para_ids` runtime API
pub fn para_ids<T: initializer::Config>() -> Vec<ParaId> {
paras::Heads::<T>::iter_keys().collect()
}

/// Implementation of `unapplied_slashes_v2` runtime API
pub fn unapplied_slashes_v2<T: disputes::slashing::Config>(
) -> Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)> {
disputes::slashing::Pallet::<T>::unapplied_slashes()
}
Loading
Loading