Build Your Own Custom Blockchain Using Polygon Supernet

FABC LLC
13 min readAug 31

--

Polygon is an interchain scalability solution that gives an infrastructure for creating blockchain networks that can interface with each other. It intends to bring the adaptability and scalability of alt chains along with Ethereum’s security, liquidity, and interoperability — allowing for speedy transactions and low fees. Depicted as “Ethereum’s internet of blockchains,” Polygon is emerging as a practical option for many exceptional projects. Polygon has its own native coin, called MATIC, which is used to pay fees on the Polygon network, for staking, and for governance. The Polygon system comprises numerous members, including block creators, developers, clients, and stakeholders.

In this blog, we will provide you with the right steps and ways for creating a blockchain using Polygon Supernet, while offering a clear-cut and easy-to-understand walkthrough of the necessary tools, coding techniques, and deployment procedures. By the end, you will be able to build your own blockchain on this platform.

Let’s walk through the key steps you need to follow for blockchain development.

  1. Ensure you have the following system prerequisites:
  • Golang (v1.15–1.19): Install Go using CLI or package manager like Snapcraft for Linux, Homebrew for Mac, or Chocolatey for Windows.
  • Docker: Required to run the geth instance.
  • Network security: Ensure that network ports used by Polygon Edge are not blocked by firewalls or other security measures

Regenesis

The regenesis process involves several steps, which are outlined below.

1. Get trie root

Obtain the trie root of the existing chain, which is required to create a snapshot of the state trie.

./polygon-edge regenesis getroot --rpc "http://localhost:10002"

2. Create trie snapshot

Create a snapshot of the state trie using the trie root. This snapshot contains the state data, including account balances and contract storage. The stateRoot is the root hash of the Merkle trie data structure that represents the current state of the blockchain at a given block height. It can be obtained by querying the blockchain node through its JSON-RPC API.

./polygon-edge regenesis \
--target-path ./trie_new \
--stateRoot 0xf5ef1a28c82226effb90f4465180ec3469226747818579673f4be929f1cd8663 \
--source-path ./test-chain-1/trie

3. Remove old chain data

Delete the data of the old chain in preparation for setting up the new chain.

rm -rf test-chain-*

4. Create new validators

Generate new validators for the new chain, ensuring that the chain operates with a fresh set of validator nodes.

./polygon-edge polybft-secrets --insecure --data-dir test-chain- --num 4

5. Generate the genesis file​

Generate the genesis file for the new chain, using the trie root from the snapshot. This file is essential for starting the new chain with the migrated state data.

./polygon-edge genesis --consensus polybft --bridge-json-rpc http://127.0.0.1:8545 \
--block-gas-limit 10000000 \
--epoch-size 10 \
--trieroot 0xf5ef1a28c82226effb90f4465180ec3469226747818579673f4be929f1cd8663

6. Start your new PolyBFT chain

Launch the new PolyBFT chain with the copied snapshot trie, ensuring that the new chain’s state is consistent with the old chain’s state.

./polygon-edge server --data-dir ./test-chain-1 --chain genesis.json --grpc-address :10000 --libp2p :30301 --jsonrpc :10002 --log-level DEBUG &
./polygon-edge server --data-dir ./test-chain-2 --chain genesis.json --grpc-address :20000 --libp2p :30302 --jsonrpc :20002 --log-level DEBUG &
./polygon-edge server --data-dir ./test-chain-3 --chain genesis.json --grpc-address :30000 --libp2p :30303 --jsonrpc :30002 --log-level DEBUG &
./polygon-edge server --data-dir ./test-chain-4 --chain genesis.json --grpc-address :40000 --libp2p :30304 --jsonrpc :40002 --log-level DEBUG &

7. Copy the snapshot trie to the data directory

Copy the snapshot trie to the data directories of each validator node, allowing the new chain to maintain the same account balances, contract storage, and other state data.

