Block chain technology is getting a lot of attention, not just as means to store the ledger of transactions that power cryptocurrencies like Bitcoin, but to encapsulate code and data as “smart contracts”. This post looks at one open-source block chain technology Ethereum and builds a smart contract to demonstrate the strengths of such an approach.

What is a block chain?

A block chain is a data structure that stores time-ordered data in an ever-growing list, like an accounting ledger. The block chain data structure is maintained using a distributed, peer-to-peer network of computers with no central “master”. Each block in the chain contains transactions which represent a change of state in the database; the transfer of funds from one account to another, for example. Transactions are verified by multiple nodes in the network and are eventually stored in blocks in the block chain. Each block contains a signed hash of the contents of the preceding block, making it impossible for a block’s contents to be tampered with. It is possible to traverse the entire block chain to ensure that the hash of one block is stored in the block that follows it.

blockchain

Block chains contain a series of transfers of value from one address to another. An address uniquely identifies an account (or a user) in the system and is in fact a public key whose paired private key belongs only to the user who created the account. Value cannot be transferred from an account without a digital signature that requires the source account’s private key.

As well as securing the list of transactions cryptographically, block chains also provide a distributed consensus of the state of the database. It ensures that value transfers happen once or not at all, giving the application developer the peace of mind that, once stored, their data is both immutable and trusted. The block chain network effectively picks a random node to generate the next block in the chain by giving that privilege to the node that solves a mathematical task that takes a lot of computing power. The node that finds a solution to the problem nominates the next block in the chain and publishes it, where it is verified by others in the network. The winning node is rewarded for this “proof of work” with freshly minted crypto-currency and transaction fees collected from the transactions’ creators. This process is known as “mining” and serves the purpose of:

  • minting new currency – the rate of generation of the currency is strictly governed
  • rewarding the “miners” for verifying transactions and establishing consensus in the network

In practice, mining favours only the very fastest, specialised hardware and an “arms race” develops where miners have to provision more and more hardware to maintain the same rate of currency harvest.

Bitcoin is the most famous practical example of a production block chain. Bitcoin is a cryptocurrency which can be used in exchange for real currencies, or transferred between Bitcoin accounts (wallets) using transactions in the Bitcoin block chain. At the time of writing there are 7000 nodes in the Bitcoin peer-to-peer network.

bitcoin screenshot from https://bitnodes.21.co/

Ethereum and smart contracts

Block chains have some key properties that are appealing to application developers:

  • The block chain is run by other people. If your application stores data in a popular block chain, the application does not need to provide its own storage mechanism for its data. The block chain nodes are incentivised for storage with transaction fees and occasionally mining new currency.
  • Block chains provide a distributed consensus solution, which is hard to implement yourself.
  • Block chains provide anonymity for users. An account ID is a public key, that’s not necessarily directly attributable to a human.
  • “Value” can be transferred from one account to another for a smaller fee that traditional wire transfer mechanisms with real currencies.
  • If the block chain is trusted, then the transactions that are stored in it are trusted too.

The Ethereum project takes the block chain principle and adds the ability to create smart contracts on the block chain—apps that can hold value, store data, and encapsulate code to perform computing tasks. Like Bitcoin, Ethereum has a currency—in this case, called Ether. Ether is mined by nodes that verify transactions before being stored in a shared-consensus block chain. Ether can be transferred between accounts (public keys) and smart contracts themselves.

Smart contracts allow anonymous parties to enter into binding agreements, with each participant having full transparency on the deal being made. Value can be transferred between accounts or held in escrow inside the smart contract itself. As the contract is just code, the application is only limited by the developer’s imagination.

unbreakable vow

Smart contracts by example: smartSponsor

In the rest of this article, we’ll build a smart contract that allows the following account-holders to interact:

  • a charity holding a fund-raising activity, which we’ll call thebenefactor
  • a sponsored runner who wants to raise money for the charity: therunner
  • other users who want to sponsor the runner: thesponsor
  • an Ethereum node that is mining the block chain, verifying transactions: theminer

