diff --git a/Cargo.lock b/Cargo.lock index 6033a5f9..5bab5893 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1291,6 +1291,7 @@ dependencies = [ "grin_api 1.1.1-beta.1 (git+https://github.com/cgilliard/mwc-node)", "grin_core 1.1.1-beta.1 (git+https://github.com/cgilliard/mwc-node)", "grin_keychain 1.1.1-beta.1 (git+https://github.com/cgilliard/mwc-node)", + "grin_p2p 1.1.1-beta.1 (git+https://github.com/cgilliard/mwc-node)", "grin_store 1.1.1-beta.1 (git+https://github.com/cgilliard/mwc-node)", "grin_util 1.1.1-beta.1 (git+https://github.com/cgilliard/mwc-node)", "hmac 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index ceff9b4b..df10579d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,3 +51,4 @@ grin_core = { git = "https://github.com/cgilliard/mwc-node" } grin_keychain = { git = "https://github.com/cgilliard/mwc-node" } grin_util = { git = "https://github.com/cgilliard/mwc-node" } grin_store = { git = "https://github.com/cgilliard/mwc-node" } +grin_p2p = { git = "https://github.com/cgilliard/mwc-node" } diff --git a/src/cli/parser.rs b/src/cli/parser.rs index d96c6464..99e66066 100644 --- a/src/cli/parser.rs +++ b/src/cli/parser.rs @@ -276,6 +276,10 @@ impl<'a, 'b> Parser { Arg::from_usage("-f, --file= 'the file to read from'") ) ) + .subcommand( + SubCommand::with_name("nodeinfo") + .about("prints information about the node") + ) .subcommand( SubCommand::with_name("set-recv") .about("sets which account is the recipient of an incoming transaction") diff --git a/src/main.rs b/src/main.rs index 12736e6f..69ea810d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -44,6 +44,7 @@ extern crate grin_core; extern crate grin_keychain; extern crate grin_store; extern crate grin_util; +extern crate grin_p2p; use std::borrow::Cow::{self, Borrowed, Owned}; use std::fs::File; @@ -1152,6 +1153,9 @@ fn do_command( wallet.lock().finalize_slate(&mut slate, None)?; cli_message!("{} finalized.", input); } + Some("nodeinfo") => { + wallet.lock().node_info()?; + } Some("send") => { let args = matches.subcommand_matches("send").unwrap(); let to = args.value_of("to"); @@ -1572,4 +1576,4 @@ pub fn enable_ansi_support() { #[cfg(not(windows))] pub fn enable_ansi_support() { -} \ No newline at end of file +} diff --git a/src/wallet/api/api.rs b/src/wallet/api/api.rs index b5ab1644..56f816d2 100644 --- a/src/wallet/api/api.rs +++ b/src/wallet/api/api.rs @@ -6,6 +6,7 @@ use grin_core::ser; use grin_util::secp::key::PublicKey; use grin_util::secp::pedersen; use grin_util::secp::{ContextFlag, Secp256k1}; +use grin_p2p::types::PeerInfoDisplay; use crate::contacts::GrinboxAddress; @@ -40,6 +41,14 @@ where phantom_c: PhantomData, } +// struct for sending back node information +pub struct NodeInfo +{ + pub height: u64, + pub total_difficulty: u64, + pub peers: Vec, +} + impl Wallet713OwnerAPI where W: WalletBackend, @@ -344,6 +353,53 @@ where w.get_stored_tx(uuid) } + pub fn node_info(&self) -> Result<(NodeInfo), Error> { + // first get height + let height = { + let mut w = self.wallet.lock(); + w.open_with_credentials()?; + w.w2n_client().get_chain_height() + }; + + // next total_difficulty + let total_difficulty = { + let mut w = self.wallet.lock(); + w.open_with_credentials()?; + w.w2n_client().get_total_difficulty() + }; + + // peer info + let peers = { + let mut w = self.wallet.lock(); + w.open_with_credentials()?; + w.w2n_client().get_connected_peer_info() + }; + + // handle any errors that occurred + match height { + Ok(height) => { + match total_difficulty { + Ok(total_difficulty) => { + match peers { + Ok(peers) => { + Ok(NodeInfo{height:height,total_difficulty:total_difficulty,peers:peers}) + }, + Err(_) => { + Ok(NodeInfo{height:0,total_difficulty:0,peers:Vec::new()}) + } + } + }, + Err(_) => { + Ok(NodeInfo{height:0,total_difficulty:0,peers:Vec::new()}) + } + } + }, + Err(_) => { + Ok(NodeInfo{height:0,total_difficulty:0,peers:Vec::new()}) + } + } + } + pub fn post_tx(&self, tx: &Transaction, fluff: bool) -> Result<(), Error> { let tx_hex = grin_util::to_hex(ser::ser_vec(tx).unwrap()); let client = { diff --git a/src/wallet/types/node_client.rs b/src/wallet/types/node_client.rs index e801a140..abad0f9a 100644 --- a/src/wallet/types/node_client.rs +++ b/src/wallet/types/node_client.rs @@ -16,6 +16,7 @@ use futures::Stream; use futures::stream; use grin_api::{Output, OutputType, OutputListing, Tip}; use grin_api::client; +use grin_p2p::types::PeerInfoDisplay; use grin_util::secp::pedersen::{Commitment, RangeProof}; use grin_util::to_hex; use std::collections::HashMap; @@ -45,6 +46,12 @@ pub trait NodeClient: Sync + Send + Clone { /// retrieves the current tip from the specified grin node fn get_chain_height(&self) -> Result; + /// retreives total difficulty + fn get_total_difficulty(&self) -> Result; + + /// retreives the connected peer info of the node + fn get_connected_peer_info(&self) -> Result, grin_api::Error>; + /// retrieve a list of outputs from the specified grin node /// need "by_height" and "by_id" variants fn get_outputs_from_node( @@ -121,6 +128,29 @@ impl NodeClient for HTTPNodeClient { Ok(()) } + /// Return Connected peers + fn get_connected_peer_info(&self) -> Result, grin_api::Error> { + let addr = self.node_url(); + let url = format!("{}/v1/peers/connected", addr); + let peers = client::get::>(url.as_str(), self.node_api_secret()); + peers + } + + /// Return total_difficulty of the chain + fn get_total_difficulty(&self) -> Result { + let addr = self.node_url(); + let url = format!("{}/v1/chain", addr); + let res = client::get::(url.as_str(), self.node_api_secret()); + match res { + Err(e) => { + let report = format!("Getting chain difficulty from node: {}", e); + error!("Get diffulty error: {}", e); + Err(ErrorKind::ClientCallback(report).into()) + } + Ok(r) => Ok(r.total_difficulty), + } + } + /// Return the chain tip from a given node fn get_chain_height(&self) -> Result { let addr = self.node_url(); @@ -233,4 +263,4 @@ impl NodeClient for HTTPNodeClient { } } } -} \ No newline at end of file +} diff --git a/src/wallet/wallet.rs b/src/wallet/wallet.rs index cf6524ec..14cb7243 100644 --- a/src/wallet/wallet.rs +++ b/src/wallet/wallet.rs @@ -50,6 +50,31 @@ impl Wallet { Ok(()) } + pub fn node_info( + &mut self) -> Result<()> { + // get wallet instance + let wallet = self.get_wallet_instance()?; + + // create a single use wallet api + controller::owner_single_use(wallet.clone(), |api| { + let ni = api.node_info().unwrap(); + // this is an error condition + if ni.height == 0 && ni.total_difficulty == 0 { + cli_message!("Error occured trying to contact node!"); + } + else + { + // otherwise it worked, print it out here. + cli_message!("Node Info:"); + cli_message!("Height: {}", ni.height); + cli_message!("Total_Difficulty: {}", ni.total_difficulty); + cli_message!("PeerInfo: {:?}", ni.peers); + } + Ok(()) + })?; + Ok(()) + } + pub fn account_exists( &mut self, account: &str) -> Result<(bool)> {