diff --git a/Cargo.lock b/Cargo.lock index 0ea6f23..39cd47d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1575,6 +1575,25 @@ dependencies = [ "syn 2.0.52", ] +[[package]] +name = "env_filter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" +dependencies = [ + "log", +] + +[[package]] +name = "env_logger" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" +dependencies = [ + "env_filter", + "log", +] + [[package]] name = "envconfig" version = "0.10.0" @@ -3010,6 +3029,7 @@ dependencies = [ "serde", "serde_json", "sqlx", + "test-log", "tokio", "tracing", "tracing-subscriber", @@ -4775,6 +4795,28 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "test-log" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b319995299c65d522680decf80f2c108d85b861d81dfe340a10d16cee29d9e6" +dependencies = [ + "env_logger", + "test-log-macros", + "tracing-subscriber", +] + +[[package]] +name = "test-log-macros" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8f546451eaa38373f549093fe9fd05e7d2bade739e2ddf834b9968621d60107" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + [[package]] name = "thiserror" version = "1.0.57" diff --git a/Cargo.toml b/Cargo.toml index 093d9c8..211175e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,8 @@ edition = "2021" [dependencies] const-hex = "1.11.3" tracing = "0.1.40" -tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } +tracing-subscriber = { version = "0.3.18", features = ["env-filter", "fmt"] } +test-log = { version = "0.2.15", features = ["trace"] } libp2p = { version = "0.53.2", features = [ "tokio", "tcp", diff --git a/src/config.rs b/src/config.rs index ef2fd61..a74963e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -44,6 +44,10 @@ pub struct Config { // If not provided in the environment, the default is to use the public node #[envconfig(from = "TRUSTED_PEERS")] pub trusted_peers: Option, + + // node_id will only be used for logging purposes, if set + #[envconfig(from = "NODE_ID")] + pub node_id: Option, } #[derive(Debug, Clone, Copy, PartialEq)] @@ -144,6 +148,7 @@ mod test { chain_inclusion_mode: ChainInclusionMode::Check, supported_chain_ids: "7777777".to_string(), trusted_peers: None, + node_id: None, }; let names = config.premint_names(); @@ -164,6 +169,7 @@ mod test { chain_inclusion_mode: ChainInclusionMode::Check, supported_chain_ids: "7777777".to_string(), trusted_peers: None, + node_id: None, }; let names = config.premint_names(); diff --git a/src/controller.rs b/src/controller.rs index b168b98..2e4d15e 100644 --- a/src/controller.rs +++ b/src/controller.rs @@ -168,7 +168,7 @@ impl Controller { tracing::warn!( "Premint failed validation: {:?}, evaluation: {:?}", premint, - evaluation + evaluation.summary() ); Err(eyre::eyre!(evaluation.summary())) } diff --git a/src/p2p.rs b/src/p2p.rs index 5be6899..152ae6d 100644 --- a/src/p2p.rs +++ b/src/p2p.rs @@ -48,6 +48,12 @@ impl SwarmController { } } + pub fn node_info(&self) -> MintpoolNodeInfo { + let peer_id = *self.swarm.local_peer_id(); + let addr: Vec = self.swarm.listeners().cloned().collect(); + MintpoolNodeInfo { peer_id, addr } + } + fn make_swarm_controller(id_keys: Keypair) -> eyre::Result> { let peer_id = id_keys.public().to_peer_id(); let swarm = libp2p::SwarmBuilder::with_existing_identity(id_keys) @@ -149,9 +155,7 @@ impl SwarmController { } } SwarmCommand::ReturnNodeInfo { channel } => { - let peer_id = *self.swarm.local_peer_id(); - let addr: Vec = self.swarm.listeners().cloned().collect(); - if channel.send(MintpoolNodeInfo { peer_id, addr }).is_err() { + if channel.send(self.node_info()).is_err() { tracing::error!("Error sending node info from swarm",); } } diff --git a/src/run.rs b/src/run.rs index 9376ff9..f936990 100644 --- a/src/run.rs +++ b/src/run.rs @@ -1,4 +1,5 @@ use libp2p::identity; +use tracing::{info_span, Instrument}; use crate::config::{ChainInclusionMode, Config}; use crate::controller::{Controller, ControllerInterface}; @@ -29,17 +30,34 @@ pub async fn start_services(config: &Config) -> eyre::Result future.instrument(info_span!("", "node_id" = node_id)).await, + None => future.await, + } + .expect("Swarm controller failed"); }); + let node_id = config.node_id.clone(); tokio::spawn(async move { - controller.run_loop().await; + let future = controller.run_loop(); + + match node_id { + Some(node_id) => future.instrument(info_span!("", "node_id" = node_id)).await, + None => future.await, + } }); if config.chain_inclusion_mode == ChainInclusionMode::Check { diff --git a/src/storage.rs b/src/storage.rs index a2e50c2..8009f90 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -142,6 +142,7 @@ mod test { supported_chain_ids: "7777777,".to_string(), trusted_peers: None, api_port: 0, + node_id: None, }; let store = PremintStorage::new(&config).await; @@ -167,6 +168,7 @@ mod test { chain_inclusion_mode: ChainInclusionMode::Check, supported_chain_ids: "7777777,".to_string(), trusted_peers: None, + node_id: None, }; let store = PremintStorage::new(&config).await; diff --git a/src/types.rs b/src/types.rs index b0b90e2..04b13d4 100644 --- a/src/types.rs +++ b/src/types.rs @@ -86,6 +86,17 @@ pub struct SimplePremint { media: String, } +impl SimplePremint { + pub fn new(chain_id: U256, sender: Address, token_id: u64, media: String) -> Self { + Self { + chain_id, + sender, + token_id, + media, + } + } +} + #[async_trait] impl Premint for SimplePremint { fn metadata(&self) -> PremintMetadata { diff --git a/tests/common/factories.rs b/tests/common/factories.rs new file mode 100644 index 0000000..93c12fc --- /dev/null +++ b/tests/common/factories.rs @@ -0,0 +1,43 @@ +use alloy_primitives::{Address, U256}; +use mintpool::types::SimplePremint; +use rand::{Rng, RngCore}; + +pub trait Factory +where + Self: Sized, + O: Default, +{ + fn build(options: O) -> Self; + fn build_default() -> Self { + Self::build(O::default()) + } +} + +#[derive(Default)] +pub struct SimplePremintOptions { + chain_id: Option, + sender: Option
, + media: Option, + token_id: Option, +} + +impl Factory for SimplePremint { + fn build(options: SimplePremintOptions) -> Self { + let mut rng = rand::thread_rng(); + + Self::new( + U256::from( + options + .chain_id + .unwrap_or(rng.gen_range(1..=i64::MAX as u64)), + ), + options + .sender + .unwrap_or(Address::from(rng.gen::<[u8; 20]>())), + options.token_id.unwrap_or(rng.next_u64()), + options + .media + .unwrap_or("http://example.com/token".to_string()), + ) + } +} diff --git a/tests/common/mod.rs b/tests/common/mod.rs new file mode 100644 index 0000000..0467b1e --- /dev/null +++ b/tests/common/mod.rs @@ -0,0 +1 @@ +pub mod factories; diff --git a/tests/p2p_test.rs b/tests/p2p_test.rs index a773cdb..0483e35 100644 --- a/tests/p2p_test.rs +++ b/tests/p2p_test.rs @@ -1,9 +1,13 @@ +mod common; + +use common::factories::Factory; use mintpool::controller::ControllerCommands; use mintpool::controller::ControllerCommands::Broadcast; -use mintpool::types::PremintTypes; +use mintpool::types::{PremintTypes, SimplePremint}; use tokio::time; +use tracing_subscriber::EnvFilter; -#[tokio::test] +#[test_log::test(tokio::test)] // test to make sure that nodes can connect to a specified host async fn test_connecting_to_other_nodes() { let num_nodes = 10; @@ -21,7 +25,7 @@ async fn test_connecting_to_other_nodes() { } } -#[tokio::test] +#[test_log::test(tokio::test)] // test announcing self to the network async fn test_announcing_to_network() { let num_nodes = 3; @@ -43,7 +47,7 @@ async fn test_announcing_to_network() { } } -#[tokio::test] +#[test_log::test(tokio::test)] // After a premint is announced, all connected nodes should be able to list it async fn test_list_all_premints() { let num_nodes = 3; @@ -60,7 +64,7 @@ async fn test_list_all_premints() { first .send_command(Broadcast { - message: PremintTypes::Simple(Default::default()), + message: PremintTypes::Simple(SimplePremint::build_default()), }) .await .unwrap(); @@ -79,7 +83,7 @@ async fn test_list_all_premints() { } } -#[tokio::test] +#[test_log::test(tokio::test)] // Connections should not be able to exceed max_connections config async fn test_max_connections() { let num_nodes = 5; @@ -98,6 +102,7 @@ async fn test_max_connections() { mod build { use mintpool::config::{ChainInclusionMode, Config}; use mintpool::controller::{ControllerCommands, ControllerInterface}; + use mintpool::types::Premint; use tokio::time; pub async fn announce_all(nodes: Vec) { @@ -140,6 +145,7 @@ mod build { chain_inclusion_mode: ChainInclusionMode::Check, supported_chain_ids: "7777777".to_string(), trusted_peers: None, + node_id: Some(i), }; let ctl = mintpool::run::start_services(&config).await.unwrap(); @@ -152,6 +158,7 @@ mod build { start_port: u64, num_nodes: u64, ) -> Vec { + tracing::info!("Generating swarm of {} nodes", num_nodes); let nodes = make_nodes(start_port, num_nodes, 1000).await; connect_all_to_first(nodes.clone()).await; time::sleep(time::Duration::from_secs(1)).await;