mirror of
https://github.com/logos-co/nomos-node.git
synced 2026-08-30 19:11:09 +00:00
277 lines
8.7 KiB
Rust
277 lines
8.7 KiB
Rust
use core::str::FromStr as _;
|
|
use std::collections::HashMap;
|
|
|
|
use color_eyre::eyre::{Result, eyre};
|
|
use lb_groth16::fr_to_bytes;
|
|
use lb_key_management_system_service::{
|
|
backend::preload::KeyId,
|
|
keys::{Ed25519Key, Key, ZkKey, ZkPublicKey, secured_key::SecuredKey as _},
|
|
};
|
|
use libp2p::{Multiaddr, PeerId};
|
|
use num_bigint::BigUint;
|
|
use rand::rngs::OsRng;
|
|
|
|
use crate::{
|
|
UserConfig,
|
|
config::{
|
|
ApiConfig, InitArgs, KmsConfig, SdpConfig, StateConfig, StorageConfig, TracingConfig,
|
|
WalletConfig,
|
|
blend::serde::{Config as BlendConfig, RequiredValues as BlendConfigRequiredValues},
|
|
cryptarchia::serde::{
|
|
Config as CryptarchiaConfig, RequiredValues as CryptarchiaConfigRequiredValues,
|
|
},
|
|
network::serde::{Config as NetworkConfig, nat},
|
|
sdp::serde::RequiredValues as SdpRequiredValues,
|
|
time::serde::Config as TimeConfig,
|
|
wallet::serde::RequiredValues as WalletConfigRequiredValues,
|
|
},
|
|
};
|
|
|
|
fn key_id(key: &Key) -> KeyId {
|
|
let key_id_bytes = match key {
|
|
Key::Ed25519(ed25519_secret_key) => ed25519_secret_key.as_public_key().to_bytes(),
|
|
Key::Zk(zk_secret_key) => fr_to_bytes(zk_secret_key.as_public_key().as_fr()),
|
|
};
|
|
hex::encode(key_id_bytes)
|
|
}
|
|
|
|
fn generate_zk_key_from_random_bytes() -> ZkKey {
|
|
let mut bytes = [0u8; 32];
|
|
rand::RngCore::fill_bytes(&mut OsRng, &mut bytes);
|
|
ZkKey::from(BigUint::from_bytes_le(&bytes))
|
|
}
|
|
|
|
struct GeneratedKeys {
|
|
blend_signing_key: Ed25519Key,
|
|
blend_zk_key: ZkKey,
|
|
leader_key: ZkKey,
|
|
funding_key: ZkKey,
|
|
blend_signing_key_id: KeyId,
|
|
blend_zk_key_id: KeyId,
|
|
leader_key_id: KeyId,
|
|
funding_key_id: KeyId,
|
|
leader_pk: ZkPublicKey,
|
|
funding_pk: ZkPublicKey,
|
|
}
|
|
|
|
fn generate_keys() -> GeneratedKeys {
|
|
let blend_signing_key = Ed25519Key::generate(&mut OsRng);
|
|
let blend_zk_key = ZkKey::from(BigUint::from_bytes_le(
|
|
blend_signing_key.public_key().as_bytes(),
|
|
));
|
|
let leader_key = generate_zk_key_from_random_bytes();
|
|
let funding_key = generate_zk_key_from_random_bytes();
|
|
|
|
let blend_signing_key_id = key_id(&blend_signing_key.clone().into());
|
|
let blend_zk_key_id = key_id(&blend_zk_key.clone().into());
|
|
let leader_key_id = key_id(&leader_key.clone().into());
|
|
let funding_key_id = key_id(&funding_key.clone().into());
|
|
|
|
let leader_pk: ZkPublicKey = leader_key.as_public_key();
|
|
let funding_pk: ZkPublicKey = funding_key.as_public_key();
|
|
|
|
GeneratedKeys {
|
|
blend_signing_key,
|
|
blend_zk_key,
|
|
leader_key,
|
|
funding_key,
|
|
blend_signing_key_id,
|
|
blend_zk_key_id,
|
|
leader_key_id,
|
|
funding_key_id,
|
|
leader_pk,
|
|
funding_pk,
|
|
}
|
|
}
|
|
|
|
pub fn run(args: &InitArgs) -> Result<()> {
|
|
if args.initial_peers.is_empty() {
|
|
eprintln!("Warning: No initial peers provided. This node will start as a genesis node.");
|
|
}
|
|
|
|
let network_key = lb_libp2p::ed25519::SecretKey::generate();
|
|
let keys = generate_keys();
|
|
|
|
let blend_listening_address =
|
|
Multiaddr::from_str(&format!("/ip4/0.0.0.0/udp/{}/quic-v1", args.blend_port))
|
|
.map_err(|e| eyre!("Invalid blend listening address: {e}"))?;
|
|
|
|
let user_config = build_user_config(args, network_key, keys, blend_listening_address);
|
|
|
|
let yaml = serde_yaml::to_string(&user_config)?;
|
|
std::fs::write(&args.output, &yaml)?;
|
|
|
|
println!("Config written to {}", args.output.display());
|
|
Ok(())
|
|
}
|
|
|
|
fn build_user_config(
|
|
args: &InitArgs,
|
|
network_key: lb_libp2p::ed25519::SecretKey,
|
|
keys: GeneratedKeys,
|
|
blend_listening_address: Multiaddr,
|
|
) -> UserConfig {
|
|
let GeneratedKeys {
|
|
blend_signing_key,
|
|
blend_zk_key,
|
|
leader_key,
|
|
funding_key,
|
|
blend_signing_key_id,
|
|
blend_zk_key_id,
|
|
leader_key_id,
|
|
funding_key_id,
|
|
leader_pk,
|
|
funding_pk,
|
|
} = keys;
|
|
|
|
let state_config = args
|
|
.state_path
|
|
.as_ref()
|
|
.map_or_else(StateConfig::default, |path| StateConfig {
|
|
base_folder: path.clone(),
|
|
});
|
|
|
|
let network_config = {
|
|
let mut base_config = NetworkConfig::default();
|
|
base_config.backend.swarm.port = args.net_port;
|
|
base_config.backend.swarm.node_key = network_key;
|
|
base_config
|
|
.backend
|
|
.initial_peers
|
|
.clone_from(&args.initial_peers);
|
|
if let Some(external_address) = &args.external_address {
|
|
base_config.backend.swarm.nat = nat::Config::Static {
|
|
external_address: external_address.clone(),
|
|
};
|
|
}
|
|
|
|
base_config
|
|
};
|
|
|
|
let blend_config = {
|
|
let mut base_config = BlendConfig::with_required_values(BlendConfigRequiredValues {
|
|
non_ephemeral_signing_key_id: blend_signing_key_id.clone(),
|
|
secret_key_kms_id: blend_zk_key_id.clone(),
|
|
});
|
|
base_config.set_listening_address(blend_listening_address);
|
|
base_config
|
|
};
|
|
|
|
let cryptarchia_config = {
|
|
let mut base_config =
|
|
CryptarchiaConfig::with_required_values(CryptarchiaConfigRequiredValues { funding_pk });
|
|
base_config.network.bootstrap.ibd.peers = args
|
|
.initial_peers
|
|
.iter()
|
|
.filter_map(|addr| match addr.iter().last() {
|
|
Some(lb_libp2p::Protocol::P2p(bytes)) => PeerId::from_multihash(bytes.into()).ok(),
|
|
_ => None,
|
|
})
|
|
.collect();
|
|
base_config
|
|
};
|
|
|
|
let time_config = TimeConfig::default();
|
|
|
|
let tracing_config = TracingConfig::default();
|
|
|
|
let sdp_config = SdpConfig::with_required_values(SdpRequiredValues { funding_pk });
|
|
|
|
let api_config = {
|
|
let mut base_config = ApiConfig::default();
|
|
base_config.backend.listen_address = args.http_addr;
|
|
base_config
|
|
};
|
|
|
|
let storage_config = StorageConfig::default();
|
|
|
|
let kms_config = {
|
|
let mut base_config = KmsConfig::default();
|
|
base_config.backend.keys = HashMap::from([
|
|
(blend_signing_key_id, blend_signing_key.into()),
|
|
(blend_zk_key_id, blend_zk_key.into()),
|
|
(leader_key_id.clone(), leader_key.into()),
|
|
(funding_key_id.clone(), funding_key.into()),
|
|
]);
|
|
base_config
|
|
};
|
|
|
|
let wallet_config = {
|
|
let mut base_config = WalletConfig::with_required_values(WalletConfigRequiredValues {
|
|
voucher_master_key_id: leader_key_id.clone(),
|
|
});
|
|
base_config.known_keys = [(leader_key_id, leader_pk), (funding_key_id, funding_pk)]
|
|
.into_iter()
|
|
.collect();
|
|
base_config
|
|
};
|
|
|
|
UserConfig {
|
|
network: network_config,
|
|
blend: blend_config,
|
|
cryptarchia: cryptarchia_config,
|
|
time: time_config,
|
|
tracing: tracing_config,
|
|
sdp: sdp_config,
|
|
api: api_config,
|
|
storage: storage_config,
|
|
kms: kms_config,
|
|
wallet: wallet_config,
|
|
state: state_config,
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use std::net::SocketAddr;
|
|
|
|
use super::*;
|
|
|
|
fn build_config_from_peers(initial_peers: Vec<Multiaddr>) -> UserConfig {
|
|
let args = InitArgs {
|
|
initial_peers,
|
|
output: "test_output.yaml".into(),
|
|
net_port: 3000,
|
|
blend_port: 3400,
|
|
http_addr: SocketAddr::from(([0, 0, 0, 0], 8080)),
|
|
external_address: None,
|
|
state_path: None,
|
|
};
|
|
let network_key = lb_libp2p::ed25519::SecretKey::generate();
|
|
let keys = generate_keys();
|
|
let blend_addr = Multiaddr::from_str("/ip4/0.0.0.0/udp/3400/quic-v1").unwrap();
|
|
build_user_config(&args, network_key, keys, blend_addr)
|
|
}
|
|
|
|
#[test]
|
|
fn extracts_peer_ids_into_ibd_config() {
|
|
let peer1 = PeerId::random();
|
|
let peer2 = PeerId::random();
|
|
|
|
let addr_with_p2p_1: Multiaddr = format!("/ip4/1.2.3.4/udp/3000/quic-v1/p2p/{peer1}")
|
|
.parse()
|
|
.unwrap();
|
|
let addr_with_p2p_2: Multiaddr = format!("/ip4/5.6.7.8/udp/3000/quic-v1/p2p/{peer2}")
|
|
.parse()
|
|
.unwrap();
|
|
let addr_without_p2p: Multiaddr = "/ip4/9.10.11.12/udp/3000/quic-v1".parse().unwrap();
|
|
|
|
let config =
|
|
build_config_from_peers(vec![addr_with_p2p_1, addr_without_p2p, addr_with_p2p_2]);
|
|
|
|
let ibd_peers = &config.cryptarchia.network.bootstrap.ibd.peers;
|
|
assert_eq!(ibd_peers.len(), 2);
|
|
assert!(ibd_peers.contains(&peer1));
|
|
assert!(ibd_peers.contains(&peer2));
|
|
}
|
|
|
|
#[test]
|
|
fn no_peer_ids_yields_empty_ibd_config() {
|
|
let addr: Multiaddr = "/ip4/1.2.3.4/udp/3000/quic-v1".parse().unwrap();
|
|
|
|
let config = build_config_from_peers(vec![addr]);
|
|
|
|
assert!(config.cryptarchia.network.bootstrap.ibd.peers.is_empty());
|
|
}
|
|
}
|