rm -rf ./test-chain-1/trie
rm -rf ./test-chain-2/trie
rm -rf ./test-chain-3/trie
rm -rf ./test-chain-4/trie
cp -fR ./trie_new/ ./test-chain-1/trie/
cp -fR ./trie_new/ ./test-chain-2/trie/
cp -fR ./trie_new/ ./test-chain-3/trie/
cp -fR ./trie_new/ ./test-chain-4/trie/

8. Re-run the chain

Restart the new chain, and the validator nodes will continue to seal new blocks. The state trie from the previous chain has been successfully migrated.

./polygon-edge server --data-dir ./test-chain-1 --chain genesis.json --grpc-address :10000 --libp2p :30301 --jsonrpc :10002 --seal --log-level DEBUG &
./polygon-edge server --data-dir ./test-chain-2 --chain genesis.json --grpc-address :20000 --libp2p :30302 --jsonrpc :20002 --seal --log-level DEBUG &
./polygon-edge server --data-dir ./test-chain-3 --chain genesis.json --grpc-address :30000 --libp2p :30303 --jsonrpc :30002 --seal --log-level DEBUG &
./polygon-edge server --data-dir ./test-chain-4 --chain genesis.json --grpc-address :40000 --libp2p :30304 --jsonrpc :40002 --seal --log-level DEBUG &

9. Check the account balance on the new PolyBFT chain

Verify the success of the migration by checking the account balances on the new chain. If the account balance is non-zero and matches the previous chain’s state, the snapshot import was successful.

curl -s -X POST --data '{"jsonrpc":"2.0", "method":"eth_getBalance", "params":["0x85da99c8a7c2c95964c8efd687e95e632fc533d6", "latest"], "id":1}' http://localhost:10002
{"jsonrpc":"2.0","id":1,"result":"0x3635c9adc5dea00000"}%

Prerequisites

  1. You need to have AWS CLI installed and configured on your machine.
  2. An AWS SSO account with the right permissions to access the SSM Parameter Store is required.

Step 1: AWS SSO Login

The first step is to log in to your AWS SSO account. In your terminal, run the following command:

aws sso login

Follow the prompts to complete the login process.

Step 2: Create Config.json File

Next, create a config.json file within your polygon-edge directory with the following contents:

{
"Type": "aws-ssm",
"Name": "validator1",
"Extra": {
"region": "us-west-2",
"ssm-parameter-path": "/test"
}
}

Ensure to replace the “Name” value with the name you wish to use for your validator, and the “ssm-parameter-path” with the path in AWS SSM Parameter Store where your parameters will be stored.

Step 3: Run the Secret Generation Command

To generate the necessary secrets for your validator node, run the

polybft-secrets command. In your terminal, input:

go run main.go polybft-secrets --config config.json

This will generate the secrets and store them in the AWS SSM Parameter Store as defined in your config.json file.

Step 4: Check Outputs in AWS SSM Parameter Store

Check your AWS SSM Parameter Store to verify that the secrets have been generated successfully. This can be done via the AWS console.

Understand the Generated Secrets

The generated secrets include the following information for each validator node:

  • ECDSA Private and Public Keys: These keys are used to sign and verify transactions on the blockchain.
  • BLS Private and Public Keys: These keys are used in the Byzantine fault-tolerant (BFT) consensus protocol to aggregate and verify signatures efficiently.
  • P2P Networking Node ID: This is a unique identifier for each validator node in the network, allowing them to establish and maintain connections with other nodes.

Cloud Deployment

. Amazon Web Services- To set up a devnet on AWS, you can refer to the AWS deployment guide available here.

. Microsoft Azure- To set up a devnet on Azure, you can refer to the Azure deployment guide available here.

4. Configure the initial childchain state by generating a new genesis file.

The genesis file is a critical component in setting up a blockchain network, containing the initial validator set, genesis block, and other essential parameters that define the network’s behavior. The initial validator set is responsible for bootstrapping the consensus mechanism, allowing the blockchain to function and reach consensus on new blocks.

