// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
// Parity Ethereum 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.
// Parity Ethereum 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 Parity Ethereum. If not, see .
//! A blockchain engine that supports a basic, non-BFT proof-of-authority.
use std::sync::Weak;
use common_types::{
header::Header,
engines::{
Headers,
PendingTransitionStore,
SealingState,
Seal,
params::CommonParams,
machine::{AuxiliaryData, Call},
},
errors::{EngineError, BlockError, EthcoreError as Error},
};
use client_traits::EngineClient;
use ethereum_types::{H256, H520};
use parking_lot::RwLock;
use engine::{Engine, ConstructedVerifier, signer::EngineSigner};
use parity_crypto::publickey::Signature;
use log::trace;
use machine::{Machine, executed_block::ExecutedBlock};
use rlp::Rlp;
use validator_set::{ValidatorSet, SimpleList, new_validator_set};
/// `BasicAuthority` params.
#[derive(Debug, PartialEq)]
pub struct BasicAuthorityParams {
/// Valid signatories.
pub validators: ethjson::spec::ValidatorSet,
}
impl From for BasicAuthorityParams {
fn from(p: ethjson::spec::BasicAuthorityParams) -> Self {
BasicAuthorityParams {
validators: p.validators,
}
}
}
struct EpochVerifier {
list: SimpleList,
}
impl engine::EpochVerifier for EpochVerifier {
fn verify_light(&self, header: &Header) -> Result<(), Error> {
verify_external(header, &self.list)
}
}
fn verify_external(header: &Header, validators: &dyn ValidatorSet) -> Result<(), Error> {
// Check if the signature belongs to a validator, can depend on parent state.
let sig = Rlp::new(&header.seal()[0]).as_val::()?;
let signer = parity_crypto::publickey::public_to_address(&parity_crypto::publickey::recover(&sig.into(), &header.bare_hash())?);
if *header.author() != signer {
return Err(EngineError::NotAuthorized(*header.author()).into())
}
match validators.contains(header.parent_hash(), &signer) {
false => Err(Error::Block(BlockError::InvalidSeal)),
true => Ok(())
}
}
/// Engine using `BasicAuthority`, trivial proof-of-authority consensus.
pub struct BasicAuthority {
machine: Machine,
signer: RwLock