Bad blocks RPC + reporting (#9433)

* Bad blocks RPC.

* Return bad blocks via RPC.

* Fix test.

* More verbose bad block message.

* Expose via CLI.

* Remove stray whitespace.

* Remove stray newline.

* Fix tests.
This commit is contained in:
Tomasz Drwięga
2018-09-08 04:04:28 +02:00
committed by Afri Schoedon
parent 915c366056
commit 61bd47ccc1
15 changed files with 375 additions and 59 deletions

96
rpc/src/v1/impls/debug.rs Normal file
View File

@@ -0,0 +1,96 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity 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 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. If not, see <http://www.gnu.org/licenses/>.
//! Debug APIs RPC implementation
use std::sync::Arc;
use ethcore::client::BlockChainClient;
use transaction::LocalizedTransaction;
use jsonrpc_core::Result;
use v1::traits::Debug;
use v1::types::{Block, Bytes, RichBlock, BlockTransactions, Transaction};
/// Debug rpc implementation.
pub struct DebugClient<C> {
client: Arc<C>,
}
impl<C> DebugClient<C> {
/// Creates new debug client.
pub fn new(client: Arc<C>) -> Self {
Self {
client,
}
}
}
impl<C: BlockChainClient + 'static> Debug for DebugClient<C> {
fn bad_blocks(&self) -> Result<Vec<RichBlock>> {
fn cast<O, T: Copy + Into<O>>(t: &T) -> O {
(*t).into()
}
Ok(self.client.bad_blocks().into_iter().map(|(block, reason)| {
let number = block.header.number();
let hash = block.header.hash();
RichBlock {
inner: Block {
hash: Some(hash.into()),
size: Some(block.bytes.len().into()),
parent_hash: cast(block.header.parent_hash()),
uncles_hash: cast(block.header.uncles_hash()),
author: cast(block.header.author()),
miner: cast(block.header.author()),
state_root: cast(block.header.state_root()),
receipts_root: cast(block.header.receipts_root()),
number: Some(number.into()),
gas_used: cast(block.header.gas_used()),
gas_limit: cast(block.header.gas_limit()),
logs_bloom: Some(cast(block.header.log_bloom())),
timestamp: block.header.timestamp().into(),
difficulty: cast(block.header.difficulty()),
total_difficulty: None,
seal_fields: block.header.seal().into_iter().cloned().map(Into::into).collect(),
uncles: block.uncles.into_iter().map(|u| u.hash().into()).collect(),
transactions: BlockTransactions::Full(block.transactions
.into_iter()
.enumerate()
.map(|(transaction_index, signed)| Transaction::from_localized(LocalizedTransaction {
block_number: number.into(),
block_hash: hash.into(),
transaction_index,
signed,
cached_sender: None,
})).collect()
),
transactions_root: cast(block.header.transactions_root()),
extra_data: block.header.extra_data().clone().into(),
},
extra_info: vec![
("reason".to_owned(), reason),
("rlp".to_owned(), serialize(&Bytes(block.bytes))),
("hash".to_owned(), format!("{:#x}", hash)),
].into_iter().collect(),
}
}).collect())
}
}
fn serialize<T: ::serde::Serialize>(t: &T) -> String {
::serde_json::to_string(t).expect("RPC types serialization is non-fallible.")
}

View File

@@ -16,6 +16,7 @@
//! Ethereum rpc interface implementation.
mod debug;
mod eth;
mod eth_filter;
mod eth_pubsub;
@@ -24,18 +25,19 @@ mod parity;
mod parity_accounts;
mod parity_set;
mod personal;
mod private;
mod pubsub;
mod rpc;
mod secretstore;
mod signer;
mod signing;
mod signing_unsafe;
mod rpc;
mod secretstore;
mod traces;
mod web3;
mod private;
pub mod light;
pub use self::debug::DebugClient;
pub use self::eth::{EthClient, EthClientOptions};
pub use self::eth_filter::EthFilterClient;
pub use self::eth_pubsub::EthPubSubClient;
@@ -44,12 +46,12 @@ pub use self::parity::ParityClient;
pub use self::parity_accounts::ParityAccountsClient;
pub use self::parity_set::ParitySetClient;
pub use self::personal::PersonalClient;
pub use self::private::PrivateClient;
pub use self::pubsub::PubSubClient;
pub use self::rpc::RpcClient;
pub use self::secretstore::SecretStoreClient;
pub use self::signer::SignerClient;
pub use self::signing::SigningQueueClient;
pub use self::signing_unsafe::SigningUnsafeClient;
pub use self::traces::TracesClient;
pub use self::web3::Web3Client;
pub use self::rpc::RpcClient;
pub use self::secretstore::SecretStoreClient;
pub use self::private::PrivateClient;