Our contract (smartSponsor):

  • is created by a runner raising money for a charity by doing a sponsored run
  • when creating the contract, the runner nominates the benefactor of the money raised
  • the runner then invites others to sponsor the run. Users sponsor the runner by calling a function on the smart contract which transfers Ether from the sponsor’s account to the contract, where it is held until further notice
  • during the lifetime of the contract everyone can see who the benefactor is, how much Ether has been raised and from whom (although the sponsors can be anonymous, of course)

smartSponsor schematic

Then one of two things can happen:

  • The run goes to plan and the runner instructs the contract to transfer all of the funds to the benefactor

smartSponsor schematic2

  • The run cannot be undertaken for some reason and the runner instructs the contract to refund the sponsors’ pledges

smartSponsor schematic2

Ethereum allows smart contracts to be defined by writing code in a language called Solidity which is Java-like language where the contract is similar to a Java class—the member variables are stored using block chain transactions and the contract’s methods can be called to interrogate the contract or change its state. As copies of the block chain are distributed to all nodes in the network, anyone can interrogate the contract to glean publicly accessible information from it.

Our contract will have the following methods:

  • smartSponsor – the contract’s constructor. It initialises the contract’s state. The creator of the contract nominates the address of the account that will benefit when the contract is drawn down
  • pledge – can be called by anyone to donate Ether to the sponsorship fund. The sponsor supplies an optional message of support
  • getPot – returns the current total of Ether stored in the contract
  • refund – sends the sponsor money back to the sponsors. Only the contract’s owner can call this function
  • drawdown – sends total value of the contract to the benefactor account. Again, only the contract’s owner can call this function

The idea is to make a contract that is binding; if Ether is transferred to the contract by a sponsor, they can’t get it back unless the whole contract is refunded. In this case, all of the data is publicly accessible, meaning that anyone who has access to the Ethereum block chain can see who set up the contract, who is the benefactor, and who pledged each amount by accessing the contract code itself.

It’s important to note that anything that changes the state of a contract (its creation, pledging, refunding, or drawing down) requires transactions to be created on the block chain which means that the data is not stored until those transactions are mined and stored in a block. Operations that only read the state of an existing contract (getPot or reading the public member variables) are free operations which do not require mining. This is an important but subtle point: write operations are slow (we have to wait until mining completes). They may never make it to the block chain (if your code throws an exception or another error occurs) and require the caller to provide an incentive to the miners for doing the work. This is called gas in Ethereum terminology. All write operations require gas to pay for operations that change the state of the block chain.

Luckily we don’t have to buy any real Ether and participate in an Ethereum network. We can use the same software but configure it to run a local test block chain and run a miner to generate our own pretend Ether. This allows us to test our code without wasting real Ether.

Solidity code

Here’s the full source code of our smart contract written in the Solidity language:

contract smartSponsor {
  address public owner;
  address public benefactor;
  bool public refunded;
  bool public complete;
  uint public numPledges;
  struct Pledge {
    uint amount;
    address eth_address;
    bytes32 message;
  }
  mapping(uint => Pledge) public pledges;

  // constructor
  function smartSponsor(address _benefactor) {
    owner = msg.sender;
    numPledges = 0;
    refunded = false;
    complete = false;
    benefactor = _benefactor;
  }

  // add a new pledge
  function pledge(bytes32 _message) {
    if (msg.value == 0 || complete || refunded) throw;
    pledges[numPledges] = Pledge(msg.value, msg.sender, _message);
    numPledges++;
  }

  function getPot() constant returns (uint) {
    return this.balance;
  }

  // refund the backers
  function refund() {
    if (msg.sender != owner || complete || refunded) throw;
    for (uint i = 0; i < numPledges; ++i) {
      pledges[i].eth_address.send(pledges[i].amount);
    }
    refunded = true;
    complete = true;
  }

  // send funds to the contract benefactor
  function drawdown() {
    if (msg.sender != owner || complete || refunded) throw;
    benefactor.send(this.balance);
    complete = true;
  }
}
  • a Pledge structure models a donation, storing the sponsor’s account id, amount pledged, and a message string
  • the pledges array stores a list of Pledge objects
  • all member variables in the contract are made public so that “getters” are created automatically
  • throw is called in some functions to prevent data being written to the block chain in error conditions

