Files
nym/nym-api/src/main.rs
T
Jędrzej Stuczyński f328f3fa9e Feature/gateway api (#3970)
* Squashing all the changes

initial router

started expanding the API

initial empty openapi/swagger

populated build-info endpoint

wip: populating rest of swagger

missing swagger data + using closure capture for immutable state

running the api as a proper task in gateway 'run'

fixing some version/feature clashes

refactored routes structures

initial host information endpoint

expanded on gateway-related endpoints

signing host information

moved all models to separate crate

unified http api client

routes unification + node api client

new generic cache and refresher

nym-api caching node self described information

removed old cache type

temporarily wired up NymContractCache to NodeDescriptionProvider

caching self reported host info

clients using self-described gateway information

fixed request timeouts for wasm

fixed wasm builds

post rebase fixes

cargo fmt

brought in wg routes into nym-node router

added ErrorResponse for wireguard routes

basic swagger support for wg endpoints

turns out swagger can be happy with strongly typed requests

output type support for wg routes

using concrete error type for nym node request error

fixed the registration test

landing page configurability

increased configurability

fixed build and lints of other crates

added default user-agent to http-api-client

reduced severity of gateway details lookup failure

changed default http port from 80 to 8080

nym-api using new default port for queries

added health endpoint

nym-api trying multiple ports for the client

using camelcase for node status

corrected health endpoint description

restored and revamped 'force_tls' flag to filter all gateways that support the wss protocol

fixed 'pub_key' path param in open api schema

derived Debug on 'NymNodeDescription'

ensuring valid public ips

added init and run flags to set hostname and public ips

fixed listening address being pushed to public ip

fixed the positional local flag

logging remote ip address of the request

updated helper function to query for described gateways

enabled tls in gateway client

removed hack-opts from mix fetch

additional changes after rebasing against origin/develop

* clippy

* wasm-related target locking

* more clippy, but this time in tests
2023-10-19 12:36:53 +02:00

239 lines
7.6 KiB
Rust

// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
#[macro_use]
extern crate rocket;
use crate::epoch_operations::RewardedSetUpdater;
use crate::network::models::NetworkDetails;
use crate::node_describe_cache::DescribedNodes;
use crate::node_status_api::uptime_updater::HistoricalUptimeUpdater;
use crate::support::caching::cache::SharedCache;
use crate::support::cli;
use crate::support::cli::CliArgs;
use crate::support::config::Config;
use crate::support::storage;
use crate::support::storage::NymApiStorage;
use ::ephemera::configuration::Configuration as EphemeraConfiguration;
use ::nym_config::defaults::setup_env;
use anyhow::Result;
use circulating_supply_api::cache::CirculatingSupplyCache;
use clap::Parser;
use coconut::dkg::controller::DkgController;
use log::info;
use node_status_api::NodeStatusCache;
use nym_bin_common::logging::setup_logging;
use nym_contract_cache::cache::NymContractCache;
use nym_sphinx::receiver::SphinxMessageReceiver;
use nym_task::TaskManager;
use rand::rngs::OsRng;
use std::error::Error;
use support::{http, nyxd};
mod circulating_supply_api;
mod coconut;
mod ephemera;
mod epoch_operations;
pub(crate) mod network;
mod network_monitor;
pub(crate) mod node_describe_cache;
pub(crate) mod node_status_api;
pub(crate) mod nym_contract_cache;
pub(crate) mod nym_nodes;
pub(crate) mod support;
struct ShutdownHandles {
task_manager_handle: TaskManager,
rocket_handle: rocket::Shutdown,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
println!("Starting nym api...");
cfg_if::cfg_if! {if #[cfg(feature = "console-subscriber")] {
// instrument tokio console subscriber needs RUSTFLAGS="--cfg tokio_unstable" at build time
console_subscriber::init();
}}
setup_logging();
let args = cli::CliArgs::parse();
setup_env(args.config_env_file.as_ref());
run_nym_api(args).await
}
async fn start_nym_api_tasks(
config: Config,
) -> Result<ShutdownHandles, Box<dyn Error + Send + Sync>> {
let nyxd_client = nyxd::Client::new(&config);
let connected_nyxd = config.get_nyxd_url();
let nym_network_details = config.get_network_details();
let network_details = NetworkDetails::new(connected_nyxd.to_string(), nym_network_details);
let coconut_keypair = coconut::keypair::KeyPair::new();
// let's build our rocket!
let rocket = http::setup_rocket(
&config,
network_details,
nyxd_client.clone(),
coconut_keypair.clone(),
)
.await?;
// setup shutdowns
let shutdown = TaskManager::new(10);
// Rocket handles shutdown on its own, but its shutdown handling should be incorporated
// with that of the rest of the tasks. Currently its runtime is forcefully terminated once
// nym-api exits.
let rocket_shutdown_handle = rocket.shutdown();
// get references to the managed state
let nym_contract_cache_state = rocket.state::<NymContractCache>().unwrap();
let node_status_cache_state = rocket.state::<NodeStatusCache>().unwrap();
let circulating_supply_cache_state = rocket.state::<CirculatingSupplyCache>().unwrap();
let maybe_storage = rocket.state::<NymApiStorage>();
let described_nodes_state = rocket.state::<SharedCache<DescribedNodes>>().unwrap();
// start note describe cache refresher
// we should be doing the below, but can't due to our current startup structure
// let refresher = node_describe_cache::new_refresher(&config.topology_cacher);
// let cache = refresher.get_shared_cache();
node_describe_cache::new_refresher_with_initial_value(
&config.topology_cacher,
nym_contract_cache_state.clone(),
described_nodes_state.to_owned(),
)
.named("node-self-described-data-refresher")
.start(shutdown.subscribe_named("node-self-described-data-refresher"));
// start all the caches first
let nym_contract_cache_listener = nym_contract_cache::start_refresher(
&config.node_status_api,
nym_contract_cache_state,
nyxd_client.clone(),
&shutdown,
);
node_status_api::start_cache_refresh(
&config.node_status_api,
nym_contract_cache_state,
node_status_cache_state,
maybe_storage,
nym_contract_cache_listener,
&shutdown,
);
circulating_supply_api::start_cache_refresh(
&config.circulating_supply_cacher,
nyxd_client.clone(),
circulating_supply_cache_state,
&shutdown,
);
// start dkg task
if config.coconut_signer.enabled {
DkgController::start(
&config.coconut_signer,
nyxd_client.clone(),
coconut_keypair,
OsRng,
&shutdown,
)
.await?;
}
// and then only start the uptime updater (and the monitor itself, duh)
// if the monitoring if it's enabled
if config.network_monitor.enabled {
let ephemera_config =
match EphemeraConfiguration::try_load(config.get_ephemera_config_path()) {
Ok(c) => c,
Err(_) => {
config
.get_ephemera_args()
.cmd
.clone()
.execute(Some(&config.get_id()));
EphemeraConfiguration::try_load(config.get_ephemera_config_path())
.expect("Config file should be created now")
}
};
let ephemera_reward_manager = if config.ephemera.enabled {
Some(
ephemera::application::NymApi::run(
config.get_ephemera_args().clone(),
ephemera_config,
nyxd_client.clone(),
&shutdown,
)
.await?,
)
} else {
None
};
// if network monitor is enabled, the storage MUST BE available
let storage = maybe_storage.unwrap();
network_monitor::start::<SphinxMessageReceiver>(
&config.network_monitor,
nym_contract_cache_state,
storage,
nyxd_client.clone(),
&shutdown,
)
.await;
HistoricalUptimeUpdater::start(storage, &shutdown);
// start 'rewarding' if its enabled
if config.rewarding.enabled {
epoch_operations::ensure_rewarding_permission(&nyxd_client).await?;
RewardedSetUpdater::start(
ephemera_reward_manager,
nyxd_client,
nym_contract_cache_state,
storage,
&shutdown,
);
}
}
// Launch the rocket, serve http endpoints and finish the startup
tokio::spawn(rocket.launch());
Ok(ShutdownHandles {
task_manager_handle: shutdown,
rocket_handle: rocket_shutdown_handle,
})
}
async fn run_nym_api(cli_args: CliArgs) -> Result<(), Box<dyn Error + Send + Sync>> {
let save_to_file = cli_args.save_config;
let config = cli::build_config(cli_args)?;
// if we just wanted to write data to the config, exit, don't start any tasks
if save_to_file {
info!("Saving the configuration to a file");
config.save_to_default_location()?;
config
.get_ephemera_args()
.cmd
.clone()
.execute(Some(&config.get_id()));
return Ok(());
}
let shutdown_handlers = start_nym_api_tasks(config).await?;
let res = shutdown_handlers
.task_manager_handle
.catch_interrupt()
.await;
log::info!("Stopping nym API");
shutdown_handlers.rocket_handle.notify();
res
}