Create a Blockchain

Introduction

One of the core features of Avalanche is the ability to create new blockchains. Avalanche currently supports the creation of new instances of the Avalanche Virtual Machine (AVM) and the Timestamp VM.

In this tutorial, we’ll create a blockchain by creating a new instance of the AVM.

Prerequisites

You will need a running node, a user on the node, and some AVAX in the address controlled by the user. All of that is covered in the Getting Started tutorial.

Next, you need to have your node be a validator on the Primary Network. You can find out how to do that in the Add a Validator tutorial. It is recommended you do that with API calls, since that is the way you will be interacting with your node in the rest of this tutorial.

Create the Subnet

Every blockchain is validated by a subnet. Before you can create a blockchain, you’ll need a subnet to validate it. You can also use a subnet that already exists if you have a sufficient number of its control keys.

Add Validators to the Subnet

The subnet needs validators in it to, well, validate blockchains.

Make sure the subnet that will validate your blockchain has at least snow-sample-size validators in it. (Recall that snow-sample-size is one of the command-line arguments when starting a node. Its default value is 20.)

Create the Genesis Data

Each blockchain has some genesis state when it’s created. Each Virtual Machine has a static API method named buildGenesis that takes in a JSON representation of a blockchain’s genesis state and returns the byte representation of that state. (This isn’t true for some VMs, like the Platform VM, because we disallow the creation of new instances.)

The AVM’s documentation specifies that the argument to avm.buildGenesis should look like this:

{
"genesisData":
{
"assetAlias1": { // Each object defines an asset
"name": "human readable name",
"symbol":"AVAL", // Symbol is between 0 and 4 characters
"initialState": {
"fixedCap" : [ // Choose the asset type.
{ // Can be "fixedCap", "variableCap"
"amount":1000, // At genesis, address A has
"address":"A" // 1000 units of asset
},
{
"amount":5000, // At genesis, address B has
"address":"B" // 1000 units of asset
},
... // Can have many initial holders
]
}
},
"assetAliasCanBeAnythingUnique": { // Asset alias can be used in place of assetID in calls
"name": "human readable name", // names need not be unique
"symbol": "AVAL", // symbols need not be unique
"initialState": {
"variableCap" : [ // No units of the asset exist at genesis
{
"minters": [ // The signature of A or B can mint more of
"A", // the asset.
"B"
],
"threshold":1
},
{
"minters": [ // The signatures of 2 of A, B and C can mint
"A", // more of the asset
"B",
"C"
],
"threshold":2
},
... // Can have many minter sets
]
}
},
... // Can list more assets
}
}

To create the byte representation of this genesis state, call avm.buildGenesis. Your call should look like the one below. Note that this call is made to the AVM’s static API endpoint, /ext/vm/avm.

curl -X POST --data '{
"jsonrpc": "2.0",
"id" : 1,
"method" : "avm.buildGenesis",
"params" : {
"genesisData": {
"asset1": {
"name": "myFixedCapAsset",
"symbol":"MFCA",
"initialState": {
"fixedCap" : [
{
"amount":100000,
"address": "8UeduLccQuSmYiY3fGQEyotM9uXxoHoQQ"
},
{
"amount":100000,
"address": "AgVkHvvDShLumJrzXzkwuHa7rYpewj9Kg"
},
{
"amount":50000,
"address": "AwBDGsUwNdXgVc8XG2E8A8dL3bkoVbkL9"
},
{
"amount":50000,
"address": "AATN8YjgmFjC2jQRq45sEeGcBFXNYPcM8"
}
]
}
},
"asset2": {
"name": "myVarCapAsset",
"symbol":"MVCA",
"initialState": {
"variableCap" : [
{
"minters": [
"AATN8YjgmFjC2jQRq45sEeGcBFXNYPcM8",
"FNqMDYafoDVYQ2o4a7Zd9maJAxcUEieQb"
],
"threshold":1
},
{
"minters": [
"JJSiKQfha9Z2TiMxBZ8XdW9F6KFw8aKS4",
"7jJHY1vZL6AAbCFb97KMLY8nqMQVyd5JG",
"58pM5cEf1wMSncPdCwtQ8tbHs2xdMA4eo"
],
"threshold":2
}
]
}
}
}
}
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/vm/avm

This returns the byte representation of your blockchain’s genesis state:

