--- a/Cargo.lock +++ b/Cargo.lock @@ -5362,6 +5362,7 @@ "substrate-wasm-builder", "up-common", "up-data-structs", + "up-pov-estimate-rpc", "up-rpc", "up-sponsorship", "xcm", @@ -5806,6 +5807,7 @@ "sp-runtime", "sp-std", "up-data-structs", + "up-pov-estimate-rpc", ] [[package]] @@ -8917,6 +8919,7 @@ "substrate-wasm-builder", "up-common", "up-data-structs", + "up-pov-estimate-rpc", "up-rpc", "up-sponsorship", "xcm", @@ -12824,18 +12827,31 @@ dependencies = [ "anyhow", "app-promotion-rpc", + "frame-benchmarking", "jsonrpsee", + "opal-runtime", "pallet-common", "pallet-evm", "parity-scale-codec 3.2.1", + "quartz-runtime", "rmrk-rpc", + "sc-client-api", + "sc-executor", + "sc-rpc-api", + "sc-service", "sp-api", "sp-blockchain", "sp-core", + "sp-externalities", "sp-rpc", "sp-runtime", + "sp-state-machine", + "unique-runtime", + "up-common", "up-data-structs", + "up-pov-estimate-rpc", "up-rpc", + "zstd", ] [[package]] @@ -12978,10 +12994,12 @@ "substrate-prometheus-endpoint", "tokio", "try-runtime-cli", + "uc-rpc", "unique-rpc", "unique-runtime", "up-common", "up-data-structs", + "up-pov-estimate-rpc", "up-rpc", ] @@ -13032,6 +13050,7 @@ "uc-rpc", "up-common", "up-data-structs", + "up-pov-estimate-rpc", "up-rpc", ] @@ -13125,6 +13144,7 @@ "substrate-wasm-builder", "up-common", "up-data-structs", + "up-pov-estimate-rpc", "up-rpc", "up-sponsorship", "xcm", @@ -13194,6 +13214,19 @@ ] [[package]] +name = "up-pov-estimate-rpc" +version = "0.1.0" +dependencies = [ + "parity-scale-codec 3.2.1", + "scale-info", + "serde", + "sp-api", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] name = "up-rpc" version = "0.1.3" dependencies = [ --- a/client/rpc/Cargo.toml +++ b/client/rpc/Cargo.toml @@ -7,16 +7,40 @@ [dependencies] pallet-common = { default-features = false, path = '../../pallets/common' } up-data-structs = { default-features = false, path = '../../primitives/data-structs' } +up-common = { default-features = false, path = '../../primitives/common' } up-rpc = { path = "../../primitives/rpc" } app-promotion-rpc = { path = "../../primitives/app_promotion_rpc" } rmrk-rpc = { path = "../../primitives/rmrk-rpc" } +up-pov-estimate-rpc = { path = "../../primitives/pov-estimate-rpc", optional = true } codec = { package = "parity-scale-codec", version = "3.1.2" } jsonrpsee = { version = "0.16.2", features = ["server", "macros"] } anyhow = "1.0.57" +zstd = { version = "0.11.2", default-features = false } +sc-rpc-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-service = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-externalities = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } sp-blockchain = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } sp-rpc = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.36" } + +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } + +sc-executor = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } + +unique-runtime = { path = '../../runtime/unique', optional = true } +quartz-runtime = { path = '../../runtime/quartz', optional = true } +opal-runtime = { path = '../../runtime/opal' } + +[features] +pov-estimate = [ + 'up-pov-estimate-rpc', + 'unique-runtime?/pov-estimate', + 'quartz-runtime?/pov-estimate', + 'opal-runtime/pov-estimate', +] --- a/client/rpc/src/lib.rs +++ b/client/rpc/src/lib.rs @@ -42,6 +42,9 @@ pub use app_promotion_unique_rpc::AppPromotionApiServer; pub use rmrk_unique_rpc::RmrkApiServer; +#[cfg(feature = "pov-estimate")] +pub mod pov_estimate; + #[rpc(server)] #[async_trait] pub trait UniqueApi { @@ -420,17 +423,18 @@ } } +#[macro_export] macro_rules! define_struct_for_server_api { - ($name:ident) => { - pub struct $name { - client: Arc, - _marker: std::marker::PhantomData

