Monday, January 29, 2018

Blockchain Smart Contracts are the new Serverless!

Smart Contracts (thanks to Michael Bacina)
Over the recent past I've been experimenting with Smart Contracts for block chain implementations. Smart Contracts are essentially programs running on the block chain infrastructure. For example Ethereum supports Smart Contracts written in Solidity. EOS is another example of a blockchain that will support smart contracts. I've been looking at EOS an its smart contracts in more detail, here the smart contracts can be written in C/C++ so you don't have to learn a new language for it.


A CryptoKitty
So what can you do with a smart contract? Smart contracts are designed to provide some sort of computation and store the result (immutably) on the blockchain. The computation is a custom program that applies to your domain, so for example you could be renting out holiday accommodation and your website might store the holiday home rental contract including the price, optional extras, insurance etc for a given period of time, after having computed it, on the blockchain. In most cases smart contracts can also handle the payment, so let's say the rental home costs 500 Euro per week, then the equivalent in Ether (ETH) or whatever the current blockchain/crypto is, can be transferred to the owner as part of the smart contract execution.
Or, more creatively as has been done on the ethereum network, your contract could compute a unique CryptoKitty for you that is a cute looking creature created just for you to look at and store the result on the blockchain.

You can even take this a little bit further. As shown with the CryptoKitty the smart contract does not need to have anything to do with transferring money from a to b or writing some sort of financial contract. In theory you could use the smart contract to do anything you might be able to use asynchronous computing power for.

After playing briefly with Solidity, the smart contract language for Ethereum I moved to play a bit more with EOS smart contracts. Why EOS? EOS as a blockchain is still in it's early phase and under heavy development although they do have a test network up and running at this stage. However I find EOS interesting because it has a couple of interesting aspects:
  • First of all it's quite easy to run a test EOS node on your own machine which allows you as a developer to play with it and understand it in a sandbox type environment.
  • EOS aims to provide much higher transaction rates than the current major block chains can provide. It promises up to 50000 transactions per second which all of a sudden is big enough to handle amounts of payments similar to major credit card companies like Visa and Mastercard.
  • Smart contracts on EOS can be written in C/C++ which is really nice, as you don't need to learn a new programming language for it.
So let's take a look at how I got my example EOS contract deployed to my own test EOS node.

Build the EOS code

I tried this on Ubuntu 16.04. Compile the EOS code base:

First, clone the EOS code
  ~$ git clone https://github.com/eosio/eos ~/eos
  
~$ cd eos

Then build the whole lot:
  ~/eos$ ./build.sh ubuntu full
This takes a while but once it's finished you should be able to run your EOS node:
  ~/eos/build/programs/eosiod$ ./eosiod

It now exits with an error. You need to set up data-dir/config.ini as described in the EOS docs: https://github.com/EOSIO/eos

At this point your EOS node should be happily up and running. Which is really neat. You've got a EOS block chain node running for development purposes on your local machine!

~/eos/build/programs/eosiod $ ./eosiod 


Before you can use your EOS node you need to create a wallet and an account. Since our smart contract will be computing the Fibonacci sequence, I'm going to call the account fibonacci. The following commands do that for you. They use a demo account inita that is created in the config.ini file when its set up as above.

Here we use the eosioc program which is a client to the EOS network:
~/eos/build/programs/eosioc $ ./eosioc wallet create
~/eos/build/programs/eosioc $ ./eosioc wallet open

Import the inita demo key:
~/eos/build/programs/eosioc $ ./eosioc wallet import 5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3

Create two private keys for the fibonacci account:
~/eos/build/programs/eosioc $ ./eosioc create key
Private key:###
Public key: ###
~/eos/build/programs/eosioc $ ./eosioc create key
Private key:###
Public key: ###

Create the fibonacci account:
~/eos/build/programs/eosioc $ ./eosioc create account inita fibonacci {private key1} {private key2}

Create the smart contract

I created a little testproject called fibonacci which computes the fibonacci sequence to a certain iteration in the EOS smart contract and stores the result in the EOS database.

The code can be found in github here: https://github.com/coderthoughts/fibonacci

