feat(devnet): Use volumes in docker compose for setup and run (#2172)

This commit is contained in:
gusto
2026-02-13 10:57:57 +02:00
committed by GitHub
parent 424686c895
commit b22be4ddbd
21 changed files with 516 additions and 263 deletions
+1
View File
@@ -7,3 +7,4 @@
ci
target
tempo-data
Generated
+1
View File
@@ -4272,6 +4272,7 @@ dependencies = [
"serde_json",
"serde_path_to_error",
"serde_yaml",
"time",
"tokio",
"tracing",
]
+222
View File
@@ -0,0 +1,222 @@
version: '3.8'
services:
explorer:
container_name: explorer
image: ghcr.io/logos-blockchain/logos-blockchain:devnet
depends_on:
- logos-blockchain-node-0
environment:
- NBE_NODE_API_HOST=logos-blockchain-node-0
- NBE_NODE_API_PORT=${NODE0_API_PORT}
ports:
- "8000:8000/tcp"
entrypoint: /opt/scripts/run_explorer.sh
cfgsync:
container_name: cfgsync
image: ghcr.io/logos-blockchain/logos-blockchain:devnet
volumes:
- ./testnet:/etc/logos-blockchain
depends_on:
- grafana
ports:
- "4400:4400/tcp"
entrypoint: /etc/logos-blockchain/scripts/run_cfgsync_server.sh
logos-blockchain-node-0:
container_name: logos_blockchain_node_0
image: ghcr.io/logos-blockchain/logos-blockchain:devnet
volumes:
- node-data:/node-data
- ./testnet:/etc/logos-blockchain
- ./tests/kzgrs/kzgrs_test_params:/kzgrs_test_params:z
depends_on:
- cfgsync
environment:
- LB_HOST_IDX=0
- CFG_HOST_IP=${PUBLIC_IP_ADDR}
- CFG_NETWORK_PORT=${NODE0_NET_PORT}
- CFG_BLEND_PORT=${NODE0_BLEND_PORT}
- CFG_API_PORT=${NODE0_API_PORT}
- FAUCET_PORT=${NODE0_FAUCET_PORT}
ports:
- "3000:3000/udp"
- "3400:3400/udp"
- "18085:18085/tcp"
entrypoint: /etc/logos-blockchain/scripts/run_node.sh
logos-blockchain-node-1:
container_name: logos_blockchain_node_1
image: ghcr.io/logos-blockchain/logos-blockchain:devnet
volumes:
- node-data:/node-data
- ./testnet:/etc/logos-blockchain
- ./tests/kzgrs/kzgrs_test_params:/kzgrs_test_params:z
depends_on:
- cfgsync
environment:
- LB_HOST_IDX=1
- CFG_HOST_IP=${PUBLIC_IP_ADDR}
- CFG_NETWORK_PORT=${NODE1_NET_PORT}
- CFG_BLEND_PORT=${NODE1_BLEND_PORT}
- CFG_API_PORT=${NODE1_API_PORT}
- FAUCET_PORT=${NODE1_FAUCET_PORT}
ports:
- "3001:3001/udp"
- "3401:3401/udp"
- "18081:18081/tcp"
entrypoint: /etc/logos-blockchain/scripts/run_node.sh
logos-blockchain-node-2:
container_name: logos_blockchain_node_2
image: ghcr.io/logos-blockchain/logos-blockchain:devnet
volumes:
- node-data:/node-data
- ./testnet:/etc/logos-blockchain
- ./tests/kzgrs/kzgrs_test_params:/kzgrs_test_params:z
depends_on:
- cfgsync
environment:
- LB_HOST_IDX=2
- CFG_HOST_IP=${PUBLIC_IP_ADDR}
- CFG_NETWORK_PORT=${NODE2_NET_PORT}
- CFG_BLEND_PORT=${NODE2_BLEND_PORT}
- CFG_API_PORT=${NODE2_API_PORT}
- FAUCET_PORT=${NODE2_FAUCET_PORT}
ports:
- "3002:3002/udp"
- "3402:3402/udp"
- "18082:18082/tcp"
entrypoint: /etc/logos-blockchain/scripts/run_node.sh
logos-blockchain-node-3:
container_name: logos_blockchain_node_3
image: ghcr.io/logos-blockchain/logos-blockchain:devnet
volumes:
- node-data:/node-data
- ./testnet:/etc/logos-blockchain
- ./tests/kzgrs/kzgrs_test_params:/kzgrs_test_params:z
depends_on:
- cfgsync
environment:
- LB_HOST_IDX=3
- CFG_HOST_IP=${PUBLIC_IP_ADDR}
- CFG_NETWORK_PORT=${NODE3_NET_PORT}
- CFG_BLEND_PORT=${NODE3_BLEND_PORT}
- CFG_API_PORT=${NODE3_API_PORT}
- FAUCET_PORT=${NODE3_FAUCET_PORT}
ports:
- "3003:3003/udp"
- "3403:3403/udp"
- "18083:18083/tcp"
entrypoint: /etc/logos-blockchain/scripts/run_node.sh
prometheus:
container_name: prometheus
image: prom/prometheus:v3.0.1
volumes:
- ./testnet/monitoring/prometheus.yml:/etc/prometheus/prometheus.yml:z
command:
- --config.file=/etc/prometheus/prometheus.yml
- --storage.tsdb.retention.time=7d
- --web.enable-otlp-receiver
ports:
- 0.0.0.0:9090:9090
restart: on-failure
grafana:
container_name: grafana
image: grafana/grafana:latest
environment:
- GF_AUTH_ANONYMOUS_ENABLED=true
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
- GF_AUTH_DISABLE_LOGIN_FORM=true
- GF_FEATURE_TOGGLES_ENABLE=traceqlEditor traceQLStreaming metricsSummary
env_file:
- ./testnet/monitoring/grafana/plugins.env
volumes:
- ./testnet/monitoring/grafana/grafana.ini:/etc/grafana/grafana.ini:z
- ./testnet/monitoring/grafana/datasources.yaml:/etc/grafana/provisioning/datasources/datasources.yaml:z
- ./testnet/monitoring/grafana/dashboards.yml:/etc/grafana/provisioning/dashboards/dashboards.yml:z
- ./testnet/monitoring/grafana/dashboards:/var/lib/grafana/dashboards/:z
ports:
- 9091:3000
restart: on-failure
depends_on:
- prometheus
loki:
image: grafana/loki:2.9.2
ports:
- "3100:3100"
command: -config.file=/etc/loki/local-config.yaml
# Tempo runs as unpriviliged user, volumes need to be chowned before running.
tempo-init:
image: busybox:latest
user: root
entrypoint:
- "chown"
- "10001:10001"
- "/var/tempo"
volumes:
- ./tempo-data:/var/tempo
tempo:
image: grafana/tempo:latest
container_name: tempo
command: [ "-config.file=/etc/tempo.yaml" ]
volumes:
- ./testnet/monitoring/tempo.yaml:/etc/tempo.yaml:z
- ./tempo-data:/var/tempo
ports:
- "4317:4317" # otlp grpc
depends_on:
- tempo-init
# L2 Sequencer Demo Services
l2-nginx:
container_name: l2_nginx
image: ghcr.io/logos-blockchain/logos-blockchain:devnet
ports:
- "18080:18080"
depends_on:
- cfgsync
- explorer
volumes:
- ./testnet/nginx.conf:/etc/nginx/nginx.conf:ro
- ./testnet/static:/usr/share/nginx/html:ro
entrypoint: [ "nginx", "-g", "daemon off;" ]
l2-sequencer:
container_name: l2_sequencer
image: ghcr.io/logos-blockchain/logos-blockchain:devnet
environment:
- SEQUENCER_LISTEN_ADDR=0.0.0.0:8080
- SEQUENCER_NODE_ENDPOINT=http://logos-blockchain-node-0:18081
- SEQUENCER_DB_PATH=/data/sequencer.db
- SEQUENCER_SIGNING_KEY_PATH=/data/sequencer.key
- SEQUENCER_CHANNEL_ID=6d656d636f696e00000000000000000000000000000000000000000000000001
- SEQUENCER_INITIAL_BALANCE=1000
volumes:
- l2-sequencer-data:/data
entrypoint: [ "/usr/bin/logos-blockchain-demo-sequencer" ]
l2-archiver:
container_name: l2_archiver
image: ghcr.io/logos-blockchain/logos-blockchain:devnet
environment:
- TESTNET_ENDPOINT=http://logos-blockchain-node-1:18081
- CHANNEL_ID=6d656d636f696e00000000000000000000000000000000000000000000000001
- TOKEN_NAME=MEM
entrypoint: [ "/usr/bin/logos-blockchain-demo-archiver" ]
# Node data volume is marked as external and assumes
# that configuration files were placed by compose.setup.yml
volumes:
l2-sequencer-data:
node-data:
name: logos-node-data
external: true
+81
View File
@@ -0,0 +1,81 @@
version: '3.8'
services:
cfgsync:
container_name: cfgsync
image: ghcr.io/logos-blockchain/logos-blockchain:devnet
volumes:
- node-data:/node-data
- ./testnet:/etc/logos-blockchain
ports:
- "4400:4400/tcp"
entrypoint: /etc/logos-blockchain/scripts/setup_cfgsync_server.sh
client-0:
container_name: client_0
image: ghcr.io/logos-blockchain/logos-blockchain:devnet
volumes:
- node-data:/node-data
- ./testnet:/etc/logos-blockchain
depends_on:
- cfgsync
environment:
- LB_HOST_IDX=0
- CFG_HOST_IP=${PUBLIC_IP_ADDR}
- CFG_NETWORK_PORT=${NODE0_NET_PORT}
- CFG_BLEND_PORT=${NODE0_BLEND_PORT}
- CFG_API_PORT=${NODE0_API_PORT}
entrypoint: /etc/logos-blockchain/scripts/setup_cfgsync_client.sh
client-1:
container_name: client_1
image: ghcr.io/logos-blockchain/logos-blockchain:devnet
volumes:
- node-data:/node-data
- ./testnet:/etc/logos-blockchain
depends_on:
- cfgsync
environment:
- LB_HOST_IDX=1
- CFG_HOST_IP=${PUBLIC_IP_ADDR}
- CFG_NETWORK_PORT=${NODE1_NET_PORT}
- CFG_BLEND_PORT=${NODE1_BLEND_PORT}
- CFG_API_PORT=${NODE1_API_PORT}
entrypoint: /etc/logos-blockchain/scripts/setup_cfgsync_client.sh
client-2:
container_name: client_2
image: ghcr.io/logos-blockchain/logos-blockchain:devnet
volumes:
- node-data:/node-data
- ./testnet:/etc/logos-blockchain
depends_on:
- cfgsync
environment:
- LB_HOST_IDX=2
- CFG_HOST_IP=${PUBLIC_IP_ADDR}
- CFG_NETWORK_PORT=${NODE2_NET_PORT}
- CFG_BLEND_PORT=${NODE2_BLEND_PORT}
- CFG_API_PORT=${NODE2_API_PORT}
entrypoint: /etc/logos-blockchain/scripts/setup_cfgsync_client.sh
client-3:
container_name: client_3
image: ghcr.io/logos-blockchain/logos-blockchain:devnet
volumes:
- node-data:/node-data
- ./testnet:/etc/logos-blockchain
depends_on:
- cfgsync
environment:
- LB_HOST_IDX=3
- CFG_HOST_IP=${PUBLIC_IP_ADDR}
- CFG_NETWORK_PORT=${NODE3_NET_PORT}
- CFG_BLEND_PORT=${NODE3_BLEND_PORT}
- CFG_API_PORT=${NODE3_API_PORT}
entrypoint: /etc/logos-blockchain/scripts/setup_cfgsync_client.sh
volumes:
node-data:
name: logos-node-data
-209
View File
@@ -1,209 +0,0 @@
version: '3.8'
services:
explorer:
container_name: explorer
image: ghcr.io/logos-blockchain/logos-blockchain:devnet
depends_on:
- logos-blockchain-node-0
environment:
- NBE_NODE_API_HOST=logos-blockchain-node-0
- NBE_NODE_API_PORT=${NODE0_API_PORT}
ports:
- "8000:8000/tcp"
entrypoint: /opt/scripts/run_explorer.sh
cfgsync:
container_name: cfgsync
image: ghcr.io/logos-blockchain/logos-blockchain:devnet
volumes:
- ./testnet:/etc/logos-blockchain
depends_on:
- grafana
ports:
- "4400:4400/tcp"
entrypoint: /etc/logos-blockchain/scripts/run_cfgsync.sh
logos-blockchain-node-0:
container_name: logos_blockchain_node_0
image: ghcr.io/logos-blockchain/logos-blockchain:devnet
volumes:
- ./testnet:/etc/logos-blockchain
- ./tests/kzgrs/kzgrs_test_params:/kzgrs_test_params:z
depends_on:
- cfgsync
environment:
- CFG_HOST_IP=${PUBLIC_IP_ADDR}
- CFG_NETWORK_PORT=${NODE0_NET_PORT}
- CFG_BLEND_PORT=${NODE0_BLEND_PORT}
- CFG_API_PORT=${NODE0_API_PORT}
- FAUCET_PORT=${NODE0_FAUCET_PORT}
ports:
- "3000:3000/udp"
- "3400:3400/udp"
- "18085:18085/tcp"
entrypoint: /etc/logos-blockchain/scripts/run_node.sh
logos-blockchain-node-1:
container_name: logos_blockchain_node_1
image: ghcr.io/logos-blockchain/logos-blockchain:devnet
volumes:
- ./testnet:/etc/logos-blockchain
- ./tests/kzgrs/kzgrs_test_params:/kzgrs_test_params:z
depends_on:
- cfgsync
environment:
- CFG_HOST_IP=${PUBLIC_IP_ADDR}
- CFG_NETWORK_PORT=${NODE1_NET_PORT}
- CFG_BLEND_PORT=${NODE1_BLEND_PORT}
- CFG_API_PORT=${NODE1_API_PORT}
- FAUCET_PORT=${NODE1_FAUCET_PORT}
ports:
- "3001:3001/udp"
- "3401:3401/udp"
- "18081:18081/tcp"
entrypoint: /etc/logos-blockchain/scripts/run_node.sh
logos-blockchain-node-2:
container_name: logos_blockchain_node_2
image: ghcr.io/logos-blockchain/logos-blockchain:devnet
volumes:
- ./testnet:/etc/logos-blockchain
- ./tests/kzgrs/kzgrs_test_params:/kzgrs_test_params:z
depends_on:
- cfgsync
environment:
- CFG_HOST_IP=${PUBLIC_IP_ADDR}
- CFG_NETWORK_PORT=${NODE2_NET_PORT}
- CFG_BLEND_PORT=${NODE2_BLEND_PORT}
- CFG_API_PORT=${NODE2_API_PORT}
- FAUCET_PORT=${NODE2_FAUCET_PORT}
ports:
- "3002:3002/udp"
- "3402:3402/udp"
- "18082:18082/tcp"
entrypoint: /etc/logos-blockchain/scripts/run_node.sh
logos-blockchain-node-3:
container_name: logos_blockchain_node_3
image: ghcr.io/logos-blockchain/logos-blockchain:devnet
volumes:
- ./testnet:/etc/logos-blockchain
- ./tests/kzgrs/kzgrs_test_params:/kzgrs_test_params:z
depends_on:
- cfgsync
environment:
- CFG_HOST_IP=${PUBLIC_IP_ADDR}
- CFG_NETWORK_PORT=${NODE3_NET_PORT}
- CFG_BLEND_PORT=${NODE3_BLEND_PORT}
- CFG_API_PORT=${NODE3_API_PORT}
- FAUCET_PORT=${NODE3_FAUCET_PORT}
ports:
- "3003:3003/udp"
- "3403:3403/udp"
- "18083:18083/tcp"
entrypoint: /etc/logos-blockchain/scripts/run_node.sh
prometheus:
container_name: prometheus
image: prom/prometheus:v3.0.1
volumes:
- ./testnet/monitoring/prometheus.yml:/etc/prometheus/prometheus.yml:z
command:
- --config.file=/etc/prometheus/prometheus.yml
- --storage.tsdb.retention.time=7d
- --web.enable-otlp-receiver
ports:
- 0.0.0.0:9090:9090
restart: on-failure
grafana:
container_name: grafana
image: grafana/grafana:latest
environment:
- GF_AUTH_ANONYMOUS_ENABLED=true
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
- GF_AUTH_DISABLE_LOGIN_FORM=true
- GF_FEATURE_TOGGLES_ENABLE=traceqlEditor traceQLStreaming metricsSummary
env_file:
- ./testnet/monitoring/grafana/plugins.env
volumes:
- ./testnet/monitoring/grafana/grafana.ini:/etc/grafana/grafana.ini:z
- ./testnet/monitoring/grafana/datasources.yaml:/etc/grafana/provisioning/datasources/datasources.yaml:z
- ./testnet/monitoring/grafana/dashboards.yml:/etc/grafana/provisioning/dashboards/dashboards.yml:z
- ./testnet/monitoring/grafana/dashboards:/var/lib/grafana/dashboards/:z
ports:
- 9091:3000
restart: on-failure
depends_on:
- prometheus
loki:
image: grafana/loki:2.9.2
ports:
- "3100:3100"
command: -config.file=/etc/loki/local-config.yaml
# Tempo runs as unpriviliged user, volumes need to be chowned before running.
tempo-init:
image: busybox:latest
user: root
entrypoint:
- "chown"
- "10001:10001"
- "/var/tempo"
volumes:
- ./tempo-data:/var/tempo
tempo:
image: grafana/tempo:latest
container_name: tempo
command: [ "-config.file=/etc/tempo.yaml" ]
volumes:
- ./testnet/monitoring/tempo.yaml:/etc/tempo.yaml:z
- ./tempo-data:/var/tempo
ports:
- "4317:4317" # otlp grpc
depends_on:
- tempo-init
# L2 Sequencer Demo Services
l2-nginx:
container_name: l2_nginx
image: ghcr.io/logos-blockchain/logos-blockchain:devnet
ports:
- "18080:18080"
depends_on:
- cfgsync
- explorer
volumes:
- ./testnet/nginx.conf:/etc/nginx/nginx.conf:ro
- ./testnet/static:/usr/share/nginx/html:ro
entrypoint: [ "nginx", "-g", "daemon off;" ]
l2-sequencer:
container_name: l2_sequencer
image: ghcr.io/logos-blockchain/logos-blockchain:devnet
environment:
- SEQUENCER_LISTEN_ADDR=0.0.0.0:8080
- SEQUENCER_NODE_ENDPOINT=http://logos-blockchain-node-0:18081
- SEQUENCER_DB_PATH=/data/sequencer.db
- SEQUENCER_SIGNING_KEY_PATH=/data/sequencer.key
- SEQUENCER_CHANNEL_ID=6d656d636f696e00000000000000000000000000000000000000000000000001
- SEQUENCER_INITIAL_BALANCE=1000
volumes:
- l2-sequencer-data:/data
entrypoint: [ "/usr/bin/logos-blockchain-demo-sequencer" ]
l2-archiver:
container_name: l2_archiver
image: ghcr.io/logos-blockchain/logos-blockchain:devnet
environment:
- TESTNET_ENDPOINT=http://logos-blockchain-node-1:18081
- CHANNEL_ID=6d656d636f696e00000000000000000000000000000000000000000000000001
- TOKEN_NAME=MEM
entrypoint: [ "/usr/bin/logos-blockchain-demo-archiver" ]
volumes:
l2-sequencer-data:
+1
View File
@@ -0,0 +1 @@
compose.devnet.run.yml
+1 -1
View File
@@ -8,7 +8,7 @@ services:
image: logos-blockchain:latest
volumes:
- ./testnet:/etc/logos-blockchain
entrypoint: /etc/logos-blockchain/scripts/run_cfgsync.sh
entrypoint: /etc/logos-blockchain/scripts/run_cfgsync_server.sh
logos-blockchain-node:
build:
+5
View File
@@ -6,6 +6,11 @@ faucet_settings:
note_count: 3
note_value: 10000000
deployment_settings_storage_path:
deployment-settings.yaml
mode: Run
# Tracing
tracing_settings:
logger: Stdout
+1
View File
@@ -28,6 +28,7 @@ serde = { workspace = true }
serde_json = { default-features = false, version = "1.0" }
serde_path_to_error = "0.1"
serde_yaml = "0.9"
time = { default-features = false, version = "0.3" }
tokio = { default-features = false, features = ["macros", "net", "rt-multi-thread"], version = "1" }
tracing = { workspace = true }
+31 -3
View File
@@ -1,26 +1,54 @@
use std::{path::PathBuf, process};
use clap::Parser;
use logos_blockchain_cfgsync::server::{CfgSyncConfig, cfgsync_app};
use logos_blockchain_cfgsync::{
CfgsyncMode,
server::{CfgSyncConfig, cfgsync_app},
};
use time::{OffsetDateTime, format_description::well_known::Rfc3339};
use tokio::net::TcpListener;
fn parse_rfc3339(s: &str) -> Result<OffsetDateTime, String> {
OffsetDateTime::parse(s, &Rfc3339)
.map_err(|e| format!("Invalid RFC3339 format (2026-02-12T04:45:00Z): {e}"))
}
#[derive(Parser, Debug)]
#[command(about = "CfgSync")]
struct Args {
config: PathBuf,
#[arg(short, long, env = "CHAIN_START_TIME", value_parser = parse_rfc3339)]
chain_start_time: Option<OffsetDateTime>,
#[arg(short, long, env = "CFG_SERVER_MODE")]
mode: Option<CfgsyncMode>,
#[arg(short, long, env = "CFG_SERVER_STORAGE_PATH")]
storage_path: Option<PathBuf>,
}
#[tokio::main]
async fn main() {
let cli = Args::parse();
let config = CfgSyncConfig::load_from_file(&cli.config).unwrap_or_else(|err| {
let mut config = CfgSyncConfig::load_from_file(&cli.config).unwrap_or_else(|err| {
eprintln!("{err}");
process::exit(1);
});
if let Some(chain_start_time) = cli.chain_start_time {
config.chain_start_time = Some(chain_start_time);
}
if let Some(storage_path) = cli.storage_path {
config.deployment_settings_storage_path = storage_path;
}
if let Some(mode) = cli.mode {
config.mode = mode;
}
let port = config.port;
let app = cfgsync_app(config.into());
let mode = config.mode;
let app = cfgsync_app(config.into(), mode);
println!("Server running on http://0.0.0.0:{port}");
let listener = TcpListener::bind(&format!("0.0.0.0:{port}")).await.unwrap();
+5
View File
@@ -48,6 +48,11 @@ pub fn create_node_configs(
ids.push(id_bytes);
}
// Clippy in 1.93.0:
// > an unstable sort typically performs faster without any
// > observable difference for this data type. [stable_sort_primitive]
ids.sort_unstable();
let (consensus_configs, faucet_note_keys, genesis_tx) =
create_consensus_configs(&ids, SHORT_PROLONGED_BOOTSTRAP_PERIOD, faucet_settings);
let network_configs = create_network_configs(&ids, &NetworkParams::default());
+8
View File
@@ -5,6 +5,7 @@ pub mod server;
use std::net::Ipv4Addr;
use clap::ValueEnum;
use serde::{Deserialize, Serialize};
const DEFAULT_LIBP2P_NETWORK_PORT: u16 = 3000;
@@ -68,3 +69,10 @@ pub struct FaucetSettings {
pub note_count: usize,
pub note_value: u64,
}
#[derive(Clone, Copy, Debug, Deserialize, ValueEnum)]
#[clap(rename_all = "kebab-case")]
pub enum CfgsyncMode {
Setup,
Run,
}
+26 -5
View File
@@ -1,5 +1,6 @@
use std::{
collections::HashMap,
path::PathBuf,
sync::{Arc, Mutex},
time::Duration,
};
@@ -9,6 +10,7 @@ use lb_node::config::{
deployment::{DeploymentSettings, WellKnownDeployment},
};
use lb_tests::topology::configs::GeneralConfig;
use time::OffsetDateTime;
use tokio::{sync::oneshot::Sender, time::timeout};
use crate::{
@@ -26,22 +28,25 @@ pub struct ConfigRepo {
waiting_hosts: Mutex<HashMap<Host, Sender<RepoResponse>>>,
generated_user_configs: Mutex<HashMap<Host, GeneralConfig>>,
deployment_settings: Mutex<Option<DeploymentSettings>>,
pub deployment_settings_storage_path: PathBuf,
n_hosts: usize,
faucet_settings: FaucetSettings,
tracing_settings: TracingConfig,
chain_start_time: OffsetDateTime,
timeout_duration: Duration,
}
impl From<CfgSyncConfig> for Arc<ConfigRepo> {
fn from(config: CfgSyncConfig) -> Self {
let faucet_settings = config.faucet_settings();
let tracing_settings = config.tracing_settings();
ConfigRepo::new(
config.n_hosts,
faucet_settings,
tracing_settings,
config.faucet_settings(),
config
.chain_start_time
.unwrap_or_else(OffsetDateTime::now_utc),
config.tracing_settings(),
Duration::from_secs(config.timeout),
config.deployment_settings_storage_path,
)
}
}
@@ -51,15 +56,19 @@ impl ConfigRepo {
pub fn new(
n_hosts: usize,
faucet_settings: FaucetSettings,
chain_start_time: OffsetDateTime,
tracing_settings: TracingConfig,
timeout_duration: Duration,
deployment_settings_storage_path: PathBuf,
) -> Arc<Self> {
let repo = Arc::new(Self {
waiting_hosts: Mutex::new(HashMap::new()),
generated_user_configs: Mutex::new(HashMap::new()),
deployment_settings: Mutex::new(None),
deployment_settings_storage_path,
n_hosts,
faucet_settings,
chain_start_time,
tracing_settings,
timeout_duration,
});
@@ -107,6 +116,14 @@ impl ConfigRepo {
None
}
fn persist_deployment_settings(&self, settings: &DeploymentSettings) -> Result<(), String> {
let yaml = serde_yaml::to_string(settings)
.map_err(|e| format!("Error: Failed to serialize deployment settings: {e}"))?;
std::fs::write(&self.deployment_settings_storage_path, yaml)
.map_err(|err| format!("Failed to write config to file: {err}"))?;
Ok(())
}
async fn run(&self) {
let timeout_duration = self.timeout_duration;
@@ -121,6 +138,7 @@ impl ConfigRepo {
let devnet_settings = {
let mut default_settings = DeploymentSettings::from(WellKnownDeployment::Devnet);
default_settings.cryptarchia.genesis_state = genesis_tx;
default_settings.time.chain_start_time = self.chain_start_time;
default_settings
};
@@ -134,6 +152,9 @@ impl ConfigRepo {
*deployment_settings = Some(devnet_settings.clone());
};
self.persist_deployment_settings(&devnet_settings)
.expect("Settings should be persisted");
for (host, sender) in waiting_hosts.drain() {
let config = configs.get(&host).expect("host should have a config");
drop(sender.send(RepoResponse::Config(Box::new((
+36 -31
View File
@@ -2,8 +2,9 @@ use std::{fs, path::PathBuf, sync::Arc};
use axum::{
Json, Router,
body::Body,
extract::State,
http::StatusCode,
http::{Response, StatusCode},
response::IntoResponse,
routing::{get, post},
};
@@ -11,10 +12,11 @@ use lb_node::config::TracingConfig;
use lb_tests::nodes::create_validator_config;
use reqwest::header::CONTENT_TYPE;
use serde::Deserialize;
use time::OffsetDateTime;
use tokio::sync::oneshot::channel;
use crate::{
FaucetSettings, Host, RegistrationInfo,
CfgsyncMode, FaucetSettings, Host, RegistrationInfo,
repo::{ConfigRepo, RepoResponse},
};
@@ -23,6 +25,10 @@ pub struct CfgSyncConfig {
pub port: u16,
pub n_hosts: usize,
pub timeout: u64,
pub chain_start_time: Option<OffsetDateTime>,
pub deployment_settings_storage_path: PathBuf,
pub mode: CfgsyncMode,
pub faucet_settings: FaucetSettings,
// Tracing params
@@ -68,39 +74,38 @@ async fn init_node(
)
}
async fn generate_config(
State(repo): State<Arc<ConfigRepo>>,
Json(info): Json<RegistrationInfo>,
) -> impl IntoResponse {
let host = Host::from(info);
repo.append(host).map_or_else(
|| {
(
StatusCode::BAD_REQUEST,
"Network not initialized. Initial nodes must sync first.",
)
.into_response()
},
|cfg| {
let node_config = create_validator_config(cfg, repo.deployment_settings().unwrap());
let yaml = serde_yaml::to_string(&node_config).unwrap_or_default();
(StatusCode::OK, [(CONTENT_TYPE, "text/yaml")], yaml).into_response()
},
async fn handle_mode_error() -> (StatusCode, &'static str) {
(
StatusCode::METHOD_NOT_ALLOWED,
"Setup is disabled: Server is in Read-Only mode.",
)
}
async fn deployment_settings(State(repo): State<Arc<ConfigRepo>>) -> impl IntoResponse {
let deployment_settings = repo.deployment_settings();
let yaml = serde_yaml::to_string(&deployment_settings).unwrap_or_default();
(StatusCode::OK, [(CONTENT_TYPE, "text/yaml")], yaml).into_response()
match tokio::fs::read(&repo.deployment_settings_storage_path).await {
Ok(bytes) => Response::builder()
.status(StatusCode::OK)
.header(CONTENT_TYPE, "text/yaml")
.body(Body::from(bytes))
.unwrap(),
Err(e) => {
eprintln!("Failed to read deployment file: {e}");
(StatusCode::NOT_FOUND, "Deployment file not found").into_response()
}
}
}
pub fn cfgsync_app(config_repo: Arc<ConfigRepo>) -> Router {
Router::new()
.route("/init-with-node", post(init_node))
.route("/generate-config", post(generate_config))
.route("/deployment-settings", get(deployment_settings))
.with_state(config_repo)
pub fn cfgsync_app(config_repo: Arc<ConfigRepo>, mode: CfgsyncMode) -> Router {
let mut router = Router::new().route("/deployment-settings", get(deployment_settings));
match mode {
CfgsyncMode::Setup => {
router = router.route("/init-with-node", post(init_node));
}
CfgsyncMode::Run => {
router = router.route("/init-with-node", post(handle_mode_error));
}
}
router.with_state(config_repo)
}
+5
View File
@@ -6,6 +6,11 @@ faucet_settings:
note_count: 3
note_value: 10000000
deployment_settings_storage_path:
deployment-settings.yaml
mode: Run
# Tracing
tracing_settings:
logger: !Stdout
+2 -1
View File
@@ -9,6 +9,8 @@ const SERVER_CFG: &str = "../cfgsync.yaml"; // Use config from "testnet" dir.
#[tokio::test]
async fn smoke_test_four_clients() {
let mut server = std::process::Command::new(SERVER_BIN)
.arg("--mode")
.arg("setup")
.arg(SERVER_CFG)
.spawn()
.expect("server failed");
@@ -38,6 +40,5 @@ async fn smoke_test_four_clients() {
fs::remove_file(out).unwrap();
}
sleep(Duration::from_secs(51)).await;
server.kill().and_then(|()| server.wait()).unwrap();
}
+51 -1
View File
@@ -14,9 +14,11 @@ const SERVER_CFG: &str = "./tests/cfgsync.yaml";
#[ignore = "For local debugging"]
#[tokio::test]
async fn test_spawn_nodes_from_cfgsync_custom_ports() {
async fn test_deploy_setup_stage() {
// Start the configuration server
let mut server = std::process::Command::new(SERVER_BIN)
.arg("--mode")
.arg("setup")
.arg(SERVER_CFG)
.spawn()
.expect("server failed");
@@ -88,3 +90,51 @@ async fn test_spawn_nodes_from_cfgsync_custom_ports() {
server.kill().unwrap();
server.wait().unwrap();
}
#[ignore = "For local debugging"]
#[tokio::test]
async fn test_deploy_run_stage() {
let server = std::process::Command::new(SERVER_BIN)
.arg("--mode")
.arg("run")
.arg("--storage-path")
.arg("cfgsync-deployment-settings.yaml")
.arg(SERVER_CFG)
.spawn()
.expect("server failed to start in run mode");
sleep(Duration::from_secs(15)).await;
let response = reqwest::get("http://127.0.0.1:4400/deployment-settings")
.await
.expect("Failed to hit deployment-settings endpoint");
let yaml_bytes = response.bytes().await.unwrap();
let deployment: DeploymentSettings = serde_yaml::from_slice(&yaml_bytes).unwrap();
let mut nodes = Vec::new();
for i in 0..4 {
let node_cfg_path = format!(".tmp_node_{i}.yaml");
let user_yaml = fs::read_to_string(&node_cfg_path).expect("Node config file missing.");
let user_config: UserConfig =
serde_yaml::from_str(&user_yaml).expect("Failed to parse user config");
let run_config = RunConfig {
user: user_config,
deployment: deployment.clone(),
};
println!(">>>> Spawning Node {i} from disk (.tmp_node_{i}.yaml)");
let node = Validator::spawn(run_config)
.await
.expect("Node spawn failed");
nodes.push(node);
}
println!("\nIndependent network spawned from disk. Press Ctrl+C to terminate.\n");
tokio::signal::ctrl_c().await.unwrap();
drop(nodes);
drop(server);
}
-5
View File
@@ -1,5 +0,0 @@
#!/bin/sh
set -e
exec /usr/bin/logos-blockchain-cfgsync-server /etc/logos-blockchain/cfgsync.yaml
+8
View File
@@ -0,0 +1,8 @@
#!/bin/sh
set -e
export CFG_SERVER_MODE="run" \
CFG_SERVER_STORAGE_PATH="/node-data/cfgsync/deploymen-settings.yaml"
exec /usr/bin/logos-blockchain-cfgsync-server /etc/logos-blockchain/cfgsync.yaml
+5 -7
View File
@@ -2,20 +2,18 @@
set -e
export CFG_FILE_PATH="/config.yaml" \
export CFG_FILE_PATH="/node-data/${LB_HOST_IDX}/config.yaml" \
CFG_SERVER_ADDR="http://cfgsync:4400" \
CFG_HOST_IDENTIFIER="validator-$CFG_API_PORT" \
LOG_LEVEL="INFO" \
POL_PROOF_DEV_MODE=true
/usr/bin/logos-blockchain-cfgsync-client
CFG_DEPLOYMENT_PATH="/node-data/cfgsync/deployment-settings.yaml" \
LOG_LEVEL="INFO"
echo "Starting Faucet..."
/usr/bin/logos-blockchain-faucet \
--port $FAUCET_PORT \
--node-base-url "http://localhost:$CFG_API_PORT"\
--host-identifier $CFG_HOST_IDENTIFIER
--host-identifier $CFG_HOST_IDENTIFIER \
--drip-amount 1000 &
echo "Starting Node..."
exec /usr/bin/logos-blockchain-node /config.yaml
exec /usr/bin/logos-blockchain-node --deployment $CFG_DEPLOYMENT_PATH $CFG_FILE_PATH
+13
View File
@@ -0,0 +1,13 @@
#!/bin/sh
rm -rf /node-data/${LB_HOST_IDX}
set -e
export CFG_FILE_PATH="/node-data/${LB_HOST_IDX}/config.yaml" \
CFG_SERVER_ADDR="http://cfgsync:4400" \
CFG_HOST_IDENTIFIER="validator-$CFG_NETWORK_PORT"
mkdir /node-data/${LB_HOST_IDX}
exec /usr/bin/logos-blockchain-cfgsync-client
+13
View File
@@ -0,0 +1,13 @@
#!/bin/sh
rm -rf /node-data/cfgsync
set -e
export CFG_SERVER_MODE="setup" \
CFG_SERVER_STORAGE_PATH="/node-data/cfgsync/deployment-settings.yaml" \
CHAIN_START_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
mkdir /node-data/cfgsync
exec /usr/bin/logos-blockchain-cfgsync-server /etc/logos-blockchain/cfgsync.yaml