Webb DKG
Running the DKG
Currently the easiest way to run the DKG is to use a 3-node local testnet using dkg-node
. We will call those nodes Alice
, Bob
and Charlie
. Each node will use the built-in development account with the same name, i.e. node Alice
will use the Alice
development account and so on. Each of the three accounts has been configured as an initial authority at genesis. So, we are using three validators for our testnet.
Alice
is our bootnode and is started like so:
$ RUST_LOG=dkg=trace ./target/debug/dkg-node --tmp --alice
Bob
is started like so:
RUST_LOG=dkg=trace ./target/debug/dkg-node --tmp --bob
Charlie
is started like so:
RUST_LOG=dkg=trace ./target/debug/dkg-node --tmp --charlie
Note that the examples above use an ephemeral DB due to the --tmp
CLI option. If you want a persistent DB, use --/tmp/[node-name]
instead. Replace node-name
with the actual node name (e.g. alice
) in order to assure separate dirctories for the DB.
Build & Run
Follow these steps to prepare a local Substrate development environment
Setup of Machine
If necessary, refer to the setup instructions at the Substrate Developer Hub.
Build
Once the development environment is set up, build the DKG. This command will build the Wasm Runtime and native code:
cargo build --release
NOTE: You must use the release builds! The optimizations here are required as in debug mode, it is expected that nodes are not able to run fast enough to produce blocks.
Relay Chain
NOTE: In the following two sections, we document how to manually start a few relay chain nodes, start a parachain node (collator), and register the parachain with the relay chain.
We also have the
polkadot-launch
CLI tool that automate the following steps and help you easily launch relay chains and parachains. However it is still good to go through the following procedures once to understand the mechanism for running and registering a parachain.
To operate a parathread or parachain, you must connect to a relay chain. Typically you would test on a local Rococo development network, then move to the testnet, and finally launch on the mainnet. Keep in mind you need to configure the specific relay chain you will connect to in your collator chain_spec.rs
. In the following examples, we will use rococo-local
as the relay network.
Build Relay Chain
Clone and build Polkadot (be aware of the version tag we used):
# Get a fresh clone, or `cd` to where you have polkadot already:
git clone -b v0.9.7 --depth 1 https://github.com/paritytech/polkadot.git
cd polkadot
cargo build --release
Generate the Relay Chain Chainspec
First, we create the chain specification file (chainspec). Note the chainspec file must be generated on a single node and then shared among all nodes!
./target/release/polkadot build-spec \
--chain rococo-local \
--raw \
--disable-default-bootnode \
> rococo_local.json
Start Relay Chain
We need n + 1 full validator nodes running on a relay chain to accept n parachain / parathread connections. Here we will start two relay chain nodes so we can have one parachain node connecting in later.
From the Polkadot working directory:
# Start Relay `Alice` node
./target/release/polkadot \
--chain ./rococo_local.json \
-d /tmp/relay/alice \
--validator \
--alice \
--port 50555
Open a new terminal, same directory:
# Start Relay `Bob` node
./target/release/polkadot \
--chain ./rococo_local.json \
-d /tmp/relay/bob \
--validator \
--bob \
--port 50556
Add more nodes as needed, with non-conflicting ports, DB directories, and validator keys (--charlie
, --dave
, etc.).
Reserve a ParaID
To connect to a relay chain, you must first _reserve a ParaId
for your parathread that will become a parachain. To do this, you will need sufficient amount of currency on the network account to reserve the ID.
In this example, we will use Charlie
development account where we have funds available. Once you submit this extrinsic successfully, you can start your collators.
The easiest way to reserve your ParaId
is via Polkadot Apps UI under the Parachains
-> Parathreads
tab and use the + ParaID
button.
Parachain
Select the Correct Relay Chain
To operate your parachain, you need to specify the correct relay chain you will connect to in your collator chain_spec.rs
. Specifically you pass the command for the network you need in the Extensions
of your ChainSpec::from_genesis()
in the code.
Extensions {
relay_chain: "rococo-local".into(), // You MUST set this to the correct network!
para_id: id.into(),
},
You can choose from any pre-set runtime chainspec in the Polkadot repo, by referring to the
cli/src/command.rs
andnode/service/src/chain_spec.rs
files or generate your own and use that. See the Cumulus Workshop for how.
In the following examples, we will use the rococo-local
relay network we setup in the last section.
Export the DKG Genesis and Runtime
We first generate the genesis state and genesis wasm needed for the parachain registration.
# Build the dkg node (from it's top level dir)
cd dkg-substrate
cargo build --release
# Folder to store resource files needed for parachain registration
mkdir -p resources
# Build the chainspec
./target/release/dkg-node build-spec \
--disable-default-bootnode > ./resources/template-local-plain.json
# Build the raw chainspec file
./target/release/dkg-node build-spec \
--chain=./resources/template-local-plain.json \
--raw --disable-default-bootnode > ./resources/template-local-raw.json
# Export genesis state to `./resources`, using 2000 as the ParaId
./target/release/dkg-node export-genesis-state --parachain-id 2000 > ./resources/para-2000-genesis
# Export the genesis wasm
./target/release/dkg-node export-genesis-wasm > ./resources/para-2000-wasm
NOTE: we have set the
para_ID
to be 2000 here. This must be unique for all parathreads/chains on the relay chain you register with. You must reserve this first on the relay chain for the testnet or mainnet.
Start a DKG Node (Collator)
From the dkg-substrate working directory:
# NOTE: this command assumes the chain spec is in a directory named `polkadot`
# that is at the same level of the template working directory. Change as needed.
#
# It also assumes a ParaId of 2000. Change as needed.
./target/release/dkg-node \
-d /tmp/parachain/alice \
--collator \
--alice \
--force-authoring \
--ws-port 9945 \
--parachain-id 2000 \
-- \
--execution wasm \
--chain ../polkadot/rococo_local.json
Parachain Registration
Now that you have two relay chain nodes, and a parachain node accompanied with a relay chain light client running, the next step is to register the parachain in the relay chain with the following steps (for detail, refer to the Substrate Cumulus Worship):
-
Goto Polkadot Apps UI, connecting to your relay chain.
-
Execute a sudo extrinsic on the relay chain by going to
Developer
->sudo
page. -
Pick
paraSudoWrapper
->sudoScheduleParaInitialize(id, genesis)
as the extrinsic type, shown below.![Polkadot Apps UI](docs/assets/ss01.png)
-
Set the
id: ParaId
to 2,000 (or whatever ParaId you used above), and set theparachain: Bool
option to Yes. -
For the
genesisHead
, drag the genesis state file exported above,para-2000-genesis
, in. -
For the
validationCode
, drag the genesis wasm file exported above,para-2000-wasm
, in.
Note: When registering to the public Rococo testnet, ensure you set a unique
paraId
larger than 1,000. Values below 1,000 are reserved exclusively for system parachains.
Restart the DKG (Collator)
The DKG node may need to be restarted to get it functioning as expected. After a new epoch starts on the relay chain, your parachain will come online. Once this happens, you should see the collator start reporting parachain blocks:
Note the delay here! It may take some time for your relay chain to enter a new epoch.
Pallets
The DKG runtime is uses the following pallets which are central to how the protocol functions.
pallet-dkg-metadata
This pallet essentially tracks the information about the current and next authority sets, including the set Ids. It does this by implementing the OneSessionHandler
trait which allows it to receieve both new and queued authority sets when the session changes.
pallet-parachain-staking
This is a custom staking pallet that handles collator selection, This pallet helps the protocol select new collators based on amount staked. It also allows for nominators, who back collators by staking their assets, both collators and nominators are rewarded after every session comes to an end. Reward for collators and their nominators is dependent on how many points accrued by the collator during the session, these points are gained by successfully authoring blocks.
This pallet implements the SessionManager
trait and that way is able to provide the the selected collators as validators to the session pallet.
pallet-dkg-proposals
This pallet handles maintaining valid proposers and also voting on proposals. The valid set of proposers is equivalent to the current DKG authorities. This pallet gains access to the current DKG authorities by implementing the OnAuthoritySetChangedHandler
trait, that way it is able to receive the updated DKG authorities from pallet-dkg-metadata
.
This pallet maintains a queue for pending proposals which the DKG authorities vote on and if the vote threshold is met, the proposal is passed on to be handled by a type that implements the ProposalHandlerTrait
.
In this current iteration the proposals are Ethereum transactions.
pallet-dkg-proposal-handler
This pallet implements the ProposalHandlerTrait
accepts proposals and signs them using the DKG authority keys.
pallet-dkg-mmr
This pallet serves as a leaf provider for the pallet-mmr
, generating leaf data that contains a merke root hash for a particular authority set.
It also provides a type that has an implementation for converting ECDSA
keys to ethereum compatible keys.