From ff8bd85fe73da92a6266b1f3859e9e9c78a5f420 Mon Sep 17 00:00:00 2001 From: Qinxuan Chen Date: Mon, 31 Jul 2023 21:50:51 +0800 Subject: [PATCH] feat: add fc-api to improve fc-db (#1076) * feat: add fc-api to improve fc-db * fix tests * fix --- Cargo.lock | 15 ++++ Cargo.toml | 2 + client/api/Cargo.toml | 20 ++++++ client/api/src/backend.rs | 81 ++++++++++++++++++++++ client/api/src/lib.rs | 23 +++++++ client/cli/Cargo.toml | 1 + client/cli/src/frontier_db_cmd/tests.rs | 16 ++--- client/db/Cargo.toml | 1 + client/db/src/kv/mod.rs | 92 ++++++++++++------------- client/db/src/kv/upgrade.rs | 23 +++---- client/db/src/lib.rs | 44 ------------ client/db/src/sql/mod.rs | 60 ++++++++-------- client/rpc/Cargo.toml | 4 +- client/rpc/src/eth/filter.rs | 29 ++++---- client/rpc/src/eth/mod.rs | 4 +- client/rpc/src/lib.rs | 8 +-- template/node/Cargo.toml | 1 + template/node/src/rpc/eth.rs | 2 +- template/node/src/rpc/mod.rs | 2 +- 19 files changed, 268 insertions(+), 160 deletions(-) create mode 100644 client/api/Cargo.toml create mode 100644 client/api/src/backend.rs create mode 100644 client/api/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index d384729f59..5d79a71d8c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2149,12 +2149,24 @@ dependencies = [ "instant", ] +[[package]] +name = "fc-api" +version = "1.0.0-dev" +dependencies = [ + "async-trait", + "fp-storage", + "parity-scale-codec", + "sp-core", + "sp-runtime", +] + [[package]] name = "fc-cli" version = "1.0.0-dev" dependencies = [ "clap", "ethereum-types", + "fc-api", "fc-db", "fp-rpc", "fp-storage", @@ -2196,6 +2208,7 @@ version = "2.0.0-dev" dependencies = [ "async-trait", "ethereum", + "fc-api", "fc-storage", "fp-consensus", "fp-rpc", @@ -2264,6 +2277,7 @@ dependencies = [ "ethereum", "ethereum-types", "evm", + "fc-api", "fc-db", "fc-mapping-sync", "fc-rpc-core", @@ -2843,6 +2857,7 @@ version = "0.0.0" dependencies = [ "async-trait", "clap", + "fc-api", "fc-cli", "fc-consensus", "fc-db", diff --git a/Cargo.toml b/Cargo.toml index 0ab455a478..9047699cfa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ members = [ "frame/evm/precompile/bls12377", "frame/evm/precompile/dispatch", "frame/evm/precompile/curve25519", + "client/api", "client/consensus", "client/rpc-core", "client/rpc", @@ -134,6 +135,7 @@ substrate-frame-rpc-system = { version = "4.0.0-dev", git = "https://github.com/ substrate-test-runtime-client = { version = "2.0.0", git = "https://github.com/paritytech/substrate", branch = "master" } substrate-wasm-builder = { version = "5.0.0-dev", git = "https://github.com/paritytech/substrate", branch = "master" } # Frontier Client +fc-api = { version = "1.0.0-dev", path = "client/api" } fc-cli = { version = "1.0.0-dev", path = "client/cli", default-features = false } fc-consensus = { version = "2.0.0-dev", path = "client/consensus" } fc-db = { version = "2.0.0-dev", path = "client/db", default-features = false } diff --git a/client/api/Cargo.toml b/client/api/Cargo.toml new file mode 100644 index 0000000000..0a70e8db39 --- /dev/null +++ b/client/api/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "fc-api" +version = "1.0.0-dev" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +description = "Frontier client interfaces" +authors = { workspace = true } +edition = { workspace = true } +repository = { workspace = true } + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +async-trait = { workspace = true } +scale-codec = { package = "parity-scale-codec", workspace = true } +# Substrate +sp-core = { workspace = true, features = ["default"] } +sp-runtime = { workspace = true, features = ["default"] } +# Frontier +fp-storage = { workspace = true, features = ["default"] } diff --git a/client/api/src/backend.rs b/client/api/src/backend.rs new file mode 100644 index 0000000000..7ad26b95a8 --- /dev/null +++ b/client/api/src/backend.rs @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 +// This file is part of Frontier. +// +// Copyright (c) 2023 Parity Technologies (UK) Ltd. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use scale_codec::{Decode, Encode}; +// Substrate +use sp_core::{H160, H256}; +use sp_runtime::traits::Block as BlockT; +// Frontier +use fp_storage::EthereumStorageSchema; + +#[derive(Clone, Debug, Eq, PartialEq, Encode, Decode)] +pub struct TransactionMetadata { + pub substrate_block_hash: Block::Hash, + pub ethereum_block_hash: H256, + pub ethereum_index: u32, +} + +/// The frontier backend interface. +#[async_trait::async_trait] +pub trait Backend: Send + Sync { + /// Get the substrate hash with the given ethereum block hash. + async fn block_hash( + &self, + ethereum_block_hash: &H256, + ) -> Result>, String>; + + /// Get the transaction metadata with the given ethereum block hash. + async fn transaction_metadata( + &self, + ethereum_transaction_hash: &H256, + ) -> Result>, String>; + + /// Returns reference to log indexer backend. + fn log_indexer(&self) -> &dyn LogIndexerBackend; + + /// Indicate whether the log indexing feature is supported. + fn is_indexed(&self) -> bool { + self.log_indexer().is_indexed() + } +} + +#[derive(Debug, Eq, PartialEq)] +pub struct FilteredLog { + pub substrate_block_hash: Block::Hash, + pub ethereum_block_hash: H256, + pub block_number: u32, + pub ethereum_storage_schema: EthereumStorageSchema, + pub transaction_index: u32, + pub log_index: u32, +} + +/// The log indexer backend interface. +#[async_trait::async_trait] +pub trait LogIndexerBackend: Send + Sync { + /// Indicate whether the log indexing feature is supported. + fn is_indexed(&self) -> bool; + + /// Filter the logs by the parameters. + async fn filter_logs( + &self, + from_block: u64, + to_block: u64, + addresses: Vec, + topics: Vec>>, + ) -> Result>, String>; +} diff --git a/client/api/src/lib.rs b/client/api/src/lib.rs new file mode 100644 index 0000000000..c922fcc439 --- /dev/null +++ b/client/api/src/lib.rs @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 +// This file is part of Frontier. +// +// Copyright (c) 2023 Parity Technologies (UK) Ltd. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#![deny(unused_crate_dependencies)] + +pub mod backend; + +pub use self::backend::*; diff --git a/client/cli/Cargo.toml b/client/cli/Cargo.toml index 4c2ec2b7b3..e05c20c63e 100644 --- a/client/cli/Cargo.toml +++ b/client/cli/Cargo.toml @@ -36,6 +36,7 @@ sp-consensus = { workspace = true } sp-io = { workspace = true } substrate-test-runtime-client = { workspace = true } # Frontier +fc-api = { workspace = true } fc-db = { workspace = true, features = ["rocksdb"] } frontier-template-runtime = { workspace = true, features = ["default"] } diff --git a/client/cli/src/frontier_db_cmd/tests.rs b/client/cli/src/frontier_db_cmd/tests.rs index bce1bf7d3e..9d9cb3d216 100644 --- a/client/cli/src/frontier_db_cmd/tests.rs +++ b/client/cli/src/frontier_db_cmd/tests.rs @@ -579,8 +579,8 @@ fn commitment_create() { ); // Expect the offchain-stored transaction metadata to match the one we stored in the runtime. - let expected_transaction_metadata = fc_db::TransactionMetadata { - block_hash, + let expected_transaction_metadata = fc_api::TransactionMetadata { + substrate_block_hash: block_hash, ethereum_block_hash, ethereum_index: 0, }; @@ -660,8 +660,8 @@ fn commitment_update() { ); // Expect the offchain-stored transaction metadata to match the one we stored in the runtime. - let expected_transaction_metadata_a1_t1 = fc_db::TransactionMetadata { - block_hash: block_a1_hash, + let expected_transaction_metadata_a1_t1 = fc_api::TransactionMetadata { + substrate_block_hash: block_a1_hash, ethereum_block_hash, ethereum_index: 0, }; @@ -706,13 +706,13 @@ fn commitment_update() { ); // Expect the offchain-stored transaction metadata to have data for both blocks. - let expected_transaction_metadata_a2_t1 = fc_db::TransactionMetadata { - block_hash: block_a2_hash, + let expected_transaction_metadata_a2_t1 = fc_api::TransactionMetadata { + substrate_block_hash: block_a2_hash, ethereum_block_hash, ethereum_index: 0, }; - let expected_transaction_metadata_a2_t2 = fc_db::TransactionMetadata { - block_hash: block_a2_hash, + let expected_transaction_metadata_a2_t2 = fc_api::TransactionMetadata { + substrate_block_hash: block_a2_hash, ethereum_block_hash, ethereum_index: 1, }; diff --git a/client/db/Cargo.toml b/client/db/Cargo.toml index edd0c03523..5a63020ba9 100644 --- a/client/db/Cargo.toml +++ b/client/db/Cargo.toml @@ -32,6 +32,7 @@ sp-database = { workspace = true } sp-runtime = { workspace = true } sp-storage = { workspace = true, optional = true } # Frontier +fc-api = { workspace = true } fc-storage = { workspace = true, optional = true } fp-consensus = { workspace = true, features = ["default"], optional = true } fp-rpc = { workspace = true, features = ["default"], optional = true } diff --git a/client/db/src/kv/mod.rs b/client/db/src/kv/mod.rs index 01c9e61e10..c70ec5f51d 100644 --- a/client/db/src/kv/mod.rs +++ b/client/db/src/kv/mod.rs @@ -31,14 +31,13 @@ use scale_codec::{Decode, Encode}; // Substrate pub use sc_client_db::DatabaseSource; use sp_blockchain::HeaderBackend; -use sp_core::H256; +use sp_core::{H160, H256}; pub use sp_database::Database; use sp_runtime::traits::Block as BlockT; // Frontier +use fc_api::{FilteredLog, TransactionMetadata}; use fp_storage::{EthereumStorageSchema, PALLET_ETHEREUM_SCHEMA_CACHE}; -use crate::TransactionMetadata; - const DB_HASH_LEN: usize = 32; /// Hash type that this backend uses for the database. pub type DbHash = [u8; DB_HASH_LEN]; @@ -66,16 +65,18 @@ pub mod static_keys { pub struct Backend { meta: Arc>, mapping: Arc>, + log_indexer: LogIndexerBackend, } #[async_trait::async_trait] -impl crate::BackendReader for Backend { +impl fc_api::Backend for Backend { async fn block_hash( &self, ethereum_block_hash: &H256, ) -> Result>, String> { self.mapping().block_hash(ethereum_block_hash) } + async fn transaction_metadata( &self, ethereum_transaction_hash: &H256, @@ -83,19 +84,30 @@ impl crate::BackendReader for Backend { self.mapping() .transaction_metadata(ethereum_transaction_hash) } + + fn log_indexer(&self) -> &dyn fc_api::LogIndexerBackend { + &self.log_indexer + } +} + +#[derive(Clone, Default)] +pub struct LogIndexerBackend(PhantomData); + +#[async_trait::async_trait] +impl fc_api::LogIndexerBackend for LogIndexerBackend { + fn is_indexed(&self) -> bool { + false + } + async fn filter_logs( &self, _from_block: u64, _to_block: u64, - _addresses: Vec, + _addresses: Vec, _topics: Vec>>, - ) -> Result>, String> { + ) -> Result>, String> { Err("KeyValue db does not index logs".into()) } - - fn is_indexed(&self) -> bool { - false - } } /// Returns the frontier database directory. @@ -152,6 +164,7 @@ impl Backend { db: db.clone(), _marker: PhantomData, }), + log_indexer: LogIndexerBackend(PhantomData), }) } @@ -171,13 +184,11 @@ pub struct MetaDb { impl MetaDb { pub fn current_syncing_tips(&self) -> Result, String> { - match self.db.get( - crate::columns::META, - crate::static_keys::CURRENT_SYNCING_TIPS, - ) { - Some(raw) => { - Ok(Vec::::decode(&mut &raw[..]).map_err(|e| format!("{:?}", e))?) - } + match self + .db + .get(columns::META, static_keys::CURRENT_SYNCING_TIPS) + { + Some(raw) => Ok(Vec::::decode(&mut &raw[..]).map_err(|e| e.to_string())?), None => Ok(Vec::new()), } } @@ -186,14 +197,12 @@ impl MetaDb { let mut transaction = sp_database::Transaction::new(); transaction.set( - crate::columns::META, - crate::static_keys::CURRENT_SYNCING_TIPS, + columns::META, + static_keys::CURRENT_SYNCING_TIPS, &tips.encode(), ); - self.db - .commit(transaction) - .map_err(|e| format!("{:?}", e))?; + self.db.commit(transaction).map_err(|e| e.to_string())?; Ok(()) } @@ -201,10 +210,10 @@ impl MetaDb { pub fn ethereum_schema(&self) -> Result>, String> { match self .db - .get(crate::columns::META, &PALLET_ETHEREUM_SCHEMA_CACHE.encode()) + .get(columns::META, &PALLET_ETHEREUM_SCHEMA_CACHE.encode()) { Some(raw) => Ok(Some( - Decode::decode(&mut &raw[..]).map_err(|e| format!("{:?}", e))?, + Decode::decode(&mut &raw[..]).map_err(|e| e.to_string())?, )), None => Ok(None), } @@ -217,14 +226,12 @@ impl MetaDb { let mut transaction = sp_database::Transaction::new(); transaction.set( - crate::columns::META, + columns::META, &PALLET_ETHEREUM_SCHEMA_CACHE.encode(), &new_cache.encode(), ); - self.db - .commit(transaction) - .map_err(|e| format!("{:?}", e))?; + self.db.commit(transaction).map_err(|e| e.to_string())?; Ok(()) } @@ -245,10 +252,7 @@ pub struct MappingDb { impl MappingDb { pub fn is_synced(&self, block_hash: &Block::Hash) -> Result { - match self - .db - .get(crate::columns::SYNCED_MAPPING, &block_hash.encode()) - { + match self.db.get(columns::SYNCED_MAPPING, &block_hash.encode()) { Some(raw) => Ok(bool::decode(&mut &raw[..]).map_err(|e| format!("{:?}", e))?), None => Ok(false), } @@ -260,7 +264,7 @@ impl MappingDb { ) -> Result>, String> { match self .db - .get(crate::columns::BLOCK_MAPPING, ðereum_block_hash.encode()) + .get(columns::BLOCK_MAPPING, ðereum_block_hash.encode()) { Some(raw) => Ok(Some( Vec::::decode(&mut &raw[..]).map_err(|e| format!("{:?}", e))?, @@ -274,11 +278,11 @@ impl MappingDb { ethereum_transaction_hash: &H256, ) -> Result>, String> { match self.db.get( - crate::columns::TRANSACTION_MAPPING, + columns::TRANSACTION_MAPPING, ðereum_transaction_hash.encode(), ) { Some(raw) => Ok(Vec::>::decode(&mut &raw[..]) - .map_err(|e| format!("{:?}", e))?), + .map_err(|e| e.to_string())?), None => Ok(Vec::new()), } } @@ -289,14 +293,12 @@ impl MappingDb { let mut transaction = sp_database::Transaction::new(); transaction.set( - crate::columns::SYNCED_MAPPING, + columns::SYNCED_MAPPING, &block_hash.encode(), &true.encode(), ); - self.db - .commit(transaction) - .map_err(|e| format!("{:?}", e))?; + self.db.commit(transaction).map_err(|e| e.to_string())?; Ok(()) } @@ -323,7 +325,7 @@ impl MappingDb { }; transaction.set( - crate::columns::BLOCK_MAPPING, + columns::BLOCK_MAPPING, &commitment.ethereum_block_hash.encode(), &substrate_hashes.encode(), ); @@ -335,26 +337,24 @@ impl MappingDb { { let mut metadata = self.transaction_metadata(ðereum_transaction_hash)?; metadata.push(TransactionMetadata:: { - block_hash: commitment.block_hash, + substrate_block_hash: commitment.block_hash, ethereum_block_hash: commitment.ethereum_block_hash, ethereum_index: i as u32, }); transaction.set( - crate::columns::TRANSACTION_MAPPING, + columns::TRANSACTION_MAPPING, ðereum_transaction_hash.encode(), &metadata.encode(), ); } transaction.set( - crate::columns::SYNCED_MAPPING, + columns::SYNCED_MAPPING, &commitment.block_hash.encode(), &true.encode(), ); - self.db - .commit(transaction) - .map_err(|e| format!("{:?}", e))?; + self.db.commit(transaction).map_err(|e| e.to_string())?; Ok(()) } diff --git a/client/db/src/kv/upgrade.rs b/client/db/src/kv/upgrade.rs index c57e47dfb7..b8acafa382 100644 --- a/client/db/src/kv/upgrade.rs +++ b/client/db/src/kv/upgrade.rs @@ -321,27 +321,26 @@ pub(crate) fn migrate_1_to_2_parity_db>( #[cfg(test)] mod tests { - use futures::executor; - use sc_block_builder::BlockBuilderProvider; - use sp_consensus::BlockOrigin; - use substrate_test_runtime_client::{ - prelude::*, DefaultTestClientBuilderExt, TestClientBuilder, - }; - use std::{ io::{Read, Write}, sync::Arc, }; - use crate::kv::DatabaseSettings; + use futures::executor; use scale_codec::Encode; + use tempfile::tempdir; + // Substrate + use sc_block_builder::BlockBuilderProvider; use sp_blockchain::HeaderBackend; + use sp_consensus::BlockOrigin; use sp_core::H256; use sp_runtime::{ generic::{Block, Header}, traits::{BlakeTwo256, Block as BlockT}, }; - use tempfile::tempdir; + use substrate_test_runtime_client::{ + prelude::*, DefaultTestClientBuilderExt, TestClientBuilder, + }; type OpaqueBlock = Block, substrate_test_runtime_client::runtime::Extrinsic>; @@ -356,7 +355,7 @@ mod tests { #[cfg_attr(not(feature = "rocksdb"), ignore)] #[test] fn upgrade_1_to_2_works() { - let settings: Vec = vec![ + let settings: Vec = vec![ // Rocks db #[cfg(feature = "rocksdb")] crate::kv::DatabaseSettings { @@ -443,7 +442,7 @@ mod tests { let mut metadata = vec![]; for hash in vec![next_canon_block_hash, orphan_block_hash].iter() { metadata.push(crate::kv::TransactionMetadata:: { - block_hash: *hash, + substrate_block_hash: *hash, ethereum_block_hash: ethhash, ethereum_index: 0u32, }); @@ -493,7 +492,7 @@ mod tests { .unwrap(); assert!(mapped_transaction .into_iter() - .any(|tx| tx.block_hash == *canon_substrate_block_hash)); + .any(|tx| tx.substrate_block_hash == *canon_substrate_block_hash)); } // Upgrade db version file diff --git a/client/db/src/lib.rs b/client/db/src/lib.rs index fb3b8c2230..5fa2044b85 100644 --- a/client/db/src/lib.rs +++ b/client/db/src/lib.rs @@ -18,15 +18,11 @@ #![deny(unused_crate_dependencies)] -use scale_codec::{Decode, Encode}; // Substrate pub use sc_client_db::DatabaseSource; -use sp_core::H256; use sp_runtime::traits::Block as BlockT; pub mod kv; -use kv::{columns, static_keys}; - #[cfg(feature = "sql")] pub mod sql; @@ -36,43 +32,3 @@ pub enum Backend { #[cfg(feature = "sql")] Sql(sql::Backend), } - -#[derive(Clone, Encode, Debug, Decode, Eq, PartialEq)] -pub struct TransactionMetadata { - pub block_hash: Block::Hash, - pub ethereum_block_hash: H256, - pub ethereum_index: u32, -} - -#[derive(Debug, Eq, PartialEq)] -pub struct FilteredLog { - pub substrate_block_hash: Block::Hash, - pub ethereum_block_hash: H256, - pub block_number: u32, - pub ethereum_storage_schema: fp_storage::EthereumStorageSchema, - pub transaction_index: u32, - pub log_index: u32, -} - -#[async_trait::async_trait] -pub trait BackendReader { - async fn block_hash( - &self, - ethereum_block_hash: &H256, - ) -> Result>, String>; - - async fn transaction_metadata( - &self, - ethereum_transaction_hash: &H256, - ) -> Result>, String>; - - async fn filter_logs( - &self, - from_block: u64, - to_block: u64, - addresses: Vec, - topics: Vec>>, - ) -> Result>, String>; - - fn is_indexed(&self) -> bool; -} diff --git a/client/db/src/sql/mod.rs b/client/db/src/sql/mod.rs index 2cbf0c7f97..ead5c0acb6 100644 --- a/client/db/src/sql/mod.rs +++ b/client/db/src/sql/mod.rs @@ -37,13 +37,12 @@ use sp_runtime::{ traits::{BlakeTwo256, Block as BlockT, Header as HeaderT, UniqueSaturatedInto, Zero}, }; // Frontier +use fc_api::{FilteredLog, TransactionMetadata}; use fc_storage::OverrideHandle; use fp_consensus::{FindLogError, Hashes, Log as ConsensusLog, PostLog, PreLog}; use fp_rpc::EthereumRuntimeRPCApi; use fp_storage::{EthereumStorageSchema, PALLET_ETHEREUM_SCHEMA}; -use crate::{BackendReader, FilteredLog}; - /// Maximum number to topics allowed to be filtered upon const MAX_TOPIC_COUNT: u16 = 4; @@ -65,7 +64,7 @@ pub struct Log { struct BlockMetadata { pub substrate_block_hash: H256, pub block_number: i32, - pub post_hashes: fp_consensus::Hashes, + pub post_hashes: Hashes, pub schema: EthereumStorageSchema, pub is_canon: i32, } @@ -108,7 +107,7 @@ pub struct Backend { impl Backend where - Block: BlockT + Send + Sync, + Block: BlockT, { /// Creates a new instance of the SQL backend. pub async fn new( @@ -201,7 +200,7 @@ where client: Arc, ) -> Result, Error> where - Client: StorageProvider + HeaderBackend + Send + Sync + 'static, + Client: StorageProvider + HeaderBackend + 'static, Client: ProvideRuntimeApi, Client::Api: EthereumRuntimeRPCApi, BE: BackendT + 'static, @@ -270,7 +269,7 @@ where overrides: Arc>, ) -> Result where - Client: StorageProvider + HeaderBackend + Send + Sync + 'static, + Client: StorageProvider + HeaderBackend + 'static, BE: BackendT + 'static, BE::State: StateBackend, { @@ -362,7 +361,7 @@ where hash: H256, ) -> Result<(), Error> where - Client: StorageProvider + HeaderBackend + Send + Sync + 'static, + Client: StorageProvider + HeaderBackend + 'static, BE: BackendT + 'static, BE::State: StateBackend, { @@ -438,7 +437,7 @@ where /// Index the logs for the newly indexed blocks upto a `max_pending_blocks` value. pub async fn index_block_logs(&self, client: Arc, block_hash: Block::Hash) where - Client: StorageProvider + HeaderBackend + Send + Sync + 'static, + Client: StorageProvider + HeaderBackend + 'static, BE: BackendT + 'static, BE::State: StateBackend, { @@ -519,7 +518,7 @@ where substrate_block_hash: H256, ) -> Vec where - Client: StorageProvider + HeaderBackend + Send + Sync + 'static, + Client: StorageProvider + HeaderBackend + 'static, BE: BackendT + 'static, BE::State: StateBackend, { @@ -567,7 +566,7 @@ where fn onchain_storage_schema(client: &Client, at: Block::Hash) -> EthereumStorageSchema where - Client: StorageProvider + HeaderBackend + Send + Sync + 'static, + Client: StorageProvider + HeaderBackend + 'static, BE: BackendT + 'static, BE::State: StateBackend, { @@ -797,7 +796,7 @@ where } #[async_trait::async_trait] -impl> BackendReader for Backend { +impl> fc_api::Backend for Backend { async fn block_hash( &self, ethereum_block_hash: &H256, @@ -822,7 +821,7 @@ impl> BackendReader for Backend { async fn transaction_metadata( &self, ethereum_transaction_hash: &H256, - ) -> Result>, String> { + ) -> Result>, String> { let ethereum_transaction_hash = ethereum_transaction_hash.as_bytes(); let out = sqlx::query( "SELECT @@ -840,8 +839,8 @@ impl> BackendReader for Backend { let ethereum_block_hash = H256::from_slice(&row.try_get::, _>(1).unwrap_or_default()[..]); let ethereum_transaction_index = row.try_get::(2).unwrap_or_default() as u32; - crate::TransactionMetadata { - block_hash: substrate_block_hash, + TransactionMetadata { + substrate_block_hash, ethereum_block_hash, ethereum_index: ethereum_transaction_index, } @@ -851,6 +850,17 @@ impl> BackendReader for Backend { Ok(out) } + fn log_indexer(&self) -> &dyn fc_api::LogIndexerBackend { + self + } +} + +#[async_trait::async_trait] +impl> fc_api::LogIndexerBackend for Backend { + fn is_indexed(&self) -> bool { + true + } + async fn filter_logs( &self, from_block: u64, @@ -876,10 +886,7 @@ impl> BackendReader for Backend { } } - let log_key = format!( - "{}-{}-{:?}-{:?}", - from_block, to_block, addresses, unique_topics - ); + let log_key = format!("{from_block}-{to_block}-{addresses:?}-{unique_topics:?}"); let mut qb = QueryBuilder::new(""); let query = build_query(&mut qb, from_block, to_block, addresses, unique_topics); let sql = query.sql(); @@ -949,10 +956,6 @@ impl> BackendReader for Backend { log::info!(target: "frontier-sql", "FILTER remove handler - {log_key}"); Ok(out) } - - fn is_indexed(&self) -> bool { - true - } } /// Build a SQL query to retrieve a list of logs given certain constraints. @@ -1046,6 +1049,7 @@ mod test { DefaultTestClientBuilderExt, TestClientBuilder, TestClientBuilderExt, }; // Frontier + use fc_api::Backend as BackendT; use fc_storage::{OverrideHandle, SchemaV3Override, StorageOverride}; use fp_storage::{EthereumStorageSchema, PALLET_ETHEREUM_SCHEMA}; @@ -1073,7 +1077,7 @@ mod test { #[allow(unused)] struct TestData { - backend: super::Backend, + backend: Backend, alice: H160, bob: H160, topics_a: H256, @@ -1135,8 +1139,8 @@ mod test { }); // Indexer backend - let indexer_backend = super::Backend::new( - super::BackendConfig::Sqlite(super::SqliteBackendConfig { + let indexer_backend = Backend::new( + BackendConfig::Sqlite(SqliteBackendConfig { path: Path::new("sqlite:///") .join(tmp.path()) .join("test.db3") @@ -1383,10 +1387,11 @@ mod test { } async fn run_test_case( - backend: super::Backend, + backend: Backend, test_case: &TestFilter, ) -> Result>, String> { backend + .log_indexer() .filter_logs( test_case.from_block, test_case.to_block, @@ -1840,8 +1845,7 @@ ORDER BY b.block_number ASC, l.transaction_index ASC, l.log_index ASC LIMIT 10001"; let mut qb = QueryBuilder::new(""); - let actual_query_sql = - super::build_query(&mut qb, from_block, to_block, addresses, topics).sql(); + let actual_query_sql = build_query(&mut qb, from_block, to_block, addresses, topics).sql(); assert_eq!(expected_query_sql, actual_query_sql); } } diff --git a/client/rpc/Cargo.toml b/client/rpc/Cargo.toml index e08070e713..d62775d230 100644 --- a/client/rpc/Cargo.toml +++ b/client/rpc/Cargo.toml @@ -48,7 +48,7 @@ sp-runtime = { workspace = true } sp-state-machine = { workspace = true } sp-storage = { workspace = true } # Frontier -fc-db = { workspace = true } +fc-api = { workspace = true } fc-mapping-sync = { workspace = true } fc-rpc-core = { workspace = true } fc-storage = { workspace = true } @@ -65,6 +65,8 @@ sc-block-builder = { workspace = true } sc-client-db = { workspace = true, features = ["rocksdb"] } sp-consensus = { workspace = true } substrate-test-runtime-client = { workspace = true } +# Frontier +fc-db = { workspace = true } [features] default = ["rocksdb"] diff --git a/client/rpc/src/eth/filter.rs b/client/rpc/src/eth/filter.rs index 57e4051810..8a0f484173 100644 --- a/client/rpc/src/eth/filter.rs +++ b/client/rpc/src/eth/filter.rs @@ -16,7 +16,12 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use std::{collections::HashSet, marker::PhantomData, sync::Arc, time}; +use std::{ + collections::{BTreeMap, HashSet}, + marker::PhantomData, + sync::Arc, + time::{Duration, Instant}, +}; use ethereum::BlockV2 as EthereumBlock; use ethereum_types::{H256, U256}; @@ -40,7 +45,7 @@ use crate::{eth::cache::EthBlockDataCacheTask, frontier_backend_client, internal pub struct EthFilter { client: Arc, - backend: Arc + Send + Sync>, + backend: Arc>, graph: Arc>, filter_pool: FilterPool, max_stored_filters: usize, @@ -52,7 +57,7 @@ pub struct EthFilter { impl EthFilter { pub fn new( client: Arc, - backend: Arc + Send + Sync>, + backend: Arc>, graph: Arc>, filter_pool: FilterPool, max_stored_filters: usize, @@ -340,7 +345,7 @@ where if backend.is_indexed() { let _ = filter_range_logs_indexed( client.as_ref(), - backend.as_ref(), + backend.log_indexer(), &block_data_cache, &mut ret, max_past_logs, @@ -419,7 +424,7 @@ where if backend.is_indexed() { let _ = filter_range_logs_indexed( client.as_ref(), - backend.as_ref(), + backend.log_indexer(), &block_data_cache, &mut ret, max_past_logs, @@ -508,7 +513,7 @@ where if backend.is_indexed() { let _ = filter_range_logs_indexed( client.as_ref(), - backend.as_ref(), + backend.log_indexer(), &block_data_cache, &mut ret, max_past_logs, @@ -536,7 +541,7 @@ where async fn filter_range_logs_indexed( _client: &C, - backend: &(dyn fc_db::BackendReader + Send + Sync), + backend: &dyn fc_api::LogIndexerBackend, block_data_cache: &EthBlockDataCacheTask, ret: &mut Vec, max_past_logs: u32, @@ -551,13 +556,12 @@ where C: HeaderBackend + StorageProvider + 'static, BE: Backend + 'static, { - use std::time::Instant; let timer_start = Instant::now(); let timer_prepare = Instant::now(); // Max request duration of 10 seconds. - let max_duration = time::Duration::from_secs(10); - let begin_request = time::Instant::now(); + let max_duration = Duration::from_secs(10); + let begin_request = Instant::now(); let topics_input = if filter.topics.is_some() { let filtered_params = FilteredParams::new(Some(filter.clone())); @@ -595,7 +599,6 @@ where { let time_fetch = timer_fetch.elapsed().as_millis(); let timer_post = Instant::now(); - use std::collections::BTreeMap; let mut statuses_cache: BTreeMap>> = BTreeMap::new(); @@ -697,8 +700,8 @@ where BE: Backend + 'static, { // Max request duration of 10 seconds. - let max_duration = time::Duration::from_secs(10); - let begin_request = time::Instant::now(); + let max_duration = Duration::from_secs(10); + let begin_request = Instant::now(); let mut current_number = from; diff --git a/client/rpc/src/eth/mod.rs b/client/rpc/src/eth/mod.rs index ed7a1491a1..646924bb9b 100644 --- a/client/rpc/src/eth/mod.rs +++ b/client/rpc/src/eth/mod.rs @@ -80,7 +80,7 @@ pub struct Eth> { is_authority: bool, signers: Vec>, overrides: Arc>, - backend: Arc + Send + Sync>, + backend: Arc>, block_data_cache: Arc>, fee_history_cache: FeeHistoryCache, fee_history_cache_limit: FeeHistoryCacheLimit, @@ -100,7 +100,7 @@ impl Eth { sync: Arc>, signers: Vec>, overrides: Arc>, - backend: Arc + Send + Sync>, + backend: Arc>, is_authority: bool, block_data_cache: Arc>, fee_history_cache: FeeHistoryCache, diff --git a/client/rpc/src/lib.rs b/client/rpc/src/lib.rs index 9964cad1e4..6d52fb4d68 100644 --- a/client/rpc/src/lib.rs +++ b/client/rpc/src/lib.rs @@ -187,7 +187,7 @@ pub mod frontier_backend_client { pub async fn native_block_id( client: &C, - backend: &(dyn fc_db::BackendReader + Send + Sync), + backend: &dyn fc_api::Backend, number: Option, ) -> RpcResult>> where @@ -213,7 +213,7 @@ pub mod frontier_backend_client { pub async fn load_hash( client: &C, - backend: &(dyn fc_db::BackendReader + Send + Sync), + backend: &dyn fc_api::Backend, hash: H256, ) -> RpcResult> where @@ -250,7 +250,7 @@ pub mod frontier_backend_client { pub async fn load_transactions( client: &C, - backend: &(dyn fc_db::BackendReader + Send + Sync), + backend: &dyn fc_api::Backend, transaction_hash: H256, only_canonical: bool, ) -> RpcResult> @@ -265,7 +265,7 @@ pub mod frontier_backend_client { transaction_metadata .iter() - .find(|meta| is_canon::(client, meta.block_hash)) + .find(|meta| is_canon::(client, meta.substrate_block_hash)) .map_or_else( || { if !only_canonical && transaction_metadata.len() > 0 { diff --git a/template/node/Cargo.toml b/template/node/Cargo.toml index d389cea3c3..0a6c5384ba 100644 --- a/template/node/Cargo.toml +++ b/template/node/Cargo.toml @@ -68,6 +68,7 @@ frame-system = { workspace = true } pallet-transaction-payment = { workspace = true } # Frontier +fc-api = { workspace = true } fc-cli = { workspace = true } fc-consensus = { workspace = true } fc-db = { workspace = true } diff --git a/template/node/src/rpc/eth.rs b/template/node/src/rpc/eth.rs index b019fa2e33..2a117ab5b8 100644 --- a/template/node/src/rpc/eth.rs +++ b/template/node/src/rpc/eth.rs @@ -41,7 +41,7 @@ pub struct EthDeps { /// Chain syncing service pub sync: Arc>, /// Frontier Backend. - pub frontier_backend: Arc + Send + Sync>, + pub frontier_backend: Arc>, /// Ethereum data access overrides. pub overrides: Arc>, /// Cache for Ethereum block data. diff --git a/template/node/src/rpc/mod.rs b/template/node/src/rpc/mod.rs index e1357ce716..2233d54c28 100644 --- a/template/node/src/rpc/mod.rs +++ b/template/node/src/rpc/mod.rs @@ -41,7 +41,7 @@ pub struct DefaultEthConfig(std::marker::PhantomData<(C, BE)>); impl fc_rpc::EthConfig for DefaultEthConfig where - C: sc_client_api::StorageProvider + Sync + Send + 'static, + C: StorageProvider + Sync + Send + 'static, BE: Backend + 'static, { type EstimateGasAdapter = ();