Create and deploy your first private blockchain in minutes

This tutorial requires two server nodes. If you have not done so already, please download and install MultiChain on each server.

1. Creating a blockchain

First we will create a new blockchain named chain1. On the first server, run this command:

multichain-util create chain1

If you are using Windows, first open a DOS command line in the directory where you installed the MultiChain executables. You can do this by navigating to that directory in the Windows Explorer, then typing cmd in the address bar at the top.

View the blockchain’s default settings (these can also be modified but we recommend using the defaults for now):

cat ~/.multichain/chain1/params.dat

On Windows, the parameters file is in %APPDATA%\MultiChain\chain1\params.dat

Initialize the blockchain, including creating the genesis block:

multichaind chain1 -daemon

You should be told that the server has started and then after a few seconds, that the genesis block was found. You should also be given the node address that others can use to connect to this chain.

Copy and paste the node address here:

2. Connecting to a blockchain

Now we’ll connect to this blockchain from elsewhere. On the second server, run the following:


You should be told that the blockchain was successfully initialized, but you do not have permission to connect. You should also be shown a message containing an address in this node’s wallet.

Copy and paste the wallet address here:

Back on the first server, add connection permissions for this address:

multichain-cli chain1 grant connect

Now try reconnecting again from the second server:

multichaind chain1 -daemon

You should be shown a message that the node was started, and it should display this second node’s address.

3. Some commands in interactive mode

Before we proceed, let’s enter interactive mode so we can issue commands without typing multichain-cli chain1 every time. On both servers:

multichain-cli chain1

If you are using Windows, interactive mode is not yet available, so all commands in this guide should be preceded by multichain-cli chain1. You will also need to open another DOS command line in the directory where you installed the MultiChain executables.

Now that the blockchain is working on two nodes, you can run the commands in this section on either or both. To get general information:


See a list of all available commands:


Show all permissions currently assigned:


Create a new address in the wallet:


List all addresses in the wallet:


Get the parameters of this blockchain (based on params.dat file):


For each node, get a list of connected peers:


4. Streams

Now let’s create a stream, which can be used for general data storage and retrieval. On the first server:

create stream stream1 false

The false means the stream can only be written to by those with explicit permissions. Let’s see its permissions:

listpermissions stream1.*

So for now, only the first server has the ability to write to the stream, as well as administrate it. Let’s publish something to it, with key key1:

publish stream1 key1 73747265616d2064617461

The txid of the stream item is returned. Now let’s see that the stream is visible on another node. On the second server:


(The root stream was in the blockchain by default.) Now we want the second server to subscribe to the stream, then view its contents:

subscribe stream1
liststreamitems stream1

Now we want the second server to be allowed to publish to the stream. On the first server:

grant send
grant stream1.write

Note that the address needs both general send permissions for the blockchain, as well as permission to write to this specific stream. Now let’s publish a couple of items on the second server:

publish stream1 key1 736f6d65206f746865722064617461
publish stream1 key2 53747265616d732052756c6521

Now let’s query the stream’s contents in many different ways. Back on the first server:

subscribe stream1
liststreamitems stream1 (should show 3 items)
liststreamkeys stream1 (2 keys)
liststreamkeyitems stream1 key1 (2 items with this key)
liststreampublishers stream1 (2 publishers)
liststreampublisheritems stream1 (2 items by this publisher)

This is just a taste of the ways in which streams can be queried – for more information, please consult the API documentation.

5. MultiChain 2.0 streams

MultiChain 2.0 will add a ton of functionality relating to streams. If you are using MultiChain 2.0 alpha 4 or later, you can preview the new streams functionality in this section. Please skip straight to the next section on assets if you are using MultiChain 1.0.x.

Let’s go back to the first server and publish some data in text and JSON formats, with some items having multiple keys:

publish stream1 key3 '{"text":"hello world!"}'
publish stream1 '["key3","key4"]' '{"json":{"name":"John Doe","city":"London"}}'
publish stream1 '["key3","key4","key5"]' '{"json":{"city":"New York"}}'

If you are using Windows, you need to use a different form of quoting on the command line. Run this instead:
publish stream1 key3 "{\"text\":\"hello world!\"}"
publish stream1 "[\"key3\",\"key4\"]" "{\"json\":{\"name\":\"John Doe\",\"city\":\"London\"}}"
publish stream1 "[\"key3\",\"key4\",\"key5\"]" "{\"json\":{\"city\":\"New York\"}}"

Now let’s list these items on the second server:

liststreamitems stream1 false 3

Within the transactions, the text and JSON data are stored efficiently. Now let’s try summarizing these items using a JSON merge:

getstreamkeysummary stream1 key3 jsonobjectmerge

You should see an error explaining that some items for this key are not in JSON format. So try this instead:

getstreamkeysummary stream1 key3 jsonobjectmerge,ignoreother

Note how the two JSON items are merged together, taking the most recent value for each field within. Many other options for merging are available, as described on the MultiChain 2.0 preview page.

