git.delta.rocks / unique-network / refs/commits / 5b6b6125c041

difftreelog

source

client/rpc/src/pov_estimate.rs6.7 KiBsourcehistory
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617use std::sync::Arc;1819use codec::Encode;2021use up_pov_estimate_rpc::{PovEstimateApi as PovEstimateRuntimeApi};22use up_common::types::opaque::RuntimeId;2324use sc_service::{NativeExecutionDispatch, config::ExecutionStrategy};25use sp_state_machine::{StateMachine, TrieBackendBuilder};2627use jsonrpsee::{28	core::RpcResult as Result,29	proc_macros::rpc,30};31use anyhow::anyhow;3233use sc_client_api::backend::Backend;34use sp_blockchain::HeaderBackend;35use sp_api::{AsTrieBackend, BlockId, BlockT, ProvideRuntimeApi};3637use sc_executor::NativeElseWasmExecutor;38use sc_rpc_api::DenyUnsafe;3940use sp_runtime::traits::Header;4142use up_pov_estimate_rpc::PovInfo;4344use crate::define_struct_for_server_api;4546type HasherOf<Block> = <<Block as BlockT>::Header as Header>::Hashing;47type StateOf<Block> = <sc_service::TFullBackend<Block> as Backend<Block>>::State;4849pub struct ExecutorParams {50	pub wasm_method: sc_service::config::WasmExecutionMethod,51	pub default_heap_pages: Option<u64>,52	pub max_runtime_instances: usize,53	pub runtime_cache_size: u8,54}5556#[cfg(feature = "unique-runtime")]57pub struct UniqueRuntimeExecutor;5859#[cfg(feature = "quartz-runtime")]60pub struct QuartzRuntimeExecutor;6162pub struct OpalRuntimeExecutor;6364#[cfg(feature = "unique-runtime")]65impl NativeExecutionDispatch for UniqueRuntimeExecutor {66	type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;6768	fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {69		unique_runtime::api::dispatch(method, data)70	}7172	fn native_version() -> sc_executor::NativeVersion {73		unique_runtime::native_version()74	}75}7677#[cfg(feature = "quartz-runtime")]78impl NativeExecutionDispatch for QuartzRuntimeExecutor {79	type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;8081	fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {82		quartz_runtime::api::dispatch(method, data)83	}8485	fn native_version() -> sc_executor::NativeVersion {86		quartz_runtime::native_version()87	}88}8990impl NativeExecutionDispatch for OpalRuntimeExecutor {91	type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;9293	fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {94		opal_runtime::api::dispatch(method, data)95	}9697	fn native_version() -> sc_executor::NativeVersion {98		opal_runtime::native_version()99	}100}101102#[cfg(feature = "pov-estimate")]103define_struct_for_server_api! {104	PovEstimate {105		client: Arc<Client>,106		backend: Arc<sc_service::TFullBackend<Block>>,107		deny_unsafe: DenyUnsafe,108		exec_params: ExecutorParams,109		runtime_id: RuntimeId,110	}111}112113#[rpc(server)]114#[async_trait]115pub trait PovEstimateApi<BlockHash> {116    #[method(name = "unique_povEstimate")]117    fn pov_estimate(&self, encoded_xt: Vec<u8>, at: Option<BlockHash>) -> Result<PovInfo>;118}119120#[allow(deprecated)]121#[cfg(feature = "pov-estimate")]122impl<C, Block>123	PovEstimateApiServer<<Block as BlockT>::Hash> for PovEstimate<C, Block>124where125	Block: BlockT,126	C: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,127	C::Api: PovEstimateRuntimeApi<Block>,128{129	fn pov_estimate(&self, encoded_xt: Vec<u8>, at: Option<<Block as BlockT>::Hash>,) -> Result<PovInfo> {130        self.deny_unsafe.check_if_safe()?;131132		let at = BlockId::<Block>::hash(at.unwrap_or_else(|| self.client.info().best_hash));133		let state = self.backend.state_at(at).map_err(|_| anyhow!("unable to fetch the state at {at:?}"))?;134        match &self.runtime_id {135            #[cfg(feature = "unique-runtime")]136            RuntimeId::Unique => execute_extrinsic_in_sandbox::<Block, UniqueRuntimeExecutor>(state, &self.exec_params, encoded_xt),137138            #[cfg(feature = "quartz-runtime")]139            RuntimeId::Quartz => execute_extrinsic_in_sandbox::<Block, QuartzRuntimeExecutor>(state, &self.exec_params, encoded_xt),140141            RuntimeId::Opal => execute_extrinsic_in_sandbox::<Block, OpalRuntimeExecutor>(state, &self.exec_params, encoded_xt),142143            runtime_id => Err(anyhow!("unknown runtime id {:?}", runtime_id).into()),144        }145	}146}147148fn execute_extrinsic_in_sandbox<Block, D>(state: StateOf<Block>, exec_params: &ExecutorParams, encoded_xt: Vec<u8>) -> Result<PovInfo>149where150    Block: BlockT,151    D: NativeExecutionDispatch + 'static,152{153    let backend = state.as_trie_backend().clone();154    let mut changes = Default::default();155    let runtime_code_backend = sp_state_machine::backend::BackendRuntimeCode::new(backend);156157    let proving_backend =158        TrieBackendBuilder::wrap(&backend).with_recorder(Default::default()).build();159160    let runtime_code = runtime_code_backend.runtime_code()161        .map_err(|_| anyhow!("runtime code backend creation failed"))?;162163    let pre_root = *backend.root();164165    let executor = NativeElseWasmExecutor::<D>::new(166        exec_params.wasm_method,167        exec_params.default_heap_pages,168        exec_params.max_runtime_instances,169        exec_params.runtime_cache_size,170    );171    let execution = ExecutionStrategy::NativeElseWasm;172173    StateMachine::new(174        &proving_backend,175        &mut changes,176        &executor,177        "PovEstimateApi_pov_estimate",178        encoded_xt.as_slice(),179        sp_externalities::Extensions::default(),180        &runtime_code,181        sp_core::testing::TaskExecutor::new(),182    )183    .execute(execution.into())184    .map_err(|e| anyhow!("failed to execute the extrinsic {:?}", e))?;185186    let proof = proving_backend187        .extract_proof()188        .expect("A recorder was set and thus, a storage proof can be extracted; qed");189    let proof_size = proof.encoded_size();190    let compact_proof = proof191        .clone()192        .into_compact_proof::<HasherOf<Block>>(pre_root)193        .map_err(|e| anyhow!("failed to generate compact proof {:?}", e))?;194    let compact_proof_size = compact_proof.encoded_size();195196    let compressed_proof = zstd::stream::encode_all(&compact_proof.encode()[..], 0)197            .map_err(|e| anyhow!("failed to generate compact proof {:?}", e))?;198    let compressed_proof_size = compressed_proof.len();199200    Ok(PovInfo {201        proof_size: proof_size as u64,202        compact_proof_size: compact_proof_size as u64,203        compressed_proof_size: compressed_proof_size as u64,204    })205}