diff --git a/chain/arweave/src/adapter.rs b/chain/arweave/src/adapter.rs index 5b71ca8cb16..fd2d962e31e 100644 --- a/chain/arweave/src/adapter.rs +++ b/chain/arweave/src/adapter.rs @@ -1,4 +1,3 @@ -use crate::capabilities::NodeCapabilities; use crate::{data_source::DataSource, Chain}; use graph::blockchain as bc; use graph::prelude::*; @@ -26,8 +25,8 @@ impl bc::TriggerFilter for TriggerFilter { transaction_filter.extend(ArweaveTransactionFilter::from_data_sources(data_sources)); } - fn node_capabilities(&self) -> NodeCapabilities { - NodeCapabilities {} + fn node_capabilities(&self) -> bc::EmptyNodeCapabilities { + bc::EmptyNodeCapabilities::default() } fn extend_with_template( diff --git a/chain/arweave/src/capabilities.rs b/chain/arweave/src/capabilities.rs deleted file mode 100644 index 27c7622aeb5..00000000000 --- a/chain/arweave/src/capabilities.rs +++ /dev/null @@ -1,37 +0,0 @@ -use graph::{anyhow::Error, impl_slog_value}; -use std::cmp::{Ordering, PartialOrd}; -use std::fmt; -use std::str::FromStr; - -use crate::data_source::DataSource; - -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub struct NodeCapabilities {} - -impl PartialOrd for NodeCapabilities { - fn partial_cmp(&self, _other: &Self) -> Option { - None - } -} - -impl FromStr for NodeCapabilities { - type Err = Error; - - fn from_str(_s: &str) -> Result { - Ok(NodeCapabilities {}) - } -} - -impl fmt::Display for NodeCapabilities { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str("arweave") - } -} - -impl_slog_value!(NodeCapabilities, "{}"); - -impl graph::blockchain::NodeCapabilities for NodeCapabilities { - fn from_data_sources(_data_sources: &[DataSource]) -> Self { - NodeCapabilities {} - } -} diff --git a/chain/arweave/src/chain.rs b/chain/arweave/src/chain.rs index 6a01857dbe7..6e11c3029b5 100644 --- a/chain/arweave/src/chain.rs +++ b/chain/arweave/src/chain.rs @@ -1,4 +1,4 @@ -use graph::blockchain::{Block, BlockchainKind}; +use graph::blockchain::{Block, BlockchainKind, EmptyNodeCapabilities}; use graph::cheap_clone::CheapClone; use graph::data::subgraph::UnifiedMappingApiVersion; use graph::firehose::{FirehoseEndpoint, FirehoseEndpoints}; @@ -20,7 +20,6 @@ use prost::Message; use std::sync::Arc; use crate::adapter::TriggerFilter; -use crate::capabilities::NodeCapabilities; use crate::data_source::{DataSourceTemplate, UnresolvedDataSourceTemplate}; use crate::runtime::RuntimeAdapter; use crate::trigger::{self, ArweaveTrigger}; @@ -82,7 +81,7 @@ impl Blockchain for Chain { type TriggerFilter = crate::adapter::TriggerFilter; - type NodeCapabilities = crate::capabilities::NodeCapabilities; + type NodeCapabilities = EmptyNodeCapabilities; fn triggers_adapter( &self, @@ -116,7 +115,11 @@ impl Blockchain for Chain { unified_api_version: UnifiedMappingApiVersion, ) -> Result>, Error> { let adapter = self - .triggers_adapter(&deployment, &NodeCapabilities {}, unified_api_version) + .triggers_adapter( + &deployment, + &EmptyNodeCapabilities::default(), + unified_api_version, + ) .unwrap_or_else(|_| panic!("no adapter for network {}", self.name)); let firehose_endpoint = self.firehose_endpoints.random()?; diff --git a/chain/arweave/src/lib.rs b/chain/arweave/src/lib.rs index a497e77bf9d..77e63bc51ab 100644 --- a/chain/arweave/src/lib.rs +++ b/chain/arweave/src/lib.rs @@ -1,5 +1,4 @@ mod adapter; -mod capabilities; mod chain; mod codec; mod data_source; diff --git a/chain/cosmos/src/adapter.rs b/chain/cosmos/src/adapter.rs index d73b8b0ec55..746c91e2e07 100644 --- a/chain/cosmos/src/adapter.rs +++ b/chain/cosmos/src/adapter.rs @@ -3,7 +3,6 @@ use std::collections::HashSet; use prost::Message; use prost_types::Any; -use crate::capabilities::NodeCapabilities; use crate::{data_source::DataSource, Chain}; use graph::blockchain as bc; use graph::firehose::EventTypeFilter; @@ -25,8 +24,8 @@ impl bc::TriggerFilter for TriggerFilter { self.block_filter.extend_from_data_sources(data_sources); } - fn node_capabilities(&self) -> NodeCapabilities { - NodeCapabilities {} + fn node_capabilities(&self) -> bc::EmptyNodeCapabilities { + bc::EmptyNodeCapabilities::default() } fn extend_with_template( diff --git a/chain/cosmos/src/capabilities.rs b/chain/cosmos/src/capabilities.rs deleted file mode 100644 index 89058123534..00000000000 --- a/chain/cosmos/src/capabilities.rs +++ /dev/null @@ -1,33 +0,0 @@ -use std::cmp::PartialOrd; -use std::fmt; -use std::str::FromStr; - -use anyhow::Error; -use graph::impl_slog_value; - -use crate::DataSource; - -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd)] -pub struct NodeCapabilities {} - -impl FromStr for NodeCapabilities { - type Err = Error; - - fn from_str(_s: &str) -> Result { - Ok(NodeCapabilities {}) - } -} - -impl fmt::Display for NodeCapabilities { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str("cosmos") - } -} - -impl_slog_value!(NodeCapabilities, "{}"); - -impl graph::blockchain::NodeCapabilities for NodeCapabilities { - fn from_data_sources(_data_sources: &[DataSource]) -> Self { - NodeCapabilities {} - } -} diff --git a/chain/cosmos/src/chain.rs b/chain/cosmos/src/chain.rs index c24f2bd0dd1..cd6e95572f8 100644 --- a/chain/cosmos/src/chain.rs +++ b/chain/cosmos/src/chain.rs @@ -11,8 +11,8 @@ use graph::{ FirehoseMapper as FirehoseMapperTrait, TriggersAdapter as TriggersAdapterTrait, }, firehose_block_stream::FirehoseBlockStream, - Block as _, BlockHash, BlockPtr, Blockchain, BlockchainKind, IngestorError, - RuntimeAdapter as RuntimeAdapterTrait, + Block as _, BlockHash, BlockPtr, Blockchain, BlockchainKind, EmptyNodeCapabilities, + IngestorError, RuntimeAdapter as RuntimeAdapterTrait, }, components::store::DeploymentLocator, firehose::{self, FirehoseEndpoint, FirehoseEndpoints, ForkStep}, @@ -20,7 +20,6 @@ use graph::{ }; use prost::Message; -use crate::capabilities::NodeCapabilities; use crate::data_source::{ DataSource, DataSourceTemplate, EventOrigin, UnresolvedDataSource, UnresolvedDataSourceTemplate, }; @@ -80,7 +79,7 @@ impl Blockchain for Chain { type TriggerFilter = TriggerFilter; - type NodeCapabilities = NodeCapabilities; + type NodeCapabilities = EmptyNodeCapabilities; fn is_refetch_block_required(&self) -> bool { false @@ -113,7 +112,11 @@ impl Blockchain for Chain { unified_api_version: UnifiedMappingApiVersion, ) -> Result>, Error> { let adapter = self - .triggers_adapter(&deployment, &NodeCapabilities {}, unified_api_version) + .triggers_adapter( + &deployment, + &EmptyNodeCapabilities::default(), + unified_api_version, + ) .unwrap_or_else(|_| panic!("no adapter for network {}", self.name)); let firehose_endpoint = self.firehose_endpoints.random()?; diff --git a/chain/cosmos/src/lib.rs b/chain/cosmos/src/lib.rs index 634cbe01ebd..6d84b61947e 100644 --- a/chain/cosmos/src/lib.rs +++ b/chain/cosmos/src/lib.rs @@ -1,5 +1,4 @@ mod adapter; -mod capabilities; pub mod chain; pub mod codec; mod data_source; diff --git a/chain/ethereum/src/capabilities.rs b/chain/ethereum/src/capabilities.rs index 688b951da64..d1296c4f45c 100644 --- a/chain/ethereum/src/capabilities.rs +++ b/chain/ethereum/src/capabilities.rs @@ -1,11 +1,9 @@ use anyhow::Error; use graph::impl_slog_value; +use std::cmp::Ordering; +use std::collections::BTreeSet; use std::fmt; use std::str::FromStr; -use std::{ - cmp::{Ord, Ordering, PartialOrd}, - collections::BTreeSet, -}; use crate::DataSource; @@ -15,28 +13,28 @@ pub struct NodeCapabilities { pub traces: bool, } -// Take all NodeCapabilities fields into account when ordering -// A NodeCapabilities instance is considered equal or greater than another -// if all of its fields are equal or greater than the other -impl Ord for NodeCapabilities { - fn cmp(&self, other: &Self) -> Ordering { - match ( +/// Two [`NodeCapabilities`] can only be compared if one is the subset of the +/// other. No [`Ord`] (i.e. total order) implementation is applicable. +impl PartialOrd for NodeCapabilities { + fn partial_cmp(&self, other: &Self) -> Option { + product_order([ self.archive.cmp(&other.archive), self.traces.cmp(&other.traces), - ) { - (Ordering::Greater, Ordering::Greater) => Ordering::Greater, - (Ordering::Greater, Ordering::Equal) => Ordering::Greater, - (Ordering::Equal, Ordering::Greater) => Ordering::Greater, - (Ordering::Equal, Ordering::Equal) => Ordering::Equal, - (Ordering::Less, _) => Ordering::Less, - (_, Ordering::Less) => Ordering::Less, - } + ]) } } -impl PartialOrd for NodeCapabilities { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) +/// Defines a [product order](https://en.wikipedia.org/wiki/Product_order) over +/// an array of [`Ordering`]. +fn product_order(cmps: [Ordering; N]) -> Option { + if cmps.iter().all(|c| c.is_eq()) { + Some(Ordering::Equal) + } else if cmps.iter().all(|c| c.is_le()) { + Some(Ordering::Less) + } else if cmps.iter().all(|c| c.is_ge()) { + Some(Ordering::Greater) + } else { + None } } diff --git a/chain/ethereum/src/network.rs b/chain/ethereum/src/network.rs index bbd1135853a..7c618659bd9 100644 --- a/chain/ethereum/src/network.rs +++ b/chain/ethereum/src/network.rs @@ -1,6 +1,7 @@ use anyhow::{anyhow, Context}; use graph::cheap_clone::CheapClone; use graph::prelude::rand::{self, seq::IteratorRandom}; +use std::cmp::Ordering; use std::collections::HashMap; use std::sync::Arc; @@ -134,9 +135,14 @@ impl EthereumNetworks { pub fn sort(&mut self) { for adapters in self.networks.values_mut() { - adapters - .adapters - .sort_by_key(|adapter| adapter.capabilities) + adapters.adapters.sort_by(|a, b| { + a.capabilities + .partial_cmp(&b.capabilities) + // We can't define a total ordering over node capabilities, + // so incomparable items are considered equal and end up + // near each other. + .unwrap_or(Ordering::Equal) + }) } } diff --git a/chain/near/src/adapter.rs b/chain/near/src/adapter.rs index 3334587577b..89c95b20c28 100644 --- a/chain/near/src/adapter.rs +++ b/chain/near/src/adapter.rs @@ -1,6 +1,5 @@ use std::collections::HashSet; -use crate::capabilities::NodeCapabilities; use crate::data_source::PartialAccounts; use crate::{data_source::DataSource, Chain}; use graph::blockchain as bc; @@ -29,8 +28,8 @@ impl bc::TriggerFilter for TriggerFilter { receipt_filter.extend(NearReceiptFilter::from_data_sources(data_sources)); } - fn node_capabilities(&self) -> NodeCapabilities { - NodeCapabilities {} + fn node_capabilities(&self) -> bc::EmptyNodeCapabilities { + bc::EmptyNodeCapabilities::default() } fn extend_with_template( diff --git a/chain/near/src/capabilities.rs b/chain/near/src/capabilities.rs deleted file mode 100644 index 0d84c9c555d..00000000000 --- a/chain/near/src/capabilities.rs +++ /dev/null @@ -1,37 +0,0 @@ -use graph::{anyhow::Error, impl_slog_value}; -use std::cmp::{Ordering, PartialOrd}; -use std::fmt; -use std::str::FromStr; - -use crate::data_source::DataSource; - -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub struct NodeCapabilities {} - -impl PartialOrd for NodeCapabilities { - fn partial_cmp(&self, _other: &Self) -> Option { - None - } -} - -impl FromStr for NodeCapabilities { - type Err = Error; - - fn from_str(_s: &str) -> Result { - Ok(NodeCapabilities {}) - } -} - -impl fmt::Display for NodeCapabilities { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str("near") - } -} - -impl_slog_value!(NodeCapabilities, "{}"); - -impl graph::blockchain::NodeCapabilities for NodeCapabilities { - fn from_data_sources(_data_sources: &[DataSource]) -> Self { - NodeCapabilities {} - } -} diff --git a/chain/near/src/chain.rs b/chain/near/src/chain.rs index 319d9564741..16551ef6df7 100644 --- a/chain/near/src/chain.rs +++ b/chain/near/src/chain.rs @@ -11,7 +11,8 @@ use graph::{ FirehoseMapper as FirehoseMapperTrait, TriggersAdapter as TriggersAdapterTrait, }, firehose_block_stream::FirehoseBlockStream, - BlockHash, BlockPtr, Blockchain, IngestorError, RuntimeAdapter as RuntimeAdapterTrait, + BlockHash, BlockPtr, Blockchain, EmptyNodeCapabilities, IngestorError, + RuntimeAdapter as RuntimeAdapterTrait, }, components::store::DeploymentLocator, firehose::{self as firehose, ForkStep}, @@ -21,7 +22,6 @@ use prost::Message; use std::sync::Arc; use crate::adapter::TriggerFilter; -use crate::capabilities::NodeCapabilities; use crate::data_source::{DataSourceTemplate, UnresolvedDataSourceTemplate}; use crate::runtime::RuntimeAdapter; use crate::trigger::{self, NearTrigger}; @@ -46,7 +46,11 @@ impl BlockStreamBuilder for NearStreamBuilder { unified_api_version: UnifiedMappingApiVersion, ) -> Result>> { let adapter = chain - .triggers_adapter(&deployment, &NodeCapabilities {}, unified_api_version) + .triggers_adapter( + &deployment, + &EmptyNodeCapabilities::default(), + unified_api_version, + ) .unwrap_or_else(|_| panic!("no adapter for network {}", chain.name)); let firehose_endpoint = chain.firehose_endpoints.random()?; @@ -140,7 +144,7 @@ impl Blockchain for Chain { type TriggerFilter = crate::adapter::TriggerFilter; - type NodeCapabilities = crate::capabilities::NodeCapabilities; + type NodeCapabilities = EmptyNodeCapabilities; fn triggers_adapter( &self, diff --git a/chain/near/src/lib.rs b/chain/near/src/lib.rs index 2ab7dd83583..c1fe4c8cfa6 100644 --- a/chain/near/src/lib.rs +++ b/chain/near/src/lib.rs @@ -1,5 +1,4 @@ mod adapter; -mod capabilities; mod chain; pub mod codec; mod data_source; diff --git a/chain/substreams/src/chain.rs b/chain/substreams/src/chain.rs index a7204f40978..7c1dbc0fc66 100644 --- a/chain/substreams/src/chain.rs +++ b/chain/substreams/src/chain.rs @@ -1,6 +1,6 @@ use crate::{data_source::*, EntityChanges, TriggerData, TriggerFilter, TriggersAdapter}; use anyhow::Error; -use core::fmt; +use graph::blockchain::EmptyNodeCapabilities; use graph::firehose::FirehoseEndpoints; use graph::prelude::{BlockHash, LoggerFactory, MetricsRegistry}; use graph::{ @@ -11,11 +11,10 @@ use graph::{ }, components::store::DeploymentLocator, data::subgraph::UnifiedMappingApiVersion, - impl_slog_value, prelude::{async_trait, BlockNumber, ChainStore}, slog::Logger, }; -use std::{str::FromStr, sync::Arc}; +use std::sync::Arc; #[derive(Default, Debug, Clone)] pub struct Block { @@ -70,31 +69,6 @@ impl std::fmt::Debug for Chain { } } -#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Ord, Eq)] -pub struct NodeCapabilities {} - -impl FromStr for NodeCapabilities { - type Err = Error; - - fn from_str(_s: &str) -> Result { - Ok(NodeCapabilities {}) - } -} - -impl fmt::Display for NodeCapabilities { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str("substream") - } -} - -impl_slog_value!(NodeCapabilities, "{}"); - -impl graph::blockchain::NodeCapabilities for NodeCapabilities { - fn from_data_sources(_data_sources: &[DataSource]) -> Self { - NodeCapabilities {} - } -} - #[async_trait] impl Blockchain for Chain { const KIND: BlockchainKind = BlockchainKind::Substreams; @@ -116,7 +90,7 @@ impl Blockchain for Chain { /// Trigger filter used as input to the triggers adapter. type TriggerFilter = TriggerFilter; - type NodeCapabilities = NodeCapabilities; + type NodeCapabilities = EmptyNodeCapabilities; fn triggers_adapter( &self, diff --git a/chain/substreams/src/trigger.rs b/chain/substreams/src/trigger.rs index df930ab73f9..d18b5bbe6b4 100644 --- a/chain/substreams/src/trigger.rs +++ b/chain/substreams/src/trigger.rs @@ -2,7 +2,7 @@ use std::{collections::HashMap, str::FromStr, sync::Arc}; use anyhow::Error; use graph::{ - blockchain::{self, block_stream::BlockWithTriggers, BlockPtr}, + blockchain::{self, block_stream::BlockWithTriggers, BlockPtr, EmptyNodeCapabilities}, components::{ store::{DeploymentLocator, EntityKey, SubgraphFork}, subgraph::{MappingError, ProofOfIndexingEvent, SharedProofOfIndexing}, @@ -20,9 +20,7 @@ use graph_runtime_wasm::module::ToAscPtr; use lazy_static::__Deref; use crate::codec; -use crate::{ - codec::entity_change::Operation, Block, Chain, NodeCapabilities, NoopDataSourceTemplate, -}; +use crate::{codec::entity_change::Operation, Block, Chain, NoopDataSourceTemplate}; #[derive(Eq, PartialEq, PartialOrd, Ord, Debug)] pub struct TriggerData {} @@ -84,8 +82,8 @@ impl blockchain::TriggerFilter for TriggerFilter { } } - fn node_capabilities(&self) -> NodeCapabilities { - NodeCapabilities {} + fn node_capabilities(&self) -> EmptyNodeCapabilities { + EmptyNodeCapabilities::default() } fn to_firehose_filter(self) -> Vec { diff --git a/graph/src/blockchain/empty_node_capabilities.rs b/graph/src/blockchain/empty_node_capabilities.rs new file mode 100644 index 00000000000..738d4561984 --- /dev/null +++ b/graph/src/blockchain/empty_node_capabilities.rs @@ -0,0 +1,46 @@ +use std::marker::PhantomData; + +use super::{Blockchain, NodeCapabilities}; + +/// A boring implementor of [`NodeCapabilities`] for blockchains that +/// only need an empty `struct`. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct EmptyNodeCapabilities(PhantomData); + +impl Default for EmptyNodeCapabilities { + fn default() -> Self { + EmptyNodeCapabilities(PhantomData) + } +} + +impl std::fmt::Display for EmptyNodeCapabilities +where + C: Blockchain, +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", C::KIND) + } +} + +impl slog::Value for EmptyNodeCapabilities +where + C: Blockchain, +{ + fn serialize( + &self, + record: &slog::Record, + key: slog::Key, + serializer: &mut dyn slog::Serializer, + ) -> slog::Result { + slog::Value::serialize(&C::KIND.to_string(), record, key, serializer) + } +} + +impl NodeCapabilities for EmptyNodeCapabilities +where + C: Blockchain, +{ + fn from_data_sources(_data_sources: &[C::DataSource]) -> Self { + EmptyNodeCapabilities(PhantomData) + } +} diff --git a/graph/src/blockchain/mod.rs b/graph/src/blockchain/mod.rs index d432c1ba726..81c495afad9 100644 --- a/graph/src/blockchain/mod.rs +++ b/graph/src/blockchain/mod.rs @@ -3,6 +3,7 @@ //! trait which is the centerpiece of this module. pub mod block_stream; +mod empty_node_capabilities; pub mod firehose_block_ingestor; pub mod firehose_block_stream; pub mod mock; @@ -41,6 +42,7 @@ use std::{ use web3::types::H256; pub use block_stream::{ChainHeadUpdateListener, ChainHeadUpdateStream, TriggersAdapter}; +pub use empty_node_capabilities::EmptyNodeCapabilities; pub use types::{BlockHash, BlockPtr, ChainIdentifier}; use self::block_stream::{BlockStream, FirehoseCursor};