In this tutorial we will create a subnet on FUji testnet "amafanssubnet". You should have a node connected and synced to Fuji testnet. You can run your validator on the same node or on another node also. For the sake of simplicity, I am going to run the validator node on the same fuji node. Please follow the step by step guide.
curl -OL https://golang.org/dl/go1.18.3.linux-amd64.tar.gz=
sudo tar -C /usr/local -xvf go1.18.3.linux-amd64.tar.gz
Add these path variables in your ~/.bashrc file and reload it
export GOPATH=$HOME/go
export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin
Reload your bashrc for these changes to take effect on the same window.
source ~/.bashrc
Now, Check go version to see if everything is upto the mark.
go version
output: go version go1.18.3 linux/amd64
git clone https://github.com/ava-labs/subnet-cli.git;
cd subnet-cli;
go install -v .;
Use this command to create your private key and fund it using fuji faucet.
I created a new directoty "keys" under my home directory and then ran this command to generate a private key.
cd keys
subnet-cli create key
A new file .subnet-cli.pk will be created with a private key. Copy the private key. By default, subnet-cli uses the key specified in file .subnet-cli.pk on the P-Chain to pay for the transaction fee, If you want to use some other key at some other location on this server, use --private-key-path later to overwrite. Please make sure that you have enough fund on this P-Chain address to pay for transactions.
Use your private key in the .subnet-cli.pk file on the web wallet to access this https://wallet.avax.network/. (Private Key is the first option on the web wallet). And pick Fuji on the top right corner as the network and locate your C-Chain address which starts with 0x. Copy this address.
Request funds from the faucet using your C-Chain address at https://faucet.avax.network/. Wait for the transaction to get confirmed.
!C-chain to P-chain
After following these 3 steps, your test key should now have a balance on the P-Chain on the Fuji Testnet.
First, you'll need to compile the subnet-evm into a binary that AvalancheGo can interact with.
git clone https://github.com/ava-labs/subnet-evm.git
cd subnet-evm/
subnet-cli create VMID amafanssubnetevm
Create a VMID with string amafanssubnetevm which you can change to whatever you like. This command is used to generate a valid VMID based on some string to uniquely identify a VM. This should stay the same for all versions of the VM, so it should be based on a word rather than the hash of some code. Output will be:
created a new VMID juedWvBi73uAL3JgXYPJsD6d2YyVPAg4xv4RRqdCzaWpTsjVj from amafanssubnetevm
Now issue this command to build
./scripts/build.sh build/juedWvBi73uAL3JgXYPJsD6d2YyVPAg4xv4RRqdCzaWpTsjVj
This command will create a binary in the build folder
ubuntu@ip-172-31-90-23:~/subnet-evm$ ls build/
juedWvBi73uAL3JgXYPJsD6d2YyVPAg4xv4RRqdCzaWpTsjVj
Choose option based on how you had built your "avalanchego".
Once the subnet-evm binary is built, you'll need to move it to AvalancheGo's plugin directory (within the --build-dir) so it can be run by your node. When building avalanchego from source (see Run an Avalanche Node Manually ), this defaults to avalanchego/build/plugins in which avalanchego is the directory where you have checked out AvalancheGo project. This build directory is structured as:
build-dir |_avalanchego (note: this is the AvalancheGo binary, not a directory) |_plugins |_evm
To put the subnet-evm binary in the right place, run the following command (assuming the avalanchego and subnet-evm repos are in the same folder):
mv ./subnet-evm/build/juedWvBi73uAL3JgXYPJsD6d2YyVPAg4xv4RRqdCzaWpTsjVj ./avalanchego/build/plugins;
avalanche-node |_avalanchego (note: this is the AvalancheGo binary, not a directory) |_plugins |_evm
mv subnet-evm/build/juedWvBi73uAL3JgXYPJsD6d2YyVPAg4xv4RRqdCzaWpTsjVj avalanche-node/plugins/
Create a Custom Subnet Configuration
avalanche subnet create amafanssubnet
It will present you several options, Let us explore them one by one.
Choose EVM, For our case, use SubnetEVM
ubuntu@ip-172-31-90-23:~$ avalanche subnet create amafanssubnet
Use the arrow keys to navigate: ↓ ↑ → ←
? Choose your VM:
▸ SubnetEVM
Custom
Choose chainID, Choose chainid which is not being used by any existing EVM chains Check here: https://chainlist.org/
Enter your subnet's ChainId. It can be any positive integer.
✗ ChainId: █
Choose Fee
? How would you like to set fees:
Low disk use / Low Throughput 1.5 mil gas/s (C-Chain's setting)
▸ Medium disk use / Medium Throughput 2 mil gas/s
High disk use / High Throughput 5 mil gas/s
Customize fee config
Airdrop Tokens in the beginning of the chain
? How would you like to distribute funds:
Airdrop 1 million tokens to the default address (do not use in production)
▸ Customize your airdrop
Enter your address and the tokens amount. If you want to add more airdrop, Keep clicking on Yes
? Would you like to airdrop more tokens?:
▸ No
Yes
Adding a custom precompile We will revisit this option in later tutorials, Let’s continue with "No" option.
? Advanced: Would you like to add a custom precompile to modify the EVM?:
▸ No
Yes
Click on No and your subnet will be created.
ubuntu@ip-172-31-90-23:~$ avalanche subnet list
+---------------+---------------+-----------+
| SUBNET | CHAIN | TYPE |
+---------------+---------------+-----------+
| amafanssubnet | amafanssubnet | SubnetEVM |
+---------------+---------------+-----------+
By default, all fees are burned (sent to the blackhole address with "allowFeeRecipients": false). However, it is possible to enable block producers to set a fee recipient (who will get compensated for blocks they produce). To enable this feature, you'll need to add the following to your genesis file (under the "config" key):
{
"config": {
"allowFeeRecipients": true
}
}
Fee Recipient With allowFeeRecipients enabled, your validators can specify their addresses to collect fees. They need to update their EVM chain config with the following to specify where the fee should be sent to.
{
"feeRecipient": "<YOUR 0x-ADDRESS>"
}
avalanche subnet describe firstsubnet --genesis
{
"config": {
"chainId": 13665,
"homesteadBlock": 0,
"eip150Block": 0,
"eip150Hash": "0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0",
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"istanbulBlock": 0,
"muirGlacierBlock": 0,
"subnetEVMTimestamp": 0,
"feeConfig": {
"gasLimit": 8000000,
"targetBlockRate": 2,
"minBaseFee": 25000000000,
"targetGas": 20000000,
"baseFeeChangeDenominator": 36,
"minBlockGasCost": 0,
"maxBlockGasCost": 1000000,
"blockGasCostStep": 200000
},
"contractDeployerAllowListConfig": {
"blockTimestamp": null,
"adminAddresses": null
},
"contractNativeMinterConfig": {
"blockTimestamp": null,
"adminAddresses": null
},
"txAllowListConfig": {
"blockTimestamp": null,
"adminAddresses": null
}
},
"nonce": "0x0",
"timestamp": "0x0",
"extraData": "0x",
"gasLimit": "0x7a1200",
"difficulty": "0x0",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": {
"3213ef068d8def86a068d0cbbcbb3c00664894ad": {
"balance": "0x8ac7230489e80000"
},
"9c4c630fab38192bbcc53464a156a59337d75a24": {
"balance": "0x5af3107a4000"
}
},
"airdropHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"airdropAmount": null,
"number": "0x0",
"gasUsed": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"baseFeePerGas": null
}
save this file in your home directory with amafanssubnet_genesis.json
Step 1: You must have a fuji node up and running, Refer to this article to deploy a fuji node on AWS. Get your nodeID by this command
ubuntu@ip-172-31-90-23:~$ curl -X POST --data '{
"jsonrpc":"2.0",
"id" :1,
"method" :"info.getNodeID"
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/info
ubuntu@ip-172-31-90-23:~$ {"jsonrpc":"2.0","result":{"nodeID":"NodeID-167TkRiC6RVLboo5U7TpiB6Sk4UfxN8w2"},"id":1}
Make note of this node-id
Step 2:
subnet-cli wizard \
--node-ids=NodeID-167TkRiC6RVLboo5U7TpiB6Sk4UfxN8w2 \
--vm-genesis-path=amafanssubnet_genesis.json \
--vm-id=juedWvBi73uAL3JgXYPJsD6d2YyVPAg4xv4RRqdCzaWpTsjVj \
--chain-name=amafanssubnet \
--private-key-path keys/subnet-cli.pk
If you see this error
subnet-cli failed insufficient funds: on [P-fuji1j38ncp5r6dpfjlt64et8cnqvcnp4yum4yfxyz6] (expected=1201000000, have=0)
Your address that corresponds to the private key in .subnet-cli.pk doesn’t have sufficient funds. Please refer to the section "Create Keys" above to fund your address.
If everything goes fine, You will see this output
subnet-cli wizard --node-ids=NodeID-167TkRiC6RVLboo5U7TpiB6Sk4UfxN8w2\
--vm-genesis-path=amafanssubnet_genesis.json \
--vm-id=juedWvBi73uAL3JgXYPJsD6d2YyVPAg4xv4RRqdCzaWpTsjVj \
--chain-name=amafanssubnet \
--private-key-path keys/subnet-cli.pk
2022-06-13T18:20:33.498Z info client/client.go:81 fetching X-Chain id
2022-06-13T18:20:33.543Z info client/client.go:87 fetched X-Chain id {"id": "2JVSBoinj9C2J33VntvzYtVJNZdN2NKiwwKjcumHUWEb5DbBrm"}
2022-06-13T18:20:33.543Z info client/client.go:96 fetching AVAX asset id {"uri": "https://api.avax-test.network"}
2022-06-13T18:20:33.564Z info client/client.go:105 fetched AVAX asset id {"id": "U8iRqJoiJm8xZHAacmvYyZVwqQx6uDNtQeP3CQ6fcgQk3JqnK"}
2022-06-13T18:20:33.564Z info client/client.go:107 fetching network information
2022-06-13T18:20:33.590Z info client/client.go:116 fetched network information {"networkId": 5, "networkName": "fuji"}
Ready to run wizard, should we continue?
*--------------------------------*---------------------------------------------------*
| PRIMARY P-CHAIN ADDRESS | P-fuji1j38ncp5r6dpfjlt64et8cnqvcnp4yum4yfxyz6 |
*--------------------------------*---------------------------------------------------*
| TOTAL P-CHAIN BALANCE | 1.9952981 $AVAX |
*--------------------------------*---------------------------------------------------*
| TX FEE | 0.201 $AVAX |
*--------------------------------*---------------------------------------------------*
| EACH STAKE AMOUNT | 1.000 $AVAX |
*--------------------------------*---------------------------------------------------*
| TOTAL STAKE AMOUNT | 1.000 $AVAX |
*--------------------------------*---------------------------------------------------*
| REQUIRED BALANCE | 1.201 $AVAX |
*--------------------------------*---------------------------------------------------*
| URI | https://api.avax-test.network |
*--------------------------------*---------------------------------------------------*
| NETWORK NAME | fuji |
*--------------------------------*---------------------------------------------------*
| NEW PRIMARY NETWORK VALIDATORS | [167TkRiC6RVLboo5U7TpiB6Sk4UfxN8w2] |
*--------------------------------*---------------------------------------------------*
| VALIDATE END | 2023-04-09T18:20:33Z |
*--------------------------------*---------------------------------------------------*
| STAKE AMOUNT | 1.000 $AVAX |
*--------------------------------*---------------------------------------------------*
| VALIDATE REWARD FEE | 2.000 % |
*--------------------------------*---------------------------------------------------*
| REWARD ADDRESS | EXBvhXRVVJhehvXTz7BJvzUtsxsWMrcdy |
*--------------------------------*---------------------------------------------------*
| CHANGE ADDRESS | EXBvhXRVVJhehvXTz7BJvzUtsxsWMrcdy |
*--------------------------------*---------------------------------------------------*
| NEW SUBNET VALIDATORS | [167TkRiC6RVLboo5U7TpiB6Sk4UfxN8w2] |
*--------------------------------*---------------------------------------------------*
| SUBNET VALIDATION WEIGHT | 1,000 |
*--------------------------------*---------------------------------------------------*
| CHAIN NAME | amafanssubnet |
*--------------------------------*---------------------------------------------------*
| VM ID | juedWvBi73uAL3JgXYPJsD6d2YyVPAg4xv4RRqdCzaWpTsjVj |
*--------------------------------*---------------------------------------------------*
| VM GENESIS PATH | amafanssubnet_genesis.json |
*--------------------------------*---------------------------------------------------*
Use the arrow keys to navigate: ↓ ↑ → ←
▸ Yes, let's create! I agree to pay the fee!
No, stop it!
Click on Yes. and you will see the following output
2022-06-13T18:21:03.709Z info client/p.go:405 adding validator {"start": "2022-06-13T18:21:33.678Z", "end": "2023-04-09T18:20:33.000Z", "stakeAmount": 1000000000, "rewardAddress": "EXBvhXRVVJhehvXTz7BJvzUtsxsWMrcdy", "changeAddress": "EXBvhXRVVJhehvXTz7BJvzUtsxsWMrcdy"}
2022-06-13T18:21:03.812Z info platformvm/checker.go:48 polling P-Chain tx {"txId": "4MQfGNN5o7HTTZL562P6NxKoSfVKGiodbh2ehm7oqZ2oavemB", "expectedStatus": "Committed"}
2022-06-13T18:21:03.812Z info poll/poll.go:42 start polling {"internal": "1s"}
2022-06-13T18:21:05.948Z info poll/poll.go:66 poll confirmed {"took": "2.136140586s"}
added 167TkRiC6RVLboo5U7TpiB6Sk4UfxN8w2 to primary network validator set (took 2.136140586s)
waiting for validator 167TkRiC6RVLboo5U7TpiB6Sk4UfxN8w2 to start validating 11111111111111111111111111111111LpoYY...(could take a few minutes)
2022-06-13T18:23:36.737Z info client/p.go:131 creating subnet {"dryMode": false, "assetId": "U8iRqJoiJm8xZHAacmvYyZVwqQx6uDNtQeP3CQ6fcgQk3JqnK", "createSubnetTxFee": 100000000}
2022-06-13T18:23:36.850Z info platformvm/checker.go:74 polling subnet {"subnetId": "QWNhddjn6AcebaE8QRwpkL9tgiRmmdFxfHBuWqoKN5pHRWRKV"}
2022-06-13T18:23:36.850Z info platformvm/checker.go:48 polling P-Chain tx {"txId": "QWNhddjn6AcebaE8QRwpkL9tgiRmmdFxfHBuWqoKN5pHRWRKV", "expectedStatus": "Committed"}
2022-06-13T18:23:36.850Z info poll/poll.go:42 start polling {"internal": "1s"}
2022-06-13T18:23:38.966Z info poll/poll.go:66 poll confirmed {"took": "2.11540627s"}
2022-06-13T18:23:38.966Z info platformvm/checker.go:88 finding subnets {"subnetId": "QWNhddjn6AcebaE8QRwpkL9tgiRmmdFxfHBuWqoKN5pHRWRKV"}
2022-06-13T18:23:38.966Z info poll/poll.go:42 start polling {"internal": "1s"}
2022-06-13T18:23:39.028Z info poll/poll.go:66 poll confirmed {"took": "62.183781ms"}
created subnet "QWNhddjn6AcebaE8QRwpkL9tgiRmmdFxfHBuWqoKN5pHRWRKV" (took 2.177590051s)
Now, time for some config changes on your node(s).
Set --whitelisted-subnets=QWNhddjn6AcebaE8QRwpkL9tgiRmmdFxfHBuWqoKN5pHRWRKV and move the compiled VM juedWvBi73uAL3JgXYPJsD6d2YyVPAg4xv4RRqdCzaWpTsjVj to <build-dir>/plugins/juedWvBi73uAL3JgXYPJsD6d2YyVPAg4xv4RRqdCzaWpTsjVj.
When you're finished, restart your node.
Use the arrow keys to navigate: ↓ ↑ → ←
▸ Yes, let's continue! I've updated --whitelisted-subnets, built my VM, and restarted my node(s)!
{"subnetId": "QWNhddjn6AcebaE8QRwpkL9tgiRmmdFxfHBuWqoKN5pHRWRKV"}
open config.json present at ~/.avalanchego/configs/node.json on your fuji node and add following details, Replace whitelisted-subnets with the subnet Id from above.
{
"http-host": "",
"network-id": "fuji",
"public-ip": "44.205.74.92",
"health-check-frequency": "2s",
"log-display-level": "DEBUG",
"log-level": "DEBUG",
"whitelisted-subnets": "QWNhddjn6AcebaE8QRwpkL9tgiRmmdFxfHBuWqoKN5pHRWRKV"
}
Restart your avalanchego service.
Go back to your console where you ran the subnet wizard command. You will see the following lines in continutation.
2022-06-13T18:39:03.126Z info client/p.go:497 creating blockchain {"subnetId": "QWNhddjn6AcebaE8QRwpkL9tgiRmmdFxfHBuWqoKN5pHRWRKV", "chainName": "amafanssubnet", "vmId": "juedWvBi73uAL3JgXYPJsD6d2YyVPAg4xv4RRqdCzaWpTsjVj", "createBlockchainTxFee": 100000000}
created blockchain "j6TJTXGmMWWBvYHsyp1bZrkiSDJVoG4FpaWz4LrTjSjpE6zxN" (took 118.540399ms)
*----------------------------*---------------------------------------------------*
| PRIMARY P-CHAIN ADDRESS | P-fuji1j38ncp5r6dpfjlt64et8cnqvcnp4yum4yfxyz6 |
*----------------------------*---------------------------------------------------*
| TOTAL P-CHAIN BALANCE | 0.8942981 $AVAX |
*----------------------------*---------------------------------------------------*
| URI | https://api.avax-test.network |
*----------------------------*---------------------------------------------------*
| NETWORK NAME | fuji |
*----------------------------*---------------------------------------------------*
| PRIMARY NETWORK VALIDATORS | [167TkRiC6RVLboo5U7TpiB6Sk4UfxN8w2] |
*----------------------------*---------------------------------------------------*
| SUBNET VALIDATORS | [167TkRiC6RVLboo5U7TpiB6Sk4UfxN8w2] |
*----------------------------*---------------------------------------------------*
| SUBNET ID | QWNhddjn6AcebaE8QRwpkL9tgiRmmdFxfHBuWqoKN5pHRWRKV |
*----------------------------*---------------------------------------------------*
| BLOCKCHAIN ID | j6TJTXGmMWWBvYHsyp1bZrkiSDJVoG4FpaWz4LrTjSjpE6zxN |
*----------------------------*---------------------------------------------------*
| CHAIN NAME | amafanssubnet |
*----------------------------*---------------------------------------------------*
| VM ID | juedWvBi73uAL3JgXYPJsD6d2YyVPAg4xv4RRqdCzaWpTsjVj |
*----------------------------*---------------------------------------------------*
| VM GENESIS PATH | amafanssubnet_genesis.json |
*----------------------------*---------------------------------------------------*
This shows that your subnet QWNhddjn6AcebaE8QRwpkL9tgiRmmdFxfHBuWqoKN5pHRWRKV and Blockchain id is j6TJTXGmMWWBvYHsyp1bZrkiSDJVoG4FpaWz4LrTjSjpE6zxN
you can check this url https://explorer-xp.avax-test.network/blockchain/j6TJTXGmMWWBvYHsyp1bZrkiSDJVoG4FpaWz4LrTjSjpE6zxN to see the blockchain and subnet.
!Subnet details
Install nginx for proxy forward port 80 to port 9650
sudo apt-get install nginx
server {
etag off;
ssl_protocols TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_prefer_server_ciphers on;
listen 80;
location / {
proxy_pass http://localhost:9650/;
real_ip_header CF-Connecting-IP;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
add_header X-Frame-Options 'deny' always;
add_header X-Content-Type-Options "nosniff";
add_header X-XSS-Protection '1; mode=block' always;
add_header Cache-Control 'must-revalidate';
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
proxy_redirect off;
#limit_except GET POST PUT { deny all; }
}
location /healthcheck {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
#add_header Access-Control-Allow-Origin *;
return 200;
}
location /home/ubuntu/ {
deny all;
return 403;
}
}
here.
Now access your RPC at http://[your validator elastic ip]/ext/bc/[Blockchain Id]/rpc
