2020-09-22 14:53:52 +02:00
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
2018-05-09 12:05:34 +02:00
2020-09-22 14:53:52 +02:00
// OpenEthereum is free software: you can redistribute it and/or modify
2018-05-09 12:05:34 +02:00
// 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.
2020-09-22 14:53:52 +02:00
// OpenEthereum is distributed in the hope that it will be useful,
2018-05-09 12:05:34 +02:00
// 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
2020-09-22 14:53:52 +02:00
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
2018-05-09 12:05:34 +02:00
use block_sync ::BlockRequest ;
use bytes ::Bytes ;
use ethereum_types ::H256 ;
2019-02-13 09:20:33 +01:00
use network ::PeerId ;
2018-05-09 12:05:34 +02:00
use rlp ::RlpStream ;
use std ::time ::Instant ;
use sync_io ::SyncIo ;
2019-01-04 14:05:46 +01:00
use types ::BlockNumber ;
2018-05-09 12:05:34 +02:00
2021-07-05 15:59:22 +02:00
use super ::{
request_id ::generate_request_id ,
sync_packet ::{ SyncPacket ::* , * } ,
} ;
2019-02-13 09:20:33 +01:00
2018-05-09 12:05:34 +02:00
use super ::{ BlockSet , ChainSync , PeerAsking } ;
/// The Chain Sync Requester: requesting data to other peers
pub struct SyncRequester ;
impl SyncRequester {
/// Perform block download request`
pub fn request_blocks (
sync : & mut ChainSync ,
2020-07-29 10:36:15 +02:00
io : & mut dyn SyncIo ,
2018-05-09 12:05:34 +02:00
peer_id : PeerId ,
request : BlockRequest ,
block_set : BlockSet ,
) {
match request {
BlockRequest ::Headers { start , count , skip } = > {
SyncRequester ::request_headers_by_hash (
sync , io , peer_id , & start , count , skip , false , block_set ,
) ;
}
BlockRequest ::Bodies { hashes } = > {
SyncRequester ::request_bodies ( sync , io , peer_id , hashes , block_set ) ;
}
BlockRequest ::Receipts { hashes } = > {
SyncRequester ::request_receipts ( sync , io , peer_id , hashes , block_set ) ;
}
}
}
2020-08-05 06:08:03 +02:00
2018-05-09 12:05:34 +02:00
/// Request block bodies from a peer
fn request_bodies (
sync : & mut ChainSync ,
2020-07-29 10:36:15 +02:00
io : & mut dyn SyncIo ,
2018-05-09 12:05:34 +02:00
peer_id : PeerId ,
hashes : Vec < H256 > ,
set : BlockSet ,
) {
let mut rlp = RlpStream ::new_list ( hashes . len ( ) ) ;
trace! ( target : " sync " , " {} <- GetBlockBodies: {} entries starting from {:?}, set = {:?} " , peer_id , hashes . len ( ) , hashes . first ( ) , set ) ;
for h in & hashes {
rlp . append ( & h . clone ( ) ) ;
}
2019-02-13 09:20:33 +01:00
SyncRequester ::send_request (
sync ,
io ,
peer_id ,
PeerAsking ::BlockBodies ,
GetBlockBodiesPacket ,
rlp . out ( ) ,
) ;
2018-05-09 12:05:34 +02:00
let peer = sync . peers . get_mut ( & peer_id ) . expect ( " peer_id may originate either from on_packet, where it is already validated or from enumerating self.peers. qed " ) ;
peer . asking_blocks = hashes ;
peer . block_set = Some ( set ) ;
}
2020-08-05 06:08:03 +02:00
2018-05-09 12:05:34 +02:00
/// Request headers from a peer by block number
pub fn request_fork_header (
sync : & mut ChainSync ,
2020-07-29 10:36:15 +02:00
io : & mut dyn SyncIo ,
2018-05-09 12:05:34 +02:00
peer_id : PeerId ,
n : BlockNumber ,
) {
trace! ( target : " sync " , " {} <- GetForkHeader: at {} " , peer_id , n ) ;
let mut rlp = RlpStream ::new_list ( 4 ) ;
rlp . append ( & n ) ;
rlp . append ( & 1 u32 ) ;
rlp . append ( & 0 u32 ) ;
rlp . append ( & 0 u32 ) ;
2019-02-13 09:20:33 +01:00
SyncRequester ::send_request (
sync ,
io ,
peer_id ,
PeerAsking ::ForkHeader ,
GetBlockHeadersPacket ,
rlp . out ( ) ,
) ;
2018-05-09 12:05:34 +02:00
}
2020-08-05 06:08:03 +02:00
2021-04-27 15:33:40 +02:00
/// Request pooled transactions from a peer
pub fn request_pooled_transactions (
sync : & mut ChainSync ,
io : & mut dyn SyncIo ,
peer_id : PeerId ,
hashes : & [ H256 ] ,
) {
trace! ( target : " sync " , " {} <- GetPooledTransactions: {:?} " , peer_id , hashes ) ;
let mut rlp = RlpStream ::new_list ( hashes . len ( ) ) ;
for h in hashes {
rlp . append ( h ) ;
}
SyncRequester ::send_request (
sync ,
io ,
peer_id ,
PeerAsking ::PooledTransactions ,
PooledTransactionsPacket ,
rlp . out ( ) ,
)
}
2018-05-09 12:05:34 +02:00
/// Find some headers or blocks to download for a peer.
2020-07-29 10:36:15 +02:00
pub fn request_snapshot_data ( sync : & mut ChainSync , io : & mut dyn SyncIo , peer_id : PeerId ) {
2018-05-09 12:05:34 +02:00
// find chunk data to download
if let Some ( hash ) = sync . snapshot . needed_chunk ( ) {
if let Some ( ref mut peer ) = sync . peers . get_mut ( & peer_id ) {
peer . asking_snapshot_data = Some ( hash . clone ( ) ) ;
}
SyncRequester ::request_snapshot_chunk ( sync , io , peer_id , & hash ) ;
2020-08-05 06:08:03 +02:00
}
2018-05-09 12:05:34 +02:00
}
2020-08-05 06:08:03 +02:00
2018-05-09 12:05:34 +02:00
/// Request snapshot manifest from a peer.
2020-07-29 10:36:15 +02:00
pub fn request_snapshot_manifest ( sync : & mut ChainSync , io : & mut dyn SyncIo , peer_id : PeerId ) {
2018-05-09 12:05:34 +02:00
trace! ( target : " sync " , " {} <- GetSnapshotManifest " , peer_id ) ;
let rlp = RlpStream ::new_list ( 0 ) ;
2019-02-13 09:20:33 +01:00
SyncRequester ::send_request (
sync ,
io ,
peer_id ,
PeerAsking ::SnapshotManifest ,
GetSnapshotManifestPacket ,
rlp . out ( ) ,
) ;
2018-05-09 12:05:34 +02:00
}
2020-08-05 06:08:03 +02:00
2018-05-09 12:05:34 +02:00
/// Request headers from a peer by block hash
fn request_headers_by_hash (
sync : & mut ChainSync ,
2020-07-29 10:36:15 +02:00
io : & mut dyn SyncIo ,
2018-05-09 12:05:34 +02:00
peer_id : PeerId ,
h : & H256 ,
count : u64 ,
skip : u64 ,
reverse : bool ,
set : BlockSet ,
) {
trace! ( target : " sync " , " {} <- GetBlockHeaders: {} entries starting from {}, set = {:?} " , peer_id , count , h , set ) ;
let mut rlp = RlpStream ::new_list ( 4 ) ;
rlp . append ( h ) ;
rlp . append ( & count ) ;
rlp . append ( & skip ) ;
rlp . append ( & if reverse { 1 u32 } else { 0 u32 } ) ;
2019-02-13 09:20:33 +01:00
SyncRequester ::send_request (
sync ,
io ,
peer_id ,
PeerAsking ::BlockHeaders ,
GetBlockHeadersPacket ,
rlp . out ( ) ,
) ;
2018-05-09 12:05:34 +02:00
let peer = sync . peers . get_mut ( & peer_id ) . expect ( " peer_id may originate either from on_packet, where it is already validated or from enumerating self.peers. qed " ) ;
peer . asking_hash = Some ( h . clone ( ) ) ;
peer . block_set = Some ( set ) ;
}
2020-08-05 06:08:03 +02:00
2018-05-09 12:05:34 +02:00
/// Request block receipts from a peer
fn request_receipts (
sync : & mut ChainSync ,
2020-07-29 10:36:15 +02:00
io : & mut dyn SyncIo ,
2018-05-09 12:05:34 +02:00
peer_id : PeerId ,
hashes : Vec < H256 > ,
set : BlockSet ,
) {
let mut rlp = RlpStream ::new_list ( hashes . len ( ) ) ;
trace! ( target : " sync " , " {} <- GetBlockReceipts: {} entries starting from {:?}, set = {:?} " , peer_id , hashes . len ( ) , hashes . first ( ) , set ) ;
for h in & hashes {
rlp . append ( & h . clone ( ) ) ;
}
2019-02-13 09:20:33 +01:00
SyncRequester ::send_request (
sync ,
io ,
peer_id ,
PeerAsking ::BlockReceipts ,
GetReceiptsPacket ,
rlp . out ( ) ,
) ;
2018-05-09 12:05:34 +02:00
let peer = sync . peers . get_mut ( & peer_id ) . expect ( " peer_id may originate either from on_packet, where it is already validated or from enumerating self.peers. qed " ) ;
peer . asking_blocks = hashes ;
peer . block_set = Some ( set ) ;
}
2020-08-05 06:08:03 +02:00
2018-05-09 12:05:34 +02:00
/// Request snapshot chunk from a peer.
fn request_snapshot_chunk (
sync : & mut ChainSync ,
2020-07-29 10:36:15 +02:00
io : & mut dyn SyncIo ,
2018-05-09 12:05:34 +02:00
peer_id : PeerId ,
chunk : & H256 ,
) {
trace! ( target : " sync " , " {} <- GetSnapshotData {:?} " , peer_id , chunk ) ;
let mut rlp = RlpStream ::new_list ( 1 ) ;
rlp . append ( chunk ) ;
2019-02-13 09:20:33 +01:00
SyncRequester ::send_request (
sync ,
io ,
peer_id ,
PeerAsking ::SnapshotData ,
GetSnapshotDataPacket ,
rlp . out ( ) ,
) ;
2018-05-09 12:05:34 +02:00
}
2020-08-05 06:08:03 +02:00
2018-05-09 12:05:34 +02:00
/// Generic request sender
2019-02-13 09:20:33 +01:00
fn send_request (
sync : & mut ChainSync ,
2020-07-29 10:36:15 +02:00
io : & mut dyn SyncIo ,
2019-02-13 09:20:33 +01:00
peer_id : PeerId ,
asking : PeerAsking ,
packet_id : SyncPacket ,
packet : Bytes ,
) {
2018-05-09 12:05:34 +02:00
if let Some ( ref mut peer ) = sync . peers . get_mut ( & peer_id ) {
if peer . asking ! = PeerAsking ::Nothing {
warn! ( target :" sync " , " Asking {:?} while requesting {:?} " , peer . asking , asking ) ;
}
peer . asking = asking ;
peer . ask_time = Instant ::now ( ) ;
2020-08-05 06:08:03 +02:00
2021-07-05 15:59:22 +02:00
let ( packet , _ ) = generate_request_id ( packet , peer , packet_id ) ;
2019-02-13 09:20:33 +01:00
let result = io . send ( peer_id , packet_id , packet ) ;
2020-08-05 06:08:03 +02:00
2018-05-09 12:05:34 +02:00
if let Err ( e ) = result {
debug! ( target :" sync " , " Error sending request: {:?} " , e ) ;
io . disconnect_peer ( peer_id ) ;
}
}
2020-08-05 06:08:03 +02:00
}
2018-05-09 12:05:34 +02:00
}