Making a Blockchain Survey with Multichain

What you Need

Purpose

To practice using Multichain for a simple practical application: a survey.

Concept

Right now, people vote by mail or in person, but they can't verify that their vote was correctly recorded. Then they wait till other people add up the votes, and tell them who won, and they can't verify the accuracy of that process either.

Here's how I propose to use Blockchains to create a better system.

Each voter has a computer connected to a blockchain, and each polling station does too, like this:

          

Voting works like this:

  1. Each voter is mailed a card with an unique random ID number.
  2. The voter installs the blockchain software and joins the blockchain.
  3. The voter goes to a faucet and gets a token, using the ID number. Each ID number is only allowed to get one token.
  4. The voter can vote online by sending the token to the account of the candidate they prefer. That voter cannot vote again, but the voter can examine the blockchain to verify that the vote was correctly recorded, and also see the total votes for each candidate at any time.
  5. If a voter can't or won't vote online, the voter can go in person to a polling place. Every polling place has the same blockchain, so they can verify that the voter has not yet voted. If the voter lost the card, or never received it, the polling place can verify that the token has not already voted, invalidate it, and assign that person a new token.
  6. Mining will be done by machines that are chosen somehow to represent all stakeholders, such as one miner per candidate, or per political party, or per county.

In this project, we'll have one Voter and one Polling station, and the Polling station will be the only miner. We'll only implement the online voting method, for now.

Install Multichain on the Poll Server

Pick one machine to be the Poll Server.

On that machine, in a Terminal window, execute these commands:

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 

Creating a Blockchain on the Poll Server

First we will create a new blockchain named "survey". On the Poll Server, run this command:
multichain-util create survey

Adjusting Blockchain Settings

On the Poll Server, run this command:
nano ~/.multichain/survey/params.dat
In the "Global permissions" section, change these four parameters, as shown below.
anyone-can-connect = true
anyone-can-send = true

allow-p2sh-outputs = false
allow-multisig-outputs = false

In the "Consensus requirements" section, change this parameter, as shown below.
setup-first-blocks = 10000

          

Save the file with Ctrl+X, Y, Enter.

Initialize the Blockchain

On the Poll Server, execute this command:
multichaind survey -daemon
The server starts, and you see 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

survey@172.16.1.134:7413

          

Getting an Address on the Poll Server

On the Poll Server, execute:
multichain-cli survey getnewaddress
An address appears. Make a note of it. In the example below, the address is

1345gLikEVK4KtkZrT6ejmhqvceHGQ2pZdrheX

          

Giving the Poll Server Address Send and Receive Permission

On the Poll server, execute this command. Replace the address with the correct address for your Poll server.
multichain-cli survey grant 1345gLikEVK4KtkZrT6ejmhqvceHGQ2pZdrheX receive,send
The command succeeds, as shown below.

          

Issue the "token" Asset

Now we'll create an asset named "token" which cannot be subdivided, and place 10,000 of them on the Poll server.

On the Poll Server, execute these commands. Replace the address with the correct address for your Poll server.

multichain-cli survey issue 1345gLikEVK4KtkZrT6ejmhqvceHGQ2pZdrheX token 10000 1
multichain-cli survey listassets
The commands succeed, so the Poll server now has 10,000 tokens, as shown below.

          

          

Install Apache on the Poll Server

On the Poll Server, execute:
sudo apt-get update
sudo apt-get install apache2 -y
sudo service apache2 start

Install PHP on the Poll Server

On the Poll Server, execute:
sudo apt-get install php5 libapache2-mod-php5 php5-mcrypt php5-cli -y

Find your RPC Credentials

On the Poll Server, execute:
cat ~/.multichain/survey/multichain.conf 
Your RPC username and password appear, as shown below. Make a note of them--you will need them later.

          

Make info.php

This script performs the "getinfo" method and prints the results three ways, to demonstrate how to excute a method and how to retrieve the results.

On the Poll Server, execute:

sudo nano /var/www/html/info.php
Enter or paste in this code. You will need to change two items:

1. Replace the password in the line beginning with "$a" with the correct password on your Poll Server
2. Replace the port number at the end of the line beginning with "$c" with the actual port number on your server.

<?php
echo "<h1>Information About the Survey Blockchain</h1>";

$a = 'curl -s --user multichainrpc:FHtgQdshp7bo96gNv4MtT64cQwj1inTQAEuonr5jG7hv --data-binary \'';
$b = '{"jsonrpc": "1.0", "id":"curltest", "method": "getinfo", "params": [';
$c = '] }\' -H "content-type: text/plain;" http://127.0.0.1:7412/';
$cmd = $a . $b . $c;