Next let’s run some queries to search for items with different sets of keys:

liststreamqueryitems stream1 '{"keys":["key3"]}'
liststreamqueryitems stream1 '{"keys":["key3","key4"]}'
liststreamqueryitems stream1 '{"keys":["key4","key5"]}'

If you are using Windows, you need to use a different form of quoting on the command line. Run this instead:
liststreamqueryitems stream1 "{\"keys\":[\"key3\"]}"
liststreamqueryitems stream1 "{\"keys\":[\"key3\",\"key4\"]}"
liststreamqueryitems stream1 "{\"keys\":[\"key4\",\"key5\"]}"

Each query returns only those items which have all of the specified keys. It’s also possible to query by publisher(s), or by both key(s) and publisher(s).

Finally let’s build up a large binary object and publish it off-chain (with on-chain hashes verifying its contents). Back on the first server:


Copy and paste the returned identifier here:

Data can be added to the binary cache using the appendbinarycache command as follows:

appendbinarycache 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef

This can be run multiple times, and each time the cache’s total size will be returned. But if you’re using Linux, you can also pipe random data directly to the cache via its file. Open a new Linux command line on the first server and enter the following to add 512 MB of random data:

head -c 536870912 < /dev/urandom >> ~/.multichain/chain1/cache/

This may take a minute or so. Now back in the MultiChain command line, enter the following (this may also take a short while):

publish stream1 key6 '{"cache":""}' offchain

If you are using Windows, you need to use a different form of quoting on the command line. Run this instead:
publish stream1 key6 "{\"cache\":\"\"}" offchain

Copy and paste the displayed transaction ID:

Now on the second server, issue this command:

liststreamkeyitems stream1 key6

You should see the new item listed. If you created a large item on Linux, it should display with "available" : false because all of the off-chain data has not yet arrived. In that case, keep running this to watch the data come in:


Once the chunk queue is empty, the item’s data should be available and you can view its first kilobyte in hexadecimal:

liststreamkeyitems stream1 key6
gettxoutdata 0 1024

6. Assets

Now we are going to create a new asset and send it between nodes. On the first server, get the address that has the permission to create assets:

listpermissions issue

Copy and paste the displayed address here:

Now we’ll create a new asset on this node with 1000 units, each of which can be subdivided into 100 parts, sending it to itself:

issue asset1 1000 0.01

On both servers, verify that the asset named asset1 is listed:


Now check the asset balances on each server. The first should show a balance of 1000, and the second should show no assets at all:


On the first server, now try sending 100 units of the asset to the second server’s wallet:

sendasset asset1 100

You should see an error that the address does not have receive permissions. So it’s time to add receive permissions:

grant receive

Now try sending the asset again, and it should go through:

sendasset asset1 100

Now check the asset balances on each server, including transactions with zero confirmations. They should be 900 and 100 respectively:

gettotalbalances 0

You can also view the transaction on each node and see how it affected their balances:

listwallettransactions 1

7. Combining assets and streams

In this section we’ll create a transaction that sends 125 units of asset1 along with some metadata written to a stream. On the first server, run:

sendwithdata '{"asset1":125}' '{"for":"stream1","key":"transfer","data":"486921"}'

If you are using Windows, you need to use a different form of quoting on the command line. Run this instead:
sendwithdata "{\"asset1\":125}" "{\"for\":\"stream1\",\"key\":\"transfer\",\"data\":\"486921\"}"

Copy and paste the displayed transaction ID:

Now this transaction can be examined on the second server as below:


In the output from this command, you should see the balance field showing the incoming 125 units of asset1 and the items field containing the stream item that was added. You can also view this item directly within the stream:

liststreamitems stream1

8. Round-robin consensus

In this section we’ll start collaborative block validation between the nodes. Note that, in the case of a permissioned MultiChain blockchain, consensus is based on block signatures and a customizable round-robin consensus scheme, rather than proof-of-work as in bitcoin.

On the first server, run:

grant mine

(Even though the permission is called mine note that there is no real “mining” taking place, in the sense of proof-of-work.) On the second server, check that two permitted block validators are listed:

listpermissions mine

Run this on both servers to maximize the degree of validator randomness:

setruntimeparam miningturnover 1

Now wait for a couple of minutes, so that a few blocks are added. (This assumes you left the block time on the default of 15 seconds.) On either server, check the creators of the last few blocks:

listblocks -10

The address of the validator of each block is in the miner field of each element of the response.

Note that this tutorial uses only two validator nodes and the low default value for the mining-diversity blockchain parameter. So each block can be created by either node, and the chain is not secure. A secure chain would use more validator nodes and/or a higher value for this parameter.

9. Now go explore…

Congratulations – you have finished the first tutorial! Now you try any of the other tutorials, create blockchains with different parameters or explore the available API commands. You can also install the Explorer or Web Demo to see a graphical interface for your blockchain.

Finally, you may want to subscribe below for updates. And if you have any questions or problems, please ask in the developer Q&A or contact us.

10. Get product updates (one email per month max)