-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add tribes and graceful shutdown (#28)
Description --- We needed tribes to let people mine together in a smaller group called tribe. P2pool must allow this functionality. Also we should have the chance to list all current tribes, cli of p2pool should support this. As a plus p2pool should support graceful shutdown. Motivation and Context --- How Has This Been Tested? --- **Testing tribes** 1. Start p2pool node on tribe `a`: `export TARI_NETWORK="esmeralda" && ./target/release/sha_p2pool start -g 18145 --tribe a` 2. Start mining on this p2pool node 3. Start another p2pool node on tribe `b`: `export TARI_NETWORK="esmeralda" && ./target/release/sha_p2pool start -g 18146 --tribe b` 4. Start mining on this other p2pool node 5. It should be visible from the logs that the 2 pools have a different share chain **Testing list tribes** Simply run `sha_p2pool list-tribes` Example output: ```json ["default","a"] ``` What process can a PR reviewer use to test or verify this change? --- See tests Breaking Changes --- - [ ] None - [ ] Requires data directory on base node to be deleted - [ ] Requires hard fork - [x] Other - Peer info contains tribe now BREAKING CHANGE: Seed peers needs to be updated to the latest version as Peer info contains tribe now
- Loading branch information
Showing
19 changed files
with
712 additions
and
291 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
// Copyright 2024 The Tari Project | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
|
||
use std::path::PathBuf; | ||
use std::sync::Arc; | ||
|
||
use clap::{Parser, Subcommand}; | ||
use tari_shutdown::ShutdownSignal; | ||
|
||
use crate::cli::commands; | ||
use crate::cli::util::cli_styles; | ||
use crate::cli::util::validate_tribe; | ||
|
||
#[allow(clippy::struct_excessive_bools)] | ||
#[derive(Clone, Parser, Debug)] | ||
pub struct StartArgs { | ||
/// (Optional) gRPC port to use. | ||
#[arg(short, long, value_name = "grpc-port")] | ||
pub grpc_port: Option<u16>, | ||
|
||
/// (Optional) p2p port to use. It is used to connect p2pool nodes. | ||
#[arg(short, long, value_name = "p2p-port")] | ||
pub p2p_port: Option<u16>, | ||
|
||
/// (Optional) stats server port to use. | ||
#[arg(long, value_name = "stats-server-port")] | ||
pub stats_server_port: Option<u16>, | ||
|
||
/// (Optional) seed peers. | ||
/// Any amount of seed peers can be added to join a p2pool network. | ||
/// | ||
/// Please note that these addresses must be in libp2p multi address format and must contain peer ID | ||
/// or use a dnsaddr multi address! | ||
/// | ||
/// By default a Tari provided seed peer is added. | ||
/// | ||
/// e.g.: | ||
/// /ip4/127.0.0.1/tcp/52313/p2p/12D3KooWCUNCvi7PBPymgsHx39JWErYdSoT3EFPrn3xoVff4CHFu | ||
/// /dnsaddr/esmeralda.p2pool.tari.com | ||
#[arg(short, long, value_name = "seed-peers")] | ||
pub seed_peers: Option<Vec<String>>, | ||
|
||
/// If set, Tari provided seed peers will NOT be automatically added to seed peers list. | ||
#[arg(long, value_name = "no-default-seed-peers", default_value_t = false)] | ||
pub no_default_seed_peers: bool, | ||
|
||
/// Starts the node as a stable peer. | ||
/// | ||
/// Identity of the peer will be saved locally (to --private-key-location) | ||
/// and ID of the Peer remains the same. | ||
#[arg(long, value_name = "stable-peer", default_value_t = false)] | ||
pub stable_peer: bool, | ||
|
||
/// Tribe to enter (a team of miners). | ||
/// A tribe can have any name. | ||
#[arg( | ||
long, value_name = "tribe", default_value = "default", value_parser = validate_tribe | ||
)] | ||
pub tribe: String, | ||
|
||
/// Private key folder. | ||
/// | ||
/// Needs --stable-peer to be set. | ||
#[arg( | ||
long, | ||
value_name = "private-key-folder", | ||
requires = "stable_peer", | ||
default_value = "." | ||
)] | ||
pub private_key_folder: PathBuf, | ||
|
||
/// Mining disabled | ||
/// | ||
/// In case it is set, the node will only handle p2p operations, | ||
/// will be syncing with share chain, but not starting gRPC services and no Tari base node needed. | ||
/// By setting this it can be used as a stable node for routing only. | ||
#[arg(long, value_name = "mining-disabled", default_value_t = false)] | ||
pub mining_disabled: bool, | ||
|
||
/// mDNS disabled | ||
/// | ||
/// If set, mDNS local peer discovery is disabled. | ||
#[arg(long, value_name = "mdns-disabled", default_value_t = false)] | ||
pub mdns_disabled: bool, | ||
|
||
/// Stats server disabled | ||
/// | ||
/// If set, local stats HTTP server is disabled. | ||
#[arg(long, value_name = "stats-server-disabled", default_value_t = false)] | ||
pub stats_server_disabled: bool, | ||
} | ||
|
||
#[derive(Subcommand, Clone, Debug)] | ||
pub enum Commands { | ||
/// Starts sha-p2pool node. | ||
Start { | ||
#[clap(flatten)] | ||
args: StartArgs, | ||
}, | ||
|
||
/// Generating new identity. | ||
GenerateIdentity, | ||
|
||
/// Listing all tribes that are present on the network. | ||
ListTribes { | ||
#[clap(flatten)] | ||
args: StartArgs, | ||
}, | ||
} | ||
|
||
#[derive(Clone, Parser)] | ||
#[command(version)] | ||
#[command(styles = cli_styles())] | ||
#[command(about = "⛏ Decentralized mining pool for Tari network ⛏", long_about = None)] | ||
pub struct Cli { | ||
#[command(subcommand)] | ||
pub command: Commands, | ||
|
||
/// (Optional) base dir. | ||
#[arg(short, long, value_name = "base-dir")] | ||
base_dir: Option<PathBuf>, | ||
} | ||
|
||
impl Cli { | ||
pub fn base_dir(&self) -> PathBuf { | ||
self.base_dir | ||
.clone() | ||
.unwrap_or_else(|| dirs::home_dir().unwrap().join(".tari/p2pool")) | ||
} | ||
|
||
/// Handles CLI command. | ||
/// [`Cli::parse`] must be called (to have all the args and params set properly) | ||
/// before calling this method. | ||
pub async fn handle_command(&self, cli_shutdown: ShutdownSignal) -> anyhow::Result<()> { | ||
let cli_ref = Arc::new(self.clone()); | ||
|
||
match &self.command { | ||
Commands::Start { args } => { | ||
commands::handle_start(cli_ref.clone(), args, cli_shutdown.clone()).await?; | ||
}, | ||
Commands::GenerateIdentity => { | ||
commands::handle_generate_identity().await?; | ||
}, | ||
Commands::ListTribes { args } => { | ||
commands::handle_list_tribes(cli_ref.clone(), args, cli_shutdown.clone()).await?; | ||
}, | ||
} | ||
|
||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// Copyright 2024 The Tari Project | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
|
||
use crate::server::p2p; | ||
|
||
pub async fn handle_generate_identity() -> anyhow::Result<()> { | ||
let result = p2p::util::generate_identity().await?; | ||
print!("{}", serde_json::to_value(result)?); | ||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// Copyright 2024 The Tari Project | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
|
||
use std::sync::Arc; | ||
use std::time::Duration; | ||
|
||
use anyhow::anyhow; | ||
use itertools::Itertools; | ||
use tari_shutdown::{Shutdown, ShutdownSignal}; | ||
use tokio::sync::oneshot; | ||
use tokio::task::JoinHandle; | ||
use tokio::{select, time}; | ||
|
||
use crate::cli::args::{Cli, StartArgs}; | ||
use crate::cli::commands::util; | ||
use crate::server::p2p::peer_store::PeerStore; | ||
|
||
pub async fn handle_list_tribes( | ||
cli: Arc<Cli>, | ||
args: &StartArgs, | ||
cli_shutdown_signal: ShutdownSignal, | ||
) -> anyhow::Result<()> { | ||
// start server asynchronously | ||
let cli_ref = cli.clone(); | ||
let mut args_clone = args.clone(); | ||
args_clone.mining_disabled = true; | ||
args_clone.stats_server_disabled = true; | ||
let mut shutdown = Shutdown::new(); | ||
let shutdown_signal = shutdown.to_signal(); | ||
let (peer_store_channel_tx, peer_store_channel_rx) = oneshot::channel::<Arc<PeerStore>>(); | ||
let handle: JoinHandle<anyhow::Result<()>> = tokio::spawn(async move { | ||
let mut server = util::server(cli_ref, &args_clone, shutdown_signal, false).await?; | ||
match peer_store_channel_tx.send(server.p2p_service().network_peer_store().clone()) { | ||
Ok(_) => server.start().await?, | ||
Err(_) => return Err(anyhow!("Failed to start server")), | ||
} | ||
|
||
Ok(()) | ||
}); | ||
|
||
// wait for peer store from started server | ||
let peer_store = peer_store_channel_rx.await?; | ||
|
||
// collect tribes for 30 seconds | ||
let mut tribes = vec![]; | ||
let timeout = time::sleep(Duration::from_secs(30)); | ||
tokio::pin!(timeout); | ||
tokio::pin!(cli_shutdown_signal); | ||
loop { | ||
select! { | ||
_ = &mut cli_shutdown_signal => { | ||
break; | ||
} | ||
() = &mut timeout => { | ||
break; | ||
} | ||
current_tribes = peer_store.tribes() => { | ||
tribes = current_tribes; | ||
if tribes.len() > 1 { | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
shutdown.trigger(); | ||
handle.await??; | ||
|
||
let tribes = tribes.iter().map(|tribe| tribe.to_string()).collect_vec(); | ||
print!("{}", serde_json::to_value(tribes)?); | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// Copyright 2024 The Tari Project | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
|
||
pub use generate_identity::*; | ||
pub use list_tribes::*; | ||
pub use start::*; | ||
|
||
mod generate_identity; | ||
mod list_tribes; | ||
mod start; | ||
mod util; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// Copyright 2024 The Tari Project | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
|
||
use std::sync::Arc; | ||
|
||
use tari_shutdown::ShutdownSignal; | ||
|
||
use crate::cli::args::{Cli, StartArgs}; | ||
use crate::cli::commands::util; | ||
|
||
pub async fn handle_start(cli: Arc<Cli>, args: &StartArgs, cli_shutdown_signal: ShutdownSignal) -> anyhow::Result<()> { | ||
util::server(cli, args, cli_shutdown_signal, true) | ||
.await? | ||
.start() | ||
.await?; | ||
Ok(()) | ||
} |
Oops, something went wrong.