Notice how the code doesn’t mention transactions, blocks, gas, or any of the terminology of block chains or crypto-currencies. It’s just code that saves state inside its member variables. It just so happens that Ethereum creates the necessary transactions and submits them to the network (in this case our test network) for verification, before being written to the block chain. All of that complication is hidden from us, leaving our code small (50 lines) and easy to understand.

This is important because smart contracts are about shared trust; all participants in a contract should be clear what they are committing to, where funds are going, and who has access to perform which operations. The simpler the code, the easier it is to verify that the contract is trustworthy.

Running the smart contract

In order to run the contract, you first need Ethereum up and running. My installation instructions for an Ubuntu server are here. I used an IBM Bluemix virtual machine and added the packages I needed using apt-get.

Assuming you have followed my setup instructions to create four Ethereum accounts on your test network and have set up a mining process, we can clone the smartSponsor code and execute it using the Ethereum console:

> git clone https://github.com/glynnbird/smartsponsor.git
> cd smartsponsor
> geth attach

From with the geth console, we can execute JavaScript commands which interact with Ethereum’s API:

> loadScript("./smartsponsor.js")
Contract transaction send: TransactionHash: 0xe797ce5c1e5eeaae6e4bd09ad6564f9deba1beeeb7f09b6c16eec728584e370c waiting to be mined...
true
> Contract mined! Address: 0x15590c0417f6421fd35e113db0fdb2055df2344b
[object Object]

The smartsponsor.js file creates variables which hold the addresses of the four Ethereum accounts we created (theminer, therunner, thebenefactor, thesponsor), which makes it easier to understand who’s doing what in the subsequent code snippets. It also contains a series of commands which compile the Solidty source, construct a smartSponsor contract and instantiate a new contract as therunner, such that the benefactor of the contract is thebenefactor.

The contract isn’t live until its transaction is mined. This may take a few seconds or a few minutes depending on the speed of the machine it is running on. Let’s look at the contract (which is assigned to a variable ss):

> ss
{
  address: "0xe021f45922e141f5e17d05a4b2721ec972065960",
  transactionHash: "0x77ba5bc77f0a62888c08084a7c00cf00b6cc024f88f988e9daada751788c8693",
  allEvents: function(),
  benefactor: function(),
  complete: function(),
  drawdown: function(),
  getPledge: function(),
  getPot: function(),
  numPledges: function(),
  owner: function(),
  pledge: function(),
  refund: function(),
  refunded: function()
}

We can see that the contract has an address, meaning it can send/receive Ether value and a transactionHash which locates it in the block chain. Also listed are the public functions that can be called against the contract. Let’s call some of those now:

> ss.benefactor()
"0x63de8807ac0bd63be460be0de250749c4df1dcb0"
> ss.owner()
"0x458305055882d53663b41a00eebd0b657469843f"
> ss.getPot()
0
> ss.numPledges()
0
> ss.complete()
false

We can see that the owner and benefactor of the contract are different accounts (therunner and thebenefactor, respectively), and the contract’s state has been initialised with no money and no pledges. These “read” operations are free so we do not have to supply any gas because we are simply reading from our own copy of the block chain.

Next we’ll give some money to thesponsor account, as accounts are generated with no Ether at first:

> personal.unlockAccount(thesponsor,"password");
> eth.sendTransaction({from: theminer, to: thesponsor, value: 100000000000000000});
"0xd4fc641311e31abb6546c3503c367c6ac971b0ad9cb4bcd4c56597e3b98d6d7a"
> eth.getBalance(theminer);
4.9524805801917e+22
> eth.getBalance(thesponsor);
100000000000000000
> 

Next we’ll authenticate as thesponsor user and pledge some money to our smart contract:

> personal.unlockAccount(thesponsor,"password");
true
> ss.pledge("Good luck with the run!", {from: thesponsor, value: 10000000, gas: 3000000});
"0xc0880c4151946014389e135bcbefe39fb8f786e9e3e0ce077fa5f967e2a31ab3"

The value parameter is the amount of Ether we wish to transfer to the contract. 10000000 may seem like a lot, but the units are in wei. There are 1000000000000000000 wei in 1 Ether!

The returned value is a transaction id. We have to wait until the transaction makes it into the block chain before the contract’s state will be updated:

