Skip to content

Commit

Permalink
Merge #3867 #3892
Browse files Browse the repository at this point in the history
3867: refactor: use clap as a commands parser r=sdbondi a=DenisKolodin

Description
---
The PR refactors replace our own parser with a derived by the `clap` crate.
It also adds the `watch` command, and avoids unexpected status printing. 

Motivation and Context
---
Improve the user experience of the node's shell.
Simplify maintenance and adding new commands.
Also periodically status prnting breaks the rustyline and prompt chars not printed properly.

How Has This Been Tested?
---
Manually


3892: chore: add license info missing from some crates r=sdbondi a=delta1

Description
---

Adds the BSD-3-Clause license field to our crates that were missing license info



Co-authored-by: Denis Kolodin <deniskolodin@gmail.com>
Co-authored-by: Byron Hambly <bizzle@tari.com>
  • Loading branch information
3 people authored Mar 7, 2022
3 parents c2bb6c4 + 6520393 + 0229c45 commit ec484ca
Show file tree
Hide file tree
Showing 53 changed files with 2,355 additions and 1,812 deletions.
41 changes: 38 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions applications/deps_only/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "deps_only"
version = "0.1.0"
edition = "2021"
license = "BSD-3-Clause"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

Expand Down
2 changes: 1 addition & 1 deletion applications/launchpad/backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "tari_launchpad"
version = "0.28.1"
description = "The Tari Launcher"
authors = ["The Tari Development Community"]
license = ""
license = "BSD-3-Clause"
repository = ""
edition = "2018"
build = "src/build.rs"
Expand Down
1 change: 1 addition & 0 deletions applications/tari_app_utilities/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name = "tari_app_utilities"
version = "0.28.1"
authors = ["The Tari Development Community"]
edition = "2018"
license = "BSD-3-Clause"

[dependencies]
tari_comms = { path = "../../comms" }
Expand Down
2 changes: 2 additions & 0 deletions applications/tari_app_utilities/src/utilities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ pub fn either_to_node_id(either: Either<CommsPublicKey, NodeId>) -> NodeId {
}
}

#[derive(Debug)]
pub struct UniPublicKey(PublicKey);

impl FromStr for UniPublicKey {
Expand All @@ -227,6 +228,7 @@ impl From<UniPublicKey> for PublicKey {
}
}

