// Copyright 2015-2020 Parity Technologies (UK) Ltd. // This file is part of OpenEthereum. // OpenEthereum 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. // OpenEthereum 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 OpenEthereum. If not, see . //! Stores recently seen bad blocks. use bytes::{Bytes, ToPretty}; use ethereum_types::H256; use itertools::Itertools; use memory_cache::MemoryLruCache; use parking_lot::RwLock; use types::BlockNumber; use verification::queue::kind::blocks::Unverified; /// Recently seen bad blocks. pub struct BadBlocks { last_blocks: RwLock>, } impl Default for BadBlocks { fn default() -> Self { BadBlocks { last_blocks: RwLock::new(MemoryLruCache::new(8 * 1024 * 1024)), } } } impl BadBlocks { /// Reports given RLP as invalid block. pub fn report(&self, raw: Bytes, message: String, eip1559_transition: BlockNumber) { match Unverified::from_rlp(raw, eip1559_transition) { Ok(unverified) => { error!( target: "client", "\nBad block detected: {}\nRLP: {}\nHeader: {:?}\nUncles: {}\nTransactions:{}\n", message, unverified.bytes.to_hex(), unverified.header, unverified.uncles .iter() .enumerate() .map(|(index, uncle)| format!("[Uncle {}] {:?}", index, uncle)) .join("\n"), unverified.transactions .iter() .enumerate() .map(|(index, tx)| format!("[Tx {}] {:?}", index, tx)) .join("\n"), ); self.last_blocks .write() .insert(unverified.header.hash(), (unverified, message)); } Err(err) => { error!(target: "client", "Bad undecodable block detected: {}\n{:?}", message, err); } } } /// Returns a list of recently detected bad blocks with error descriptions. pub fn bad_blocks(&self, eip1559_transition: BlockNumber) -> Vec<(Unverified, String)> { self.last_blocks .read() .backstore() .iter() .map(|(_k, (unverified, message))| { ( Unverified::from_rlp(unverified.bytes.clone(), eip1559_transition) .expect("Bytes coming from UnverifiedBlock so decodable; qed"), message.clone(), ) }) .collect() } }