> ss.getPot()
10000000
> ss.numPledges()
1
> ss.pledges(0)
[10000000, "0x225905462cf12404757852c01edfd2ec0bf0dbe9", "0x476f6f64206c75636b2077697468207468652072756e21000000000000000000"]
> 

The call to pledges(0), returns the first pledge as an array containing the value, the sponsor’s address and the message (as a string of bytes). We can keep adding pledges with repeated calls to the pledge function and watch the pot build up. After seven sponsors have pledged we have:

> ss.getPot()
70000000

Notice that the contract gets the full value of the Ether pledged by the sponsor, but the sponsor’s account is actually debited with slightly more than the pledge. Why is this? It’s because the caller of the pledge function also has to supply the “gas” to power the operation.

When the runner is ready to complete the contract, only a call to drawdown is needed:

> personal.unlockAccount(therunner,"password");
true
> ss.drawdown({from: therunner, gas:3000000});
"0x082424d8057b8c250f8b86cda05211628bb3bae513ce27bf6194445ae035a3c4"

After that contract has mined, we should see that the benefactor’s account has received the contents of the contract:

> eth.getBalance(thebenefactor);
70000000
> ss.getPot()
0

The smart contract holds multiple donations in escrow inside the contract until they are ready to be transferred either to the benefactor, or back to the sponsors. The code has safeguards in place to ensure that only the creator of the contract can refund or draw it down and to prevent further funds being added after the contract’s completion. The state of the contract can be interrogated at all times by all parties and all in 50 lines of code!

The commands that are executed on the geth command-line utility are actually JavaScript statements. The same calls can be made by your own client-side code which communicate back to the live (or test) network using a remote procedure call API. This makes it simple to create web-based front-ends for your smart contracts.

There is also the Mist browser that lets you create accounts, and view and interact with contracts—like an App Store of smart contracts. There are grand plans for Mist, but at the moment it is a relatively simple wallet app and contract browser.

Are blockchains just distributed databases?

A blockchain is a means of storing data in time-ordered ledger across a multi-node distributed database. But not distributed in the sense that Cloudant is a distributed database. The data is not sharded into pieces to spread the workload into manageable chunks; all members of the network have to deal with every change in data. Furthermore, the process of mining nodes performing “proof-of-work” tasks to prove that they are worthy of suggesting changes makes the process of writing data extremely slow. At the time of writing, the Ethereum network can handle only 20-30 transactions per second (not 20-30 transactions per user, but total) across the global network.

Ethereum also is more than a data store. It adds the ability to encapsulate executable code alongside the data in the blockchain. This allows participants to trust that a contract will do what it says it is going to. Compare and contrast that with signed paper contracts, lawyers, notaries, banks, insurers, clearing houses, etc.

What should block chains and smart contracts be used for?

Ethereum is only one of a number of smart contract platforms that have been created to provide a means of building applications on block chain technology. The most suitable use-cases are applications that:

  • transfer value from one party to another
  • require anonymity for one or more parties
  • require value to be held for a time in the contract itself
  • wish to avoid transaction fees associated with moving real currencies around
  • need to establish consensus
  • wish to demonstrate their openness by storing state in the public domain
  • need to guarantee the provenance of physical or virtual material

Applications such as auctions, loans, wills, registries, crowdfunding, shareholding, and voting spring to mind.

Write operations are expensive, both monetarily and computationally, so smart contracts lend themselves to applications which write infrequently but whose data has a high value. Although read operations are free, there are only primitive querying operations. You can create indexes on stored data, but there is no query language or means to extract or aggregate data as you would in a conventional database.

There are other drawbacks to block chains. Every participant in the network saves every block—the data is not sharded to divide the data into manageable chunks—so every node has to store the entire database and deal with every change. The “proof of work” model for distributing trust in the network is a clever work-around, but in practice, causes hundreds or thousands of nodes burning megawatts of power to prove that they are trustworthy. Finally, the value of Ether, like Bitcoin, is subject to speculative buying and selling, making the monetary value of Ether unstable. Ethereum has items in its roadmap to address performance, scalability, and a replacement for proof-of-work, but at the time of writing they are just wish-list items.

References

Join The Discussion

Your email address will not be published. Required fields are marked *