From 27dfca8a72a35b6dd4a49106ec9ceff73abe2121 Mon Sep 17 00:00:00 2001 From: Chris Purta Date: Wed, 18 Jul 2018 12:21:23 -0700 Subject: [PATCH 1/6] Add bad blocks to Blockchain implementation --- ethcore/src/blockchain/blockchain.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index b2ba886b4dd..ac40c498c20 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -213,6 +213,7 @@ pub struct BlockChain { block_hashes: RwLock>, transaction_addresses: RwLock>, block_receipts: RwLock>, + bad_blocks: RwLock>, db: Arc, @@ -527,6 +528,7 @@ impl BlockChain { block_hashes: RwLock::new(HashMap::new()), transaction_addresses: RwLock::new(HashMap::new()), block_receipts: RwLock::new(HashMap::new()), + bad_blocks: RwLock::new(HashMap::new()), db: db.clone(), cache_man: Mutex::new(cache_man), pending_best_block: RwLock::new(None), @@ -985,6 +987,11 @@ impl BlockChain { let info = self.block_info(&header, route, &extras); + if self.is_blacklisted_hash(hash) { + self.bad_blocks.write().insert(hash, info); + return ImportRoute::none(); + } + if let BlockLocation::BranchBecomingCanonChain(ref d) = info.location { info!(target: "reorg", "Reorg to {} ({} {} {})", Colour::Yellow.bold().paint(format!("#{} {}", info.number, info.hash)), @@ -1364,6 +1371,26 @@ impl BlockChain { } } + /// Determine if a hash is blacklisted (part of a hard fork) + fn is_blacklisted_hash(&self, hash: H256) -> bool { + if self.blacklisted_hashes().contains_key(&hash) { + return true + } + false + } + + /// Get all blacklisted hashes + fn blacklisted_hashes(&self) -> HashMap { + let mut blacklist = HashMap::new(); + blacklist.insert("05bef30ef572270f654746da22639a7a0c97dd97a7050b9e252391996aaeb689".into(), true); + blacklist.insert("7d05d08cbc596a2e5e4f13b80a743e53e09221b5323c3a61946b20873e58583f".into(), true); + blacklist + } + + pub fn bad_blocks(&self) -> HashMap { + self.bad_blocks.read().clone() + } + /// Get best block hash. pub fn best_block_hash(&self) -> H256 { self.best_block.read().header.hash() From 9e0624c3eb4d98273d72b6457e5f5ae7080c9281 Mon Sep 17 00:00:00 2001 From: Chris Purta Date: Mon, 23 Jul 2018 08:58:42 -0700 Subject: [PATCH 2/6] Return blocks for getBadBlocks endpoint Updated the traits to allow for endpoints to return a result of badblocks that are held in the blockchain implementation. --- ethcore/src/blockchain/blockchain.rs | 4 ++-- ethcore/src/client/client.rs | 10 ++++++++++ ethcore/src/client/test_client.rs | 10 ++++++++++ ethcore/src/client/traits.rs | 3 +++ rpc/src/v1/impls/eth.rs | 9 +++++++++ rpc/src/v1/impls/light/eth.rs | 4 ++++ rpc/src/v1/traits/eth.rs | 4 ++++ 7 files changed, 42 insertions(+), 2 deletions(-) diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index ac40c498c20..ad58953a826 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -1387,8 +1387,8 @@ impl BlockChain { blacklist } - pub fn bad_blocks(&self) -> HashMap { - self.bad_blocks.read().clone() + pub fn bad_blocks(&self) -> Vec { + self.bad_blocks.read().iter().map(|(hash, _)| *hash).collect::>() } /// Get best block hash. diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 56c71a86ec9..046a03fe4e1 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -1650,6 +1650,16 @@ impl BlockChainClient for Client { Self::block_hash(&chain, id) } + fn bad_blocks(&self) -> Option> { + let blocks = self.chain.read().bad_blocks(); + + if blocks.len() > 0 { + Some(blocks) + } else { + None + } + } + fn code(&self, address: &Address, state: StateOrBlock) -> Option> { let result = match state { StateOrBlock::State(s) => s.code(address).ok(), diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 7a3dfcd0075..0f0c7cab553 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -324,6 +324,12 @@ impl TestBlockChainClient { } } + fn bad_blocks(&self) -> Option> { + let mut bad_block = Vec::new(); + bad_block.push("05bef30ef572270f654746da22639a7a0c97dd97a7050b9e252391996aaeb689".into()); + Some(bad_block) + } + /// Inserts a transaction with given gas price to miners transactions queue. pub fn insert_transaction_with_gas_price_to_queue(&self, gas_price: U256) -> H256 { let keypair = Random.generate().unwrap(); @@ -622,6 +628,10 @@ impl BlockChainClient for TestBlockChainClient { Self::block_hash(self, id) } + fn bad_blocks(&self) -> Option> { + Self::bad_blocks(self) + } + fn storage_root(&self, _address: &Address, _id: BlockId) -> Option { None } diff --git a/ethcore/src/client/traits.rs b/ethcore/src/client/traits.rs index 65bf0092118..4bf59acf733 100644 --- a/ethcore/src/client/traits.rs +++ b/ethcore/src/client/traits.rs @@ -233,6 +233,9 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra /// Get block hash. fn block_hash(&self, id: BlockId) -> Option; + /// Get all known bad blocks in chain. + fn bad_blocks(&self) -> Option>; + /// Get address code at given block's state. fn code(&self, address: &Address, state: StateOrBlock) -> Option>; diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index d20b2feb267..5bd177b4f7c 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -817,6 +817,15 @@ impl Eth for EthClient< Ok(true) } + fn bad_blocks(&self, include_txs: bool) -> BoxFuture> { + let blocks = self.client.bad_blocks() + .and_then(|vec| { + vec.iter().map(|hash| self.rich_block(BlockNumberOrId::Id(BlockId::Hash(*hash)), include_txs)).collect() + }).ok_or(Err("No bad blocks")); + + Box::new(future::done(blocks)) + } + fn send_raw_transaction(&self, raw: Bytes) -> Result { Rlp::new(&raw.into_vec()).as_val() .map_err(errors::rlp) diff --git a/rpc/src/v1/impls/light/eth.rs b/rpc/src/v1/impls/light/eth.rs index e88ac2dab35..5fe83cd7841 100644 --- a/rpc/src/v1/impls/light/eth.rs +++ b/rpc/src/v1/impls/light/eth.rs @@ -528,6 +528,10 @@ impl Eth for EthClient { fn submit_hashrate(&self, _rate: RpcU256, _id: RpcH256) -> Result { Err(errors::light_unimplemented(None)) } + + fn bad_blocks(&self, _include_txs: bool) -> BoxFuture> { + Box::new(future::done(Ok(>::new()))) + } } // This trait implementation triggers a blanked impl of `EthFilter`. diff --git a/rpc/src/v1/traits/eth.rs b/rpc/src/v1/traits/eth.rs index 48e315ce7e9..b73205fd071 100644 --- a/rpc/src/v1/traits/eth.rs +++ b/rpc/src/v1/traits/eth.rs @@ -174,6 +174,10 @@ build_rpc_trait! { /// Used for submitting mining hashrate. #[rpc(name = "eth_submitHashrate")] fn submit_hashrate(&self, U256, H256) -> Result; + + /// Used for finding bad blocks in current chain. + #[rpc(name = "debug_getBadBlocks")] + fn bad_blocks(&self, bool) -> BoxFuture>; } } From 602a7c4aa40a7cbdfe8ba50802c3e8af64f3ea24 Mon Sep 17 00:00:00 2001 From: Chris Purta Date: Mon, 23 Jul 2018 09:01:51 -0700 Subject: [PATCH 3/6] Use one line declaration --- rpc/src/v1/impls/eth.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 5bd177b4f7c..8393df3b3ac 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -818,10 +818,7 @@ impl Eth for EthClient< } fn bad_blocks(&self, include_txs: bool) -> BoxFuture> { - let blocks = self.client.bad_blocks() - .and_then(|vec| { - vec.iter().map(|hash| self.rich_block(BlockNumberOrId::Id(BlockId::Hash(*hash)), include_txs)).collect() - }).ok_or(Err("No bad blocks")); + let blocks = self.client.bad_blocks().and_then(|vec| vec.iter().map(|hash| self.rich_block(BlockNumberOrId::Id(BlockId::Hash(*hash)), include_txs)).collect()); Box::new(future::done(blocks)) } From d040683edff98e7a50577f0334e5135c4658dfd3 Mon Sep 17 00:00:00 2001 From: Chris Purta Date: Fri, 3 Aug 2018 16:46:41 -0700 Subject: [PATCH 4/6] Fix bad_blocks function Fixed the bad_blocks function by correctly unwrapping and chaining together functions to create RichBlocks from the hashes of the current bad_blocks on the chain. --- rpc/src/v1/impls/eth.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 8393df3b3ac..1a32c734892 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -818,9 +818,13 @@ impl Eth for EthClient< } fn bad_blocks(&self, include_txs: bool) -> BoxFuture> { - let blocks = self.client.bad_blocks().and_then(|vec| vec.iter().map(|hash| self.rich_block(BlockNumberOrId::Id(BlockId::Hash(*hash)), include_txs)).collect()); + let blocks = self.client.bad_blocks() + .unwrap() + .iter() + .map(|hash| self.rich_block(BlockNumberOrId::Id(BlockId::Hash(*hash)), include_txs).unwrap().unwrap()) + .collect(); - Box::new(future::done(blocks)) + Box::new(future::done(Ok(blocks))) } fn send_raw_transaction(&self, raw: Bytes) -> Result { From 51cfb69f5053c0713b4cdc508fc02407b856317f Mon Sep 17 00:00:00 2001 From: Chris Purta Date: Tue, 21 Aug 2018 12:14:39 -0700 Subject: [PATCH 5/6] Fix bad_blocks function from using unwrap --- rpc/src/v1/impls/eth.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 1a32c734892..0fafe76f7c5 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -819,10 +819,13 @@ impl Eth for EthClient< fn bad_blocks(&self, include_txs: bool) -> BoxFuture> { let blocks = self.client.bad_blocks() - .unwrap() - .iter() - .map(|hash| self.rich_block(BlockNumberOrId::Id(BlockId::Hash(*hash)), include_txs).unwrap().unwrap()) - .collect(); + .and_then(|vec| { + vec.iter() + .filter_map(|hash| { + self.rich_block(BlockNumberOrId::Id(BlockId::Hash(*hash)), include_txs).ok() + }) + .collect() + }); Box::new(future::done(Ok(blocks))) } From 9659c09277d5a9cc16cf3fde053e5181837c8adf Mon Sep 17 00:00:00 2001 From: Chris Purta Date: Wed, 22 Aug 2018 09:23:33 -0700 Subject: [PATCH 6/6] Use match on bad blocks for return value --- rpc/src/v1/impls/eth.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 0fafe76f7c5..c735ca9992e 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -827,7 +827,10 @@ impl Eth for EthClient< .collect() }); - Box::new(future::done(Ok(blocks))) + match blocks { + Some(b) => Box::new(future::done(Ok(b))), + None => Box::new(future::done(Ok(>::new()))) + } } fn send_raw_transaction(&self, raw: Bytes) -> Result {