diff --git a/zebra-network/src/peer/connection.rs b/zebra-network/src/peer/connection.rs index 39c14d9d3..3f4b0bf13 100644 --- a/zebra-network/src/peer/connection.rs +++ b/zebra-network/src/peer/connection.rs @@ -18,7 +18,7 @@ use zebra_chain::{ use crate::{ constants, protocol::{ - external::{types::Nonce, Message}, + external::{types::Nonce, InventoryHash, Message}, internal::{Request, Response}, }, BoxedStdError, @@ -35,6 +35,7 @@ pub(super) enum Handler { hashes: HashSet, blocks: Vec, }, + FindBlocks, } impl Handler { @@ -81,6 +82,15 @@ impl Handler { Finished(Err(Arc::new(PeerError::WrongBlock).into())) } } + (FindBlocks, Message::Inv(inv_hashes)) => Finished(Ok(Response::BlockHeaderHashes( + inv_hashes + .into_iter() + .filter_map(|inv| match inv { + InventoryHash::Block(hash) => Some(hash), + _ => None, + }) + .collect(), + ))), // By default, messages are not responses. (state, msg) => { ignored_msg = Some(msg); @@ -317,6 +327,15 @@ where tx, ) }), + (AwaitingRequest, FindBlocks { known_blocks, stop }) => self + .peer_tx + .send(Message::GetBlocks { + block_locator_hashes: known_blocks, + hash_stop: stop.unwrap_or(BlockHeaderHash([0; 32])), + }) + .await + .map_err(|e| e.into()) + .map(|()| AwaitingResponse(Handler::FindBlocks, tx)), } { Ok(new_state) => { self.state = new_state; @@ -421,6 +440,15 @@ where } } } + Response::BlockHeaderHashes(hashes) => { + if let Err(e) = self + .peer_tx + .send(Message::Inv(hashes.into_iter().map(Into::into).collect())) + .await + { + self.fail_with(e.into()) + } + } } } } diff --git a/zebra-network/src/peer/error.rs b/zebra-network/src/peer/error.rs index f5cb15f10..fad924da6 100644 --- a/zebra-network/src/peer/error.rs +++ b/zebra-network/src/peer/error.rs @@ -2,7 +2,7 @@ use std::sync::{Arc, Mutex}; use thiserror::Error; -use zebra_chain::{serialization::SerializationError}; +use zebra_chain::serialization::SerializationError; /// A wrapper around `Arc` that implements `Error`. #[derive(Error, Debug, Clone)] diff --git a/zebra-network/src/protocol/internal/request.rs b/zebra-network/src/protocol/internal/request.rs index 990fd592c..b6f495bb1 100644 --- a/zebra-network/src/protocol/internal/request.rs +++ b/zebra-network/src/protocol/internal/request.rs @@ -28,4 +28,13 @@ pub enum Request { /// didn't start with a `Vec` but with, e.g., an iterator, they can collect /// directly into a `HashSet` and save work. BlocksByHash(HashSet), + + /// Request block hashes of subsequent blocks in the chain, giving hashes of + /// known blocks. + FindBlocks { + /// Hashes of known blocks, ordered from highest height to lowest height. + known_blocks: Vec, + /// Optionally, the last header to request. + stop: Option, + }, } diff --git a/zebra-network/src/protocol/internal/response.rs b/zebra-network/src/protocol/internal/response.rs index 6a35cee1b..b7ca82aad 100644 --- a/zebra-network/src/protocol/internal/response.rs +++ b/zebra-network/src/protocol/internal/response.rs @@ -1,5 +1,5 @@ // XXX clean module layout of zebra_chain -use zebra_chain::block::Block; +use zebra_chain::block::{Block, BlockHeaderHash}; use crate::meta_addr::MetaAddr; @@ -14,4 +14,7 @@ pub enum Response { /// A list of blocks. Blocks(Vec), -} \ No newline at end of file + + /// A list of block hashes. + BlockHeaderHashes(Vec), +} diff --git a/zebrad/src/commands/connect.rs b/zebrad/src/commands/connect.rs index 6db13e965..731ebfd53 100644 --- a/zebrad/src/commands/connect.rs +++ b/zebrad/src/commands/connect.rs @@ -112,6 +112,15 @@ impl ConnectCmd { info!(?rsp); } + peer_set.ready().await.unwrap(); + let mut rsp = peer_set + .call(Request::FindBlocks { + known_blocks: Vec::new(), + stop: None, + }) + .await; + info!(?rsp); + let eternity = future::pending::<()>(); eternity.await;