From 3246e7a7effb09d2d01c12a67fb28de62f404df2 Mon Sep 17 00:00:00 2001 From: hopeyen Date: Thu, 6 Jul 2023 20:11:24 -0500 Subject: [PATCH 1/7] fix: standarlize nonce across graphcast and radio --- poi-radio/benches/gossips.rs | 4 +- poi-radio/src/config.rs | 12 +- poi-radio/src/lib.rs | 170 ++------------- poi-radio/src/main.rs | 11 +- poi-radio/src/messages/mod.rs | 61 ++++++ poi-radio/src/messages/poi.rs | 301 ++++++++++++++++++++++++++ poi-radio/src/messages/upgrade.rs | 141 ++++++++++++ poi-radio/src/operator/attestation.rs | 7 +- poi-radio/src/operator/mod.rs | 75 +++++-- poi-radio/src/operator/operation.rs | 255 +++++++++++++--------- poi-radio/src/server/model/mod.rs | 14 +- poi-radio/src/state.rs | 47 ++-- test-runner/src/invalid_sender.rs | 2 +- test-runner/src/message_handling.rs | 8 +- test-runner/src/topics.rs | 18 +- test-sender/src/main.rs | 8 +- test-utils/src/config.rs | 2 +- test-utils/src/lib.rs | 27 +-- 18 files changed, 825 insertions(+), 338 deletions(-) create mode 100644 poi-radio/src/messages/mod.rs create mode 100644 poi-radio/src/messages/poi.rs create mode 100644 poi-radio/src/messages/upgrade.rs diff --git a/poi-radio/benches/gossips.rs b/poi-radio/benches/gossips.rs index 2087f0d6..50f454e5 100644 --- a/poi-radio/benches/gossips.rs +++ b/poi-radio/benches/gossips.rs @@ -58,13 +58,13 @@ fn gossip_poi_bench(c: &mut Criterion) { discv5_enrs: None, discv5_port: None, filter_protocol: None, - id_validation: Some(IdentityValidation::NoCheck), + id_validation: IdentityValidation::NoCheck, topic_update_interval: 600, }); c.bench_function("gossip_poi", move |b| { b.to_async(FuturesExecutor).iter(|| async { - RadioOperator::new(config.clone()) + RadioOperator::new(&config) .await .gossip_poi( identifiers.clone(), diff --git a/poi-radio/src/config.rs b/poi-radio/src/config.rs index 7e7e57e2..ed1920a9 100644 --- a/poi-radio/src/config.rs +++ b/poi-radio/src/config.rs @@ -14,6 +14,7 @@ use graphcast_sdk::{ }, init_tracing, wallet_address, }; + use serde::{Deserialize, Serialize}; use std::collections::HashSet; use tracing::{debug, info, trace}; @@ -295,7 +296,7 @@ pub struct Config { registered-indexer: must be registered at Graphcast Registry, correspond to and Indexer statisfying indexer minimum stake requirement, \n indexer: must be registered at Graphcast Registry or is a Graph Account, correspond to and Indexer statisfying indexer minimum stake requirement" )] - pub id_validation: Option, + pub id_validation: IdentityValidation, #[clap( long, value_name = "TOPIC_UPDATE_INTERVAL", @@ -348,7 +349,8 @@ impl Config { self.radio_name.clone(), self.registry_subgraph.clone(), self.network_subgraph.clone(), - self.graph_node_endpoint.clone(), + self.id_validation.clone(), + Some(self.graph_node_endpoint.clone()), Some(self.boot_node_addresses.clone()), Some(self.graphcast_network.to_owned()), Some(topics), @@ -359,7 +361,6 @@ impl Config { self.filter_protocol, self.discv5_enrs.clone(), self.discv5_port, - self.id_validation.clone(), ) .await } @@ -393,9 +394,12 @@ impl Config { // panic_hook(&path); let state = PersistedState::load_cache(path); trace!( + local_attestations = tracing::field::debug(&state.local_attestations()), + remote_messages = tracing::field::debug(&state.remote_messages()), state = tracing::field::debug(&state), "Loaded Persisted state cache" ); + state } else { debug!("Created new state"); @@ -412,7 +416,7 @@ impl Config { CallBook::new( self.graph_node_endpoint.clone(), self.registry_subgraph.clone(), - self.network_subgraph.clone(), + Some(self.network_subgraph.clone()), ) } diff --git a/poi-radio/src/lib.rs b/poi-radio/src/lib.rs index 2ff88e42..c75bf9e2 100644 --- a/poi-radio/src/lib.rs +++ b/poi-radio/src/lib.rs @@ -1,11 +1,9 @@ -use async_graphql::{Error, ErrorExtensions, SimpleObject}; +use async_graphql::{Error, ErrorExtensions}; use autometrics::autometrics; use ethers_contract::EthAbiType; use ethers_core::types::transaction::eip712::Eip712; use ethers_derive_eip712::*; use once_cell::sync::OnceCell; -use prost::Message; -use serde::{Deserialize, Serialize}; use std::{ collections::HashMap, sync::{ @@ -14,177 +12,46 @@ use std::{ }, }; use tokio::signal; -use tracing::{error, trace}; +use tracing::{error}; + use graphcast_sdk::{ graphcast_agent::GraphcastAgentError, - graphql::{client_graph_node::get_indexing_statuses, QueryError}, + graphql::{ + client_graph_node::get_indexing_statuses, QueryError, + }, }; use graphcast_sdk::{ graphcast_agent::{ - message_typing::{BuildMessageError, GraphcastMessage}, GraphcastAgent, }, graphql::{ - client_graph_node::query_graph_node_network_block_hash, client_network::query_network_subgraph, }, networks::NetworkName, BlockPointer, }; -use crate::operator::attestation::AttestationError; +use crate::operator::{attestation::AttestationError, RadioOperator}; pub mod config; pub mod graphql; +pub mod messages; pub mod metrics; pub mod operator; pub mod server; pub mod state; +/// A global static (singleton) instance of GraphcastAgent. It is useful to ensure that we have only one GraphcastAgent +/// per Radio instance, so that we can keep track of state and more easily test our Radio application. +pub static RADIO_OPERATOR: OnceCell = OnceCell::new(); + /// A global static (singleton) instance of GraphcastAgent. It is useful to ensure that we have only one GraphcastAgent /// per Radio instance, so that we can keep track of state and more easily test our Radio application. pub static GRAPHCAST_AGENT: OnceCell> = OnceCell::new(); pub fn radio_name() -> &'static str { - "poi-radio" -} - -#[derive(Eip712, EthAbiType, Clone, Message, Serialize, Deserialize, PartialEq, SimpleObject)] -#[eip712( - name = "Graphcast POI Radio", - version = "0", - chain_id = 1, - verifying_contract = "0xc944e90c64b2c07662a292be6244bdf05cda44a7" -)] -pub struct RadioPayloadMessage { - #[prost(string, tag = "1")] - pub identifier: String, - #[prost(string, tag = "2")] - pub content: String, - //TODO: see if timestamp that comes with waku message can be used - /// nonce cached to check against the next incoming message - #[prost(int64, tag = "3")] - pub nonce: i64, - /// blockchain relevant to the message - #[prost(string, tag = "4")] - pub network: String, - /// block relevant to the message - #[prost(uint64, tag = "5")] - pub block_number: u64, - /// block hash generated from the block number - #[prost(string, tag = "6")] - pub block_hash: String, - /// Graph account sender - #[prost(string, tag = "7")] - pub graph_account: String, -} - -impl RadioPayloadMessage { - pub fn new( - identifier: String, - content: String, - nonce: i64, - network: String, - block_number: u64, - block_hash: String, - graph_account: String, - ) -> Self { - RadioPayloadMessage { - identifier, - content, - nonce, - network, - block_number, - block_hash, - graph_account, - } - } - - pub fn build( - identifier: String, - content: String, - nonce: i64, - network: NetworkName, - block_number: u64, - block_hash: String, - graph_account: String, - ) -> Self { - RadioPayloadMessage::new( - identifier, - content, - nonce, - network.to_string(), - block_number, - block_hash, - graph_account, - ) - } - - pub fn payload_content(&self) -> String { - self.content.clone() - } - - // Check for the valid hash between local graph node and gossip - pub async fn valid_hash(&self, graph_node_endpoint: &str) -> Result<&Self, BuildMessageError> { - let block_hash: String = query_graph_node_network_block_hash( - graph_node_endpoint, - &self.network, - self.block_number, - ) - .await - .map_err(BuildMessageError::FieldDerivations)?; - - trace!( - network = tracing::field::debug(self.network.clone()), - block_number = self.block_number, - block_hash = block_hash, - "Queried block hash from graph node", - ); - - if self.block_hash == block_hash { - Ok(self) - } else { - Err(BuildMessageError::InvalidFields(anyhow::anyhow!( - "Message hash ({}) differ from trusted provider response ({}), drop message", - self.block_hash, - block_hash - ))) - } - } - - /// Check duplicated fields: payload message has duplicated fields with GraphcastMessage, the values must be the same - pub fn valid_outer(&self, outer: &GraphcastMessage) -> Result<&Self, BuildMessageError> { - let nonce_check = self.nonce == outer.nonce; - let account_check = self.graph_account == outer.graph_account; - let identifier_check = self.identifier == outer.identifier; - - if nonce_check && account_check && identifier_check { - Ok(self) - } else { - Err(BuildMessageError::InvalidFields(anyhow::anyhow!( - "Radio message wrapped by inconsistent GraphcastMessage: {:#?} <- {:#?}\nNonce check: {:#?}\nAccount check: {:#?}\nIdentifier check: {:#?}", - &self, - &outer, - nonce_check, - account_check, - identifier_check - ))) - } - } - - /// Make sure all messages stored are valid - pub async fn validity_check( - &self, - gc_msg: &GraphcastMessage, - graph_node_endpoint: &str, - ) -> Result<&Self, BuildMessageError> { - let _ = self - .valid_hash(graph_node_endpoint) - .await - .map(|radio_msg| radio_msg.valid_outer(gc_msg))??; - Ok(self) - } + "subgraph-radio" } /// Generate default topics that is operator address resolved to indexer address @@ -306,10 +173,13 @@ impl ErrorExtensions for OperationError { #[cfg(test)] mod tests { + use graphcast_sdk::graphcast_agent::message_typing::GraphcastMessage; + use crate::messages::poi::PublicPoiMessage; + use super::*; - fn simple_message() -> RadioPayloadMessage { - RadioPayloadMessage::new( + fn simple_message() -> PublicPoiMessage { + PublicPoiMessage::new( String::from("QmHash"), String::from("0x0"), 1, @@ -320,7 +190,7 @@ mod tests { ) } - fn wrong_outer_message(payload: RadioPayloadMessage) -> GraphcastMessage { + fn wrong_outer_message(payload: PublicPoiMessage) -> GraphcastMessage { GraphcastMessage { identifier: String::from("ping-pong-content-topic"), payload, @@ -330,7 +200,7 @@ mod tests { } } - fn good_outer_message(payload: RadioPayloadMessage) -> GraphcastMessage { + fn good_outer_message(payload: PublicPoiMessage) -> GraphcastMessage { GraphcastMessage { identifier: payload.identifier.clone(), payload: payload.clone(), diff --git a/poi-radio/src/main.rs b/poi-radio/src/main.rs index 1a556df3..0078b70e 100644 --- a/poi-radio/src/main.rs +++ b/poi-radio/src/main.rs @@ -1,22 +1,17 @@ use dotenv::dotenv; -use once_cell::sync::OnceCell; -use poi_radio::{config::Config, operator::RadioOperator}; -extern crate partial_application; +use poi_radio::{config::Config, operator::RadioOperator, RADIO_OPERATOR}; -/// A global static (singleton) instance of GraphcastAgent. It is useful to ensure that we have only one GraphcastAgent -/// per Radio instance, so that we can keep track of state and more easily test our Radio application. -pub static RADIO_OPERATOR: OnceCell = OnceCell::new(); +extern crate partial_application; #[tokio::main] async fn main() { dotenv().ok(); - // Parse basic configurations let radio_config = Config::args(); // Initialization and pass in for static lifetime throughout the program - let radio_operator = RadioOperator::new(radio_config).await; + let radio_operator = RadioOperator::new(&radio_config).await; // Start separate processes radio_operator.prepare().await; diff --git a/poi-radio/src/messages/mod.rs b/poi-radio/src/messages/mod.rs new file mode 100644 index 00000000..a04439a2 --- /dev/null +++ b/poi-radio/src/messages/mod.rs @@ -0,0 +1,61 @@ +use graphcast_sdk::graphcast_agent::{ + message_typing::GraphcastMessage, waku_handling::WakuHandlingError, +}; +use poi::PublicPoiMessage; +use std::{ + any::Any, + sync::{mpsc, Mutex as SyncMutex}, +}; +use tracing::{error, trace}; +use upgrade::VersionUpgradeMessage; + +pub mod poi; +pub mod upgrade; + +#[derive(Debug, Clone, serde_derive::Deserialize, serde_derive::Serialize)] +pub enum MessageType { + PublicPoi(GraphcastMessage), + VersionUpgrade(GraphcastMessage), +} + +pub fn typed_handler(sender: SyncMutex>, msg: &dyn Any) { + if let Some(Ok(ppoi_message)) = + msg.downcast_ref::, WakuHandlingError>>() + { + trace!( + ppoi_message = tracing::field::debug(&ppoi_message), + "Received Graphcast validated message" + ); + + // let id = ppoi_message.identifier.clone(); + // VALIDATED_MESSAGES.with_label_values(&[&id]).inc(); + + match sender + .lock() + .unwrap() + .send(MessageType::PublicPoi(ppoi_message.clone())) + { + Ok(_) => trace!("Sent received message to radio operator"), + Err(e) => error!("Could not send message to channel: {:#?}", e), + } + } else if let Some(Ok(upgrade_message)) = + msg.downcast_ref::, WakuHandlingError>>() + { + trace!( + upgrade_message = tracing::field::debug(&upgrade_message), + "Received Graphcast validated message" + ); + + // let id = upgrade_message.identifier.clone(); + // VALIDATED_MESSAGES.with_label_values(&[&id]).inc(); + + match sender + .lock() + .unwrap() + .send(MessageType::VersionUpgrade(upgrade_message.clone())) + { + Ok(_) => trace!("Sent upgrade message to radio operator"), + Err(e) => error!("Could not send message to channel: {:#?}", e), + } + } +} diff --git a/poi-radio/src/messages/poi.rs b/poi-radio/src/messages/poi.rs new file mode 100644 index 00000000..dcc6e8b7 --- /dev/null +++ b/poi-radio/src/messages/poi.rs @@ -0,0 +1,301 @@ +use async_graphql::{SimpleObject}; + + +use ethers_contract::EthAbiType; +use ethers_core::types::transaction::eip712::Eip712; +use ethers_derive_eip712::*; + +use prost::Message; +use serde::{Deserialize, Serialize}; + + +use tracing::{trace}; + + +use graphcast_sdk::{ + graphcast_agent::{ + message_typing::{BuildMessageError, GraphcastMessage}, + }, + graphql::{ + client_graph_node::query_graph_node_network_block_hash, + }, + networks::NetworkName, +}; + + + + + +#[derive(Eip712, EthAbiType, Clone, Message, Serialize, Deserialize, PartialEq, SimpleObject)] +#[eip712( + name = "PublicPoiMessage", + version = "0", + chain_id = 1, + verifying_contract = "0xc944e90c64b2c07662a292be6244bdf05cda44a7" +)] +pub struct PublicPoiMessage { + #[prost(string, tag = "1")] + pub identifier: String, + #[prost(string, tag = "2")] + pub content: String, + //TODO: see if timestamp that comes with waku message can be used + /// nonce cached to check against the next incoming message + #[prost(int64, tag = "3")] + pub nonce: i64, + /// blockchain relevant to the message + #[prost(string, tag = "4")] + pub network: String, + /// block relevant to the message + #[prost(uint64, tag = "5")] + pub block_number: u64, + /// block hash generated from the block number + #[prost(string, tag = "6")] + pub block_hash: String, + /// Graph account sender + #[prost(string, tag = "7")] + pub graph_account: String, +} + +impl PublicPoiMessage { + pub fn new( + identifier: String, + content: String, + nonce: i64, + network: String, + block_number: u64, + block_hash: String, + graph_account: String, + ) -> Self { + PublicPoiMessage { + identifier, + content, + nonce, + network, + block_number, + block_hash, + graph_account, + } + } + + pub fn build( + identifier: String, + content: String, + timestamp: i64, + network: NetworkName, + block_number: u64, + block_hash: String, + graph_account: String, + ) -> Self { + PublicPoiMessage::new( + identifier, + content, + timestamp, + network.to_string(), + block_number, + block_hash, + graph_account, + ) + } + + pub fn payload_content(&self) -> String { + self.content.clone() + } + + // Check for the valid hash between local graph node and gossip + pub async fn valid_hash(&self, graph_node_endpoint: &str) -> Result<&Self, BuildMessageError> { + let block_hash: String = query_graph_node_network_block_hash( + graph_node_endpoint, + &self.network, + self.block_number, + ) + .await + .map_err(BuildMessageError::FieldDerivations)?; + + trace!( + network = tracing::field::debug(self.network.clone()), + block_number = self.block_number, + block_hash = block_hash, + "Queried block hash from graph node", + ); + + if self.block_hash == block_hash { + Ok(self) + } else { + Err(BuildMessageError::InvalidFields(anyhow::anyhow!( + "Message hash ({}) differ from trusted provider response ({}), drop message", + self.block_hash, + block_hash + ))) + } + } + + /// Check duplicated fields: payload message has duplicated fields with GraphcastMessage, the values must be the same + pub fn valid_outer(&self, outer: &GraphcastMessage) -> Result<&Self, BuildMessageError> { + if self.nonce == outer.nonce + && self.graph_account == outer.graph_account + && self.identifier == outer.identifier + { + Ok(self) + } else { + Err(BuildMessageError::InvalidFields(anyhow::anyhow!( + "Radio message wrapped by inconsistent GraphcastMessage: {:#?} <- {:#?}\nnonce check: {:#?}\naccount check: {:#?}\nidentifier check: {:#?}", + &self, + &outer, + self.nonce == outer.nonce, + self.graph_account == outer.graph_account, + self.identifier == outer.identifier, + ))) + } + } + + /// Make sure all messages stored are valid + pub async fn validity_check( + &self, + gc_msg: &GraphcastMessage, + graph_node_endpoint: &str, + ) -> Result<&Self, BuildMessageError> { + let _ = self + .valid_hash(graph_node_endpoint) + .await + .map(|radio_msg| radio_msg.valid_outer(gc_msg))??; + Ok(self) + } +} + + + +// #[derive(Eip712, EthAbiType, Clone, Message, Serialize, Deserialize, PartialEq, SimpleObject)] +// #[eip712( +// name = "Graphcast POI Radio", +// version = "0", +// chain_id = 1, +// verifying_contract = "0xc944e90c64b2c07662a292be6244bdf05cda44a7" +// )] +// pub struct RadioPayloadMessage { +// #[prost(string, tag = "1")] +// pub identifier: String, +// #[prost(string, tag = "2")] +// pub content: String, +// //TODO: see if timestamp that comes with waku message can be used +// /// nonce cached to check against the next incoming message +// #[prost(int64, tag = "3")] +// pub nonce: i64, +// /// blockchain relevant to the message +// #[prost(string, tag = "4")] +// pub network: String, +// /// block relevant to the message +// #[prost(uint64, tag = "5")] +// pub block_number: u64, +// /// block hash generated from the block number +// #[prost(string, tag = "6")] +// pub block_hash: String, +// /// Graph account sender +// #[prost(string, tag = "7")] +// pub graph_account: String, +// } + +// impl RadioPayloadMessage { +// pub fn new( +// identifier: String, +// content: String, +// nonce: i64, +// network: String, +// block_number: u64, +// block_hash: String, +// graph_account: String, +// ) -> Self { +// RadioPayloadMessage { +// identifier, +// content, +// nonce, +// network, +// block_number, +// block_hash, +// graph_account, +// } +// } + +// pub fn build( +// identifier: String, +// content: String, +// nonce: i64, +// network: NetworkName, +// block_number: u64, +// block_hash: String, +// graph_account: String, +// ) -> Self { +// RadioPayloadMessage::new( +// identifier, +// content, +// nonce, +// network.to_string(), +// block_number, +// block_hash, +// graph_account, +// ) +// } + +// pub fn payload_content(&self) -> String { +// self.content.clone() +// } + +// // Check for the valid hash between local graph node and gossip +// pub async fn valid_hash(&self, graph_node_endpoint: &str) -> Result<&Self, BuildMessageError> { +// let block_hash: String = query_graph_node_network_block_hash( +// graph_node_endpoint, +// &self.network, +// self.block_number, +// ) +// .await +// .map_err(BuildMessageError::FieldDerivations)?; + +// trace!( +// network = tracing::field::debug(self.network.clone()), +// block_number = self.block_number, +// block_hash = block_hash, +// "Queried block hash from graph node", +// ); + +// if self.block_hash == block_hash { +// Ok(self) +// } else { +// Err(BuildMessageError::InvalidFields(anyhow::anyhow!( +// "Message hash ({}) differ from trusted provider response ({}), drop message", +// self.block_hash, +// block_hash +// ))) +// } +// } + +// /// Check duplicated fields: payload message has duplicated fields with GraphcastMessage, the values must be the same +// pub fn valid_outer(&self, outer: &GraphcastMessage) -> Result<&Self, BuildMessageError> { +// let nonce_check = self.nonce == outer.nonce; +// let account_check = self.graph_account == outer.graph_account; +// let identifier_check = self.identifier == outer.identifier; + +// if nonce_check && account_check && identifier_check { +// Ok(self) +// } else { +// Err(BuildMessageError::InvalidFields(anyhow::anyhow!( +// "Radio message wrapped by inconsistent GraphcastMessage: {:#?} <- {:#?}\nNonce check: {:#?}\nAccount check: {:#?}\nIdentifier check: {:#?}", +// &self, +// &outer, +// nonce_check, +// account_check, +// identifier_check +// ))) +// } +// } + +// /// Make sure all messages stored are valid +// pub async fn validity_check( +// &self, +// gc_msg: &GraphcastMessage, +// graph_node_endpoint: &str, +// ) -> Result<&Self, BuildMessageError> { +// let _ = self +// .valid_hash(graph_node_endpoint) +// .await +// .map(|radio_msg| radio_msg.valid_outer(gc_msg))??; +// Ok(self) +// } \ No newline at end of file diff --git a/poi-radio/src/messages/upgrade.rs b/poi-radio/src/messages/upgrade.rs new file mode 100644 index 00000000..677295b5 --- /dev/null +++ b/poi-radio/src/messages/upgrade.rs @@ -0,0 +1,141 @@ +use async_graphql::{SimpleObject}; + +use chrono::Utc; +use ethers_contract::EthAbiType; +use ethers_core::types::transaction::eip712::Eip712; +use ethers_derive_eip712::*; + +use prost::Message; +use serde::{Deserialize, Serialize}; + + + + +use graphcast_sdk::{ + graphql::{ + client_graph_account::owned_subgraphs, + }, +}; +use graphcast_sdk::{ + graphcast_agent::{ + message_typing::{BuildMessageError, GraphcastMessage}, + }, + networks::NetworkName, +}; + + + +#[derive(Eip712, EthAbiType, Clone, Message, Serialize, Deserialize, PartialEq, SimpleObject)] +#[eip712( + name = "VersionUpgradeMessage", + version = "0", + chain_id = 1, + verifying_contract = "0xc944e90c64b2c07662a292be6244bdf05cda44a7" +)] +pub struct VersionUpgradeMessage { + // identify through the current subgraph deployment + #[prost(string, tag = "1")] + pub identifier: String, + // new version of the subgraph has a new deployment hash + #[prost(string, tag = "2")] + pub new_hash: String, + /// subgraph id shared by both versions of the subgraph deployment + #[prost(string, tag = "6")] + pub subgraph_id: String, + /// nonce cached to check against the next incoming message + #[prost(int64, tag = "3")] + pub nonce: i64, + /// blockchain relevant to the message + #[prost(string, tag = "4")] + pub network: String, + /// estimated timestamp for the usage to switch to the new version + #[prost(int64, tag = "5")] + pub migrate_time: i64, + /// Graph account sender - expect the sender to be subgraph owner + #[prost(string, tag = "7")] + pub graph_account: String, +} + +impl VersionUpgradeMessage { + pub fn new( + identifier: String, + new_hash: String, + subgraph_id: String, + nonce: i64, + network: String, + migrate_time: i64, + graph_account: String, + ) -> Self { + VersionUpgradeMessage { + identifier, + new_hash, + subgraph_id, + nonce, + network, + migrate_time, + graph_account, + } + } + + pub fn build( + identifier: String, + new_hash: String, + subgraph_id: String, + network: NetworkName, + migrate_time: i64, + graph_account: String, + ) -> Self { + VersionUpgradeMessage::new( + identifier, + new_hash, + subgraph_id, + Utc::now().timestamp(), + network.to_string(), + migrate_time, + graph_account, + ) + } + + /// Check duplicated fields: payload message has duplicated fields with GraphcastMessage, the values must be the same + pub fn valid_outer(&self, outer: &GraphcastMessage) -> Result<&Self, BuildMessageError> { + if self.nonce == outer.nonce + && self.graph_account == outer.graph_account + && self.identifier == outer.identifier + { + Ok(self) + } else { + Err(BuildMessageError::InvalidFields(anyhow::anyhow!( + "Radio message wrapped by inconsistent GraphcastMessage: {:#?} <- {:#?}", + &self, + &outer, + ))) + } + } + + /// Check message from valid sender: check for ownership for subgraph-owner messages + pub async fn valid_owner(&self, network_subgraph: &str) -> Result<&Self, BuildMessageError> { + let subgraphs = owned_subgraphs(network_subgraph, &self.graph_account) + .await + .map_err(BuildMessageError::FieldDerivations)?; + if !subgraphs.contains(&self.identifier) { + return Err(BuildMessageError::InvalidFields(anyhow::anyhow!(format!( + "Verified account failed to be subgraph owner. Verified account: {:#?}", + self.graph_account + )))); + } + Ok(self) + } + + /// Make sure all messages stored are valid + pub async fn validity_check( + &self, + gc_msg: &GraphcastMessage, + graph_network: &str, + ) -> Result<&Self, BuildMessageError> { + let _ = self + .valid_owner(graph_network) + .await + .map(|radio_msg| radio_msg.valid_outer(gc_msg))??; + Ok(self) + } +} diff --git a/poi-radio/src/operator/attestation.rs b/poi-radio/src/operator/attestation.rs index 89f0aebe..b57f6ad0 100644 --- a/poi-radio/src/operator/attestation.rs +++ b/poi-radio/src/operator/attestation.rs @@ -18,11 +18,12 @@ use graphcast_sdk::{ }; use crate::{ + messages::poi::PublicPoiMessage, metrics::{ ACTIVE_INDEXERS, DIVERGING_SUBGRAPHS, INDEXER_COUNT_BY_NPOI, LOCAL_NPOIS_TO_COMPARE, }, state::PersistedState, - OperationError, RadioPayloadMessage, + OperationError, }; use super::Notifier; @@ -108,8 +109,8 @@ pub fn attestations_to_vec(attestations: &LocalAttestationsMap) -> Vec>, +pub async fn process_ppoi_message( + messages: Vec>, callbook: &CallBook, ) -> Result { let mut remote_attestations: RemoteAttestationsMap = HashMap::new(); diff --git a/poi-radio/src/operator/mod.rs b/poi-radio/src/operator/mod.rs index bd3161b0..40725785 100644 --- a/poi-radio/src/operator/mod.rs +++ b/poi-radio/src/operator/mod.rs @@ -1,4 +1,5 @@ use derive_getters::Getters; + use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{mpsc, Arc, Mutex as SyncMutex}; use std::time::Duration; @@ -13,13 +14,16 @@ use graphcast_sdk::{ }; use crate::chainhead_block_str; +use crate::messages::poi::PublicPoiMessage; + + use crate::metrics::handle_serve_metrics; use crate::operator::attestation::log_gossip_summary; use crate::operator::attestation::process_comparison_results; use crate::server::run_server; use crate::state::PersistedState; +use crate::GRAPHCAST_AGENT; use crate::{config::Config, metrics::CACHED_MESSAGES}; -use crate::{RadioPayloadMessage, GRAPHCAST_AGENT}; use self::notifier::Notifier; @@ -85,7 +89,7 @@ pub struct RadioOperator { impl RadioOperator { /// Create a radio operator with radio configurations, persisted data, /// graphcast agent, and control flow - pub async fn new(config: Config) -> RadioOperator { + pub async fn new(config: &Config) -> RadioOperator { debug!("Initializing Radio operator"); let _wallet = build_wallet( config @@ -108,10 +112,10 @@ impl RadioOperator { debug!("Set global static instance of graphcast_agent"); _ = GRAPHCAST_AGENT.set(graphcast_agent.clone()); - let notifier = Notifier::from_config(&config); + let notifier = Notifier::from_config(config); RadioOperator { - config, + config: config.clone(), persisted_state, graphcast_agent, notifier, @@ -141,8 +145,11 @@ impl RadioOperator { .update_content_topics(topics.clone()) .await; - let (sender, receiver) = mpsc::channel::>(); - let handler = RadioOperator::radio_msg_handler(SyncMutex::new(sender)); + // let (poi_sender, poi_receiver) = mpsc::channel::>(); + // let (version_sender, version_receiver) = mpsc::channel::>(); + + let (sender, receiver) = mpsc::channel::>(); + let handler = RadioOperator::radio_msg_handler::(SyncMutex::new(sender)); GRAPHCAST_AGENT .get() .unwrap() @@ -152,29 +159,45 @@ impl RadioOperator { let config = self.config.clone(); + let graph_node = self.config.graph_node_endpoint().clone(); tokio::spawn(async move { for msg in receiver { trace!( "Radio operator received a validated message from Graphcast agent: {:#?}", msg ); + // let identifier = msg.identifier.clone(); + + // let is_valid = msg + // .validity_check(&msg, config.graph_node_endpoint()) + // .await; + + // if is_valid.is_ok() { + // state_ref.add_remote_message(msg.clone()); + // } + + // CACHED_MESSAGES.with_label_values(&[&identifier]).set( + // state_ref + // .remote_messages() + // .iter() + // .filter(|m| m.identifier == identifier) + // .collect::>>() + // .len() + // .try_into() + // .unwrap(), + // ); let identifier = msg.identifier.clone(); - let is_valid = msg - .payload - .validity_check(&msg, config.graph_node_endpoint()) - .await; - + let is_valid = msg.payload.validity_check(&msg, &graph_node).await; if is_valid.is_ok() { state_ref.add_remote_message(msg.clone()); } - CACHED_MESSAGES.with_label_values(&[&identifier]).set( state_ref .remote_messages() .iter() .filter(|m| m.identifier == identifier) - .collect::>>() + .collect::>>() .len() .try_into() .unwrap(), @@ -182,6 +205,27 @@ impl RadioOperator { } }); } + // for msg in receiver { + // // + // trace!( + // "Radio operator received a validated message from Graphcast agent: {:#?}", + // msg + // ); + + // // let identifier = msg.identifier.clone(); + // // state_ref.add_remote_message(msg.clone()); + // // CACHED_MESSAGES.with_label_values(&[&identifier]).set( + // // state_ref + // // .remote_messages() + // // .iter() + // // .filter(|m| m.identifier == identifier) + // // .collect::>>() + // // .len() + // // .try_into() + // // .unwrap(), + // // ); + // } + // }); pub fn graphcast_agent(&self) -> &GraphcastAgent { &self.graphcast_agent @@ -344,6 +388,11 @@ impl RadioOperator { let identifiers = self.graphcast_agent().content_identifiers().await; let blocks_str = chainhead_block_str(&network_chainhead_blocks); + trace!( + state = tracing::field::debug(&self.state()), + "current state", + ); + let comparison_res = self.compare_poi( identifiers.clone(), ) diff --git a/poi-radio/src/operator/operation.rs b/poi-radio/src/operator/operation.rs index 5d09a038..4f26d1c9 100644 --- a/poi-radio/src/operator/operation.rs +++ b/poi-radio/src/operator/operation.rs @@ -1,6 +1,8 @@ use autometrics::autometrics; use chrono::Utc; use graphcast_sdk::callbook::CallBook; +use prost::Message; +use std::any::Any; use std::cmp::max; use std::collections::HashMap; use std::sync::{mpsc, Arc, Mutex as SyncMutex}; @@ -17,7 +19,9 @@ use graphcast_sdk::{ BlockPointer, NetworkBlockError, NetworkPointer, }; -use crate::operator::attestation::process_messages; + +use crate::messages::{poi::PublicPoiMessage, upgrade::VersionUpgradeMessage}; +use crate::operator::attestation::process_ppoi_message; use crate::{ metrics::{CACHED_MESSAGES, VALIDATED_MESSAGES}, operator::{ @@ -28,7 +32,7 @@ use crate::{ callbook::CallBookRadioExtensions, RadioOperator, }, - OperationError, RadioPayloadMessage, GRAPHCAST_AGENT, + OperationError, GRAPHCAST_AGENT, }; /// Determine the parameters for messages to send and compare @@ -147,7 +151,7 @@ pub async fn message_send( .block_hash(&network_name.to_string(), message_block) .await .map_err(OperationError::Query)?; - let radio_message = RadioPayloadMessage::build( + let radio_message = PublicPoiMessage::build( id.clone(), content.clone(), nonce, @@ -195,7 +199,7 @@ pub async fn message_comparison( id: String, collect_window_duration: i64, callbook: CallBook, - messages: Vec>, + messages: Vec>, local_attestations: HashMap>, ) -> Result { let time = Utc::now().timestamp(); @@ -226,7 +230,7 @@ pub async fn message_comparison( } }; - let filter_msg: Vec> = messages + let filter_msg: Vec> = messages .iter() .filter(|&m| m.payload.block_number == compare_block && m.nonce <= collect_window_end) .cloned() @@ -240,7 +244,7 @@ pub async fn message_comparison( number_of_messages_matched_to_compare = filter_msg.len(), "Comparison state", ); - let remote_attestations_result = process_messages(filter_msg, &callbook).await; + let remote_attestations_result = process_ppoi_message(filter_msg, &callbook).await; let remote_attestations = match remote_attestations_result { Ok(remote) => { debug!(unique_remote_nPOIs = remote.len(), "Processed messages",); @@ -265,10 +269,22 @@ impl RadioOperator { /// to process them at a later time. This is required because for the processing we use async operations which are not allowed /// in the handler. #[autometrics] - pub fn radio_msg_handler( - sender: SyncMutex>>, - ) -> impl Fn(Result, WakuHandlingError>) { - move |msg: Result, WakuHandlingError>| { + pub fn radio_msg_handler( + poi_sender: SyncMutex>>, + // sender: SyncMutex>>, + ) -> impl Fn(Result, WakuHandlingError>) + // sender: SyncMutex>, + // ) -> impl Fn(&dyn Any) + where + T: Message + + ethers::types::transaction::eip712::Eip712 + + Default + + Clone + + 'static + + async_graphql::OutputType, + { + // move |msg: &dyn Any| { + move |msg: Result, WakuHandlingError>| { // TODO: Handle the error case by incrementing a Prometheus "error" counter if let Ok(msg) = msg { trace!( @@ -278,107 +294,132 @@ impl RadioOperator { let id = msg.identifier.clone(); VALIDATED_MESSAGES.with_label_values(&[&id]).inc(); - match sender.lock().unwrap().send(msg) { - Ok(_) => trace!("Sent received message to radio operator"), - Err(e) => error!("Could not send message to channel, {:#?}", e), - }; + // typed_handler(sender, &msg); + + let any_msg: &dyn Any = &msg; + trace!( + any_msg = tracing::field::debug(any_msg), + "Received Graphcast validated message" + ); + if let Some(ppoi_message) = &any_msg.downcast_ref::>() { + + // let id = any_msg.identifier.clone(); + // VALIDATED_MESSAGES.with_label_values(&[&id]).inc(); + + match poi_sender.lock().unwrap().send((*ppoi_message).clone()) { + Ok(_) => trace!("Sent received public POI message to radio operator"), + Err(e) => error!("Could not send message to channel: {:#?}", e), + } + } else if let Some(Ok(upgrade_message)) = any_msg.downcast_ref::, WakuHandlingError>>() { + trace!( + upgrade_message = tracing::field::debug(&upgrade_message), + "Received Graphcast validated message" + ); + + // // let id = upgrade_message.identifier.clone(); + // // VALIDATED_MESSAGES.with_label_values(&[&id]).inc(); + + // match sender.lock().unwrap().send(MessageType::VersionUpgrade(upgrade_message.clone())) { + // Ok(_) => trace!("Sent upgrade message to radio operator"), + // Err(e) => error!("Could not send message to channel: {:#?}", e), + // } + } //TODO: Make sure CACHED_MESSAGES is updated } } } - /// Construct the message and send it to Graphcast network - #[autometrics(track_concurrency)] - pub async fn create_radio_message( - &self, - id: String, - message_block: u64, - latest_block: BlockPointer, - network_name: NetworkName, - ) -> Result { - trace!( - message_block = message_block, - latest_block = latest_block.number, - "Check message send requirement", - ); - - // Deployment did not sync to message_block - if latest_block.number < message_block { - //TODO: fill in variant in SDK - let err_msg = format!( - "Did not send message for deployment {}: latest_block ({}) syncing status must catch up to the message block ({})", - id.clone(), - latest_block.number, message_block, - ); - trace!(err = err_msg, "Skip send",); - return Err(OperationError::SendTrigger(err_msg)); - }; - - // Skip messages that has been sent before - if self - .state() - .local_attestations() - .get(&id.clone()) - .and_then(|blocks| blocks.get(&message_block)) - .is_some() - { - let err_msg = format!( - "Repeated message for deployment {}, skip sending message for block: {}", - id.clone(), - message_block - ); - trace!(err = err_msg, "Skip send"); - return Err(OperationError::SkipDuplicate(err_msg)); - } - - let block_hash = match self - .config - .callbook() - .block_hash(&network_name.to_string(), message_block) - .await - { - Ok(hash) => hash, - Err(e) => { - let err_msg = format!("Failed to query graph node for the block hash: {e}"); - error!(err = err_msg, "Failed to send message"); - return Err(OperationError::Query(e)); - } - }; - - match self - .config - .callbook() - .query_poi( - id.clone(), - block_hash.clone(), - message_block.try_into().unwrap(), - ) - .await - { - Ok(content) => Ok(RadioPayloadMessage::build( - id.clone(), - content, - Utc::now().timestamp(), - network_name, - message_block, - block_hash, - self.graphcast_agent - .graphcast_identity - .graph_account - .clone(), - )), - Err(e) => { - error!( - err = tracing::field::debug(&e), - "Failed to query message content" - ); - Err(OperationError::Agent( - GraphcastAgentError::QueryResponseError(e), - )) - } - } - } + // /// Construct the message and send it to Graphcast network + // #[autometrics(track_concurrency)] + // pub async fn create_radio_message( + // &self, + // id: String, + // message_block: u64, + // latest_block: BlockPointer, + // network_name: NetworkName, + // ) -> Result { + // trace!( + // message_block = message_block, + // latest_block = latest_block.number, + // "Check message send requirement", + // ); + + // // Deployment did not sync to message_block + // if latest_block.number < message_block { + // //TODO: fill in variant in SDK + // let err_msg = format!( + // "Did not send message for deployment {}: latest_block ({}) syncing status must catch up to the message block ({})", + // id.clone(), + // latest_block.number, message_block, + // ); + // trace!(err = err_msg, "Skip send",); + // return Err(OperationError::SendTrigger(err_msg)); + // }; + + // // Skip messages that has been sent before + // if self + // .state() + // .local_attestations() + // .get(&id.clone()) + // .and_then(|blocks| blocks.get(&message_block)) + // .is_some() + // { + // let err_msg = format!( + // "Repeated message for deployment {}, skip sending message for block: {}", + // id.clone(), + // message_block + // ); + // trace!(err = err_msg, "Skip send"); + // return Err(OperationError::SkipDuplicate(err_msg)); + // } + + // let block_hash = match self + // .config + // .callbook() + // .block_hash(&network_name.to_string(), message_block) + // .await + // { + // Ok(hash) => hash, + // Err(e) => { + // let err_msg = format!("Failed to query graph node for the block hash: {e}"); + // error!(err = err_msg, "Failed to send message"); + // return Err(OperationError::Query(e)); + // } + // }; + + // match self + // .config + // .callbook() + // .query_poi( + // id.clone(), + // block_hash.clone(), + // message_block.try_into().unwrap(), + // ) + // .await + // { + // Ok(content) => Ok(PublicPoiMessage::build( + // id.clone(), + // content, + // network_name, + // message_block, + // block_hash, + // self.graphcast_agent + // .graphcast_identity + // .graph_account + // .clone(), + // )), + // Err(e) => { + // error!( + // err = tracing::field::debug(&e), + // "Failed to query message content" + // ); + // Err(OperationError::Agent( + // GraphcastAgentError::QueryResponseError(e), + // )) + // } + // } + // } pub async fn gossip_poi( &self, @@ -438,11 +479,11 @@ impl RadioOperator { identifiers: Vec, ) -> Vec> { let mut compare_handles = vec![]; - // Update to only process the identifier&compare_block related messages within the collection window + // Additional radio message check happens here since messages are synchronously stored to state cache in msg handler let remote_messages = self .state() - .valid_messages(&self.config.graph_node_endpoint) + .valid_ppoi_messages(&self.config.graph_node_endpoint) .await; for id in identifiers.clone() { diff --git a/poi-radio/src/server/model/mod.rs b/poi-radio/src/server/model/mod.rs index 3de3cf53..a43699ef 100644 --- a/poi-radio/src/server/model/mod.rs +++ b/poi-radio/src/server/model/mod.rs @@ -5,13 +5,13 @@ use thiserror::Error; use crate::{ config::Config, + messages::poi::PublicPoiMessage, operator::attestation::{ - self, attestations_to_vec, compare_attestation, process_messages, Attestation, + self, attestations_to_vec, compare_attestation, process_ppoi_message, Attestation, AttestationEntry, AttestationError, ComparisonResult, ComparisonResultType, LocalAttestationsMap, }, state::PersistedState, - RadioPayloadMessage, }; use graphcast_sdk::{graphcast_agent::message_typing::GraphcastMessage, graphql::QueryError}; @@ -28,7 +28,7 @@ impl QueryRoot { ctx: &Context<'_>, identifier: Option, block: Option, - ) -> Result>, HttpServiceError> { + ) -> Result>, HttpServiceError> { let msgs = ctx .data_unchecked::>() .remote_messages_filtered(&identifier, &block); @@ -237,7 +237,7 @@ impl POIRadioContext { } } - pub fn remote_messages(&self) -> Vec> { + pub fn remote_messages(&self) -> Vec> { self.persisted_state.remote_messages() } @@ -245,7 +245,7 @@ impl POIRadioContext { &self, identifier: &Option, block: &Option, - ) -> Vec> { + ) -> Vec> { let msgs = self.remote_messages(); let filtered = msgs .iter() @@ -288,7 +288,7 @@ impl POIRadioContext { for entry in locals { let deployment_identifier = entry.deployment.clone(); let msgs = self.remote_messages_filtered(&identifier, &block); - let remote_attestations = process_messages(msgs, &config.callbook()) + let remote_attestations = process_ppoi_message(msgs, &config.callbook()) .await .ok() .and_then(|r| { @@ -316,7 +316,7 @@ impl POIRadioContext { /// Filter funciton for Attestations on deployment and block fn filter_remote_messages( - entry: &GraphcastMessage, + entry: &GraphcastMessage, identifier: &Option, block: &Option, ) -> bool { diff --git a/poi-radio/src/state.rs b/poi-radio/src/state.rs index ba1ab64a..db5f5068 100644 --- a/poi-radio/src/state.rs +++ b/poi-radio/src/state.rs @@ -1,13 +1,15 @@ use serde::{Deserialize, Serialize}; -use std::fs; + use std::path::Path; + +use std::fs; use std::sync::{Arc, Mutex as SyncMutex}; use std::{ collections::HashMap, fs::{remove_file, File}, io::{BufReader, Write}, }; -use tracing::{trace, warn}; +use tracing::{info, trace, warn}; use graphcast_sdk::graphcast_agent::message_typing::GraphcastMessage; @@ -15,10 +17,11 @@ use crate::operator::attestation::{ clear_local_attestation, ComparisonResult, ComparisonResultType, }; use crate::operator::notifier::Notifier; -use crate::{operator::attestation::Attestation, RadioPayloadMessage}; + +use crate::{messages::poi::PublicPoiMessage, operator::attestation::Attestation}; type Local = Arc>>>; -type Remote = Arc>>>; +type Remote = Arc>>>; type ComparisonResults = Arc>>; #[derive(Serialize, Deserialize, Clone, Debug)] @@ -86,7 +89,7 @@ impl PersistedState { } /// Getter for remote_messages - pub fn remote_messages(&self) -> Vec> { + pub fn remote_messages(&self) -> Vec> { self.remote_messages.lock().unwrap().clone() } @@ -112,15 +115,15 @@ impl PersistedState { /// Update remote_messages pub async fn update_remote( &mut self, - remote_messages: Vec>, - ) -> Vec> { + remote_messages: Vec>, + ) -> Vec> { self.remote_messages = Arc::new(SyncMutex::new(remote_messages)); self.remote_messages() } /// Add message to remote_messages - /// Generalize RadioPayloadMessage - pub fn add_remote_message(&self, msg: GraphcastMessage) { + /// Generalize PublicPoiMessage + pub fn add_remote_message(&self, msg: GraphcastMessage) { trace!(msg = tracing::field::debug(&msg), "adding remote message"); self.remote_messages.lock().unwrap().push(msg) } @@ -135,10 +138,10 @@ impl PersistedState { .insert(deployment, comparison_result); } - pub async fn valid_messages( + pub async fn valid_ppoi_messages( &mut self, graph_node_endpoint: &str, - ) -> Vec> { + ) -> Vec> { let remote_messages = self.remote_messages(); let mut valid_messages = vec![]; @@ -246,12 +249,18 @@ impl PersistedState { /// Load cache into persisted state pub fn load_cache(path: &str) -> PersistedState { + info!(path, "load cache from path"); let file = match File::open(path) { Ok(f) => f, - Err(_) => { - warn!("No persisted state file provided, create an empty state"); + Err(e) => { + warn!( + err = tracing::field::debug(&e), + "No persisted state file provided, create an empty state" + ); // No state persisted, create new - return PersistedState::new(None, None, None); + let state = PersistedState::new(None, None, None); + state.update_cache(path); + return state; } }; @@ -278,13 +287,17 @@ impl PersistedState { // TODO: panic hook for updating the cache file before exiting the program // /// Set up panic hook to store persisted state -// pub fn panic_hook<'a>(file_path: &str){ +// pub fn panic_hook<'a>(file_path: &str) { // let path = String::from_str(file_path).expect("Invalid file path provided"); // panic::set_hook(Box::new(move |panic_info| panic_cache(panic_info, &path))); // } // pub fn panic_cache(panic_info: &PanicInfo<'_>, file_path: &str) { -// update_cache(file_path); +// RADIO_OPERATOR +// .get() +// .unwrap() +// .state() +// .update_cache(file_path); // // Log panic information and program state // eprintln!("Panic occurred! Panic info: {:?}", panic_info); // } @@ -350,7 +363,7 @@ mod tests { let nonce: i64 = 123321; let block_number: u64 = 0; let block_hash: String = "0xblahh".to_string(); - let radio_msg = RadioPayloadMessage::build( + let radio_msg = PublicPoiMessage::build( hash.clone(), content, nonce, diff --git a/test-runner/src/invalid_sender.rs b/test-runner/src/invalid_sender.rs index 290c4bab..27c4d332 100644 --- a/test-runner/src/invalid_sender.rs +++ b/test-runner/src/invalid_sender.rs @@ -19,7 +19,7 @@ pub async fn invalid_sender_test() { let mut config = test_config(); config.persistence_file_path = Some(store_path.clone()); config.topics = radio_topics.clone(); - config.id_validation = Some(IdentityValidation::RegisteredIndexer); + config.id_validation = IdentityValidation::RegisteredIndexer; let mut test_sender_config = TestSenderConfig { topics: test_sender_topics, diff --git a/test-runner/src/message_handling.rs b/test-runner/src/message_handling.rs index 10ce13cc..8ea95f4a 100644 --- a/test-runner/src/message_handling.rs +++ b/test-runner/src/message_handling.rs @@ -21,6 +21,7 @@ pub async fn send_and_receive_test() { let mut config = test_config(); config.persistence_file_path = Some(store_path.clone()); config.topics = radio_topics.clone(); + config.topic_update_interval = 10; let mut test_sender_config = TestSenderConfig { topics: test_sender_topics, @@ -34,7 +35,7 @@ pub async fn send_and_receive_test() { let process_manager = setup(&config, test_file_name, &mut test_sender_config).await; - sleep(Duration::from_secs(89)).await; + sleep(Duration::from_secs(85)).await; let persisted_state = PersistedState::load_cache(&store_path); debug!("persisted state {:?}", persisted_state); @@ -42,6 +43,11 @@ pub async fn send_and_receive_test() { teardown(process_manager, &store_path); let local_attestations = persisted_state.local_attestations(); + debug!( + "local tattestations {:#?}, \nchecking result: {:#?}", + local_attestations, + !local_attestations.is_empty() + ); let remote_messages = persisted_state.remote_messages(); assert!( diff --git a/test-runner/src/topics.rs b/test-runner/src/topics.rs index 3dad2567..e4e901cb 100644 --- a/test-runner/src/topics.rs +++ b/test-runner/src/topics.rs @@ -25,7 +25,7 @@ pub async fn topics_test() { let mut config = test_config(); config.persistence_file_path = Some(store_path.clone()); config.topics = radio_topics.clone(); - config.topic_update_interval = 90; + config.topic_update_interval = 10; let mut test_sender_config = TestSenderConfig { topics: test_sender_topics, @@ -41,13 +41,23 @@ pub async fn topics_test() { sleep(Duration::from_secs(89)).await; - let persisted_state = PersistedState::load_cache(&store_path); - debug!("persisted state {:?}", persisted_state); + // can be sure that file path is set to Some (after test_config() + let persisted_state = PersistedState::load_cache(&config.persistence_file_path.unwrap()); + debug!( + local_attestations = tracing::field::debug(&persisted_state.local_attestations()), + remote_messages = tracing::field::debug(&persisted_state.remote_messages()), + persisted_state = tracing::field::debug(&persisted_state), + "loaded persisted state" + ); let local_attestations = persisted_state.local_attestations(); let remote_messages = persisted_state.remote_messages(); - debug!("Starting topics_test"); + debug!( + local_attestations = tracing::field::debug(&local_attestations), + remote_messages = tracing::field::debug(&remote_messages), + "Starting topics_test" + ); assert!( !local_attestations.is_empty(), diff --git a/test-sender/src/main.rs b/test-sender/src/main.rs index a9c8899e..938c0e5a 100644 --- a/test-sender/src/main.rs +++ b/test-sender/src/main.rs @@ -11,7 +11,7 @@ use graphcast_sdk::{ init_tracing, networks::NetworkName, }; -use poi_radio::RadioPayloadMessage; +use poi_radio::messages::poi::PublicPoiMessage; use test_utils::{config::TestSenderConfig, dummy_msg::DummyMsg, find_random_udp_port}; use tracing::{error, info}; use waku::{ @@ -86,7 +86,7 @@ async fn start_sender(config: TestSenderConfig) { let radio_payload_clone = config.radio_payload.clone(); match radio_payload_clone.as_deref() { Some("radio_payload_message") => { - let radio_payload = RadioPayloadMessage::build( + let radio_payload = PublicPoiMessage::build( topic.clone(), config.poi.clone().unwrap(), nonce, @@ -99,8 +99,8 @@ async fn start_sender(config: TestSenderConfig) { let graphcast_message = GraphcastMessage::build( &wallet, topic.clone(), - nonce, "0x7e6528e4ce3055e829a32b5dc4450072bac28bc6".to_string(), + nonce, radio_payload, ) .await @@ -124,8 +124,8 @@ async fn start_sender(config: TestSenderConfig) { let graphcast_message = GraphcastMessage::build( &wallet, topic.clone(), - nonce, "0x7e6528e4ce3055e829a32b5dc4450072bac28bc6".to_string(), + timestamp, payload, ) .await diff --git a/test-utils/src/config.rs b/test-utils/src/config.rs index a6ce1db9..39f00b97 100644 --- a/test-utils/src/config.rs +++ b/test-utils/src/config.rs @@ -59,7 +59,7 @@ pub fn test_config() -> Config { discv5_enrs: None, discv5_port: None, filter_protocol: None, - id_validation: Some(IdentityValidation::GraphcastRegistered), + id_validation: IdentityValidation::GraphcastRegistered, topic_update_interval: 600, } } diff --git a/test-utils/src/lib.rs b/test-utils/src/lib.rs index 6d7576db..5629d941 100644 --- a/test-utils/src/lib.rs +++ b/test-utils/src/lib.rs @@ -15,7 +15,7 @@ use graphcast_sdk::graphcast_agent::message_typing::IdentityValidation; use mock_server::{start_mock_server, ServerState}; use poi_radio::{ config::{Config, CoverageLevel}, - RadioPayloadMessage, + messages::poi::PublicPoiMessage, }; use prost::Message; use rand::Rng; @@ -221,20 +221,15 @@ pub fn start_radio(config: &Config) -> Child { .arg("--indexer-address") .arg(&config.indexer_address) .arg("--id-validation") - .arg( - match config - .id_validation - .clone() - .unwrap_or(IdentityValidation::RegisteredIndexer) - { - IdentityValidation::NoCheck => "no-check", - IdentityValidation::ValidAddress => "valid-address", - IdentityValidation::GraphcastRegistered => "graphcast-registered", - IdentityValidation::GraphNetworkAccount => "graph-network-account", - IdentityValidation::RegisteredIndexer => "registered-indexer", - IdentityValidation::Indexer => "indexer", - }, - ) + .arg(match config.id_validation { + IdentityValidation::NoCheck => "no-check", + IdentityValidation::ValidAddress => "valid-address", + IdentityValidation::GraphcastRegistered => "graphcast-registered", + IdentityValidation::GraphNetworkAccount => "graph-network-account", + IdentityValidation::RegisteredIndexer => "registered-indexer", + IdentityValidation::Indexer => "indexer", + IdentityValidation::SubgraphStaker => "subgraph-staker", + }) .spawn() .expect("Failed to start command") } @@ -276,7 +271,7 @@ where && msg1.signature == msg2.signature } -pub fn payloads_are_equal(payload1: &RadioPayloadMessage, payload2: &RadioPayloadMessage) -> bool { +pub fn payloads_are_equal(payload1: &PublicPoiMessage, payload2: &PublicPoiMessage) -> bool { payload1.identifier == payload2.identifier && payload1.content == payload2.content && payload1.network == payload2.network From 1702aaa79c08199ae403974c2c12856f0a536c20 Mon Sep 17 00:00:00 2001 From: hopeyen Date: Tue, 11 Jul 2023 18:03:48 -0500 Subject: [PATCH 2/7] refactor: radio message decode and handle multiple types --- Cargo.lock | 54 +++++++- poi-radio/Cargo.toml | 4 +- poi-radio/benches/attestations.rs | 6 +- poi-radio/src/config.rs | 13 +- poi-radio/src/lib.rs | 29 ++--- poi-radio/src/messages/poi.rs | 169 ++------------------------ poi-radio/src/messages/upgrade.rs | 27 ++-- poi-radio/src/operator/attestation.rs | 11 +- poi-radio/src/operator/mod.rs | 169 ++++++++++++-------------- poi-radio/src/operator/notifier.rs | 2 +- poi-radio/src/operator/operation.rs | 166 +------------------------ poi-radio/src/state.rs | 5 +- test-runner/Cargo.toml | 3 +- test-sender/Cargo.toml | 3 +- test-sender/src/main.rs | 15 ++- test-utils/Cargo.toml | 3 +- test-utils/src/config.rs | 2 +- 17 files changed, 184 insertions(+), 497 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e47905ee..e05914c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -300,9 +300,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.70" +version = "0.1.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79fa67157abdfd688a259b6648808757db9347af834624f27ec646da976aee5d" +checksum = "a564d521dd56509c4c47480d00b80ee55f7e385ae48db5744c67ad50c92d2ebf" dependencies = [ "proc-macro2", "quote", @@ -2294,7 +2294,6 @@ dependencies = [ [[package]] name = "graphcast-sdk" version = "0.3.4" -source = "git+https://github.com/graphops/graphcast-sdk#d0e383d06b94cc27cc3f0e00744443cc7a98f8b6" dependencies = [ "anyhow", "async-graphql", @@ -3399,6 +3398,54 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "one-shot" +version = "0.3.6" +dependencies = [ + "anyhow", + "async-graphql", + "async-graphql-axum", + "autometrics", + "axum 0.5.17", + "cargo-husky", + "chrono", + "clap", + "derive-getters", + "dotenv", + "ethers", + "ethers-contract", + "ethers-core 2.0.7", + "ethers-derive-eip712", + "graphcast-sdk", + "graphql_client 0.9.0", + "hex", + "metrics", + "metrics-exporter-prometheus", + "num-bigint", + "num-traits", + "once_cell", + "opentelemetry", + "partial_application", + "poi-radio", + "prometheus", + "prost", + "rand 0.8.5", + "regex", + "reqwest", + "secp256k1 0.25.0", + "serde", + "serde_derive", + "serde_json", + "sha3", + "thiserror", + "tokio", + "tower-http 0.4.1", + "tracing", + "tracing-opentelemetry", + "tracing-subscriber", + "wiremock", +] + [[package]] name = "oorandom" version = "11.1.3" @@ -3837,6 +3884,7 @@ dependencies = [ "anyhow", "async-graphql", "async-graphql-axum", + "async-trait", "autometrics", "axum 0.5.17", "cargo-husky", diff --git a/poi-radio/Cargo.toml b/poi-radio/Cargo.toml index 7231b20e..ba6957fc 100644 --- a/poi-radio/Cargo.toml +++ b/poi-radio/Cargo.toml @@ -10,7 +10,8 @@ keywords = ["graphprotocol", "data-integrity", "Indexer", "waku", "p2p"] categories = ["network-programming", "web-programming::http-client"] [dependencies] -graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk" } +# graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", rev = "f39cb28" } +graphcast-sdk = { package = "graphcast-sdk", path = "../../graphcast-rs" } prost = "0.11" once_cell = "1.17" chrono = "0.4" @@ -51,6 +52,7 @@ prometheus = "0.13.3" tower-http = { version = "0.4.0", features = ["trace", "cors"] } async-graphql = "4.0.16" async-graphql-axum = "4.0.16" +async-trait = "0.1.71" metrics = "0.20.1" metrics-exporter-prometheus = "0.11.0" opentelemetry = { version = "0.18.0", features = ["rt-tokio"] } diff --git a/poi-radio/benches/attestations.rs b/poi-radio/benches/attestations.rs index 809dd52b..99dd347a 100644 --- a/poi-radio/benches/attestations.rs +++ b/poi-radio/benches/attestations.rs @@ -6,10 +6,10 @@ mod attestation { use criterion::{black_box, criterion_group, Criterion}; use graphcast_sdk::graphcast_agent::message_typing::GraphcastMessage; use poi_radio::{ + messages::poi::PublicPoiMessage, operator::attestation::{ compare_attestations, local_comparison_point, update_blocks, Attestation, }, - RadioPayloadMessage, }; use std::collections::HashMap; @@ -140,12 +140,12 @@ mod attestation { }); } - pub fn test_msg_vec() -> Vec> { + pub fn test_msg_vec() -> Vec> { vec![GraphcastMessage { identifier: String::from("hash"), nonce: 2, graph_account: String::from("0x7e6528e4ce3055e829a32b5dc4450072bac28bc6"), - payload: RadioPayloadMessage { + payload: PublicPoiMessage { identifier: String::from("hash"), content: String::from("awesome-npoi"), nonce: 2, diff --git a/poi-radio/src/config.rs b/poi-radio/src/config.rs index ed1920a9..aea976bb 100644 --- a/poi-radio/src/config.rs +++ b/poi-radio/src/config.rs @@ -6,8 +6,7 @@ use graphcast_sdk::{ build_wallet, callbook::CallBook, graphcast_agent::{ - message_typing::IdentityValidation, GraphcastAgent, GraphcastAgentConfig, - GraphcastAgentError, + message_typing::IdentityValidation, GraphcastAgentConfig, GraphcastAgentError, }, graphql::{ client_network::query_network_subgraph, client_registry::query_registry, QueryError, @@ -286,6 +285,7 @@ pub struct Config { long, value_name = "ID_VALIDATION", value_enum, + default_value = "registered-indexer", env = "ID_VALIDATION", help = "Identity validaiton mechanism for message signers", long_help = "Identity validaiton mechanism for message signers\n @@ -407,16 +407,11 @@ impl Config { } } - pub async fn create_graphcast_agent(&self) -> Result { - let config = self.to_graphcast_agent_config().await.unwrap(); - GraphcastAgent::new(config).await - } - pub fn callbook(&self) -> CallBook { CallBook::new( - self.graph_node_endpoint.clone(), self.registry_subgraph.clone(), - Some(self.network_subgraph.clone()), + self.network_subgraph.clone(), + Some(self.graph_node_endpoint.clone()), ) } diff --git a/poi-radio/src/lib.rs b/poi-radio/src/lib.rs index c75bf9e2..61d29a23 100644 --- a/poi-radio/src/lib.rs +++ b/poi-radio/src/lib.rs @@ -1,8 +1,6 @@ use async_graphql::{Error, ErrorExtensions}; use autometrics::autometrics; -use ethers_contract::EthAbiType; -use ethers_core::types::transaction::eip712::Eip712; -use ethers_derive_eip712::*; + use once_cell::sync::OnceCell; use std::{ collections::HashMap, @@ -12,24 +10,15 @@ use std::{ }, }; use tokio::signal; -use tracing::{error}; - +use tracing::error; use graphcast_sdk::{ - graphcast_agent::GraphcastAgentError, - graphql::{ - client_graph_node::get_indexing_statuses, QueryError, - }, + graphcast_agent::GraphcastAgent, graphql::client_network::query_network_subgraph, + networks::NetworkName, BlockPointer, }; use graphcast_sdk::{ - graphcast_agent::{ - GraphcastAgent, - }, - graphql::{ - client_network::query_network_subgraph, - }, - networks::NetworkName, - BlockPointer, + graphcast_agent::GraphcastAgentError, + graphql::{client_graph_node::get_indexing_statuses, QueryError}, }; use crate::operator::{attestation::AttestationError, RadioOperator}; @@ -51,7 +40,7 @@ pub static RADIO_OPERATOR: OnceCell = OnceCell::new(); pub static GRAPHCAST_AGENT: OnceCell> = OnceCell::new(); pub fn radio_name() -> &'static str { - "subgraph-radio" + "poi-radio" } /// Generate default topics that is operator address resolved to indexer address @@ -173,10 +162,8 @@ impl ErrorExtensions for OperationError { #[cfg(test)] mod tests { - use graphcast_sdk::graphcast_agent::message_typing::GraphcastMessage; use crate::messages::poi::PublicPoiMessage; - - use super::*; + use graphcast_sdk::graphcast_agent::message_typing::GraphcastMessage; fn simple_message() -> PublicPoiMessage { PublicPoiMessage::new( diff --git a/poi-radio/src/messages/poi.rs b/poi-radio/src/messages/poi.rs index dcc6e8b7..9b775482 100644 --- a/poi-radio/src/messages/poi.rs +++ b/poi-radio/src/messages/poi.rs @@ -1,30 +1,15 @@ -use async_graphql::{SimpleObject}; - - +use async_graphql::SimpleObject; use ethers_contract::EthAbiType; use ethers_core::types::transaction::eip712::Eip712; use ethers_derive_eip712::*; - -use prost::Message; -use serde::{Deserialize, Serialize}; - - -use tracing::{trace}; - - use graphcast_sdk::{ - graphcast_agent::{ - message_typing::{BuildMessageError, GraphcastMessage}, - }, - graphql::{ - client_graph_node::query_graph_node_network_block_hash, - }, + graphcast_agent::message_typing::{BuildMessageError, GraphcastMessage}, + graphql::client_graph_node::query_graph_node_network_block_hash, networks::NetworkName, }; - - - - +use prost::Message; +use serde::{Deserialize, Serialize}; +use tracing::trace; #[derive(Eip712, EthAbiType, Clone, Message, Serialize, Deserialize, PartialEq, SimpleObject)] #[eip712( @@ -80,7 +65,7 @@ impl PublicPoiMessage { pub fn build( identifier: String, content: String, - timestamp: i64, + nonce: i64, network: NetworkName, block_number: u64, block_hash: String, @@ -89,7 +74,7 @@ impl PublicPoiMessage { PublicPoiMessage::new( identifier, content, - timestamp, + nonce, network.to_string(), block_number, block_hash, @@ -161,141 +146,3 @@ impl PublicPoiMessage { Ok(self) } } - - - -// #[derive(Eip712, EthAbiType, Clone, Message, Serialize, Deserialize, PartialEq, SimpleObject)] -// #[eip712( -// name = "Graphcast POI Radio", -// version = "0", -// chain_id = 1, -// verifying_contract = "0xc944e90c64b2c07662a292be6244bdf05cda44a7" -// )] -// pub struct RadioPayloadMessage { -// #[prost(string, tag = "1")] -// pub identifier: String, -// #[prost(string, tag = "2")] -// pub content: String, -// //TODO: see if timestamp that comes with waku message can be used -// /// nonce cached to check against the next incoming message -// #[prost(int64, tag = "3")] -// pub nonce: i64, -// /// blockchain relevant to the message -// #[prost(string, tag = "4")] -// pub network: String, -// /// block relevant to the message -// #[prost(uint64, tag = "5")] -// pub block_number: u64, -// /// block hash generated from the block number -// #[prost(string, tag = "6")] -// pub block_hash: String, -// /// Graph account sender -// #[prost(string, tag = "7")] -// pub graph_account: String, -// } - -// impl RadioPayloadMessage { -// pub fn new( -// identifier: String, -// content: String, -// nonce: i64, -// network: String, -// block_number: u64, -// block_hash: String, -// graph_account: String, -// ) -> Self { -// RadioPayloadMessage { -// identifier, -// content, -// nonce, -// network, -// block_number, -// block_hash, -// graph_account, -// } -// } - -// pub fn build( -// identifier: String, -// content: String, -// nonce: i64, -// network: NetworkName, -// block_number: u64, -// block_hash: String, -// graph_account: String, -// ) -> Self { -// RadioPayloadMessage::new( -// identifier, -// content, -// nonce, -// network.to_string(), -// block_number, -// block_hash, -// graph_account, -// ) -// } - -// pub fn payload_content(&self) -> String { -// self.content.clone() -// } - -// // Check for the valid hash between local graph node and gossip -// pub async fn valid_hash(&self, graph_node_endpoint: &str) -> Result<&Self, BuildMessageError> { -// let block_hash: String = query_graph_node_network_block_hash( -// graph_node_endpoint, -// &self.network, -// self.block_number, -// ) -// .await -// .map_err(BuildMessageError::FieldDerivations)?; - -// trace!( -// network = tracing::field::debug(self.network.clone()), -// block_number = self.block_number, -// block_hash = block_hash, -// "Queried block hash from graph node", -// ); - -// if self.block_hash == block_hash { -// Ok(self) -// } else { -// Err(BuildMessageError::InvalidFields(anyhow::anyhow!( -// "Message hash ({}) differ from trusted provider response ({}), drop message", -// self.block_hash, -// block_hash -// ))) -// } -// } - -// /// Check duplicated fields: payload message has duplicated fields with GraphcastMessage, the values must be the same -// pub fn valid_outer(&self, outer: &GraphcastMessage) -> Result<&Self, BuildMessageError> { -// let nonce_check = self.nonce == outer.nonce; -// let account_check = self.graph_account == outer.graph_account; -// let identifier_check = self.identifier == outer.identifier; - -// if nonce_check && account_check && identifier_check { -// Ok(self) -// } else { -// Err(BuildMessageError::InvalidFields(anyhow::anyhow!( -// "Radio message wrapped by inconsistent GraphcastMessage: {:#?} <- {:#?}\nNonce check: {:#?}\nAccount check: {:#?}\nIdentifier check: {:#?}", -// &self, -// &outer, -// nonce_check, -// account_check, -// identifier_check -// ))) -// } -// } - -// /// Make sure all messages stored are valid -// pub async fn validity_check( -// &self, -// gc_msg: &GraphcastMessage, -// graph_node_endpoint: &str, -// ) -> Result<&Self, BuildMessageError> { -// let _ = self -// .valid_hash(graph_node_endpoint) -// .await -// .map(|radio_msg| radio_msg.valid_outer(gc_msg))??; -// Ok(self) -// } \ No newline at end of file diff --git a/poi-radio/src/messages/upgrade.rs b/poi-radio/src/messages/upgrade.rs index 677295b5..1983fefe 100644 --- a/poi-radio/src/messages/upgrade.rs +++ b/poi-radio/src/messages/upgrade.rs @@ -1,29 +1,15 @@ -use async_graphql::{SimpleObject}; +use async_graphql::SimpleObject; -use chrono::Utc; use ethers_contract::EthAbiType; use ethers_core::types::transaction::eip712::Eip712; use ethers_derive_eip712::*; - -use prost::Message; -use serde::{Deserialize, Serialize}; - - - - +use graphcast_sdk::graphql::client_graph_account::owned_subgraphs; use graphcast_sdk::{ - graphql::{ - client_graph_account::owned_subgraphs, - }, -}; -use graphcast_sdk::{ - graphcast_agent::{ - message_typing::{BuildMessageError, GraphcastMessage}, - }, + graphcast_agent::message_typing::{BuildMessageError, GraphcastMessage}, networks::NetworkName, }; - - +use prost::Message; +use serde::{Deserialize, Serialize}; #[derive(Eip712, EthAbiType, Clone, Message, Serialize, Deserialize, PartialEq, SimpleObject)] #[eip712( @@ -80,6 +66,7 @@ impl VersionUpgradeMessage { pub fn build( identifier: String, new_hash: String, + timestamp: i64, subgraph_id: String, network: NetworkName, migrate_time: i64, @@ -89,7 +76,7 @@ impl VersionUpgradeMessage { identifier, new_hash, subgraph_id, - Utc::now().timestamp(), + timestamp, network.to_string(), migrate_time, graph_account, diff --git a/poi-radio/src/operator/attestation.rs b/poi-radio/src/operator/attestation.rs index b57f6ad0..28b4c420 100644 --- a/poi-radio/src/operator/attestation.rs +++ b/poi-radio/src/operator/attestation.rs @@ -199,15 +199,10 @@ pub fn combine_senders(attestations: &[Attestation]) -> Vec { /// If they don't exist, then return default value that shall never be validated to trigger pub fn local_comparison_point( local_attestations: &LocalAttestationsMap, - remote_messages: &Vec>, + remote_messages: &[GraphcastMessage], id: String, collect_window_duration: i64, ) -> Option<(u64, i64)> { - debug!( - local = tracing::field::debug(&local_attestations), - remote_messages = tracing::field::debug(&remote_messages), - "find local comparison point" - ); if let Some(blocks_map) = local_attestations.get(&id) { // Find the attestaion by the smallest block let remote_blocks = remote_messages @@ -1020,12 +1015,12 @@ mod tests { assert_eq!(local.lock().unwrap().get("hash2").unwrap().len(), 3); } - pub fn test_msg_vec() -> Vec> { + pub fn test_msg_vec() -> Vec> { vec![GraphcastMessage { identifier: String::from("hash"), nonce: 2, graph_account: String::from("0x7e6528e4ce3055e829a32b5dc4450072bac28bc6"), - payload: RadioPayloadMessage { + payload: PublicPoiMessage { identifier: String::from("hash"), content: String::from("awesome-npoi"), nonce: 2, diff --git a/poi-radio/src/operator/mod.rs b/poi-radio/src/operator/mod.rs index 40725785..e6da11fb 100644 --- a/poi-radio/src/operator/mod.rs +++ b/poi-radio/src/operator/mod.rs @@ -1,9 +1,9 @@ use derive_getters::Getters; - -use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::{mpsc, Arc, Mutex as SyncMutex}; +use std::sync::{ + atomic::{AtomicBool, Ordering}, + Arc, +}; use std::time::Duration; -use tokio::sync::Mutex as AsyncMutex; use tokio::time::{interval, sleep, timeout}; use tracing::{debug, error, info, trace, warn}; @@ -16,7 +16,7 @@ use graphcast_sdk::{ use crate::chainhead_block_str; use crate::messages::poi::PublicPoiMessage; - +use crate::messages::upgrade::VersionUpgradeMessage; use crate::metrics::handle_serve_metrics; use crate::operator::attestation::log_gossip_summary; use crate::operator::attestation::process_comparison_results; @@ -103,17 +103,79 @@ impl RadioOperator { let persisted_state: PersistedState = config.init_radio_state().await; debug!("Initializing Graphcast Agent"); - let graphcast_agent = Arc::new( - config - .create_graphcast_agent() + let (agent, receiver) = + GraphcastAgent::new(config.to_graphcast_agent_config().await.unwrap()) .await - .expect("Initialize Graphcast agent"), - ); + .expect("Initialize Graphcast agent"); + let graphcast_agent = Arc::new(agent); + debug!("Set global static instance of graphcast_agent"); _ = GRAPHCAST_AGENT.set(graphcast_agent.clone()); let notifier = Notifier::from_config(config); + let state_ref = persisted_state.clone(); + let upgrade_notifier = notifier.clone(); + let graph_node = config.graph_node_endpoint().clone(); + // try message format in order of PublicPOIMessage, VersionUpgradeMessage + tokio::spawn(async move { + for msg in receiver { + trace!("Decoding waku message into Graphcast Message with Radio specified payload"); + let agent = GRAPHCAST_AGENT + .get() + .expect("Could not retrieve Graphcast agent"); + if let Ok(msg) = agent.decoder::(msg.payload()).await { + trace!( + message = tracing::field::debug(&msg), + "Parsed and validated as Public PoI message", + ); + let identifier = msg.identifier.clone(); + + let is_valid = msg.payload.validity_check(&msg, &graph_node).await; + + if is_valid.is_ok() { + state_ref.add_remote_message(msg.clone()); + CACHED_MESSAGES.with_label_values(&[&identifier]).set( + state_ref + .remote_messages() + .iter() + .filter(|m| m.identifier == identifier) + .collect::>>() + .len() + .try_into() + .unwrap(), + ); + }; + } else if let Ok(msg) = agent.decoder::(msg.payload()).await + { + trace!( + message = tracing::field::debug(&msg), + "Parsed and validated as Version Upgrade message", + ); + let is_valid = msg.payload.validity_check(&msg, &graph_node).await; + + if let Ok(payload) = is_valid { + // send notifications to the indexer? + upgrade_notifier.notify(format!( + "Subgraph owner for a deployment has shared version upgrade info:\nold deployment: {}\nnew deployment: {}\nplanned migrate time: {}\nnetwork: {}", + payload.identifier, + payload.new_hash, + payload.migrate_time, + payload.network + )).await; + }; + } else { + trace!("Waku message not decoded or validated, skipped message",); + }; + } + }); + + GRAPHCAST_AGENT + .get() + .unwrap() + .register_handler() + .expect("Could not register handler"); + RadioOperator { config: config.clone(), persisted_state, @@ -144,88 +206,7 @@ impl RadioOperator { self.graphcast_agent .update_content_topics(topics.clone()) .await; - - // let (poi_sender, poi_receiver) = mpsc::channel::>(); - // let (version_sender, version_receiver) = mpsc::channel::>(); - - let (sender, receiver) = mpsc::channel::>(); - let handler = RadioOperator::radio_msg_handler::(SyncMutex::new(sender)); - GRAPHCAST_AGENT - .get() - .unwrap() - .register_handler(Arc::new(AsyncMutex::new(handler))) - .expect("Could not register handler"); - let state_ref = self.persisted_state.clone(); - - let config = self.config.clone(); - - let graph_node = self.config.graph_node_endpoint().clone(); - tokio::spawn(async move { - for msg in receiver { - trace!( - "Radio operator received a validated message from Graphcast agent: {:#?}", - msg - ); - // let identifier = msg.identifier.clone(); - - // let is_valid = msg - // .validity_check(&msg, config.graph_node_endpoint()) - // .await; - - // if is_valid.is_ok() { - // state_ref.add_remote_message(msg.clone()); - // } - - // CACHED_MESSAGES.with_label_values(&[&identifier]).set( - // state_ref - // .remote_messages() - // .iter() - // .filter(|m| m.identifier == identifier) - // .collect::>>() - // .len() - // .try_into() - // .unwrap(), - // ); - let identifier = msg.identifier.clone(); - - let is_valid = msg.payload.validity_check(&msg, &graph_node).await; - if is_valid.is_ok() { - state_ref.add_remote_message(msg.clone()); - } - CACHED_MESSAGES.with_label_values(&[&identifier]).set( - state_ref - .remote_messages() - .iter() - .filter(|m| m.identifier == identifier) - .collect::>>() - .len() - .try_into() - .unwrap(), - ); - } - }); } - // for msg in receiver { - // // - // trace!( - // "Radio operator received a validated message from Graphcast agent: {:#?}", - // msg - // ); - - // // let identifier = msg.identifier.clone(); - // // state_ref.add_remote_message(msg.clone()); - // // CACHED_MESSAGES.with_label_values(&[&identifier]).set( - // // state_ref - // // .remote_messages() - // // .iter() - // // .filter(|m| m.identifier == identifier) - // // .collect::>>() - // // .len() - // // .try_into() - // // .unwrap(), - // // ); - // } - // }); pub fn graphcast_agent(&self) -> &GraphcastAgent { &self.graphcast_agent @@ -315,7 +296,7 @@ impl RadioOperator { res, ), Err(e) => { - error!(err = tracing::field::debug(&e), "Could not query indexing statuses, pull again later"); + error!(err = tracing::field::debug(&e), "Could not query indexing statuses, failed to get network chainhead, pull again later"); continue; } }; @@ -323,7 +304,7 @@ impl RadioOperator { let subgraph_network_latest_blocks = match self.config.callbook().indexing_statuses().await { Ok(res) => subgraph_network_blocks(res), Err(e) => { - error!(err = tracing::field::debug(&e), "Could not query indexing statuses, pull again later"); + error!(err = tracing::field::debug(&e), "Could not query indexing statuses, failed to get subgraph latest block, pull again later"); continue; } }; @@ -378,7 +359,7 @@ impl RadioOperator { let indexing_status = match self.config.callbook().indexing_statuses().await { Ok(res) => res, Err(e) => { - error!(err = tracing::field::debug(&e), "Could not query indexing statuses, pull again later"); + error!(err = tracing::field::debug(&e), "Could not query indexing statuses for comparison, pull again later"); continue; } }; diff --git a/poi-radio/src/operator/notifier.rs b/poi-radio/src/operator/notifier.rs index 9a2f7953..9ad7c9c7 100644 --- a/poi-radio/src/operator/notifier.rs +++ b/poi-radio/src/operator/notifier.rs @@ -53,7 +53,7 @@ impl Notifier { ) } - pub async fn notify(self, content: String) { + pub async fn notify(&self, content: String) { if let (Some(token), Some(channel)) = (&self.slack_token, &self.slack_channel) { if let Err(e) = SlackBot::send_webhook(token.to_string(), channel, &self.radio_name, &content).await diff --git a/poi-radio/src/operator/operation.rs b/poi-radio/src/operator/operation.rs index 4f26d1c9..a9d9bf12 100644 --- a/poi-radio/src/operator/operation.rs +++ b/poi-radio/src/operator/operation.rs @@ -1,29 +1,25 @@ use autometrics::autometrics; use chrono::Utc; use graphcast_sdk::callbook::CallBook; -use prost::Message; -use std::any::Any; use std::cmp::max; use std::collections::HashMap; -use std::sync::{mpsc, Arc, Mutex as SyncMutex}; +use std::sync::{Arc, Mutex as SyncMutex}; use tracing::{debug, error, trace, warn}; use graphcast_sdk::{ determine_message_block, graphcast_agent::{ message_typing::{BuildMessageError, GraphcastMessage}, - waku_handling::WakuHandlingError, GraphcastAgent, GraphcastAgentError, }, networks::NetworkName, BlockPointer, NetworkBlockError, NetworkPointer, }; - -use crate::messages::{poi::PublicPoiMessage, upgrade::VersionUpgradeMessage}; +use crate::messages::poi::PublicPoiMessage; use crate::operator::attestation::process_ppoi_message; use crate::{ - metrics::{CACHED_MESSAGES, VALIDATED_MESSAGES}, + metrics::CACHED_MESSAGES, operator::{ attestation::{ compare_attestations, local_comparison_point, save_local_attestation, Attestation, @@ -265,162 +261,6 @@ pub async fn message_comparison( } impl RadioOperator { - /// Custom callback for handling the validated GraphcastMessage, in this case we only save the messages to a local store - /// to process them at a later time. This is required because for the processing we use async operations which are not allowed - /// in the handler. - #[autometrics] - pub fn radio_msg_handler( - poi_sender: SyncMutex>>, - // sender: SyncMutex>>, - ) -> impl Fn(Result, WakuHandlingError>) - // sender: SyncMutex>, - // ) -> impl Fn(&dyn Any) - where - T: Message - + ethers::types::transaction::eip712::Eip712 - + Default - + Clone - + 'static - + async_graphql::OutputType, - { - // move |msg: &dyn Any| { - move |msg: Result, WakuHandlingError>| { - // TODO: Handle the error case by incrementing a Prometheus "error" counter - if let Ok(msg) = msg { - trace!( - msg = tracing::field::debug(&msg), - "Received Graphcast validated message" - ); - - let id = msg.identifier.clone(); - VALIDATED_MESSAGES.with_label_values(&[&id]).inc(); - // typed_handler(sender, &msg); - - let any_msg: &dyn Any = &msg; - trace!( - any_msg = tracing::field::debug(any_msg), - "Received Graphcast validated message" - ); - if let Some(ppoi_message) = &any_msg.downcast_ref::>() { - - // let id = any_msg.identifier.clone(); - // VALIDATED_MESSAGES.with_label_values(&[&id]).inc(); - - match poi_sender.lock().unwrap().send((*ppoi_message).clone()) { - Ok(_) => trace!("Sent received public POI message to radio operator"), - Err(e) => error!("Could not send message to channel: {:#?}", e), - } - } else if let Some(Ok(upgrade_message)) = any_msg.downcast_ref::, WakuHandlingError>>() { - trace!( - upgrade_message = tracing::field::debug(&upgrade_message), - "Received Graphcast validated message" - ); - - // // let id = upgrade_message.identifier.clone(); - // // VALIDATED_MESSAGES.with_label_values(&[&id]).inc(); - - // match sender.lock().unwrap().send(MessageType::VersionUpgrade(upgrade_message.clone())) { - // Ok(_) => trace!("Sent upgrade message to radio operator"), - // Err(e) => error!("Could not send message to channel: {:#?}", e), - // } - } - - //TODO: Make sure CACHED_MESSAGES is updated - } - } - } - - // /// Construct the message and send it to Graphcast network - // #[autometrics(track_concurrency)] - // pub async fn create_radio_message( - // &self, - // id: String, - // message_block: u64, - // latest_block: BlockPointer, - // network_name: NetworkName, - // ) -> Result { - // trace!( - // message_block = message_block, - // latest_block = latest_block.number, - // "Check message send requirement", - // ); - - // // Deployment did not sync to message_block - // if latest_block.number < message_block { - // //TODO: fill in variant in SDK - // let err_msg = format!( - // "Did not send message for deployment {}: latest_block ({}) syncing status must catch up to the message block ({})", - // id.clone(), - // latest_block.number, message_block, - // ); - // trace!(err = err_msg, "Skip send",); - // return Err(OperationError::SendTrigger(err_msg)); - // }; - - // // Skip messages that has been sent before - // if self - // .state() - // .local_attestations() - // .get(&id.clone()) - // .and_then(|blocks| blocks.get(&message_block)) - // .is_some() - // { - // let err_msg = format!( - // "Repeated message for deployment {}, skip sending message for block: {}", - // id.clone(), - // message_block - // ); - // trace!(err = err_msg, "Skip send"); - // return Err(OperationError::SkipDuplicate(err_msg)); - // } - - // let block_hash = match self - // .config - // .callbook() - // .block_hash(&network_name.to_string(), message_block) - // .await - // { - // Ok(hash) => hash, - // Err(e) => { - // let err_msg = format!("Failed to query graph node for the block hash: {e}"); - // error!(err = err_msg, "Failed to send message"); - // return Err(OperationError::Query(e)); - // } - // }; - - // match self - // .config - // .callbook() - // .query_poi( - // id.clone(), - // block_hash.clone(), - // message_block.try_into().unwrap(), - // ) - // .await - // { - // Ok(content) => Ok(PublicPoiMessage::build( - // id.clone(), - // content, - // network_name, - // message_block, - // block_hash, - // self.graphcast_agent - // .graphcast_identity - // .graph_account - // .clone(), - // )), - // Err(e) => { - // error!( - // err = tracing::field::debug(&e), - // "Failed to query message content" - // ); - // Err(OperationError::Agent( - // GraphcastAgentError::QueryResponseError(e), - // )) - // } - // } - // } - pub async fn gossip_poi( &self, identifiers: Vec, diff --git a/poi-radio/src/state.rs b/poi-radio/src/state.rs index db5f5068..566cf254 100644 --- a/poi-radio/src/state.rs +++ b/poi-radio/src/state.rs @@ -204,10 +204,7 @@ impl PersistedState { }; if should_notify { - notifier - .clone() - .notify(updated_comparison_result.to_string()) - .await; + notifier.notify(updated_comparison_result.to_string()).await; } result_type diff --git a/test-runner/Cargo.toml b/test-runner/Cargo.toml index 33520645..e8e53f86 100644 --- a/test-runner/Cargo.toml +++ b/test-runner/Cargo.toml @@ -23,7 +23,8 @@ categories = [ [dependencies] waku = { version = "0.1.1", package = "waku-bindings" } test-utils = { path = "../test-utils" } -graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk" } +# graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", rev = "f39cb28" } +graphcast-sdk = { package = "graphcast-sdk", path = "../../graphcast-rs" } poi-radio = { path = "../poi-radio" } tokio = { version = "1.1.1", features = ["full", "rt"] } tracing = "0.1" diff --git a/test-sender/Cargo.toml b/test-sender/Cargo.toml index 17cb8fb9..76594aaa 100644 --- a/test-sender/Cargo.toml +++ b/test-sender/Cargo.toml @@ -22,7 +22,8 @@ categories = [ [dependencies] waku = { version = "0.1.1", package = "waku-bindings" } -graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk" } +# graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", rev = "f39cb28" } +graphcast-sdk = { package = "graphcast-sdk", path = "../../graphcast-rs" } test-utils = { path = "../test-utils" } poi-radio = { path = "../poi-radio" } tokio = { version = "1.1.1", features = ["full", "rt"] } diff --git a/test-sender/src/main.rs b/test-sender/src/main.rs index 938c0e5a..19be9f71 100644 --- a/test-sender/src/main.rs +++ b/test-sender/src/main.rs @@ -1,5 +1,3 @@ -use std::{net::IpAddr, str::FromStr, thread::sleep, time::Duration}; - use chrono::Utc; use clap::Parser; use graphcast_sdk::{ @@ -10,8 +8,10 @@ use graphcast_sdk::{ }, init_tracing, networks::NetworkName, + wallet_address, }; use poi_radio::messages::poi::PublicPoiMessage; +use std::{net::IpAddr, str::FromStr, thread::sleep, time::Duration}; use test_utils::{config::TestSenderConfig, dummy_msg::DummyMsg, find_random_udp_port}; use tracing::{error, info}; use waku::{ @@ -81,7 +81,7 @@ async fn start_sender(config: TestSenderConfig) { let content_topic = format!("/{}/0/{}/proto", config.radio_name, topic); let content_topic = WakuContentTopic::from_str(&content_topic).unwrap(); - let nonce = config.nonce.clone().unwrap().parse::().unwrap(); + // let nonce = config.nonce.clone().unwrap().parse::().unwrap(); let radio_payload_clone = config.radio_payload.clone(); match radio_payload_clone.as_deref() { @@ -89,7 +89,7 @@ async fn start_sender(config: TestSenderConfig) { let radio_payload = PublicPoiMessage::build( topic.clone(), config.poi.clone().unwrap(), - nonce, + timestamp, NetworkName::Goerli, timestamp.try_into().unwrap(), config.block_hash.clone().unwrap(), @@ -100,12 +100,17 @@ async fn start_sender(config: TestSenderConfig) { &wallet, topic.clone(), "0x7e6528e4ce3055e829a32b5dc4450072bac28bc6".to_string(), - nonce, + timestamp, radio_payload, ) .await .unwrap(); + assert!( + wallet_address(&wallet) + == graphcast_message.recover_sender_address().unwrap() + ); + match graphcast_message.send_to_waku( &node_handle, WakuPubSubTopic::from_str("/waku/2/graphcast-v0-testnet/proto").unwrap(), diff --git a/test-utils/Cargo.toml b/test-utils/Cargo.toml index 7b3d93c2..14b0cb33 100644 --- a/test-utils/Cargo.toml +++ b/test-utils/Cargo.toml @@ -22,7 +22,8 @@ categories = [ [dependencies] waku = { version = "0.1.1", package = "waku-bindings" } -graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk" } +# graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", rev = "f39cb28" } +graphcast-sdk = { package = "graphcast-sdk", path = "../../graphcast-rs" } poi-radio = { path = "../poi-radio" } tokio = { version = "1.1.1", features = ["full", "rt"] } tracing = "0.1" diff --git a/test-utils/src/config.rs b/test-utils/src/config.rs index 39f00b97..5bec52f8 100644 --- a/test-utils/src/config.rs +++ b/test-utils/src/config.rs @@ -59,7 +59,7 @@ pub fn test_config() -> Config { discv5_enrs: None, discv5_port: None, filter_protocol: None, - id_validation: IdentityValidation::GraphcastRegistered, + id_validation: IdentityValidation::ValidAddress, topic_update_interval: 600, } } From 5e3f0c1102a3a03dce22f968f9209e20f7533c74 Mon Sep 17 00:00:00 2001 From: hopeyen Date: Tue, 11 Jul 2023 18:05:45 -0500 Subject: [PATCH 3/7] feat: one-shot radio for version upgrade --- Cargo.toml | 2 +- one-shot/Cargo.toml | 66 +++++ one-shot/src/config.rs | 423 +++++++++++++++++++++++++++++ one-shot/src/lib.rs | 17 ++ one-shot/src/main.rs | 19 ++ one-shot/src/operator/mod.rs | 63 +++++ one-shot/src/operator/operation.rs | 43 +++ 7 files changed, 632 insertions(+), 1 deletion(-) create mode 100644 one-shot/Cargo.toml create mode 100644 one-shot/src/config.rs create mode 100644 one-shot/src/lib.rs create mode 100644 one-shot/src/main.rs create mode 100644 one-shot/src/operator/mod.rs create mode 100644 one-shot/src/operator/operation.rs diff --git a/Cargo.toml b/Cargo.toml index 29e40956..ba8ea16f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace] -members = ["poi-radio", "test-sender", "test-utils", "test-runner"] +members = ["poi-radio", "test-sender", "test-utils", "test-runner", "one-shot"] resolver = "2" [profile.dev] diff --git a/one-shot/Cargo.toml b/one-shot/Cargo.toml new file mode 100644 index 00000000..8d1ed7a2 --- /dev/null +++ b/one-shot/Cargo.toml @@ -0,0 +1,66 @@ +[package] +name = "one-shot" +version = "0.3.6" +edition = "2021" +authors = ["GraphOps (axiomatic-aardvark, hopeyen)"] +description = "One-shot messaging using Graphcast SDK (can be separated to a different repo)" +license = "Apache-2.0" +repository = "https://github.com/graphops/poi-radio" +keywords = ["graphprotocol", "data-integrity", "Indexer", "waku", "p2p"] +categories = ["network-programming", "web-programming::http-client"] + +[dependencies] +# graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", rev = "f39cb28" } +graphcast-sdk = { package = "graphcast-sdk", path = "../../graphcast-rs" } +poi-radio = { path = "../poi-radio" } +prost = "0.11" +once_cell = "1.17" +chrono = "0.4" +serde = { version = "1.0.163", features = ["rc"] } +serde_json = "1.0.96" +sha3 = "0.10.8" +derive-getters = "0.2.1" +tokio = { version = "1.28.1", features = ["full", "rt"] } +anyhow = "1.0" +graphql_client = "0.9.0" +serde_derive = "1.0" +reqwest = { version = "0.11.17", features = ["json"] } +thiserror = "1.0.40" +regex = "1.8.1" +ethers = "2.0.4" +ethers-contract = "2.0.4" +ethers-core = "2.0.4" +ethers-derive-eip712 = "1.0.2" +partial_application = "0.2.1" +num-bigint = "0.4.3" +num-traits = "0.2.15" +wiremock = "0.5.18" +dotenv = "0.15" +rand = "0.8.5" +secp256k1 = "0.25.0" +hex = "0.4.3" +tracing = "0.1" +tracing-subscriber = { version = "0.3", features = [ + "env-filter", + "ansi", + "fmt", + "std", + "json", +] } +autometrics = { version = "0.3.3", features = ["prometheus-exporter"] } +axum = "0.5" +prometheus = "0.13.3" +tower-http = { version = "0.4.0", features = ["trace", "cors"] } +async-graphql = "4.0.16" +async-graphql-axum = "4.0.16" +metrics = "0.20.1" +metrics-exporter-prometheus = "0.11.0" +opentelemetry = { version = "0.18.0", features = ["rt-tokio"] } +tracing-opentelemetry = "0.18.0" +clap = { version = "3.2.25", features = ["derive", "env"] } + +[dev-dependencies.cargo-husky] +version = "1" +default-features = false +# Disable features which are enabled by default +features = ["precommit-hook", "run-cargo-fmt", "run-cargo-clippy"] diff --git a/one-shot/src/config.rs b/one-shot/src/config.rs new file mode 100644 index 00000000..520db12b --- /dev/null +++ b/one-shot/src/config.rs @@ -0,0 +1,423 @@ +use clap::Parser; +use derive_getters::Getters; +use ethers::signers::WalletError; +use serde::{Deserialize, Serialize}; +use tracing::info; + +use graphcast_sdk::{ + build_wallet, + callbook::CallBook, + graphcast_agent::{ + message_typing::IdentityValidation, GraphcastAgentConfig, GraphcastAgentError, + }, + graphql::{ + client_network::query_network_subgraph, client_registry::query_registry, QueryError, + }, + init_tracing, wallet_address, +}; + +#[derive(Clone, Debug, Parser, Serialize, Deserialize, Getters, Default)] +#[clap( + name = "one-shot-messenger", + about = "Send a message to Graphcast network", + author = "GraphOps" +)] +pub struct Config { + #[clap( + long, + value_name = "KEY", + value_parser = Config::parse_key, + env = "PRIVATE_KEY", + hide_env_values = true, + help = "Private key to the Graphcast ID wallet (Precendence over mnemonics)", + )] + // should keep this value private, this is current public due to the constructing a Config in test-utils + // We can get around this by making an explicit function to make config instead of direct build in {} + pub private_key: Option, + #[clap( + long, + value_name = "KEY", + value_parser = Config::parse_key, + env = "MNEMONIC", + hide_env_values = true, + help = "Mnemonic to the Graphcast ID wallet (first address of the wallet is used; Only one of private key or mnemonic is needed)", + )] + pub mnemonic: Option, + #[clap( + long, + value_name = "GRAPH_ACCOUNT", + env = "GRAPH_ACCOUNT", + help = "Graph account corresponding to Graphcast operator" + )] + pub graph_account: String, + #[clap( + long, + value_name = "SUBGRAPH", + env = "REGISTRY_SUBGRAPH", + help = "Subgraph endpoint to the Graphcast Registry", + default_value = "https://api.thegraph.com/subgraphs/name/hopeyen/graphcast-registry-goerli" + )] + pub registry_subgraph: String, + #[clap( + long, + value_name = "SUBGRAPH", + env = "NETWORK_SUBGRAPH", + help = "Subgraph endpoint to The Graph network subgraph", + default_value = "https://api.thegraph.com/subgraphs/name/graphprotocol/graph-network-goerli" + )] + pub network_subgraph: String, + #[clap( + long, + default_value = "testnet", + value_name = "NAME", + env = "GRAPHCAST_NETWORK", + help = "Supported Graphcast networks: mainnet, testnet", + possible_values = ["testnet", "mainnet"], + )] + pub graphcast_network: String, + #[clap( + long, + value_name = "[TOPIC]", + value_delimiter = ',', + env = "TOPICS", + help = "Comma separated static list of content topics to subscribe to (Static list to include) (right now just send message to the first element of the vec?" + )] + pub topics: Vec, + #[clap( + long, + value_name = "IDENTIFIER", + env = "IDENTIFIER", + help = "Subgraph hash is used to be the message content identifier" + )] + pub identifier: String, + #[clap( + long, + value_name = "NEW_HASH", + env = "NEW_HASH", + help = "Subgraph hash for the upgrade version of the subgraph" + )] + pub new_hash: String, + #[clap( + long, + value_name = "SUBGRAPH_ID", + env = "SUBGRAPH_ID", + help = "Subgraph id shared by the old and new deployment" + )] + pub subgraph_id: String, + #[clap( + long, + value_name = "INDEX_NETWORK", + env = "INDEX_NETWORK", + help = "Subgraph id shared by the old and new deployment" + )] + pub index_network: String, + #[clap( + long, + value_name = "MIGRATION_TIME", + env = "MIGRATION_TIME", + help = "UNIX timestamp that the developer plan on migrating the usage" + )] + pub migration_time: i64, + #[clap( + long, + value_name = "WAKU_HOST", + help = "Host for the Waku gossip client", + env = "WAKU_HOST" + )] + pub waku_host: Option, + #[clap( + long, + value_name = "WAKU_PORT", + help = "Port for the Waku gossip client", + env = "WAKU_PORT" + )] + pub waku_port: Option, + #[clap( + long, + value_name = "KEY", + env = "WAKU_NODE_KEY", + hide_env_values = true, + help = "Private key to the Waku node id" + )] + pub waku_node_key: Option, + #[clap( + long, + value_name = "KEY", + env = "WAKU_ADDRESS", + hide_env_values = true, + help = "Advertised address to be connected among the Waku peers" + )] + pub waku_addr: Option, + #[clap( + long, + value_name = "NODE_ADDRESSES", + help = "Comma separated static list of waku boot nodes to connect to", + env = "BOOT_NODE_ADDRESSES" + )] + pub boot_node_addresses: Vec, + #[clap( + long, + value_name = "WAKU_LOG_LEVEL", + help = "Waku node logging configuration", + env = "WAKU_LOG_LEVEL" + )] + pub waku_log_level: Option, + #[clap( + long, + value_name = "DISCV5_ENRS", + help = "Comma separated ENRs for Waku discv5 bootstrapping", + env = "DISCV5_ENRS" + )] + pub discv5_enrs: Option>, + #[clap( + long, + value_name = "DISCV5_PORT", + help = "Waku node to expose discoverable udp port", + env = "DISCV5_PORT" + )] + pub discv5_port: Option, + #[clap( + long, + value_name = "LOG_LEVEL", + default_value = "info", + help = "logging configurationt to set as RUST_LOG", + env = "RUST_LOG" + )] + pub log_level: String, + #[clap( + long, + value_name = "SLACK_TOKEN", + help = "Slack bot API token", + env = "SLACK_TOKEN" + )] + pub slack_token: Option, + #[clap( + long, + value_name = "SLACK_CHANNEL", + help = "Name of Slack channel to send messages to (has to be a public channel)", + env = "SLACK_CHANNEL" + )] + pub slack_channel: Option, + #[clap( + long, + value_name = "DISCORD_WEBHOOK", + help = "Discord webhook URL to send messages to", + env = "DISCORD_WEBHOOK" + )] + pub discord_webhook: Option, + #[clap( + long, + value_name = "TELEGRAM_TOKEN", + help = "Telegram Bot API Token", + env = "TELEGRAM_TOKEN" + )] + pub telegram_token: Option, + #[clap( + long, + value_name = "TELEGRAM_CHAT_ID", + help = "Id of Telegram chat (DM or group) to send messages to", + env = "TELEGRAM_CHAT_ID" + )] + pub telegram_chat_id: Option, + #[clap( + long, + value_name = "METRICS_HOST", + default_value = "0.0.0.0", + help = "If port is set, the Radio will expose Prometheus metrics on the given host. This requires having a local Prometheus server running and scraping metrics on the given port.", + env = "METRICS_HOST" + )] + pub metrics_host: String, + #[clap( + long, + value_name = "METRICS_PORT", + help = "If set, the Radio will expose Prometheus metrics on the given port (off by default). This requires having a local Prometheus server running and scraping metrics on the given port.", + env = "METRICS_PORT" + )] + pub metrics_port: Option, + #[clap( + long, + value_name = "SERVER_HOST", + default_value = "0.0.0.0", + help = "If port is set, the Radio will expose API service on the given host.", + env = "SERVER_HOST" + )] + pub server_host: String, + #[clap( + long, + value_name = "SERVER_PORT", + help = "If set, the Radio will expose API service on the given port (off by default).", + env = "SERVER_PORT" + )] + pub server_port: Option, + #[clap( + long, + value_name = "PERSISTENCE_FILE_PATH", + help = "If set, the Radio will periodically store states of the program to the file in json format", + env = "PERSISTENCE_FILE_PATH" + )] + pub persistence_file_path: Option, + #[clap( + long, + value_name = "LOG_FORMAT", + env = "LOG_FORMAT", + help = "Support logging formats: pretty, json, full, compact", + long_help = "pretty: verbose and human readable; json: not verbose and parsable; compact: not verbose and not parsable; full: verbose and not parsible", + possible_values = ["pretty", "json", "full", "compact"], + default_value = "pretty" + )] + pub log_format: String, + #[clap( + long, + value_name = "RADIO_NAME", + env = "RADIO_NAME", + default_value = "poi-radio" + )] + pub radio_name: String, + #[clap(long, value_name = "FILTER_PROTOCOL", env = "ENABLE_FILTER_PROTOCOL")] + pub filter_protocol: Option, + #[clap( + long, + value_name = "ID_VALIDATION", + value_enum, + env = "ID_VALIDATION", + help = "Identity validaiton mechanism for message signers", + long_help = "Identity validaiton mechanism for message signers\n + no-check: all messages signer is valid, \n + valid-address: signer needs to be an valid Eth address, \n + graphcast-registered: must be registered at Graphcast Registry, \n + graph-network-account: must be a Graph account, \n + registered-indexer: must be registered at Graphcast Registry, correspond to and Indexer statisfying indexer minimum stake requirement, \n + indexer: must be registered at Graphcast Registry or is a Graph Account, correspond to and Indexer statisfying indexer minimum stake requirement" + )] + pub id_validation: IdentityValidation, + #[clap( + long, + value_name = "TOPIC_UPDATE_INTERVAL", + env = "TOPIC_UPDATE_INTERVAL", + default_value = "600" + )] + pub topic_update_interval: u64, +} + +impl Config { + /// Parse config arguments + pub fn args() -> Self { + // TODO: load config file before parse (maybe add new level of subcommands) + let config = Config::parse(); + std::env::set_var("RUST_LOG", config.log_level.clone()); + // Enables tracing under RUST_LOG variable + init_tracing(config.log_format.clone()).expect("Could not set up global default subscriber for logger, check environmental variable `RUST_LOG` or the CLI input `log-level`"); + config + } + + /// Validate that private key as an Eth wallet + fn parse_key(value: &str) -> Result { + // The wallet can be stored instead of the original private key + let wallet = build_wallet(value)?; + let address = wallet_address(&wallet); + info!(address, "Resolved Graphcast id"); + Ok(String::from(value)) + } + + /// Private key takes precedence over mnemonic + pub fn wallet_input(&self) -> Result<&String, ConfigError> { + match (&self.private_key, &self.mnemonic) { + (Some(p), _) => Ok(p), + (_, Some(m)) => Ok(m), + _ => Err(ConfigError::ValidateInput( + "Must provide either private key or mnemonic".to_string(), + )), + } + } + + pub async fn to_graphcast_agent_config( + &self, + ) -> Result { + let wallet_key = self.wallet_input().unwrap().to_string(); + let topics = self.topics.clone(); + + info!( + wallet_key = tracing::field::debug(&wallet_key), + graph_account = tracing::field::debug(&self.graph_account.clone()), + radio_name = tracing::field::debug(&self.radio_name.clone()), + registry_subgraph = tracing::field::debug(&self.registry_subgraph.clone()), + network_subgraph = tracing::field::debug(&self.network_subgraph.clone()), + id_validation = tracing::field::debug(&self.id_validation.clone()), + boot_node_addresses = tracing::field::debug(&Some(self.boot_node_addresses.clone())), + graphcast_network = tracing::field::debug(&Some(self.graphcast_network.to_owned())), + topics = tracing::field::debug(&Some(topics.clone())), + waku_node_key = tracing::field::debug(&self.waku_node_key.clone()), + waku_host = tracing::field::debug(&self.waku_host.clone()), + waku_port = tracing::field::debug(&self.waku_port.clone()), + waku_addr = tracing::field::debug(&self.waku_addr.clone()), + filter_protocol = tracing::field::debug(&self.filter_protocol), + discv5_enrs = tracing::field::debug(&self.discv5_enrs.clone()), + discv5_port = tracing::field::debug(&self.discv5_port), + "Config stuff", + ); + + GraphcastAgentConfig::new( + wallet_key, + self.graph_account.clone(), + self.radio_name.clone(), + self.registry_subgraph.clone(), + self.network_subgraph.clone(), + self.id_validation.clone(), + None, + Some(self.boot_node_addresses.clone()), + Some(self.graphcast_network.to_owned()), + Some(topics), + self.waku_node_key.clone(), + self.waku_host.clone(), + self.waku_port.clone(), + self.waku_addr.clone(), + self.filter_protocol, + self.discv5_enrs.clone(), + self.discv5_port, + ) + .await + } + + pub async fn basic_info(&self) -> Result<(String, f32), QueryError> { + // Using unwrap directly as the query has been ran in the set-up validation + let wallet = build_wallet( + self.wallet_input() + .map_err(|e| QueryError::Other(e.into()))?, + ) + .map_err(|e| QueryError::Other(e.into()))?; + // The query here must be Ok but so it is okay to panic here + // Alternatively, make validate_set_up return wallet, address, and stake + let my_address = query_registry(self.registry_subgraph(), &wallet_address(&wallet)).await?; + let my_stake = query_network_subgraph(self.network_subgraph(), &my_address) + .await + .unwrap() + .indexer_stake(); + info!( + my_address, + my_stake, "Initializing radio operator for indexer identity", + ); + Ok((my_address, my_stake)) + } + + pub fn callbook(&self) -> CallBook { + CallBook::new( + self.registry_subgraph.clone(), + self.network_subgraph.clone(), + None, + ) + } +} + +#[derive(Debug, thiserror::Error)] +pub enum ConfigError { + #[error("Validate the input: {0}")] + ValidateInput(String), + #[error("Generate JSON representation of the config file: {0}")] + GenerateJson(serde_json::Error), + #[error("QueryError: {0}")] + QueryError(QueryError), + #[error("Toml file error: {0}")] + ReadStr(std::io::Error), + #[error("Unknown error: {0}")] + Other(anyhow::Error), +} diff --git a/one-shot/src/lib.rs b/one-shot/src/lib.rs new file mode 100644 index 00000000..0011b77f --- /dev/null +++ b/one-shot/src/lib.rs @@ -0,0 +1,17 @@ +use once_cell::sync::OnceCell; +use std::sync::Arc; + +use graphcast_sdk::graphcast_agent::GraphcastAgent; + +use crate::operator::RadioOperator; + +pub mod config; +pub mod operator; + +/// A global static (singleton) instance of GraphcastAgent. It is useful to ensure that we have only one GraphcastAgent +/// per Radio instance, so that we can keep track of state and more easily test our Radio application. +pub static RADIO_OPERATOR: OnceCell = OnceCell::new(); + +/// A global static (singleton) instance of GraphcastAgent. It is useful to ensure that we have only one GraphcastAgent +/// per Radio instance, so that we can keep track of state and more easily test our Radio application. +pub static GRAPHCAST_AGENT: OnceCell> = OnceCell::new(); diff --git a/one-shot/src/main.rs b/one-shot/src/main.rs new file mode 100644 index 00000000..e26d2f35 --- /dev/null +++ b/one-shot/src/main.rs @@ -0,0 +1,19 @@ +use dotenv::dotenv; +use one_shot::{config::Config, operator::RadioOperator, RADIO_OPERATOR}; + +extern crate partial_application; + +#[tokio::main] +async fn main() { + dotenv().ok(); + // Parse basic configurations + let radio_config = Config::args(); + + // Initialization and pass in for static lifetime throughout the program + let radio_operator = RadioOperator::new(&radio_config).await; + + _ = RADIO_OPERATOR.set(radio_operator); + + // Start radio operations + RADIO_OPERATOR.get().unwrap().run().await; +} diff --git a/one-shot/src/operator/mod.rs b/one-shot/src/operator/mod.rs new file mode 100644 index 00000000..961cb5eb --- /dev/null +++ b/one-shot/src/operator/mod.rs @@ -0,0 +1,63 @@ +use std::sync::Arc; +use tracing::{debug, warn}; + +use graphcast_sdk::{build_wallet, graphcast_agent::GraphcastAgent}; + +use crate::config::Config; +use crate::GRAPHCAST_AGENT; +pub mod operation; + +/// Radio operator contains all states needed for radio operations +#[allow(unused)] +pub struct RadioOperator { + config: Config, + graphcast_agent: Arc, +} + +impl RadioOperator { + /// Create a radio operator with radio configurations, persisted data, + /// graphcast agent, and control flow + pub async fn new(config: &Config) -> RadioOperator { + debug!("Initializing Radio operator"); + let _wallet = build_wallet( + config + .wallet_input() + .expect("Operator wallet input invalid"), + ) + .expect("Radio operator cannot build wallet"); + + debug!("Initializing Graphcast Agent"); + let (agent, _receiver) = + GraphcastAgent::new(config.to_graphcast_agent_config().await.unwrap()) + .await + .expect("Initialize Graphcast agent"); + let graphcast_agent = Arc::new(agent); + // Provide topics to Graphcast agent + let topics = vec![config.identifier.clone()]; + debug!( + topics = tracing::field::debug(&topics), + "Found content topics for subscription", + ); + graphcast_agent.update_content_topics(topics.clone()).await; + debug!("Set global static instance of graphcast_agent"); + _ = GRAPHCAST_AGENT.set(graphcast_agent.clone()); + + RadioOperator { + config: config.clone(), + graphcast_agent, + } + } + + pub fn graphcast_agent(&self) -> &GraphcastAgent { + &self.graphcast_agent + } + + /// radio continuously attempt to send message until success + pub async fn run(&'static self) { + let mut res = self.gossip_one_shot().await; + while let Err(e) = res { + warn!(err = tracing::field::debug(&e), "Failed to gossip, repeat"); + res = self.gossip_one_shot().await; + } + } +} diff --git a/one-shot/src/operator/operation.rs b/one-shot/src/operator/operation.rs new file mode 100644 index 00000000..a88de85b --- /dev/null +++ b/one-shot/src/operator/operation.rs @@ -0,0 +1,43 @@ +use chrono::Utc; +use tracing::{error, info}; + +use graphcast_sdk::networks::NetworkName; + +use crate::operator::RadioOperator; +use poi_radio::{messages::upgrade::VersionUpgradeMessage, OperationError}; + +impl RadioOperator { + pub async fn gossip_one_shot(&self) -> Result { + // configure radio config to parse in a subcommand for the radio payload message? + let identifier = self.config.identifier.clone(); + let new_hash = self.config.new_hash.clone(); + let subgraph_id = self.config.subgraph_id.clone(); + let time = Utc::now().timestamp(); + let network = self.config.index_network(); + let migrate_time = self.config.migration_time; + let graph_account = self.config.graph_account.clone(); + let radio_message = VersionUpgradeMessage::build( + identifier.clone(), + new_hash.clone(), + time, + subgraph_id, + NetworkName::from_string(network), + migrate_time, + graph_account, + ); + match self + .graphcast_agent + .send_message(&identifier, radio_message, time) + .await + { + Ok(msg_id) => { + info!(msg_id, "Sent message"); + Ok(msg_id) + } + Err(e) => { + error!(err = tracing::field::debug(&e), "Failed to send message"); + Err(OperationError::Agent(e)) + } + } + } +} From 444fae102d99f22496a06d58cf06d2f3fd541424 Mon Sep 17 00:00:00 2001 From: hopeyen Date: Wed, 12 Jul 2023 11:14:15 -0500 Subject: [PATCH 4/7] fix: add test retries and gc msg valid check --- Cargo.lock | 1 + one-shot/Cargo.toml | 3 +- poi-radio/Cargo.toml | 3 +- poi-radio/src/config.rs | 3 +- poi-radio/src/messages/mod.rs | 59 ----------------------------------- poi-radio/src/operator/mod.rs | 54 ++++++++++++++++++++++++++++++-- poi-radio/src/state.rs | 35 +++++++++++---------- test-runner/Cargo.toml | 3 +- test-runner/src/topics.rs | 28 +++++++++++------ test-sender/Cargo.toml | 3 +- test-sender/src/main.rs | 13 +++++--- test-utils/Cargo.toml | 3 +- test-utils/src/mock_server.rs | 4 +-- 13 files changed, 107 insertions(+), 105 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e05914c1..41106e1e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2294,6 +2294,7 @@ dependencies = [ [[package]] name = "graphcast-sdk" version = "0.3.4" +source = "git+https://github.com/graphops/graphcast-sdk?rev=99d942e#99d942edebb70e2c148c2d0a2008344060107903" dependencies = [ "anyhow", "async-graphql", diff --git a/one-shot/Cargo.toml b/one-shot/Cargo.toml index 8d1ed7a2..a17332c4 100644 --- a/one-shot/Cargo.toml +++ b/one-shot/Cargo.toml @@ -10,8 +10,7 @@ keywords = ["graphprotocol", "data-integrity", "Indexer", "waku", "p2p"] categories = ["network-programming", "web-programming::http-client"] [dependencies] -# graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", rev = "f39cb28" } -graphcast-sdk = { package = "graphcast-sdk", path = "../../graphcast-rs" } +graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", rev = "99d942e" } poi-radio = { path = "../poi-radio" } prost = "0.11" once_cell = "1.17" diff --git a/poi-radio/Cargo.toml b/poi-radio/Cargo.toml index ba6957fc..6f69c949 100644 --- a/poi-radio/Cargo.toml +++ b/poi-radio/Cargo.toml @@ -10,8 +10,7 @@ keywords = ["graphprotocol", "data-integrity", "Indexer", "waku", "p2p"] categories = ["network-programming", "web-programming::http-client"] [dependencies] -# graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", rev = "f39cb28" } -graphcast-sdk = { package = "graphcast-sdk", path = "../../graphcast-rs" } +graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", rev = "99d942e" } prost = "0.11" once_cell = "1.17" chrono = "0.4" diff --git a/poi-radio/src/config.rs b/poi-radio/src/config.rs index aea976bb..0a79c630 100644 --- a/poi-radio/src/config.rs +++ b/poi-radio/src/config.rs @@ -18,7 +18,7 @@ use serde::{Deserialize, Serialize}; use std::collections::HashSet; use tracing::{debug, info, trace}; -use crate::state::PersistedState; +use crate::state::{panic_hook, PersistedState}; use crate::{active_allocation_hashes, syncing_deployment_hashes}; #[derive(clap::ValueEnum, Clone, Debug, Serialize, Deserialize, Default)] @@ -400,6 +400,7 @@ impl Config { "Loaded Persisted state cache" ); + panic_hook(path); state } else { debug!("Created new state"); diff --git a/poi-radio/src/messages/mod.rs b/poi-radio/src/messages/mod.rs index a04439a2..b3d3ad2e 100644 --- a/poi-radio/src/messages/mod.rs +++ b/poi-radio/src/messages/mod.rs @@ -1,61 +1,2 @@ -use graphcast_sdk::graphcast_agent::{ - message_typing::GraphcastMessage, waku_handling::WakuHandlingError, -}; -use poi::PublicPoiMessage; -use std::{ - any::Any, - sync::{mpsc, Mutex as SyncMutex}, -}; -use tracing::{error, trace}; -use upgrade::VersionUpgradeMessage; - pub mod poi; pub mod upgrade; - -#[derive(Debug, Clone, serde_derive::Deserialize, serde_derive::Serialize)] -pub enum MessageType { - PublicPoi(GraphcastMessage), - VersionUpgrade(GraphcastMessage), -} - -pub fn typed_handler(sender: SyncMutex>, msg: &dyn Any) { - if let Some(Ok(ppoi_message)) = - msg.downcast_ref::, WakuHandlingError>>() - { - trace!( - ppoi_message = tracing::field::debug(&ppoi_message), - "Received Graphcast validated message" - ); - - // let id = ppoi_message.identifier.clone(); - // VALIDATED_MESSAGES.with_label_values(&[&id]).inc(); - - match sender - .lock() - .unwrap() - .send(MessageType::PublicPoi(ppoi_message.clone())) - { - Ok(_) => trace!("Sent received message to radio operator"), - Err(e) => error!("Could not send message to channel: {:#?}", e), - } - } else if let Some(Ok(upgrade_message)) = - msg.downcast_ref::, WakuHandlingError>>() - { - trace!( - upgrade_message = tracing::field::debug(&upgrade_message), - "Received Graphcast validated message" - ); - - // let id = upgrade_message.identifier.clone(); - // VALIDATED_MESSAGES.with_label_values(&[&id]).inc(); - - match sender - .lock() - .unwrap() - .send(MessageType::VersionUpgrade(upgrade_message.clone())) - { - Ok(_) => trace!("Sent upgrade message to radio operator"), - Err(e) => error!("Could not send message to channel: {:#?}", e), - } - } -} diff --git a/poi-radio/src/operator/mod.rs b/poi-radio/src/operator/mod.rs index e6da11fb..a6119bf2 100644 --- a/poi-radio/src/operator/mod.rs +++ b/poi-radio/src/operator/mod.rs @@ -9,7 +9,11 @@ use tracing::{debug, error, info, trace, warn}; use graphcast_sdk::{ build_wallet, - graphcast_agent::{message_typing::GraphcastMessage, GraphcastAgent}, + graphcast_agent::{ + message_typing::{check_message_validity, GraphcastMessage}, + waku_handling::WakuHandlingError, + GraphcastAgent, + }, graphql::client_graph_node::{subgraph_network_blocks, update_network_chainheads}, }; @@ -117,6 +121,7 @@ impl RadioOperator { let state_ref = persisted_state.clone(); let upgrade_notifier = notifier.clone(); let graph_node = config.graph_node_endpoint().clone(); + // try message format in order of PublicPOIMessage, VersionUpgradeMessage tokio::spawn(async move { for msg in receiver { @@ -124,11 +129,35 @@ impl RadioOperator { let agent = GRAPHCAST_AGENT .get() .expect("Could not retrieve Graphcast agent"); + let id_validation = agent.id_validation.clone(); + let callbook = agent.callbook.clone(); + let nonces = agent.nonces.clone(); + let local_sender = agent.graphcast_identity.graphcast_id.clone(); if let Ok(msg) = agent.decoder::(msg.payload()).await { trace!( message = tracing::field::debug(&msg), - "Parsed and validated as Public PoI message", + "Parseable as Public PoI message, now validate", ); + let msg = match check_message_validity( + msg, + &nonces, + callbook.clone(), + local_sender.clone(), + &id_validation, + ) + .await + .map_err(|e| WakuHandlingError::InvalidMessage(e.to_string())) + { + Ok(msg) => msg, + Err(e) => { + debug!( + err = tracing::field::debug(e), + "Failed to validate by Graphcast" + ); + continue; + } + }; + let identifier = msg.identifier.clone(); let is_valid = msg.payload.validity_check(&msg, &graph_node).await; @@ -150,8 +179,27 @@ impl RadioOperator { { trace!( message = tracing::field::debug(&msg), - "Parsed and validated as Version Upgrade message", + "Parseable as Version Upgrade message, now validate", ); + let msg = match check_message_validity( + msg, + &nonces, + callbook.clone(), + local_sender.clone(), + &id_validation, + ) + .await + .map_err(|e| WakuHandlingError::InvalidMessage(e.to_string())) + { + Ok(msg) => msg, + Err(e) => { + debug!( + err = tracing::field::debug(e), + "Failed to validate by Graphcast" + ); + continue; + } + }; let is_valid = msg.payload.validity_check(&msg, &graph_node).await; if let Ok(payload) = is_valid { diff --git a/poi-radio/src/state.rs b/poi-radio/src/state.rs index 566cf254..0a8b9536 100644 --- a/poi-radio/src/state.rs +++ b/poi-radio/src/state.rs @@ -1,14 +1,16 @@ use serde::{Deserialize, Serialize}; +use std::panic::PanicInfo; use std::path::Path; -use std::fs; +use std::str::FromStr; use std::sync::{Arc, Mutex as SyncMutex}; use std::{ collections::HashMap, fs::{remove_file, File}, io::{BufReader, Write}, }; +use std::{fs, panic}; use tracing::{info, trace, warn}; use graphcast_sdk::graphcast_agent::message_typing::GraphcastMessage; @@ -17,6 +19,7 @@ use crate::operator::attestation::{ clear_local_attestation, ComparisonResult, ComparisonResultType, }; use crate::operator::notifier::Notifier; +use crate::RADIO_OPERATOR; use crate::{messages::poi::PublicPoiMessage, operator::attestation::Attestation}; @@ -283,21 +286,21 @@ impl PersistedState { } // TODO: panic hook for updating the cache file before exiting the program -// /// Set up panic hook to store persisted state -// pub fn panic_hook<'a>(file_path: &str) { -// let path = String::from_str(file_path).expect("Invalid file path provided"); -// panic::set_hook(Box::new(move |panic_info| panic_cache(panic_info, &path))); -// } - -// pub fn panic_cache(panic_info: &PanicInfo<'_>, file_path: &str) { -// RADIO_OPERATOR -// .get() -// .unwrap() -// .state() -// .update_cache(file_path); -// // Log panic information and program state -// eprintln!("Panic occurred! Panic info: {:?}", panic_info); -// } +/// Set up panic hook to store persisted state +pub fn panic_hook(file_path: &str) { + let path = String::from_str(file_path).expect("Invalid file path provided"); + panic::set_hook(Box::new(move |panic_info| panic_cache(panic_info, &path))); +} + +pub fn panic_cache(panic_info: &PanicInfo<'_>, file_path: &str) { + RADIO_OPERATOR + .get() + .unwrap() + .state() + .update_cache(file_path); + // Log panic information and program state + eprintln!("Panic occurred! Panic info: {:?}", panic_info); +} #[cfg(test)] mod tests { diff --git a/test-runner/Cargo.toml b/test-runner/Cargo.toml index e8e53f86..4cd1ff32 100644 --- a/test-runner/Cargo.toml +++ b/test-runner/Cargo.toml @@ -23,8 +23,7 @@ categories = [ [dependencies] waku = { version = "0.1.1", package = "waku-bindings" } test-utils = { path = "../test-utils" } -# graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", rev = "f39cb28" } -graphcast-sdk = { package = "graphcast-sdk", path = "../../graphcast-rs" } +graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", rev = "99d942e" } poi-radio = { path = "../poi-radio" } tokio = { version = "1.1.1", features = ["full", "rt"] } tracing = "0.1" diff --git a/test-runner/src/topics.rs b/test-runner/src/topics.rs index e4e901cb..357cc1e9 100644 --- a/test-runner/src/topics.rs +++ b/test-runner/src/topics.rs @@ -108,16 +108,16 @@ pub async fn topics_test() { tokio::time::sleep(Duration::from_secs(50)).await; - let persisted_state = PersistedState::load_cache(&store_path); - debug!("persisted state {:?}", persisted_state); - - let remote_messages = persisted_state.remote_messages(); - let test_hash = "QmonlyintestsenderXyZABCdeFgHIjklMNOpqrstuvWXYZabcdEFG"; - let has_test_hash = remote_messages - .iter() - .any(|msg| msg.identifier == test_hash); - + let mut has_test_hash = test_result(&store_path, test_hash); + + let max_test_attempts = 3; + let mut num_test_attempts = 0; + while num_test_attempts < max_test_attempts && !has_test_hash { + tokio::time::sleep(Duration::from_secs(config.topic_update_interval + 1)).await; + has_test_hash = test_result(&store_path, test_hash); + num_test_attempts += 1; + } assert!( has_test_hash, "Expected remote message not found with identifier {}", @@ -126,3 +126,13 @@ pub async fn topics_test() { teardown(process_manager, &store_path); } + +fn test_result(store_path: &str, test_hash: &str) -> bool { + let persisted_state = PersistedState::load_cache(store_path); + debug!("persisted state {:?}", persisted_state); + + let remote_messages = persisted_state.remote_messages(); + remote_messages + .iter() + .any(|msg| msg.identifier == test_hash) +} diff --git a/test-sender/Cargo.toml b/test-sender/Cargo.toml index 76594aaa..b012fa5c 100644 --- a/test-sender/Cargo.toml +++ b/test-sender/Cargo.toml @@ -22,8 +22,7 @@ categories = [ [dependencies] waku = { version = "0.1.1", package = "waku-bindings" } -# graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", rev = "f39cb28" } -graphcast-sdk = { package = "graphcast-sdk", path = "../../graphcast-rs" } +graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", rev = "99d942e" } test-utils = { path = "../test-utils" } poi-radio = { path = "../poi-radio" } tokio = { version = "1.1.1", features = ["full", "rt"] } diff --git a/test-sender/src/main.rs b/test-sender/src/main.rs index 19be9f71..2e0bf960 100644 --- a/test-sender/src/main.rs +++ b/test-sender/src/main.rs @@ -71,9 +71,6 @@ async fn start_sender(config: TestSenderConfig) { let pubsub_topic = WakuPubSubTopic::from_str(pubsub_topic_str).unwrap(); loop { for topic in config.topics.clone() { - let timestamp = Utc::now().timestamp(); - let timestamp = (timestamp + 9) / 10 * 10; - let nodes = gather_nodes(vec![], &pubsub_topic); // Connect to peers on the filter protocol connect_multiaddresses(nodes, &node_handle, ProtocolId::Filter); @@ -81,7 +78,13 @@ async fn start_sender(config: TestSenderConfig) { let content_topic = format!("/{}/0/{}/proto", config.radio_name, topic); let content_topic = WakuContentTopic::from_str(&content_topic).unwrap(); - // let nonce = config.nonce.clone().unwrap().parse::().unwrap(); + let timestamp = + if let Some(n) = config.nonce.clone().and_then(|x| x.parse::().ok()) { + n + } else { + Utc::now().timestamp() + }; + let block_number = (timestamp + 9) / 10 * 10; let radio_payload_clone = config.radio_payload.clone(); match radio_payload_clone.as_deref() { @@ -91,7 +94,7 @@ async fn start_sender(config: TestSenderConfig) { config.poi.clone().unwrap(), timestamp, NetworkName::Goerli, - timestamp.try_into().unwrap(), + block_number.try_into().unwrap(), config.block_hash.clone().unwrap(), "0x7e6528e4ce3055e829a32b5dc4450072bac28bc6".to_string(), ); diff --git a/test-utils/Cargo.toml b/test-utils/Cargo.toml index 14b0cb33..fe3fe8e3 100644 --- a/test-utils/Cargo.toml +++ b/test-utils/Cargo.toml @@ -22,8 +22,7 @@ categories = [ [dependencies] waku = { version = "0.1.1", package = "waku-bindings" } -# graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", rev = "f39cb28" } -graphcast-sdk = { package = "graphcast-sdk", path = "../../graphcast-rs" } +graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", rev = "99d942e" } poi-radio = { path = "../poi-radio" } tokio = { version = "1.1.1", features = ["full", "rt"] } tracing = "0.1" diff --git a/test-utils/src/mock_server.rs b/test-utils/src/mock_server.rs index a766c34f..67e6f29a 100644 --- a/test-utils/src/mock_server.rs +++ b/test-utils/src/mock_server.rs @@ -59,7 +59,7 @@ pub async fn start_mock_server( async fn handler_graphql(subgraphs: Arc>>) -> Result { let timestamp = Utc::now().timestamp(); - let timestamp = (timestamp + 9) / 10 * 10; + let block_number = (timestamp + 9) / 10 * 10; let subgraphs = subgraphs.lock().await; // Prepare indexingStatuses part of the response dynamically from the subgraphs vector @@ -67,7 +67,7 @@ async fn handler_graphql(subgraphs: Arc>>) -> Result Date: Thu, 13 Jul 2023 22:06:50 +0300 Subject: [PATCH 5/7] refactor: fix tests --- Cargo.lock | 196 ++++++++++++++++++---------------- one-shot/Cargo.toml | 2 +- poi-radio/Cargo.toml | 2 +- poi-radio/src/operator/mod.rs | 5 +- test-runner/Cargo.toml | 2 +- test-runner/src/main.rs | 102 +++++++++--------- test-runner/src/topics.rs | 30 ++---- test-sender/Cargo.toml | 2 +- test-sender/src/main.rs | 11 +- test-utils/Cargo.toml | 2 +- test-utils/src/lib.rs | 8 +- 11 files changed, 173 insertions(+), 189 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 41106e1e..f840f0ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -167,9 +167,9 @@ dependencies = [ [[package]] name = "async-channel" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", "event-listener", @@ -273,7 +273,7 @@ checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.25", ] [[package]] @@ -295,7 +295,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.25", ] [[package]] @@ -306,7 +306,7 @@ checksum = "a564d521dd56509c4c47480d00b80ee55f7e385ae48db5744c67ad50c92d2ebf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.25", ] [[package]] @@ -691,9 +691,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.4" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" dependencies = [ "serde", ] @@ -706,9 +706,9 @@ checksum = "7b02b629252fe8ef6460461409564e2c21d0c8e77e0944f3d189ff06c4e932ad" [[package]] name = "cargo-platform" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" +checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479" dependencies = [ "serde", ] @@ -890,7 +890,7 @@ dependencies = [ "getrandom 0.2.10", "hmac", "once_cell", - "pbkdf2 0.12.1", + "pbkdf2 0.12.2", "rand 0.8.5", "sha2 0.10.7", "thiserror", @@ -940,9 +940,9 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6340df57935414636969091153f35f68d9f00bbc8fb4a9c6054706c213e6c6bc" +checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747" [[package]] name = "const_format" @@ -1240,12 +1240,12 @@ dependencies = [ [[package]] name = "dashmap" -version = "5.4.0" +version = "5.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" +checksum = "6943ae99c34386c84a470c499d3414f66502a41340aa895406e0d2e4a207b91d" dependencies = [ "cfg-if", - "hashbrown 0.12.3", + "hashbrown 0.14.0", "lock_api", "once_cell", "parking_lot_core", @@ -1544,9 +1544,9 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "erasable" @@ -1715,8 +1715,8 @@ dependencies = [ "reqwest", "serde", "serde_json", - "syn 2.0.23", - "toml 0.7.5", + "syn 2.0.25", + "toml 0.7.6", "walkdir", ] @@ -1733,7 +1733,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.23", + "syn 2.0.25", ] [[package]] @@ -1790,7 +1790,7 @@ dependencies = [ "serde", "serde_json", "strum", - "syn 2.0.23", + "syn 2.0.25", "tempfile", "thiserror", "tiny-keccak", @@ -2170,7 +2170,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.25", ] [[package]] @@ -2294,7 +2294,7 @@ dependencies = [ [[package]] name = "graphcast-sdk" version = "0.3.4" -source = "git+https://github.com/graphops/graphcast-sdk?rev=99d942e#99d942edebb70e2c148c2d0a2008344060107903" +source = "git+https://github.com/graphops/graphcast-sdk?branch=hope/subgraph-owner-check#29fdf3c1f4ab0b655e424d288c282e67e0a6cc07" dependencies = [ "anyhow", "async-graphql", @@ -2326,7 +2326,7 @@ dependencies = [ "teloxide", "thiserror", "tokio", - "toml 0.7.5", + "toml 0.7.6", "tracing", "tracing-subscriber", "url", @@ -2863,12 +2863,12 @@ checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" [[package]] name = "is-terminal" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24fddda5af7e54bf7da53067d6e802dbcc381d0a8eef629df528e3ebf68755cb" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi 0.3.2", - "rustix 0.38.3", + "rustix 0.38.4", "windows-sys", ] @@ -3381,7 +3381,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.25", ] [[package]] @@ -3507,7 +3507,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.25", ] [[package]] @@ -3691,9 +3691,9 @@ dependencies = [ [[package]] name = "pbkdf2" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0ca0b5a68607598bf3bad68f32227a8164f6254833f84eafaac409cd6746c31" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" dependencies = [ "digest 0.10.7", "hmac", @@ -3771,7 +3771,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.25", ] [[package]] @@ -3809,7 +3809,7 @@ checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.25", ] [[package]] @@ -3945,14 +3945,14 @@ version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e30165d31df606f5726b090ec7592c308a0eaf61721ff64c9a3018e344a8753e" dependencies = [ - "portable-atomic 1.3.3", + "portable-atomic 1.4.0", ] [[package]] name = "portable-atomic" -version = "1.3.3" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "767eb9f07d4a5ebcb39bbf2d452058a93c011373abf6832e24194a1c3f004794" +checksum = "d220334a184db82b31b83f5ff093e3315280fb2b6bbc032022b2304a509aab7a" [[package]] name = "ppv-lite86" @@ -3973,7 +3973,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92139198957b410250d43fad93e630d956499a625c527eda65175c8680f83387" dependencies = [ "proc-macro2", - "syn 2.0.23", + "syn 2.0.25", ] [[package]] @@ -4026,9 +4026,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" +checksum = "78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da" dependencies = [ "unicode-ident", ] @@ -4057,7 +4057,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "time 0.3.22", + "time 0.3.23", "url", ] @@ -4269,14 +4269,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89089e897c013b3deb627116ae56a6955a72b8bed395c9526af31c9fe528b484" +checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.3.0", - "regex-syntax 0.7.3", + "regex-automata 0.3.3", + "regex-syntax 0.7.4", ] [[package]] @@ -4290,13 +4290,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.0" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa250384981ea14565685dea16a9ccc4d1c541a13f82b9c168572264d1df8c56" +checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.3", + "regex-syntax 0.7.4", ] [[package]] @@ -4307,9 +4307,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab07dc67230e4a4718e70fd5c20055a4334b121f1f9db8fe63ef39ce9b8c846" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" [[package]] name = "reqwest" @@ -4483,9 +4483,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.3" +version = "0.38.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac5ffa1efe7548069688cd7028f32591853cd7b5b756d41bcffd2353e4fc75b4" +checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" dependencies = [ "bitflags 2.3.3", "errno", @@ -4496,13 +4496,13 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.2" +version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e32ca28af694bc1bbf399c33a516dbdf1c90090b8ab23c2bc24f834aa2247f5f" +checksum = "79ea77c539259495ce8ca47f53e66ae0330a8819f67e23ac96ca02f50e7b7d36" dependencies = [ "log", "ring", - "rustls-webpki", + "rustls-webpki 0.101.1", "sct", ] @@ -4537,6 +4537,16 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustls-webpki" +version = "0.101.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15f36a6828982f422756984e47912a7a51dcbc2a197aa791158f8ca61cd8204e" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.13" @@ -4787,29 +4797,29 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.166" +version = "1.0.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d01b7404f9d441d3ad40e6a636a7782c377d2abdbe4fa2440e2edcc2f4f10db8" +checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.166" +version = "1.0.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dd83d6dde2b6b2d466e14d9d1acce8816dedee94f735eac6395808b3483c6d6" +checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.25", ] [[package]] name = "serde_json" -version = "1.0.100" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f1e14e89be7aa4c4b78bdbdc9eb5bf8517829a600ae8eaa39a6e1d960b5185c" +checksum = "b5062a995d481b2308b6064e9af76011f2921c35f97b0468811ed9f6cd91dfed" dependencies = [ "itoa", "ryu", @@ -4818,9 +4828,9 @@ dependencies = [ [[package]] name = "serde_path_to_error" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b1b6471d7496b051e03f1958802a73f88b947866f5146f329e47e36554f4e55" +checksum = "8acc4422959dd87a76cb117c191dcbffc20467f06c9100b76721dab370f24d3a" dependencies = [ "itoa", "serde", @@ -5027,9 +5037,9 @@ dependencies = [ [[package]] name = "slack-morphism" -version = "1.12.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48ae1450a14bf7a4588b25fdee8668d94eb69f079581ddaf48a1a767befd2e9e" +checksum = "68424167daf78e9e80d440d21fdac021c2693b111470f55bd1be1083c8391112" dependencies = [ "async-recursion", "async-trait", @@ -5067,9 +5077,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" [[package]] name = "smart-default" @@ -5161,7 +5171,7 @@ dependencies = [ "quote", "regex-syntax 0.6.29", "strsim", - "syn 2.0.23", + "syn 2.0.25", "unicode-width", ] @@ -5251,9 +5261,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.23" +version = "2.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59fb7d6d8281a51045d62b8eb3a7d1ce347b76f312af50cd3dc0af39c87c1737" +checksum = "15e3fc8c0c74267e2df136e5e5fb656a464158aa57624053375eb9c8c6e25ae2" dependencies = [ "proc-macro2", "quote", @@ -5465,22 +5475,22 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.41" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c16a64ba9387ef3fdae4f9c1a7f07a0997fce91985c0336f1ddc1822b3b37802" +checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.41" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d14928354b01c4d6a4f0e549069adef399a284e7995c7ccca94e8a07a5346c59" +checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.25", ] [[package]] @@ -5505,9 +5515,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.22" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd" +checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446" dependencies = [ "serde", "time-core", @@ -5522,9 +5532,9 @@ checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" [[package]] name = "time-macros" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" +checksum = "96ba15a897f3c86766b757e5ac7221554c6750054d74d5b28844fce5fb36a6c4" dependencies = [ "time-core", ] @@ -5592,7 +5602,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.25", ] [[package]] @@ -5680,9 +5690,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebafdf5ad1220cb59e7d17cf4d2c72015297b75b19a10472f99b89225089240" +checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" dependencies = [ "serde", "serde_spanned", @@ -5701,9 +5711,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.19.11" +version = "0.19.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266f016b7f039eec8a1a80dfe6156b633d208b9fccca5e4db1d6775b0c4e34a7" +checksum = "c500344a19072298cd05a7224b3c0c629348b78692bf48466c5238656e315a78" dependencies = [ "indexmap 2.0.0", "serde", @@ -5799,7 +5809,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.25", ] [[package]] @@ -5932,9 +5942,9 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "ucd-trie" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" [[package]] name = "uint" @@ -6183,7 +6193,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.25", "wasm-bindgen-shared", ] @@ -6217,7 +6227,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn 2.0.25", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6276,7 +6286,7 @@ version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b03058f88386e5ff5310d9111d53f48b17d732b401aeb83a8d5190f2ac459338" dependencies = [ - "rustls-webpki", + "rustls-webpki 0.100.1", ] [[package]] @@ -6398,9 +6408,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "winnow" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448" +checksum = "81a2094c43cc94775293eaa0e499fbc30048a6d824ac82c0351a8c0bf9112529" dependencies = [ "memchr", ] @@ -6492,7 +6502,7 @@ dependencies = [ "hmac", "pbkdf2 0.11.0", "sha1", - "time 0.3.22", + "time 0.3.23", "zstd", ] diff --git a/one-shot/Cargo.toml b/one-shot/Cargo.toml index a17332c4..2c5f0387 100644 --- a/one-shot/Cargo.toml +++ b/one-shot/Cargo.toml @@ -10,7 +10,7 @@ keywords = ["graphprotocol", "data-integrity", "Indexer", "waku", "p2p"] categories = ["network-programming", "web-programming::http-client"] [dependencies] -graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", rev = "99d942e" } +graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", branch = "hope/subgraph-owner-check" } poi-radio = { path = "../poi-radio" } prost = "0.11" once_cell = "1.17" diff --git a/poi-radio/Cargo.toml b/poi-radio/Cargo.toml index 6f69c949..6d089012 100644 --- a/poi-radio/Cargo.toml +++ b/poi-radio/Cargo.toml @@ -10,7 +10,7 @@ keywords = ["graphprotocol", "data-integrity", "Indexer", "waku", "p2p"] categories = ["network-programming", "web-programming::http-client"] [dependencies] -graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", rev = "99d942e" } +graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", branch = "hope/subgraph-owner-check" } prost = "0.11" once_cell = "1.17" chrono = "0.4" diff --git a/poi-radio/src/operator/mod.rs b/poi-radio/src/operator/mod.rs index a6119bf2..4ff0b70c 100644 --- a/poi-radio/src/operator/mod.rs +++ b/poi-radio/src/operator/mod.rs @@ -133,7 +133,7 @@ impl RadioOperator { let callbook = agent.callbook.clone(); let nonces = agent.nonces.clone(); let local_sender = agent.graphcast_identity.graphcast_id.clone(); - if let Ok(msg) = agent.decoder::(msg.payload()).await { + if let Ok(msg) = agent.decode::(msg.payload()).await { trace!( message = tracing::field::debug(&msg), "Parseable as Public PoI message, now validate", @@ -175,8 +175,7 @@ impl RadioOperator { .unwrap(), ); }; - } else if let Ok(msg) = agent.decoder::(msg.payload()).await - { + } else if let Ok(msg) = agent.decode::(msg.payload()).await { trace!( message = tracing::field::debug(&msg), "Parseable as Version Upgrade message, now validate", diff --git a/test-runner/Cargo.toml b/test-runner/Cargo.toml index 4cd1ff32..7e44ee45 100644 --- a/test-runner/Cargo.toml +++ b/test-runner/Cargo.toml @@ -23,7 +23,7 @@ categories = [ [dependencies] waku = { version = "0.1.1", package = "waku-bindings" } test-utils = { path = "../test-utils" } -graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", rev = "99d942e" } +graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", branch = "hope/subgraph-owner-check" } poi-radio = { path = "../poi-radio" } tokio = { version = "1.1.1", features = ["full", "rt"] } tracing = "0.1" diff --git a/test-runner/src/main.rs b/test-runner/src/main.rs index 03f24ba2..a20defd0 100644 --- a/test-runner/src/main.rs +++ b/test-runner/src/main.rs @@ -38,16 +38,16 @@ pub async fn main() { let config = test_config(); std::env::set_var( - "RUST_LOG", - "off,hyper=off,graphcast_sdk=trace,poi_radio=trace,test_runner=trace,test_sender=trace,test_utils=trace", - ); + "RUST_LOG", + "off,hyper=off,graphcast_sdk=trace,poi_radio=trace,test_runner=trace,test_sender=trace,test_utils=trace", + ); init_tracing(config.log_format).expect("Could not set up global default subscriber for logger, check environmental variable `RUST_LOG` or the CLI input `log-level"); let start_time = Instant::now(); - let mut retry_count = 3; - let mut initial_test_results: HashMap = HashMap::new(); + let mut retry_count = 5; let mut initial_tests_passed = false; + let mut initial_test_results: HashMap = HashMap::new(); while retry_count > 0 && !initial_tests_passed { let initial_tests = vec![ @@ -68,58 +68,51 @@ pub async fn main() { } } - if initial_tests_passed { - let poi_tests = vec![ - ("poi_divergent_test", tokio::spawn(poi_divergent_test())), - ("poi_match_test", tokio::spawn(poi_match_test())), - ]; - - let (poi_tests_passed, poi_test_results) = run_tests(poi_tests).await; - if poi_tests_passed { - let remaining_tests = vec![ - ( - "invalid_block_hash_test", - tokio::spawn(invalid_block_hash_test()), - ), - ("invalid_sender_test", tokio::spawn(invalid_sender_test())), - ("invalid_nonce_test", tokio::spawn(invalid_nonce_test())), - ("invalid_payload_test", tokio::spawn(invalid_payload_test())), - ]; - - let (remaining_tests_passed, remaining_test_results) = run_tests(remaining_tests).await; - - print_test_summary( - initial_test_results, - poi_test_results, - remaining_test_results, - remaining_tests_passed, - start_time, - ); - } else { - print_test_summary( - initial_test_results, - poi_test_results, - HashMap::new(), - false, - start_time, - ); - } - } else { - print_test_summary( - initial_test_results, - HashMap::new(), - HashMap::new(), - false, - start_time, - ); - } + let poi_tests = vec![ + ("poi_divergent_test", tokio::spawn(poi_divergent_test())), + ("poi_match_test", tokio::spawn(poi_match_test())), + ]; + + let (poi_tests_passed, poi_test_results) = run_tests(poi_tests).await; + + let validity_tests_group_1 = vec![ + ( + "invalid_block_hash_test", + tokio::spawn(invalid_block_hash_test()), + ), + ("invalid_sender_test", tokio::spawn(invalid_sender_test())), + ]; + + let (validity_tests_group_1_passed, validity_test_results_group_1) = + run_tests(validity_tests_group_1).await; + + let validity_tests_group_2 = vec![ + ("invalid_nonce_test", tokio::spawn(invalid_nonce_test())), + ("invalid_payload_test", tokio::spawn(invalid_payload_test())), + ]; + + let (validity_tests_group_2_passed, validity_test_results_group_2) = + run_tests(validity_tests_group_2).await; + + print_test_summary( + initial_test_results, + poi_test_results, + validity_test_results_group_1, + validity_test_results_group_2, + initial_tests_passed + && poi_tests_passed + && validity_tests_group_1_passed + && validity_tests_group_2_passed, + start_time, + ); } fn print_test_summary( initial_test_results: HashMap, poi_test_results: HashMap, - remaining_test_results: HashMap, - remaining_tests_passed: bool, + validity_test_results_group_1: HashMap, + validity_test_results_group_2: HashMap, + tests_passed: bool, start_time: Instant, ) { let elapsed_time = start_time.elapsed(); @@ -128,7 +121,8 @@ fn print_test_summary( for (test_name, passed) in initial_test_results .iter() .chain(&poi_test_results) - .chain(&remaining_test_results) + .chain(&validity_test_results_group_1) + .chain(&validity_test_results_group_2) { if *passed { info!("{}: PASSED", test_name); @@ -137,7 +131,7 @@ fn print_test_summary( } } - if remaining_tests_passed { + if tests_passed { info!( "All tests passed ✅. Time elapsed: {}s", elapsed_time.as_secs() diff --git a/test-runner/src/topics.rs b/test-runner/src/topics.rs index 357cc1e9..df4fc146 100644 --- a/test-runner/src/topics.rs +++ b/test-runner/src/topics.rs @@ -25,7 +25,7 @@ pub async fn topics_test() { let mut config = test_config(); config.persistence_file_path = Some(store_path.clone()); config.topics = radio_topics.clone(); - config.topic_update_interval = 10; + config.topic_update_interval = 90; let mut test_sender_config = TestSenderConfig { topics: test_sender_topics, @@ -108,16 +108,16 @@ pub async fn topics_test() { tokio::time::sleep(Duration::from_secs(50)).await; + let persisted_state = PersistedState::load_cache(&store_path); + debug!("persisted state {:?}", persisted_state); + + let remote_messages = persisted_state.remote_messages(); + let test_hash = "QmonlyintestsenderXyZABCdeFgHIjklMNOpqrstuvWXYZabcdEFG"; - let mut has_test_hash = test_result(&store_path, test_hash); - - let max_test_attempts = 3; - let mut num_test_attempts = 0; - while num_test_attempts < max_test_attempts && !has_test_hash { - tokio::time::sleep(Duration::from_secs(config.topic_update_interval + 1)).await; - has_test_hash = test_result(&store_path, test_hash); - num_test_attempts += 1; - } + let has_test_hash = remote_messages + .iter() + .any(|msg| msg.identifier == test_hash); + assert!( has_test_hash, "Expected remote message not found with identifier {}", @@ -126,13 +126,3 @@ pub async fn topics_test() { teardown(process_manager, &store_path); } - -fn test_result(store_path: &str, test_hash: &str) -> bool { - let persisted_state = PersistedState::load_cache(store_path); - debug!("persisted state {:?}", persisted_state); - - let remote_messages = persisted_state.remote_messages(); - remote_messages - .iter() - .any(|msg| msg.identifier == test_hash) -} diff --git a/test-sender/Cargo.toml b/test-sender/Cargo.toml index b012fa5c..8714dc88 100644 --- a/test-sender/Cargo.toml +++ b/test-sender/Cargo.toml @@ -22,7 +22,7 @@ categories = [ [dependencies] waku = { version = "0.1.1", package = "waku-bindings" } -graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", rev = "99d942e" } +graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", branch = "hope/subgraph-owner-check" } test-utils = { path = "../test-utils" } poi-radio = { path = "../poi-radio" } tokio = { version = "1.1.1", features = ["full", "rt"] } diff --git a/test-sender/src/main.rs b/test-sender/src/main.rs index 2e0bf960..ff41c432 100644 --- a/test-sender/src/main.rs +++ b/test-sender/src/main.rs @@ -78,12 +78,9 @@ async fn start_sender(config: TestSenderConfig) { let content_topic = format!("/{}/0/{}/proto", config.radio_name, topic); let content_topic = WakuContentTopic::from_str(&content_topic).unwrap(); - let timestamp = - if let Some(n) = config.nonce.clone().and_then(|x| x.parse::().ok()) { - n - } else { - Utc::now().timestamp() - }; + let nonce = config.nonce.clone().and_then(|s| s.parse::().ok()); + + let timestamp = Utc::now().timestamp(); let block_number = (timestamp + 9) / 10 * 10; let radio_payload_clone = config.radio_payload.clone(); @@ -92,7 +89,7 @@ async fn start_sender(config: TestSenderConfig) { let radio_payload = PublicPoiMessage::build( topic.clone(), config.poi.clone().unwrap(), - timestamp, + nonce.unwrap_or(timestamp), NetworkName::Goerli, block_number.try_into().unwrap(), config.block_hash.clone().unwrap(), diff --git a/test-utils/Cargo.toml b/test-utils/Cargo.toml index fe3fe8e3..eeab7cbf 100644 --- a/test-utils/Cargo.toml +++ b/test-utils/Cargo.toml @@ -22,7 +22,7 @@ categories = [ [dependencies] waku = { version = "0.1.1", package = "waku-bindings" } -graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", rev = "99d942e" } +graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", branch = "hope/subgraph-owner-check" } poi-radio = { path = "../poi-radio" } tokio = { version = "1.1.1", features = ["full", "rt"] } tracing = "0.1" diff --git a/test-utils/src/lib.rs b/test-utils/src/lib.rs index 5629d941..9338b57a 100644 --- a/test-utils/src/lib.rs +++ b/test-utils/src/lib.rs @@ -8,7 +8,6 @@ use std::{ time::Duration, }; -use chrono::Utc; use config::TestSenderConfig; use graphcast_sdk::graphcast_agent::message_typing::GraphcastMessage; use graphcast_sdk::graphcast_agent::message_typing::IdentityValidation; @@ -96,12 +95,7 @@ pub async fn setup( "4dbba1ba9fb18b0034965712598be1368edcf91ae2c551d59462aab578dab9c5".to_string(), )) .arg("--nonce") - .arg( - &test_sender_config - .nonce - .clone() - .unwrap_or(Utc::now().timestamp().to_string()), - ) + .arg(test_sender_config.nonce.as_deref().unwrap_or("None")) .arg("--radio-payload") .arg( test_sender_config From abff8a8972975466e0acf7fc22d6c3f3ed2fd7b3 Mon Sep 17 00:00:00 2001 From: hopeyen Date: Thu, 13 Jul 2023 15:15:21 -0500 Subject: [PATCH 6/7] chore: grafana config and sdk-dep update --- Cargo.lock | 2 +- one-shot/Cargo.toml | 2 +- poi-radio-grafana.json | 32 +++++++++++++++++++++----------- poi-radio/Cargo.toml | 2 +- test-runner/Cargo.toml | 2 +- test-sender/Cargo.toml | 2 +- test-utils/Cargo.toml | 2 +- 7 files changed, 27 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f840f0ab..7c436767 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2294,7 +2294,7 @@ dependencies = [ [[package]] name = "graphcast-sdk" version = "0.3.4" -source = "git+https://github.com/graphops/graphcast-sdk?branch=hope/subgraph-owner-check#29fdf3c1f4ab0b655e424d288c282e67e0a6cc07" +source = "git+https://github.com/graphops/graphcast-sdk#dcb2653528f7e20521a2b17d671cae41ecf192d2" dependencies = [ "anyhow", "async-graphql", diff --git a/one-shot/Cargo.toml b/one-shot/Cargo.toml index 2c5f0387..f48e0252 100644 --- a/one-shot/Cargo.toml +++ b/one-shot/Cargo.toml @@ -10,7 +10,7 @@ keywords = ["graphprotocol", "data-integrity", "Indexer", "waku", "p2p"] categories = ["network-programming", "web-programming::http-client"] [dependencies] -graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", branch = "hope/subgraph-owner-check" } +graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk" } poi-radio = { path = "../poi-radio" } prost = "0.11" once_cell = "1.17" diff --git a/poi-radio-grafana.json b/poi-radio-grafana.json index b056bdc2..27bfd981 100644 --- a/poi-radio-grafana.json +++ b/poi-radio-grafana.json @@ -37,7 +37,8 @@ "mode": "percentage", "steps": [ { - "color": "green" + "color": "green", + "value": null } ] } @@ -55,7 +56,8 @@ "mode": "absolute", "steps": [ { - "color": "green" + "color": "green", + "value": null }, { "color": "#EAB839", @@ -176,7 +178,8 @@ "mode": "absolute", "steps": [ { - "color": "green" + "color": "green", + "value": null } ] } @@ -278,7 +281,8 @@ "mode": "absolute", "steps": [ { - "color": "green" + "color": "green", + "value": null }, { "color": "red", @@ -379,7 +383,8 @@ "mode": "absolute", "steps": [ { - "color": "green" + "color": "green", + "value": null }, { "color": "red", @@ -491,7 +496,8 @@ "mode": "absolute", "steps": [ { - "color": "green" + "color": "green", + "value": null }, { "color": "red", @@ -603,7 +609,8 @@ "mode": "absolute", "steps": [ { - "color": "green" + "color": "green", + "value": null }, { "color": "red", @@ -715,7 +722,8 @@ "mode": "absolute", "steps": [ { - "color": "green" + "color": "green", + "value": null }, { "color": "red", @@ -839,7 +847,8 @@ "mode": "absolute", "steps": [ { - "color": "green" + "color": "green", + "value": null }, { "color": "red", @@ -926,7 +935,8 @@ "mode": "absolute", "steps": [ { - "color": "green" + "color": "green", + "value": null }, { "color": "red", @@ -1123,4 +1133,4 @@ "uid": "WzeduAYVz", "version": 61, "weekStart": "" -} \ No newline at end of file +} diff --git a/poi-radio/Cargo.toml b/poi-radio/Cargo.toml index 6d089012..42aa6c10 100644 --- a/poi-radio/Cargo.toml +++ b/poi-radio/Cargo.toml @@ -10,7 +10,7 @@ keywords = ["graphprotocol", "data-integrity", "Indexer", "waku", "p2p"] categories = ["network-programming", "web-programming::http-client"] [dependencies] -graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", branch = "hope/subgraph-owner-check" } +graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk" } prost = "0.11" once_cell = "1.17" chrono = "0.4" diff --git a/test-runner/Cargo.toml b/test-runner/Cargo.toml index 7e44ee45..33520645 100644 --- a/test-runner/Cargo.toml +++ b/test-runner/Cargo.toml @@ -23,7 +23,7 @@ categories = [ [dependencies] waku = { version = "0.1.1", package = "waku-bindings" } test-utils = { path = "../test-utils" } -graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", branch = "hope/subgraph-owner-check" } +graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk" } poi-radio = { path = "../poi-radio" } tokio = { version = "1.1.1", features = ["full", "rt"] } tracing = "0.1" diff --git a/test-sender/Cargo.toml b/test-sender/Cargo.toml index 8714dc88..17cb8fb9 100644 --- a/test-sender/Cargo.toml +++ b/test-sender/Cargo.toml @@ -22,7 +22,7 @@ categories = [ [dependencies] waku = { version = "0.1.1", package = "waku-bindings" } -graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", branch = "hope/subgraph-owner-check" } +graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk" } test-utils = { path = "../test-utils" } poi-radio = { path = "../poi-radio" } tokio = { version = "1.1.1", features = ["full", "rt"] } diff --git a/test-utils/Cargo.toml b/test-utils/Cargo.toml index eeab7cbf..7b3d93c2 100644 --- a/test-utils/Cargo.toml +++ b/test-utils/Cargo.toml @@ -22,7 +22,7 @@ categories = [ [dependencies] waku = { version = "0.1.1", package = "waku-bindings" } -graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk", branch = "hope/subgraph-owner-check" } +graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk" } poi-radio = { path = "../poi-radio" } tokio = { version = "1.1.1", features = ["full", "rt"] } tracing = "0.1" From 0f0af4e49a915cb975a4d4ce9394064f52ce48cb Mon Sep 17 00:00:00 2001 From: axiomatic-aardvark Date: Fri, 14 Jul 2023 14:30:08 +0300 Subject: [PATCH 7/7] chore: update sdk dep to 0.4.0 --- Cargo.lock | 13 +++++++------ one-shot/Cargo.toml | 2 +- poi-radio/Cargo.toml | 2 +- test-runner/Cargo.toml | 2 +- test-sender/Cargo.toml | 2 +- test-utils/Cargo.toml | 2 +- 6 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7c436767..af6e98a4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2293,8 +2293,9 @@ dependencies = [ [[package]] name = "graphcast-sdk" -version = "0.3.4" -source = "git+https://github.com/graphops/graphcast-sdk#dcb2653528f7e20521a2b17d671cae41ecf192d2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d84f56df57a05e3e01f08c3cce8ef8ce2feefc81ebfc50af9353b9060fb5f7c1" dependencies = [ "anyhow", "async-graphql", @@ -5711,9 +5712,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.19.12" +version = "0.19.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c500344a19072298cd05a7224b3c0c629348b78692bf48466c5238656e315a78" +checksum = "5f8751d9c1b03c6500c387e96f81f815a4f8e72d142d2d4a9ffa6fedd51ddee7" dependencies = [ "indexmap 2.0.0", "serde", @@ -6408,9 +6409,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "winnow" -version = "0.4.9" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81a2094c43cc94775293eaa0e499fbc30048a6d824ac82c0351a8c0bf9112529" +checksum = "81fac9742fd1ad1bd9643b991319f72dd031016d44b77039a26977eb667141e7" dependencies = [ "memchr", ] diff --git a/one-shot/Cargo.toml b/one-shot/Cargo.toml index f48e0252..9fae187a 100644 --- a/one-shot/Cargo.toml +++ b/one-shot/Cargo.toml @@ -10,7 +10,7 @@ keywords = ["graphprotocol", "data-integrity", "Indexer", "waku", "p2p"] categories = ["network-programming", "web-programming::http-client"] [dependencies] -graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk" } +graphcast-sdk = "0.4.0" poi-radio = { path = "../poi-radio" } prost = "0.11" once_cell = "1.17" diff --git a/poi-radio/Cargo.toml b/poi-radio/Cargo.toml index 42aa6c10..f8a027d5 100644 --- a/poi-radio/Cargo.toml +++ b/poi-radio/Cargo.toml @@ -10,7 +10,7 @@ keywords = ["graphprotocol", "data-integrity", "Indexer", "waku", "p2p"] categories = ["network-programming", "web-programming::http-client"] [dependencies] -graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk" } +graphcast-sdk = "0.4.0" prost = "0.11" once_cell = "1.17" chrono = "0.4" diff --git a/test-runner/Cargo.toml b/test-runner/Cargo.toml index 33520645..5bd23d7b 100644 --- a/test-runner/Cargo.toml +++ b/test-runner/Cargo.toml @@ -23,7 +23,7 @@ categories = [ [dependencies] waku = { version = "0.1.1", package = "waku-bindings" } test-utils = { path = "../test-utils" } -graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk" } +graphcast-sdk = "0.4.0" poi-radio = { path = "../poi-radio" } tokio = { version = "1.1.1", features = ["full", "rt"] } tracing = "0.1" diff --git a/test-sender/Cargo.toml b/test-sender/Cargo.toml index 17cb8fb9..3968026e 100644 --- a/test-sender/Cargo.toml +++ b/test-sender/Cargo.toml @@ -22,7 +22,7 @@ categories = [ [dependencies] waku = { version = "0.1.1", package = "waku-bindings" } -graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk" } +graphcast-sdk = "0.4.0" test-utils = { path = "../test-utils" } poi-radio = { path = "../poi-radio" } tokio = { version = "1.1.1", features = ["full", "rt"] } diff --git a/test-utils/Cargo.toml b/test-utils/Cargo.toml index 7b3d93c2..2fdd740a 100644 --- a/test-utils/Cargo.toml +++ b/test-utils/Cargo.toml @@ -22,7 +22,7 @@ categories = [ [dependencies] waku = { version = "0.1.1", package = "waku-bindings" } -graphcast-sdk = { package = "graphcast-sdk", git = "https://github.com/graphops/graphcast-sdk" } +graphcast-sdk = "0.4.0" poi-radio = { path = "../poi-radio" } tokio = { version = "1.1.1", features = ["full", "rt"] } tracing = "0.1"