Files
nym/ephemera/src/cli/run_node.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

141 lines
4.0 KiB
Rust

use anyhow::anyhow;
use std::str::FromStr;
use std::sync::Arc;
use clap::Parser;
use log::trace;
use nym_task::TaskManager;
use reqwest::Url;
use crate::ephemera_api::ApplicationResult;
use crate::utilities::codec::{Codec, EphemeraCodec};
use crate::{
api::application::CheckBlockResult,
cli::PEERS_CONFIG_FILE,
config::Configuration,
crypto::EphemeraKeypair,
crypto::Keypair,
ephemera_api::{ApiBlock, ApiEphemeraMessage, Application, Dummy, RawApiEphemeraMessage},
network::members::ConfigMembersProvider,
EphemeraStarterInit,
};
#[derive(Clone, Debug)]
pub struct HttpMembersProviderArg {
pub url: Url,
}
impl FromStr for HttpMembersProviderArg {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(HttpMembersProviderArg { url: s.parse()? })
}
}
#[derive(Parser)]
pub struct RunExternalNodeCmd {
#[clap(short, long)]
pub config_file: String,
#[clap(short, long)]
pub peers_config: String,
}
impl RunExternalNodeCmd {
/// # Errors
/// If the members provider cannot be created.
///
/// # Panics
/// If the ephemera cannot be created.
pub async fn execute(&self) -> anyhow::Result<()> {
let ephemera_conf = match Configuration::try_load(self.config_file.clone()) {
Ok(conf) => conf,
Err(err) => anyhow::bail!("Error loading configuration file: {err:?}"),
};
let members_provider = Self::config_members_provider_with_path(self.peers_config.clone())?;
let ephemera = EphemeraStarterInit::new(ephemera_conf.clone())
.unwrap()
.with_application(Dummy)
.with_members_provider(members_provider)?
.build();
let shutdown = TaskManager::new(10);
let shutdown_listener = shutdown.subscribe();
tokio::spawn(ephemera.run(shutdown_listener));
if let Err(err) = shutdown.catch_interrupt().await {
Err(anyhow!("Shutdown error {:?}", err))
} else {
Ok(())
}
}
#[allow(dead_code)]
fn config_members_provider() -> anyhow::Result<ConfigMembersProvider> {
let peers_conf_path = Configuration::ephemera_root_dir(None)
.unwrap()
.join(PEERS_CONFIG_FILE);
let peers_conf = match ConfigMembersProvider::init(peers_conf_path) {
Ok(conf) => conf,
Err(err) => anyhow::bail!("Error loading peers file: {err:?}"),
};
Ok(peers_conf)
}
#[allow(dead_code)]
fn config_members_provider_with_path(
peers_conf_path: String,
) -> anyhow::Result<ConfigMembersProvider> {
let peers_conf = match ConfigMembersProvider::init(peers_conf_path) {
Ok(conf) => conf,
Err(err) => anyhow::bail!("Error loading peers file: {err:?}"),
};
Ok(peers_conf)
}
}
pub struct SignatureVerificationApplication {
keypair: Arc<Keypair>,
}
impl SignatureVerificationApplication {
#[must_use]
pub fn new(keypair: Arc<Keypair>) -> Self {
Self { keypair }
}
pub(crate) fn verify_message(&self, msg: ApiEphemeraMessage) -> anyhow::Result<()> {
let signature = msg.certificate.clone();
let raw_message: RawApiEphemeraMessage = msg.into();
let encoded_message = Codec::encode(&raw_message)?;
if self
.keypair
.verify(&encoded_message, &signature.signature.into())
{
Ok(())
} else {
anyhow::bail!("Invalid signature")
}
}
}
impl Application for SignatureVerificationApplication {
fn check_tx(&self, tx: ApiEphemeraMessage) -> ApplicationResult<bool> {
trace!("SignatureVerificationApplicationHook::check_tx");
self.verify_message(tx)?;
Ok(true)
}
fn check_block(&self, _block: &ApiBlock) -> ApplicationResult<CheckBlockResult> {
Ok(CheckBlockResult::Accept)
}
fn deliver_block(&self, _block: ApiBlock) -> ApplicationResult<()> {
trace!("SignatureVerificationApplicationHook::deliver_block");
Ok(())
}
}