diff --git a/src/config.rs b/src/config.rs index 2789da7..3f9528e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -11,8 +11,11 @@ use crate::types::PremintName; #[derive(Envconfig, Debug)] pub struct Config { - #[envconfig(from = "SEED")] - pub seed: u64, + // Used to derive an ed25519 keypair for node identity + // Should be 32 bytes of random hex. + // Ex: output of `openssl rand -hex 32` + #[envconfig(from = "SECRET")] + pub secret: String, #[envconfig(from = "PEER_PORT", default = "7778")] pub peer_port: u64, @@ -79,7 +82,8 @@ pub struct Config { impl Config { pub fn test_default() -> Self { Config { - seed: rand::random(), + secret: "0x7948efac1e9dbfb77691541df857b3142ea88f5b75b37dfca506f1f1c5d659ee" + .to_string(), peer_port: rand::thread_rng().gen_range(5000..=10000), connect_external: false, db_url: None, @@ -198,14 +202,15 @@ mod test { #[test] fn test_init() { - env::set_var("SEED", "1"); + env::set_var("SECRET", "0x01"); super::init(); } #[test] fn test_premint_names() { let config = super::Config { - seed: 0, + secret: "0x7948efac1e9dbfb77691541df857b3142ea88f5b75b37dfca506f1f1c5d659ee" + .to_string(), peer_port: 7777, connect_external: false, db_url: None, @@ -232,7 +237,8 @@ mod test { assert_eq!(names[1].0, "zora_premint_v2"); let config = super::Config { - seed: 0, + secret: "0x7948efac1e9dbfb77691541df857b3142ea88f5b75b37dfca506f1f1c5d659ee" + .to_string(), peer_port: 7777, connect_external: false, db_url: None, diff --git a/src/run.rs b/src/run.rs index cf1e6f8..781f162 100644 --- a/src/run.rs +++ b/src/run.rs @@ -1,4 +1,6 @@ +use alloy::hex; use libp2p::identity; +use libp2p::identity::Keypair; use std::time::Duration; use tracing::{info_span, Instrument}; @@ -18,11 +20,8 @@ pub async fn start_p2p_services( config: &Config, rules: RulesEngine, ) -> eyre::Result { - let mut bytes = [0u8; 32]; - bytes[0] = config.seed as u8; - - let id_keys = identity::Keypair::ed25519_from_bytes(bytes).unwrap(); - + let id_keys = make_keypair(config) + .expect("Failed to create keypair, node cannot start. Confirm secret is 32 bytes of hex (0x + 64 hex chars)"); let (event_send, event_recv) = tokio::sync::mpsc::channel(1024); let (swrm_cmd_send, swrm_recv) = tokio::sync::mpsc::channel(1024); let (ext_cmd_send, ext_cmd_recv) = tokio::sync::mpsc::channel(1024); @@ -95,6 +94,20 @@ pub async fn start_p2p_services( Ok(controller_interface) } +fn make_keypair(config: &Config) -> eyre::Result { + let secret_bytes = hex::decode(&config.secret)?; + let mut bytes = [0u8; 32]; + if secret_bytes.len() < 32 { + bytes[..secret_bytes.len()].copy_from_slice(&secret_bytes); + } else if secret_bytes.len() > 32 { + bytes.copy_from_slice(&secret_bytes[..32]); + } else { + bytes.copy_from_slice(&secret_bytes); + }; + + Ok(Keypair::ed25519_from_bytes(bytes)?) +} + async fn connect_to_boot_nodes(ctl: &ControllerInterface, boot_nodes: Vec) { for boot_node in boot_nodes { if let Err(err) = ctl diff --git a/tests/common/mod.rs b/tests/common/mod.rs index e7766c6..03a06a0 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -1,8 +1,9 @@ pub mod factories; pub mod mintpool_build { - use mintpool::config::{BootNodes, ChainInclusionMode, Config}; + use mintpool::config::Config; use mintpool::controller::{ControllerCommands, ControllerInterface}; use mintpool::rules::RulesEngine; + use rand::Rng; use tokio::time; pub async fn announce_all(nodes: Vec) { @@ -25,28 +26,12 @@ pub mod mintpool_build { } pub fn make_config(port: u64, peer_limit: u64) -> Config { - let rand_n = rand::random::(); - Config { - seed: rand_n, - connect_external: false, - db_url: None, - persist_state: false, - prune_minted_premints: false, - api_port: 0, - peer_limit, - supported_premint_types: "simple,zora_premint_v2".to_string(), - chain_inclusion_mode: ChainInclusionMode::Check, - supported_chain_ids: "7777777".to_string(), - trusted_peers: None, - node_id: None, - external_address: None, - peer_port: port, - interactive: false, - enable_rpc: true, - admin_api_secret: None, - rate_limit_rps: 1, - boot_nodes: BootNodes::Chain, - } + let mut config = Config::test_default(); + config.secret = format!("0x{}", rand::thread_rng().gen_range(10..99)); + config.peer_port = port; + config.peer_limit = peer_limit; + + config } pub async fn make_nodes( diff --git a/tests/e2e_test.rs b/tests/e2e_test.rs index 208147c..607d8a6 100644 --- a/tests/e2e_test.rs +++ b/tests/e2e_test.rs @@ -49,27 +49,10 @@ async fn test_zora_premint_v2_e2e() { .fork("https://rpc.zora.energy") .spawn(); - let config = Config { - seed: 0, - peer_port: 7778, - connect_external: false, - db_url: None, - persist_state: false, - prune_minted_premints: false, // important so we can query table - api_port: 0, - peer_limit: 10, - supported_premint_types: "zora_premint_v2".to_string(), - chain_inclusion_mode: ChainInclusionMode::Check, - supported_chain_ids: "7777777".to_string(), - trusted_peers: None, - node_id: None, - external_address: None, - interactive: false, - enable_rpc: true, - admin_api_secret: None, - rate_limit_rps: 1, - boot_nodes: BootNodes::Chain, - }; + let mut config = Config::test_default(); + config.chain_inclusion_mode = ChainInclusionMode::Check; + config.prune_minted_premints = false; + config.supported_premint_types = "zora_premint_v2".to_string(); // set this so CHAINS will use the anvil rpc rather than the one in chains.json env::set_var("CHAIN_7777777_RPC_WSS", anvil.ws_endpoint()); @@ -209,49 +192,15 @@ async fn test_verify_e2e() { .fork("https://rpc.zora.energy") .spawn(); - let config1 = Config { - seed: 0, - peer_port: 5778, - connect_external: false, - db_url: None, - persist_state: false, - prune_minted_premints: false, - api_port: 0, - peer_limit: 10, - supported_premint_types: "zora_premint_v2".to_string(), - chain_inclusion_mode: ChainInclusionMode::Check, // <- this is the key - supported_chain_ids: "7777777".to_string(), - trusted_peers: None, - node_id: None, - external_address: None, - interactive: false, - enable_rpc: true, - admin_api_secret: None, - rate_limit_rps: 1, - boot_nodes: BootNodes::Chain, - }; + let mut config1 = Config::test_default(); + config1.secret = "0x01".to_string(); + config1.peer_port = 5778; + config1.chain_inclusion_mode = ChainInclusionMode::Check; - let config2 = Config { - seed: 1, - peer_port: 5779, - connect_external: false, - db_url: None, - persist_state: false, - prune_minted_premints: false, // important so we can query table - api_port: 0, - peer_limit: 10, - supported_premint_types: "zora_premint_v2".to_string(), - chain_inclusion_mode: ChainInclusionMode::Verify, // <- this is the key - supported_chain_ids: "7777777".to_string(), - trusted_peers: None, - node_id: None, - external_address: None, - interactive: false, - enable_rpc: true, - admin_api_secret: None, - rate_limit_rps: 1, - boot_nodes: BootNodes::Chain, - }; + let mut config2 = Config::test_default(); + config2.secret = "0x02".to_string(); + config2.peer_port = 5779; + config2.chain_inclusion_mode = ChainInclusionMode::Verify; env::set_var("CHAIN_7777777_RPC_WSS", anvil.ws_endpoint()); @@ -270,27 +219,11 @@ async fn test_verify_e2e() { let node_info = ctl1.get_node_info().await.unwrap(); - let config3 = Config { - seed: 2, - peer_port: 5776, - connect_external: false, - db_url: None, - persist_state: false, - prune_minted_premints: false, - api_port: 0, - peer_limit: 10, - supported_premint_types: "zora_premint_v2".to_string(), - chain_inclusion_mode: ChainInclusionMode::Trust, // <- this is the key - supported_chain_ids: "7777777".to_string(), - trusted_peers: Some(node_info.peer_id.to_string()), - node_id: None, - external_address: None, - interactive: false, - enable_rpc: true, - admin_api_secret: None, - rate_limit_rps: 1, - boot_nodes: BootNodes::Chain, - }; + let mut config3 = Config::test_default(); + config3.secret = "0x03".to_string(); + config3.peer_port = 5776; + config3.chain_inclusion_mode = ChainInclusionMode::Trust; + config3.trusted_peers = Some(node_info.peer_id.to_string()); let ctl3 = run::start_p2p_services(&config3, RulesEngine::new_with_default_rules(&config3)) .await