Files
nym/ephemera/src/cli/init.rs
T
Bogdan-Ștefan Neacşu ee5b55fab6 Feature/ephemera (#3731)
* Feature/ephemera compile (#3437)

* Include ephemera node code in repo

* Upgrade deps

* Bump minor version of cosmwasm-std

* Include ephemera in nym-api dep and downgrade rusqlite

* Fix clippy and ephemera docs code

* More clippy on ephemera

---------

Co-authored-by: Andrus Salumets <andrus@nymtech.net>

* Start ephemera components in nym-api (#3475)

* Start ephemera components in nym-api

* Pass nyxd client and use common metric structures

* Swap url endpoint with contract for sending rewarding messages

* Fix build after rebase

* Perform ephemera rewards computation before normal nym-api ones

* Remove contract mock from ephemera

* Take raw rewards from network monitor

* Remove ephemera old reward version

* Use nym shutdown procedure in ephemera

* Temporary fix for some warnings

* Umock contract membership of ephemera (#3574)

* Pass nyxd client to members provider

* Basic ephemera contract

* Add register peer tx

* Add query all peers

* Nyxd ephemera client

* Add registration of ephemera peer

* Replace epoch http api with actual contract

* Merge ephemera config into nym-api config

* Load cluster from contract

* Guard nym-outfox out of cosmwasm builds (#3650)

* Feature/fixes while testing (#3668)

* Commit local peer before querying contract

* Default to anyonline

* Remove string from template

* Fix avg computing

* Use updated qa env

* Fix clippy

* Add unit tests for ephemera contract

* Upload ephemera contract in CI

* Add group check for peer signup

* Peer registration unit test

* Start ephemera only on monitoring

* Remove old MixnodeToReward struct

* Move all ephemera config to its file

* Skip with serde ephemera config

* Fix default value in args

* Feature/add ephemera flag (#3727)

* Replace unwrap with error handling

* Add ephemera enable flag

* Fix template

* Add json schema to ephemera contract (#3735)

* Update lock files

* Update changelog

---------

Co-authored-by: Andrus Salumets <andrus@nymtech.net>
2023-08-18 14:14:13 +03:00

166 lines
6.0 KiB
Rust

use clap::{Args, Parser};
use serde::{Deserialize, Serialize};
use crate::config::{
BlockManagerConfiguration, Configuration, DatabaseConfiguration, HttpConfiguration,
Libp2pConfiguration, MembershipKind as ConfigMembershipKind, NodeConfiguration,
WebsocketConfiguration,
};
use crate::crypto::{EphemeraKeypair, Keypair};
//network settings
const DEFAULT_LISTEN_ADDRESS: &str = "127.0.0.1";
const DEFAULT_PROT_LISTEN_PORT: u16 = 3000;
const DEFAULT_WS_LISTEN_PORT: u16 = 3001;
const DEFAULT_HTTP_LISTEN_PORT: u16 = 3002;
//libp2p settings
const DEFAULT_MESSAGES_TOPIC_NAME: &str = "nym-ephemera-proposed";
const DEFAULT_HEARTBEAT_INTERVAL_SEC: u64 = 1;
#[derive(Args, Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
#[group(required = true, multiple = false)]
pub struct MembershipKind {
/// Requires the threshold of peers returned by membership provider to be online
#[clap(long)]
threshold: Option<u64>,
/// Requires that all peers returned by membership provider peers to be online
#[clap(long)]
all: bool,
/// Membership is just all online peers from the set returned by membership provider
#[clap(long)]
any: bool,
}
impl Default for MembershipKind {
fn default() -> Self {
MembershipKind {
threshold: None,
all: false,
any: true,
}
}
}
impl From<MembershipKind> for ConfigMembershipKind {
fn from(kind: MembershipKind) -> Self {
match (kind.threshold, kind.all, kind.any) {
//FIXME: use threshold value
(Some(_), false, false) => ConfigMembershipKind::Threshold,
(None, true, false) => ConfigMembershipKind::AllOnline,
(None, false, true) => ConfigMembershipKind::AnyOnline,
_ => panic!("Invalid membership kind"),
}
}
}
#[derive(Parser, Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct Cmd {
#[clap(long)]
/// The IP address to listen on
pub ephemera_ip: Option<String>,
/// The port which Ephemera uses for peer to peer communication
#[clap(long)]
pub ephemera_protocol_port: Option<u16>,
/// The port which Ephemera listens on for websocket subscriptions
#[clap(long)]
pub ephemera_websocket_port: Option<u16>,
/// The port which Ephemera listens on for http api
#[clap(long)]
pub ephemera_http_api_port: Option<u16>,
/// Either this node produces blocks or not
#[clap(skip)]
pub block_producer: bool,
/// At which interval to produce blocks
#[clap(skip)]
pub block_creation_interval_sec: u64,
/// When next block is created before previous one is finished, should we repeat it with the same messages
#[clap(skip)]
pub repeat_last_block_messages: bool,
/// The interval at which Ephemera requests the list of members
#[clap(skip)]
pub members_provider_delay_sec: u64,
/// A rule how to choose members based on their online status
#[clap(skip)]
pub membership_kind: MembershipKind,
}
impl Default for Cmd {
fn default() -> Self {
Cmd {
ephemera_ip: Some(String::from(DEFAULT_LISTEN_ADDRESS)),
ephemera_protocol_port: Some(DEFAULT_PROT_LISTEN_PORT),
ephemera_websocket_port: Some(DEFAULT_WS_LISTEN_PORT),
ephemera_http_api_port: Some(DEFAULT_HTTP_LISTEN_PORT),
block_producer: true,
block_creation_interval_sec: 30,
repeat_last_block_messages: false,
members_provider_delay_sec: 60 * 60,
membership_kind: MembershipKind::default(),
}
}
}
impl Cmd {
/// # Panics
/// Panics if the config file already exists.
pub fn execute(self, id: Option<&str>) {
assert!(
Configuration::try_load_from_home_dir().is_err(),
"Configuration file already exists",
);
let path = Configuration::ephemera_root_dir(id).unwrap();
println!("Creating ephemera node configuration in: {path:?}",);
let db_dir = path.join("db");
let rocksdb_path = db_dir.join("rocksdb");
let sqlite_path = db_dir.join("ephemera.sqlite");
std::fs::create_dir_all(&rocksdb_path).unwrap();
std::fs::File::create(&sqlite_path).unwrap();
let keypair = Keypair::generate(None);
let private_key = keypair.to_base58();
let default_cfg = Self::default();
let configuration = Configuration {
node: NodeConfiguration {
ip: self.ephemera_ip.unwrap_or(default_cfg.ephemera_ip.unwrap()),
private_key,
},
libp2p: Libp2pConfiguration {
port: self
.ephemera_protocol_port
.unwrap_or(default_cfg.ephemera_protocol_port.unwrap()),
ephemera_msg_topic_name: DEFAULT_MESSAGES_TOPIC_NAME.to_string(),
heartbeat_interval_sec: DEFAULT_HEARTBEAT_INTERVAL_SEC,
members_provider_delay_sec: self.members_provider_delay_sec,
membership_kind: self.membership_kind.into(),
},
storage: DatabaseConfiguration {
rocksdb_path: rocksdb_path.as_os_str().to_str().unwrap().to_string(),
sqlite_path: sqlite_path.as_os_str().to_str().unwrap().to_string(),
create_if_not_exists: true,
},
websocket: WebsocketConfiguration {
port: self
.ephemera_websocket_port
.unwrap_or(default_cfg.ephemera_websocket_port.unwrap()),
},
http: HttpConfiguration {
port: self
.ephemera_http_api_port
.unwrap_or(default_cfg.ephemera_http_api_port.unwrap()),
},
block_manager: BlockManagerConfiguration {
producer: self.block_producer,
creation_interval_sec: self.block_creation_interval_sec,
repeat_last_block_messages: self.repeat_last_block_messages,
},
};
configuration.try_write_home_dir(id).ok();
}
}