{
"jsonrpc": "2.0",
"result": {
"bytes": "111TNWzUtHKoSvxohjyfEwE2X228ZDGBngZ4mdMUVMnVnjtnawW1b1zbAhzyAM1v6d7ECNj6DXsT7qDmhSEf3DWgXRj7ECwBX36ZXFc9tWVB2qHURoUfdDvFsBeSRqatCmj76eZQMGZDgBFRNijRhPNKUap7bCeKpHDtuCZc4YpPkd4mR84dLL2AL1b4K46eirWKMaFVjA5btYS4DnyUx5cLpAq3d35kEdNdU5zH3rTU18S4TxYV8voMPcLCTZ3h4zRsM5jW1cUzjWVvKg7uYS2oR9qXRFcgy1gwNTFZGstySuvSF7MZeZF4zSdNgC4rbY9H94RVhqe8rW7MXqMSZB6vBTB2BpgF6tNFehmYxEXwjaKRrimX91utvZe9YjgGbDr8XHsXCnXXg4ZDCjapCy4HmmRUtUoAduGNBdGVMiwE9WvVbpMFFcNfgDXGz9NiatgSnkxQALTHvGXXm8bn4CoLFzKnAtq3KwiWqHmV3GjFYeUm3m8Zee9VDfZAvDsha51acxfto1htstxYu66DWpT36YT18WSbxibZcKXa7gZrrsCwyzid8CCWw79DbaLCUiq9u47VqofG1kgxwuuyHb8NVnTgRTkQASSbj232fyG7YeX4mAvZY7a7K7yfSyzJaXdUdR7aLeCdLP6mbFDqUMrN6YEkU2X8d4Ck3T"
},
"id": 1
}

Create the Blockchain

Now let’s create the new blockchain. To do so, we call platform.createBlockchain. Your call should look like the one below. You have to change subnetID to the subnet that will validate your blockchain, and supply a username that controls a sufficient number of the subnet’s control keys. As a reminder, you can find out what a subnet’s threshold and control keys are by calling platform.getSubnets.

curl -X POST --data '{
"jsonrpc": "2.0",
"method": "platform.createBlockchain",
"params" : {
"subnetID": "KL1e8io1Zi2kr8cTXxvi321pAzfQuUa8tmBfadqpf9K2dc2TT",
"vmID":"avm",
"name":"My new AVM",
"genesisData": "111TNWzUtHKoSvxohjyfEwE2X228ZDGBngZ4mdMUVMnVnjtnawW1b1zbAhzyAM1v6d7ECNj6DXsT7qDmhSEf3DWgXRj7ECwBX36ZXFc9tWVB2qHURoUfdDvFsBeSRqatCmj76eZQMGZDgBFRNijRhPNKUap7bCeKpHDtuCZc4YpPkd4mR84dLL2AL1b4K46eirWKMaFVjA5btYS4DnyUx5cLpAq3d35kEdNdU5zH3rTU18S4TxYV8voMPcLCTZ3h4zRsM5jW1cUzjWVvKg7uYS2oR9qXRFcgy1gwNTFZGstySuvSF7MZeZF4zSdNgC4rbY9H94RVhqe8rW7MXqMSZB6vBTB2BpgF6tNFehmYxEXwjaKRrimX91utvZe9YjgGbDr8XHsXCnXXg4ZDCjapCy4HmmRUtUoAduGNBdGVMiwE9WvVbpMFFcNfgDXGz9NiatgSnkxQALTHvGXXm8bn4CoLFzKnAtq3KwiWqHmV3GjFYeUm3m8Zee9VDfZAvDsha51acxfto1htstxYu66DWpT36YT18WSbxibZcKXa7gZrrsCwyzid8CCWw79DbaLCUiq9u47VqofG1kgxwuuyHb8NVnTgRTkQASSbj232fyG7YeX4mAvZY7a7K7yfSyzJaXdUdR7aLeCdLP6mbFDqUMrN6YEkU2X8d4Ck3T",
"username":"USERNAME",
"password":"PASSWORD"
},
"id": 1
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/P

The response contains the transaction ID:

{
"jsonrpc": "2.0",
"result": {
"txID": "xAd5n5PQFV6RRo8UgH54Gf5tJs8oQdctQS2ygp5F2dKZDckYH",
"changeAddr": "P-avax103y30cxeulkjfe3kwfnpt432ylmnxux8r73r8u"
},
"id": 1
}

