Template to Core - Setup & Initial Deployment of a Parachain
This guide uses the Rococo testnet. The Kusama relay chain can also be used in place of Rococo, as coretime is also enabled there. Polkadot will enable agile coretime after it has been thoroughly tested on Kusama. This guide is considered a moving document - and will update as networks that have coretime enabled become suitable candidates.
This guide aims to get you up and running with the basics of:
- Obtaining coretime (bulk or on-demand)
- Compiling and configuring your first template
- Deploying your template on your procured core
Getting ROC and Reserving a ParaId
Before starting to work with coretime, you'll need some ROC tokens to pay fees, reserve a ParaId, and more.
Head over to Polkadot.js to reserve a ParaId. We'll need a ParaId to upload our parachain's code:
- Get the Polkadot.js Web Extension.
- Create a wallet, and get some ROC via the faucet. with your new address.
- Go to the Polkadot.js Web App, and make sure you select Rococo as your network via the tabs on the side or visit this link to get to Rococo directly
- Head to Network > Parachains > Parathreads (the tab)
- Follow these instructions to reserve a ParaId.
You can also visit the Accounts tab to view all registered accounts and associated balances within the Polkadot.js Extension. Once finished, you should see your new ParaId at the bottom of the list within Network > Parachains > Parathreads with the option to "Deregister" to the right:
Compiling Parachain Runtime and Generating Wasm Blob
We can now move on to working with the template. Some essential prerequisites are:
- Install Rust and its associated tooling.
- Install the Rust nightly version.
- Have a command line, git, and other common development tools.
Visit the dependencies' installation page before starting.
We need to clone the Polkadot SDK. This guide uses release
polkadot-v1.10.0
,
which can be cloned using the appropriate release tag:
git clone git@github.com:paritytech/polkadot-sdk.git --branch polkadot-v1.10.0 --single-branch
Now, navigate to polkadot-sdk/templates/parachain
:
cd polkadot-sdk/templates/parachain
Open this in your code editor of choice. This template contains the necessary dependencies we need to utilize a core.
Compiling the Parachain Template Node
This tutorial won't go into the specifics of the template, nor will it go into the specifics of FRAME and Substrate. All you need to know is the following:
runtime/
- Contains the runtime and business logic. This is how all of your pallets (runtime modules) are configured. The runtime, once it's compiled as a WebAssembly blob, is uploaded to the state on-chain.node/
- The node implementation takes care of networking and RPC setup. The genesis configuration (chain_spec.rs
) is also located here.
Pallets are essentially just Rust crates, which are imported as dependencies, as seen in
runtime/Cargo.toml
. Read more about pallets here.
When we compile our template, we can extract the runtime code as a .wasm
blob, which is one of the
key artifacts for our core.
For the sake of this example, we won't go into adding or modifying any pallets. However, this is definitey a next step after you get used to deploying your parachain on Rococo!
Configuring Parachain's Chain Spec
Before we generate the binary for our parachain's node, we have a bit of prep to do to our node
inside node/src/chain_spec.rs
. Namely, there are a few main factors to check off our list:
- Make sure that
relay_chain
is set to the target relay chain (rococo
, in our case) - Make sure that
para_id
(right belowrelay_chain
) is set to your reserved ParaId - Make sure that our
ChainType
is set toChainType::Live
- Remove all collators except for one, Alice. See the FAQ/Troubleshooting page for why we do this
- Be sure to also set the para id in
testnet_genesis
! - Optionally, change the name and id of your chain (mine is called "SomeChain" for the name, and "some_chain" for the id). My ticker symbol for the default token is called "SOME". You may change this as you see fit.
If you fail to do one of these, there is a large chance that your chain may fail to produce blocks.
Feel free to copy the configuration below and use it to ensure everything is in place for a Rococo
deployment. This function should replace the local_testnet_config
function within
node/src/chain_spec.rs
:
⚠️ WARNING! ⚠️ Make sure you replace the ParaId with the one you reserved earlier!
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(), "SOME".into());
properties.insert("tokenDecimals".into(), (12).into());
properties.insert("ss58Format".into(), (42).into());
#[allow(deprecated)]
ChainSpec::builder(
runtime::WASM_BINARY.expect("WASM binary was not built, please build it!"),
Extensions {
relay_chain: "rococo".into(),
// You MUST set this to the correct network!
para_id: YOUR_PARA_ID_HERE,
}
)
.with_name("SomeChain")
.with_id("some_chain")
.with_chain_type(ChainType::Live)
.with_genesis_config_patch(
testnet_genesis(
// initial collators.
vec![
(
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_collator_keys_from_seed("Alice"),
),
],
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"),
(YOUR_PARA_ID_HERE).into()
)
)
.with_protocol_id("template-local")
.with_properties(properties)
.build()
}
Once this is in place, you are ready to compile your parachain node.
Generating the Runtime and Genesis
Be sure first to build the node using the following (assuming you're within
polkadot-sdk/templates/parachain
):
cargo build -p parachain-template-node --release
../../target/release/parachain-template-node export-genesis-state genesis
../../target/release/parachain-template-node export-genesis-wasm genesis-wasm
Within polkadot-sdk/templates/parachain
, you should now have two files:
genesis
- the initial state of your parachain.genesis-wasm
- the initial runtime WebAssembly blob of your parachain.
Running Your Collator
It would help if you now started syncing your collator. Keep in mind that you will need to sync
Rococo first - this could take some time (12 hours to a day - depending on your download speed), so
best to get started ASAP. In order to avoid storing the full state of the relay chain, be sure to
run with the appropriate pruning flags (blocks-pruning
and state-pruning
):
./../target/release/parachain-template-node --collator \
--alice \
--force-authoring \
--base-path <your-base-path-here> \
-- \
--chain=rococo \
--sync fast-unsafe \
--blocks-pruning 256 \
--state-pruning 256
Fun fact: This command really spins up two nodes: your collator node for your parachain, along with an embedded relay chain node, hence the separation in the command via
--
.
You should now see your relay chain syncing, reaching the same target that your target relay chain is currently at:
2024-05-07 11:43:18 [Relaychain] ⚙️ Syncing 490.8 bps, target=#10342815 (9 peers), best: #10013784 (0x91d7…aeb2), finalized #10013704 (0x8556…e679), ⬇ 8.3MiB/s ⬆ 1.2kiB/s
Register the Parachain as a Parathread
With your genesis
and genesis-wasm
created, you can now create your parathread. Head
back to
Network > Parachains > Parathreads (the tab)
in PolkadotJS, and click + Parathread in the top right. Now, you can upload your runtime and
genesis accordingly:
- Upload
genesis-wasm
in thecode
field - Upload
genesis
in theinitial state
field
Pay the deposit, and you're good to go! Keep in mind the parathread takes around ~2 hours to onboard. You can scroll down to your ParaId to see it onboarding, for example:
Procure Coretime
Your node should be synced with the relay before this step.
Procuring a core is easy with coretime marketplaces already available. Visit The Coretime Marketplaces page to learn more about them, and purchase a core!
We have two options:
- Bulk - obtain a set amount of coretime in bulk (for Rococo, 7 days).
- On-demand - pay as we go for our block production.
With bulk coretime, we assign a core to our ParaId, and as long as that core is valid, our parachain will produce blocks and finalize them via Rococo until we have to renew the core.
It's worth noting that you can easily experiment using on-demand extrinsics, then later switch to a bulk coretime model. For now, let's start with on-demand coretime to get our first blocks going.
It is recommended that you first try an on-demand assignment, then move to a bulk assignment after you confirm your chain can create blocks!
On-Demand Coretime
Provided your collator is synced, you can create a block using an on-demand extrinsic.
- Head to PolkadotJS > Extrinsics
- Issue the
onDemandAssignmentProvider.placeOrderAllowDeath
extrinsic - Set the
max_amount
to at least1000000000000
andparaId
to your ParaId. - As long as your collator is running, you should see your block height increase from 0 to 1!
Bulk Coretime: Assigning your Core
If everything is working as intended, you can now choose to assign bulk coretime to your parachain for persistent block generation. For this assignment, RegionX's CoreHub will be used to purchase and assign cores.
In the upper right, you will see two balances: one for the relay chain, and one for the coretime chain. Before you can purchase a core, you need ROC on the coretime chain. RegionX includes a tool for doing so:
- Head to General > Cross Chain Transfer on the right, and transfer 10 ROC:
- Sign the transaction with Polkadot.js. If all goes well, you should see the balance update in the upper right:
- Connect your wallet and make sure you select Rococo as your network:
- Click Purchase a Core on the left:
- In the lower right, click "Purchase Core":
- Go to My Regions, and click to select your region, then click Assign on the right side:
- Click Add Task, and input your ParaId along with a name for your chain:
- Select your task, and select Provisional Assignment, and sign using Polkadot JS:
- Once the transaction is confirmed, provided everything is synced and your collator is running, you should see blocks being persistently created as they were with the on-demand extrinsic:
What's Next?
Now that you can launch a layer one blockchain, the possibilities are endless:
- Setup a local development environment for your parachain
- Create a pallet
- Take a look at the OpenZepplin template - which has a lot more pallets configured.
- Upgrade your network