Skip to content

Commit

Permalink
Merge pull request #1612 from subspace/GenesisReceiptExt
Browse files Browse the repository at this point in the history
Generate the genesis state root using runtime interface
  • Loading branch information
liuchengxu authored Jun 30, 2023
2 parents f7fc7f1 + 36411c3 commit 4933327
Show file tree
Hide file tree
Showing 9 changed files with 192 additions and 43 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions crates/sp-domains/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ sp-application-crypto = { version = "23.0.0", default-features = false, git = "h
sp-blockchain = { version = "4.0.0-dev", git = "https://github.com/subspace/substrate", rev = "55c157cff49b638a59d81a9f971f0f9a66829c71", optional = true }
sp-consensus-slots = { version = "0.10.0-dev", default-features = false, git = "https://github.com/subspace/substrate", rev = "55c157cff49b638a59d81a9f971f0f9a66829c71" }
sp-core = { version = "21.0.0", default-features = false, git = "https://github.com/subspace/substrate", rev = "55c157cff49b638a59d81a9f971f0f9a66829c71" }
sp-externalities = { version = "0.19.0", default-features = false, git = "https://github.com/subspace/substrate", rev = "55c157cff49b638a59d81a9f971f0f9a66829c71" }
sp-keystore = { version = "0.27.0", git = "https://github.com/subspace/substrate", rev = "55c157cff49b638a59d81a9f971f0f9a66829c71", optional = true }
sp-runtime = { version = "24.0.0", default-features = false, git = "https://github.com/subspace/substrate", rev = "55c157cff49b638a59d81a9f971f0f9a66829c71" }
sp-runtime-interface = { version = "17.0.0", default-features = false, git = "https://github.com/subspace/substrate", rev = "55c157cff49b638a59d81a9f971f0f9a66829c71" }
sp-state-machine = { version = "0.28.0", default-features = false, git = "https://github.com/subspace/substrate", rev = "55c157cff49b638a59d81a9f971f0f9a66829c71" }
sp-std = { version = "8.0.0", default-features = false, git = "https://github.com/subspace/substrate", rev = "55c157cff49b638a59d81a9f971f0f9a66829c71" }
sp-trie = { version = "22.0.0", default-features = false, git = "https://github.com/subspace/substrate", rev = "55c157cff49b638a59d81a9f971f0f9a66829c71" }
Expand All @@ -44,8 +46,10 @@ std = [
"sp-application-crypto/std",
"sp-consensus-slots/std",
"sp-core/std",
"sp-externalities/std",
"sp-keystore",
"sp-runtime/std",
"sp-runtime-interface/std",
"sp-state-machine/std",
"sp-std/std",
"sp-trie/std",
Expand Down
51 changes: 46 additions & 5 deletions crates/sp-domains/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ use sp_core::H256;
use sp_runtime::generic::OpaqueDigestItemId;
use sp_runtime::traits::{BlakeTwo256, Block as BlockT, Hash as HashT, NumberFor, Zero};
use sp_runtime::{DigestItem, OpaqueExtrinsic, RuntimeAppPublic};
use sp_runtime_interface::pass_by::PassBy;
use sp_runtime_interface::{pass_by, runtime_interface};
use sp_std::vec::Vec;
use sp_trie::StorageProof;
use subspace_core_primitives::crypto::blake2b_256_hash;
Expand Down Expand Up @@ -301,11 +303,6 @@ impl<DomainHash> BundleSolution<DomainHash> {
pub fn proof_of_election(&self) -> &ProofOfElection<DomainHash> {
&self.proof_of_election
}

/// Returns the hash of the block on top of which the solution was created.
pub fn creation_block_hash(&self) -> &DomainHash {
&self.proof_of_election.system_block_hash
}
}

impl<DomainHash: Default> BundleSolution<DomainHash> {
Expand Down Expand Up @@ -485,6 +482,10 @@ pub enum RuntimeType {
Evm,
}

impl PassBy for RuntimeType {
type PassBy = pass_by::Codec<Self>;
}

/// Type representing the runtime ID.
pub type RuntimeId = u32;

Expand Down Expand Up @@ -515,6 +516,46 @@ impl DomainsDigestItem for DigestItem {
}
}

#[cfg(feature = "std")]
pub trait GenerateGenesisStateRoot: Send + Sync {
/// Returns the state root of genesis block built from the runtime genesis config on success.
fn generate_genesis_state_root(
&self,
runtime_type: RuntimeType,
raw_runtime_genesis_config: Vec<u8>,
) -> Option<H256>;
}

#[cfg(feature = "std")]
sp_externalities::decl_extension! {
/// A domain genesis receipt extension.
pub struct GenesisReceiptExtension(std::sync::Arc<dyn GenerateGenesisStateRoot>);
}

#[cfg(feature = "std")]
impl GenesisReceiptExtension {
/// Create a new instance of [`GenesisReceiptExtension`].
pub fn new(inner: std::sync::Arc<dyn GenerateGenesisStateRoot>) -> Self {
Self(inner)
}
}

/// Domain-related runtime interface
#[runtime_interface]
pub trait Domain {
fn generate_genesis_state_root(
&mut self,
runtime_type: RuntimeType,
raw_runtime_genesis_config: Vec<u8>,
) -> Option<H256> {
use sp_externalities::ExternalitiesExt;

self.extension::<GenesisReceiptExtension>()
.expect("No `GenesisReceiptExtension` associated for the current context!")
.generate_genesis_state_root(runtime_type, raw_runtime_genesis_config)
}
}

sp_api::decl_runtime_apis! {
/// API necessary for executor pallet.
pub trait ExecutorApi<DomainHash: Encode + Decode> {
Expand Down
1 change: 1 addition & 0 deletions crates/subspace-node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ sc-tracing = { version = "4.0.0-dev", git = "https://github.com/subspace/substra
sc-utils = { version = "4.0.0-dev", git = "https://github.com/subspace/substrate", rev = "55c157cff49b638a59d81a9f971f0f9a66829c71" }
serde = "1.0.159"
serde_json = "1.0.95"
sp-blockchain = { version = "4.0.0-dev", git = "https://github.com/subspace/substrate", rev = "55c157cff49b638a59d81a9f971f0f9a66829c71" }
sp-consensus = { version = "0.10.0-dev", git = "https://github.com/subspace/substrate", rev = "55c157cff49b638a59d81a9f971f0f9a66829c71" }
sp-consensus-subspace = { version = "0.1.0", path = "../sp-consensus-subspace" }
sp-core = { version = "21.0.0", git = "https://github.com/subspace/substrate", rev = "55c157cff49b638a59d81a9f971f0f9a66829c71" }
Expand Down
51 changes: 21 additions & 30 deletions crates/subspace-node/src/bin/subspace-node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,39 +29,23 @@ use futures::StreamExt;
use sc_cli::{ChainSpec, CliConfiguration, SubstrateCli};
use sc_client_api::BlockchainEvents;
use sc_consensus_slots::SlotProportion;
use sc_executor::NativeExecutionDispatch;
use sc_service::{BasePath, PartialComponents};
use sc_storage_monitor::StorageMonitorService;
use sp_core::crypto::Ss58AddressFormat;
use sp_core::traits::SpawnEssentialNamed;
use subspace_node::{
AccountId32ToAccountId20Converter, Cli, DomainCli, DomainSubcommand, ExecutorDispatch,
Subcommand,
use sp_domains::GenerateGenesisStateRoot;
use std::sync::Arc;
use subspace_node::domain::{
AccountId32ToAccountId20Converter, DomainCli, DomainGenesisBlockBuilder, DomainSubcommand,
EVMDomainExecutorDispatch,
};
use subspace_node::{Cli, ExecutorDispatch, Subcommand};
use subspace_proof_of_space::chia::ChiaTable;
use subspace_runtime::{Block, RuntimeApi};
use subspace_service::{DsnConfig, SubspaceConfiguration, SubspaceNetworking};

type PosTable = ChiaTable;

/// EVM domain executor instance.
pub struct EVMDomainExecutorDispatch;

impl NativeExecutionDispatch for crate::EVMDomainExecutorDispatch {
#[cfg(feature = "runtime-benchmarks")]
type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
#[cfg(not(feature = "runtime-benchmarks"))]
type ExtendHostFunctions = ();

fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
evm_domain_runtime::api::dispatch(method, data)
}

fn native_version() -> sc_executor::NativeVersion {
evm_domain_runtime::native_version()
}
}

/// Subspace node error.
#[derive(thiserror::Error, Debug)]
pub enum Error {
Expand Down Expand Up @@ -128,7 +112,7 @@ fn main() -> Result<(), Error> {
task_manager,
..
} = subspace_service::new_partial::<PosTable, RuntimeApi, ExecutorDispatch>(
&config,
&config, None,
)?;
Ok((
cmd.run(client, import_queue).map_err(Error::SubstrateCli),
Expand All @@ -145,7 +129,7 @@ fn main() -> Result<(), Error> {
task_manager,
..
} = subspace_service::new_partial::<PosTable, RuntimeApi, ExecutorDispatch>(
&config,
&config, None,
)?;
Ok((
cmd.run(client, config.database)
Expand All @@ -163,7 +147,7 @@ fn main() -> Result<(), Error> {
task_manager,
..
} = subspace_service::new_partial::<PosTable, RuntimeApi, ExecutorDispatch>(
&config,
&config, None,
)?;
Ok((
cmd.run(client, config.chain_spec)
Expand All @@ -182,7 +166,7 @@ fn main() -> Result<(), Error> {
task_manager,
..
} = subspace_service::new_partial::<PosTable, RuntimeApi, ExecutorDispatch>(
&config,
&config, None,
)?;
Ok((
cmd.run(client, import_queue).map_err(Error::SubstrateCli),
Expand All @@ -201,7 +185,7 @@ fn main() -> Result<(), Error> {
other: (_block_import, subspace_link, _telemetry, _bundle_validator),
..
} = subspace_service::new_partial::<PosTable, RuntimeApi, ExecutorDispatch>(
&config,
&config, None,
)?;

let subspace_archiver = sc_consensus_subspace::create_subspace_archiver(
Expand Down Expand Up @@ -274,7 +258,7 @@ fn main() -> Result<(), Error> {
task_manager,
..
} = subspace_service::new_partial::<PosTable, RuntimeApi, ExecutorDispatch>(
&config,
&config, None,
)?;
Ok((
cmd.run(client, backend, None).map_err(Error::SubstrateCli),
Expand Down Expand Up @@ -309,15 +293,17 @@ fn main() -> Result<(), Error> {
PosTable,
RuntimeApi,
ExecutorDispatch,
>(&config)?;
>(
&config, None
)?;

cmd.run(client)
}
BenchmarkCmd::Storage(cmd) => {
let PartialComponents {
client, backend, ..
} = subspace_service::new_partial::<PosTable, RuntimeApi, ExecutorDispatch>(
&config,
&config, None,
)?;
let db = backend.expose_db();
let storage = backend.expose_storage();
Expand Down Expand Up @@ -485,9 +471,14 @@ fn main() -> Result<(), Error> {
|| cli.run.is_dev().unwrap_or(false),
};

let construct_domain_genesis_block_builder =
|backend, executor| -> Arc<dyn GenerateGenesisStateRoot> {
Arc::new(DomainGenesisBlockBuilder::new(backend, executor))
};
let partial_components =
subspace_service::new_partial::<PosTable, RuntimeApi, ExecutorDispatch>(
&primary_chain_config,
Some(&construct_domain_genesis_block_builder),
)
.map_err(|error| {
sc_service::Error::Other(format!(
Expand Down
97 changes: 95 additions & 2 deletions crates/subspace-node/src/domain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,17 @@
pub(crate) mod cli;
pub(crate) mod evm_chain_spec;

pub use self::cli::{DomainCli, Subcommand as DomainSubcommand};
use evm_domain_runtime::AccountId as AccountId20;
use sc_client_api::Backend;
use sc_executor::{NativeExecutionDispatch, RuntimeVersionOf};
use sc_service::{BuildGenesisBlock, GenesisBlockBuilder};
use sp_core::crypto::AccountId32;
use sp_core::{ByteArray, H160};
use sp_runtime::traits::Convert;
use sp_core::{ByteArray, H160, H256};
use sp_domains::RuntimeType;
use sp_runtime::traits::{Block as BlockT, Convert, Header as HeaderT};
use std::marker::PhantomData;
use std::sync::Arc;

pub struct AccountId32ToAccountId20Converter;

Expand All @@ -30,3 +37,89 @@ impl Convert<AccountId32, AccountId20> for AccountId32ToAccountId20Converter {
H160::from_slice(&acc.as_slice()[0..20]).into()
}
}

/// EVM domain executor instance.
pub struct EVMDomainExecutorDispatch;

impl NativeExecutionDispatch for EVMDomainExecutorDispatch {
#[cfg(feature = "runtime-benchmarks")]
type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
#[cfg(not(feature = "runtime-benchmarks"))]
type ExtendHostFunctions = ();

fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
evm_domain_runtime::api::dispatch(method, data)
}

fn native_version() -> sc_executor::NativeVersion {
evm_domain_runtime::native_version()
}
}

/// [`DomainGenesisBlockBuilder`] is used on the consensus node for building the
/// domain genesis block from a specific serialized domain runtime genesis config.
pub struct DomainGenesisBlockBuilder<Block, B, E> {
backend: Arc<B>,
executor: E,
_phantom: PhantomData<Block>,
}

impl<Block, B, E> DomainGenesisBlockBuilder<Block, B, E>
where
Block: BlockT,
B: Backend<Block>,
E: RuntimeVersionOf + Clone,
{
/// Constructs a new instance of [`DomainGenesisBlockBuilder`].
pub fn new(backend: Arc<B>, executor: E) -> Self {
Self {
backend,
executor,
_phantom: Default::default(),
}
}

/// Constructs the genesis domain block from a serialized runtime genesis config.
pub fn generate_genesis_block(
&self,
runtime_type: RuntimeType,
raw_runtime_genesis_config: Vec<u8>,
) -> sp_blockchain::Result<Block> {
let domain_genesis_block_builder = match runtime_type {
RuntimeType::Evm => {
let runtime_genesis_config: evm_domain_runtime::RuntimeGenesisConfig =
serde_json::from_slice(&raw_runtime_genesis_config)
.map_err(|err| sp_blockchain::Error::Application(Box::new(err)))?;

GenesisBlockBuilder::new(
&runtime_genesis_config,
false,
self.backend.clone(),
self.executor.clone(),
)?
}
};
domain_genesis_block_builder
.build_genesis_block()
.map(|(genesis_block, _)| genesis_block)
}
}

impl<Block, B, E> sp_domains::GenerateGenesisStateRoot for DomainGenesisBlockBuilder<Block, B, E>
where
Block: BlockT,
Block::Hash: Into<H256>,
B: Backend<Block>,
E: RuntimeVersionOf + Clone + Send + Sync,
{
fn generate_genesis_state_root(
&self,
runtime_type: RuntimeType,
raw_runtime_genesis_config: Vec<u8>,
) -> Option<H256> {
self.generate_genesis_block(runtime_type, raw_runtime_genesis_config)
.map(|genesis_block| *genesis_block.header().state_root())
.ok()
.map(Into::into)
}
}
2 changes: 1 addition & 1 deletion crates/subspace-node/src/domain/evm_chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
//! EVM domain configurations.

use crate::chain_spec_utils::chain_spec_properties;
use crate::AccountId32ToAccountId20Converter;
use crate::domain::AccountId32ToAccountId20Converter;
use evm_domain_runtime::{
AccountId, BalancesConfig, EVMChainIdConfig, EVMConfig, GenesisConfig, MessengerConfig,
Precompiles, SudoConfig, SystemConfig, WASM_BINARY,
Expand Down
Loading

0 comments on commit 4933327

Please sign in to comment.