From 15ca12a2f5047327fac0ed3c2bea825c0de52f78 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Wed, 11 Sep 2019 22:30:32 -0700 Subject: [PATCH] Add a `connect` command for testing. With `./src/zcashd -debug=net -logips=1`: ``` 2019-09-19 15:24:38 Added connection to 127.0.0.1:35932 peer=1 2019-09-19 15:24:38 connection from 127.0.0.1:35932 accepted 2019-09-19 15:24:38 socket closed 2019-09-19 15:24:38 disconnecting peer=1 ``` With `RUST_LOG="trace"`, `cargo run connect`: ``` Sep 19 08:24:24.530 INFO zebrad::commands::connect: version=Version { version: Version(170007), services: Services(1), timestamp: 2019-09-19T15:24:24.530059300Z, address_recv: (Services(1), V4(127.0.0.1:8233)), address_from: (Services(1), V4(127.0.0.1:9000)), nonce: Nonce(1), user_agent: "Zebra Connect", start_height: BlockHeight(0), relay: false } Sep 19 08:24:24.530 TRACE Task::run: tokio_executor::threadpool::task: state=Running Sep 19 08:24:24.530 DEBUG Task::run: tokio_net::driver::reactor: adding I/O source token=0 Sep 19 08:24:24.530 INFO zebrad::commands::connect: version_bytes="24e9276476657273696f6e000000000063000000cb30ab03179802000100000000000000a89d835d00000000010000000000000000000000000000000000ffff7f0000012029010000000000000000000000000000000000ffff7f000001232801000000000000000d5a6562726120436f6e6e6563740000000000" Sep 19 08:24:24.530 TRACE Task::run: log: registering with poller ``` --- zebra-network/src/lib.rs | 7 ++- zebrad/Cargo.toml | 4 ++ zebrad/src/commands.rs | 7 ++- zebrad/src/commands/connect.rs | 108 +++++++++++++++++++++++++++++++++ 4 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 zebrad/src/commands/connect.rs diff --git a/zebra-network/src/lib.rs b/zebra-network/src/lib.rs index d242fd1bf..2ef2c802a 100644 --- a/zebra-network/src/lib.rs +++ b/zebra-network/src/lib.rs @@ -5,7 +5,10 @@ #[macro_use] extern crate failure; -mod constants; pub mod message; -mod meta_addr; pub mod types; + +// XXX make this private once connect is removed +pub mod meta_addr; +// XXX make this private once connect is removed +pub mod constants; diff --git a/zebrad/Cargo.toml b/zebrad/Cargo.toml index b204b20a0..26b596f12 100644 --- a/zebrad/Cargo.toml +++ b/zebrad/Cargo.toml @@ -5,6 +5,7 @@ version = "0.1.0" edition = "2018" [dependencies] +chrono = "0.4" abscissa_core = "0.3.0" failure = "0.1" gumdrop = "0.6" @@ -21,6 +22,9 @@ hyper = { git = "https://github.com/hyperium/hyper" } futures-core-preview = { version = "=0.3.0-alpha.18" } futures-util-preview = { version = "=0.3.0-alpha.18" } +zebra-chain = { path = "../zebra-chain" } +zebra-network = { path = "../zebra-network" } + [dev-dependencies.abscissa_core] version = "0.3.0" features = ["testing"] diff --git a/zebrad/src/commands.rs b/zebrad/src/commands.rs index d3413ea98..c599496ed 100644 --- a/zebrad/src/commands.rs +++ b/zebrad/src/commands.rs @@ -10,10 +10,11 @@ //! See the `impl Configurable` below for how to specify the path to the //! application's configuration file. +mod connect; mod start; mod version; -use self::{start::StartCmd, version::VersionCmd}; +use self::{connect::ConnectCmd, start::StartCmd, version::VersionCmd}; use crate::config::ZebradConfig; use abscissa_core::{ config::Override, Command, Configurable, FrameworkError, Help, Options, Runnable, @@ -37,6 +38,10 @@ pub enum ZebradCmd { /// The `version` subcommand #[options(help = "display version information")] Version(VersionCmd), + + /// The `connect` subcommand + #[options(help = "testing stub for dumping network messages")] + Connect(ConnectCmd), } /// This trait allows you to define how application configuration is loaded. diff --git a/zebrad/src/commands/connect.rs b/zebrad/src/commands/connect.rs new file mode 100644 index 000000000..255c999a3 --- /dev/null +++ b/zebrad/src/commands/connect.rs @@ -0,0 +1,108 @@ +//! `connect` subcommand - test stub for talking to zcashd + +use crate::prelude::*; + +use abscissa_core::{Command, Options, Runnable}; + +/// `connect` subcommand +#[derive(Command, Debug, Options)] +pub struct ConnectCmd { + /// The address of the node to connect to. + #[options( + help = "The address of the node to connect to.", + default = "127.0.0.1:8233" + )] + addr: std::net::SocketAddr, +} + +impl Runnable for ConnectCmd { + /// Start the application. + fn run(&self) { + info!(connect.addr = ?self.addr); + + use crate::components::tokio::TokioComponent; + + let wait = tokio::future::pending::<()>(); + // Combine the connect future with an infinite wait + // so that the program has to be explicitly killed and + // won't die before all tracing messages are written. + let fut = futures_util::future::join(self.connect(), wait); + + let _ = app_reader() + .state() + .components + .get_downcast_ref::() + .expect("TokioComponent should be available") + .rt + .block_on(fut); + } +} + +impl ConnectCmd { + async fn connect(&self) -> Result<(), failure::Error> { + use std::net::Shutdown; + + use chrono::Utc; + use tokio::net::TcpStream; + + use zebra_chain::types::BlockHeight; + use zebra_network::{constants, message::*, types::*}; + + info!("connecting"); + + let mut stream = TcpStream::connect(self.addr).await?; + + let version = Message::Version { + version: constants::CURRENT_VERSION, + services: Services(1), + timestamp: Utc::now(), + address_recv: (Services(1), self.addr), + // We just make something up because at this stage the `connect` command + // doesn't run a server or anything -- will the zcashd respond on the + // same tcp connection or try to open one to the bogus address below? + address_from: (Services(1), "127.0.0.1:9000".parse().unwrap()), + nonce: Nonce(1), + user_agent: "Zebra Connect".to_owned(), + start_height: BlockHeight(0), + relay: false, + }; + + info!(version = ?version); + + version + .send( + &mut stream, + constants::magics::MAINNET, + constants::CURRENT_VERSION, + ) + .await?; + + let resp_version = Message::recv( + &mut stream, + constants::magics::MAINNET, + constants::CURRENT_VERSION, + ) + .await?; + info!(resp_version = ?resp_version); + + Message::Verack + .send( + &mut stream, + constants::magics::MAINNET, + constants::CURRENT_VERSION, + ) + .await?; + + let resp_verack = Message::recv( + &mut stream, + constants::magics::MAINNET, + constants::CURRENT_VERSION, + ) + .await?; + info!(resp_verack = ?resp_verack); + + stream.shutdown(Shutdown::Both)?; + + Ok(()) + } +}