#[derive(Debug)]
pub enum UniNodeId {
PublicKey(PublicKey),
NodeId(NodeId),
Expand Down
5 changes: 4 additions & 1 deletion applications/tari_base_node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ tari_shutdown = { path = "../../infrastructure/shutdown" }
tari_utilities = "0.3.0"

anyhow = "1.0.53"
async-trait = "0.1.52"
bincode = "1.3.1"
chrono = { version = "0.4.19", default-features = false }
clap = { version = "3.1.1", features = ["derive"] }
config = { version = "0.9.3" }
crossterm = "0.22"
derive_more = "0.99.17"
Expand All @@ -34,10 +36,11 @@ futures = { version = "^0.3.16", default-features = false, features = ["alloc"]
log = { version = "0.4.8", features = ["std"] }
log-mdc = "0.1.0"
num_cpus = "1"
nom = "7.1.0"
regex = "1"
rustyline = "9.0"
rustyline-derive = "0.5"
strum = "0.22"
strum = { version = "0.22", features = ["derive"] }
strum_macros = "0.22"
thiserror = "^1.0.26"
tokio = { version = "1.11", features = ["signal"] }
Expand Down
96 changes: 0 additions & 96 deletions applications/tari_base_node/src/commands/args.rs
Original file line number Diff line number Diff line change
@@ -1,97 +1 @@
use std::{
iter::Peekable,
str::{FromStr, SplitWhitespace},
};

use tari_utilities::hex::{Hex, HexError};
use thiserror::Error;

#[derive(Debug, Error)]
#[error("{name} {reason}")]
pub struct ArgsError {
name: &'static str,
reason: ArgsReason,
}

impl ArgsError {
pub fn new(name: &'static str, reason: impl Into<ArgsReason>) -> Self {
Self {
name,
reason: reason.into(),
}
}
}

#[derive(Debug, Error)]
pub enum ArgsReason {
#[error("argument required")]
Required,
#[error("argument can't be parsed: {details}")]
NotParsed { details: String },
#[error("argument is not valid: {description}")]
Inconsistent { description: String },
}

impl<T: AsRef<str>> From<T> for ArgsReason {
fn from(value: T) -> Self {
Self::Inconsistent {
description: value.as_ref().to_owned(),
}
}
}

pub struct Args<'a> {
splitted: Peekable<SplitWhitespace<'a>>,
}

impl<'a> Args<'a> {
pub fn split(s: &'a str) -> Self {
Self {
splitted: s.split_whitespace().peekable(),
}
}

// TODO: Remove
pub fn shift_one(&mut self) {
self.splitted.next();
}

// TODO: Use `next` always
pub fn try_take_next<T>(&mut self, name: &'static str) -> Result<Option<T>, ArgsError>
where
T: FromStr,
T::Err: ToString,
{
match self.splitted.peek().map(|s| s.parse()) {
Some(Ok(value)) => Ok(Some(value)),
Some(Err(err)) => Err(ArgsError::new(name, ArgsReason::NotParsed {
details: err.to_string(),
})),
None => Ok(None),
}
}

pub fn take_next<T>(&mut self, name: &'static str) -> Result<T, ArgsError>
where
T: FromStr,
T::Err: ToString,
{
match self.try_take_next(name)? {
Some(value) => {
self.shift_one();
Ok(value)
},
None => Err(ArgsError::new(name, ArgsReason::Required)),
}
}
}

pub struct FromHex<T>(pub T);

impl<T: Hex> FromStr for FromHex<T> {
type Err = HexError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
T::from_hex(s).map(Self)
}
}
83 changes: 83 additions & 0 deletions applications/tari_base_node/src/commands/command/ban_peer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use std::time::Duration;

use anyhow::Error;
use async_trait::async_trait;
use clap::Parser;
use tari_app_utilities::utilities::UniNodeId;
use tari_comms::peer_manager::NodeId;

use super::{CommandContext, HandleCommand};
use crate::LOG_TARGET;

/// Bans a peer
#[derive(Debug, Parser)]
pub struct ArgsBan {
/// hex public key or emoji id
node_id: UniNodeId,
/// length of time to ban the peer for in seconds
#[clap(default_value_t = std::u64::MAX)]
length: u64,
}

/// Removes a peer ban
#[derive(Debug, Parser)]
pub struct ArgsUnban {
/// hex public key or emoji id
node_id: UniNodeId,
/// length of time to ban the peer for in seconds
#[clap(default_value_t = std::u64::MAX)]
length: u64,
}

#[async_trait]
impl HandleCommand<ArgsBan> for CommandContext {
async fn handle_command(&mut self, args: ArgsBan) -> Result<(), Error> {
let node_id = args.node_id.into();
let duration = Duration::from_secs(args.length);
self.ban_peer(node_id, duration, true).await
}
}

#[async_trait]
impl HandleCommand<ArgsUnban> for CommandContext {
async fn handle_command(&mut self, args: ArgsUnban) -> Result<(), Error> {
let node_id = args.node_id.into();
let duration = Duration::from_secs(args.length);
self.ban_peer(node_id, duration, false).await
}
}

impl CommandContext {
pub async fn ban_peer(&mut self, node_id: NodeId, duration: Duration, must_ban: bool) -> Result<(), Error> {
if self.base_node_identity.node_id() == &node_id {
println!("Cannot ban our own node");
} else if must_ban {
// TODO: Use errors
match self
.connectivity
.ban_peer_until(node_id.clone(), duration, "UI manual ban".to_string())
.await
{
Ok(_) => println!("Peer was banned in base node."),
Err(err) => {
println!("Failed to ban peer: {:?}", err);
log::error!(target: LOG_TARGET, "Could not ban peer: {:?}", err);
},
}
} else {
match self.peer_manager.unban_peer(&node_id).await {
Ok(_) => {
println!("Peer ban was removed from base node.");
},
Err(err) if err.is_peer_not_found() => {
println!("Peer not found in base node");
},
Err(err) => {
println!("Failed to ban peer: {:?}", err);
log::error!(target: LOG_TARGET, "Could not ban peer: {:?}", err);
},
}
}
Ok(())
}
}
48 changes: 48 additions & 0 deletions applications/tari_base_node/src/commands/command/block_timing.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use anyhow::Error;
use async_trait::async_trait;
use clap::Parser;
use tari_core::blocks::BlockHeader;

use super::{CommandContext, HandleCommand};

/// Calculates the maximum, minimum, and average time taken to mine a given range of blocks
#[derive(Debug, Parser)]
pub struct Args {
/// number of blocks from chain tip or start height
start: u64,
/// end height
end: Option<u64>,
}

#[async_trait]
impl HandleCommand<Args> for CommandContext {
async fn handle_command(&mut self, args: Args) -> Result<(), Error> {
// TODO: is that possible to validate it with clap?
if args.end.is_none() && args.start < 2 {
Err(Error::msg("Number of headers must be at least 2."))
} else {
self.block_timing(args.start, args.end).await
}
}
}

impl CommandContext {
pub async fn block_timing(&self, start: u64, end: Option<u64>) -> Result<(), Error> {
let headers = self.get_chain_headers(start, end).await?;
if !headers.is_empty() {
let headers = headers.into_iter().map(|ch| ch.into_header()).rev().collect::<Vec<_>>();
let (max, min, avg) = BlockHeader::timing_stats(&headers);
println!(
"Timing for blocks #{} - #{}",
headers.first().unwrap().height,
headers.last().unwrap().height
);
println!("Max block time: {}", max);
println!("Min block time: {}", min);
println!("Avg block time: {}", avg);
} else {
println!("No headers found");
}
Ok(())
}
}
Loading

0 comments on commit ec484ca

Please sign in to comment.