View File

@@ -41,7 +41,7 @@ pub mod informant;
pub mod metadata;
pub mod traits;
pub use self::traits::{Web3, Eth, EthFilter, EthPubSub, EthSigning, Net, Parity, ParityAccounts, ParitySet, ParitySigning, PubSub, Signer, Personal, Traces, Rpc, SecretStore, Private};
pub use self::traits::{Debug, Eth, EthFilter, EthPubSub, EthSigning, Net, Parity, ParityAccounts, ParitySet, ParitySigning, Personal, PubSub, Private, Rpc, SecretStore, Signer, Traces, Web3};
pub use self::impls::*;
pub use self::helpers::{NetworkSettings, block_import, dispatch};
pub use self::metadata::Metadata;

View File

@@ -0,0 +1,37 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity 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 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. If not, see <http://www.gnu.org/licenses/>.
use std::sync::Arc;
use ethcore::client::TestBlockChainClient;
use jsonrpc_core::IoHandler;
use v1::{Debug, DebugClient};
fn io() -> IoHandler {
let client = Arc::new(TestBlockChainClient::new());
let mut io = IoHandler::new();
io.extend_with(DebugClient::new(client).to_delegate());
io
}
#[test]
fn rpc_debug_get_bad_blocks() {
let request = r#"{"jsonrpc": "2.0", "method": "debug_getBadBlocks", "params": [], "id": 1}"#;
let response = "{\"jsonrpc\":\"2.0\",\"result\":[{\"author\":\"0x0000000000000000000000000000000000000000\",\"difficulty\":\"0x0\",\"extraData\":\"0x\",\"gasLimit\":\"0x0\",\"gasUsed\":\"0x0\",\"hash\":\"27bfb37e507ce90da141307204b1c6ba24194380613590ac50ca4b1d7198ff65\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x0000000000000000000000000000000000000000\",\"number\":\"0x0\",\"parentHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"reason\":\"Invalid block\",\"receiptsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"rlp\":\"\\\"0x010203\\\"\",\"sealFields\":[],\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x3\",\"stateRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"timestamp\":\"0x0\",\"totalDifficulty\":null,\"transactions\":[],\"transactionsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"uncles\":[]}],\"id\":1}";
assert_eq!(io().handle_request_sync(request), Some(response.to_owned()));
}

View File

@@ -17,6 +17,7 @@
//! RPC mocked tests. Most of these test that the RPC server is serializing and forwarding
//! method calls properly.
mod debug;
mod eth;
mod eth_pubsub;
mod manage_network;

View File

@@ -0,0 +1,30 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity 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 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. If not, see <http://www.gnu.org/licenses/>.
//! Debug RPC interface.
use jsonrpc_core::Result;
use v1::types::RichBlock;
build_rpc_trait! {
/// Debug RPC interface.
pub trait Debug {
/// Returns recently seen bad blocks.
#[rpc(name = "debug_getBadBlocks")]
fn bad_blocks(&self) -> Result<Vec<RichBlock>>;
}
}

View File

@@ -16,7 +16,7 @@
//! Ethereum rpc interfaces.
pub mod web3;
pub mod debug;
pub mod eth;
pub mod eth_pubsub;
pub mod eth_signing;
@@ -26,14 +26,15 @@ pub mod parity_accounts;
pub mod parity_set;
pub mod parity_signing;
pub mod personal;
pub mod private;
pub mod pubsub;
pub mod signer;
pub mod traces;
pub mod rpc;
pub mod secretstore;
pub mod private;
pub mod signer;
pub mod traces;
pub mod web3;
pub use self::web3::Web3;
pub use self::debug::Debug;
pub use self::eth::{Eth, EthFilter};
pub use self::eth_pubsub::EthPubSub;
pub use self::eth_signing::EthSigning;
@@ -43,9 +44,10 @@ pub use self::parity_accounts::ParityAccounts;
pub use self::parity_set::ParitySet;
pub use self::parity_signing::ParitySigning;
pub use self::personal::Personal;
pub use self::private::Private;
pub use self::pubsub::PubSub;
pub use self::signer::Signer;
pub use self::traces::Traces;
pub use self::rpc::Rpc;
pub use self::secretstore::SecretStore;
pub use self::private::Private;
pub use self::signer::Signer;
pub use self::traces::Traces;
pub use self::web3::Web3;