It exists of two components: an external contract, in the fibonacci.abi file which defines how the application communicates with the outside world. The actual communication typically happens in JSON:

{
  "structs": [{
      "name": "compute",
      "base": "",
      "fields": {
        "iterations": "uint64"
      }
  },{
    "name": "result",
    "base": "",
    "fields": {
      "id": "name",
      "value": "uint64"
    }
  }],
  "actions": [{
    "action_name": "compute",
    "type": "compute"
  }],
  "tables": [{
    "table_name": "results",
    "type": "result",
    "index_type": "i64",
    "key_names": ["id"],
    "key_types": ["name"]
  }]
}

And there is the fibonacci.cpp file that contains the source code in C++ of the contract. The main bit of the C++ contract is just the apply() method that gets invoked when the EOS Smart Contract receives a message:
    uint64_t fibonacci(uint64_t iterations) {
        uint64_t first = 0;
        uint64_t second = 1;

        if (iterations == 0)
            return 0;

        eosio::print("1 ");
        for (uint64_t i=1; i < iterations; i++) {
            uint64_t res = first + second;
            first = second;
            second = res;
            eosio::print(res, " ");
        }
        return second;
    }

    /// The apply method implements the dispatch of events to this contract
    void apply(uint64_t code, uint64_t action) {
        if (action == N(compute)) {
            auto message = eosio::current_message<compute>();
            eosio::print("Calling fibonacci\n");
            uint64_t num = fibonacci(message.iterations);

            result res(eosio::name(code), num);
            Results::store(res, res.id);
            eosio::print("Stored result in database\n");
        }
    }

There are also specific EOS libraries available, the documentation is here: https://eosio.github.io/eos/group__contractdev.html

Deploy your own smart contract

An interesting part of the EOS smart contract development lifecycle is that these contract don't get compiled in regular machine language, what C++ compilers normally do, but it gets compiles into a WebAssembly .wast file. This file is some sort of assembler language but then platform independent and this is what EOS uses at runtime.

Once deployed, you can execute your contract by sending a message to it. The contract executes and can write its output to a database location for later retrieval by a client.

The easiest way to compile the fibonacci source is to put the files with the other example smart contracts in the EOS codebase, in the contracts directory. Then you've got everything in the path as the compiler expects it:

Compile the project:
~/eos/contracts$ ../build/tools/eoscpp -o fibonacci/fibonacci.wast fibonacci/fibonacci.cpp
Upload the fibonacci smart contract to the EOS node:
~/eos/contracts$ eosioc set contract fibonacci fibonacci/fibonacci.wast fibonacci/fibonacci.abi
Now we can start executing it. Lets run the fibonacci compute for 8 iterations and store the result:
~/eos/contracts$ eosioc push message fibonacci compute '{"iterations":8}' -S fibonacci

On the EOS demon console you can see some debug output from the smart contract

> Calling fibonacci
> 1 1 2 3 5 8 13 21 Stored result

However a real user will obviously never be able to see this. So to obtain the result of the computation, we'll look it up in the EOS database:

/build/programs/eosioc$ ./eosioc get table fibonacci fibonacci results 


{
  "rows": [{
      "id": "fibonacci",
      "value": 21
    }
  ],
  "more": false
}


So the result is 21. We've executed our smart contract and obtained the result on the EOS blockchain!

Conclusion

I'm pretty excited by the possibilities of smart contracts with regard to the possibilities that these, once matured, can provide. It becomes similar to what today is labeled 'serverless' computing. Things that are at the moment possible through large providers such as Amazon Lambda and Microsoft Azure Functions will also be provided via block chain networks. One difference is that the computation is not done by a single cloud entity, but rather by a collection of nodes that are run by individuals who have mining machines for that crypto. In my eyes it's still early days and certain things in the contracts can certainly be improved, e.g. the available APIs usable from within the smart contracts are still fairly limited, but that will probably improve over time. The fun thing is: it's pretty easy to get started experimenting and writing smart contracts, even from a simple Linux box, so you can learn and develop your smart contracts while the blockchain teams are working on maturing the infrastructure.