, + ($name:ident { $($arg:ident: $arg_ty:ty),+ $(,)? }) => { + pub struct $name { + $($arg: $arg_ty),+, + _marker: std::marker::PhantomData, } - impl $name { - pub fn new(client: Arc) -> Self { + impl $name { + pub fn new($($arg: $arg_ty),+) -> Self { Self { - client, + $($arg),+, _marker: Default::default(), } } @@ -438,9 +442,23 @@ }; } -define_struct_for_server_api!(Unique); -define_struct_for_server_api!(AppPromotion); -define_struct_for_server_api!(Rmrk); +define_struct_for_server_api! { + Unique { + client: Arc + } +} + +define_struct_for_server_api! { + AppPromotion { + client: Arc + } +} + +define_struct_for_server_api! { + Rmrk { + client: Arc + } +} macro_rules! pass_method { ( --- /dev/null +++ b/client/rpc/src/pov_estimate.rs @@ -0,0 +1,205 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network 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. + +// Unique Network 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 Unique Network. If not, see . + +use std::sync::Arc; + +use codec::Encode; + +use up_pov_estimate_rpc::{PovEstimateApi as PovEstimateRuntimeApi}; +use up_common::types::opaque::RuntimeId; + +use sc_service::{NativeExecutionDispatch, config::ExecutionStrategy}; +use sp_state_machine::{StateMachine, TrieBackendBuilder}; + +use jsonrpsee::{ + core::RpcResult as Result, + proc_macros::rpc, +}; +use anyhow::anyhow; + +use sc_client_api::backend::Backend; +use sp_blockchain::HeaderBackend; +use sp_api::{AsTrieBackend, BlockId, BlockT, ProvideRuntimeApi}; + +use sc_executor::NativeElseWasmExecutor; +use sc_rpc_api::DenyUnsafe; + +use sp_runtime::traits::Header; + +use up_pov_estimate_rpc::PovInfo; + +use crate::define_struct_for_server_api; + +type HasherOf = <::Header as Header>::Hashing; +type StateOf = as Backend>::State; + +pub struct ExecutorParams { + pub wasm_method: sc_service::config::WasmExecutionMethod, + pub default_heap_pages: Option, + pub max_runtime_instances: usize, + pub runtime_cache_size: u8, +} + +#[cfg(feature = "unique-runtime")] +pub struct UniqueRuntimeExecutor; + +#[cfg(feature = "quartz-runtime")] +pub struct QuartzRuntimeExecutor; + +pub struct OpalRuntimeExecutor; + +#[cfg(feature = "unique-runtime")] +impl NativeExecutionDispatch for UniqueRuntimeExecutor { + type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; + + fn dispatch(method: &str, data: &[u8]) -> Option> { + unique_runtime::api::dispatch(method, data) + } + + fn native_version() -> sc_executor::NativeVersion { + unique_runtime::native_version() + } +} + +#[cfg(feature = "quartz-runtime")] +impl NativeExecutionDispatch for QuartzRuntimeExecutor { + type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; + + fn dispatch(method: &str, data: &[u8]) -> Option> { + quartz_runtime::api::dispatch(method, data) + } + + fn native_version() -> sc_executor::NativeVersion { + quartz_runtime::native_version() + } +} + +impl NativeExecutionDispatch for OpalRuntimeExecutor { + type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; + + fn dispatch(method: &str, data: &[u8]) -> Option> { + opal_runtime::api::dispatch(method, data) + } + + fn native_version() -> sc_executor::NativeVersion { + opal_runtime::native_version() + } +} + +#[cfg(feature = "pov-estimate")] +define_struct_for_server_api! { + PovEstimate { + client: Arc, + backend: Arc>, + deny_unsafe: DenyUnsafe, + exec_params: ExecutorParams, + runtime_id: RuntimeId, + } +} + +#[rpc(server)] +#[async_trait] +pub trait PovEstimateApi { + #[method(name = "unique_povEstimate")] + fn pov_estimate(&self, encoded_xt: Vec, at: Option) -> Result; +} + +#[allow(deprecated)] +#[cfg(feature = "pov-estimate")] +impl + PovEstimateApiServer<::Hash> for PovEstimate +where + Block: BlockT, + C: 'static + ProvideRuntimeApi + HeaderBackend, + C::Api: PovEstimateRuntimeApi, +{ + fn pov_estimate(&self, encoded_xt: Vec, at: Option<::Hash>,) -> Result { + self.deny_unsafe.check_if_safe()?; + + let at = BlockId::::hash(at.unwrap_or_else(|| self.client.info().best_hash)); + let state = self.backend.state_at(at).map_err(|_| anyhow!("unable to fetch the state at {at:?}"))?; + match &self.runtime_id { + #[cfg(feature = "unique-runtime")] + RuntimeId::Unique => execute_extrinsic_in_sandbox::(state, &self.exec_params, encoded_xt), + + #[cfg(feature = "quartz-runtime")] + RuntimeId::Quartz => execute_extrinsic_in_sandbox::(state, &self.exec_params, encoded_xt), + + RuntimeId::Opal => execute_extrinsic_in_sandbox::(state, &self.exec_params, encoded_xt), + + runtime_id => Err(anyhow!("unknown runtime id {:?}", runtime_id).into()), + } + } +} + +fn execute_extrinsic_in_sandbox(state: StateOf, exec_params: &ExecutorParams, encoded_xt: Vec) -> Result +where + Block: BlockT, + D: NativeExecutionDispatch + 'static, +{ + let backend = state.as_trie_backend().clone(); + let mut changes = Default::default(); + let runtime_code_backend = sp_state_machine::backend::BackendRuntimeCode::new(backend); + + let proving_backend = + TrieBackendBuilder::wrap(&backend).with_recorder(Default::default()).build(); + + let runtime_code = runtime_code_backend.runtime_code() + .map_err(|_| anyhow!("runtime code backend creation failed"))?; + + let pre_root = *backend.root(); + + let executor = NativeElseWasmExecutor::::new( + exec_params.wasm_method, + exec_params.default_heap_pages, + exec_params.max_runtime_instances, + exec_params.runtime_cache_size, + ); + let execution = ExecutionStrategy::NativeElseWasm; + + StateMachine::new( + &proving_backend, + &mut changes, + &executor, + "PovEstimateApi_pov_estimate", + encoded_xt.as_slice(), + sp_externalities::Extensions::default(), + &runtime_code, + sp_core::testing::TaskExecutor::new(), + ) + .execute(execution.into()) + .map_err(|e| anyhow!("failed to execute the extrinsic {:?}", e))?; + + let proof = proving_backend + .extract_proof() + .expect("A recorder was set and thus, a storage proof can be extracted; qed"); + let proof_size = proof.encoded_size(); + let compact_proof = proof + .clone() + .into_compact_proof::>(pre_root) + .map_err(|e| anyhow!("failed to generate compact proof {:?}", e))?; + let compact_proof_size = compact_proof.encoded_size(); + + let compressed_proof = zstd::stream::encode_all(&compact_proof.encode()[..], 0) + .map_err(|e| anyhow!("failed to generate compact proof {:?}", e))?; + let compressed_proof_size = compressed_proof.len(); + + Ok(PovInfo { + proof_size: proof_size as u64, + compact_proof_size: compact_proof_size as u64, + compressed_proof_size: compressed_proof_size as u64, + }) +} --- a/node/cli/Cargo.toml +++ b/node/cli/Cargo.toml @@ -319,8 +319,10 @@ pallet-ethereum = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.36" } unique-rpc = { default-features = false, path = "../rpc" } +uc-rpc = { default-features = false, path = "../../client/rpc" } app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false } rmrk-rpc = { path = "../../primitives/rmrk-rpc" } +up-pov-estimate-rpc = { path = "../../primitives/pov-estimate-rpc", default-features = false } [features] default = ["opal-runtime"] @@ -339,3 +341,10 @@ 'try-runtime-cli/try-runtime', ] sapphire-runtime = ['opal-runtime', 'opal-runtime/become-sapphire'] +pov-estimate = [ + 'unique-runtime?/pov-estimate', + 'quartz-runtime?/pov-estimate', + 'opal-runtime/pov-estimate', + 'uc-rpc/pov-estimate', + 'unique-rpc/pov-estimate', +] --- a/node/cli/src/chain_spec.rs +++ b/node/cli/src/chain_spec.rs @@ -54,17 +54,6 @@ #[cfg(all(not(feature = "unique-runtime"), not(feature = "quartz-runtime")))] pub type DefaultChainSpec = OpalChainSpec; -pub enum RuntimeId { - #[cfg(feature = "unique-runtime")] - Unique, - - #[cfg(feature = "quartz-runtime")] - Quartz, - - Opal, - Unknown(String), -} - #[cfg(not(feature = "unique-runtime"))] /// PARA_ID for Opal/Sapphire/Quartz const PARA_ID: u32 = 2095; --- a/node/cli/src/command.rs +++ b/node/cli/src/command.rs @@ -33,7 +33,7 @@ // limitations under the License. use crate::{ - chain_spec::{self, RuntimeId, RuntimeIdentification, ServiceId, ServiceIdentification}, + chain_spec::{self, RuntimeIdentification, ServiceId, ServiceIdentification}, cli::{Cli, RelayChainCli, Subcommand}, service::{new_partial, start_node, start_dev_node}, }; @@ -66,13 +66,13 @@ use sp_runtime::traits::{AccountIdConversion, Block as BlockT}; use std::{net::SocketAddr, time::Duration}; -use up_common::types::opaque::Block; +use up_common::types::opaque::{Block, RuntimeId}; macro_rules! no_runtime_err { - ($chain_name:expr) => { + ($runtime_id:expr) => { format!( - "No runtime valid runtime was found for chain {}", - $chain_name + "No runtime valid runtime was found for chain {:#?}", + $runtime_id ) }; } @@ -94,7 +94,7 @@ RuntimeId::Quartz => Box::new(chain_spec::QuartzChainSpec::from_json_file(path)?), RuntimeId::Opal => chain_spec, - RuntimeId::Unknown(chain) => return Err(no_runtime_err!(chain)), + runtime_id => return Err(no_runtime_err!(runtime_id)), } } }) @@ -147,7 +147,7 @@ RuntimeId::Quartz => &quartz_runtime::VERSION, RuntimeId::Opal => &opal_runtime::VERSION, - RuntimeId::Unknown(chain) => panic!("{}", no_runtime_err!(chain)), + runtime_id => panic!("{}", no_runtime_err!(runtime_id)), } } } @@ -235,7 +235,7 @@ runner, $components, $cli, $cmd, $config, $( $code )* ), - RuntimeId::Unknown(chain) => Err(no_runtime_err!(chain).into()) + runtime_id => Err(no_runtime_err!(runtime_id).into()) } }} } @@ -274,7 +274,7 @@ runner, $components, $cli, $cmd, $config, $( $code )* ), - RuntimeId::Unknown(chain) => Err(no_runtime_err!(chain).into()) + runtime_id => Err(no_runtime_err!(runtime_id).into()) } }} } @@ -302,7 +302,7 @@ OpalRuntimeExecutor, >($config $(, $($args),+)?) $($code)*, - RuntimeId::Unknown(chain) => Err(no_runtime_err!(chain).into()), + runtime_id => Err(no_runtime_err!(runtime_id).into()), } }; } @@ -445,7 +445,7 @@ sp_io::SubstrateHostFunctions, ::ExtendHostFunctions, >>()), - RuntimeId::Unknown(chain) => return Err(no_runtime_err!(chain).into()), + runtime_id => return Err(no_runtime_err!(runtime_id).into()), }, task_manager, )) --- a/node/cli/src/service.rs +++ b/node/cli/src/service.rs @@ -66,9 +66,8 @@ use fc_rpc_core::types::FilterPool; use fc_mapping_sync::{MappingSyncWorker, SyncStrategy}; -use up_common::types::opaque::{ - AuraId, RuntimeInstance, AccountId, Balance, Index, Hash, Block, BlockNumber, -}; +use up_common::types::opaque::*; +use crate::chain_spec::RuntimeIdentification; // RMRK use up_data_structs::{ @@ -412,7 +411,8 @@ RmrkBaseInfo, RmrkPartType, RmrkTheme, - > + substrate_frame_rpc_system::AccountNonceApi + > + up_pov_estimate_rpc::PovEstimateApi + + substrate_frame_rpc_system::AccountNonceApi + sp_api::Metadata + sp_offchain::OffchainWorkerApi + cumulus_primitives_core::CollectCollationInfo, @@ -517,9 +517,25 @@ .for_each(|()| futures::future::ready(())), ); + let rpc_backend = backend.clone(); + let runtime_id = parachain_config.chain_spec.runtime_id(); let rpc_builder = Box::new(move |deny_unsafe, subscription_task_executor| { let full_deps = unique_rpc::FullDeps { - backend: rpc_frontier_backend.clone(), + #[cfg(feature = "pov-estimate")] + runtime_id: runtime_id.clone(), + + #[cfg(feature = "pov-estimate")] + exec_params: uc_rpc::pov_estimate::ExecutorParams { + wasm_method: parachain_config.wasm_method, + default_heap_pages: parachain_config.default_heap_pages, + max_runtime_instances: parachain_config.max_runtime_instances, + runtime_cache_size: parachain_config.runtime_cache_size, + }, + + #[cfg(feature = "pov-estimate")] + backend: rpc_backend.clone(), + + eth_backend: rpc_frontier_backend.clone(), deny_unsafe, client: rpc_client.clone(), pool: rpc_pool.clone(), @@ -720,7 +736,8 @@ RmrkBaseInfo, RmrkPartType, RmrkTheme, - > + substrate_frame_rpc_system::AccountNonceApi + > + up_pov_estimate_rpc::PovEstimateApi + + substrate_frame_rpc_system::AccountNonceApi + sp_api::Metadata + sp_offchain::OffchainWorkerApi + cumulus_primitives_core::CollectCollationInfo @@ -869,7 +886,8 @@ RmrkBaseInfo, RmrkPartType, RmrkTheme, - > + substrate_frame_rpc_system::AccountNonceApi + > + up_pov_estimate_rpc::PovEstimateApi + + substrate_frame_rpc_system::AccountNonceApi + sp_api::Metadata + sp_offchain::OffchainWorkerApi + cumulus_primitives_core::CollectCollationInfo @@ -1040,9 +1058,24 @@ let rpc_pool = transaction_pool.clone(); let rpc_network = network.clone(); let rpc_frontier_backend = frontier_backend.clone(); + let rpc_backend = backend.clone(); + let runtime_id = config.chain_spec.runtime_id(); let rpc_builder = Box::new(move |deny_unsafe, subscription_executor| { let full_deps = unique_rpc::FullDeps { - backend: rpc_frontier_backend.clone(), + #[cfg(feature = "pov-estimate")] + runtime_id: runtime_id.clone(), + + #[cfg(feature = "pov-estimate")] + exec_params: uc_rpc::pov_estimate::ExecutorParams { + wasm_method: config.wasm_method, + default_heap_pages: config.default_heap_pages, + max_runtime_instances: config.max_runtime_instances, + runtime_cache_size: config.runtime_cache_size, + }, + + #[cfg(feature = "pov-estimate")] + backend: rpc_backend.clone(), + eth_backend: rpc_frontier_backend.clone(), deny_unsafe, client: rpc_client.clone(), pool: rpc_pool.clone(), --- a/node/rpc/Cargo.toml +++ b/node/rpc/Cargo.toml @@ -55,6 +55,7 @@ up-rpc = { path = "../../primitives/rpc" } app-promotion-rpc = { path = "../../primitives/app_promotion_rpc" } rmrk-rpc = { path = "../../primitives/rmrk-rpc" } +up-pov-estimate-rpc = { path = "../../primitives/pov-estimate-rpc" } up-data-structs = { default-features = false, path = "../../primitives/data-structs" } [dependencies.serde] @@ -65,3 +66,4 @@ default = [] std = [] unique-runtime = [] +pov-estimate = ['uc-rpc/pov-estimate'] --- a/node/rpc/src/lib.rs +++ b/node/rpc/src/lib.rs @@ -40,7 +40,7 @@ use sc_service::TransactionPool; use std::{collections::BTreeMap, sync::Arc}; -use up_common::types::opaque::{Hash, AccountId, RuntimeInstance, Index, Block, BlockNumber, Balance}; +use up_common::types::opaque::*; // RMRK use up_data_structs::{ @@ -48,6 +48,8 @@ RmrkPartType, RmrkTheme, }; +type FullBackend = sc_service::TFullBackend; + /// Extra dependencies for GRANDPA pub struct GrandpaDeps { /// Voting round info. @@ -82,8 +84,18 @@ pub deny_unsafe: DenyUnsafe, /// EthFilterApi pool. pub filter_pool: Option, - /// Backend. - pub backend: Arc>, + + #[cfg(feature = "pov-estimate")] + pub runtime_id: RuntimeId, + /// Executor params for PoV estimating + #[cfg(feature = "pov-estimate")] + pub exec_params: uc_rpc::pov_estimate::ExecutorParams, + /// Substrate Backend. + #[cfg(feature = "pov-estimate")] + pub backend: Arc, + + /// Ethereum Backend. + pub eth_backend: Arc>, /// Maximum number of logs in a query. pub max_past_logs: u32, /// Maximum fee history cache size. @@ -162,6 +174,7 @@ RmrkPartType, RmrkTheme, >, + C::Api: up_pov_estimate_rpc::PovEstimateApi, B: sc_client_api::Backend + Send + Sync + 'static, B::State: sc_client_api::backend::StateBackend>, P: TransactionPool + 'static, @@ -182,6 +195,9 @@ #[cfg(not(feature = "unique-runtime"))] use uc_rpc::{RmrkApiServer, Rmrk}; + #[cfg(feature = "pov-estimate")] + use uc_rpc::pov_estimate::{PovEstimateApiServer, PovEstimate}; + // use pallet_contracts_rpc::{Contracts, ContractsApi}; use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer}; use substrate_frame_rpc_system::{System, SystemApiServer}; @@ -200,7 +216,17 @@ network, deny_unsafe, filter_pool, + + #[cfg(feature = "pov-estimate")] + runtime_id, + + #[cfg(feature = "pov-estimate")] + exec_params, + + #[cfg(feature = "pov-estimate")] backend, + + eth_backend, max_past_logs, } = deps; @@ -226,7 +252,7 @@ network.clone(), signers, overrides.clone(), - backend.clone(), + eth_backend.clone(), is_authority, block_data_cache.clone(), fee_history_cache, @@ -244,11 +270,14 @@ #[cfg(not(feature = "unique-runtime"))] io.merge(Rmrk::new(client.clone()).into_rpc())?; + #[cfg(feature = "pov-estimate")] + io.merge(PovEstimate::new(client.clone(), backend, deny_unsafe, exec_params, runtime_id).into_rpc())?; + if let Some(filter_pool) = filter_pool { io.merge( EthFilter::new( client.clone(), - backend, + eth_backend, filter_pool, 500_usize, // max stored filters max_past_logs, --- a/pallets/common/Cargo.toml +++ b/pallets/common/Cargo.toml @@ -23,6 +23,7 @@ evm-coder = { default-features = false, path = '../../crates/evm-coder' } ethereum = { version = "0.14.0", default-features = false } pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.36" } +up-pov-estimate-rpc = { default-features = false, path = "../../primitives/pov-estimate-rpc" } serde = { version = "1.0.130", default-features = false } scale-info = { version = "2.0.1", default-features = false, features = [ @@ -39,6 +40,7 @@ "fp-evm-mapping/std", "up-data-structs/std", "pallet-evm/std", + "up-pov-estimate-rpc/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", --- a/pallets/common/src/lib.rs +++ b/pallets/common/src/lib.rs @@ -115,6 +115,7 @@ RmrkNftChild, CollectionPermissions, }; +use up_pov_estimate_rpc::PovInfo; pub use pallet::*; use sp_core::H160; @@ -881,6 +882,8 @@ RmrkPartType, RmrkBoundedTheme, RmrkNftChild, + // PoV Estimate Info + PovInfo, )>, ), QueryKind = OptionQuery, --- a/primitives/common/src/types.rs +++ b/primitives/common/src/types.rs @@ -29,6 +29,14 @@ pub use super::{BlockNumber, Signature, AccountId, Balance, Index, Hash, AuraId}; + #[derive(Debug, Clone)] + pub enum RuntimeId { + Unique, + Quartz, + Opal, + Unknown(sp_std::vec::Vec), + } + /// Opaque block header type. pub type Header = generic::Header; --- /dev/null +++ b/primitives/pov-estimate-rpc/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "up-pov-estimate-rpc" +version = "0.1.0" +license = "GPLv3" +edition = "2021" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.1.2", default-features = false, features = [ + "derive", +] } +serde = { version = "1.0.130", features = ["derive"], default-features = false, optional = true } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } + +[features] +default = ["std"] +std = [ + "codec/std", + "serde/std", + "scale-info/std", + "sp-core/std", + "sp-std/std", + "sp-api/std", + "sp-runtime/std", +] --- /dev/null +++ b/primitives/pov-estimate-rpc/src/lib.rs @@ -0,0 +1,39 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network 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. + +// Unique Network 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 Unique Network. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; + +#[cfg(feature = "std")] +use serde::Serialize; + +use sp_runtime::ApplyExtrinsicResult; + +#[cfg_attr(feature = "std", derive(Serialize))] +#[derive(Encode, Decode, Debug, TypeInfo, MaxEncodedLen)] +pub struct PovInfo { + pub proof_size: u64, + pub compact_proof_size: u64, + pub compressed_proof_size: u64, +} + +sp_api::decl_runtime_apis! { + pub trait PovEstimateApi { + fn pov_estimate(uxt: Block::Extrinsic) -> ApplyExtrinsicResult; + } +} --- a/runtime/common/runtime_apis.rs +++ b/runtime/common/runtime_apis.rs @@ -39,7 +39,7 @@ use sp_runtime::{ Permill, traits::Block as BlockT, - transaction_validity::{TransactionSource, TransactionValidity}, + transaction_validity::{TransactionSource, TransactionValidity, TransactionValidityError, InvalidTransaction}, ApplyExtrinsicResult, DispatchError, }; use fp_rpc::TransactionStatus; @@ -778,6 +778,17 @@ } } + impl up_pov_estimate_rpc::PovEstimateApi for Runtime { + #[allow(unused_variables)] + fn pov_estimate(uxt: ::Extrinsic) -> ApplyExtrinsicResult { + #[cfg(feature = "pov-estimate")] + return Executive::apply_extrinsic(uxt); + + #[cfg(not(feature = "pov-estimate"))] + return Err(TransactionValidityError::Invalid(InvalidTransaction::Call)) + } + } + #[cfg(feature = "try-runtime")] impl frame_try_runtime::TryRuntime for Runtime { fn on_runtime_upgrade(checks: bool) -> (frame_support::pallet_prelude::Weight, frame_support::pallet_prelude::Weight) { --- a/runtime/opal/Cargo.toml +++ b/runtime/opal/Cargo.toml @@ -127,6 +127,7 @@ 'pallet-base-fee/std', 'fp-rpc/std', 'up-rpc/std', + 'up-pov-estimate-rpc/std', 'app-promotion-rpc/std', 'fp-evm-mapping/std', 'fp-self-contained/std', @@ -184,6 +185,7 @@ 'pallet-test-utils', ] become-sapphire = [] +pov-estimate = [] refungible = [] scheduler = [] @@ -468,6 +470,7 @@ derivative = "2.2.0" pallet-unique = { path = '../../pallets/unique', default-features = false } up-rpc = { path = "../../primitives/rpc", default-features = false } +up-pov-estimate-rpc = { path = "../../primitives/pov-estimate-rpc", default-features = false } app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false } rmrk-rpc = { path = "../../primitives/rmrk-rpc", default-features = false } fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.36" } --- a/runtime/quartz/Cargo.toml +++ b/runtime/quartz/Cargo.toml @@ -122,6 +122,7 @@ 'pallet-base-fee/std', 'fp-rpc/std', 'up-rpc/std', + 'up-pov-estimate-rpc/std', 'app-promotion-rpc/std', 'fp-evm-mapping/std', 'fp-self-contained/std', @@ -169,6 +170,7 @@ ] limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing'] quartz-runtime = ['refungible', 'app-promotion', 'foreign-assets'] +pov-estimate = [] refungible = [] scheduler = [] @@ -461,6 +463,7 @@ derivative = "2.2.0" pallet-unique = { path = '../../pallets/unique', default-features = false } up-rpc = { path = "../../primitives/rpc", default-features = false } +up-pov-estimate-rpc = { path = "../../primitives/pov-estimate-rpc", default-features = false } app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false } fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.36" } fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.36" } --- a/runtime/unique/Cargo.toml +++ b/runtime/unique/Cargo.toml @@ -123,6 +123,7 @@ 'pallet-base-fee/std', 'fp-rpc/std', 'up-rpc/std', + 'up-pov-estimate-rpc/std', 'app-promotion-rpc/std', 'fp-evm-mapping/std', 'fp-self-contained/std', @@ -170,6 +171,7 @@ ] limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing'] unique-runtime = ['foreign-assets'] +pov-estimate = [] stubgen = ["evm-coder/stubgen"] refungible = [] @@ -454,6 +456,7 @@ derivative = "2.2.0" pallet-unique = { path = '../../pallets/unique', default-features = false } up-rpc = { path = "../../primitives/rpc", default-features = false } +up-pov-estimate-rpc = { path = "../../primitives/pov-estimate-rpc", default-features = false } app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false } rmrk-rpc = { path = "../../primitives/rmrk-rpc", default-features = false } pallet-inflation = { path = '../../pallets/inflation', default-features = false }