// 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 .
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};
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(UncheckedSigned);
impl Signed {
/// Convert back to an unchecked type.
pub fn into_unchecked(self) -> UncheckedSigned {
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 {
/// 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,
}
impl, RealPayload: Encode> Signed {
/// Used to create a `Signed` from already existing parts.
///
/// The signature is checked as part of the process.
#[cfg(feature = "std")]
pub fn new(
payload: Payload,
validator_index: ValidatorIndex,
signature: ValidatorSignature,
context: &SigningContext,
key: &ValidatorId,
) -> Option {
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(
keystore: &SyncCryptoStorePtr,
payload: Payload,
context: &SigningContext,
validator_index: ValidatorIndex,
key: &ValidatorId,
) -> Result