Supernets allow for customizable parameters such as the block gas limit, epoch size, and block rewards, which enable network operators to tailor the network to specific requirements. Additionally, Supernets support allowlists and blocklists for transactions and validators, providing an extra layer of control and security to the network. These lists can be used to restrict or permit specific addresses, ensuring only authorized parties can participate in the network or execute transactions.

To create the chain configuration, we use the polygon-edge genesis command, which generates the genesis file.

Deployment Considerations

A) Difference between chain-id and supernet-id

Supernets differentiates chain-id and supernet-id within the genesis file.

  • The chain-id is a unique identifier for a childchain.
  • The supernet-id is a unique identifier that is automatically populated during the Supernet's registration process with the StakeManager contract. There can be multiple Supernets registered within the same StakeManager - the supernet-id is used to distinguish them.

Users can assign a custom chain-id to their Supernet via the genesis command. However, supernet-id doesn't function as a flag within this command. Instead, its value is derived from the rootchain deploy command during the Supernet's registration process with the StakeManager contract.

B) Create a Native Token and Premine

--premine : Specify pre mined accounts and their balances. Use the flag multiple times for multiple accounts.

--native-token-configConfigure the native token, including its name, symbol, decimal count, and whether it is mintable.

There is also an --owner flag only applicable for mintable native tokens and designates the account that has permission to mint and burn tokens, in addition to the predicate.

C) Enable EIP1559

--burn-contract: Specify the burn contract address to enable the London hard fork and set where fees will be sent.

--genesis-base-fee:Set the initial base fee (in GWEI) for the genesis block.

Specify Validator Set & Generate Genesis

There are two ways to specify the initial validator set:

  • Single-Host Validator Setup: All validator information is present in the local storage of a single host. In this case, you can provide the directory using the --validators-path flag and the validator folder prefix names using the --validators-prefix flag. To enable reward distribution, you must define a reward wallet address and its balance using the --reward-wallet flag. The wallet address is used to distribute reward tokens from that address to validators that signed blocks in that epoch.
  • Multi-Host Validator Setup: Validator information is scattered across multiple hosts. In this case, you can supply the necessary information using the --validators flag.

5. Configure the associated rootchain of the Supernet and deploy the necessary rootchain core contracts.

After generating the initial chain state for your Supernet, the next step is to connect and initialize the rootchain contracts. This can be done using either a demo Geth instance or any EVM-compatible rootchain. The demo Geth instance is a local instance of a Geth node running in development mode, which simulates the Ethereum network and is only intended for testing purposes.

A) Deploy and initialize rootchain contracts

i. Start the geth node

The polygon-edge rootchain server command starts an Ethereum/client-go container, which runs a new Geth node. To do this, open a new terminal session and run:

./polygon-edge rootchain server

This will start the root chain server on the default JSON-RPC port of 8545.

ii. Deploy StakeManager contract

If the StakeManager hasn't been deployed to the rootchain, you need to carry out this step. This command also contains a test flag. This flag is strictly for testing purposes, and its usage results in deploying a mock ERC-20 token that will serve for staking.

./polygon-edge polybft stake-manager-deploy \
--private-key <hex_encoded_rootchain_account_private_key> \
--genesis ./genesis.json \
--jsonrpc http://127.0.0.1:8545 \
--stake-token 0xaddressOfStakeToken \
--test

B) Deployment Considerations

To deploy the rootchain contracts, we use the polygon-edge rootchain deploy command. Before deployment, consider the following actions:

i. Funding required for nodes

Before initializing the contracts on the rootchain, we need to make sure that the nodes are funded with sufficient funds to cover the gas cost of deploying the contracts. Otherwise, the initialization process may fail due to a lack of funds.

Note that the demo server already funds the default test account. If you’re not omitting, ensure that you pass the correct key; otherwise, you may encounter an error due to insufficient funds, such as the following:

failed to deploy rootchain contracts: {"code":-32000,"message":"INTERNAL_ERROR: insufficient funds"}

You can also create a root chain wallet and fund the nodes by using polygon-cli. Follow the steps outlined here.

ii. Using an existing ERC-20 as the native gas token

If you already have an ERC-20 token deployed on the root chain that you want to use as the gas token, you can specify its address using the --erc20-token flag when deploying the rootchain contracts.

To deposit a desired amount and mint it on the childchain, please refer to the guidelines outlined in the deposit guide here.

C) Deploy root chain contracts

Using the --deployer-key flag, you will need to replace <hex_encoded_deployer_private_key> with the hex-encoded private key of the deployer account that will be used to deploy the smart contracts. If you omit the --deployer-key option, the default account in your local client will be used.

To run the deployment in test mode and use the test account provided by the Geth dev instance as the depositor, add the --test flag. In this case, you may omit the --deployer-key flag, and the default test account will be used as the depositor.

./polygon-edge rootchain deploy \
--stake-manager $(cat genesis.json | jq -r '.params.engine.polybft.bridge.stakeManagerAddr') \
--stake-token $(cat genesis.json | jq -r '.params.engine.polybft.bridge.stakeTokenAddr')
--test

The above example will get the stake-manager and stake-token addresses directly from your genesis.json file.

D) Funding validators on the root chain

Before deploying validator nodes on the Supernet, we need to ensure that the validators have sufficient funds on the rootchain network. It’s crucial to have enough funds in the validator account, as they need to cover the gas fees associated with their transactions on the rootchain.

To fund the validators’ accounts on the rootchain, we use the polygon-edge rootchain fund command. When executed with the appropriate flags, it will:

  1. Retrieve the validator account from the secrets manager.
  2. Send a transaction to fund the validator account on the rootchain with a value of 10,000 $token (the network’s native token).
  3. Repeat steps 1 and 2 for each validator.

It’s important to note that this command is also for testing purposes only.

In a production environment, you would need to ensure that the validators have sufficient funds on the rootchain network to cover the gas fees associated with their transactions.

Here’s an example of how to fund a validator account (replace address value with your own):

./polygon-edge rootchain fund --addresses 0x77C1eedFf656477462ce16084fE5Dc7F8a2507B9 --amounts 1000000000000000000

5. Configure the initial rootchain validator set through allowlisting and by staking.

A) Allowlist validators on the root chain

The CustomSupernetManager contract on the rootchain is responsible for managing the PolyBFT network.

Before validators can be registered on the CustomSupernetManager contract on the rootchain, they need to be allowed by the deployer of the CustomSupernetManager contract. Validators can register themselves, or a registrator can register them on their behalf. Once registered, validators can stake and start validating transactions.

This can be done using the polygon-edge polybft whitelist-validators command. The deployer can specify the hex-encoded private key of the CustomSupernetManager contract deployer or use the --data-dir flag if they have initialized their secrets.

In the following example command, we are using a placeholder private key for the CustomSupernetManager contract deployer.

The --addresses flag is a comma-separated list of the first two validators generated earlier. The --supernet-manager flag specifies the actual CustomSupernetManager contract address that was deployed.

./polygon-edge polybft whitelist-validators \
--private-key 0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef \
--addresses 0x61324166B0202DB1E7502924326262274Fa4358F,0xFE5E166BA5EA50c04fCa00b07b59966E6C2E9570 \
--supernet-manager 0x75aA024A2292A3FD3C17d67b54B3d00435437246

B) Register validators on the root chain

Each validator needs to register themselves on the CustomSupernetManager contract. This is done using the polygon-edge polybft register-validator command. Note that this command is for testing purposes only.

./polygon-edge polybft register-validator --data-dir ./test-chain-1 \
--supernet-manager --supernet-manager 0x75aA024A2292A3FD3C17d67b54B3d00435437246

C) Initial staking on the root chain

Each validator needs to perform initial staking on the rootchain StakeManager contract. This is done using the polygon-edge polybft stake command. Note that this command is for testing purposes only.

