On June 10th, it was the third day in Hong Kong. In the previous 26 hours, we had almost given up sleep, trying to develop the prototype for a project codenamed SensorPay, as part of the first stage of EOS Global hackathon with a prize fund of 1.5 million USD. The moment to introduce our project to the judge was approaching.

If you are eager to hear the end of the story, you can simply jump right to the last chapter. Meanwhile, we are going to ease into our story about EOS technologies and about how we came to this idea of linking IoT payments to EOS. Then, in detail, we will describe the technical content of our project.

Introduction

EOS is the next-generation of blockchain. Some even call it the "Ethereum killer." We, however, started digging deep into EOS around a year ago, including a thorough study of the preceding products from its authors, BitShares, and Steem.

The advantages of EOS, as compared to Ethereum, are their ability to make transactions higher by three orders of magnitude, advanced permission systems for smart contracts, access recovery and blockchain troubleshooting features, and on-chain network governance. The disadvantages include centralization concerns, potentially more vulnerable DPoS consensus, code that wasn't tried in production, and a steeper learning curve for developers.

Because we have been interested in this technology for quite some time now and find it to be worthwhile, we could not ignore a series of hackathons sponsored by the EOS authors. We just wanted to get there and bring our ideas to life in such an inspiring atmosphere and share them with the audience. Of course, the opportunity to win a lot of money was also a strong incentive.

So, EOS is the only known working solution for a public blockchain that is capable of handling a lot of transactions. Where is it required? In IoT, of course! If a toaster is able to send micropayments to a fridge for each piece of bread (which is by itself quite cool, as you can imagine), there is going to be a lot of transactions. Not to mention other applications in healthcare, manufacturing, or household items.

A few weeks before the hackathon started, we were still brainstorming and throwing around a few alternative ideas. We were comparing ideas based on the known assessment criteria — application of EOS capabilities, creativity tools, social impact, and scalability. We finally chose a combined IoT and EOS solution that would support retrieving sensor data and send a lot of payment transactions to EOS.

By the way, we would also like to share how we arranged our Block Producer for EOS and how we planned the implementation of an ERC721-like token designer to support constant functions. Along with that, we will demonstrate how we developed a Merkle Root ACL protocol. However, this article will never be able to cover all this, so let us get back to our main project.

Preparations

IoT

Preparing an IoT portion of a project means selecting the right hardware. We chose an RC522 based on the SPI bus to be an RFID reader — it is quite popular, simple, and easy to use.

When looking for a suitable counter, we paid attention mainly to whether or not it had a pulse output. This truly simplifies the process of reading data — one pulse is equal to X kWh (where X depends upon the model). We finally chose a Mercury 201.5 counter.

The most challenging aspect was selecting a controller that had to collect data from sensors, create a transaction, sign it with its private key, and, then, send it to the network. So, we wanted a device equipped with a networking module that could sign a transaction using the ECDSA (in this case, on the SECP256k1 elliptic curve, because this curve is used for signatures in EOS).

First, we decided to use an ESP8266 microcontroller, because it had a Wi-Fi module and all the interfaces required to connect to our sensors. Additionally, it was really compact. However, none of its firmware versions contained a native implementation of elliptic primitives. We could develop our own implementation, but that was hardly a task to be solved during a hackathon. As a result, we chose Raspberry Pi 3 B and an eosjs library for generating and signing transactions.

Infrastructure

A couple of days before the hackathon started, we built an EOS both locally and on an eos-hackathon.smartz.io (source codes). Specifying dependencies, building and testing were surprisingly smooth for a young project like this (provided that the documentation was used). Regrettably, we were short on time, which prevented us from preparing the remaining infrastructure. This meant that we had to do it right at the hackathon.

Architecture

The day before the hackathon, we discussed architecture-related issues and hammered out the product details. We were going to implement the following basic use cases: settlements for electric energy and payment for the purchased items marked with RFID tags. We also wanted the product to be easily extendable in order to support other applications.

The idea behind the architecture is that a producer creates a single contract that is a central point of interface between the supplier and consumers. Each consumer has his/her own replenishable balance, from which the funds are charged based on sensor signals. All data (user, sensor, or statistic data) is stored within a supplier contract.

The consumer is linked to custom settings or flags (e.g. privileged user category) — user_meta . The consumer may also be linked to multiple sensors with a contract and billing settings specified for each of them ( billing_meta ). Thus, you can get a non-changeable stateless billing contract that can be used for a large number of consumers. The data required will appear in the course of calling the bill(payload, user_meta, billing_meta) method. Various billing logic (i.e. various contracts) is also supported. For instance, one contract counts energy consumption and the other counts goods. Each sensor has a pointer to its billing contract.

