diff --git a/Cargo.lock b/Cargo.lock index 1ba4ed0afe0..5e04d0015a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2387,7 +2387,7 @@ dependencies = [ [[package]] name = "fc-consensus" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#375226a771f4009ee183809c3a359e37e2b9247a" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#51d6a64cbdea721df4e3920f6e61166631b56ac3" dependencies = [ "async-trait", "derive_more", @@ -2413,7 +2413,7 @@ dependencies = [ [[package]] name = "fc-db" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#375226a771f4009ee183809c3a359e37e2b9247a" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#51d6a64cbdea721df4e3920f6e61166631b56ac3" dependencies = [ "fp-storage", "kvdb", @@ -2429,7 +2429,7 @@ dependencies = [ [[package]] name = "fc-mapping-sync" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#375226a771f4009ee183809c3a359e37e2b9247a" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#51d6a64cbdea721df4e3920f6e61166631b56ac3" dependencies = [ "fc-consensus", "fc-db", @@ -2447,7 +2447,7 @@ dependencies = [ [[package]] name = "fc-rpc" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#375226a771f4009ee183809c3a359e37e2b9247a" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#51d6a64cbdea721df4e3920f6e61166631b56ac3" dependencies = [ "ethereum", "ethereum-types", @@ -2493,7 +2493,7 @@ dependencies = [ [[package]] name = "fc-rpc-core" version = "1.1.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#375226a771f4009ee183809c3a359e37e2b9247a" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#51d6a64cbdea721df4e3920f6e61166631b56ac3" dependencies = [ "ethereum", "ethereum-types", @@ -2614,7 +2614,7 @@ dependencies = [ [[package]] name = "fp-consensus" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#375226a771f4009ee183809c3a359e37e2b9247a" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#51d6a64cbdea721df4e3920f6e61166631b56ac3" dependencies = [ "ethereum", "parity-scale-codec", @@ -2628,7 +2628,7 @@ dependencies = [ [[package]] name = "fp-evm" version = "3.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#375226a771f4009ee183809c3a359e37e2b9247a" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#51d6a64cbdea721df4e3920f6e61166631b56ac3" dependencies = [ "evm", "parity-scale-codec", @@ -2640,7 +2640,7 @@ dependencies = [ [[package]] name = "fp-rpc" version = "3.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#375226a771f4009ee183809c3a359e37e2b9247a" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#51d6a64cbdea721df4e3920f6e61166631b56ac3" dependencies = [ "ethereum", "ethereum-types", @@ -2657,7 +2657,7 @@ dependencies = [ [[package]] name = "fp-self-contained" version = "1.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#375226a771f4009ee183809c3a359e37e2b9247a" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#51d6a64cbdea721df4e3920f6e61166631b56ac3" dependencies = [ "ethereum", "frame-support", @@ -2674,7 +2674,7 @@ dependencies = [ [[package]] name = "fp-storage" version = "2.0.0" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#375226a771f4009ee183809c3a359e37e2b9247a" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#51d6a64cbdea721df4e3920f6e61166631b56ac3" [[package]] name = "frame-benchmarking" @@ -5545,6 +5545,7 @@ dependencies = [ "pallet-author-mapping", "pallet-author-slot-filter", "pallet-balances", + "pallet-base-fee", "pallet-collective", "pallet-crowdloan-rewards", "pallet-democracy", @@ -5754,6 +5755,7 @@ dependencies = [ "pallet-author-mapping", "pallet-author-slot-filter", "pallet-balances", + "pallet-base-fee", "pallet-collective", "pallet-crowdloan-rewards", "pallet-democracy", @@ -6553,7 +6555,7 @@ dependencies = [ [[package]] name = "pallet-base-fee" version = "1.0.0" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#375226a771f4009ee183809c3a359e37e2b9247a" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#51d6a64cbdea721df4e3920f6e61166631b56ac3" dependencies = [ "frame-support", "frame-system", @@ -6808,7 +6810,7 @@ dependencies = [ [[package]] name = "pallet-ethereum" version = "4.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#375226a771f4009ee183809c3a359e37e2b9247a" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#51d6a64cbdea721df4e3920f6e61166631b56ac3" dependencies = [ "ethereum", "ethereum-types", @@ -6849,7 +6851,7 @@ dependencies = [ [[package]] name = "pallet-evm" version = "6.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#375226a771f4009ee183809c3a359e37e2b9247a" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#51d6a64cbdea721df4e3920f6e61166631b56ac3" dependencies = [ "evm", "evm-gasometer", @@ -6928,7 +6930,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-blake2" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#375226a771f4009ee183809c3a359e37e2b9247a" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#51d6a64cbdea721df4e3920f6e61166631b56ac3" dependencies = [ "fp-evm", "sp-core", @@ -6938,7 +6940,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-bn128" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#375226a771f4009ee183809c3a359e37e2b9247a" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#51d6a64cbdea721df4e3920f6e61166631b56ac3" dependencies = [ "fp-evm", "sp-core", @@ -6949,7 +6951,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-dispatch" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#375226a771f4009ee183809c3a359e37e2b9247a" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#51d6a64cbdea721df4e3920f6e61166631b56ac3" dependencies = [ "fp-evm", "frame-support", @@ -6962,7 +6964,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-modexp" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#375226a771f4009ee183809c3a359e37e2b9247a" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#51d6a64cbdea721df4e3920f6e61166631b56ac3" dependencies = [ "fp-evm", "num", @@ -6973,7 +6975,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-sha3fips" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#375226a771f4009ee183809c3a359e37e2b9247a" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#51d6a64cbdea721df4e3920f6e61166631b56ac3" dependencies = [ "fp-evm", "sp-core", @@ -6984,7 +6986,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-simple" version = "2.0.0-dev" -source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#375226a771f4009ee183809c3a359e37e2b9247a" +source = "git+https://github.com/purestake/frontier?branch=moonbeam-polkadot-v0.9.13#51d6a64cbdea721df4e3920f6e61166631b56ac3" dependencies = [ "fp-evm", "ripemd160", @@ -9867,9 +9869,9 @@ dependencies = [ [[package]] name = "rlp" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e54369147e3e7796c9b885c7304db87ca3d09a0a98f72843d532868675bbfba8" +checksum = "999508abb0ae792aabed2460c45b89106d97fe4adac593bdaef433c2605847b5" dependencies = [ "bytes 1.0.1", "rustc-hex", diff --git a/node/cli-opt/src/lib.rs b/node/cli-opt/src/lib.rs index ac82ca7d294..823fb916bb8 100644 --- a/node/cli-opt/src/lib.rs +++ b/node/cli-opt/src/lib.rs @@ -76,4 +76,5 @@ pub struct RpcConfig { pub ethapi_trace_cache_duration: u64, pub eth_log_block_cache: usize, pub max_past_logs: u32, + pub fee_history_limit: u64, } diff --git a/node/cli/src/cli.rs b/node/cli/src/cli.rs index 8032ba7523d..688a68e6b9e 100644 --- a/node/cli/src/cli.rs +++ b/node/cli/src/cli.rs @@ -192,6 +192,10 @@ pub struct RunCmd { /// Id of the parachain this collator collates for. #[structopt(long)] pub parachain_id: Option, + + /// Maximum fee history cache size. + #[structopt(long, default_value = "2048")] + pub fee_history_limit: u64, } impl std::ops::Deref for RunCmd { diff --git a/node/cli/src/command.rs b/node/cli/src/command.rs index 586f1d596cf..ebb9953bedb 100644 --- a/node/cli/src/command.rs +++ b/node/cli/src/command.rs @@ -601,6 +601,7 @@ pub fn run() -> Result<()> { ethapi_trace_cache_duration: cli.run.ethapi_trace_cache_duration, eth_log_block_cache: cli.run.eth_log_block_cache, max_past_logs: cli.run.max_past_logs, + fee_history_limit: cli.run.fee_history_limit, }; // If dev service was requested, start up manual or instant seal. diff --git a/node/perf-test/src/command.rs b/node/perf-test/src/command.rs index 3cc6e5d5602..6ae0798deab 100644 --- a/node/perf-test/src/command.rs +++ b/node/perf-test/src/command.rs @@ -90,7 +90,14 @@ where select_chain: maybe_select_chain, transaction_pool, other: - (block_import, filter_pool, telemetry, _telemetry_worker_handle, frontier_backend), + ( + block_import, + filter_pool, + telemetry, + _telemetry_worker_handle, + frontier_backend, + fee_history_cache, + ), } = service::new_partial::(&config, true)?; // TODO: review -- we don't need any actual networking @@ -183,13 +190,18 @@ where let subscription_task_executor = sc_rpc::SubscriptionTaskExecutor::new(task_manager.spawn_handle()); + let overrides = rpc::overrides_handle(client.clone()); + let fee_history_limit = 2048; service::rpc::spawn_essential_tasks(service::rpc::SpawnTasksParams { task_manager: &task_manager, client: client.clone(), substrate_backend: backend.clone(), frontier_backend: frontier_backend.clone(), filter_pool: filter_pool.clone(), + overrides: overrides.clone(), + fee_history_limit, + fee_history_cache: fee_history_cache.clone(), }); let command_sink_for_deps = command_sink.clone(); @@ -202,6 +214,8 @@ where let network = network.clone(); let max_past_logs = 1000; let runtime_variant = runtime_variant.clone(); + let fee_history_cache = fee_history_cache.clone(); + let overrides = overrides.clone(); Box::new(move |deny_unsafe, _| { let runtime_variant = runtime_variant.clone(); @@ -219,13 +233,15 @@ where frontier_backend: frontier_backend.clone(), backend: backend.clone(), max_past_logs, + fee_history_limit, + fee_history_cache: fee_history_cache.clone(), transaction_converter: TransactionConverters::for_runtime_variant( runtime_variant, ), xcm_senders: None, }; #[allow(unused_mut)] - let mut io = rpc::create_full(deps, subscription_task_executor.clone()); + let mut io = rpc::create_full(deps, subscription_task_executor.clone(), overrides.clone()); Ok(io) }) }; diff --git a/node/service/src/chain_spec/moonbeam.rs b/node/service/src/chain_spec/moonbeam.rs index 3645de15072..0edf777fc18 100644 --- a/node/service/src/chain_spec/moonbeam.rs +++ b/node/service/src/chain_spec/moonbeam.rs @@ -218,6 +218,7 @@ pub fn testnet_genesis( .collect(), }, ethereum: EthereumConfig {}, + base_fee: Default::default(), democracy: DemocracyConfig::default(), scheduler: SchedulerConfig {}, parachain_staking: ParachainStakingConfig { diff --git a/node/service/src/chain_spec/moonriver.rs b/node/service/src/chain_spec/moonriver.rs index ee665c64a16..dbfb3bc3793 100644 --- a/node/service/src/chain_spec/moonriver.rs +++ b/node/service/src/chain_spec/moonriver.rs @@ -218,6 +218,7 @@ pub fn testnet_genesis( .collect(), }, ethereum: EthereumConfig {}, + base_fee: Default::default(), democracy: DemocracyConfig::default(), scheduler: SchedulerConfig {}, parachain_staking: ParachainStakingConfig { diff --git a/node/service/src/lib.rs b/node/service/src/lib.rs index 800da0548e2..02245df3a30 100644 --- a/node/service/src/lib.rs +++ b/node/service/src/lib.rs @@ -24,7 +24,7 @@ use cli_opt::{EthApi as EthApiCmd, RpcConfig}; use fc_consensus::FrontierBlockImport; -use fc_rpc_core::types::FilterPool; +use fc_rpc_core::types::{FeeHistoryCache, FilterPool}; use futures::StreamExt; #[cfg(feature = "moonbase-native")] pub use moonbase_runtime; @@ -298,6 +298,7 @@ pub fn new_partial( Option, Option, Arc>, + FeeHistoryCache, ), >, ServiceError, @@ -359,6 +360,7 @@ where ); let filter_pool: Option = Some(Arc::new(Mutex::new(BTreeMap::new()))); + let fee_history_cache: FeeHistoryCache = Arc::new(Mutex::new(BTreeMap::new())); let frontier_backend = open_frontier_backend(config)?; @@ -393,6 +395,7 @@ where telemetry, telemetry_worker_handle, frontier_backend, + fee_history_cache, ), }) } @@ -493,8 +496,14 @@ where let parachain_config = prepare_node_config(parachain_config); let params = new_partial(¶chain_config, false)?; - let (block_import, filter_pool, mut telemetry, telemetry_worker_handle, frontier_backend) = - params.other; + let ( + block_import, + filter_pool, + mut telemetry, + telemetry_worker_handle, + frontier_backend, + fee_history_cache, + ) = params.other; let relay_chain_full_node = cumulus_client_service::build_polkadot_full_node(polkadot_config, telemetry_worker_handle) @@ -530,6 +539,8 @@ where let subscription_task_executor = sc_rpc::SubscriptionTaskExecutor::new(task_manager.spawn_handle()); + let overrides = crate::rpc::overrides_handle(client.clone()); + let fee_history_limit = rpc_config.fee_history_limit; rpc::spawn_essential_tasks(rpc::SpawnTasksParams { task_manager: &task_manager, @@ -537,6 +548,9 @@ where substrate_backend: backend.clone(), frontier_backend: frontier_backend.clone(), filter_pool: filter_pool.clone(), + overrides: overrides.clone(), + fee_history_limit, + fee_history_cache: fee_history_cache.clone(), }); let ethapi_cmd = rpc_config.ethapi.clone(); @@ -550,6 +564,9 @@ where substrate_backend: backend.clone(), frontier_backend: frontier_backend.clone(), filter_pool: filter_pool.clone(), + overrides: overrides.clone(), + fee_history_limit, + fee_history_cache: fee_history_cache.clone(), }, ) } else { @@ -568,6 +585,8 @@ where let backend = backend.clone(); let ethapi_cmd = ethapi_cmd.clone(); let max_past_logs = rpc_config.max_past_logs; + let overrides = overrides.clone(); + let fee_history_cache = fee_history_cache.clone(); let is_moonbeam = parachain_config.chain_spec.is_moonbeam(); let is_moonriver = parachain_config.chain_spec.is_moonriver(); @@ -594,12 +613,14 @@ where pool: pool.clone(), is_authority: collator, max_past_logs, + fee_history_limit, + fee_history_cache: fee_history_cache.clone(), network: network.clone(), transaction_converter, xcm_senders: None, }; #[allow(unused_mut)] - let mut io = rpc::create_full(deps, subscription_task_executor.clone()); + let mut io = rpc::create_full(deps, subscription_task_executor.clone(), overrides.clone()); if ethapi_cmd.contains(&EthApiCmd::Debug) || ethapi_cmd.contains(&EthApiCmd::Trace) { rpc::tracing::extend_with_tracing( client.clone(), @@ -754,7 +775,15 @@ where keystore_container, select_chain: maybe_select_chain, transaction_pool, - other: (block_import, filter_pool, telemetry, _telemetry_worker_handle, frontier_backend), + other: + ( + block_import, + filter_pool, + telemetry, + _telemetry_worker_handle, + frontier_backend, + fee_history_cache, + ), } = new_partial::(&config, true)?; let (network, system_rpc_tx, network_starter) = @@ -780,6 +809,8 @@ where let prometheus_registry = config.prometheus_registry().cloned(); let subscription_task_executor = sc_rpc::SubscriptionTaskExecutor::new(task_manager.spawn_handle()); + let overrides = crate::rpc::overrides_handle(client.clone()); + let fee_history_limit = rpc_config.fee_history_limit; let mut command_sink = None; let mut xcm_senders = None; let collator = config.role.is_authority(); @@ -892,6 +923,9 @@ where substrate_backend: backend.clone(), frontier_backend: frontier_backend.clone(), filter_pool: filter_pool.clone(), + overrides: overrides.clone(), + fee_history_limit, + fee_history_cache: fee_history_cache.clone(), }); let ethapi_cmd = rpc_config.ethapi.clone(); let tracing_requesters = @@ -904,6 +938,9 @@ where substrate_backend: backend.clone(), frontier_backend: frontier_backend.clone(), filter_pool: filter_pool.clone(), + overrides: overrides.clone(), + fee_history_limit, + fee_history_cache: fee_history_cache.clone(), }, ) } else { @@ -920,6 +957,8 @@ where let network = network.clone(); let ethapi_cmd = ethapi_cmd.clone(); let max_past_logs = rpc_config.max_past_logs; + let overrides = overrides.clone(); + let fee_history_cache = fee_history_cache.clone(); let is_moonbeam = config.chain_spec.is_moonbeam(); let is_moonriver = config.chain_spec.is_moonriver(); @@ -946,12 +985,14 @@ where pool: pool.clone(), is_authority: collator, max_past_logs, + fee_history_limit, + fee_history_cache: fee_history_cache.clone(), network: network.clone(), transaction_converter, xcm_senders: xcm_senders.clone(), }; #[allow(unused_mut)] - let mut io = rpc::create_full(deps, subscription_task_executor.clone()); + let mut io = rpc::create_full(deps, subscription_task_executor.clone(), overrides.clone()); if ethapi_cmd.contains(&EthApiCmd::Debug) || ethapi_cmd.contains(&EthApiCmd::Trace) { rpc::tracing::extend_with_tracing( client.clone(), diff --git a/node/service/src/rpc.rs b/node/service/src/rpc.rs index 31944955ba2..f2a66365889 100644 --- a/node/service/src/rpc.rs +++ b/node/service/src/rpc.rs @@ -33,7 +33,7 @@ use fc_rpc::{ RuntimeApiStorageOverride, SchemaV1Override, SchemaV2Override, StorageOverride, Web3Api, Web3ApiServer, }; -use fc_rpc_core::types::FilterPool; +use fc_rpc_core::types::{FeeHistoryCache, FilterPool}; use futures::StreamExt; use jsonrpc_pubsub::manager::SubscriptionManager; use manual_xcm_rpc::{ManualXcm, ManualXcmApi}; @@ -90,15 +90,48 @@ pub struct FullDeps { pub command_sink: Option>>, /// Maximum number of logs in a query. pub max_past_logs: u32, + /// Maximum fee history cache size. + pub fee_history_limit: u64, + /// Fee history cache. + pub fee_history_cache: FeeHistoryCache, /// Ethereum transaction to Extrinsic converter. pub transaction_converter: TransactionConverters, /// Channels for manual xcm messages (downward, hrmp) pub xcm_senders: Option<(flume::Sender>, flume::Sender<(ParaId, Vec)>)>, } + +pub fn overrides_handle(client: Arc) -> Arc> +where + C: ProvideRuntimeApi + StorageProvider + AuxStore, + C: HeaderBackend + HeaderMetadata, + C: Send + Sync + 'static, + C::Api: fp_rpc::EthereumRuntimeRPCApi, + BE: Backend + 'static, + BE::State: StateBackend, +{ + let mut overrides_map = BTreeMap::new(); + overrides_map.insert( + EthereumStorageSchema::V1, + Box::new(SchemaV1Override::new(client.clone())) + as Box + Send + Sync>, + ); + overrides_map.insert( + EthereumStorageSchema::V2, + Box::new(SchemaV2Override::new(client.clone())) + as Box + Send + Sync>, + ); + + Arc::new(OverrideHandle { + schemas: overrides_map, + fallback: Box::new(RuntimeApiStorageOverride::new(client.clone())), + }) +} + /// Instantiate all Full RPC extensions. pub fn create_full( deps: FullDeps, subscription_task_executor: SubscriptionTaskExecutor, + overrides: Arc>, ) -> jsonrpc_core::IoHandler where BE: Backend + 'static, @@ -127,6 +160,8 @@ where frontier_backend, backend: _, max_past_logs, + fee_history_limit, + fee_history_cache, transaction_converter, xcm_senders, } = deps; @@ -147,23 +182,6 @@ where eth_log_block_cache, )); - let mut overrides_map = BTreeMap::new(); - overrides_map.insert( - EthereumStorageSchema::V1, - Box::new(SchemaV1Override::new(client.clone())) - as Box + Send + Sync>, - ); - overrides_map.insert( - EthereumStorageSchema::V2, - Box::new(SchemaV2Override::new(client.clone())) - as Box + Send + Sync>, - ); - - let overrides = Arc::new(OverrideHandle { - schemas: overrides_map, - fallback: Box::new(RuntimeApiStorageOverride::new(client.clone())), - }); - io.extend_with(EthApiServer::to_delegate(EthApi::new( client.clone(), pool.clone(), @@ -177,6 +195,8 @@ where max_past_logs, block_data_cache.clone(), fc_rpc::format::Geth, + fee_history_limit, + fee_history_cache, ))); if let Some(filter_pool) = filter_pool { @@ -238,6 +258,9 @@ pub struct SpawnTasksParams<'a, B: BlockT, C, BE> { pub substrate_backend: Arc, pub frontier_backend: Arc>, pub filter_pool: Option, + pub overrides: Arc>, + pub fee_history_limit: u64, + pub fee_history_cache: FeeHistoryCache, } /// Spawn the tasks that are required to run Moonbeam. @@ -294,4 +317,16 @@ where Arc::clone(¶ms.frontier_backend), ), ); + + // Spawn Frontier FeeHistory cache maintenance task. + params.task_manager.spawn_essential_handle().spawn( + "frontier-fee-history", + Some("frontier"), + EthTask::fee_history_task( + Arc::clone(¶ms.client), + Arc::clone(¶ms.overrides), + params.fee_history_cache, + params.fee_history_limit, + ), + ); } diff --git a/runtime/common/src/apis.rs b/runtime/common/src/apis.rs index 1030c96fbaf..3999c85fe31 100644 --- a/runtime/common/src/apis.rs +++ b/runtime/common/src/apis.rs @@ -316,6 +316,10 @@ macro_rules! impl_runtime_apis_plus_common { _ => None }).collect::>() } + + fn elasticity() -> Option { + Some(BaseFee::elasticity()) + } } impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi diff --git a/runtime/moonbase/src/lib.rs b/runtime/moonbase/src/lib.rs index 319c974faf6..b462a76ab10 100644 --- a/runtime/moonbase/src/lib.rs +++ b/runtime/moonbase/src/lib.rs @@ -1611,6 +1611,10 @@ impl pallet_proxy_genesis_companion::Config for Runtime { type ProxyType = ProxyType; } +parameter_types! { + pub IsActive: bool = true; +} + pub struct BaseFeeThreshold; impl pallet_base_fee::BaseFeeThreshold for BaseFeeThreshold { fn lower() -> Permill { @@ -1627,6 +1631,7 @@ impl pallet_base_fee::BaseFeeThreshold for BaseFeeThreshold { impl pallet_base_fee::Config for Runtime { type Event = Event; type Threshold = BaseFeeThreshold; + type IsActive = IsActive; } construct_runtime! { diff --git a/runtime/moonbeam/Cargo.toml b/runtime/moonbeam/Cargo.toml index 887b5f14b94..72434602659 100644 --- a/runtime/moonbeam/Cargo.toml +++ b/runtime/moonbeam/Cargo.toml @@ -75,6 +75,7 @@ sp-version = { git = "https://github.com/purestake/substrate", branch = "moonbea fp-evm = { git = "https://github.com/purestake/frontier", branch = "moonbeam-polkadot-v0.9.13", default-features = false } fp-rpc = { git = "https://github.com/purestake/frontier", branch = "moonbeam-polkadot-v0.9.13", default-features = false } fp-self-contained = { git = "https://github.com/purestake/frontier", branch = "moonbeam-polkadot-v0.9.13", default-features = false } +pallet-base-fee = { git = "https://github.com/purestake/frontier", branch = "moonbeam-polkadot-v0.9.13", default-features = false } pallet-ethereum = { git = "https://github.com/purestake/frontier", branch = "moonbeam-polkadot-v0.9.13", default-features = false } pallet-evm = { git = "https://github.com/purestake/frontier", branch = "moonbeam-polkadot-v0.9.13", default-features = false } pallet-evm-precompile-blake2 = { git = "https://github.com/purestake/frontier", branch = "moonbeam-polkadot-v0.9.13", default-features = false } @@ -133,6 +134,7 @@ std = [ "pallet-author-mapping/std", "pallet-author-slot-filter/std", "pallet-balances/std", + "pallet-base-fee/std", "pallet-collective/std", "pallet-crowdloan-rewards/std", "pallet-democracy/std", diff --git a/runtime/moonbeam/src/lib.rs b/runtime/moonbeam/src/lib.rs index bc28f0d3591..50aa013bc5e 100644 --- a/runtime/moonbeam/src/lib.rs +++ b/runtime/moonbeam/src/lib.rs @@ -398,6 +398,29 @@ impl pallet_evm::Config for Runtime { type FindAuthor = FindAuthorAdapter; } +parameter_types! { + pub IsActive: bool = false; +} + +pub struct BaseFeeThreshold; +impl pallet_base_fee::BaseFeeThreshold for BaseFeeThreshold { + fn lower() -> Permill { + Permill::zero() + } + fn ideal() -> Permill { + Permill::from_parts(500_000) + } + fn upper() -> Permill { + Permill::from_parts(1_000_000) + } +} + +impl pallet_base_fee::Config for Runtime { + type Event = Event; + type Threshold = BaseFeeThreshold; + type IsActive = IsActive; +} + parameter_types! { pub MaximumSchedulerWeight: Weight = NORMAL_DISPATCH_RATIO * BlockWeights::get().max_block; pub const MaxScheduledPerBlock: u32 = 50; @@ -956,6 +979,7 @@ construct_runtime! { EthereumChainId: pallet_ethereum_chain_id::{Pallet, Storage, Config} = 50, EVM: pallet_evm::{Pallet, Config, Call, Storage, Event} = 51, Ethereum: pallet_ethereum::{Pallet, Call, Storage, Event, Origin, Config} = 52, + BaseFee: pallet_base_fee::{Pallet, Call, Storage, Config, Event} = 53, // Governance stuff. Scheduler: pallet_scheduler::{Pallet, Storage, Config, Event, Call} = 60, diff --git a/runtime/moonriver/Cargo.toml b/runtime/moonriver/Cargo.toml index 98280f2309d..507108db349 100644 --- a/runtime/moonriver/Cargo.toml +++ b/runtime/moonriver/Cargo.toml @@ -86,6 +86,7 @@ sp-version = { git = "https://github.com/purestake/substrate", branch = "moonbea fp-evm = { git = "https://github.com/purestake/frontier", branch = "moonbeam-polkadot-v0.9.13", default-features = false } fp-rpc = { git = "https://github.com/purestake/frontier", branch = "moonbeam-polkadot-v0.9.13", default-features = false } fp-self-contained = { git = "https://github.com/purestake/frontier", branch = "moonbeam-polkadot-v0.9.13", default-features = false } +pallet-base-fee = { git = "https://github.com/purestake/frontier", branch = "moonbeam-polkadot-v0.9.13", default-features = false } pallet-ethereum = { git = "https://github.com/purestake/frontier", branch = "moonbeam-polkadot-v0.9.13", default-features = false } pallet-evm = { git = "https://github.com/purestake/frontier", branch = "moonbeam-polkadot-v0.9.13", default-features = false } pallet-evm-precompile-blake2 = { git = "https://github.com/purestake/frontier", branch = "moonbeam-polkadot-v0.9.13", default-features = false } @@ -167,6 +168,7 @@ std = [ "pallet-author-mapping/std", "pallet-author-slot-filter/std", "pallet-balances/std", + "pallet-base-fee/std", "pallet-collective/std", "pallet-crowdloan-rewards/std", "pallet-democracy/std", diff --git a/runtime/moonriver/src/lib.rs b/runtime/moonriver/src/lib.rs index 59de2d6f26c..4969a904882 100644 --- a/runtime/moonriver/src/lib.rs +++ b/runtime/moonriver/src/lib.rs @@ -660,6 +660,29 @@ impl pallet_ethereum::Config for Runtime { type StateRoot = pallet_ethereum::IntermediateStateRoot; } +parameter_types! { + pub IsActive: bool = false; +} + +pub struct BaseFeeThreshold; +impl pallet_base_fee::BaseFeeThreshold for BaseFeeThreshold { + fn lower() -> Permill { + Permill::zero() + } + fn ideal() -> Permill { + Permill::from_parts(500_000) + } + fn upper() -> Permill { + Permill::from_parts(1_000_000) + } +} + +impl pallet_base_fee::Config for Runtime { + type Event = Event; + type Threshold = BaseFeeThreshold; + type IsActive = IsActive; +} + parameter_types! { pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4; } @@ -1572,6 +1595,7 @@ construct_runtime! { EthereumChainId: pallet_ethereum_chain_id::{Pallet, Storage, Config} = 50, EVM: pallet_evm::{Pallet, Config, Call, Storage, Event} = 51, Ethereum: pallet_ethereum::{Pallet, Call, Storage, Event, Origin, Config} = 52, + BaseFee: pallet_base_fee::{Pallet, Call, Storage, Config, Event} = 53, // Governance stuff. Scheduler: pallet_scheduler::{Pallet, Storage, Config, Event, Call} = 60, diff --git a/tests/tests/test-fee-history.ts b/tests/tests/test-fee-history.ts new file mode 100644 index 00000000000..f6d6e7cc544 --- /dev/null +++ b/tests/tests/test-fee-history.ts @@ -0,0 +1,100 @@ +import { ethers } from "ethers"; +import { expect } from "chai"; + +import { ALITH, GENESIS_ACCOUNT, GENESIS_ACCOUNT_PRIVATE_KEY } from "../util/constants"; +import { customWeb3Request } from "../util/providers"; +import { getCompiled } from "../util/contracts"; +import { describeDevMoonbeamAllEthTxTypes } from "../util/setup-dev-tests"; + +// We use ethers library in this test as apparently web3js's types are not fully EIP-1559 +// compliant yet. +describeDevMoonbeamAllEthTxTypes("Fee History", (context) => { + async function sendTransaction(context, payload: any) { + let signer = new ethers.Wallet(GENESIS_ACCOUNT_PRIVATE_KEY, context.ethers); + // Ethers internally matches the locally calculated transaction hash against the one + // returned as a response. + // Test would fail in case of mismatch. + const tx = await signer.sendTransaction(payload); + return tx; + } + + function get_percentile(percentile, array) { + array.sort(function (a, b) { + return a - b; + }); + let index = (percentile / 100) * array.length - 1; + if (Math.floor(index) == index) { + return array[index]; + } else { + return Math.ceil((array[Math.floor(index)] + array[Math.ceil(index)]) / 2); + } + } + + async function createBlocks(block_count, reward_percentiles, priority_fees) { + const contractData = await getCompiled("TestContract"); + let nonce = await context.web3.eth.getTransactionCount(GENESIS_ACCOUNT); + for (var b = 0; b < block_count; b++) { + for (var p = 0; p < priority_fees.length; p++) { + await sendTransaction(context, { + from: GENESIS_ACCOUNT, + data: contractData.byteCode, + value: "0x00", + maxFeePerGas: "0x3B9ACA00", + maxPriorityFeePerGas: context.web3.utils.numberToHex(priority_fees[p]), + accessList: [], + nonce: nonce, + gasLimit: "0x100000", + chainId: 1281, + }); + nonce++; + } + await context.createBlock(); + } + } + + it("result length should match spec", async function () { + this.timeout(100000); + let block_count = 2; + let reward_percentiles = [20, 50, 70]; + let priority_fees = [1, 2, 3]; + await createBlocks(block_count, reward_percentiles, priority_fees); + let result = ( + await customWeb3Request(context.web3, "eth_feeHistory", ["0x2", "latest", reward_percentiles]) + ).result; + + // baseFeePerGas is always the requested block range + 1 (the next derived base fee). + expect(result.baseFeePerGas.length).to.be.eq(block_count + 1); + // gasUsedRatio for the requested block range. + expect(result.gasUsedRatio.length).to.be.eq(block_count); + // two-dimensional reward list for the requested block range. + expect(result.reward.length).to.be.eq(block_count); + // each block has a reward list which's size is the requested percentile list. + for (let i = 0; i < block_count; i++) { + expect(result.reward[i].length).to.be.eq(reward_percentiles.length); + } + }); + + it("should calculate percentiles", async function () { + this.timeout(100000); + let block_count = 11; + let reward_percentiles = [20, 50, 70, 85, 100]; + let priority_fees = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + await createBlocks(block_count, reward_percentiles, priority_fees); + let result = ( + await customWeb3Request(context.web3, "eth_feeHistory", ["0xA", "latest", reward_percentiles]) + ).result; + + // Calculate the percentiles in javascript. + let local_rewards = []; + for (let i = 0; i < reward_percentiles.length; i++) { + local_rewards.push(get_percentile(reward_percentiles[i], priority_fees)); + } + // Compare the rpc result with the javascript percentiles. + for (let i = 0; i < result.reward.length; i++) { + expect(result.reward[i].length).to.be.eq(local_rewards.length); + for (let j = 0; j < local_rewards.length; j++) { + expect(context.web3.utils.hexToNumber(result.reward[i][j])).to.be.eq(local_rewards[j]); + } + } + }); +});