In the following example command, we use the validator key and the rootchain StakeManager contract address that was generated earlier. We also set the staking amount 1000000000000000000 which is equivalent to 1 token. The --native-root-token flag is used to specify the address of the native token of the rootchain.

./polygon-edge polybft stake \
--data-dir ./test-chain-1 \
--chain-id 100 \
--amount 1000000000000000000 \
--stake-manager 0x6ceCFe1Db48Ab97fA89b06Df6Bd0bBdE6E64e6F7 \
--native-root-token 0x559Dd13d8A3CAb3Ff127c408f2A08A8a2AEfC56c

D) Finalize the validator set on the root chain

After all validators from the genesis block have been performed initial staking on the root chain, the final step required before starting the chain is to finalize the genesis validator set on the SupernetMagnet contract on the root chain. This can be done using the polygon-edge polybft supernet command.

The deployer of the SupernetManager contract can specify their hex-encoded private key or use the --data-dir flag if they have initialized their secrets. If the --enable-staking flag is provided, and validators will be able to continue staking on the rootchain. If not, genesis validators will not be able to update their stake or unstake, nor will newly registered validators after genesis be able to stake tokens on the rootchain. The enabling of staking can be done through this command or later after the Supernet starts.

In the following example command, we use a placeholder hex-encoded private key of the SupernetManager contract deployer. The addresses of the SupernetManager and StakeManager contracts are the addresses that were generated earlier. We also use the --finalize-genesis and --enable-staking flags to enable staking and finalize the Genesis state.

./polygon-edge polybft supernet --private-key 0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef \
--genesis /path/to/genesis/file \
--supernet-manager 0x75aA024A2292A3FD3C17d67b54B3d00435437246 \
--stake-manager 0x811068e4106f7A70D443684FF4927eC3940439Ec \
--finalize-genesis --enable-staking

6. Run the Supernet cluster of Edge clients. In this example, we’ll run a cluster of four Edge clients.

To run a Supernet cluster, we use the polygon-edge server command with the following options:

./polygon-edge server --data-dir ./test-chain-1 --chain genesis.json --grpc-address :5001 --libp2p :30301 --jsonrpc :10001 --seal --log-level DEBUG
./polygon-edge server --data-dir ./test-chain-2 --chain genesis.json --grpc-address :5002 --libp2p :30302 --jsonrpc :10002 --seal --log-level DEBUG./polygon-edge server --data-dir ./test-chain-3 --chain genesis.json --grpc-address :5003 --libp2p :30303 --jsonrpc :10003 --seal --log-level DEBUG./polygon-edge server --data-dir ./test-chain-4 --chain genesis.json --grpc-address :5004 --libp2p :30304 --jsonrpc :10004 --seal --log-level DEBUG

In conclusion, the blog helps you build your own custom blockchain using the Polygon Supernet, By leveraging the capabilities of Polygon’s layer 2 solutions, you can create smart contracts that not only provide fast and cost-effective transactions but also contribute to the broader ecosystem of decentralized applications. Whether you’re a developer looking to innovate or a business seeking to optimize operations, Polygon Supernet’s infrastructure and tools open up a world of possibilities for creating next-generation blockchain solutions. Embrace the future of blockchain technology with Polygon Supernet and start transforming your ideas into reality today.

FABC is the world’s first web3.0 global skill exchange platform, our council is an embodiment of the community that also provides job opportunities, encompassing the spectrum of innovators, change-makers, and pioneers. we are committed to Uncover blockchain’s core with hands-on lessons, making complex concepts accessible to all. Lay the groundwork for confident exploration in the blockchain realm. Learn more about us at FABC and discover how we’re contributing to the industry/solving problems/making a difference.

Explore the array of courses we offer from our official website:

https://fabc.global/allCourse.

--

--

FABC LLC

FABC-First Academy of Blockchain Council, The World's first global web 3.0 skill exchange platform.