diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 8af94b4ea..57eb101cb 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -937,6 +937,11 @@ impl ChainSync { } /// Called when peer sends us new transactions fn on_peer_transactions(&mut self, io: &mut SyncIo, peer_id: PeerId, r: &UntrustedRlp) -> Result<(), PacketDecodeError> { + // accepting transactions once only fully synced + if !io.is_chain_queue_empty() { + return Ok(()); + } + let item_count = r.item_count(); trace!(target: "sync", "{} -> Transactions ({} entries)", peer_id, item_count); @@ -1282,10 +1287,12 @@ impl ChainSync { /// called when block is imported to chain, updates transactions queue and propagates the blocks pub fn chain_new_blocks(&mut self, io: &mut SyncIo, imported: &[H256], invalid: &[H256], enacted: &[H256], retracted: &[H256]) { - // Notify miner - self.miner.chain_new_blocks(io.chain(), imported, invalid, enacted, retracted); - // Propagate latests blocks - self.propagate_latest_blocks(io); + if io.is_chain_queue_empty() { + // Notify miner + self.miner.chain_new_blocks(io.chain(), imported, invalid, enacted, retracted); + // Propagate latests blocks + self.propagate_latest_blocks(io); + } // TODO [todr] propagate transactions? } @@ -1654,6 +1661,33 @@ mod tests { assert_eq!(status.transactions_in_future_queue, 0); } + #[test] + fn should_not_add_transactions_to_queue_if_not_synced() { + // given + let mut client = TestBlockChainClient::new(); + client.add_blocks(98, EachBlockWith::Uncle); + client.add_blocks(1, EachBlockWith::UncleAndTransaction); + client.add_blocks(1, EachBlockWith::Transaction); + let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5)); + + let good_blocks = vec![client.block_hash_delta_minus(2)]; + let retracted_blocks = vec![client.block_hash_delta_minus(1)]; + + let mut queue = VecDeque::new(); + let mut io = TestIo::new(&mut client, &mut queue, None); + + // when + sync.chain_new_blocks(&mut io, &[], &[], &[], &good_blocks); + assert_eq!(sync.miner.status().transactions_in_future_queue, 0); + assert_eq!(sync.miner.status().transactions_in_pending_queue, 0); + sync.chain_new_blocks(&mut io, &good_blocks, &[], &[], &retracted_blocks); + + // then + let status = sync.miner.status(); + assert_eq!(status.transactions_in_pending_queue, 0); + assert_eq!(status.transactions_in_future_queue, 0); + } + #[test] fn returns_requested_block_headers() { let mut client = TestBlockChainClient::new(); diff --git a/sync/src/io.rs b/sync/src/io.rs index 00ee49be4..84697a021 100644 --- a/sync/src/io.rs +++ b/sync/src/io.rs @@ -37,6 +37,10 @@ pub trait SyncIo { fn peer_info(&self, peer_id: PeerId) -> String { peer_id.to_string() } + /// Returns if the chain block queue empty + fn is_chain_queue_empty(&self) -> bool { + self.chain().queue_info().is_empty() + } } /// Wraps `NetworkContext` and the blockchain client diff --git a/sync/src/lib.rs b/sync/src/lib.rs index 1c87da2de..a4f6eff38 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -173,7 +173,7 @@ impl NetworkProtocolHandler for EthSync { SyncMessage::NewChainHead => { let mut sync_io = NetSyncIo::new(io, self.chain.deref()); self.sync.write().unwrap().chain_new_head(&mut sync_io); - } + }, _ => {/* Ignore other messages */}, } }