Migration from Ethereum to Lition blockchain

TLDR: successfully migrated to Lition blockchain and created own explorer, but it’s just one big step to the blockchain standard for the business.

What we had

Trading platform with nice user interface, that allows consumer to buy and energy producer to sell energy; the platform automatically matches orders. Frontend is built on top of a Ethereum blockchain proxy, Infura, a popular Ethereum provider. EnergyStore smart contracts in Ropsten and Mainnet chains are integrated with Powercloud, a platform for energy supply companies. You can read more about Lition infrastructure here.

There were multiple issues with the given setup: slow block confirmation, requiring asynchronous callbacks, transaction costs on Ethereum mainnet, no data privacy, no deletability — so we had to do something!

What we have

After migration we manage to fix most of the critical issues. We have instant transactions, private smart contracts, ability to delete information from specific node in our own Lition networks. There are two networks for staging and production environments, each one with 11 nodes. Staging network, visible e.g. on http://bc1.lition.io/, is public, production is hidden.

| server_name | tx_visibility |
| producer_1 | sees only tx for plant 1 |
| producer_6 | sees only tx for plant 6 |
| producer_9 | sees only tx for plant 9 |
| producer_10 | sees only tx for plant 10 |
| producer_11 | sees only tx for plant 11 |
| producer_13 | sees only tx for plant 13 |
| producer_18 | sees only tx for plant 18 |
| producer_19 | sees only tx for plant 19 |
| consumer_1 | sees only tx for demo user id ('demo') |
| supplier_lition | sees all tx |
| observer | sees all tx |

See the video from our MVP launch event to get more details and deep explanation of Lition blockchain.

Underlying technology components we use

We considered several existing solution that we can improve to meet our privacy requirements. Unfortunately R3 Corda works fine only for financial use cases, Hyperledger Fabric has not trivial process for expanding the network with new participants, in Parity privacy is hardcoded in node settings, Enigma has hardware limitations. At same time Quorum allows to reuse existing solidity contracts and keeps payloads off-chain on each node, so we can delete payload selectively.

Lition PoC blockchain re-uses code from Geth and Quorum. Those were adapted, especially with delete functionality and ethereum mainnet sync. In addition, own block explorer was developed. As a benefit, the solution is compatible with the popular tools for creating dApps like Web3js, Truffle or Remix.


The following text tries to summarize the necessary steps to perform the task, as well as the obstacles that arose on the way.

Initial setup

We manage to run the PoC network really quickly thanks to Quorum Maker. However, there was a known bug, and whenever we a node crashed or restart of one node was needed, we had to regenerate whole network — the issue was fixed just a month ago.

To partially mitigate it, we routed more expensive operations on the biggest node in the cluster, limiting number of out-of-memory crashes.

In addition, some nodes stopped accepting RPC requests after some time of being idle. So we added a health-check to docker command:

--health-cmd="(curl -s -X POST http://localhost:$RPC_PORT -H 'Content-Type: application/json' -d '{\"jsonrpc\": \"2.0\", \"method\": \"eth_blockNumber\", \"params\": [], \"id\": 1}' || echo '{}') | jq -e '.result' || exit 1" \
--restart=always \

Last but not least, Quorum Makers docker setup didn’t trigger restarting container automatically, so autoheal was added.

Anyway, these small adjustments helped us to dramatically decrease the rate at which otherwise correct transactions were failing due to factors external to blockchain logic.

Transaction confirmation

In order to receive transaction confirmation, one has to wait for the new block to be generated. In case of Ropsten, this was sometimes up to 30 seconds, what is not acceptable for UI in nowadays. Therefore, we had to hide it from the customers, and execute transaction asynchronously in the background, grouping them into batches executed at midnight. After moving from Ropsten we reached fast transaction confirmations and added this to the trading platform. Now the energy trading happens in real time.


Quorum allowed us also to send and receive private transactions by just adding privateFor to some RPC calls, e.g.:

const EnergyStore = artifacts.require('./EnergyStore.sol');
const config = require('../truffle-config');
module.exports = (deployer, network) => {
deployer.deploy(EnergyStore, {
privateFor: config.networks[network].privateFor

The transaction data are then encrypted, carried offchain to the recipient(s) and only hash of the data is included in transaction stored in the blockchain.

Again, as nothing works smoothly out of the box, Truffle v5 support for private contracts is somehow limited. We had to dig out the old v4 and backport.

Let us spend few words about the privacy in the network. Every node can be recipient or sender of a private transaction, and as a result, each node maintains its own state, that can be different to any other. There is no consensus about “global memory” state regarding state of private contracts. As an example, assume a network of 3 nodes n1, n2 and n3 and a very simple contract:

contract Adder{
uint256 state;
constructor() public {
state = 0;
function add(uint256 b) public{
state = state+b;

Now, when a private transactions Adder.add() is called from node n1 to node n2, nodes n1 and n2 see state==1, while n3 sees state==0. Further calls between the nodes with limited privacy can desync even the states of nodes n1 and n2.

Additionally, since private data is stored in offchain, we developed functionality to delete it from there. The interesting consequence is, that any contract state remains unchanged, just some of the data, used for calculation of the current state, become unavailable. In our previous example, the value of the iterator Adder.state remains unchanged, however, we won’t be able to recognize who exactly increased it by how much. The result is, that we are keeping aggregated anonymized business data while staying GDPR compliant.

Other issues

The chain is so fast that regular timestamp in seconds is not enough for saving blocks and it uses timestamp in nanoseconds. This was an issue for Web3js as all output formatters convert it using simple bn.js, which can’t handle such big number. So we had to rewrite all the javascript code to convert it to string.

this.web3js.utils.hexToNumber = v => {
if (!v) return v;
try {
return numberToBN(v).toNumber();
} catch (e) {
return numberToBN(v).toString();

Also we extended web3 with special method to get actual transaction input using payload id:

property: 'eth',
methods: [new this.web3js.extend.Method({
name: 'getQuorumPayload',
call: 'eth_getQuorumPayload',
params: 1,

Lition block explorer

Significant amount of work has been done on the Smart Contract Viewer and Debugger, which became the official Lition Explorer.

Initially the Smart Contract Viewer and Debugger was a simple tool written in Vue — a simple to use and instinctive framework, which allowed us to focus on functionality in plain JS and don’t waste time on complex implementation.

It had just one page that could work with our hardcoded EnergyStore contracts using Metamask and showed only list of bids, asks and events.


and asks

Routing, pagination, search, deleting, read and write contract, correct decoding transactions and events has been added. Also unique features like reading contract using specific block and writing to contract privately has been developed. Since we do some transaction on behalf of consumers we added to explorer possibility to select node that should issue the transaction. We managed to implement everything without backend database, just with Metamask. Of course, proper backend would open us more possibilities.

Home page contains list of blocks and transactions

Block page contains all details about block

The same for transaction. In addition to this if ABI is available it decode input and events. Also you can remove private payload on this page and nobody will be able to see the input on this node, even you

Address page contains number of transactions

If address is a contract and ABI is available you can see additional tabs. On events tab you can find all events of this contract paginated by blocks

On read tab you can read current state of the contract or historical state by specifying block

On write tab you can send transaction from specified in the top right corner node and select recipients who will be able to read original transaction input

Problems to solve

We solved the main painpoints, and got fast, cheap network, compatible with Ethereum and GDPR, but there are still a some issues to cope with.

Node use a lot of memory and crash or stop answering or loose wallet keys. Probably running them without docker could solve the issue.

Consensus protocol has to be changed to allow any participant to run their own node.

Small, low memory devices like Raspberry Pi would benefit from light client implementation.

The Quorum Maker security model has to be revisited, as it is designed rather to private networks with good access control.

Private contracts are limited to the list of participants known at the time of creation. New players can’t join and run once-deployed private contracts.

We are going to add notary for each network and submit hashes of some blocks to Ethereum Mainnet to additionally prove that chain is genuine.

Our next steps are described here.

Follow us in social networks not to miss anything important.