Verify Success

After a few seconds, the transaction to create our blockchain should have been accepted and the blockchain should exist (assuming the request was well-formed, etc.)

To check, call platform.getBlockchains. This returns a list of all blockchains that exist.

curl -X POST --data '{
"jsonrpc":"2.0",
"id" :1,
"method" :"platform.getBlockchains",
"params" :{}
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/P

The response confirms that the blockchain was created:

{
"jsonrpc": "2.0",
"result": {
"blockchains": [
{
"id": "AXerNQX7voY2AABaRdTAyXcawBURBR6thPRJp43LtPpZZi6Qz",
"name": "X-Chain",
"subnetID": "11111111111111111111111111111111LpoYY",
"vmID": "jvYyfQTxGMJLuGWa55kdP2p2zSUYsQ5Raupu4TW34ZAUBAbtq"
},
{
"id": "tZGm6RCkeGpVETUTp11DW3UYFZmm69zfqxchpHrSF7wgy8rmw",
"name": "C-Chain",
"subnetID": "11111111111111111111111111111111LpoYY",
"vmID": "mgj786NP7uDwBCcq6YwThhaN8FLyybkCa4zBWTQbNgmK6k9A6"
},
{
"id": "CqhF97NNugqYLiGaQJ2xckfmkEr8uNeGG5TQbyGcgnZ5ahQwa",
"name": "Simple DAG Payments",
"subnetID": "11111111111111111111111111111111LpoYY",
"vmID": "sqjdyTKUSrQs1YmKDTUbdUhdstSdtRTGRbUn8sqK8B6pkZkz1"
},
{
"id": "VcqKNBJsYanhVFxGyQE5CyNVYxL3ZFD7cnKptKWeVikJKQkjv",
"name": "Simple Chain Payments",
"subnetID": "11111111111111111111111111111111LpoYY",
"vmID": "sqjchUjzDqDfBPGjfQq2tXW1UCwZTyvzAWHsNzF2cb1eVHt6w"
},
{
"id": "2SMYrx4Dj6QqCEA3WjnUTYEFSnpqVTwyV3GPNgQqQZbBbFgoJX",
"name": "Simple Timestamp Server",
"subnetID": "11111111111111111111111111111111LpoYY",
"vmID": "tGas3T58KzdjLHhBDMnH2TvrddhqTji5iZAMZ3RXs2NLpSnhH"
},
{
"id": "zpFTwJwzPh3b9N6Ahccy4fXdJFHJJdhGah5z731J6ZspcYKpK",
"name": "My new AVM",
"subnetID": "KL1e8io1Zi2kr8cTXxvi321pAzfQuUa8tmBfadqpf9K2dc2TT",
"vmID": "jvYyfQTxGMJLuGWa55kdP2p2zSUYsQ5Raupu4TW34ZAUBAbtq"
}
]
},
"id": 1
}

Interact With the New Blockchain

You can interact with this new instance of the AVM almost the same way you’d interact with the X-Chain. There are two small differences:

  • The API endpoint of your blockchain is 127.0.0.1:9650/ext/bc/zpFTwJwzPh3b9N6Ahccy4fXdJFHJJdhGah5z731J6ZspcYKpK.

  • Addresses are prepended with zpFTwJwzPh3b9N6Ahccy4fXdJFHJJdhGah5z731J6ZspcYKpK- rather than X-.

In the genesis data we specified that address 8UeduLccQuSmYiY3fGQEyotM9uXxoHoQQ has 100,000 units of the asset with alias asset1. Let’s verify that:

curl -X POST --data '{
"jsonrpc":"2.0",
"id" :1,
"method" :"avm.getBalance",
"params" :{
"address":"zpFTwJwzPh3b9N6Ahccy4fXdJFHJJdhGah5z731J6ZspcYKpK-8UeduLccQuSmYiY3fGQEyotM9uXxoHoQQ",
"assetID":"asset1"
}
}' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/zpFTwJwzPh3b9N6Ahccy4fXdJFHJJdhGah5z731J6ZspcYKpK
```json
{
"jsonrpc": "2.0",
"result": {
"balance": "100000"
},
"id": 1
}