Four genuine blockchain use cases
In this project, you will make your own private blockchain.
The coins we create won't be publicly traded, and they won't be worth any real money. The purpose of this project is merely to learn how blockchain technology works, not to get rich quick.
MultiChain is by far the best blockchain software I have encountered. It has clear instructions that actually work without problems. That is almost unheard-of in the world of open-source software, and especially blockchain software. These folks really know what they are doing, as far as I can tell!
cd /tmp
wget http://www.multichain.com/download/multichain-1.0-alpha-21.tar.gz
tar -xvzf multichain-1.0-alpha-21.tar.gz
cd multichain-1.0-alpha-21
sudo mv multichaind multichain-cli multichain-util /usr/local/bin
Choose one of your Ubuntu machines to be the
"First Server".
Note: It's surprising to me that they deliver the software over http instead of https, and that they don't verify a hash value or signature. I'd like to see a more secure software distribution channel than this, as a future upgrade.
multichain-util create chain1
View the blockchain's default settings (these can also be modified but we recommend using the defaults for now):
cat ~/.multichain/chain1/params.dat
Initialize the blockchain, including mining the genesis block:
Interesting parameters
target-block-time = 15Target time between blocks (transaction confirmation delay), seconds. (5 - 86400) This is far faster than Bitcoin's 10-minute delay, which should make it far more useful for real-time transaction processing.
maximum-block-size = 1000000Maximum block size in bytes. (1000 - 1000000000) This is the infamous "block size" parameter that is causing a crisis on the Bitcoin blockchain now (June, 2016). Bitcoin is almost at its limit of transactions per block. With this value, and the 15-second delay above, this blockchain should be able to handle 40 times as many transactions per day as Bitcoin, assuming that the transaction size is the same as Bitcoin.
skip-pow-check = falseSkip checking whether block hashes demonstrate proof of work. This blockchain will force miners to work hard and prove it. This seems like a critical adjustment to me. Requiring proof-of-work makes it more expensive for legitimate miners, but it also requires attackers to work harder to corrupt the blockchain.
pow-minimum-bits = 16Initial and minimum proof of work difficulty, in leading zero bits. (1 - 32) This means that each miner will have to calculate 2^16 hashes on average, hunting for a valid one to sign a block with. For comparison, the current bitcoin difficulty is 69.53 bits. So it seems like a default Multichain is far easier to mine than Bitcoin, at least at first. And it also seems like the real difficulty will rapidly rise above 32 bits, if there's a free market of competing miners, and the asset value is comparable to a Bitcoin.
target-adjust-freq = 86400Interval between proof of work difficulty adjustments, in seconds. (3600 - 4294967295) Bitcoin adjusts its difficulty every 14 days . This blockchain will adjust its difficulty every day. That seems sensible; roughly in accordance with the 15 second transaction delay.Network Ports
default-network-port = 2645Default TCP/IP port for peer-to-peer connection with other nodes.
default-rpc-port = 2644Default TCP/IP port for incoming JSON-RPC API requests. MultiCoin warns users not to change these values. It's useful to know what ports are used, so we can examine traffic with netstat, tcpdump, and wireshark later.
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.
Make a note of your node address. In the figure below, it is
chain1@172.16.1.135:2645
multichaind chain1@172.16.1.135:2645
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.
Make a note of the wallet address which appears
at the end of the "multichain-cli" commands
at the bottom of this message. In the figure
below, it's
1563sRd7muFNrVumhsX9RNF3hBohba1wcKmSx2
Back on the first server, add connection permissions for this address:
multichain-cli chain1 grant 1563sRd7muFNrVumhsX9RNF3hBohba1wcKmSx2 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.
multichain-cli chain1
You should see a "chain1:" prompt,
as shown below.
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:
getinfo
as shown below.
See a list of all available commands:
help
The commands are very similar to bitcoin-cli,
as shown below.
To see more information about a specific command, enter "help" followed by the command name, like this:
help listwallettransactions
There's a lot of useful information here
as shown below. At the bottom
there are JSON versions of the commands, too
(not shown in the image below).
Show all permissions currently assigned:
listpermissions
The first item is the "connect" permission
I assigned to the other node earlier.
After that there are many entries showing my First Server with many permissions, such as "mine" and "admin".
Create a new address in the wallet:
getnewaddress
Just as in bitcoin-cli, this displays a
new address that can be used to receive
assets,
as shown below.
List all addresses in the wallet:
getaddresses
There are now two addresses:
the first one is the new one
revealed
by the "getnewaddress" command,
and
the second one is the address
we saw earlier
with the "mine" and "admin" permissions.
Get the parameters of this blockchain (based on params.dat file):
getblockchainparams
These are the same parameters we
saw previously.
For each node, get a list of connected peers:
getpeerinfo
There's only one peer right now,
as shown below.
listpermissions issue
Make a note of this address. In the figure
below, it's
15QnvP19xxVgseXX3tJ5XwcUDbhkP8GmSi7FZ7.
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.
On your First Server, execute this command, using the address you noted in the previous step.
issue 15QnvP19xxVgseXX3tJ5XwcUDbhkP8GmSi7FZ7 asset1 1000 0.01
On both servers, verify that the asset named asset1 is listed:
listassets
Now check the asset balances on the First Server:
gettotalbalances
The First Server has 1000 units of "asset1",
as shown below.
Now check the asset balances on the Second Server:
gettotalbalances
The Second Server doesn't have any "asset1",
as shown below.
On the first server, now try sending 100 units of the asset to the second server's wallet. The address here is the address of your Second Server, which you found back in section "2. Connecting to a blockchain".
sendassettoaddress 1563sRd7muFNrVumhsX9RNF3hBohba1wcKmSx2 asset1 100
The transaction fails, because the Second Server's
address doesn't have "receive permission",
as shown below.
So let's add receive and send permissions. On your First Server, execute this command, using your Second Server's address:
grant 1563sRd7muFNrVumhsX9RNF3hBohba1wcKmSx2 receive,send
The grant succeeds,
as shown below.
Now try sending the asset again. On your First Server, execute this command, using your Second Server's address:
sendassettoaddress 1563sRd7muFNrVumhsX9RNF3hBohba1wcKmSx2 asset1 100
Now there's no error message,
as shown below.
Note: the transaction that created the asset requires 30 seconds or so for confirmation.On the First Server, execute this command to check its asset balances:If you are working really fast, you may see another error at this point. If that happens, wait 30 seconds and try again.
gettotalbalances
The First Server has 900 units of "asset1"
left,
as shown below.
On the Second Server, execute this command to check its asset balances:
gettotalbalances
The Second Server has 100 units of "asset1",
as shown below.
On the First Server, execute this command to see the most recent transaction.
listwallettransactions 1
This transaction has "qty" of -100,
indicating that the First Server lost
100 units of asset1,
as shown below.
On the Second Server, execute this command to see the most recent transaction.
listwallettransactions 1
This transaction has "qty" of 100,
indicating that the First Server gained
100 units of asset1,
as shown below.
help sendwithmetadata
We can include metadata in a transaction, but it
has to be in hexadecimal format,
as shown below.
Let's send 125 units of asset1 along with metadata of "deadbeef". On your First Server, execute this command, using the address of your Second Server.
sendwithmetadata 1563sRd7muFNrVumhsX9RNF3hBohba1wcKmSx2 '{"asset1":125}' deadbeef
The transaction succeeds, and returns a Transaction ID,
as shown below.
To examine the transaction, execute this command on your Second Server, using that Transaction ID:
getwallettransaction 8197e05c7eb34856b9bf9b17aaceedfa5ce2b11a86212719608ce30f92484683
The "qty" and "data" fields appear,
as shown below.
First let's create the second asset with 10 indivisible units. On your First Server, execute this command, using the address you noted in section "4. Using native assets":
issue 15QnvP19xxVgseXX3tJ5XwcUDbhkP8GmSi7FZ7 asset2 10 1
The command completes without errors,
as shown below.
On your First Server, check your assets:
listassets
Your blockchain now contains two types of assets:
1000 units of asset1, and 10 units of asset2,
as shown below.
We are going to swap 50 units of asset1 for 1 unit of asset2. To do this, we will begin building the exchange transaction on the First Server, then complete it on the Second Server.
On the First Server, create a locked transaction output containing 1 unit of asset2:
preparelockunspent '{"asset2":1}'
The response includes a "txid" value, and
a "vout" value,
as shown below.
Because it is locked, this transaction output will be protected against spending unless explicitly spent or unlocked. Now we will use it to start the exchange transaction, specifying that we want 50 units of asset1 in exchange for this output.
On the First Server, execute this command, using the "txid" you got from the previous command. The "0" is the "vout" value, which is probably the same on your system.
createrawexchange 9895f9da49d95b8ee489a2cbee92983e4368f8d522e02679604c823ef1375b3b 0 '{"asset1":50}'
as shown below.
This will output a large hexadecimal blob of text that contains the raw transaction data representing the offer of exchange. Copy this blob from the first server, then on the second server, run:
decoderawexchange [paste-hex-blob]
as shown below.
The output will show you exactly what is represented by this exchange offer in the offer and ask sections. In addition, "cancomplete" should be "true" meaning that the second server has the assets required to complete the exchange.
Now on the second server, create a locked transaction output containing 50 units of asset1:
preparelockunspent '{"asset1":50}'
Note the "txid" and "vout" values returned,
as shown below.
Now we will prepare the exchange transaction. On your Second Server, execute this command, using your hex-blob, and the "txid" and "vout" values returned by the previous command:
appendrawexchange [paste-hex-blob] a7676682a1db07fa7d359b8791bb2f2b718b200ae5ad27118f0fc26cc8fdcb8ae 1 '{"asset2":1}'
The output should contain an even longer hexadecimal blob of text, alongside another field "complete" whose value is "true",
as shown below.
This final hex blob is a raw transaction representing the completed exchange. On your Second Server, execute this command to send the transaction to the network:
sendrawtransaction [paste-longer-hex-blob]
The response contains a regular transaction ID,
as shown below.
To verify that the exchange was successful, on your First Server, execute this command:
gettotalbalances 0
The First Server now has 825 units of asset1 and
9 units of asset2,
as shown below.
To verify that this is correct, let's review the transactions we've performed.
We created 1000 units of asset1 on the First Server.So the First Server should have:
We sent 100 units of asset1 to the Second Server.
We sent 125 more units of asset1 to the Second Server with metadata.
We created 10 units of asset2 on the First Server.
We sent 1 unit of asset2 to the Second Server and received 50 units of asset1 in exchange.
1000 - 100 - 125 + 50 = 825 units of asset1 andAs you can see above, the balances are correct on the First Server.
10 - 1 = 9 units of asset2
The Second Server should have:
100 + 125 - 50 = 175 units of asset1 andOn your Second Server, execute this command:
1 unit of asset2
gettotalbalances 0
The balances are correct,
as shown below.
The last exchange of assets was performed atomically in a single transaction, which you can view on either server using:
listwallettransactions 1
as shown below.
On your First Server, execute this command, using the address of your Second Server from the "2. Connecting to a blockchain" section:
grant 1563sRd7muFNrVumhsX9RNF3hBohba1wcKmSx2 mine
The command completes without error,
as shown below.
On the Second Server, execute this command to see how many permitted miners there are:
listpermissions mine
There are two addresses listed,
as shown below.
Now wait for a couple of minutes, so that a few blocks are mined. On either server, check the current block height:
getinfo
Find the number of blocks,
as shown below.
Now get the hashes of the last few blocks, with commands like this:
getblockhash 1027
getblockhash 1026
getblockhash 1025
as shown below.
For each hash, get more information about the block:
getblock [block-hash]
When I did it, blocks 1027, 1026, and 1025 were all from the same
miner, but block 1024 was from the other miner,
as shown below. It's a race between the miners,
so they each have a 50% chance of winning, if both machines
have the same processing power.