Skip to content

Commit

Permalink
feat(watcher): start validator node process (#1116)
Browse files Browse the repository at this point in the history
Description
---
Spawns the the `tari_validator_node` through a tokio `Command` but has
not been tested fully with actual config. (It doesn't persist the child
or even outlives its scope.)

Breaking Changes
---

- [x] None
- [ ] Requires data directory to be deleted
- [ ] Other - Please specify
  • Loading branch information
therealdannzor authored Aug 12, 2024
1 parent 7b914ce commit 067bf14
Show file tree
Hide file tree
Showing 8 changed files with 231 additions and 28 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion applications/tari_watcher/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
#tari_common = { workspace = true }

clap = { workspace = true, features = ["derive"] }
serde = { workspace = true, features = ["derive"] }
anyhow = { workspace = true }
tokio = { workspace = true, features = ["rt-multi-thread", "macros", "signal", "process", "time", "fs", "io-util"] }
log = { workspace = true }
fern = { workspace = true, features = ["colored"] }

toml = "0.8.12"
humantime = "2.1.0"
31 changes: 29 additions & 2 deletions applications/tari_watcher/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::path::PathBuf;

use clap::Parser;

use crate::config::Config;
use crate::config::{Config, InstanceType};

#[derive(Clone, Debug, Parser)]
pub struct Cli {
Expand Down Expand Up @@ -43,7 +43,7 @@ pub struct CommonCli {
#[derive(Clone, Debug, clap::Subcommand)]
pub enum Commands {
Init(InitArgs),
Start,
Start(Overrides),
}

#[derive(Clone, Debug, clap::Args)]
Expand All @@ -58,3 +58,30 @@ impl InitArgs {
config.auto_register = !self.no_auto_register;
}
}

#[derive(Clone, Debug, clap::Args)]
pub struct Overrides {
#[clap(long)]
// The path to the validator node binary (optional)
pub vn_node_path: Option<PathBuf>,
}

impl Overrides {
pub fn apply(&self, config: &mut Config) {
if self.vn_node_path.is_none() {
return;
}

if let Some(exec_config) = config
.executable_config
.iter_mut()
.find(|c| c.instance_type == InstanceType::TariValidatorNode)
{
exec_config.executable_path = self.vn_node_path.clone();
}
log::info!(
"Overriding validator node binary path to {:?}",
self.vn_node_path.as_ref().unwrap()
);
}
}
26 changes: 6 additions & 20 deletions applications/tari_watcher/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ pub struct Config {
/// The Minotari console wallet gRPC address
pub base_wallet_grpc_address: String,

/// The base directory of the watcher with configuration and data files
pub base_dir: PathBuf,

/// The path of the validator node registration file, containing signed information required to
/// submit a registration transaction on behalf of the node
pub vn_registration_file: PathBuf,
Expand Down Expand Up @@ -71,17 +74,9 @@ pub struct ChannelConfig {
pub struct ExecutableConfig {
pub instance_type: InstanceType,
pub executable_path: Option<PathBuf>,
pub compile: Option<CompileConfig>,
pub env: Vec<(String, String)>,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct CompileConfig {
pub working_dir: Option<PathBuf>,
pub package_name: String,
pub target_dir: Option<PathBuf>,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct InstanceConfig {
pub name: String,
Expand Down Expand Up @@ -116,22 +111,12 @@ pub fn get_base_config(cli: &Cli) -> anyhow::Result<Config> {
let executables = vec![
ExecutableConfig {
instance_type: InstanceType::TariValidatorNode,
executable_path: Some("target/release/minotari_node".into()),
compile: Some(CompileConfig {
working_dir: Some("../tari".into()),
package_name: "minotari_node".to_string(),
target_dir: None,
}),
executable_path: Some("target/release/tari_validator_node".into()),
env: vec![],
},
ExecutableConfig {
instance_type: InstanceType::MinoTariConsoleWallet,
executable_path: Some("target/release/minotari_wallet".into()),
compile: Some(CompileConfig {
working_dir: Some("../tari".into()),
package_name: "minotari_wallet".to_string(),
target_dir: None,
}),
env: vec![],
},
];
Expand Down Expand Up @@ -161,7 +146,8 @@ pub fn get_base_config(cli: &Cli) -> anyhow::Result<Config> {
base_node_grpc_address: "localhost:18142".to_string(),
base_wallet_grpc_address: "localhost:18143".to_string(),
sidechain_id: None,
vn_registration_file: base_dir.join("vn_registration.toml"),
base_dir: base_dir.clone(),
vn_registration_file: base_dir.join("registration.json"),
instance_config: instances.to_vec(),
executable_config: executables,
channel_config: vec![
Expand Down
85 changes: 85 additions & 0 deletions applications/tari_watcher/src/forker.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright 2024 The Tari Project
// SPDX-License-Identifier: BSD-3-Clause

use std::{
env,
net::IpAddr,
path::{Path, PathBuf},
process::Stdio,
};

use tokio::process::{Child, Command};

use crate::{
config::{ExecutableConfig, InstanceType},
port::PortAllocator,
};

#[allow(dead_code)]
pub struct Forker {
// Used for the validator to connect to the base (L1) node
base_node_grpc_address: String,
// The base directory of calling the application
base_dir: PathBuf,
// The Tari L2 validator instance
validator: Option<Instance>,
// The Minotari L1 wallet instance
wallet: Option<Instance>,
}

impl Forker {
pub fn new(base_node_grpc_address: String, base_dir: PathBuf) -> Self {
Self {
validator: None,
wallet: None,
base_node_grpc_address,
base_dir,
}
}

pub async fn start_validator(&mut self, config: ExecutableConfig) -> anyhow::Result<Child> {
let instance = Instance::new(InstanceType::TariValidatorNode, config.clone());
self.validator = Some(instance.clone());

let mut cmd = Command::new(
config
.executable_path
.unwrap_or_else(|| Path::new("tari_validator_node").to_path_buf()),
);

// TODO: stdout logs
// let process_dir = self.base_dir.join("processes").join("TariValidatorNode");
// let stdout_log_path = process_dir.join("stdout.log");
// let stderr_log_path = process_dir.join("stderr.log");
cmd.envs(env::vars())
//.arg(format!("--config={validator_node_config_path}"))
.kill_on_drop(true)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.stdin(Stdio::null());

let child = cmd.spawn()?;

Ok(child)
}
}

#[allow(dead_code)]
#[derive(Clone)]
struct Instance {
app: InstanceType,
config: ExecutableConfig,
listen_ip: Option<IpAddr>,
port: PortAllocator,
}

impl Instance {
pub fn new(app: InstanceType, config: ExecutableConfig) -> Self {
Self {
app,
config,
listen_ip: None,
port: PortAllocator::new(),
}
}
}
51 changes: 46 additions & 5 deletions applications/tari_watcher/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
// Copyright 2024 The Tari Project
// SPDX-License-Identifier: BSD-3-Clause

use std::time::SystemTime;

use anyhow::{anyhow, Context};
use tokio::fs;

use crate::{
cli::{Cli, Commands},
config::get_base_config,
config::{get_base_config, Config},
manager::ProcessManager,
};

mod cli;
mod config;
mod forker;
mod manager;
mod port;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
let cli = Cli::init();
let config_path = cli.get_config_path();

setup_logger()?;

match cli.command {
Commands::Init(ref args) => {
// set by default in CommonCli
Expand All @@ -36,14 +44,47 @@ async fn main() -> anyhow::Result<()> {
.canonicalize()
.context("Failed to canonicalize config path")?;

// TODO: use standardised logging
// if let Err(e) = initialize_logging(..)
log::info!("Config file created at {}", config_path.display());
},
Commands::Start => {
unimplemented!("Start command not implemented");
Commands::Start(ref args) => {
let mut config = get_base_config(&cli)?;
// optionally override config values
args.apply(&mut config);
start(config).await?;
},
}

Ok(())
}

async fn start(config: Config) -> anyhow::Result<()> {
let mut manager = ProcessManager::new(config.clone());
manager.forker.start_validator(manager.validator_config).await?;

Ok(())
}

fn setup_logger() -> Result<(), fern::InitError> {
let colors = fern::colors::ColoredLevelConfig::new()
.info(fern::colors::Color::Green)
.debug(fern::colors::Color::Cyan)
.warn(fern::colors::Color::Yellow)
.error(fern::colors::Color::Red);

fern::Dispatch::new()
.format(move |out, message, record| {
out.finish(format_args!(
"[{} {} {}] {}",
humantime::format_rfc3339_seconds(SystemTime::now()),
colors.color(record.level()),
record.target(),
message
))
})
.level(log::LevelFilter::Debug)
.chain(std::io::stdout())
.chain(fern::log_file("output.log")?)
.apply()?;

Ok(())
}
23 changes: 23 additions & 0 deletions applications/tari_watcher/src/manager.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright 2024 The Tari Project
// SPDX-License-Identifier: BSD-3-Clause

use crate::{
config::{Config, ExecutableConfig},
forker::Forker,
};

pub struct ProcessManager {
pub validator_config: ExecutableConfig,
pub wallet_config: ExecutableConfig,
pub forker: Forker,
}

impl ProcessManager {
pub fn new(config: Config) -> Self {
Self {
validator_config: config.executable_config[0].clone(),
wallet_config: config.executable_config[1].clone(),
forker: Forker::new(config.base_node_grpc_address, config.base_dir),
}
}
}
38 changes: 38 additions & 0 deletions applications/tari_watcher/src/port.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright 2024 The Tari Project
// SPDX-License-Identifier: BSD-3-Clause

#[derive(Clone)]
pub struct PortAllocator {
pub wallet: MinotariPorts,
}

impl PortAllocator {
pub fn new() -> Self {
Self {
wallet: MinotariPorts::new(),
}
}
}

#[derive(Clone)]
pub struct MinotariPorts {
pub p2p: Option<u16>,
pub grpc: Option<u16>,
}

#[allow(dead_code)]
impl MinotariPorts {
fn new() -> Self {
Self { p2p: None, grpc: None }
}

pub fn p2p_port_as_string(&self) -> Option<String> {
self.p2p?;
Some(format!("{}", self.p2p.unwrap()))
}

pub fn grpc_port_as_string(&self) -> Option<String> {
self.grpc?;
Some(format!("{}", self.grpc.unwrap()))
}
}

0 comments on commit 067bf14

Please sign in to comment.