Light protocol syncing improvements (#4212)

* remove old lint silencer

* dispatch requests only to peers with higher TD

* dynamic target for sync rounds

* use round pivots instead of frames, fix test

* fix total difficulty calculation for test client

* fix broken reorg algorithm

* fork test, fix ancestor search
This commit is contained in:
Robert Habermeier
2017-01-20 12:41:59 +01:00
committed by Arkadiy Paronyan
parent 3ff9324ec0
commit a791cb50a6
7 changed files with 254 additions and 80 deletions

View File

@@ -14,6 +14,50 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
#![allow(dead_code)]
use tests::helpers::TestNet;
use ethcore::client::{BlockChainClient, BlockId, EachBlockWith};
mod test_net;
#[test]
fn basic_sync() {
let mut net = TestNet::light(1, 2);
net.peer(1).chain().add_blocks(5000, EachBlockWith::Nothing);
net.peer(2).chain().add_blocks(6000, EachBlockWith::Nothing);
net.sync();
assert!(net.peer(0).light_chain().get_header(BlockId::Number(6000)).is_some());
}
#[test]
fn fork_post_cht() {
const CHAIN_LENGTH: u64 = 50; // shouldn't be longer than ::light::cht::size();
let mut net = TestNet::light(1, 2);
// peer 2 is on a higher TD chain.
net.peer(1).chain().add_blocks(CHAIN_LENGTH as usize, EachBlockWith::Nothing);
net.peer(2).chain().add_blocks(CHAIN_LENGTH as usize + 1, EachBlockWith::Uncle);
// get the light peer on peer 1's chain.
for id in (0..CHAIN_LENGTH).map(|x| x + 1).map(BlockId::Number) {
let (light_peer, full_peer) = (net.peer(0), net.peer(1));
let light_chain = light_peer.light_chain();
let header = full_peer.chain().block_header(id).unwrap().decode();
let _ = light_chain.import_header(header);
light_chain.flush_queue();
light_chain.import_verified();
assert!(light_chain.get_header(id).is_some());
}
net.sync();
for id in (0..CHAIN_LENGTH).map(|x| x + 1).map(BlockId::Number) {
assert_eq!(
net.peer(0).light_chain().get_header(id),
net.peer(2).chain().block_header(id).map(|h| h.into_inner())
);
}
}

View File

@@ -174,13 +174,24 @@ impl PeerLike for Peer {
}
fn is_done(&self) -> bool {
self.queue.read().is_empty()
self.queue.read().is_empty() && match self.data {
PeerData::Light(_, ref client) => {
// should create a test light client which just imports
// headers directly and doesn't have a queue to drain.
client.import_verified();
client.queue_info().is_empty()
}
_ => true,
}
}
fn sync_step(&self) {
if let PeerData::Light(_, ref client) = self.data {
client.flush_queue();
client.import_verified();
while !client.queue_info().is_empty() {
client.import_verified()
}
}
}