Skip to content

Commit

Permalink
Use raw_genesis_config to construct the genesis domain block/receipt
Browse files Browse the repository at this point in the history
Signed-off-by: linning <[email protected]>
  • Loading branch information
NingLin-P committed Jul 26, 2023
1 parent 7503802 commit 9eca1e7
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 28 deletions.
9 changes: 8 additions & 1 deletion crates/pallet-domains/src/domain_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,12 @@ pub(crate) fn do_instantiate_domain<T: Config>(
let genesis_receipt = {
let runtime_obj = RuntimeRegistry::<T>::get(domain_config.runtime_id)
.expect("Runtime object must exist as checked in `can_instantiate_domain`; qed");
initialize_genesis_receipt::<T>(domain_id, runtime_obj.runtime_type, runtime_obj.code)?
initialize_genesis_receipt::<T>(
domain_id,
runtime_obj.runtime_type,
runtime_obj.code,
raw_genesis_config.clone(),
)?
};
let genesis_receipt_hash = genesis_receipt.hash();

Expand Down Expand Up @@ -191,13 +196,15 @@ fn initialize_genesis_receipt<T: Config>(
domain_id: DomainId,
runtime_type: RuntimeType,
runtime_code: Vec<u8>,
raw_genesis_config: Option<Vec<u8>>,
) -> Result<ExecutionReceiptOf<T>, Error> {
let consensus_genesis_hash = frame_system::Pallet::<T>::block_hash(T::BlockNumber::zero());
let genesis_state_root = generate_genesis_state_root(
domain_id,
DomainInstanceData {
runtime_type,
runtime_code,
raw_genesis_config,
},
)
.ok_or(Error::FailedToGenerateGenesisStateRoot)?;
Expand Down
10 changes: 5 additions & 5 deletions crates/pallet-domains/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1043,14 +1043,14 @@ impl<T: Config> Pallet<T> {
}

pub fn domain_instance_data(domain_id: DomainId) -> Option<DomainInstanceData> {
let runtime_id = DomainRegistry::<T>::get(domain_id)?
.domain_config
.runtime_id;
let (runtime_type, runtime_code) = RuntimeRegistry::<T>::get(runtime_id)
.map(|runtime_object| (runtime_object.runtime_type, runtime_object.code))?;
let domain_obj = DomainRegistry::<T>::get(domain_id)?;
let (runtime_type, runtime_code) =
RuntimeRegistry::<T>::get(domain_obj.domain_config.runtime_id)
.map(|runtime_object| (runtime_object.runtime_type, runtime_object.code))?;
Some(DomainInstanceData {
runtime_type,
runtime_code,
raw_genesis_config: domain_obj.raw_genesis_config,
})
}

Expand Down
5 changes: 5 additions & 0 deletions crates/sp-domains/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,11 @@ impl DomainsDigestItem for DigestItem {
pub struct DomainInstanceData {
pub runtime_type: RuntimeType,
pub runtime_code: Vec<u8>,
// The genesis config of the domain, encoded in json format.
//
// NOTE: the WASM code in the `system-pallet` genesis config should be empty to avoid
// redundancy with the `runtime_code` field.
pub raw_genesis_config: Option<Vec<u8>>,

This comment has been minimized.

Copy link
@nazar-pc

nazar-pc Aug 17, 2023

Member

If it is JSON format, then it should be stored in a string (as it is guaranteed to be utf-8), using Vec<u8> while valid, is a bit confusing. Also I don't understand what the comment is trying to explain.

This comment has been minimized.

Copy link
@NingLin-P

NingLin-P Aug 17, 2023

Author Member

If it is JSON format, then it should be stored in a string (as it is guaranteed to be utf-8), using Vec while valid, is a bit confusing.

Not sure if we can directly use String in non_std and String also means unbounded length, this is just follows how substrate pallet stores string value in runtime.

Also I don't understand what the comment is trying to explain.

The RuntimeGenesisConfig::system also contains the WASM runtime blob, what the comment says is the runtime blob should be removed from RuntimeGenesisConfig since we also already store it at the RuntimeRegistry assign it to DomainInstanceData:: runtime_code

This comment has been minimized.

Copy link
@nazar-pc

nazar-pc Aug 17, 2023

Member

Not sure if we can directly use String in non_std and String also means unbounded length, this is just follows how substrate pallet stores string value in runtime.

You absolutely can, internally it is just a vector with a guarantee that it is properly utf-8 encoded.

The RuntimeGenesisConfig::system also contains the WASM runtime blob, what the comment says is the runtime blob should be removed from RuntimeGenesisConfig since we also already store it at the RuntimeRegistry assign it to DomainInstanceData:: runtime_code

Why storing it there in the first place then, why not removing before it even gets here? And I'm certainly out of context here, but I do not understand why we store something that we then remove/replace, feels awkward and error-prone.

This comment has been minimized.

Copy link
@NingLin-P

NingLin-P Aug 17, 2023

Author Member

Why storing it there in the first place then, why not removing before it even gets here?

It is removed before we store it onchain, the comment just tries to explain raw_genesis_config is the RuntimeGenesisConfig with the runtime code removed.

}

impl PassBy for DomainInstanceData {
Expand Down
11 changes: 10 additions & 1 deletion crates/subspace-node/src/domain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,19 @@ where
let DomainInstanceData {
runtime_type,
runtime_code,
raw_genesis_config,
} = domain_instance_data;
let domain_genesis_block_builder = match runtime_type {
RuntimeType::Evm => {
let mut runtime_cfg = evm_domain_runtime::RuntimeGenesisConfig::default();
let mut runtime_cfg = match raw_genesis_config {
Some(raw_genesis_config) => serde_json::from_slice(&raw_genesis_config)
.map_err(|_| {
sp_blockchain::Error::Application(Box::from(
"Failed to deserialize genesis config of the evm domain",
))
})?,
None => evm_domain_runtime::RuntimeGenesisConfig::default(),
};
runtime_cfg.system.code = runtime_code;
runtime_cfg.self_domain_id.domain_id = Some(domain_id);
GenesisBlockBuilder::new(
Expand Down
19 changes: 11 additions & 8 deletions crates/subspace-node/src/domain/evm_chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,13 +262,6 @@ fn load_chain_spec_with(
Ok(Box::new(chain_spec))
}

fn domain_instance_genesis_config(domain_id: DomainId, runtime_code: Vec<u8>) -> GenesisConfig {
let mut cfg = GenesisConfig::default();
cfg.system.code = runtime_code;
cfg.self_domain_id.domain_id = Some(domain_id);
cfg
}

pub fn create_domain_spec(
domain_id: DomainId,
chain_id: &str,
Expand All @@ -277,11 +270,21 @@ pub fn create_domain_spec(
let DomainInstanceData {
runtime_type,
runtime_code,
raw_genesis_config,
} = domain_instance_data;

match runtime_type {
RuntimeType::Evm => {
let genesis_config = domain_instance_genesis_config(domain_id, runtime_code);
let mut genesis_config = match raw_genesis_config {
Some(raw_genesis_config) => {
serde_json::from_slice(&raw_genesis_config).map_err(|_| {
"Failed to deserialize genesis config of the evm domain".to_string()
})?
}
None => GenesisConfig::default(),
};
genesis_config.system.code = runtime_code;
genesis_config.self_domain_id.domain_id = Some(domain_id);
let spec = load_chain_spec_with(chain_id, genesis_config)?;
Ok(spec)
}
Expand Down
32 changes: 25 additions & 7 deletions domains/test/service/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ fn testnet_evm_genesis() -> GenesisConfig {
static GENESIS_CONFIG: OnceCell<Vec<u8>> = OnceCell::new();

/// Load chain spec that contains the given `GenesisConfig`
pub fn load_chain_spec_with(genesis_config: GenesisConfig) -> Box<dyn ChainSpec> {
fn load_chain_spec_with(genesis_config: GenesisConfig) -> Box<dyn ChainSpec> {
let _ = GENESIS_CONFIG.set(
serde_json::to_vec(&genesis_config).expect("Genesis config serialization never fails; qed"),
);
Expand All @@ -143,10 +143,28 @@ pub fn load_chain_spec_with(genesis_config: GenesisConfig) -> Box<dyn ChainSpec>
Box::new(chain_spec_from_genesis!(constructor))
}

/// Create a `GenesisConfig`
pub fn domain_instance_genesis_config(domain_id: DomainId, runtime_code: Vec<u8>) -> GenesisConfig {
let mut cfg = GenesisConfig::default();
cfg.system.code = runtime_code;
cfg.self_domain_id.domain_id = Some(domain_id);
cfg
/// Create chain spec
pub fn create_domain_spec(
domain_id: DomainId,
domain_instance_data: DomainInstanceData,
) -> Box<dyn ChainSpec> {
let DomainInstanceData {
runtime_type,
runtime_code,
raw_genesis_config,
} = domain_instance_data;

match runtime_type {
RuntimeType::Evm => {
let mut genesis_config = match raw_genesis_config {
Some(raw_genesis_config) => serde_json::from_slice(&raw_genesis_config)
.expect("Raw genesis config should be well-formatted"),
None => GenesisConfig::default(),
};
genesis_config.system.code = runtime_code;
genesis_config.self_domain_id.domain_id = Some(domain_id);

load_chain_spec_with(genesis_config)
}
}
}
8 changes: 2 additions & 6 deletions domains/test/service/src/domain.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Utilities used for testing with the domain.
#![warn(missing_docs)]

use crate::chain_spec::{domain_instance_genesis_config, load_chain_spec_with};
use crate::chain_spec::create_domain_spec;
use crate::{construct_extrinsic_generic, node_config, EcdsaKeyring, UncheckedExtrinsicFor};
use domain_client_operator::{Bootstrapper, OperatorStreams};
use domain_runtime_primitives::opaque::Block;
Expand Down Expand Up @@ -416,11 +416,7 @@ impl DomainNodeBuilder {
.expect("Failed to get domain instance data")
.domain_instance_data
};
let chain_spec = {
let genesis_config =
domain_instance_genesis_config(domain_id, domain_instance_data.runtime_code);
load_chain_spec_with(genesis_config)
};
let chain_spec = create_domain_spec(domain_id, domain_instance_data);
DomainNode::build(
DomainId::new(0u32),
self.tokio_handle,
Expand Down

0 comments on commit 9eca1e7

Please sign in to comment.