echo "\n<h2>Raw Output</h2><pre>\n";
$ret=system($cmd);

echo "\n<h2>Decoded Output</h2>\n";
$rets = json_decode($ret, true);
print_r($rets);

echo "\n<h2>Single-Item Output</h2>\n";
echo $rets['result']['version'];
?>

          

Save the file with Ctrl+X, Y, Enter.

To test the script, on the Poll Server, execute:

php /var/www/html/info.php
You should see the same information three different ways, as shown below.

          
          

Make a pay.php Script

This script will send 1 token to a specific address.

On the Poll Server, execute:

sudo nano /var/www/html/pay.php
Enter or paste in this code.

Enter or paste in this code. You will need to change two items:

1. Replace the password in the line beginning with "$a" with the correct password on your Poll Server
2. Replace the port number at the end of the line beginning with "$d" with the actual port number on your server.

<?php

echo "<h1>Sending you a Survey Token!</h1>";
$addr = $_POST["address"];

$a = 'curl -s --user multichainrpc:FHtgQdshp7bo96gNv4MtT64cQwj1inTQAEuonr5jG7hv --data-binary \'';
$b = '{"jsonrpc": "1.0", "id":"curltest", "method": "sendassettoaddress", "params": ["';
$c = '", "token", 1';
$d = '] }\' -H "content-type: text/plain;" http://127.0.0.1:7412/';
$cmd = $a . $b . $addr . $c . $d;

$ret=system($cmd);
echo $ret;
?>
          

Save the file with Ctrl+X, Y, Enter.

Make a faucet.htm Page

On the Poll Server, execute:
sudo nano /var/www/html/faucet.htm
Enter or paste in this code.
<html><head><title>Survey Token Faucet</title></head>
<body bgcolor="#cccccc">
<h1 align="center">Survey Token Faucet</h1>

<form method="post" action="pay.php">
<p align="center"><b>Enter your address</b></p>
<p align="center"><input type="text" name="address" size="90"></textarea></p>
<p align="center">
<button type="submit" name="submitButton" value="">Get Token</button>
</form> 

</body></html>
          

Save the file with Ctrl+X, Y, Enter.

Install Multichain on the Voter

Your other Linux machine will be the Voter.

On that machine, in a Terminal window, execute these commands:

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 

Connecting the Voter to the Blockchain

On the Voter, run the following command, replacing the node address with your own value:
multichaind survey@172.16.1.134:7413 -daemon
Your node connects, and shows a "Node started" message, as shown below.

          

Getting an Address

On the Voter, run the following command:
multichain-cli survey getnewaddress
An address appears. Make a note of it. In the example below, the address is

1Vf3VdFjgfnEJLM812A8EY35gUbzPP5b897X8r

          

Using the Faucet

On the Voter, open a Web browser and go to this address, replacing the IP address with the IP address of your Poll Server. You used this address just a few steps above to connect to the blockchain.
172.16.1.134/faucet.htm
Paste your address into the Faucet page, as shown below.

          

Click the "Get Token" button.

An error message appears, showing that the address doesn't have receive permission.

          

Make pay2.php

We don't want Voters sending tokens to one another, so we don't want the Voters to have receive permission all the time.

What we really want is to grant the Voter receive permission just long enough to receive 1 token, and then revoke it.

Looking at the MultiChain JSON-RPC API commands reveals that there are commands to do precisely that.

On the Poll Server, execute:

sudo nano /var/www/html/pay2.php
Enter or paste in this code.
<?php
echo "<h1>Sending you a Survey Token!</h1>";
$addr = $_POST["address"];

$a = 'curl -s --user multichainrpc:FHtgQdshp7bo96gNv4MtT64cQwj1inTQAEuonr5jG7hv --data-binary \'';
$b = '{"jsonrpc": "1.0", "id":"curltest", "method": "grant", "params": ["';
$c = '", "receive"';
$d = '] }\' -H "content-type: text/plain;" http://127.0.0.1:7412/';
$cmd = $a . $b . $addr . $c . $d;
$ret=system($cmd);

$a = 'curl -s --user multichainrpc:FHtgQdshp7bo96gNv4MtT64cQwj1inTQAEuonr5jG7hv --data-binary \'';
$b = '{"jsonrpc": "1.0", "id":"curltest", "method": "sendassettoaddress", "params": ["';
$c = '", "token", 1';
$d = '] }\' -H "content-type: text/plain;" http://127.0.0.1:7412/';
$cmd = $a . $b . $addr . $c . $d;
$ret=system($cmd);

