openethereum/ethcore/engines/validator-set/src/test.rs
Andreas Fackler f59ed47b1b Aura: Report malice on sibling blocks from the same validator (#11160)
* Aura: Report malice on sibling blocks from the same validator

This was originally written by @vkomenda, then squashed for
easier rebasing on master. Cleanup of `received_step_hashes`
was moved to `verify_block_family`, since `on_prepare_block`
does not exist on master, and a unit test was added.
Original commit messages:

added the map of received block header hashes

do not return an error and remove older received block records

optimised older record removal

block hash comparison optimisation and the weak client ref fix

SIBLING_MALICE_DETECTION_PERIOD constant

review comments

using step numbers instead of block numbers

* Add docs; use map_or.

* Update step hash record comment.

Co-Authored-By: David <dvdplm@gmail.com>

* Remove hash records after 2 rounds instead of 100 steps.
2019-10-14 12:56:38 +02:00

118 lines
3.4 KiB
Rust

// Copyright 2015-2019 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 <http://www.gnu.org/licenses/>.
/// Used for Engine testing.
use std::str::FromStr;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering};
use log::trace;
use parity_util_mem::MallocSizeOf;
use common_types::{
BlockNumber,
ids::BlockId,
header::Header,
errors::EthcoreError,
engines::machine::{Call, AuxiliaryData},
};
use ethereum_types::{H256, Address};
use machine::Machine;
use parity_bytes::Bytes;
use super::{ValidatorSet, SimpleList};
/// Set used for testing with a single validator.
#[derive(Clone, MallocSizeOf, Debug)]
pub struct TestSet {
validator: SimpleList,
#[ignore_malloc_size_of = "zero sized"]
last_malicious: Arc<AtomicUsize>,
#[ignore_malloc_size_of = "zero sized"]
last_benign: Arc<AtomicUsize>,
}
impl Default for TestSet {
fn default() -> Self {
TestSet::new(
Default::default(),
Default::default(),
vec![Address::from_str("7d577a597b2742b498cb5cf0c26cdcd726d39e6e").unwrap()]
)
}
}
impl TestSet {
pub fn new(last_malicious: Arc<AtomicUsize>, last_benign: Arc<AtomicUsize>, validators: Vec<Address>) -> Self {
TestSet {
validator: SimpleList::new(validators),
last_malicious,
last_benign,
}
}
pub fn from_validators(validators: Vec<Address>) -> Self {
TestSet::new(Default::default(), Default::default(), validators)
}
pub fn last_malicious(&self) -> usize {
self.last_malicious.load(AtomicOrdering::SeqCst)
}
pub fn last_benign(&self) -> usize {
self.last_benign.load(AtomicOrdering::SeqCst)
}
}
impl ValidatorSet for TestSet {
fn default_caller(&self, _block_id: BlockId) -> Box<Call> {
Box::new(|_, _| Err("Test set doesn't require calls.".into()))
}
fn is_epoch_end(&self, _first: bool, _chain_head: &Header) -> Option<Vec<u8>> { None }
fn signals_epoch_end(&self, _: bool, _: &Header, _: AuxiliaryData)
-> engine::EpochChange
{
engine::EpochChange::No
}
fn epoch_set(&self, _: bool, _: &Machine, _: BlockNumber, _: &[u8]) -> Result<(SimpleList, Option<H256>), EthcoreError> {
Ok((self.validator.clone(), None))
}
fn contains_with_caller(&self, bh: &H256, address: &Address, _: &Call) -> bool {
self.validator.contains(bh, address)
}
fn get_with_caller(&self, bh: &H256, nonce: usize, _: &Call) -> Address {
self.validator.get(bh, nonce)
}
fn count_with_caller(&self, _bh: &H256, _: &Call) -> usize {
1
}
fn report_malicious(&self, _validator: &Address, _set_block: BlockNumber, block: BlockNumber, _proof: Bytes) {
self.last_malicious.store(block as usize, AtomicOrdering::SeqCst)
}
fn report_benign(&self, _validator: &Address, _set_block: BlockNumber, block: BlockNumber) {
trace!(target: "engine", "test validator set recording benign misbehaviour");
self.last_benign.store(block as usize, AtomicOrdering::SeqCst)
}
}