Skip to content

Commit

Permalink
Add westend chain-spec and some chain-spec utilities (#19)
Browse files Browse the repository at this point in the history
  • Loading branch information
clangenb authored Apr 16, 2024
1 parent 1410086 commit 97a9fa6
Show file tree
Hide file tree
Showing 14 changed files with 452 additions and 129 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,7 @@ build/
# Chopsticks
/chopsticks/*.db.sqlite*

# genesis state and chain-spec dumps
/chain_dumps

# Before adding new lines, see the comment at the top.
1 change: 1 addition & 0 deletions Cargo.lock

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

24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,27 @@ Simply create an external proposal and fast-track it with a small voting period
polkadot-js/apps, go to Developer -> JavaScript and execute the following chopsticks-dev-rpc:
`api.rpc('dev_newBlock', { count: 10 })`. After this you can observe the blocks being created one by one until the
proposal is executed.

### Creating new production network chainspecs.

We have parametrized chain-spec generation to simplify creating new production network chain-specs without manual
copy-pasting.
This helps to prevent human errors, and the code also serves as documentation at the same time. How to create a new
production
chain-spec:

1. Add a new `*-fresh` entry in the [node/src/command], e.g., `bajun-westend-fresh`.
2. Ensure that the collator and the runtime is of the most recent build, and run the
script: `scripts/dump_wasm_state_and_spec.sh bajun-westend-fresh`.
3. Copy the `chain_dumps/bajun-westend-fresh-raw.json`/`-.state`/`-.wasm` into `resources/bajun/westend`.
4. Rename the files to remove the `-fresh` suffix.
5. Delete the unsorted chain-spec.
6. Add a new function into `node/src/chain_spec.rs`

```rust
pub fn bajun_westend_config() -> Result<ChainSpec, String> {
ChainSpec::from_json_bytes(&include_bytes!("../../resources/bajun/bajun-westend-raw.json")[..])
}
```

7. Refer to the new function in `node/src/command.rs`.
1 change: 1 addition & 0 deletions node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ sp-blockchain = { workspace = true }
sp-consensus-aura = { workspace = true, features = ["std"] }
sp-core = { workspace = true, features = ["std"] }
sp-keystore = { workspace = true, features = ["std"] }
sp-keyring = { workspace = true }
sp-runtime = { workspace = true, features = ["std"] }
sp-timestamp = { workspace = true, features = ["std"] }
substrate-frame-rpc-system = { workspace = true }
Expand Down
176 changes: 51 additions & 125 deletions node/src/chain_spec.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,16 @@
use bajun_runtime::{AccountId, AuraId, Signature, EXISTENTIAL_DEPOSIT};
use crate::chain_spec_utils::{BajunDevKeys, BajunKeys, GenesisKeys, RelayChain, WellKnownKeys};
use bajun_runtime::{AccountId, AuraId, EXISTENTIAL_DEPOSIT};
use cumulus_primitives_core::ParaId;
use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup};
use sc_service::ChainType;
use serde::{Deserialize, Serialize};
use sp_core::{sr25519, Pair, Public};
use sp_runtime::traits::{IdentifyAccount, Verify};

/// Specialized `ChainSpec` for the normal parachain runtime.
pub type ChainSpec = sc_service::GenericChainSpec<(), Extensions>;

const SS58_FORMAT: u32 = 1337;
const PARA_ID: u32 = 2119;
/// The default XCM version to set in genesis config.
const SAFE_XCM_VERSION: u32 = staging_xcm::prelude::XCM_VERSION;

/// Helper function to generate a crypto pair from seed
pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
TPublic::Pair::from_string(&format!("//{}", seed), None)
.expect("static values are valid; qed")
.public()
}

/// The extensions for the [`ChainSpec`].
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)]
#[serde(deny_unknown_fields)]
Expand All @@ -38,137 +28,71 @@ impl Extensions {
}
}

type AccountPublic = <Signature as Verify>::Signer;

/// Generate collator keys from seed.
///
/// This function's return type must always match the session keys of the chain in tuple format.
pub fn get_collator_keys_from_seed(seed: &str) -> AuraId {
get_from_seed::<AuraId>(seed)
}

/// Helper function to generate an account ID from seed
pub fn get_account_id_from_seed<TPublic: Public>(seed: &str) -> AccountId
where
AccountPublic: From<<TPublic::Pair as Pair>::Public>,
{
AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()
}

/// Generate the session keys from individual elements.
///
/// The input must be a tuple of individual keys (a single arg for now since we have just one key).
pub fn template_session_keys(keys: AuraId) -> bajun_runtime::SessionKeys {
bajun_runtime::SessionKeys { aura: keys }
}

pub fn development_config() -> ChainSpec {
pub fn bajun_chain_spec(
para_id: ParaId,
genesis_keys: GenesisKeys,
relay_chain: RelayChain,
) -> ChainSpec {
// Give your base currency a unit name and decimal places
let mut properties = sc_chain_spec::Properties::new();
properties.insert("tokenSymbol".into(), "BAJU".into());
properties.insert("tokenDecimals".into(), 12.into());
properties.insert("ss58Format".into(), SS58_FORMAT.into());

ChainSpec::builder(
bajun_runtime::WASM_BINARY.expect("WASM binary was not built, please build it!"),
Extensions {
relay_chain: "rococo-local".into(),
// You MUST set this to the correct network!
para_id: PARA_ID,
},
)
.with_name("Bajun Dev")
.with_id("bajun-dev")
.with_chain_type(ChainType::Development)
.with_genesis_config_patch(testnet_genesis(
// initial collators.
vec![
(
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_collator_keys_from_seed("Alice"),
),
(
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_collator_keys_from_seed("Bob"),
),
],
vec![
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_account_id_from_seed::<sr25519::Public>("Charlie"),
get_account_id_from_seed::<sr25519::Public>("Dave"),
get_account_id_from_seed::<sr25519::Public>("Eve"),
get_account_id_from_seed::<sr25519::Public>("Ferdie"),
get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),
get_account_id_from_seed::<sr25519::Public>("Dave//stash"),
get_account_id_from_seed::<sr25519::Public>("Eve//stash"),
get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
],
get_account_id_from_seed::<sr25519::Public>("Alice"),
PARA_ID.into(),
))
.build()
}

pub fn local_testnet_config() -> ChainSpec {
// Give your base currency a unit name and decimal places
let mut properties = sc_chain_spec::Properties::new();
properties.insert("tokenSymbol".into(), "BAJU".into());
properties.insert("tokenDecimals".into(), 12.into());
properties.insert("ss58Format".into(), SS58_FORMAT.into());
let (root, endowed, invulnerables, gov) = match genesis_keys {
GenesisKeys::Bajun => (
BajunKeys::root(),
vec![BajunKeys::root()],
BajunKeys::invulnerables(),
BajunKeys::governance(),
),
GenesisKeys::BajunDev => (
BajunDevKeys::root(),
vec![BajunDevKeys::root()],
BajunDevKeys::invulnerables(),
BajunDevKeys::governance(),
),
GenesisKeys::WellKnown => (
WellKnownKeys::root(),
WellKnownKeys::endowed(),
WellKnownKeys::invulnerables(),
WellKnownKeys::governance(),
),
};

#[allow(deprecated)]
ChainSpec::builder(
bajun_runtime::WASM_BINARY.expect("WASM binary was not built, please build it!"),
Extensions {
relay_chain: "rococo-local".into(),
// You MUST set this to the correct network!
para_id: PARA_ID,
},
Extensions { relay_chain: relay_chain.to_string(), para_id: para_id.into() },
)
.with_name("Bajun Local Testnet")
.with_id("bajun_local_testnet")
.with_chain_type(ChainType::Local)
.with_name("Bajun")
.with_id(&format!("bajun-{}", relay_chain.to_string()))
.with_protocol_id(relay_chain.protocol_id())
.with_chain_type(relay_chain.chain_type())
.with_properties(properties)
.with_genesis_config_patch(testnet_genesis(
// initial collators.
vec![
(
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_collator_keys_from_seed("Alice"),
),
(
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_collator_keys_from_seed("Bob"),
),
],
vec![
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_account_id_from_seed::<sr25519::Public>("Charlie"),
get_account_id_from_seed::<sr25519::Public>("Dave"),
get_account_id_from_seed::<sr25519::Public>("Eve"),
get_account_id_from_seed::<sr25519::Public>("Ferdie"),
get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),
get_account_id_from_seed::<sr25519::Public>("Dave//stash"),
get_account_id_from_seed::<sr25519::Public>("Eve//stash"),
get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
],
get_account_id_from_seed::<sr25519::Public>("Alice"),
PARA_ID.into(),
invulnerables,
endowed,
root,
gov,
para_id,
))
.with_protocol_id("bajun-local")
.with_properties(properties)
.build()
}

fn testnet_genesis(
invulnerables: Vec<(AccountId, AuraId)>,
endowed_accounts: Vec<AccountId>,
root: AccountId,
governance_accounts: Vec<AccountId>,
id: ParaId,
) -> serde_json::Value {
serde_json::json!({
Expand All @@ -183,18 +107,10 @@ fn testnet_genesis(
"candidacyBond": EXISTENTIAL_DEPOSIT * 16,
},
"council": {
"members": vec![
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_account_id_from_seed::<sr25519::Public>("Charlie"),
]
"members": governance_accounts
},
"technicalCommittee": {
"members": vec![
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_account_id_from_seed::<sr25519::Public>("Charlie"),
]
"members": governance_accounts
},
"session": {
"keys": invulnerables
Expand All @@ -214,3 +130,13 @@ fn testnet_genesis(
"sudo": { "key": Some(root) }
})
}

pub fn bajun_config() -> Result<ChainSpec, String> {
ChainSpec::from_json_bytes(&include_bytes!("../../resources/bajun/bajun-raw.json")[..])
}

pub fn bajun_westend_config() -> Result<ChainSpec, String> {
ChainSpec::from_json_bytes(
&include_bytes!("../../resources/bajun/westend/bajun-westend-raw.json")[..],
)
}
Loading

0 comments on commit 97a9fa6

Please sign in to comment.