$a = 'curl -s --user multichainrpc:FHtgQdshp7bo96gNv4MtT64cQwj1inTQAEuonr5jG7hv --data-binary \'';
$b = '{"jsonrpc": "1.0", "id":"curltest", "method": "revoke", "params": ["';
$c = '", "receive"';
$d = '] }\' -H "content-type: text/plain;" http://127.0.0.1:7412/';
$cmd = $a . $b . $addr . $c . $d;
$ret=system($cmd);
?>
          

Save the file with Ctrl+X, Y, Enter.

Editing the faucet.htm Page

The faucet.htm file must be modified to reference the pay2.php script.

On the Poll Server, execute:

sudo nano /var/www/html/faucet.htm
In the form tag, change the action to pay2.php, as shown below.

          

Save the file with Ctrl+X, Y, Enter.

Using the Faucet

On the Voter, in your Web browser, click the Back button to return to the Faucet. Click the Refresh button to reload the page.

Paste in your address, as shown below.

          

Click the "Get Token" button.

Three messages appear, all showing "error:null" -- it worked!

          

Checking your Balance

On the Voter, execute:
multichain-cli survey gettotalbalances
You now have 1 token, as shown below.

          

Getting an Account for Candidate #1

On the Poll Server, execute:
multichain-cli survey getnewaddress
The address appears, as shown below. Make a note of it.

          

On the Poll Server, execute this command. Replace the address with the address you just found.

multichain-cli survey grant 17CFf1ZJV73igpcb2egZRFjGYiabTf21T61kiQ receive
The operation proceeds without errors, as shown below.

          

Getting an Account for Candidate #2

On the Poll Server, execute:
multichain-cli survey getnewaddress
The address appears, as shown below. Make a note of it.

On the Poll Server, execute this command. Replace the address with the address you just found.

multichain-cli survey grant 17CFf1ZJV73igpcb2egZRFjGYiabTf21T61kiQ receive

Making a Candidates Page

On the Poll Server, execute:
sudo nano /var/www/html/candidates.htm
Paste in this code. Replace the addresses with the two addresses you just made.
<html>
<head><title>Candidates</title></head>
<body>

<h2>Candidate #1</h2>
17CFf1ZJV73igpcb2egZRFjGYiabTf21T61kiQ

<h2>Candidate #1</h2>
1CTMCxciVnWCGorSzgErkRjA2ogDK7XF7nT1nG

</body>
</html>
Save the file with Ctrl+X, Y, Enter.

Voting

On the Voter, in a Web browser, and go to this address, replacing the IP address with the IP address of your Poll Server.
172.16.1.134/candidates.htm
You see the candidate addresses, as shown below.

          

To vote, on your Voter Machine, execute this command, replacing the address with one of the addresses from the Candidates page.

multichain-cli survey sendassettoaddress 17CFf1ZJV73igpcb2egZRFjGYiabTf21T61kiQ token 1
The transaction proceeds without errors, as shown below.

          

To check your account balance, on your Voter Machine, execute this command, replacing the address with one of the addresses from the Candidates page.

multichain-cli survey getmultibalances 17CFf1ZJV73igpcb2egZRFjGYiabTf21T61kiQ,1CTMCxciVnWCGorSzgErkRjA2ogDK7XF7nT1nG
Your token is gone, as shown below.

          

Viewing the Election Results

To see the election results, execute these commands on the Poll Server, replacing the addresses with the addresses of your candidates.
multichain-cli survey getaddressbalances 17CFf1ZJV73igpcb2egZRFjGYiabTf21T61kiQ
multichain-cli survey getaddressbalances 1CTMCxciVnWCGorSzgErkRjA2ogDK7XF7nT1nG
As shown below, one candidate has 1 token, and the other has no tokens.

          

Limitations

This system doesn't allow the Voters to independently view the results now. When I tried it, I got an error because those accounts were not in my wallet. It also has no protection against a person voting multiple times right now. Those are improvements that could be made in a later version.

Sources

Customizing blockchain parameters
API reference (JSON-RPC)
Step by step tutorial for leveraging JSON-RPC API?
Bitcoin JSON-RPC Tutorial 5 - Your First Calls - YouTube
EasyBitcoin-PHP GitHub
Unofficial PHP library for interacting with the Multichain JsonRPC interface
How To Install and Use Composer on Ubuntu 14.04
composer-cache file permissions #19
How To Install Linux, Apache, MySQL, PHP (LAMP) stack on Ubuntu 14.04
MultiChain JSON-RPC API commands

Posted 6-18-16 by Sam Bowne