mirror of
https://github.com/mimblewimble/grin.git
synced 2025-02-01 08:51:08 +03:00
Update ``grin client status
`` (#599)
* Add status type * Add /v1/status handler * Updated client for API::Status type * Remove unused dependency * Moved user agent up
This commit is contained in:
parent
ac5010e8f7
commit
cbc40c9824
4 changed files with 103 additions and 42 deletions
|
@ -19,7 +19,6 @@ grin_grin = { path = "./grin" }
|
|||
grin_config = { path = "./config" }
|
||||
grin_core = { path = "./core" }
|
||||
grin_pow = { path = "./pow"}
|
||||
grin_p2p = { path = "./p2p"}
|
||||
grin_util = { path = "./util"}
|
||||
blake2-rfc = "~0.2.17"
|
||||
clap = "^2.23.3"
|
||||
|
|
|
@ -317,6 +317,25 @@ impl Handler for PeerGetHandler {
|
|||
}
|
||||
}
|
||||
|
||||
// Status handler. Post a summary of the server status
|
||||
// GET /v1/status
|
||||
pub struct StatusHandler {
|
||||
pub chain: Arc<chain::Chain>,
|
||||
pub peers: p2p::Peers,
|
||||
}
|
||||
|
||||
impl StatusHandler {
|
||||
fn get_status(&self) -> Status {
|
||||
Status::from_tip_and_peers(self.chain.head().unwrap(), self.peers.peer_count())
|
||||
}
|
||||
}
|
||||
|
||||
impl Handler for StatusHandler {
|
||||
fn handle(&self, _req: &mut Request) -> IronResult<Response> {
|
||||
json_response(&self.get_status())
|
||||
}
|
||||
}
|
||||
|
||||
// Chain handler. Get the head details.
|
||||
// GET /v1/chain
|
||||
pub struct ChainHandler {
|
||||
|
@ -440,15 +459,12 @@ where
|
|||
tx.inputs.len(),
|
||||
tx.outputs.len()
|
||||
);
|
||||
|
||||
let res = self.tx_pool
|
||||
.write()
|
||||
.unwrap()
|
||||
.add_to_memory_pool(source, tx);
|
||||
|
||||
let res = self.tx_pool.write().unwrap().add_to_memory_pool(source, tx);
|
||||
|
||||
match res {
|
||||
Ok(()) => Ok(Response::with(status::Ok)),
|
||||
Err(e) => Err(IronError::from(Error::Argument(format!("{:?}", e))))
|
||||
Err(e) => Err(IronError::from(Error::Argument(format!("{:?}", e)))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -498,6 +514,10 @@ pub fn start_rest_apis<T>(
|
|||
let chain_tip_handler = ChainHandler {
|
||||
chain: chain.clone(),
|
||||
};
|
||||
let status_handler = StatusHandler {
|
||||
chain: chain.clone(),
|
||||
peers: peers.clone(),
|
||||
};
|
||||
let sumtree_handler = SumTreeHandler {
|
||||
chain: chain.clone(),
|
||||
};
|
||||
|
@ -524,6 +544,7 @@ pub fn start_rest_apis<T>(
|
|||
"get blocks".to_string(),
|
||||
"get chain".to_string(),
|
||||
"get chain/utxos".to_string(),
|
||||
"get status".to_string(),
|
||||
"get sumtrees/roots".to_string(),
|
||||
"get sumtrees/lastutxos?n=10".to_string(),
|
||||
"get sumtrees/lastrangeproofs".to_string(),
|
||||
|
@ -544,6 +565,7 @@ pub fn start_rest_apis<T>(
|
|||
blocks: get "/blocks/*" => block_handler,
|
||||
chain_tip: get "/chain" => chain_tip_handler,
|
||||
chain_utxos: get "/chain/utxos/*" => utxo_handler,
|
||||
status: get "/status" => status_handler,
|
||||
sumtree_roots: get "/sumtrees/*" => sumtree_handler,
|
||||
pool_info: get "/pool" => pool_info_handler,
|
||||
pool_push: post "/pool/push" => pool_push_handler,
|
||||
|
|
|
@ -16,6 +16,7 @@ use std::sync::Arc;
|
|||
use core::{core, global};
|
||||
use core::core::hash::Hashed;
|
||||
use chain;
|
||||
use p2p;
|
||||
use util::secp::pedersen;
|
||||
use rest::*;
|
||||
use util;
|
||||
|
@ -44,6 +45,30 @@ impl Tip {
|
|||
}
|
||||
}
|
||||
|
||||
/// Status page containing different server information
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct Status {
|
||||
// The protocol version
|
||||
pub protocol_version: u32,
|
||||
// The user user agent
|
||||
pub user_agent: String,
|
||||
// The current number of connections
|
||||
pub connections: u32,
|
||||
// The state of the current fork Tip
|
||||
pub tip: Tip,
|
||||
}
|
||||
|
||||
impl Status {
|
||||
pub fn from_tip_and_peers(current_tip: chain::Tip, connections: u32) -> Status {
|
||||
Status {
|
||||
protocol_version: p2p::msg::PROTOCOL_VERSION,
|
||||
user_agent: p2p::msg::USER_AGENT.to_string(),
|
||||
connections: connections,
|
||||
tip: Tip::from_tip(current_tip),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Sumtrees
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct SumTrees {
|
||||
|
@ -88,7 +113,7 @@ impl SumTreeNode {
|
|||
.get_block_header_by_output_commit(&elem_output.1.commit)
|
||||
.map_err(|_| Error::NotFound);
|
||||
// Need to call further method to check if output is spent
|
||||
let mut output = OutputPrintable::from_output(&elem_output.1, &header.unwrap(),true);
|
||||
let mut output = OutputPrintable::from_output(&elem_output.1, &header.unwrap(), true);
|
||||
if let Ok(_) = chain.get_unspent(&elem_output.1.commit) {
|
||||
output.spent = false;
|
||||
}
|
||||
|
@ -148,8 +173,12 @@ pub struct Output {
|
|||
}
|
||||
|
||||
impl Output {
|
||||
pub fn from_output(output: &core::Output, block_header: &core::BlockHeader,
|
||||
include_proof:bool, include_switch: bool) -> Output {
|
||||
pub fn from_output(
|
||||
output: &core::Output,
|
||||
block_header: &core::BlockHeader,
|
||||
include_proof: bool,
|
||||
include_switch: bool,
|
||||
) -> Output {
|
||||
let (output_type, lock_height) = match output.features {
|
||||
x if x.contains(core::transaction::COINBASE_OUTPUT) => (
|
||||
OutputType::Coinbase,
|
||||
|
@ -196,7 +225,11 @@ pub struct OutputPrintable {
|
|||
}
|
||||
|
||||
impl OutputPrintable {
|
||||
pub fn from_output(output: &core::Output, block_header: &core::BlockHeader, include_proof_hash:bool) -> OutputPrintable {
|
||||
pub fn from_output(
|
||||
output: &core::Output,
|
||||
block_header: &core::BlockHeader,
|
||||
include_proof_hash: bool,
|
||||
) -> OutputPrintable {
|
||||
let (output_type, lock_height) = match output.features {
|
||||
x if x.contains(core::transaction::COINBASE_OUTPUT) => (
|
||||
OutputType::Coinbase,
|
||||
|
@ -214,7 +247,7 @@ impl OutputPrintable {
|
|||
proof_hash: match include_proof_hash {
|
||||
true => Some(util::to_hex(output.proof.hash().to_vec())),
|
||||
false => None,
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -257,7 +290,7 @@ impl TxKernelPrintable {
|
|||
fee: k.fee,
|
||||
lock_height: k.lock_height,
|
||||
excess: util::to_hex(k.excess.0.to_vec()),
|
||||
excess_sig: util::to_hex(k.excess_sig.to_vec())
|
||||
excess_sig: util::to_hex(k.excess_sig.to_vec()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -322,7 +355,7 @@ impl BlockHeaderPrintable {
|
|||
kernel_root: util::to_hex(h.kernel_root.to_vec()),
|
||||
nonce: h.nonce,
|
||||
difficulty: h.difficulty.into_num(),
|
||||
total_difficulty: h.total_difficulty.into_num()
|
||||
total_difficulty: h.total_difficulty.into_num(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -342,15 +375,18 @@ pub struct BlockPrintable {
|
|||
|
||||
impl BlockPrintable {
|
||||
pub fn from_block(block: &core::Block) -> BlockPrintable {
|
||||
let inputs = block.inputs
|
||||
let inputs = block
|
||||
.inputs
|
||||
.iter()
|
||||
.map(|input| util::to_hex((input.0).0.to_vec()))
|
||||
.collect();
|
||||
let outputs = block.outputs
|
||||
let outputs = block
|
||||
.outputs
|
||||
.iter()
|
||||
.map(|output| OutputPrintable::from_output(output, &block.header, true))
|
||||
.collect();
|
||||
let kernels = block.kernels
|
||||
let kernels = block
|
||||
.kernels
|
||||
.iter()
|
||||
.map(|kernel| TxKernelPrintable::from_txkernel(kernel))
|
||||
.collect();
|
||||
|
|
|
@ -12,43 +12,47 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
extern crate grin_p2p as p2p;
|
||||
extern crate term;
|
||||
|
||||
use api;
|
||||
use grin::ServerConfig;
|
||||
|
||||
pub fn show_status(config: &ServerConfig) {
|
||||
println!();
|
||||
let title=format!("Grin Server Status ");
|
||||
let mut t = term::stdout().unwrap();
|
||||
let mut e = term::stdout().unwrap();
|
||||
t.fg(term::color::MAGENTA).unwrap();
|
||||
writeln!(t, "{}", title).unwrap();
|
||||
writeln!(t, "--------------------------").unwrap();
|
||||
t.reset().unwrap();
|
||||
writeln!(e, "Protocol version: {}", p2p::msg::PROTOCOL_VERSION).unwrap();
|
||||
writeln!(e, "User agent: {}", p2p::msg::USER_AGENT).unwrap();
|
||||
match get_tip_from_node(config) {
|
||||
Ok(tip) => {
|
||||
writeln!(e, "Chain height: {}", tip.height).unwrap();
|
||||
writeln!(e, "Total difficulty: {}", tip.total_difficulty).unwrap();
|
||||
writeln!(e, "Last block pushed: {}", tip.last_block_pushed).unwrap()
|
||||
}
|
||||
Err(_) => writeln!(e, "WARNING: Client failed to get data. Is your `grin server` offline or broken?").unwrap()
|
||||
};
|
||||
e.reset().unwrap();
|
||||
println!();
|
||||
println!();
|
||||
let title = format!("Grin Server Status ");
|
||||
let mut t = term::stdout().unwrap();
|
||||
let mut e = term::stdout().unwrap();
|
||||
t.fg(term::color::MAGENTA).unwrap();
|
||||
writeln!(t, "{}", title).unwrap();
|
||||
writeln!(t, "--------------------------").unwrap();
|
||||
t.reset().unwrap();
|
||||
match get_status_from_node(config) {
|
||||
Ok(status) => {
|
||||
writeln!(e, "Protocol version: {}", status.protocol_version).unwrap();
|
||||
writeln!(e, "User agent: {}", status.user_agent).unwrap();
|
||||
writeln!(e, "Connections: {}", status.connections).unwrap();
|
||||
writeln!(e, "Chain height: {}", status.tip.height).unwrap();
|
||||
writeln!(e, "Last block hash: {}", status.tip.last_block_pushed).unwrap();
|
||||
writeln!(e, "Previous block hash: {}", status.tip.prev_block_to_last).unwrap();
|
||||
writeln!(e, "Total difficulty: {}", status.tip.total_difficulty).unwrap()
|
||||
}
|
||||
Err(_) => writeln!(
|
||||
e,
|
||||
"WARNING: Client failed to get data. Is your `grin server` offline or broken?"
|
||||
).unwrap(),
|
||||
};
|
||||
e.reset().unwrap();
|
||||
println!();
|
||||
}
|
||||
|
||||
fn get_tip_from_node(config: &ServerConfig) -> Result<api::Tip, Error> {
|
||||
let url = format!("http://{}/v1/chain", config.api_http_addr);
|
||||
api::client::get::<api::Tip>(url.as_str()).map_err(|e| Error::API(e))
|
||||
fn get_status_from_node(config: &ServerConfig) -> Result<api::Status, Error> {
|
||||
let url = format!("http://{}/v1/status", config.api_http_addr);
|
||||
api::client::get::<api::Status>(url.as_str()).map_err(|e| Error::API(e))
|
||||
}
|
||||
|
||||
/// Error type wrapping underlying module errors.
|
||||
#[derive(Debug)]
|
||||
enum Error {
|
||||
/// Error originating from HTTP API calls.
|
||||
API(api::Error)
|
||||
API(api::Error),
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue