From 374bfa05cf747f67e70fa52b6198df02600016d5 Mon Sep 17 00:00:00 2001 From: koushiro Date: Sun, 12 May 2024 23:38:59 +0800 Subject: [PATCH] refactor: storage override --- Cargo.lock | 2 - client/cli/src/frontier_db_cmd/tests.rs | 8 +- client/db/Cargo.toml | 2 - client/db/src/sql/mod.rs | 94 ++--- client/mapping-sync/src/kv/mod.rs | 29 +- client/mapping-sync/src/kv/worker.rs | 37 +- client/mapping-sync/src/sql/mod.rs | 169 +++------ client/rpc/src/cache/mod.rs | 48 +-- client/rpc/src/debug.rs | 29 +- client/rpc/src/eth/block.rs | 6 +- client/rpc/src/eth/client.rs | 6 +- client/rpc/src/eth/execute.rs | 15 +- client/rpc/src/eth/fee.rs | 18 +- client/rpc/src/eth/filter.rs | 19 +- client/rpc/src/eth/mod.rs | 30 +- client/rpc/src/eth/state.rs | 15 +- client/rpc/src/eth_pubsub.rs | 29 +- client/rpc/src/lib.rs | 5 +- client/storage/Cargo.toml | 1 - client/storage/src/lib.rs | 173 +++++++-- client/storage/src/overrides/mod.rs | 234 +++++------- client/storage/src/overrides/runtime_api.rs | 149 ++++++++ client/storage/src/overrides/schema.rs | 352 ++++++++++++++++++ .../src/overrides/schema_v1_override.rs | 145 -------- .../src/overrides/schema_v2_override.rs | 153 -------- .../src/overrides/schema_v3_override.rs | 140 ------- primitives/rpc/src/lib.rs | 81 ++-- primitives/storage/src/lib.rs | 48 +-- template/node/src/eth.rs | 9 +- template/node/src/rpc/eth.rs | 14 +- template/node/src/rpc/mod.rs | 2 +- template/node/src/service.rs | 21 +- 32 files changed, 978 insertions(+), 1105 deletions(-) create mode 100644 client/storage/src/overrides/runtime_api.rs create mode 100644 client/storage/src/overrides/schema.rs delete mode 100644 client/storage/src/overrides/schema_v1_override.rs delete mode 100644 client/storage/src/overrides/schema_v2_override.rs delete mode 100644 client/storage/src/overrides/schema_v3_override.rs diff --git a/Cargo.lock b/Cargo.lock index 7327245ad4..b27d82c254 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2444,7 +2444,6 @@ dependencies = [ "sp-core", "sp-database", "sp-runtime", - "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.10.1)", "sqlx", "substrate-test-runtime-client", "tempfile", @@ -2568,7 +2567,6 @@ dependencies = [ "parity-scale-codec", "sc-client-api", "sp-api", - "sp-blockchain", "sp-io", "sp-runtime", "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk?branch=release-polkadot-v1.10.1)", diff --git a/client/cli/src/frontier_db_cmd/tests.rs b/client/cli/src/frontier_db_cmd/tests.rs index 712166af0f..54854db948 100644 --- a/client/cli/src/frontier_db_cmd/tests.rs +++ b/client/cli/src/frontier_db_cmd/tests.rs @@ -38,7 +38,7 @@ use substrate_test_runtime_client::{ TestClientBuilder, }; // Frontier -use fp_storage::{EthereumStorageSchema, ETHEREUM_CURRENT_TRANSACTION_STATUS, PALLET_ETHEREUM}; +use fp_storage::{constants::*, EthereumStorageSchema}; use frontier_template_runtime::RuntimeApi; use crate::frontier_db_cmd::{Column, FrontierDbCmd, Operation}; @@ -545,7 +545,7 @@ fn commitment_create() { let statuses = vec![t1]; // Build a block and fill the pallet-ethereum status. - let key = storage_prefix_build(PALLET_ETHEREUM, ETHEREUM_CURRENT_TRANSACTION_STATUS); + let key = storage_prefix_build(PALLET_ETHEREUM, ETHEREUM_CURRENT_TRANSACTION_STATUSES); let chain = client.chain_info(); let mut builder = BlockBuilderBuilder::new(&*client) .on_parent_block(chain.best_hash) @@ -628,7 +628,7 @@ fn commitment_update() { let statuses_a1 = vec![t1.clone()]; let statuses_a2 = vec![t1, t2]; - let key = storage_prefix_build(PALLET_ETHEREUM, ETHEREUM_CURRENT_TRANSACTION_STATUS); + let key = storage_prefix_build(PALLET_ETHEREUM, ETHEREUM_CURRENT_TRANSACTION_STATUSES); // First we create block and insert data in the offchain db. @@ -756,7 +756,7 @@ fn mapping_read_works() { let statuses = vec![t1]; // Build a block and fill the pallet-ethereum status. - let key = storage_prefix_build(PALLET_ETHEREUM, ETHEREUM_CURRENT_TRANSACTION_STATUS); + let key = storage_prefix_build(PALLET_ETHEREUM, ETHEREUM_CURRENT_TRANSACTION_STATUSES); let chain = client.chain_info(); let mut builder = BlockBuilderBuilder::new(&*client) .on_parent_block(chain.best_hash) diff --git a/client/db/Cargo.toml b/client/db/Cargo.toml index b8a4db2d2f..6d188f4e82 100644 --- a/client/db/Cargo.toml +++ b/client/db/Cargo.toml @@ -30,7 +30,6 @@ sp-blockchain = { workspace = true } sp-core = { workspace = true } 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 } @@ -61,7 +60,6 @@ sql = [ "tokio", "sc-client-api", "sp-api", - "sp-storage", "fc-storage", "fp-consensus", "fp-rpc", diff --git a/client/db/src/sql/mod.rs b/client/db/src/sql/mod.rs index 73abc467d9..73b0c8b6e9 100644 --- a/client/db/src/sql/mod.rs +++ b/client/db/src/sql/mod.rs @@ -38,10 +38,10 @@ use sp_runtime::{ }; // Frontier use fc_api::{FilteredLog, TransactionMetadata}; -use fc_storage::OverrideHandle; +use fc_storage::{StorageOverride, StorageQuerier}; use fp_consensus::{FindLogError, Hashes, Log as ConsensusLog, PostLog, PreLog}; use fp_rpc::EthereumRuntimeRPCApi; -use fp_storage::{EthereumStorageSchema, PALLET_ETHEREUM_SCHEMA}; +use fp_storage::EthereumStorageSchema; /// Maximum number to topics allowed to be filtered upon const MAX_TOPIC_COUNT: u16 = 4; @@ -98,7 +98,7 @@ pub struct Backend { pool: SqlitePool, /// The additional overrides for the logs handler. - overrides: Arc>, + storage_override: Arc>, /// The number of allowed operations for the Sqlite filter call. /// A value of `0` disables the timeout. @@ -114,7 +114,7 @@ where config: BackendConfig<'_>, pool_size: u32, num_ops_timeout: Option, - overrides: Arc>, + storage_override: Arc>, ) -> Result { let any_pool = SqlitePoolOptions::new() .max_connections(pool_size) @@ -123,7 +123,7 @@ where let _ = Self::create_indexes_if_not_exist(&any_pool).await?; Ok(Self { pool: any_pool, - overrides, + storage_override, num_ops_timeout: num_ops_timeout .map(|n| n.get()) .unwrap_or(0) @@ -232,8 +232,10 @@ where .expect("runtime api reachable") .expect("ethereum genesis block"); - let schema = - Self::onchain_storage_schema(client.as_ref(), substrate_genesis_hash).encode(); + let schema = StorageQuerier::new(client) + .storage_schema(substrate_genesis_hash) + .unwrap_or(EthereumStorageSchema::V3) + .encode(); let ethereum_block_hash = ethereum_block.header.hash().as_bytes().to_owned(); let substrate_block_hash = substrate_genesis_hash.as_bytes(); let block_number = 0i32; @@ -266,7 +268,7 @@ where fn insert_block_metadata_inner( client: Arc, hash: H256, - overrides: Arc>, + storage_override: &dyn StorageOverride, ) -> Result where Client: StorageProvider + HeaderBackend + 'static, @@ -277,16 +279,14 @@ where if let Ok(Some(header)) = client.header(hash) { match fp_consensus::find_log(header.digest()) { Ok(log) => { - let schema = Self::onchain_storage_schema(client.as_ref(), hash); + let schema = StorageQuerier::new(client.clone()) + .storage_schema(hash) + .unwrap_or(EthereumStorageSchema::V3); let log_hashes = match log { ConsensusLog::Post(PostLog::Hashes(post_hashes)) => post_hashes, ConsensusLog::Post(PostLog::Block(block)) => Hashes::from_block(block), ConsensusLog::Post(PostLog::BlockHash(expect_eth_block_hash)) => { - let ethereum_block = overrides - .schemas - .get(&schema) - .unwrap_or(&overrides.fallback) - .current_block(hash); + let ethereum_block = storage_override.current_block(hash); match ethereum_block { Some(block) => { let got_eth_block_hash = block.header.hash(); @@ -366,9 +366,9 @@ where BE::State: StateBackend, { // Spawn a blocking task to get block metadata from substrate backend. - let overrides = self.overrides.clone(); + let storage_override = self.storage_override.clone(); let metadata = tokio::task::spawn_blocking(move || { - Self::insert_block_metadata_inner(client.clone(), hash, overrides) + Self::insert_block_metadata_inner(client.clone(), hash, &*storage_override) }) .await .map_err(|_| Error::Protocol("tokio blocking metadata task failed".to_string()))??; @@ -435,14 +435,9 @@ 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 + 'static, - BE: BackendT + 'static, - BE::State: StateBackend, - { + pub async fn index_block_logs(&self, block_hash: Block::Hash) { let pool = self.pool().clone(); - let overrides = self.overrides.clone(); + let storage_override = self.storage_override.clone(); let _ = async { // The overarching db transaction for the task. // Due to the async nature of this task, the same work is likely to happen @@ -469,7 +464,7 @@ where Ok(_) => { // Spawn a blocking task to get log data from substrate backend. let logs = tokio::task::spawn_blocking(move || { - Self::get_logs(client.clone(), overrides, block_hash) + Self::get_logs(storage_override, block_hash) }) .await .map_err(|_| Error::Protocol("tokio blocking task failed".to_string()))?; @@ -512,26 +507,14 @@ where log::debug!(target: "frontier-sql", "Batch committed"); } - fn get_logs( - client: Arc, - overrides: Arc>, + fn get_logs( + storage_override: Arc>, substrate_block_hash: H256, - ) -> Vec - where - Client: StorageProvider + HeaderBackend + 'static, - BE: BackendT + 'static, - BE::State: StateBackend, - { + ) -> Vec { let mut logs: Vec = vec![]; let mut transaction_count: usize = 0; let mut log_count: usize = 0; - let schema = Self::onchain_storage_schema(client.as_ref(), substrate_block_hash); - let handler = overrides - .schemas - .get(&schema) - .unwrap_or(&overrides.fallback); - - let receipts = handler + let receipts = storage_override .current_receipts(substrate_block_hash) .unwrap_or_default(); @@ -565,20 +548,6 @@ where logs } - fn onchain_storage_schema(client: &Client, at: Block::Hash) -> EthereumStorageSchema - where - Client: StorageProvider + HeaderBackend + 'static, - BE: BackendT + 'static, - BE::State: StateBackend, - { - match client.storage(at, &sp_storage::StorageKey(PALLET_ETHEREUM_SCHEMA.to_vec())) { - Ok(Some(bytes)) => Decode::decode(&mut &bytes.0[..]) - .ok() - .unwrap_or(EthereumStorageSchema::Undefined), - _ => EthereumStorageSchema::Undefined, - } - } - /// Retrieves the status if a block has been already indexed. pub async fn is_block_indexed(&self, block_hash: Block::Hash) -> bool { sqlx::query("SELECT substrate_block_hash FROM sync_status WHERE substrate_block_hash = ?") @@ -1034,7 +1003,7 @@ LIMIT 10001", mod test { use super::*; - use std::{collections::BTreeMap, path::Path}; + use std::path::Path; use maplit::hashset; use scale_codec::Encode; @@ -1051,7 +1020,7 @@ mod test { }; // Frontier use fc_api::Backend as BackendT; - use fc_storage::{OverrideHandle, SchemaV3Override, StorageOverride}; + use fc_storage::SchemaV3StorageOverride; use fp_storage::{EthereumStorageSchema, PALLET_ETHEREUM_SCHEMA}; type OpaqueBlock = @@ -1129,16 +1098,7 @@ mod test { ); let client = Arc::new(client); // Overrides - let mut overrides_map = BTreeMap::new(); - overrides_map.insert( - EthereumStorageSchema::V3, - Box::new(SchemaV3Override::new(client.clone())) as Box>, - ); - let overrides = Arc::new(OverrideHandle { - schemas: overrides_map, - fallback: Box::new(SchemaV3Override::new(client.clone())), - }); - + let storage_override = Arc::new(SchemaV3StorageOverride::new(client.clone())); // Indexer backend let indexer_backend = Backend::new( BackendConfig::Sqlite(SqliteBackendConfig { @@ -1153,7 +1113,7 @@ mod test { }), 1, None, - overrides.clone(), + storage_override.clone(), ) .await .expect("indexer pool to be created"); diff --git a/client/mapping-sync/src/kv/mod.rs b/client/mapping-sync/src/kv/mod.rs index 5f67b1dac3..0ac044bcd2 100644 --- a/client/mapping-sync/src/kv/mod.rs +++ b/client/mapping-sync/src/kv/mod.rs @@ -31,22 +31,17 @@ use sp_blockchain::{Backend as _, HeaderBackend}; use sp_consensus::SyncOracle; use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Zero}; // Frontier -use fc_storage::OverrideHandle; +use fc_storage::StorageOverride; use fp_consensus::{FindLogError, Hashes, Log, PostLog, PreLog}; use fp_rpc::EthereumRuntimeRPCApi; use crate::{EthereumBlockNotification, EthereumBlockNotificationSinks, SyncStrategy}; -pub fn sync_block( - client: &C, - overrides: Arc>, +pub fn sync_block( + storage_override: Arc>, backend: &fc_db::kv::Backend, header: &Block::Header, -) -> Result<(), String> -where - C: HeaderBackend + StorageProvider, - BE: Backend, -{ +) -> Result<(), String> { let substrate_block_hash = header.hash(); match fp_consensus::find_log(header.digest()) { Ok(log) => { @@ -77,13 +72,7 @@ where backend.mapping().write_hashes(mapping_commitment) } PostLog::BlockHash(expect_eth_block_hash) => { - let schema = - fc_storage::onchain_storage_schema(client, substrate_block_hash); - let ethereum_block = overrides - .schemas - .get(&schema) - .unwrap_or(&overrides.fallback) - .current_block(substrate_block_hash); + let ethereum_block = storage_override.current_block(substrate_block_hash); match ethereum_block { Some(block) => { let got_eth_block_hash = block.header.hash(); @@ -158,7 +147,7 @@ where pub fn sync_one_block( client: &C, substrate_backend: &BE, - overrides: Arc>, + storage_override: Arc>, frontier_backend: &fc_db::kv::Backend, sync_from: ::Number, strategy: SyncStrategy, @@ -220,7 +209,7 @@ where { return Ok(false); } - sync_block(client, overrides, frontier_backend, &operating_header)?; + sync_block(storage_override, frontier_backend, &operating_header)?; current_syncing_tips.push(*operating_header.parent_hash()); frontier_backend @@ -247,7 +236,7 @@ where pub fn sync_blocks( client: &C, substrate_backend: &BE, - overrides: Arc>, + storage_override: Arc>, frontier_backend: &fc_db::kv::Backend, limit: usize, sync_from: ::Number, @@ -270,7 +259,7 @@ where || sync_one_block( client, substrate_backend, - overrides.clone(), + storage_override.clone(), frontier_backend, sync_from, strategy, diff --git a/client/mapping-sync/src/kv/worker.rs b/client/mapping-sync/src/kv/worker.rs index 49b51eec4a..352e9c3b59 100644 --- a/client/mapping-sync/src/kv/worker.rs +++ b/client/mapping-sync/src/kv/worker.rs @@ -34,7 +34,7 @@ use sp_blockchain::HeaderBackend; use sp_consensus::SyncOracle; use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; // Frontier -use fc_storage::OverrideHandle; +use fc_storage::StorageOverride; use fp_rpc::EthereumRuntimeRPCApi; use crate::SyncStrategy; @@ -46,7 +46,7 @@ pub struct MappingSyncWorker { client: Arc, substrate_backend: Arc, - overrides: Arc>, + storage_override: Arc>, frontier_backend: Arc>, have_next: bool, @@ -67,7 +67,7 @@ impl MappingSyncWorker { timeout: Duration, client: Arc, substrate_backend: Arc, - overrides: Arc>, + storage_override: Arc>, frontier_backend: Arc>, retry_times: usize, sync_from: ::Number, @@ -84,7 +84,7 @@ impl MappingSyncWorker { client, substrate_backend, - overrides, + storage_override, frontier_backend, have_next: true, @@ -140,7 +140,7 @@ where match crate::kv::sync_blocks( self.client.as_ref(), self.substrate_backend.as_ref(), - self.overrides.clone(), + self.storage_override.clone(), self.frontier_backend.as_ref(), self.retry_times, self.sync_from, @@ -168,7 +168,7 @@ where mod tests { use super::*; use crate::{EthereumBlockNotification, EthereumBlockNotificationSinks}; - use fc_storage::{OverrideHandle, SchemaV3Override, StorageOverride}; + use fc_storage::SchemaV3StorageOverride; use fp_storage::{EthereumStorageSchema, PALLET_ETHEREUM_SCHEMA}; use sc_block_builder::BlockBuilderBuilder; use sc_client_api::BlockchainEvents; @@ -176,7 +176,6 @@ mod tests { use sp_consensus::BlockOrigin; use sp_core::{H160, H256, U256}; use sp_runtime::{generic::Header, traits::BlakeTwo256, Digest}; - use std::collections::BTreeMap; use substrate_test_runtime_client::{ ClientBlockImportExt, DefaultTestClientBuilderExt, TestClientBuilder, TestClientBuilderExt, }; @@ -248,15 +247,7 @@ mod tests { builder.build_with_native_executor::(None); let mut client = Arc::new(client); // Overrides - let mut overrides_map = BTreeMap::new(); - overrides_map.insert( - EthereumStorageSchema::V3, - Box::new(SchemaV3Override::new(client.clone())) as Box>, - ); - let overrides = Arc::new(OverrideHandle { - schemas: overrides_map, - fallback: Box::new(SchemaV3Override::new(client.clone())), - }); + let storage_override = Arc::new(SchemaV3StorageOverride::new(client.clone())); let frontier_backend = Arc::new( fc_db::kv::Backend::::new( @@ -287,7 +278,7 @@ mod tests { Duration::new(6, 0), client_inner, backend, - overrides.clone(), + storage_override.clone(), frontier_backend, 3, 0, @@ -398,15 +389,7 @@ mod tests { builder.build_with_native_executor::(None); let mut client = Arc::new(client); // Overrides - let mut overrides_map = BTreeMap::new(); - overrides_map.insert( - EthereumStorageSchema::V3, - Box::new(SchemaV3Override::new(client.clone())) as Box>, - ); - let overrides = Arc::new(OverrideHandle { - schemas: overrides_map, - fallback: Box::new(SchemaV3Override::new(client.clone())), - }); + let storage_override = Arc::new(SchemaV3StorageOverride::new(client.clone())); let frontier_backend = Arc::new( fc_db::kv::Backend::::new( @@ -437,7 +420,7 @@ mod tests { Duration::new(6, 0), client_inner, backend, - overrides.clone(), + storage_override.clone(), frontier_backend, 3, 0, diff --git a/client/mapping-sync/src/sql/mod.rs b/client/mapping-sync/src/sql/mod.rs index d83377d1ff..b78885ad2a 100644 --- a/client/mapping-sync/src/sql/mod.rs +++ b/client/mapping-sync/src/sql/mod.rs @@ -153,9 +153,7 @@ where indexer_backend.get_first_pending_canon_block().await { log::debug!(target: "frontier-sql", "Indexing pending canonical block {block_hash:?}"); - indexer_backend - .index_block_logs(client.clone(), block_hash) - .await; + indexer_backend.index_block_logs(block_hash).await; } // Fix any missing blocks @@ -304,7 +302,7 @@ async fn index_block_and_ancestors( log::error!(target: "frontier-sql", "{e}"); }); log::debug!(target: "frontier-sql", "Inserted block metadata"); - indexer_backend.index_block_logs(client.clone(), hash).await; + indexer_backend.index_block_logs(hash).await; if let Ok(Some(header)) = blockchain_backend.header(hash) { let parent_hash = header.parent_hash(); @@ -372,7 +370,7 @@ async fn index_canonical_block_and_ancestors( log::error!(target: "frontier-sql", "{e}"); }); log::debug!(target: "frontier-sql", "Inserted block metadata {hash:?}"); - indexer_backend.index_block_logs(client.clone(), hash).await; + indexer_backend.index_block_logs(hash).await; if let Ok(Some(header)) = blockchain_backend.header(hash) { let parent_hash = header.parent_hash(); @@ -472,7 +470,6 @@ mod test { use super::*; use std::{ - collections::BTreeMap, path::Path, sync::{Arc, Mutex}, }; @@ -495,10 +492,8 @@ mod test { prelude::*, DefaultTestClientBuilderExt, TestClientBuilder, TestClientBuilderExt, }; // Frontier - use fc_storage::{OverrideHandle, SchemaV3Override, StorageOverride}; - use fp_storage::{ - EthereumStorageSchema, ETHEREUM_CURRENT_RECEIPTS, PALLET_ETHEREUM, PALLET_ETHEREUM_SCHEMA, - }; + use fc_storage::SchemaV3StorageOverride; + use fp_storage::{constants::*, EthereumStorageSchema, PALLET_ETHEREUM_SCHEMA}; type OpaqueBlock = sp_runtime::generic::Block< Header, @@ -559,15 +554,7 @@ mod test { builder.build_with_native_executor::(None); let mut client = Arc::new(client); // Overrides - let mut overrides_map = BTreeMap::new(); - overrides_map.insert( - EthereumStorageSchema::V3, - Box::new(SchemaV3Override::new(client.clone())) as Box>, - ); - let overrides = Arc::new(OverrideHandle { - schemas: overrides_map, - fallback: Box::new(SchemaV3Override::new(client.clone())), - }); + let storage_override = Arc::new(SchemaV3StorageOverride::new(client.clone())); // Indexer backend let indexer_backend = fc_db::sql::Backend::new( fc_db::sql::BackendConfig::Sqlite(fc_db::sql::SqliteBackendConfig { @@ -582,7 +569,7 @@ mod test { }), 100, None, - overrides.clone(), + storage_override.clone(), ) .await .expect("indexer pool to be created"); @@ -701,7 +688,7 @@ mod test { }); // Enough time for interval to run - futures_timer::Delay::new(std::time::Duration::from_millis(1500)).await; + futures_timer::Delay::new(Duration::from_millis(1500)).await; // Query db let db_logs = sqlx::query( @@ -770,15 +757,7 @@ mod test { builder.build_with_native_executor::(None); let mut client = Arc::new(client); // Overrides - let mut overrides_map = BTreeMap::new(); - overrides_map.insert( - EthereumStorageSchema::V3, - Box::new(SchemaV3Override::new(client.clone())) as Box>, - ); - let overrides = Arc::new(OverrideHandle { - schemas: overrides_map, - fallback: Box::new(SchemaV3Override::new(client.clone())), - }); + let storage_override = Arc::new(SchemaV3StorageOverride::new(client.clone())); // Indexer backend let indexer_backend = fc_db::sql::Backend::new( fc_db::sql::BackendConfig::Sqlite(fc_db::sql::SqliteBackendConfig { @@ -793,7 +772,7 @@ mod test { }), 100, None, - overrides.clone(), + storage_override.clone(), ) .await .expect("indexer pool to be created"); @@ -912,7 +891,7 @@ mod test { }, )); // Let's not notify too quickly - futures_timer::Delay::new(std::time::Duration::from_millis(100)).await; + futures_timer::Delay::new(Duration::from_millis(100)).await; } // Query db @@ -982,15 +961,7 @@ mod test { builder.build_with_native_executor::(None); let mut client = Arc::new(client); // Overrides - let mut overrides_map = BTreeMap::new(); - overrides_map.insert( - EthereumStorageSchema::V3, - Box::new(SchemaV3Override::new(client.clone())) as Box>, - ); - let overrides = Arc::new(OverrideHandle { - schemas: overrides_map, - fallback: Box::new(SchemaV3Override::new(client.clone())), - }); + let storage_override = Arc::new(SchemaV3StorageOverride::new(client.clone())); // Indexer backend let indexer_backend = fc_db::sql::Backend::new( fc_db::sql::BackendConfig::Sqlite(fc_db::sql::SqliteBackendConfig { @@ -1005,7 +976,7 @@ mod test { }), 100, None, - overrides.clone(), + storage_override.clone(), ) .await .expect("indexer pool to be created"); @@ -1070,7 +1041,7 @@ mod test { } parent_hash = block_hash; // Let's not notify too quickly - futures_timer::Delay::new(std::time::Duration::from_millis(100)).await; + futures_timer::Delay::new(Duration::from_millis(100)).await; } // Test all blocks are initially canon. @@ -1104,7 +1075,7 @@ mod test { executor::block_on(client.import(BlockOrigin::Own, block)).unwrap(); parent_hash = block_hash; // Let's not notify too quickly - futures_timer::Delay::new(std::time::Duration::from_millis(100)).await; + futures_timer::Delay::new(Duration::from_millis(100)).await; } // Test the reorged chain is correctly indexed. @@ -1156,15 +1127,7 @@ mod test { builder.build_with_native_executor::(None); let mut client = Arc::new(client); // Overrides - let mut overrides_map = BTreeMap::new(); - overrides_map.insert( - EthereumStorageSchema::V3, - Box::new(SchemaV3Override::new(client.clone())) as Box>, - ); - let overrides = Arc::new(OverrideHandle { - schemas: overrides_map, - fallback: Box::new(SchemaV3Override::new(client.clone())), - }); + let storage_override = Arc::new(SchemaV3StorageOverride::new(client.clone())); // Indexer backend let indexer_backend = fc_db::sql::Backend::new( fc_db::sql::BackendConfig::Sqlite(fc_db::sql::SqliteBackendConfig { @@ -1179,7 +1142,7 @@ mod test { }), 100, None, - overrides.clone(), + storage_override.clone(), ) .await .expect("indexer pool to be created"); @@ -1252,7 +1215,7 @@ mod test { .await }); // Enough time for indexing - futures_timer::Delay::new(std::time::Duration::from_millis(1500)).await; + futures_timer::Delay::new(Duration::from_millis(1500)).await; // Test the reorged chain is correctly indexed. let actual_imported_blocks = @@ -1309,15 +1272,7 @@ mod test { let (client, _) = builder.build_with_native_executor::(None); let mut client = Arc::new(client); - let mut overrides_map = BTreeMap::new(); - overrides_map.insert( - EthereumStorageSchema::V3, - Box::new(SchemaV3Override::new(client.clone())) as Box>, - ); - let overrides = Arc::new(OverrideHandle { - schemas: overrides_map, - fallback: Box::new(SchemaV3Override::new(client.clone())), - }); + let storage_override = Arc::new(SchemaV3StorageOverride::new(client.clone())); let indexer_backend = fc_db::sql::Backend::new( fc_db::sql::BackendConfig::Sqlite(fc_db::sql::SqliteBackendConfig { path: Path::new("sqlite:///") @@ -1331,7 +1286,7 @@ mod test { }), 100, None, - overrides.clone(), + storage_override.clone(), ) .await .expect("indexer pool to be created"); @@ -1364,7 +1319,7 @@ mod test { .await }); // Enough time for startup - futures_timer::Delay::new(std::time::Duration::from_millis(200)).await; + futures_timer::Delay::new(Duration::from_millis(200)).await; // Import 3 blocks as part of normal operation, storing them oldest first. sync_oracle_wrapper.set_sync_status(false); @@ -1392,7 +1347,7 @@ mod test { } // Enough time for indexing - futures_timer::Delay::new(std::time::Duration::from_millis(3000)).await; + futures_timer::Delay::new(Duration::from_millis(3000)).await; // Test the chain is correctly indexed. let actual_imported_blocks = @@ -1418,15 +1373,7 @@ mod test { let (client, _) = builder.build_with_native_executor::(None); let mut client = Arc::new(client); - let mut overrides_map = BTreeMap::new(); - overrides_map.insert( - EthereumStorageSchema::V3, - Box::new(SchemaV3Override::new(client.clone())) as Box>, - ); - let overrides = Arc::new(OverrideHandle { - schemas: overrides_map, - fallback: Box::new(SchemaV3Override::new(client.clone())), - }); + let storage_override = Arc::new(SchemaV3StorageOverride::new(client.clone())); let indexer_backend = fc_db::sql::Backend::new( fc_db::sql::BackendConfig::Sqlite(fc_db::sql::SqliteBackendConfig { path: Path::new("sqlite:///") @@ -1440,7 +1387,7 @@ mod test { }), 100, None, - overrides.clone(), + storage_override.clone(), ) .await .expect("indexer pool to be created"); @@ -1473,7 +1420,7 @@ mod test { .await }); // Enough time for startup - futures_timer::Delay::new(std::time::Duration::from_millis(200)).await; + futures_timer::Delay::new(Duration::from_millis(200)).await; // Import 3 blocks as part of normal operation, storing them oldest first. sync_oracle_wrapper.set_sync_status(false); @@ -1515,7 +1462,7 @@ mod test { executor::block_on(client.import(BlockOrigin::Own, block)).unwrap(); // Enough time for indexing - futures_timer::Delay::new(std::time::Duration::from_millis(3000)).await; + futures_timer::Delay::new(Duration::from_millis(3000)).await; // Test the chain is correctly indexed. let actual_imported_blocks = @@ -1541,15 +1488,7 @@ mod test { let (client, _) = builder.build_with_native_executor::(None); let mut client = Arc::new(client); - let mut overrides_map = BTreeMap::new(); - overrides_map.insert( - EthereumStorageSchema::V3, - Box::new(SchemaV3Override::new(client.clone())) as Box>, - ); - let overrides = Arc::new(OverrideHandle { - schemas: overrides_map, - fallback: Box::new(SchemaV3Override::new(client.clone())), - }); + let storage_override = Arc::new(SchemaV3StorageOverride::new(client.clone())); let indexer_backend = fc_db::sql::Backend::new( fc_db::sql::BackendConfig::Sqlite(fc_db::sql::SqliteBackendConfig { path: Path::new("sqlite:///") @@ -1563,7 +1502,7 @@ mod test { }), 100, None, - overrides.clone(), + storage_override.clone(), ) .await .expect("indexer pool to be created"); @@ -1596,7 +1535,7 @@ mod test { .await }); // Enough time for startup - futures_timer::Delay::new(std::time::Duration::from_millis(200)).await; + futures_timer::Delay::new(Duration::from_millis(200)).await; // Import 3 blocks as part of normal operation, storing them oldest first. sync_oracle_wrapper.set_sync_status(false); @@ -1624,7 +1563,7 @@ mod test { } // Enough time for indexing - futures_timer::Delay::new(std::time::Duration::from_millis(3000)).await; + futures_timer::Delay::new(Duration::from_millis(3000)).await; // Test the chain is correctly indexed. let actual_imported_blocks = @@ -1650,15 +1589,7 @@ mod test { let (client, _) = builder.build_with_native_executor::(None); let mut client = Arc::new(client); - let mut overrides_map = BTreeMap::new(); - overrides_map.insert( - EthereumStorageSchema::V3, - Box::new(SchemaV3Override::new(client.clone())) as Box>, - ); - let overrides = Arc::new(OverrideHandle { - schemas: overrides_map, - fallback: Box::new(SchemaV3Override::new(client.clone())), - }); + let storage_override = Arc::new(SchemaV3StorageOverride::new(client.clone())); let indexer_backend = fc_db::sql::Backend::new( fc_db::sql::BackendConfig::Sqlite(fc_db::sql::SqliteBackendConfig { path: Path::new("sqlite:///") @@ -1672,7 +1603,7 @@ mod test { }), 100, None, - overrides.clone(), + storage_override.clone(), ) .await .expect("indexer pool to be created"); @@ -1705,7 +1636,7 @@ mod test { .await }); // Enough time for startup - futures_timer::Delay::new(std::time::Duration::from_millis(200)).await; + futures_timer::Delay::new(Duration::from_millis(200)).await; // Import 3 blocks as part of normal operation, storing them oldest first. sync_oracle_wrapper.set_sync_status(false); @@ -1747,7 +1678,7 @@ mod test { executor::block_on(client.import(BlockOrigin::Own, block)).unwrap(); // Enough time for indexing - futures_timer::Delay::new(std::time::Duration::from_millis(3000)).await; + futures_timer::Delay::new(Duration::from_millis(3000)).await; // Test the chain is correctly indexed. let actual_imported_blocks = @@ -1773,15 +1704,7 @@ mod test { let (client, _) = builder.build_with_native_executor::(None); let mut client = Arc::new(client); - let mut overrides_map = BTreeMap::new(); - overrides_map.insert( - EthereumStorageSchema::V3, - Box::new(SchemaV3Override::new(client.clone())) as Box>, - ); - let overrides = Arc::new(OverrideHandle { - schemas: overrides_map, - fallback: Box::new(SchemaV3Override::new(client.clone())), - }); + let storage_override = Arc::new(SchemaV3StorageOverride::new(client.clone())); let indexer_backend = fc_db::sql::Backend::new( fc_db::sql::BackendConfig::Sqlite(fc_db::sql::SqliteBackendConfig { path: Path::new("sqlite:///") @@ -1795,7 +1718,7 @@ mod test { }), 100, None, - overrides.clone(), + storage_override.clone(), ) .await .expect("indexer pool to be created"); @@ -1828,7 +1751,7 @@ mod test { .await }); // Enough time for startup - futures_timer::Delay::new(std::time::Duration::from_millis(200)).await; + futures_timer::Delay::new(Duration::from_millis(200)).await; // Import 3 blocks as part of initial network sync, storing them oldest first. sync_oracle_wrapper.set_sync_status(true); @@ -1856,7 +1779,7 @@ mod test { } // Enough time for indexing - futures_timer::Delay::new(std::time::Duration::from_millis(3000)).await; + futures_timer::Delay::new(Duration::from_millis(3000)).await; // Test the chain is correctly indexed. let actual_imported_blocks = @@ -1882,15 +1805,7 @@ mod test { let (client, _) = builder.build_with_native_executor::(None); let mut client = Arc::new(client); - let mut overrides_map = BTreeMap::new(); - overrides_map.insert( - EthereumStorageSchema::V3, - Box::new(SchemaV3Override::new(client.clone())) as Box>, - ); - let overrides = Arc::new(OverrideHandle { - schemas: overrides_map, - fallback: Box::new(SchemaV3Override::new(client.clone())), - }); + let storage_override = Arc::new(SchemaV3StorageOverride::new(client.clone())); let indexer_backend = fc_db::sql::Backend::new( fc_db::sql::BackendConfig::Sqlite(fc_db::sql::SqliteBackendConfig { path: Path::new("sqlite:///") @@ -1904,7 +1819,7 @@ mod test { }), 100, None, - overrides.clone(), + storage_override.clone(), ) .await .expect("indexer pool to be created"); @@ -1937,7 +1852,7 @@ mod test { .await }); // Enough time for startup - futures_timer::Delay::new(std::time::Duration::from_millis(200)).await; + futures_timer::Delay::new(Duration::from_millis(200)).await; // Import 3 blocks as part of initial network sync, storing them oldest first. sync_oracle_wrapper.set_sync_status(true); @@ -1965,7 +1880,7 @@ mod test { } // Enough time for indexing - futures_timer::Delay::new(std::time::Duration::from_millis(3000)).await; + futures_timer::Delay::new(Duration::from_millis(3000)).await; // Test the chain is correctly indexed. let actual_imported_blocks = diff --git a/client/rpc/src/cache/mod.rs b/client/rpc/src/cache/mod.rs index 3f07861ab0..5ae08f061a 100644 --- a/client/rpc/src/cache/mod.rs +++ b/client/rpc/src/cache/mod.rs @@ -39,9 +39,8 @@ use sp_blockchain::HeaderBackend; use sp_runtime::traits::{Block as BlockT, Header as HeaderT, UniqueSaturatedInto}; // Frontier use fc_rpc_core::types::*; -use fc_storage::{OverrideHandle, StorageOverride}; +use fc_storage::StorageOverride; use fp_rpc::{EthereumRuntimeRPCApi, TransactionStatus}; -use fp_storage::EthereumStorageSchema; use self::lru_cache::LRUCacheByteLimited; @@ -50,7 +49,6 @@ type WaitList = HashMap>>>; enum EthBlockDataCacheMessage { RequestCurrentBlock { block_hash: B::Hash, - schema: EthereumStorageSchema, response_tx: oneshot::Sender>, }, FetchedCurrentBlock { @@ -60,7 +58,6 @@ enum EthBlockDataCacheMessage { RequestCurrentTransactionStatuses { block_hash: B::Hash, - schema: EthereumStorageSchema, response_tx: oneshot::Sender>>, }, FetchedCurrentTransactionStatuses { @@ -78,7 +75,7 @@ pub struct EthBlockDataCacheTask(mpsc::Sender EthBlockDataCacheTask { pub fn new( spawn_handle: SpawnTaskHandle, - overrides: Arc>, + storage_override: Arc>, blocks_cache_max_size: usize, statuses_cache_max_size: usize, prometheus_registry: Option, @@ -113,15 +110,13 @@ impl EthBlockDataCacheTask { match message { RequestCurrentBlock { block_hash, - schema, response_tx, } => Self::request_current( &spawn_handle, &mut blocks_cache, &mut awaiting_blocks, - Arc::clone(&overrides), + storage_override.clone(), block_hash, - schema, response_tx, task_tx.clone(), move |handler| FetchedCurrentBlock { @@ -143,15 +138,13 @@ impl EthBlockDataCacheTask { RequestCurrentTransactionStatuses { block_hash, - schema, response_tx, } => Self::request_current( &spawn_handle, &mut statuses_cache, &mut awaiting_statuses, - Arc::clone(&overrides), + storage_override.clone(), block_hash, - schema, response_tx, task_tx.clone(), move |handler| FetchedCurrentTransactionStatuses { @@ -184,15 +177,14 @@ impl EthBlockDataCacheTask { spawn_handle: &SpawnTaskHandle, cache: &mut LRUCacheByteLimited, wait_list: &mut WaitList, - overrides: Arc>, + storage_override: Arc>, block_hash: B::Hash, - schema: EthereumStorageSchema, response_tx: oneshot::Sender>, task_tx: mpsc::Sender>, handler_call: F, ) where T: Clone + scale_codec::Encode, - F: FnOnce(&Box>) -> EthBlockDataCacheMessage, + F: FnOnce(&dyn StorageOverride) -> EthBlockDataCacheMessage, F: Send + 'static, { // Data is cached, we respond immediately. @@ -214,28 +206,18 @@ impl EthBlockDataCacheTask { wait_list.insert(block_hash, vec![response_tx]); spawn_handle.spawn("EthBlockDataCacheTask Worker", None, async move { - let handler = overrides - .schemas - .get(&schema) - .unwrap_or(&overrides.fallback); - - let message = handler_call(handler); + let message = handler_call(&*storage_override); let _ = task_tx.send(message).await; }); } /// Cache for `handler.current_block`. - pub async fn current_block( - &self, - schema: EthereumStorageSchema, - block_hash: B::Hash, - ) -> Option { + pub async fn current_block(&self, block_hash: B::Hash) -> Option { let (response_tx, response_rx) = oneshot::channel(); self.0 .send(EthBlockDataCacheMessage::RequestCurrentBlock { block_hash, - schema, response_tx, }) .await @@ -247,7 +229,6 @@ impl EthBlockDataCacheTask { /// Cache for `handler.current_transaction_statuses`. pub async fn current_transaction_statuses( &self, - schema: EthereumStorageSchema, block_hash: B::Hash, ) -> Option> { let (response_tx, response_rx) = oneshot::channel(); @@ -256,7 +237,6 @@ impl EthBlockDataCacheTask { .send( EthBlockDataCacheMessage::RequestCurrentTransactionStatuses { block_hash, - schema, response_tx, }, ) @@ -298,7 +278,7 @@ where pub async fn fee_history_task( client: Arc, - overrides: Arc>, + storage_override: Arc>, fee_history_cache: FeeHistoryCache, block_limit: u64, ) { @@ -312,12 +292,6 @@ where FeeHistoryCacheItem, Option ) { - let schema = fc_storage::onchain_storage_schema(client.as_ref(), hash); - let handler = overrides - .schemas - .get(&schema) - .unwrap_or(&overrides.fallback); - // Evenly spaced percentile list from 0.0 to 100.0 with a 0.5 resolution. // This means we cache 200 percentile points. // Later in request handling we will approximate by rounding percentiles that @@ -333,10 +307,10 @@ where .collect() }; - let block = handler.current_block(hash); + let block = storage_override.current_block(hash); let mut block_number: Option = None; let base_fee = client.runtime_api().gas_price(hash).unwrap_or_default(); - let receipts = handler.current_receipts(hash); + let receipts = storage_override.current_receipts(hash); let mut result = FeeHistoryCacheItem { base_fee: UniqueSaturatedInto::::unique_saturated_into(base_fee), gas_used_ratio: 0f64, diff --git a/client/rpc/src/debug.rs b/client/rpc/src/debug.rs index 85ce3307c5..3bd3a03574 100644 --- a/client/rpc/src/debug.rs +++ b/client/rpc/src/debug.rs @@ -29,7 +29,7 @@ use sp_blockchain::HeaderBackend; use sp_runtime::traits::Block as BlockT; // Frontier use fc_rpc_core::{types::*, DebugApiServer}; -use fc_storage::OverrideHandle; +use fc_storage::StorageOverride; use fp_rpc::EthereumRuntimeRPCApi; use crate::{cache::EthBlockDataCacheTask, frontier_backend_client, internal_err}; @@ -38,7 +38,7 @@ use crate::{cache::EthBlockDataCacheTask, frontier_backend_client, internal_err} pub struct Debug { client: Arc, backend: Arc>, - overrides: Arc>, + storage_override: Arc>, block_data_cache: Arc>, _marker: PhantomData, } @@ -47,13 +47,13 @@ impl Debug { pub fn new( client: Arc, backend: Arc>, - overrides: Arc>, + storage_override: Arc>, block_data_cache: Arc>, ) -> Self { Self { client, backend, - overrides, + storage_override, block_data_cache, _marker: PhantomData, } @@ -79,11 +79,7 @@ impl Debug { .client .expect_block_hash_from_id(&id) .map_err(|_| internal_err(format!("Expect block number from id: {}", id)))?; - let schema = fc_storage::onchain_storage_schema(self.client.as_ref(), substrate_hash); - let block = self - .block_data_cache - .current_block(schema, substrate_hash) - .await; + let block = self.block_data_cache.current_block(substrate_hash).await; Ok(block) } @@ -118,11 +114,7 @@ impl Debug { None => return Ok(None), }; - let schema = fc_storage::onchain_storage_schema(self.client.as_ref(), substrate_hash); - let block = self - .block_data_cache - .current_block(schema, substrate_hash) - .await; + let block = self.block_data_cache.current_block(substrate_hash).await; if let Some(block) = block { Ok(Some(block.transactions[index].clone())) } else { @@ -154,13 +146,8 @@ impl Debug { .expect_block_hash_from_id(&id) .map_err(|_| internal_err(format!("Expect block number from id: {}", id)))?; - let schema = fc_storage::onchain_storage_schema(self.client.as_ref(), substrate_hash); - let handler = self - .overrides - .schemas - .get(&schema) - .unwrap_or(&self.overrides.fallback); - let receipts = handler.current_receipts(substrate_hash); + // TODO: use data cache in the future + let receipts = self.storage_override.current_receipts(substrate_hash); Ok(receipts) } } diff --git a/client/rpc/src/eth/block.rs b/client/rpc/src/eth/block.rs index 28b1f614ca..c474355aba 100644 --- a/client/rpc/src/eth/block.rs +++ b/client/rpc/src/eth/block.rs @@ -103,11 +103,9 @@ where .expect_block_hash_from_id(&id) .map_err(|_| internal_err(format!("Expect block number from id: {}", id)))?; - let schema = fc_storage::onchain_storage_schema(client.as_ref(), substrate_hash); - - let block = block_data_cache.current_block(schema, substrate_hash).await; + let block = block_data_cache.current_block(substrate_hash).await; let statuses = block_data_cache - .current_transaction_statuses(schema, substrate_hash) + .current_transaction_statuses(substrate_hash) .await; let base_fee = client.runtime_api().gas_price(substrate_hash).ok(); diff --git a/client/rpc/src/eth/client.rs b/client/rpc/src/eth/client.rs index 63f6475e7a..c25f6d7631 100644 --- a/client/rpc/src/eth/client.rs +++ b/client/rpc/src/eth/client.rs @@ -71,12 +71,8 @@ where pub fn author(&self) -> RpcResult { let hash = self.client.info().best_hash; - let schema = fc_storage::onchain_storage_schema(self.client.as_ref(), hash); let current_block = self - .overrides - .schemas - .get(&schema) - .unwrap_or(&self.overrides.fallback) + .storage_override .current_block(hash) .ok_or_else(|| internal_err("fetching author through override failed"))?; Ok(current_block.header.beneficiary) diff --git a/client/rpc/src/eth/execute.rs b/client/rpc/src/eth/execute.rs index 67a1279324..f60f751e12 100644 --- a/client/rpc/src/eth/execute.rs +++ b/client/rpc/src/eth/execute.rs @@ -40,7 +40,7 @@ use sp_state_machine::OverlayedChanges; use fc_rpc_core::types::*; use fp_evm::{ExecutionInfo, ExecutionInfoV2}; use fp_rpc::{EthereumRuntimeRPCApi, RuntimeStorageOverride}; -use fp_storage::{EVM_ACCOUNT_CODES, PALLET_EVM}; +use fp_storage::constants::{EVM_ACCOUNT_CODES, EVM_ACCOUNT_STORAGES, PALLET_EVM}; use crate::{ eth::{Eth, EthConfig}, @@ -467,8 +467,7 @@ where } let block_gas_limit = { - let schema = fc_storage::onchain_storage_schema(client.as_ref(), substrate_hash); - let block = block_data_cache.current_block(schema, substrate_hash).await; + let block = block_data_cache.current_block(substrate_hash).await; block .ok_or_else(|| internal_err("block unavailable, cannot query gas limit"))? .header @@ -919,12 +918,10 @@ where overlayed_changes.set_storage(key.clone(), Some(encoded_code)); } - let mut account_storage_key = [ - twox_128(PALLET_EVM), - twox_128(fp_storage::EVM_ACCOUNT_STORAGES), - ] - .concat() - .to_vec(); + let mut account_storage_key = + [twox_128(PALLET_EVM), twox_128(EVM_ACCOUNT_STORAGES)] + .concat() + .to_vec(); account_storage_key.extend(blake2_128(address.as_bytes())); account_storage_key.extend(address.as_bytes()); diff --git a/client/rpc/src/eth/fee.rs b/client/rpc/src/eth/fee.rs index f1a0c4c71b..df8a8c20a9 100644 --- a/client/rpc/src/eth/fee.rs +++ b/client/rpc/src/eth/fee.rs @@ -23,7 +23,10 @@ use sc_client_api::backend::{Backend, StorageProvider}; use sc_transaction_pool::ChainApi; use sp_api::ProvideRuntimeApi; use sp_blockchain::HeaderBackend; -use sp_runtime::traits::{Block as BlockT, UniqueSaturatedInto}; +use sp_runtime::{ + traits::{Block as BlockT, UniqueSaturatedInto}, + Permill, +}; // Frontier use fc_rpc_core::types::*; use fp_rpc::EthereumRuntimeRPCApi; @@ -135,17 +138,10 @@ where self.client.expect_block_hash_from_id(&id).map_err(|_| { internal_err(format!("Expect block number from id: {}", id)) })?; - let schema = - fc_storage::onchain_storage_schema(self.client.as_ref(), substrate_hash); - let handler = self - .overrides - .schemas - .get(&schema) - .unwrap_or(&self.overrides.fallback); - let default_elasticity = sp_runtime::Permill::from_parts(125_000); - let elasticity = handler + let elasticity = self + .storage_override .elasticity(substrate_hash) - .unwrap_or(default_elasticity) + .unwrap_or(Permill::from_parts(125_000)) .deconstruct(); let elasticity = elasticity as f64 / 1_000_000f64; let last_fee_per_gas = diff --git a/client/rpc/src/eth/filter.rs b/client/rpc/src/eth/filter.rs index f158cd1065..30c7ae71dc 100644 --- a/client/rpc/src/eth/filter.rs +++ b/client/rpc/src/eth/filter.rs @@ -326,10 +326,7 @@ where internal_err(format!("Expect block number from id: {}", id)) })?; - let schema = - fc_storage::onchain_storage_schema(client.as_ref(), substrate_hash); - - let block = block_data_cache.current_block(schema, substrate_hash).await; + let block = block_data_cache.current_block(substrate_hash).await; if let Some(block) = block { ethereum_hashes.push(block.header.hash()) } @@ -484,11 +481,10 @@ where Some(hash) => hash, _ => return Err(crate::err(-32000, "unknown block", None)), }; - let schema = fc_storage::onchain_storage_schema(client.as_ref(), substrate_hash); - let block = block_data_cache.current_block(schema, substrate_hash).await; + let block = block_data_cache.current_block(substrate_hash).await; let statuses = block_data_cache - .current_transaction_statuses(schema, substrate_hash) + .current_transaction_statuses(substrate_hash) .await; if let (Some(block), Some(statuses)) = (block, statuses) { filter_block_logs(&mut ret, &filter, block, statuses); @@ -606,7 +602,6 @@ where for log in logs.iter() { let substrate_hash = log.substrate_block_hash; - let schema = log.ethereum_storage_schema; let ethereum_block_hash = log.ethereum_block_hash; let block_number = log.block_number; let db_transaction_index = log.transaction_index; @@ -616,7 +611,7 @@ where statuses.clone() } else { let statuses = block_data_cache - .current_transaction_statuses(schema, substrate_hash) + .current_transaction_statuses(substrate_hash) .await; statuses_cache.insert(log.substrate_block_hash, statuses.clone()); statuses @@ -722,16 +717,14 @@ where .expect_block_hash_from_id(&id) .map_err(|_| internal_err(format!("Expect block number from id: {}", id)))?; - let schema = fc_storage::onchain_storage_schema(client, substrate_hash); - - let block = block_data_cache.current_block(schema, substrate_hash).await; + let block = block_data_cache.current_block(substrate_hash).await; if let Some(block) = block { if FilteredParams::address_in_bloom(block.header.logs_bloom, &address_bloom_filter) && FilteredParams::topics_in_bloom(block.header.logs_bloom, &topics_bloom_filter) { let statuses = block_data_cache - .current_transaction_statuses(schema, substrate_hash) + .current_transaction_statuses(substrate_hash) .await; if let Some(statuses) = statuses { filter_block_logs(ret, filter, block, statuses); diff --git a/client/rpc/src/eth/mod.rs b/client/rpc/src/eth/mod.rs index 318d6a9f66..d7d3e14fba 100644 --- a/client/rpc/src/eth/mod.rs +++ b/client/rpc/src/eth/mod.rs @@ -46,7 +46,7 @@ use sp_inherents::CreateInherentDataProviders; use sp_runtime::traits::{Block as BlockT, UniqueSaturatedInto}; // Frontier use fc_rpc_core::{types::*, EthApiServer}; -use fc_storage::OverrideHandle; +use fc_storage::StorageOverride; use fp_rpc::{ ConvertTransaction, ConvertTransactionRuntimeApi, EthereumRuntimeRPCApi, RuntimeStorageOverride, TransactionStatus, @@ -79,7 +79,7 @@ pub struct Eth { sync: Arc>, is_authority: bool, signers: Vec>, - overrides: Arc>, + storage_override: Arc>, backend: Arc>, block_data_cache: Arc>, fee_history_cache: FeeHistoryCache, @@ -110,7 +110,7 @@ where convert_transaction: Option, sync: Arc>, signers: Vec>, - overrides: Arc>, + storage_override: Arc>, backend: Arc>, is_authority: bool, block_data_cache: Arc>, @@ -129,7 +129,7 @@ where sync, is_authority, signers, - overrides, + storage_override, backend, block_data_cache, fee_history_cache, @@ -223,23 +223,13 @@ where &self, substrate_hash: B::Hash, ) -> RpcResult> { - let schema = fc_storage::onchain_storage_schema(self.client.as_ref(), substrate_hash); - let handler = self - .overrides - .schemas - .get(&schema) - .unwrap_or(&self.overrides.fallback); - - let block = self - .block_data_cache - .current_block(schema, substrate_hash) - .await; - let receipts = handler.current_receipts(substrate_hash); + let block = self.block_data_cache.current_block(substrate_hash).await; let statuses = self .block_data_cache - .current_transaction_statuses(schema, substrate_hash) + .current_transaction_statuses(substrate_hash) .await; - let is_eip1559 = handler.is_eip1559(substrate_hash); + let receipts = self.storage_override.current_receipts(substrate_hash); + let is_eip1559 = self.storage_override.is_eip1559(substrate_hash); let base_fee = self .client .runtime_api() @@ -272,7 +262,7 @@ where sync, is_authority, signers, - overrides, + storage_override, backend, block_data_cache, fee_history_cache, @@ -292,7 +282,7 @@ where sync, is_authority, signers, - overrides, + storage_override, backend, block_data_cache, fee_history_cache, diff --git a/client/rpc/src/eth/state.rs b/client/rpc/src/eth/state.rs index 320595f38e..ebc8f2f322 100644 --- a/client/rpc/src/eth/state.rs +++ b/client/rpc/src/eth/state.rs @@ -107,13 +107,9 @@ where .client .expect_block_hash_from_id(&id) .map_err(|_| internal_err(format!("Expect block number from id: {id}")))?; - let schema = fc_storage::onchain_storage_schema(self.client.as_ref(), substrate_hash); Ok(self - .overrides - .schemas - .get(&schema) - .unwrap_or(&self.overrides.fallback) - .storage_at(substrate_hash, address, index) + .storage_override + .account_storage_at(substrate_hash, address, index) .unwrap_or_default()) } else { Ok(H256::default()) @@ -199,13 +195,8 @@ where .client .expect_block_hash_from_id(&id) .map_err(|_| internal_err(format!("Expect block number from id: {id}")))?; - let schema = fc_storage::onchain_storage_schema(self.client.as_ref(), substrate_hash); - Ok(self - .overrides - .schemas - .get(&schema) - .unwrap_or(&self.overrides.fallback) + .storage_override .account_code_at(substrate_hash, address) .unwrap_or_default() .into()) diff --git a/client/rpc/src/eth_pubsub.rs b/client/rpc/src/eth_pubsub.rs index 993b81fa1c..a0feb56182 100644 --- a/client/rpc/src/eth_pubsub.rs +++ b/client/rpc/src/eth_pubsub.rs @@ -45,7 +45,7 @@ use fc_rpc_core::{ }, EthPubSubApiServer, }; -use fc_storage::OverrideHandle; +use fc_storage::StorageOverride; use fp_rpc::EthereumRuntimeRPCApi; #[derive(Debug)] @@ -62,7 +62,7 @@ pub struct EthPubSub { client: Arc, sync: Arc>, executor: SubscriptionTaskExecutor, - overrides: Arc>, + storage_override: Arc>, starting_block: u64, pubsub_notification_sinks: Arc>>, _marker: PhantomData, @@ -75,7 +75,7 @@ impl Clone for EthPubSub { client: self.client.clone(), sync: self.sync.clone(), executor: self.executor.clone(), - overrides: self.overrides.clone(), + storage_override: self.storage_override.clone(), starting_block: self.starting_block, pubsub_notification_sinks: self.pubsub_notification_sinks.clone(), _marker: PhantomData::, @@ -96,7 +96,7 @@ where client: Arc, sync: Arc>, executor: SubscriptionTaskExecutor, - overrides: Arc>, + storage_override: Arc>, pubsub_notification_sinks: Arc< EthereumBlockNotificationSinks>, >, @@ -109,7 +109,7 @@ where client, sync, executor, - overrides, + storage_override, starting_block, pubsub_notification_sinks, _marker: PhantomData, @@ -121,13 +121,7 @@ where notification: EthereumBlockNotification, ) -> future::Ready> { let res = if notification.is_new_best { - let schema = fc_storage::onchain_storage_schema(&*self.client, notification.hash); - let handler = self - .overrides - .schemas - .get(&schema) - .unwrap_or(&self.overrides.fallback); - handler.current_block(notification.hash) + self.storage_override.current_block(notification.hash) } else { None }; @@ -142,15 +136,8 @@ where let res = if notification.is_new_best { let substrate_hash = notification.hash; - let schema = fc_storage::onchain_storage_schema(&*self.client, substrate_hash); - let handler = self - .overrides - .schemas - .get(&schema) - .unwrap_or(&self.overrides.fallback); - - let block = handler.current_block(substrate_hash); - let receipts = handler.current_receipts(substrate_hash); + let block = self.storage_override.current_block(substrate_hash); + let receipts = self.storage_override.current_receipts(substrate_hash); match (block, receipts) { (Some(block), Some(receipts)) => Some((block, receipts)), diff --git a/client/rpc/src/lib.rs b/client/rpc/src/lib.rs index 48a621c81f..f1cce8b83d 100644 --- a/client/rpc/src/lib.rs +++ b/client/rpc/src/lib.rs @@ -54,10 +54,7 @@ pub use fc_rpc_core::{ DebugApiServer, EthApiServer, EthFilterApiServer, EthPubSubApiServer, NetApiServer, Web3ApiServer, }; -pub use fc_storage::{ - OverrideHandle, RuntimeApiStorageOverride, SchemaV1Override, SchemaV2Override, - SchemaV3Override, StorageOverride, -}; +pub use fc_storage::{overrides::*, StorageOverrideHandler}; pub mod frontier_backend_client { use super::internal_err; diff --git a/client/storage/Cargo.toml b/client/storage/Cargo.toml index b259cb0c66..9f0f9f7e54 100644 --- a/client/storage/Cargo.toml +++ b/client/storage/Cargo.toml @@ -18,7 +18,6 @@ scale-codec = { package = "parity-scale-codec", workspace = true } # Substrate sc-client-api = { workspace = true } sp-api = { workspace = true } -sp-blockchain = { workspace = true } sp-io = { workspace = true } sp-runtime = { workspace = true } sp-storage = { workspace = true } diff --git a/client/storage/src/lib.rs b/client/storage/src/lib.rs index 3e423e536b..44d3705441 100644 --- a/client/storage/src/lib.rs +++ b/client/storage/src/lib.rs @@ -18,60 +18,151 @@ #![warn(unused_crate_dependencies)] -mod overrides; -pub use self::overrides::*; +pub mod overrides; -use std::{collections::BTreeMap, sync::Arc}; +use std::sync::Arc; -use scale_codec::Decode; +use ethereum::{BlockV2, ReceiptV3}; +use ethereum_types::{Address, H256, U256}; // Substrate use sc_client_api::{backend::Backend, StorageProvider}; use sp_api::ProvideRuntimeApi; -use sp_blockchain::HeaderBackend; -use sp_runtime::traits::Block as BlockT; -use sp_storage::StorageKey; +use sp_runtime::{traits::Block as BlockT, Permill}; // Frontier -use fp_rpc::EthereumRuntimeRPCApi; -use fp_storage::{EthereumStorageSchema, PALLET_ETHEREUM_SCHEMA}; +use fp_rpc::{EthereumRuntimeRPCApi, TransactionStatus}; +use fp_storage::EthereumStorageSchema; + +pub use self::overrides::*; + +/// A storage override for runtimes that use different ethereum schema. +/// +/// It fetches data from the state backend, with some assumptions about pallet-ethereum's storage +/// schema, as a preference. However, if there is no ethereum schema in the state, it'll use the +/// runtime API as fallback implementation. +/// +/// It is used to avoid spawning the runtime and the overhead associated with it. +#[derive(Clone)] +pub struct StorageOverrideHandler { + querier: StorageQuerier, + fallback: RuntimeApiStorageOverride, +} + +impl StorageOverrideHandler { + pub fn new(client: Arc) -> Self { + Self { + querier: StorageQuerier::new(client.clone()), + fallback: RuntimeApiStorageOverride::::new(client), + } + } +} -pub fn overrides_handle(client: Arc) -> Arc> +impl StorageOverride for StorageOverrideHandler where B: BlockT, C: ProvideRuntimeApi, C::Api: EthereumRuntimeRPCApi, - C: HeaderBackend + StorageProvider + 'static, + C: StorageProvider + Send + Sync + 'static, BE: Backend + 'static, { - let mut overrides_map = BTreeMap::new(); - overrides_map.insert( - EthereumStorageSchema::V1, - Box::new(SchemaV1Override::new(client.clone())) as Box>, - ); - overrides_map.insert( - EthereumStorageSchema::V2, - Box::new(SchemaV2Override::new(client.clone())) as Box>, - ); - overrides_map.insert( - EthereumStorageSchema::V3, - Box::new(SchemaV3Override::new(client.clone())) as Box>, - ); - - Arc::new(OverrideHandle { - schemas: overrides_map, - fallback: Box::new(RuntimeApiStorageOverride::::new(client)), - }) -} + fn account_code_at(&self, at: B::Hash, address: Address) -> Option> { + match self.querier.storage_schema(at) { + Some(EthereumStorageSchema::V1) => { + SchemaV1StorageOverrideRef::new(&self.querier).account_code_at(at, address) + } + Some(EthereumStorageSchema::V2) => { + SchemaV2StorageOverrideRef::new(&self.querier).account_code_at(at, address) + } + Some(EthereumStorageSchema::V3) => { + SchemaV3StorageOverrideRef::new(&self.querier).account_code_at(at, address) + } + None => self.fallback.account_code_at(at, address), + } + } -pub fn onchain_storage_schema(client: &C, hash: B::Hash) -> EthereumStorageSchema -where - B: BlockT, - C: HeaderBackend + StorageProvider, - BE: Backend, -{ - match client.storage(hash, &StorageKey(PALLET_ETHEREUM_SCHEMA.to_vec())) { - Ok(Some(bytes)) => Decode::decode(&mut &bytes.0[..]) - .ok() - .unwrap_or(EthereumStorageSchema::Undefined), - _ => EthereumStorageSchema::Undefined, + fn account_storage_at(&self, at: B::Hash, address: Address, index: U256) -> Option { + match self.querier.storage_schema(at) { + Some(EthereumStorageSchema::V1) => SchemaV1StorageOverrideRef::new(&self.querier) + .account_storage_at(at, address, index), + Some(EthereumStorageSchema::V2) => SchemaV2StorageOverrideRef::new(&self.querier) + .account_storage_at(at, address, index), + Some(EthereumStorageSchema::V3) => SchemaV3StorageOverrideRef::new(&self.querier) + .account_storage_at(at, address, index), + None => self.fallback.account_storage_at(at, address, index), + } + } + + fn current_block(&self, at: B::Hash) -> Option { + match self.querier.storage_schema(at) { + Some(EthereumStorageSchema::V1) => { + SchemaV1StorageOverrideRef::new(&self.querier).current_block(at) + } + Some(EthereumStorageSchema::V2) => { + SchemaV2StorageOverrideRef::new(&self.querier).current_block(at) + } + Some(EthereumStorageSchema::V3) => { + SchemaV3StorageOverrideRef::new(&self.querier).current_block(at) + } + None => self.fallback.current_block(at), + } + } + + fn current_receipts(&self, at: B::Hash) -> Option> { + match self.querier.storage_schema(at) { + Some(EthereumStorageSchema::V1) => { + SchemaV1StorageOverrideRef::new(&self.querier).current_receipts(at) + } + Some(EthereumStorageSchema::V2) => { + SchemaV2StorageOverrideRef::new(&self.querier).current_receipts(at) + } + Some(EthereumStorageSchema::V3) => { + SchemaV3StorageOverrideRef::new(&self.querier).current_receipts(at) + } + None => self.fallback.current_receipts(at), + } + } + + fn current_transaction_statuses(&self, at: B::Hash) -> Option> { + match self.querier.storage_schema(at) { + Some(EthereumStorageSchema::V1) => { + SchemaV1StorageOverrideRef::new(&self.querier).current_transaction_statuses(at) + } + Some(EthereumStorageSchema::V2) => { + SchemaV2StorageOverrideRef::new(&self.querier).current_transaction_statuses(at) + } + Some(EthereumStorageSchema::V3) => { + SchemaV3StorageOverrideRef::new(&self.querier).current_transaction_statuses(at) + } + None => self.fallback.current_transaction_statuses(at), + } + } + + fn elasticity(&self, at: B::Hash) -> Option { + match self.querier.storage_schema(at) { + Some(EthereumStorageSchema::V1) => { + SchemaV1StorageOverrideRef::new(&self.querier).elasticity(at) + } + Some(EthereumStorageSchema::V2) => { + SchemaV2StorageOverrideRef::new(&self.querier).elasticity(at) + } + Some(EthereumStorageSchema::V3) => { + SchemaV3StorageOverrideRef::new(&self.querier).elasticity(at) + } + None => self.fallback.elasticity(at), + } + } + + fn is_eip1559(&self, at: B::Hash) -> bool { + match self.querier.storage_schema(at) { + Some(EthereumStorageSchema::V1) => { + SchemaV1StorageOverrideRef::new(&self.querier).is_eip1559(at) + } + Some(EthereumStorageSchema::V2) => { + SchemaV2StorageOverrideRef::new(&self.querier).is_eip1559(at) + } + Some(EthereumStorageSchema::V3) => { + SchemaV3StorageOverrideRef::new(&self.querier).is_eip1559(at) + } + None => self.fallback.is_eip1559(at), + } } } diff --git a/client/storage/src/overrides/mod.rs b/client/storage/src/overrides/mod.rs index b30e3662d1..f7b39ccf23 100644 --- a/client/storage/src/overrides/mod.rs +++ b/client/storage/src/overrides/mod.rs @@ -1,70 +1,73 @@ -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 // This file is part of Frontier. -// -// Copyright (c) 2017-2022 Parity Technologies (UK) Ltd. -// + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + // 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 std::{collections::BTreeMap, marker::PhantomData, sync::Arc}; +use std::{marker::PhantomData, sync::Arc}; -use ethereum::BlockV2 as EthereumBlock; -use ethereum_types::{H160, H256, U256}; +use ethereum_types::{Address, H256, U256}; +use scale_codec::Decode; // Substrate -use sp_api::{ApiExt, ProvideRuntimeApi}; +use sc_client_api::{Backend, StorageProvider}; use sp_io::hashing::{blake2_128, twox_128}; use sp_runtime::{traits::Block as BlockT, Permill}; +use sp_storage::StorageKey; // Frontier -use fp_rpc::{EthereumRuntimeRPCApi, TransactionStatus}; -use fp_storage::EthereumStorageSchema; +use fp_rpc::TransactionStatus; +use fp_storage::{constants::*, EthereumStorageSchema, PALLET_ETHEREUM_SCHEMA}; -mod schema_v1_override; -mod schema_v2_override; -mod schema_v3_override; +mod runtime_api; +mod schema; pub use self::{ - schema_v1_override::SchemaV1Override, schema_v2_override::SchemaV2Override, - schema_v3_override::SchemaV3Override, + runtime_api::RuntimeApiStorageOverride, + schema::{ + v1::{ + SchemaStorageOverride as SchemaV1StorageOverride, + SchemaStorageOverrideRef as SchemaV1StorageOverrideRef, + }, + v2::{ + SchemaStorageOverride as SchemaV2StorageOverride, + SchemaStorageOverrideRef as SchemaV2StorageOverrideRef, + }, + v3::{ + SchemaStorageOverride as SchemaV3StorageOverride, + SchemaStorageOverrideRef as SchemaV3StorageOverrideRef, + }, + }, }; -pub struct OverrideHandle { - pub schemas: BTreeMap>>, - pub fallback: Box>, -} - -/// Something that can fetch Ethereum-related data. This trait is quite similar to the runtime API, -/// and indeed oe implementation of it uses the runtime API. -/// Having this trait is useful because it allows optimized implementations that fetch data from a -/// State Backend with some assumptions about pallet-ethereum's storage schema. Using such an -/// optimized implementation avoids spawning a runtime and the overhead associated with it. +/// This trait is used to obtain Ethereum-related data. pub trait StorageOverride: Send + Sync { - /// For a given account address, returns pallet_evm::AccountCodes. - fn account_code_at(&self, block_hash: Block::Hash, address: H160) -> Option>; - /// For a given account address and index, returns pallet_evm::AccountStorages. - fn storage_at(&self, block_hash: Block::Hash, address: H160, index: U256) -> Option; - /// Return the current block. - fn current_block(&self, block_hash: Block::Hash) -> Option; - /// Return the current receipt. - fn current_receipts(&self, block_hash: Block::Hash) -> Option>; - /// Return the current transaction status. - fn current_transaction_statuses( - &self, - block_hash: Block::Hash, - ) -> Option>; - /// Return the base fee at the given height. - fn elasticity(&self, block_hash: Block::Hash) -> Option; - /// Return `true` if the request BlockId is post-eip1559. - fn is_eip1559(&self, block_hash: Block::Hash) -> bool; + /// Return the code with the given address. + fn account_code_at(&self, at: Block::Hash, address: Address) -> Option>; + /// Return the storage data with the given address and storage index. + fn account_storage_at(&self, at: Block::Hash, address: Address, index: U256) -> Option; + + /// Return the current ethereum block. + fn current_block(&self, at: Block::Hash) -> Option; + /// Return the current ethereum transaction receipt. + fn current_receipts(&self, at: Block::Hash) -> Option>; + /// Return the current ethereum transaction status. + fn current_transaction_statuses(&self, at: Block::Hash) -> Option>; + + /// Return the elasticity multiplier at the given post-eip1559 block. + fn elasticity(&self, at: Block::Hash) -> Option; + /// Return `true` if the request block is post-eip1559. + fn is_eip1559(&self, at: Block::Hash) -> bool; } fn storage_prefix_build(module: &[u8], storage: &[u8]) -> Vec { @@ -77,14 +80,14 @@ fn blake2_128_extend(bytes: &[u8]) -> Vec { ext } -/// A wrapper type for the Runtime API. This type implements `StorageOverride`, so it can be used -/// when calling the runtime API is desired but a `dyn StorageOverride` is required. -pub struct RuntimeApiStorageOverride { +/// A useful utility for querying storage. +#[derive(Clone)] +pub struct StorageQuerier { client: Arc, - _marker: PhantomData, + _marker: PhantomData<(B, BE)>, } -impl RuntimeApiStorageOverride { +impl StorageQuerier { pub fn new(client: Arc) -> Self { Self { client, @@ -93,111 +96,60 @@ impl RuntimeApiStorageOverride { } } -impl StorageOverride for RuntimeApiStorageOverride +impl StorageQuerier where - Block: BlockT, - C: ProvideRuntimeApi + Send + Sync, - C::Api: EthereumRuntimeRPCApi, + B: BlockT, + C: StorageProvider, + BE: Backend, { - /// For a given account address, returns pallet_evm::AccountCodes. - fn account_code_at(&self, block_hash: Block::Hash, address: H160) -> Option> { - self.client - .runtime_api() - .account_code_at(block_hash, address) - .ok() + pub fn query(&self, at: B::Hash, key: &StorageKey) -> Option { + if let Ok(Some(data)) = self.client.storage(at, key) { + if let Ok(result) = Decode::decode(&mut &data.0[..]) { + return Some(result); + } + } + None } - /// For a given account address and index, returns pallet_evm::AccountStorages. - fn storage_at(&self, block_hash: Block::Hash, address: H160, index: U256) -> Option { - self.client - .runtime_api() - .storage_at(block_hash, address, index) - .ok() + pub fn storage_schema(&self, at: B::Hash) -> Option { + let key = PALLET_ETHEREUM_SCHEMA.to_vec(); + self.query::(at, &StorageKey(key)) } - /// Return the current block. - fn current_block(&self, block_hash: Block::Hash) -> Option { - let api = self.client.runtime_api(); - - let api_version = if let Ok(Some(api_version)) = - api.api_version::>(block_hash) - { - api_version - } else { - return None; - }; - if api_version == 1 { - #[allow(deprecated)] - let old_block = api.current_block_before_version_2(block_hash).ok()?; - old_block.map(|block| block.into()) - } else { - api.current_block(block_hash).ok()? - } + pub fn account_code(&self, at: B::Hash, address: Address) -> Option> { + let mut key: Vec = storage_prefix_build(PALLET_EVM, EVM_ACCOUNT_CODES); + key.extend(blake2_128_extend(address.as_bytes())); + self.query::>(at, &StorageKey(key)) } - /// Return the current receipt. - fn current_receipts(&self, block_hash: Block::Hash) -> Option> { - let api = self.client.runtime_api(); - - let api_version = if let Ok(Some(api_version)) = - api.api_version::>(block_hash) - { - api_version - } else { - return None; - }; - if api_version < 4 { - #[allow(deprecated)] - let old_receipts = api.current_receipts_before_version_4(block_hash).ok()?; - old_receipts.map(|receipts| { - receipts - .into_iter() - .map(|r| { - ethereum::ReceiptV3::Legacy(ethereum::EIP658ReceiptData { - status_code: r.state_root.to_low_u64_be() as u8, - used_gas: r.used_gas, - logs_bloom: r.logs_bloom, - logs: r.logs, - }) - }) - .collect() - }) - } else { - self.client - .runtime_api() - .current_receipts(block_hash) - .ok()? - } + pub fn account_storage(&self, at: B::Hash, address: Address, index: U256) -> Option { + let tmp: &mut [u8; 32] = &mut [0; 32]; + index.to_big_endian(tmp); + + let mut key: Vec = storage_prefix_build(PALLET_EVM, EVM_ACCOUNT_STORAGES); + key.extend(blake2_128_extend(address.as_bytes())); + key.extend(blake2_128_extend(tmp)); + + self.query::(at, &StorageKey(key)) } - /// Return the current transaction status. - fn current_transaction_statuses( - &self, - block_hash: Block::Hash, - ) -> Option> { - self.client - .runtime_api() - .current_transaction_statuses(block_hash) - .ok()? + pub fn current_block(&self, at: B::Hash) -> Option { + let key = storage_prefix_build(PALLET_ETHEREUM, ETHEREUM_CURRENT_BLOCK); + self.query::(at, &StorageKey(key)) } - /// Return the elasticity multiplier at the give post-eip1559 height. - fn elasticity(&self, block_hash: Block::Hash) -> Option { - if self.is_eip1559(block_hash) { - self.client.runtime_api().elasticity(block_hash).ok()? - } else { - None - } + pub fn current_receipts(&self, at: B::Hash) -> Option> { + let key = storage_prefix_build(PALLET_ETHEREUM, ETHEREUM_CURRENT_RECEIPTS); + self.query::>(at, &StorageKey(key)) } - fn is_eip1559(&self, block_hash: Block::Hash) -> bool { - if let Ok(Some(api_version)) = self - .client - .runtime_api() - .api_version::>(block_hash) - { - return api_version >= 2; - } - false + pub fn current_transaction_statuses(&self, at: B::Hash) -> Option> { + let key = storage_prefix_build(PALLET_ETHEREUM, ETHEREUM_CURRENT_TRANSACTION_STATUSES); + self.query::>(at, &StorageKey(key)) + } + + pub fn elasticity(&self, at: B::Hash) -> Option { + let key = storage_prefix_build(PALLET_BASE_FEE, BASE_FEE_ELASTICITY); + self.query::(at, &StorageKey(key)) } } diff --git a/client/storage/src/overrides/runtime_api.rs b/client/storage/src/overrides/runtime_api.rs new file mode 100644 index 0000000000..1e969647c0 --- /dev/null +++ b/client/storage/src/overrides/runtime_api.rs @@ -0,0 +1,149 @@ +// This file is part of Frontier. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// 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 std::{marker::PhantomData, sync::Arc}; + +use ethereum_types::{Address, H256, U256}; +// Substrate +use sp_api::{ApiExt, ApiRef, ProvideRuntimeApi}; +use sp_runtime::{traits::Block as BlockT, Permill}; +// Frontier +use fp_rpc::{EthereumRuntimeRPCApi, TransactionStatus}; + +use crate::overrides::StorageOverride; + +/// A storage override for runtimes that use runtime API. +#[derive(Clone)] +pub struct RuntimeApiStorageOverride { + client: Arc, + _marker: PhantomData, +} + +impl RuntimeApiStorageOverride { + pub fn new(client: Arc) -> Self { + Self { + client, + _marker: PhantomData, + } + } +} + +impl RuntimeApiStorageOverride +where + B: BlockT, + C: ProvideRuntimeApi, + C::Api: EthereumRuntimeRPCApi, +{ + fn api_version(api: &ApiRef<'_, C::Api>, block_hash: B::Hash) -> Option { + match api.api_version::>(block_hash) { + Ok(Some(api_version)) => Some(api_version), + _ => None, + } + } +} + +impl StorageOverride for RuntimeApiStorageOverride +where + B: BlockT, + C: ProvideRuntimeApi + Send + Sync, + C::Api: EthereumRuntimeRPCApi, +{ + fn account_code_at(&self, block_hash: B::Hash, address: Address) -> Option> { + self.client + .runtime_api() + .account_code_at(block_hash, address) + .ok() + } + + fn account_storage_at( + &self, + block_hash: B::Hash, + address: Address, + index: U256, + ) -> Option { + self.client + .runtime_api() + .storage_at(block_hash, address, index) + .ok() + } + + fn current_block(&self, block_hash: B::Hash) -> Option { + let api = self.client.runtime_api(); + + let api_version = Self::api_version(&api, block_hash)?; + if api_version == 1 { + #[allow(deprecated)] + let old_block = api.current_block_before_version_2(block_hash).ok()?; + old_block.map(|block| block.into()) + } else { + api.current_block(block_hash).ok()? + } + } + + fn current_receipts(&self, block_hash: B::Hash) -> Option> { + let api = self.client.runtime_api(); + + let api_version = Self::api_version(&api, block_hash)?; + if api_version < 4 { + #[allow(deprecated)] + let old_receipts = api.current_receipts_before_version_4(block_hash).ok()?; + old_receipts.map(|receipts| { + receipts + .into_iter() + .map(|r| { + ethereum::ReceiptV3::Legacy(ethereum::EIP658ReceiptData { + status_code: r.state_root.to_low_u64_be() as u8, + used_gas: r.used_gas, + logs_bloom: r.logs_bloom, + logs: r.logs, + }) + }) + .collect() + }) + } else { + self.client + .runtime_api() + .current_receipts(block_hash) + .ok()? + } + } + + fn current_transaction_statuses(&self, block_hash: B::Hash) -> Option> { + self.client + .runtime_api() + .current_transaction_statuses(block_hash) + .ok()? + } + + fn elasticity(&self, block_hash: B::Hash) -> Option { + if self.is_eip1559(block_hash) { + self.client.runtime_api().elasticity(block_hash).ok()? + } else { + None + } + } + + fn is_eip1559(&self, block_hash: B::Hash) -> bool { + let api = self.client.runtime_api(); + if let Some(api_version) = Self::api_version(&api, block_hash) { + api_version >= 2 + } else { + false + } + } +} diff --git a/client/storage/src/overrides/schema.rs b/client/storage/src/overrides/schema.rs new file mode 100644 index 0000000000..2848248315 --- /dev/null +++ b/client/storage/src/overrides/schema.rs @@ -0,0 +1,352 @@ +// This file is part of Frontier. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// 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 std::sync::Arc; + +use ethereum_types::{Address, H256, U256}; +// Substrate +use sc_client_api::backend::{Backend, StorageProvider}; +use sp_runtime::{traits::Block as BlockT, Permill}; +// Frontier +use fp_rpc::TransactionStatus; + +use crate::overrides::{StorageOverride, StorageQuerier}; + +pub mod v1 { + use super::*; + + /// A storage override for runtimes that use schema v1. + #[derive(Clone)] + pub struct SchemaStorageOverride { + querier: StorageQuerier, + } + + impl SchemaStorageOverride { + pub fn new(client: Arc) -> Self { + let querier = StorageQuerier::new(client); + Self { querier } + } + } + + impl StorageOverride for SchemaStorageOverride + where + B: BlockT, + C: StorageProvider + Send + Sync, + BE: Backend, + { + fn account_code_at(&self, at: B::Hash, address: Address) -> Option> { + SchemaStorageOverrideRef::new(&self.querier).account_code_at(at, address) + } + + fn account_storage_at(&self, at: B::Hash, address: Address, index: U256) -> Option { + SchemaStorageOverrideRef::new(&self.querier).account_storage_at(at, address, index) + } + + fn current_block(&self, at: B::Hash) -> Option { + SchemaStorageOverrideRef::new(&self.querier).current_block(at) + } + + fn current_receipts(&self, at: B::Hash) -> Option> { + SchemaStorageOverrideRef::new(&self.querier).current_receipts(at) + } + + fn current_transaction_statuses(&self, at: B::Hash) -> Option> { + SchemaStorageOverrideRef::new(&self.querier).current_transaction_statuses(at) + } + + fn elasticity(&self, at: B::Hash) -> Option { + SchemaStorageOverrideRef::new(&self.querier).elasticity(at) + } + + fn is_eip1559(&self, at: B::Hash) -> bool { + SchemaStorageOverrideRef::new(&self.querier).is_eip1559(at) + } + } + + /// A storage override reference for runtimes that use schema v1. + pub struct SchemaStorageOverrideRef<'a, B, C, BE> { + querier: &'a StorageQuerier, + } + + impl<'a, B, C, BE> SchemaStorageOverrideRef<'a, B, C, BE> { + pub fn new(querier: &'a StorageQuerier) -> Self { + Self { querier } + } + } + + impl<'a, B, C, BE> StorageOverride for SchemaStorageOverrideRef<'a, B, C, BE> + where + B: BlockT, + C: StorageProvider + Send + Sync, + BE: Backend, + { + fn account_code_at(&self, at: B::Hash, address: Address) -> Option> { + self.querier.account_code(at, address) + } + + fn account_storage_at(&self, at: B::Hash, address: Address, index: U256) -> Option { + self.querier.account_storage(at, address, index) + } + + fn current_block(&self, at: B::Hash) -> Option { + self.querier + .current_block::(at) + .map(Into::into) + } + + fn current_receipts(&self, at: B::Hash) -> Option> { + self.querier + .current_receipts::(at) + .map(|receipts| { + receipts + .into_iter() + .map(|r| { + ethereum::ReceiptV3::Legacy(ethereum::EIP658ReceiptData { + status_code: r.state_root.to_low_u64_be() as u8, + used_gas: r.used_gas, + logs_bloom: r.logs_bloom, + logs: r.logs, + }) + }) + .collect() + }) + } + + fn current_transaction_statuses(&self, at: B::Hash) -> Option> { + self.querier.current_transaction_statuses(at) + } + + fn elasticity(&self, _at: B::Hash) -> Option { + None + } + + fn is_eip1559(&self, _at: B::Hash) -> bool { + false + } + } +} + +pub mod v2 { + use super::*; + + /// A storage override for runtimes that use schema v2. + #[derive(Clone)] + pub struct SchemaStorageOverride { + querier: StorageQuerier, + } + + impl SchemaStorageOverride { + pub fn new(client: Arc) -> Self { + let querier = StorageQuerier::new(client); + Self { querier } + } + } + + impl StorageOverride for SchemaStorageOverride + where + B: BlockT, + C: StorageProvider + Send + Sync, + BE: Backend, + { + fn account_code_at(&self, at: B::Hash, address: Address) -> Option> { + SchemaStorageOverrideRef::new(&self.querier).account_code_at(at, address) + } + + fn account_storage_at(&self, at: B::Hash, address: Address, index: U256) -> Option { + SchemaStorageOverrideRef::new(&self.querier).account_storage_at(at, address, index) + } + + fn current_block(&self, at: B::Hash) -> Option { + SchemaStorageOverrideRef::new(&self.querier).current_block(at) + } + + fn current_receipts(&self, at: B::Hash) -> Option> { + SchemaStorageOverrideRef::new(&self.querier).current_receipts(at) + } + + fn current_transaction_statuses(&self, at: B::Hash) -> Option> { + SchemaStorageOverrideRef::new(&self.querier).current_transaction_statuses(at) + } + + fn elasticity(&self, at: B::Hash) -> Option { + SchemaStorageOverrideRef::new(&self.querier).elasticity(at) + } + + fn is_eip1559(&self, at: B::Hash) -> bool { + SchemaStorageOverrideRef::new(&self.querier).is_eip1559(at) + } + } + + /// A storage override reference for runtimes that use schema v2. + pub struct SchemaStorageOverrideRef<'a, B, C, BE> { + querier: &'a StorageQuerier, + } + + impl<'a, B, C, BE> SchemaStorageOverrideRef<'a, B, C, BE> { + pub fn new(querier: &'a StorageQuerier) -> Self { + Self { querier } + } + } + + impl<'a, B, C, BE> StorageOverride for SchemaStorageOverrideRef<'a, B, C, BE> + where + B: BlockT, + C: StorageProvider + Send + Sync, + BE: Backend, + { + fn account_code_at(&self, at: B::Hash, address: Address) -> Option> { + self.querier.account_code(at, address) + } + + fn account_storage_at(&self, at: B::Hash, address: Address, index: U256) -> Option { + self.querier.account_storage(at, address, index) + } + + fn current_block(&self, at: B::Hash) -> Option { + self.querier.current_block(at) + } + + fn current_receipts(&self, at: B::Hash) -> Option> { + self.querier + .current_receipts::(at) + .map(|receipts| { + receipts + .into_iter() + .map(|r| { + ethereum::ReceiptV3::Legacy(ethereum::EIP658ReceiptData { + status_code: r.state_root.to_low_u64_be() as u8, + used_gas: r.used_gas, + logs_bloom: r.logs_bloom, + logs: r.logs, + }) + }) + .collect() + }) + } + + fn current_transaction_statuses(&self, at: B::Hash) -> Option> { + self.querier.current_transaction_statuses(at) + } + + fn elasticity(&self, at: B::Hash) -> Option { + self.querier.elasticity(at) + } + + fn is_eip1559(&self, _at: B::Hash) -> bool { + true + } + } +} + +pub mod v3 { + use super::*; + + /// A storage override for runtimes that use schema v3. + #[derive(Clone)] + pub struct SchemaStorageOverride { + querier: StorageQuerier, + } + + impl SchemaStorageOverride { + pub fn new(client: Arc) -> Self { + let querier = StorageQuerier::new(client); + Self { querier } + } + } + + impl StorageOverride for SchemaStorageOverride + where + B: BlockT, + C: StorageProvider + Send + Sync, + BE: Backend, + { + fn account_code_at(&self, at: B::Hash, address: Address) -> Option> { + SchemaStorageOverrideRef::new(&self.querier).account_code_at(at, address) + } + + fn account_storage_at(&self, at: B::Hash, address: Address, index: U256) -> Option { + SchemaStorageOverrideRef::new(&self.querier).account_storage_at(at, address, index) + } + + fn current_block(&self, at: B::Hash) -> Option { + SchemaStorageOverrideRef::new(&self.querier).current_block(at) + } + + fn current_receipts(&self, at: B::Hash) -> Option> { + SchemaStorageOverrideRef::new(&self.querier).current_receipts(at) + } + + fn current_transaction_statuses(&self, at: B::Hash) -> Option> { + SchemaStorageOverrideRef::new(&self.querier).current_transaction_statuses(at) + } + + fn elasticity(&self, at: B::Hash) -> Option { + SchemaStorageOverrideRef::new(&self.querier).elasticity(at) + } + + fn is_eip1559(&self, at: B::Hash) -> bool { + SchemaStorageOverrideRef::new(&self.querier).is_eip1559(at) + } + } + + /// A storage override for runtimes that use schema v3. + pub struct SchemaStorageOverrideRef<'a, B, C, BE> { + querier: &'a StorageQuerier, + } + + impl<'a, B, C, BE> SchemaStorageOverrideRef<'a, B, C, BE> { + pub fn new(querier: &'a StorageQuerier) -> Self { + Self { querier } + } + } + + impl<'a, B, C, BE> StorageOverride for SchemaStorageOverrideRef<'a, B, C, BE> + where + B: BlockT, + C: StorageProvider + Send + Sync, + BE: Backend, + { + fn account_code_at(&self, at: B::Hash, address: Address) -> Option> { + self.querier.account_code(at, address) + } + + fn account_storage_at(&self, at: B::Hash, address: Address, index: U256) -> Option { + self.querier.account_storage(at, address, index) + } + + fn current_block(&self, at: B::Hash) -> Option { + self.querier.current_block(at) + } + + fn current_receipts(&self, at: B::Hash) -> Option> { + self.querier.current_receipts::(at) + } + + fn current_transaction_statuses(&self, at: B::Hash) -> Option> { + self.querier.current_transaction_statuses(at) + } + + fn elasticity(&self, at: B::Hash) -> Option { + self.querier.elasticity(at) + } + + fn is_eip1559(&self, _at: B::Hash) -> bool { + true + } + } +} diff --git a/client/storage/src/overrides/schema_v1_override.rs b/client/storage/src/overrides/schema_v1_override.rs deleted file mode 100644 index 088e7fd0d1..0000000000 --- a/client/storage/src/overrides/schema_v1_override.rs +++ /dev/null @@ -1,145 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 -// This file is part of Frontier. -// -// Copyright (c) 2017-2022 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 std::{marker::PhantomData, sync::Arc}; - -use ethereum_types::{H160, H256, U256}; -use scale_codec::Decode; -// Substrate -use sc_client_api::backend::{Backend, StorageProvider}; -use sp_blockchain::HeaderBackend; -use sp_runtime::{traits::Block as BlockT, Permill}; -use sp_storage::StorageKey; -// Frontier -use fp_rpc::TransactionStatus; -use fp_storage::*; - -use super::{blake2_128_extend, storage_prefix_build, StorageOverride}; - -/// An override for runtimes that use Schema V1 -pub struct SchemaV1Override { - client: Arc, - _marker: PhantomData<(B, BE)>, -} - -impl SchemaV1Override { - pub fn new(client: Arc) -> Self { - Self { - client, - _marker: PhantomData, - } - } -} - -impl SchemaV1Override -where - B: BlockT, - C: HeaderBackend + StorageProvider + 'static, - BE: Backend + 'static, -{ - fn query_storage(&self, block_hash: B::Hash, key: &StorageKey) -> Option { - if let Ok(Some(data)) = self.client.storage(block_hash, key) { - if let Ok(result) = Decode::decode(&mut &data.0[..]) { - return Some(result); - } - } - None - } -} - -impl StorageOverride for SchemaV1Override -where - B: BlockT, - C: HeaderBackend + StorageProvider + 'static, - BE: Backend + 'static, -{ - /// For a given account address, returns pallet_evm::AccountCodes. - fn account_code_at(&self, block_hash: B::Hash, address: H160) -> Option> { - let mut key: Vec = storage_prefix_build(PALLET_EVM, EVM_ACCOUNT_CODES); - key.extend(blake2_128_extend(address.as_bytes())); - self.query_storage::>(block_hash, &StorageKey(key)) - } - - /// For a given account address and index, returns pallet_evm::AccountStorages. - fn storage_at(&self, block_hash: B::Hash, address: H160, index: U256) -> Option { - let tmp: &mut [u8; 32] = &mut [0; 32]; - index.to_big_endian(tmp); - - let mut key: Vec = storage_prefix_build(PALLET_EVM, EVM_ACCOUNT_STORAGES); - key.extend(blake2_128_extend(address.as_bytes())); - key.extend(blake2_128_extend(tmp)); - - self.query_storage::(block_hash, &StorageKey(key)) - } - - /// Return the current block. - fn current_block(&self, block_hash: B::Hash) -> Option { - self.query_storage::( - block_hash, - &StorageKey(storage_prefix_build( - PALLET_ETHEREUM, - ETHEREUM_CURRENT_BLOCK, - )), - ) - .map(Into::into) - } - - /// Return the current receipt. - fn current_receipts(&self, block_hash: B::Hash) -> Option> { - self.query_storage::>( - block_hash, - &StorageKey(storage_prefix_build( - PALLET_ETHEREUM, - ETHEREUM_CURRENT_RECEIPTS, - )), - ) - .map(|receipts| { - receipts - .into_iter() - .map(|r| { - ethereum::ReceiptV3::Legacy(ethereum::EIP658ReceiptData { - status_code: r.state_root.to_low_u64_be() as u8, - used_gas: r.used_gas, - logs_bloom: r.logs_bloom, - logs: r.logs, - }) - }) - .collect() - }) - } - - /// Return the current transaction status. - fn current_transaction_statuses(&self, block_hash: B::Hash) -> Option> { - self.query_storage::>( - block_hash, - &StorageKey(storage_prefix_build( - PALLET_ETHEREUM, - ETHEREUM_CURRENT_TRANSACTION_STATUS, - )), - ) - } - - /// Prior to eip-1559 there is no elasticity. - fn elasticity(&self, _block_hash: B::Hash) -> Option { - None - } - - fn is_eip1559(&self, _block_hash: B::Hash) -> bool { - false - } -} diff --git a/client/storage/src/overrides/schema_v2_override.rs b/client/storage/src/overrides/schema_v2_override.rs deleted file mode 100644 index d21cf1e40e..0000000000 --- a/client/storage/src/overrides/schema_v2_override.rs +++ /dev/null @@ -1,153 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 -// This file is part of Frontier. -// -// Copyright (c) 2017-2022 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 std::{marker::PhantomData, sync::Arc}; - -use ethereum_types::{H160, H256, U256}; -use scale_codec::Decode; -// Substrate -use sc_client_api::backend::{Backend, StorageProvider}; -use sp_blockchain::HeaderBackend; -use sp_runtime::{traits::Block as BlockT, Permill}; -use sp_storage::StorageKey; -// Frontier -use fp_rpc::TransactionStatus; -use fp_storage::*; - -use super::{blake2_128_extend, storage_prefix_build, StorageOverride}; - -/// An override for runtimes that use Schema V2 -pub struct SchemaV2Override { - client: Arc, - _marker: PhantomData<(B, BE)>, -} - -impl SchemaV2Override { - pub fn new(client: Arc) -> Self { - Self { - client, - _marker: PhantomData, - } - } -} - -impl SchemaV2Override -where - B: BlockT, - C: HeaderBackend + StorageProvider + 'static, - BE: Backend + 'static, -{ - fn query_storage(&self, block_hash: B::Hash, key: &StorageKey) -> Option { - if let Ok(Some(data)) = self.client.storage(block_hash, key) { - if let Ok(result) = Decode::decode(&mut &data.0[..]) { - return Some(result); - } - } - None - } -} - -impl StorageOverride for SchemaV2Override -where - B: BlockT, - C: HeaderBackend + StorageProvider + 'static, - BE: Backend + 'static, -{ - /// For a given account address, returns pallet_evm::AccountCodes. - fn account_code_at(&self, block_hash: B::Hash, address: H160) -> Option> { - let mut key: Vec = storage_prefix_build(PALLET_EVM, EVM_ACCOUNT_CODES); - key.extend(blake2_128_extend(address.as_bytes())); - self.query_storage::>(block_hash, &StorageKey(key)) - } - - /// For a given account address and index, returns pallet_evm::AccountStorages. - fn storage_at(&self, block_hash: B::Hash, address: H160, index: U256) -> Option { - let tmp: &mut [u8; 32] = &mut [0; 32]; - index.to_big_endian(tmp); - - let mut key: Vec = storage_prefix_build(PALLET_EVM, EVM_ACCOUNT_STORAGES); - key.extend(blake2_128_extend(address.as_bytes())); - key.extend(blake2_128_extend(tmp)); - - self.query_storage::(block_hash, &StorageKey(key)) - } - - /// Return the current block. - fn current_block(&self, block_hash: B::Hash) -> Option { - self.query_storage::( - block_hash, - &StorageKey(storage_prefix_build( - PALLET_ETHEREUM, - ETHEREUM_CURRENT_BLOCK, - )), - ) - } - - /// Return the current receipt. - fn current_receipts(&self, block_hash: B::Hash) -> Option> { - self.query_storage::>( - block_hash, - &StorageKey(storage_prefix_build( - PALLET_ETHEREUM, - ETHEREUM_CURRENT_RECEIPTS, - )), - ) - .map(|receipts| { - receipts - .into_iter() - .map(|r| { - ethereum::ReceiptV3::Legacy(ethereum::EIP658ReceiptData { - status_code: r.state_root.to_low_u64_be() as u8, - used_gas: r.used_gas, - logs_bloom: r.logs_bloom, - logs: r.logs, - }) - }) - .collect() - }) - } - - /// Return the current transaction status. - fn current_transaction_statuses(&self, block_hash: B::Hash) -> Option> { - self.query_storage::>( - block_hash, - &StorageKey(storage_prefix_build( - PALLET_ETHEREUM, - ETHEREUM_CURRENT_TRANSACTION_STATUS, - )), - ) - } - - /// Return the elasticity at the given height. - fn elasticity(&self, block_hash: B::Hash) -> Option { - let default_elasticity = Some(Permill::from_parts(125_000)); - let elasticity = self.query_storage::( - block_hash, - &StorageKey(storage_prefix_build(PALLET_BASE_FEE, BASE_FEE_ELASTICITY)), - ); - if elasticity.is_some() { - elasticity - } else { - default_elasticity - } - } - - fn is_eip1559(&self, _block_hash: B::Hash) -> bool { - true - } -} diff --git a/client/storage/src/overrides/schema_v3_override.rs b/client/storage/src/overrides/schema_v3_override.rs deleted file mode 100644 index 6dd3494bb2..0000000000 --- a/client/storage/src/overrides/schema_v3_override.rs +++ /dev/null @@ -1,140 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 -// This file is part of Frontier. -// -// Copyright (c) 2017-2022 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 std::{marker::PhantomData, sync::Arc}; - -use ethereum_types::{H160, H256, U256}; -use scale_codec::Decode; -// Substrate -use sc_client_api::backend::{Backend, StorageProvider}; -use sp_blockchain::HeaderBackend; -use sp_runtime::{traits::Block as BlockT, Permill}; -use sp_storage::StorageKey; -// Frontier -use fp_rpc::TransactionStatus; -use fp_storage::*; - -use super::{blake2_128_extend, storage_prefix_build, StorageOverride}; - -/// An override for runtimes that use Schema V3 -pub struct SchemaV3Override { - client: Arc, - _marker: PhantomData<(B, BE)>, -} - -impl SchemaV3Override { - pub fn new(client: Arc) -> Self { - Self { - client, - _marker: PhantomData, - } - } -} - -impl SchemaV3Override -where - B: BlockT, - C: HeaderBackend + StorageProvider + 'static, - BE: Backend + 'static, -{ - fn query_storage(&self, block_hash: B::Hash, key: &StorageKey) -> Option { - if let Ok(Some(data)) = self.client.storage(block_hash, key) { - if let Ok(result) = Decode::decode(&mut &data.0[..]) { - return Some(result); - } - } - None - } -} - -impl StorageOverride for SchemaV3Override -where - B: BlockT, - C: HeaderBackend + StorageProvider + 'static, - BE: Backend + 'static, -{ - /// For a given account address, returns pallet_evm::AccountCodes. - fn account_code_at(&self, block_hash: B::Hash, address: H160) -> Option> { - let mut key: Vec = storage_prefix_build(PALLET_EVM, EVM_ACCOUNT_CODES); - key.extend(blake2_128_extend(address.as_bytes())); - self.query_storage::>(block_hash, &StorageKey(key)) - } - - /// For a given account address and index, returns pallet_evm::AccountStorages. - fn storage_at(&self, block_hash: B::Hash, address: H160, index: U256) -> Option { - let tmp: &mut [u8; 32] = &mut [0; 32]; - index.to_big_endian(tmp); - - let mut key: Vec = storage_prefix_build(PALLET_EVM, EVM_ACCOUNT_STORAGES); - key.extend(blake2_128_extend(address.as_bytes())); - key.extend(blake2_128_extend(tmp)); - - self.query_storage::(block_hash, &StorageKey(key)) - } - - /// Return the current block. - fn current_block(&self, block_hash: B::Hash) -> Option { - self.query_storage::( - block_hash, - &StorageKey(storage_prefix_build( - PALLET_ETHEREUM, - ETHEREUM_CURRENT_BLOCK, - )), - ) - } - - /// Return the current receipt. - fn current_receipts(&self, block_hash: B::Hash) -> Option> { - self.query_storage::>( - block_hash, - &StorageKey(storage_prefix_build( - PALLET_ETHEREUM, - ETHEREUM_CURRENT_RECEIPTS, - )), - ) - } - - /// Return the current transaction status. - fn current_transaction_statuses(&self, block_hash: B::Hash) -> Option> { - self.query_storage::>( - block_hash, - &StorageKey(storage_prefix_build( - PALLET_ETHEREUM, - ETHEREUM_CURRENT_TRANSACTION_STATUS, - )), - ) - } - - /// Return the elasticity at the given height. - fn elasticity(&self, block_hash: B::Hash) -> Option { - let default_elasticity = Some(Permill::from_parts(125_000)); - let elasticity = self.query_storage::( - block_hash, - &StorageKey(storage_prefix_build(PALLET_BASE_FEE, BASE_FEE_ELASTICITY)), - ); - if elasticity.is_some() { - elasticity - } else { - default_elasticity - } - } - - fn is_eip1559(&self, _block_hash: B::Hash) -> bool { - true - } -} diff --git a/primitives/rpc/src/lib.rs b/primitives/rpc/src/lib.rs index a3fd1590db..614e9fa146 100644 --- a/primitives/rpc/src/lib.rs +++ b/primitives/rpc/src/lib.rs @@ -20,11 +20,11 @@ #![warn(unused_crate_dependencies)] use ethereum::Log; -use ethereum_types::Bloom; +use ethereum_types::{Address, Bloom}; use scale_codec::{Decode, Encode}; use scale_info::TypeInfo; // Substrate -use sp_core::{H160, H256, U256}; +use sp_core::{H256, U256}; use sp_runtime::{ traits::{Block as BlockT, HashingFor}, Permill, RuntimeDebug, @@ -36,9 +36,9 @@ use sp_std::vec::Vec; pub struct TransactionStatus { pub transaction_hash: H256, pub transaction_index: u32, - pub from: H160, - pub to: Option, - pub contract_address: Option, + pub from: Address, + pub to: Option
, + pub contract_address: Option
, pub logs: Vec, pub logs_bloom: Bloom, } @@ -51,12 +51,12 @@ pub trait RuntimeStorageOverride: Send + Sync { overlayed_changes: &mut OverlayedChanges>, block: B::Hash, version: u32, - address: H160, + address: Address, balance: Option, nonce: Option, ); - fn into_account_id_bytes(address: H160) -> Vec; + fn into_account_id_bytes(address: Address) -> Vec; } impl RuntimeStorageOverride for () { @@ -69,13 +69,13 @@ impl RuntimeStorageOverride for () { _overlayed_changes: &mut OverlayedChanges>, _block: B::Hash, _version: u32, - _address: H160, + _address: Address, _balance: Option, _nonce: Option, ) { } - fn into_account_id_bytes(_address: H160) -> Vec { + fn into_account_id_bytes(_address: Address) -> Vec { Vec::default() } } @@ -86,21 +86,27 @@ sp_api::decl_runtime_apis! { pub trait EthereumRuntimeRPCApi { /// Returns runtime defined pallet_evm::ChainId. fn chain_id() -> u64; + /// Returns pallet_evm::Accounts by address. - fn account_basic(address: H160) -> fp_evm::Account; + fn account_basic(address: Address) -> fp_evm::Account; + /// Returns FixedGasPrice::min_gas_price fn gas_price() -> U256; + /// For a given account address, returns pallet_evm::AccountCodes. - fn account_code_at(address: H160) -> Vec; + fn account_code_at(address: Address) -> Vec; + /// Returns the converted FindAuthor::find_author authority id. - fn author() -> H160; + fn author() -> Address; + /// For a given account address and index, returns pallet_evm::AccountStorages. - fn storage_at(address: H160, index: U256) -> H256; + fn storage_at(address: Address, index: U256) -> H256; + /// Returns a frame_ethereum::call response. If `estimate` is true, #[changed_in(2)] fn call( - from: H160, - to: H160, + from: Address, + to: Address, data: Vec, value: U256, gas_limit: U256, @@ -110,8 +116,8 @@ sp_api::decl_runtime_apis! { ) -> Result>, sp_runtime::DispatchError>; #[changed_in(4)] fn call( - from: H160, - to: H160, + from: Address, + to: Address, data: Vec, value: U256, gas_limit: U256, @@ -122,8 +128,8 @@ sp_api::decl_runtime_apis! { ) -> Result>, sp_runtime::DispatchError>; #[changed_in(5)] fn call( - from: H160, - to: H160, + from: Address, + to: Address, data: Vec, value: U256, gas_limit: U256, @@ -131,11 +137,11 @@ sp_api::decl_runtime_apis! { max_priority_fee_per_gas: Option, nonce: Option, estimate: bool, - access_list: Option)>>, + access_list: Option)>>, ) -> Result>, sp_runtime::DispatchError>; fn call( - from: H160, - to: H160, + from: Address, + to: Address, data: Vec, value: U256, gas_limit: U256, @@ -143,22 +149,23 @@ sp_api::decl_runtime_apis! { max_priority_fee_per_gas: Option, nonce: Option, estimate: bool, - access_list: Option)>>, + access_list: Option)>>, ) -> Result>, sp_runtime::DispatchError>; + /// Returns a frame_ethereum::create response. #[changed_in(2)] fn create( - from: H160, + from: Address, data: Vec, value: U256, gas_limit: U256, gas_price: Option, nonce: Option, estimate: bool, - ) -> Result, sp_runtime::DispatchError>; + ) -> Result, sp_runtime::DispatchError>; #[changed_in(4)] fn create( - from: H160, + from: Address, data: Vec, value: U256, gas_limit: U256, @@ -166,10 +173,10 @@ sp_api::decl_runtime_apis! { max_priority_fee_per_gas: Option, nonce: Option, estimate: bool, - ) -> Result, sp_runtime::DispatchError>; + ) -> Result, sp_runtime::DispatchError>; #[changed_in(5)] fn create( - from: H160, + from: Address, data: Vec, value: U256, gas_limit: U256, @@ -177,10 +184,10 @@ sp_api::decl_runtime_apis! { max_priority_fee_per_gas: Option, nonce: Option, estimate: bool, - access_list: Option)>>, - ) -> Result, sp_runtime::DispatchError>; + access_list: Option)>>, + ) -> Result, sp_runtime::DispatchError>; fn create( - from: H160, + from: Address, data: Vec, value: U256, gas_limit: U256, @@ -188,20 +195,24 @@ sp_api::decl_runtime_apis! { max_priority_fee_per_gas: Option, nonce: Option, estimate: bool, - access_list: Option)>>, - ) -> Result, sp_runtime::DispatchError>; + access_list: Option)>>, + ) -> Result, sp_runtime::DispatchError>; + /// Return the current block. Legacy. #[changed_in(2)] fn current_block() -> Option; /// Return the current block. fn current_block() -> Option; + /// Return the current receipt. #[changed_in(4)] fn current_receipts() -> Option>; /// Return the current receipt. fn current_receipts() -> Option>; + /// Return the current transaction status. fn current_transaction_statuses() -> Option>; + /// Return all the current data for a block in a single runtime call. Legacy. #[changed_in(2)] fn current_all() -> ( @@ -221,6 +232,7 @@ sp_api::decl_runtime_apis! { Option>, Option> ); + /// Receives a `Vec` and filters all the ethereum transactions. Legacy. #[changed_in(2)] fn extrinsic_filter( @@ -230,11 +242,14 @@ sp_api::decl_runtime_apis! { fn extrinsic_filter( xts: Vec<::Extrinsic>, ) -> Vec; + /// Return the elasticity multiplier. fn elasticity() -> Option; + /// Used to determine if gas limit multiplier for non-transactional calls (eth_call/estimateGas) /// is supported. fn gas_limit_multiplier_support(); + /// Return the pending block. fn pending_block( xts: Vec<::Extrinsic>, diff --git a/primitives/storage/src/lib.rs b/primitives/storage/src/lib.rs index 8fb464cbdf..34d682aa0f 100644 --- a/primitives/storage/src/lib.rs +++ b/primitives/storage/src/lib.rs @@ -20,39 +20,41 @@ use scale_codec::{Decode, Encode}; +/// Some storage constants +pub mod constants { + /// Pallet Evm storage items + pub const PALLET_EVM: &[u8] = b"EVM"; + pub const EVM_ACCOUNT_CODES: &[u8] = b"AccountCodes"; + pub const EVM_ACCOUNT_STORAGES: &[u8] = b"AccountStorages"; + + /// Pallet Ethereum storage items + pub const PALLET_ETHEREUM: &[u8] = b"Ethereum"; + pub const ETHEREUM_CURRENT_BLOCK: &[u8] = b"CurrentBlock"; + pub const ETHEREUM_CURRENT_RECEIPTS: &[u8] = b"CurrentReceipts"; + pub const ETHEREUM_CURRENT_TRANSACTION_STATUSES: &[u8] = b"CurrentTransactionStatuses"; + + /// Pallet BaseFee storage items + pub const PALLET_BASE_FEE: &[u8] = b"BaseFee"; + pub const BASE_FEE_PER_GAS: &[u8] = b"BaseFeePerGas"; + pub const BASE_FEE_ELASTICITY: &[u8] = b"Elasticity"; +} + /// Current version of pallet Ethereum's storage schema is stored under this key. pub const PALLET_ETHEREUM_SCHEMA: &[u8] = b":ethereum_schema"; /// Cached version of pallet Ethereum's storage schema is stored under this key in the AuxStore. pub const PALLET_ETHEREUM_SCHEMA_CACHE: &[u8] = b":ethereum_schema_cache"; -/// Pallet Evm storage items -pub const PALLET_EVM: &[u8] = b"EVM"; -pub const EVM_ACCOUNT_CODES: &[u8] = b"AccountCodes"; -pub const EVM_ACCOUNT_STORAGES: &[u8] = b"AccountStorages"; - -/// Pallet Ethereum storage items -pub const PALLET_ETHEREUM: &[u8] = b"Ethereum"; -pub const ETHEREUM_CURRENT_BLOCK: &[u8] = b"CurrentBlock"; -pub const ETHEREUM_CURRENT_RECEIPTS: &[u8] = b"CurrentReceipts"; -pub const ETHEREUM_CURRENT_TRANSACTION_STATUS: &[u8] = b"CurrentTransactionStatuses"; - -/// Pallet BaseFee storage items -pub const PALLET_BASE_FEE: &[u8] = b"BaseFee"; -pub const BASE_FEE_PER_GAS: &[u8] = b"BaseFeePerGas"; -pub const BASE_FEE_ELASTICITY: &[u8] = b"Elasticity"; - /// The schema version for Pallet Ethereum's storage #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Encode, Decode)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum EthereumStorageSchema { - Undefined, + // deprecated + // #[codec(index = 0)] + // Undefined, + #[codec(index = 1)] V1, + #[codec(index = 2)] V2, + #[codec(index = 3)] V3, } - -impl Default for EthereumStorageSchema { - fn default() -> Self { - Self::Undefined - } -} diff --git a/template/node/src/eth.rs b/template/node/src/eth.rs index 7400943a91..a3bcb3dbe0 100644 --- a/template/node/src/eth.rs +++ b/template/node/src/eth.rs @@ -14,8 +14,9 @@ use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; use sp_api::ConstructRuntimeApi; // Frontier pub use fc_consensus::FrontierBlockImport; -use fc_rpc::{EthTask, OverrideHandle}; +use fc_rpc::EthTask; pub use fc_rpc_core::types::{FeeHistoryCache, FeeHistoryCacheLimit, FilterPool}; +pub use fc_storage::{StorageOverride, StorageOverrideHandler}; // Local use frontier_template_runtime::opaque::Block; @@ -128,7 +129,7 @@ pub async fn spawn_frontier_tasks( backend: Arc, frontier_backend: FrontierBackend, filter_pool: Option, - overrides: Arc>, + storage_override: Arc>, fee_history_cache: FeeHistoryCache, fee_history_cache_limit: FeeHistoryCacheLimit, sync: Arc>, @@ -154,7 +155,7 @@ pub async fn spawn_frontier_tasks( Duration::new(6, 0), client.clone(), backend, - overrides.clone(), + storage_override.clone(), Arc::new(b), 3, 0, @@ -203,7 +204,7 @@ pub async fn spawn_frontier_tasks( Some("frontier"), EthTask::fee_history_task( client, - overrides, + storage_override, fee_history_cache, fee_history_cache_limit, ), diff --git a/template/node/src/rpc/eth.rs b/template/node/src/rpc/eth.rs index 29e15a26da..8e4ca12dc3 100644 --- a/template/node/src/rpc/eth.rs +++ b/template/node/src/rpc/eth.rs @@ -20,9 +20,9 @@ use sp_core::H256; use sp_inherents::CreateInherentDataProviders; use sp_runtime::traits::Block as BlockT; // Frontier -pub use fc_rpc::{EthBlockDataCacheTask, EthConfig, OverrideHandle}; +pub use fc_rpc::{EthBlockDataCacheTask, EthConfig}; pub use fc_rpc_core::types::{FeeHistoryCache, FeeHistoryCacheLimit, FilterPool}; -pub use fc_storage::overrides_handle; +use fc_storage::StorageOverride; use fp_rpc::{ConvertTransaction, ConvertTransactionRuntimeApi, EthereumRuntimeRPCApi}; /// Extra dependencies for Ethereum compatibility. @@ -46,7 +46,7 @@ pub struct EthDeps { /// Frontier Backend. pub frontier_backend: Arc>, /// Ethereum data access overrides. - pub overrides: Arc>, + pub storage_override: Arc>, /// Cache for Ethereum block data. pub block_data_cache: Arc>, /// EthFilterApi pool. @@ -111,7 +111,7 @@ where network, sync, frontier_backend, - overrides, + storage_override, block_data_cache, filter_pool, max_past_logs, @@ -135,7 +135,7 @@ where converter, sync.clone(), signers, - overrides.clone(), + storage_override.clone(), frontier_backend.clone(), is_authority, block_data_cache.clone(), @@ -171,7 +171,7 @@ where client.clone(), sync, subscription_task_executor, - overrides.clone(), + storage_override.clone(), pubsub_notification_sinks, ) .into_rpc(), @@ -193,7 +193,7 @@ where Debug::new( client.clone(), frontier_backend, - overrides, + storage_override, block_data_cache, ) .into_rpc(), diff --git a/template/node/src/rpc/mod.rs b/template/node/src/rpc/mod.rs index b655b1e890..0c8a7300ff 100644 --- a/template/node/src/rpc/mod.rs +++ b/template/node/src/rpc/mod.rs @@ -24,7 +24,7 @@ use sp_runtime::traits::Block as BlockT; use frontier_template_runtime::{opaque::Block, AccountId, Balance, Hash, Nonce}; mod eth; -pub use self::eth::{create_eth, overrides_handle, EthDeps}; +pub use self::eth::{create_eth, EthDeps}; /// Full client dependencies. pub struct FullDeps { diff --git a/template/node/src/service.rs b/template/node/src/service.rs index a008902c3d..69c0605f59 100644 --- a/template/node/src/service.rs +++ b/template/node/src/service.rs @@ -23,7 +23,8 @@ use crate::{ client::{BaseRuntimeApiCollection, FullBackend, FullClient, RuntimeApiCollection}, eth::{ new_frontier_partial, spawn_frontier_tasks, BackendType, EthCompatRuntimeApiCollection, - FrontierBackend, FrontierBlockImport, FrontierPartialComponents, + FrontierBackend, FrontierBlockImport, FrontierPartialComponents, StorageOverride, + StorageOverrideHandler, }, }; pub use crate::{ @@ -60,7 +61,7 @@ pub fn new_partial( BoxBlockImport, GrandpaLinkHalf>, FrontierBackend, - Arc>, + Arc>, ), >, ServiceError, @@ -116,7 +117,7 @@ where telemetry.as_ref().map(|x| x.handle()), )?; - let overrides = crate::rpc::overrides_handle(client.clone()); + let storage_override = Arc::new(StorageOverrideHandler::new(client.clone())); let frontier_backend = match eth_config.frontier_backend_type { BackendType::KeyValue => FrontierBackend::KeyValue(fc_db::kv::Backend::open( Arc::clone(&client), @@ -139,7 +140,7 @@ where }), eth_config.frontier_sql_backend_pool_size, std::num::NonZeroU32::new(eth_config.frontier_sql_backend_num_ops_timeout), - overrides.clone(), + storage_override.clone(), )) .unwrap_or_else(|err| panic!("failed creating sql backend: {:?}", err)); FrontierBackend::Sql(backend) @@ -176,7 +177,7 @@ where block_import, grandpa_link, frontier_backend, - overrides, + storage_override, ), }) } @@ -282,7 +283,7 @@ where keystore_container, select_chain, transaction_pool, - other: (mut telemetry, block_import, grandpa_link, frontier_backend, overrides), + other: (mut telemetry, block_import, grandpa_link, frontier_backend, storage_override), } = new_partial(&config, ð_config, build_import_queue)?; let FrontierPartialComponents { @@ -380,11 +381,11 @@ where let filter_pool = filter_pool.clone(); let frontier_backend = frontier_backend.clone(); let pubsub_notification_sinks = pubsub_notification_sinks.clone(); - let overrides = overrides.clone(); + let storage_override = storage_override.clone(); let fee_history_cache = fee_history_cache.clone(); let block_data_cache = Arc::new(fc_rpc::EthBlockDataCacheTask::new( task_manager.spawn_handle(), - overrides.clone(), + storage_override.clone(), eth_config.eth_log_block_cache, eth_config.eth_statuses_cache, prometheus_registry.clone(), @@ -418,7 +419,7 @@ where fc_db::Backend::KeyValue(b) => Arc::new(b), fc_db::Backend::Sql(b) => Arc::new(b), }, - overrides: overrides.clone(), + storage_override: storage_override.clone(), block_data_cache: block_data_cache.clone(), filter_pool: filter_pool.clone(), max_past_logs, @@ -469,7 +470,7 @@ where backend, frontier_backend, filter_pool, - overrides, + storage_override, fee_history_cache, fee_history_cache_limit, sync_service.clone(),