diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index d951523417a..77d638deb19 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -518,6 +518,11 @@ impl BlockChain { /// Given a block's `parent`, find every block header which represents a valid possible uncle. pub fn find_uncle_headers(&self, parent: &H256, uncle_generations: usize) -> Option> { + self.find_uncle_hashes(parent, uncle_generations).map(|v| v.into_iter().filter_map(|h| self.block_header(&h)).collect()) + } + + /// Given a block's `parent`, find every block hash which represents a valid possible uncle. + pub fn find_uncle_hashes(&self, parent: &H256, uncle_generations: usize) -> Option> { if !self.is_known(parent) { return None; } let mut excluded = HashSet::new(); @@ -529,7 +534,7 @@ impl BlockChain { let mut ret = Vec::new(); for a in self.ancestry_iter(parent.clone()).unwrap().skip(1).take(uncle_generations) { ret.extend(self.block_details(&a).unwrap().children.iter() - .filter_map(|h| if excluded.contains(h) { None } else { self.block_header(h) }) + .filter(|h| !excluded.contains(h)) ); } Some(ret) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 83b77b7748d..80e423d0bfb 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -622,6 +622,10 @@ impl BlockChainClient for Client where V: Verifier { } } + fn find_uncles(&self, hash: &H256) -> Option> { + self.chain.find_uncle_hashes(hash, self.engine.maximum_uncle_age()) + } + fn state_data(&self, hash: &H256) -> Option { self.state_db.lock().unwrap().state(hash) } diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 5c83d14c2d2..4a3d2c5f461 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -93,6 +93,9 @@ pub trait BlockChainClient : Sync + Send { /// See `BlockChain::tree_route`. fn tree_route(&self, from: &H256, to: &H256) -> Option; + /// Get all possible uncle hashes for a block. + fn find_uncles(&self, hash: &H256) -> Option>; + /// Get latest state node fn state_data(&self, hash: &H256) -> Option; diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 014566b6fee..b75ab9ea0b2 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -348,6 +348,10 @@ impl BlockChainClient for TestBlockChainClient { }) } + fn find_uncles(&self, _hash: &H256) -> Option> { + None + } + // TODO: returns just hashes instead of node state rlp(?) fn state_data(&self, hash: &H256) -> Option { // starts with 'f' ? diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 01f6749f98e..68700d5d255 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -252,7 +252,7 @@ impl ChainSync { let chain = chain.chain_info(); let mut sync = ChainSync { state: SyncState::ChainHead, - starting_block: 0, + starting_block: chain.best_block_number, highest_block: None, last_imported_block: chain.best_block_number, last_imported_hash: chain.best_block_hash, @@ -278,7 +278,7 @@ impl ChainSync { network_id: self.network_id, start_block_number: self.starting_block, last_imported_block_number: Some(self.last_imported_block), - highest_block_number: self.highest_block, + highest_block_number: self.highest_block.map(|n| max(n, self.last_imported_block)), blocks_received: if self.last_imported_block > self.starting_block { self.last_imported_block - self.starting_block } else { 0 }, blocks_total: match self.highest_block { Some(x) if x > self.starting_block => x - self.starting_block, _ => 0 }, num_peers: self.peers.len(), @@ -1114,11 +1114,14 @@ impl ChainSync { fn create_new_hashes_rlp(chain: &BlockChainClient, from: &H256, to: &H256) -> Option { match chain.tree_route(from, to) { Some(route) => { + let uncles = chain.find_uncles(from).unwrap_or_else(Vec::new); match route.blocks.len() { 0 => None, _ => { - let mut rlp_stream = RlpStream::new_list(route.blocks.len()); - for block_hash in route.blocks { + let mut blocks = route.blocks; + blocks.extend(uncles); + let mut rlp_stream = RlpStream::new_list(blocks.len()); + for block_hash in blocks { let mut hash_rlp = RlpStream::new_list(2); let difficulty = chain.block_total_difficulty(BlockID::Hash(block_hash.clone())).expect("Malformed block without a difficulty on the chain!"); hash_rlp.append(&block_hash);