It is presumed that the consumer trusts the sensor manufacturer, but they may distrust the supplier. The sensor interface is unbelievably simple. It includes calling a supplier's contract method with a numeric parameter that will be sent to billing. The service supplier enters the consumers, sensors, billing contracts, and correlations between them in the contract using the control transactions — primitive setters. When a transaction is received from a sensor, the following takes place: the data are checked, a dataset is created for billing, the billing system is called, the payment is registered, and, then, a statistics record is created.

The following matters could greatly influence the product's real-life applicability and were the most highly discussed:

Should we prefer advance payments or post-payments? Does a user need to top up his/her balance and only then get access to the service (like it happens with the mobile connection), or can he/she use the service first and then pay for it (like in AWS)? There cannot be any right or wrong answer to this — different business types prefer different models. For clarity's sake, we decided to have advance payments.

Should a user register a separate account for each supplier, or is a single account charged for all the services? Again, there is no right or wrong solution. Besides, the answer is closely related to the answer to the previous question. Advance payments can be easily set for individual consumer accounts. Because of this, we chose that option.

Should we accept payments in EOS, supplier tokens, or stable coin (bound to a fiat currency)? Certainly. The stable coin is the only convenient option for consumers, as the others remain volatile, but the stable coin is not yet applicable within the EOS concept. There was actually no main EOS network at the time. So, we chose a provisional token for simplicity.

Code

First of all, we specified the API and supplier contract framework in order to start developing the front-end portion, device codes, billing systems, and a basic contract (sources).

IoT

The code for the sensor pulse reading was implemented first. We used an on/off JS library for working with the GPIO (general purpose pins). Later, we added two LEDs to give it a better look. The first LED blinked when a signal arrived from the counter, and the second one blinked when EOS node gave the response notification of a successful transaction. In a similar way, we developed a schema and code for reading RFID tags. There was only one difference — the reading was performed by an SPI bus using an MFRC522-python library. It turned out that configuring SPI for the Raspberry Pi 3 is different from that in previous board models. We managed to grasp the idea with the help of this manual.

Devices received power from a power bank (power banks were provided free of charge to all hackathon participants). However, we had to use an iPhone 5 as a hotspot because the hackathon venue only provided a 5 GHz Wi-Fi channel, which was not suitable for the Raspberry Pi.

Infrastructure and Utility Software

The organizers recommended using an eos-dev docker image, but we were discouraged by the absence of description and documentation for the image. We kept on using the prepared build on the server and used eos-dev locally, in order to avoid installation of EOS to the system.

We immediately felt an urge to build and test everything rapidly. An ideal option was building and launching a locally executable file. However, we could not ignore the fact that, in the long run, we needed WebAssembly in the EOS environment (with relevant boost libraries, system contracts, etc.). We could have found the necessary compilation parameters in eosiocpp.in; however, we decided not to play this game. Getting a predictable result not as quickly is still better than quickly getting a potentially troublesome solution. That is why we used the eoscpp contained in an eos-dev container for our builds.

Launching it was a little bit more difficult. We had to set up a local EOS blockchain without having a ready-to-use solution at hand. We only had the software. In this way, we got the first version of the launch infrastructure. The idea was to hide the assemblage and configuration details and get a self-consistent set of four or five "buttons" assigned to standard actions. This offers fewer control capabilities, but, at the same time, it reduces the chance of error and saves time.

Basic EOS components include nodeos daemons, keosd, cleos console utility, and an eoscpp compiler:

nodeos is an EOS node, and daemon is a network member that provides access to blockchain and optionally creates new blocks;

keosd is the daemon for managing the local wallets where key pairs are stored;

cleos is a command line interface to various actions from obtaining transaction-related information to operating keys. Its implementation is based on calls in nodeos and keosd via HTTP API;

eoscpp compiles contracts in WebAssembly and enables getting an Application Binary Interface based on the source code.

It became clear that cleos commands related to access operations in keosd were not functional. We saw a "keosd unavailable" error, so we spent some time to troubleshoot networking issues in a docker network. However, strace demonstrated that the network was not the problem — cleos accesses an invalid address, accessing localhost at all times (in the case of our infrastructure, various daemons had different network addresses in a separate docker network). We identified a bug in cleos. The keosd availability check performed before applying any wallet-related command considered the port sent in arguments, but it did not consider the address. Within the framework of the hackathon, we chose migration to a host network in docker as a workaround.

The next step was developing a contract compilation utility using a containerized compiler (commit). Then, we assembled the input and output directories. After that, we finally got an opportunity to load the contract into blockchain and send transactions (commit). Again, we had consistent-style utility software and simple "buttons." With that, we were done with the underlying infrastructure, but surprises kept on coming up. We detected a problem with memory handling C functions (more information on this given below).

Finally, we began to add accounts into a single file (each contract and each member required a separate account) together with the key pairs created automatically when launching the blockchain. This was done so that a single command could get the entire test environment going. One copy of the environment was deployed at eos-hackathon.smartz.io.

That's all for Part 1, be sure to tune in tomorrow when we'll describe the technical content of our project in greater detail.





The project team and co-authors of this article: