Finish migration to v2 primitives (#5037)

* remove v0 primitives from polkadot-primitives

* first pass: remove v0

* fix fallout in erasure-coding

* remove v1 primitives, consolidate to v2

* the great import update

* update runtime_api_impl_v1 to v2 as well

* guide: add `Version` request for runtime API

* add version query to runtime API

* reintroduce OldV1SessionInfo in a limited way
This commit is contained in:
Robert Habermeier
2022-03-09 14:01:13 -06:00
committed by GitHub
parent 3394cbb142
commit 49f7e5cce4
215 changed files with 2312 additions and 3123 deletions
+179
View File
@@ -0,0 +1,179 @@
// Copyright 2021 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
//! Runtime metric primitives.
use parity_scale_codec::{Decode, Encode};
use sp_std::prelude::*;
/// Runtime metric operations.
#[derive(Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum RuntimeMetricOp {
/// Increment a counter metric with labels by value.
IncrementCounterVec(u64, RuntimeMetricLabelValues),
/// Increment a counter metric by value.
IncrementCounter(u64),
}
/// Runtime metric update event.
#[derive(Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct RuntimeMetricUpdate {
/// The name of the metric.
pub metric_name: Vec<u8>,
/// The operation applied to the metric.
pub op: RuntimeMetricOp,
}
fn vec_to_str<'a>(v: &'a Vec<u8>, default: &'static str) -> &'a str {
return sp_std::str::from_utf8(v).unwrap_or(default)
}
impl RuntimeMetricLabels {
/// Returns a labels as `Vec<&str>`.
pub fn as_str_vec(&self) -> Vec<&str> {
self.0
.iter()
.map(|label_vec| vec_to_str(&label_vec.0, "invalid_label"))
.collect()
}
/// Return the inner values as vec.
pub fn clear(&mut self) {
self.0.clear();
}
}
impl From<&[&'static str]> for RuntimeMetricLabels {
fn from(v: &[&'static str]) -> RuntimeMetricLabels {
RuntimeMetricLabels(
v.iter().map(|label| RuntimeMetricLabel(label.as_bytes().to_vec())).collect(),
)
}
}
impl RuntimeMetricUpdate {
/// Returns the metric name.
pub fn metric_name(&self) -> &str {
vec_to_str(&self.metric_name, "invalid_metric_name")
}
}
/// A set of metric labels.
#[derive(Clone, Default, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct RuntimeMetricLabels(Vec<RuntimeMetricLabel>);
/// A metric label.
#[derive(Clone, Default, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct RuntimeMetricLabel(Vec<u8>);
/// A metric label value.
pub type RuntimeMetricLabelValue = RuntimeMetricLabel;
/// A set of metric label values.
pub type RuntimeMetricLabelValues = RuntimeMetricLabels;
/// Trait for converting Vec<u8> to `&str`.
pub trait AsStr {
/// Return a str reference.
fn as_str(&self) -> Option<&str>;
}
impl AsStr for RuntimeMetricLabel {
fn as_str(&self) -> Option<&str> {
sp_std::str::from_utf8(&self.0).ok()
}
}
impl From<&'static str> for RuntimeMetricLabel {
fn from(s: &'static str) -> Self {
Self(s.as_bytes().to_vec())
}
}
/// Contains all runtime metrics defined as constants.
pub mod metric_definitions {
/// `Counter` metric definition.
pub struct CounterDefinition {
/// The name of the metric.
pub name: &'static str,
/// The description of the metric.
pub description: &'static str,
}
/// `CounterVec` metric definition.
pub struct CounterVecDefinition<'a> {
/// The name of the metric.
pub name: &'static str,
/// The description of the metric.
pub description: &'static str,
/// The label names of the metric.
pub labels: &'a [&'static str],
}
/// Counts parachain inherent data weights. Use `before` and `after` labels to differentiate
/// between the weight before and after filtering.
pub const PARACHAIN_INHERENT_DATA_WEIGHT: CounterVecDefinition = CounterVecDefinition {
name: "polkadot_parachain_inherent_data_weight",
description: "Inherent data weight before and after filtering",
labels: &["when"],
};
/// Counts the number of bitfields processed in `enter_inner`.
pub const PARACHAIN_INHERENT_DATA_BITFIELDS_PROCESSED: CounterDefinition = CounterDefinition {
name: "polkadot_parachain_inherent_data_bitfields_processed",
description: "Counts the number of bitfields processed in `enter_inner`.",
};
/// Counts the `total`, `sanitized` and `included` number of parachain block candidates
/// in `enter_inner`.
pub const PARACHAIN_INHERENT_DATA_CANDIDATES_PROCESSED: CounterVecDefinition =
CounterVecDefinition {
name: "polkadot_parachain_inherent_data_candidates_processed",
description:
"Counts the number of parachain block candidates processed in `enter_inner`.",
labels: &["category"],
};
/// Counts the number of `imported`, `current` and `concluded_invalid` dispute statements sets
/// processed in `enter_inner`. The `current` label refers to the disputes statement sets of
/// the current session.
pub const PARACHAIN_INHERENT_DATA_DISPUTE_SETS_PROCESSED: CounterVecDefinition =
CounterVecDefinition {
name: "polkadot_parachain_inherent_data_dispute_sets_processed",
description: "Counts the number of dispute statements sets processed in `enter_inner`.",
labels: &["category"],
};
/// Counts the number of dispute statements sets included in a block in `enter_inner`.
pub const PARACHAIN_INHERENT_DATA_DISPUTE_SETS_INCLUDED: CounterDefinition =
CounterDefinition {
name: "polkadot_parachain_inherent_data_dispute_sets_included",
description:
"Counts the number of dispute statements sets included in a block in `enter_inner`.",
};
/// Counts the number of `valid` and `invalid` bitfields signature checked in `enter_inner`.
pub const PARACHAIN_CREATE_INHERENT_BITFIELDS_SIGNATURE_CHECKS: CounterVecDefinition =
CounterVecDefinition {
name: "polkadot_parachain_create_inherent_bitfields_signature_checks",
description: "Counts the number of bitfields signature checked in `enter_inner`.",
labels: &["validity"],
};
}
File diff suppressed because it is too large Load Diff
+325
View File
@@ -0,0 +1,325 @@
// Copyright 2021 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use parity_scale_codec::{Decode, Encode};
use scale_info::TypeInfo;
#[cfg(feature = "std")]
use application_crypto::AppKey;
#[cfg(feature = "std")]
use sp_keystore::{CryptoStore, Error as KeystoreError, SyncCryptoStorePtr};
#[cfg(feature = "std")]
use sp_std::convert::TryInto;
use sp_std::prelude::Vec;
use primitives::RuntimeDebug;
use runtime_primitives::traits::AppVerify;
use super::{SigningContext, ValidatorId, ValidatorIndex, ValidatorSignature};
/// Signed data with signature already verified.
///
/// NOTE: This type does not have an Encode/Decode instance, as this would cancel out our
/// valid signature guarantees. If you need to encode/decode you have to convert into an
/// `UncheckedSigned` first.
///
/// `Signed` can easily be converted into `UncheckedSigned` and conversion back via `into_signed`
/// enforces a valid signature again.
#[derive(Clone, PartialEq, Eq, RuntimeDebug)]
pub struct Signed<Payload, RealPayload = Payload>(UncheckedSigned<Payload, RealPayload>);
impl<Payload, RealPayload> Signed<Payload, RealPayload> {
/// Convert back to an unchecked type.
pub fn into_unchecked(self) -> UncheckedSigned<Payload, RealPayload> {
self.0
}
}
/// Unchecked signed data, can be converted to `Signed` by checking the signature.
#[derive(Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, TypeInfo)]
pub struct UncheckedSigned<Payload, RealPayload = Payload> {
/// The payload is part of the signed data. The rest is the signing context,
/// which is known both at signing and at validation.
payload: Payload,
/// The index of the validator signing this statement.
validator_index: ValidatorIndex,
/// The signature by the validator of the signed payload.
signature: ValidatorSignature,
/// This ensures the real payload is tracked at the typesystem level.
real_payload: sp_std::marker::PhantomData<RealPayload>,
}
impl<Payload: EncodeAs<RealPayload>, RealPayload: Encode> Signed<Payload, RealPayload> {
/// Used to create a `Signed` from already existing parts.
///
/// The signature is checked as part of the process.
#[cfg(feature = "std")]
pub fn new<H: Encode>(
payload: Payload,
validator_index: ValidatorIndex,
signature: ValidatorSignature,
context: &SigningContext<H>,
key: &ValidatorId,
) -> Option<Self> {
let s = UncheckedSigned {
payload,
validator_index,
signature,
real_payload: std::marker::PhantomData,
};
s.check_signature(context, key).ok()?;
Some(Self(s))
}
/// Create a new `Signed` by signing data.
#[cfg(feature = "std")]
pub async fn sign<H: Encode>(
keystore: &SyncCryptoStorePtr,
payload: Payload,
context: &SigningContext<H>,
validator_index: ValidatorIndex,
key: &ValidatorId,
) -> Result<Option<Self>, KeystoreError> {
let r = UncheckedSigned::sign(keystore, payload, context, validator_index, key).await?;
Ok(r.map(Self))
}
/// Try to convert from `UncheckedSigned` by checking the signature.
pub fn try_from_unchecked<H: Encode>(
unchecked: UncheckedSigned<Payload, RealPayload>,
context: &SigningContext<H>,
key: &ValidatorId,
) -> Result<Self, UncheckedSigned<Payload, RealPayload>> {
if unchecked.check_signature(context, key).is_ok() {
Ok(Self(unchecked))
} else {
Err(unchecked)
}
}
/// Get a reference to data as unchecked.
pub fn as_unchecked(&self) -> &UncheckedSigned<Payload, RealPayload> {
&self.0
}
/// Immutably access the payload.
#[inline]
pub fn payload(&self) -> &Payload {
&self.0.payload
}
/// Immutably access the validator index.
#[inline]
pub fn validator_index(&self) -> ValidatorIndex {
self.0.validator_index
}
/// Immutably access the signature.
#[inline]
pub fn signature(&self) -> &ValidatorSignature {
&self.0.signature
}
/// Discard signing data, get the payload
#[inline]
pub fn into_payload(self) -> Payload {
self.0.payload
}
/// Convert `Payload` into `RealPayload`.
pub fn convert_payload(&self) -> Signed<RealPayload>
where
for<'a> &'a Payload: Into<RealPayload>,
{
Signed(self.0.unchecked_convert_payload())
}
}
// We can't bound this on `Payload: Into<RealPayload>` because that conversion consumes
// the payload, and we don't want that. We can't bound it on `Payload: AsRef<RealPayload>`
// because there's no blanket impl of `AsRef<T> for T`. In the end, we just invent our
// own trait which does what we need: EncodeAs.
impl<Payload: EncodeAs<RealPayload>, RealPayload: Encode> UncheckedSigned<Payload, RealPayload> {
/// Used to create a `UncheckedSigned` from already existing parts.
///
/// Signature is not checked here, hence `UncheckedSigned`.
#[cfg(feature = "std")]
pub fn new(
payload: Payload,
validator_index: ValidatorIndex,
signature: ValidatorSignature,
) -> Self {
Self { payload, validator_index, signature, real_payload: std::marker::PhantomData }
}
/// Check signature and convert to `Signed` if successful.
pub fn try_into_checked<H: Encode>(
self,
context: &SigningContext<H>,
key: &ValidatorId,
) -> Result<Signed<Payload, RealPayload>, Self> {
Signed::try_from_unchecked(self, context, key)
}
/// Immutably access the payload.
#[inline]
pub fn unchecked_payload(&self) -> &Payload {
&self.payload
}
/// Immutably access the validator index.
#[inline]
pub fn unchecked_validator_index(&self) -> ValidatorIndex {
self.validator_index
}
/// Immutably access the signature.
#[inline]
pub fn unchecked_signature(&self) -> &ValidatorSignature {
&self.signature
}
/// Discard signing data, get the payload
#[inline]
pub fn unchecked_into_payload(self) -> Payload {
self.payload
}
/// Convert `Payload` into `RealPayload`.
pub fn unchecked_convert_payload(&self) -> UncheckedSigned<RealPayload>
where
for<'a> &'a Payload: Into<RealPayload>,
{
UncheckedSigned {
signature: self.signature.clone(),
validator_index: self.validator_index,
payload: (&self.payload).into(),
real_payload: sp_std::marker::PhantomData,
}
}
fn payload_data<H: Encode>(payload: &Payload, context: &SigningContext<H>) -> Vec<u8> {
// equivalent to (`real_payload`, context).encode()
let mut out = payload.encode_as();
out.extend(context.encode());
out
}
/// Sign this payload with the given context and key, storing the validator index.
#[cfg(feature = "std")]
async fn sign<H: Encode>(
keystore: &SyncCryptoStorePtr,
payload: Payload,
context: &SigningContext<H>,
validator_index: ValidatorIndex,
key: &ValidatorId,
) -> Result<Option<Self>, KeystoreError> {
let data = Self::payload_data(&payload, context);
let signature =
CryptoStore::sign_with(&**keystore, ValidatorId::ID, &key.into(), &data).await?;
let signature = match signature {
Some(sig) =>
sig.try_into().map_err(|_| KeystoreError::KeyNotSupported(ValidatorId::ID))?,
None => return Ok(None),
};
Ok(Some(Self {
payload,
validator_index,
signature,
real_payload: std::marker::PhantomData,
}))
}
/// Validate the payload given the context and public key
/// without creating a `Signed` type.
pub fn check_signature<H: Encode>(
&self,
context: &SigningContext<H>,
key: &ValidatorId,
) -> Result<(), ()> {
let data = Self::payload_data(&self.payload, context);
if self.signature.verify(data.as_slice(), key) {
Ok(())
} else {
Err(())
}
}
/// Sign this payload with the given context and pair.
#[cfg(any(feature = "runtime-benchmarks", feature = "std"))]
pub fn benchmark_sign<H: Encode>(
public: &super::ValidatorId,
payload: Payload,
context: &SigningContext<H>,
validator_index: ValidatorIndex,
) -> Self {
use application_crypto::RuntimeAppPublic;
let data = Self::payload_data(&payload, context);
let signature = public.sign(&data).unwrap();
Self { payload, validator_index, signature, real_payload: sp_std::marker::PhantomData }
}
/// Immutably access the signature.
#[cfg(any(feature = "runtime-benchmarks", feature = "std"))]
pub fn benchmark_signature(&self) -> ValidatorSignature {
self.signature.clone()
}
/// Set the signature. Only should be used for creating testing mocks.
#[cfg(feature = "std")]
pub fn set_signature(&mut self, signature: ValidatorSignature) {
self.signature = signature
}
}
impl<Payload, RealPayload> From<Signed<Payload, RealPayload>>
for UncheckedSigned<Payload, RealPayload>
{
fn from(signed: Signed<Payload, RealPayload>) -> Self {
signed.0
}
}
/// This helper trait ensures that we can encode `Statement` as `CompactStatement`,
/// and anything as itself.
///
/// This resembles `parity_scale_codec::EncodeLike`, but it's distinct:
/// `EncodeLike` is a marker trait which asserts at the typesystem level that
/// one type's encoding is a valid encoding for another type. It doesn't
/// perform any type conversion when encoding.
///
/// This trait, on the other hand, provides a method which can be used to
/// simultaneously convert and encode one type as another.
pub trait EncodeAs<T> {
/// Convert Self into T, then encode T.
///
/// This is useful when T is a subset of Self, reducing encoding costs;
/// its signature also means that we do not need to clone Self in order
/// to retain ownership, as we would if we were to do
/// `self.clone().into().encode()`.
fn encode_as(&self) -> Vec<u8>;
}
impl<T: Encode> EncodeAs<T> for T {
fn encode_as(&self) -> Vec<u8> {
self.encode()
}
}