diff --git a/chain/arweave/src/data_source.rs b/chain/arweave/src/data_source.rs index 119ee59c1a3..11d7f43a8af 100644 --- a/chain/arweave/src/data_source.rs +++ b/chain/arweave/src/data_source.rs @@ -162,8 +162,8 @@ impl blockchain::DataSource for DataSource { self.mapping.api_version.clone() } - fn runtime(&self) -> &[u8] { - self.mapping.runtime.as_ref() + fn runtime(&self) -> Option>> { + Some(self.mapping.runtime.cheap_clone()) } } @@ -289,8 +289,8 @@ impl blockchain::DataSourceTemplate for DataSourceTemplate { self.mapping.api_version.clone() } - fn runtime(&self) -> &[u8] { - self.mapping.runtime.as_ref() + fn runtime(&self) -> Option>> { + Some(self.mapping.runtime.cheap_clone()) } } diff --git a/chain/cosmos/src/data_source.rs b/chain/cosmos/src/data_source.rs index 5b11741e83e..c3806b01d58 100644 --- a/chain/cosmos/src/data_source.rs +++ b/chain/cosmos/src/data_source.rs @@ -197,8 +197,8 @@ impl blockchain::DataSource for DataSource { self.mapping.api_version.clone() } - fn runtime(&self) -> &[u8] { - self.mapping.runtime.as_ref() + fn runtime(&self) -> Option>> { + Some(self.mapping.runtime.cheap_clone()) } } @@ -339,7 +339,7 @@ impl blockchain::DataSourceTemplate for DataSourceTemplate { unimplemented!("{}", TEMPLATE_ERROR); } - fn runtime(&self) -> &[u8] { + fn runtime(&self) -> Option>> { unimplemented!("{}", TEMPLATE_ERROR); } } diff --git a/chain/ethereum/src/data_source.rs b/chain/ethereum/src/data_source.rs index b59ea5045b6..099b864f9a6 100644 --- a/chain/ethereum/src/data_source.rs +++ b/chain/ethereum/src/data_source.rs @@ -219,8 +219,8 @@ impl blockchain::DataSource for DataSource { self.mapping.api_version.clone() } - fn runtime(&self) -> &[u8] { - self.mapping.runtime.as_ref() + fn runtime(&self) -> Option>> { + Some(self.mapping.runtime.cheap_clone()) } } @@ -836,8 +836,8 @@ impl blockchain::DataSourceTemplate for DataSourceTemplate { self.mapping.api_version.clone() } - fn runtime(&self) -> &[u8] { - self.mapping.runtime.as_ref() + fn runtime(&self) -> Option>> { + Some(self.mapping.runtime.cheap_clone()) } } diff --git a/chain/near/src/data_source.rs b/chain/near/src/data_source.rs index 320c7bb46b1..bafc36d46ef 100644 --- a/chain/near/src/data_source.rs +++ b/chain/near/src/data_source.rs @@ -219,8 +219,8 @@ impl blockchain::DataSource for DataSource { self.mapping.api_version.clone() } - fn runtime(&self) -> &[u8] { - self.mapping.runtime.as_ref() + fn runtime(&self) -> Option>> { + Some(self.mapping.runtime.cheap_clone()) } } @@ -374,8 +374,8 @@ impl blockchain::DataSourceTemplate for DataSourceTemplate { self.mapping.api_version.clone() } - fn runtime(&self) -> &[u8] { - self.mapping.runtime.as_ref() + fn runtime(&self) -> Option>> { + Some(self.mapping.runtime.cheap_clone()) } } diff --git a/chain/substreams/src/data_source.rs b/chain/substreams/src/data_source.rs index fb7845431d8..759cf1f417b 100644 --- a/chain/substreams/src/data_source.rs +++ b/chain/substreams/src/data_source.rs @@ -58,7 +58,7 @@ impl blockchain::DataSource for DataSource { todo!() } - fn runtime(&self) -> &[u8] { + fn runtime(&self) -> Option>> { todo!() } @@ -145,7 +145,7 @@ impl blockchain::DataSourceTemplate for DataSourceTemplate { todo!() } - fn runtime(&self) -> &[u8] { + fn runtime(&self) -> Option>> { todo!() } diff --git a/core/src/subgraph/instance.rs b/core/src/subgraph/instance.rs index a13a162d85a..0e5daa37300 100644 --- a/core/src/subgraph/instance.rs +++ b/core/src/subgraph/instance.rs @@ -72,9 +72,16 @@ where // we use the same order here as in the subgraph manifest to make the // event processing behavior predictable for ds in manifest.data_sources { + let runtime = ds.runtime(); + let module_bytes = match runtime { + None => continue, + Some(ref module_bytes) => module_bytes, + }; + let host = this.new_host( logger.cheap_clone(), ds, + module_bytes, templates.cheap_clone(), host_metrics.cheap_clone(), )?; @@ -84,21 +91,23 @@ where Ok(this) } + // module_bytes is the same as data_source.runtime().unwrap(), this is to ensure that this + // function is only called for data_sources for which data_source.runtime().is_some() is true. fn new_host( &mut self, logger: Logger, data_source: C::DataSource, + module_bytes: &Arc>, templates: Arc>, host_metrics: Arc, ) -> Result { let mapping_request_sender = { - let module_bytes = data_source.runtime(); - let module_hash = tiny_keccak::keccak256(module_bytes); + let module_hash = tiny_keccak::keccak256(module_bytes.as_ref()); if let Some(sender) = self.module_cache.get(&module_hash) { sender.clone() } else { let sender = T::spawn_mapping( - module_bytes.to_owned(), + module_bytes.as_ref(), logger, self.subgraph_id.clone(), host_metrics.clone(), @@ -167,7 +176,18 @@ where <= data_source.creation_block() ); - let host = Arc::new(self.new_host(logger.clone(), data_source, templates, metrics)?); + let module_bytes = match &data_source.runtime() { + None => return Ok(None), + Some(ref module_bytes) => module_bytes.cheap_clone(), + }; + + let host = Arc::new(self.new_host( + logger.clone(), + data_source, + &module_bytes, + templates, + metrics, + )?); Ok(if self.hosts.contains(&host) { None diff --git a/graph/src/blockchain/mock.rs b/graph/src/blockchain/mock.rs index d527ad2badf..fd48f59fc25 100644 --- a/graph/src/blockchain/mock.rs +++ b/graph/src/blockchain/mock.rs @@ -87,7 +87,7 @@ impl DataSource for MockDataSource { todo!() } - fn runtime(&self) -> &[u8] { + fn runtime(&self) -> Option>> { todo!() } @@ -142,7 +142,7 @@ impl DataSourceTemplate for MockDataSourceTemplate { todo!() } - fn runtime(&self) -> &[u8] { + fn runtime(&self) -> Option>> { todo!() } diff --git a/graph/src/blockchain/mod.rs b/graph/src/blockchain/mod.rs index 36ab6b0c6ac..f4c9cf033b2 100644 --- a/graph/src/blockchain/mod.rs +++ b/graph/src/blockchain/mod.rs @@ -199,7 +199,7 @@ pub trait DataSource: fn context(&self) -> Arc>; fn creation_block(&self) -> Option; fn api_version(&self) -> semver::Version; - fn runtime(&self) -> &[u8]; + fn runtime(&self) -> Option>>; /// Checks if `trigger` matches this data source, and if so decodes it into a `MappingTrigger`. /// A return of `Ok(None)` mean the trigger does not match. @@ -245,7 +245,7 @@ pub trait UnresolvedDataSourceTemplate: pub trait DataSourceTemplate: Send + Sync + Debug { fn api_version(&self) -> semver::Version; - fn runtime(&self) -> &[u8]; + fn runtime(&self) -> Option>>; fn name(&self) -> &str; } diff --git a/graph/src/components/subgraph/host.rs b/graph/src/components/subgraph/host.rs index c9606b3b54b..a3371323187 100644 --- a/graph/src/components/subgraph/host.rs +++ b/graph/src/components/subgraph/host.rs @@ -160,7 +160,7 @@ pub trait RuntimeHostBuilder: Clone + Send + Sync + 'static { /// Spawn a mapping and return a channel for mapping requests. The sender should be able to be /// cached and shared among mappings that use the same wasm file. fn spawn_mapping( - raw_module: Vec, + raw_module: &[u8], logger: Logger, subgraph_id: DeploymentHash, metrics: Arc, diff --git a/graph/src/data/subgraph/features.rs b/graph/src/data/subgraph/features.rs index ef60999a401..29c769f9231 100644 --- a/graph/src/data/subgraph/features.rs +++ b/graph/src/data/subgraph/features.rs @@ -135,7 +135,7 @@ fn detect_ipfs_on_ethereum_contracts( ) -> Result, InvalidMapping> { for runtime in manifest.runtimes() { for function_name in IPFS_ON_ETHEREUM_CONTRACTS_FUNCTION_NAMES { - if calls_host_fn(runtime, function_name).map_err(|_| InvalidMapping)? { + if calls_host_fn(&runtime, function_name).map_err(|_| InvalidMapping)? { return Ok(Some(SubgraphFeature::IpfsOnEthereumContracts)); } } diff --git a/graph/src/data/subgraph/mod.rs b/graph/src/data/subgraph/mod.rs index b2351ca5190..ef7b202638e 100644 --- a/graph/src/data/subgraph/mod.rs +++ b/graph/src/data/subgraph/mod.rs @@ -697,8 +697,7 @@ impl SubgraphManifest { // Assume the manifest has been validated, ensuring network names are homogenous self.data_sources .iter() - .filter_map(|d| d.network().map(|n| n.to_string())) - .next() + .find_map(|d| d.network().map(|n| n.to_string())) .expect("Validated manifest does not have a network defined on any datasource") } @@ -716,11 +715,15 @@ impl SubgraphManifest { .chain(self.data_sources.iter().map(|source| source.api_version())) } - pub fn runtimes(&self) -> impl Iterator + '_ { + pub fn runtimes(&self) -> impl Iterator>> + '_ { self.templates .iter() - .map(|template| template.runtime()) - .chain(self.data_sources.iter().map(|source| source.runtime())) + .filter_map(|template| template.runtime()) + .chain( + self.data_sources + .iter() + .filter_map(|source| source.runtime()), + ) } pub fn unified_mapping_api_version( diff --git a/runtime/wasm/src/host.rs b/runtime/wasm/src/host.rs index 7978dcb7f4b..8e4943e179d 100644 --- a/runtime/wasm/src/host.rs +++ b/runtime/wasm/src/host.rs @@ -53,7 +53,7 @@ impl RuntimeHostBuilderTrait for RuntimeHostBuilder { type Req = MappingRequest; fn spawn_mapping( - raw_module: Vec, + raw_module: &[u8], logger: Logger, subgraph_id: DeploymentHash, metrics: Arc, diff --git a/runtime/wasm/src/mapping.rs b/runtime/wasm/src/mapping.rs index 4e73bf017fa..580fb48d35e 100644 --- a/runtime/wasm/src/mapping.rs +++ b/runtime/wasm/src/mapping.rs @@ -13,7 +13,7 @@ use std::thread; /// Spawn a wasm module in its own thread. pub fn spawn_module( - raw_module: Vec, + raw_module: &[u8], logger: Logger, subgraph_id: DeploymentHash, host_metrics: Arc, @@ -21,7 +21,7 @@ pub fn spawn_module( timeout: Option, experimental_features: ExperimentalFeatures, ) -> Result>, anyhow::Error> { - let valid_module = Arc::new(ValidModule::new(&logger, &raw_module)?); + let valid_module = Arc::new(ValidModule::new(&logger, raw_module)?); // Create channel for event handling requests let (mapping_request_sender, mapping_request_receiver) = mpsc::channel(100);