Implementing own sidechain using Lisk.

Lisk is dedicated to develop custom blockchain based applications using Javascript. After Alpha SDK release it’s possible for developers to prototype first custom applications. Technology is awaited by project investors since some time already. In that article I would like to go through the process of installing Lisk and all dependent technologies and then create and run own Lisk blockchain application.

How looks like the Lisk Alpha SDK application development process?
How looks like the code of custom blockchain?
What are the possibilities and potential of Lisk technology?

I would like to present software engineer point of view and describe both the positive and negative aspects.

Preparing the development environment

Lisk SDK is actually the software library and tools dedicated to develop own blockchain. Complete blockchain application based on Lisk consist of more components and these are the technologies being present on the market since many years.

Preparing the development environment is based on installing and configuring required components on the target operating system (system which will run the Lisk application). I will follow the Lisk setup instruction. Supported operating systems are Ubuntu (Linux) and MacOS. I work on Arch Linux, this is why some steps will be different in my case than described in the Lisk docs instruction.

PostgreSQL installation

PostgreSQL is the universal relational database. Lisk stores some blockchain data in the database (e.g. some accounts and blocks information). In the docs there are two ways presented of installing Postgres in the system: directly and dockerized. I will use already prepared PostgreSQL docker images. The benefit of that solution is that the database lives only in running docker container which can be stopped any time (e.g. after shutting down the system). So I don’t mess anything in my local system. I will use docker-compose tool for running docker images. The docker-compose script responsible for running the images is given (saved as postgres.yaml):

version: '3.1'
networks:
  pgnet:
services:
  postgres:
    container_name: postgres
    image: postgres:12-alpine
    restart: always
    environment:
      POSTGRES_PASSWORD: pass1234
      POSTGRES_USER: lisk
      POSTGRES_DB: lisk_dev
    ports:
      - 5432:5432
    networks:
      - pgnet

  adminer:
    image: adminer
    restart: always
    ports:
      - 9000:8080
    networks:
      - pgnet

Having such script, running the database is simply (in bash):

docker-compose -f postgres.yaml up

Node.js installation

Node.js is the Javascript runtime, mostly used as web server (web applications). Node.js runs the Lisk blockchain application – process the code of entire application. In order to install the Node.js I will use nvm tool which is also recommended by Lisk. This is tool is Node.js version manager and gives the possibility to switch between Node versions. It’s very helpful when you work with Node and you switch often between versions. According to the Lisk docs 10.15.3 is required version of Node.js. Having nvm installed in the system I invoke (in bash):

nvm install 10.15.3

lisk-sdk installation

lisk-sdk is the heart of Lisk blockchain application: the software library and tools aggregating the logic required to create and run own custom blockchain. Currently consists of 3 components: Lisk Framework, List Elements and Lisk Commander. Lisk Elements and Framework are programming libraries. Lisk Commander is console tool. The libraries are implemented in Javascript. These components are provided in single npm package present in npm repository. Even if installation of this package is the preparing environment step – I will do it later and include the package as a dependency in built application. Thanks to that I will have the package in the project folder, not somewhere in the system.

Preparing environment remarks

  • only Ubuntu and MacOS supported – docs suggest that there are only 2 systems supported. This information drives away since the setup on other operating system is quite straightforward (like in my case). I hope this information will be gone soon. Generally API should be operating system agnostic as much as possible. Generally Lisk shouldn’t favor any of the operating systems. Actually it’s not even true, so what must be changed are simply docs.
  • old Node.js version – officially supported version is 10.15.3, but currently newest generation of Node.js is 12. I hope Lisk will upgrade dependencies soon.
  • misleading lisk-sdk installation step – installation of this package on the operating system shouldn’t be generally present in the development environment setup. First of all it’s misleading as I said – this package is not needed directly. I’ve downloaded the package and even Lisk Commander was missing there – which would be the reason to have it globally in the system. The dependencies installation should be present (it will be in my case) directly in the project configuration (this makes the application encapsulated, the dependencies belong to the project).

Cashback App – implementing example app

Having the environment prepared I can implement and run own blockchain application. I will use example Lisk reference project – Cashback App.

Downloading the sources

First of all I will download the sources from Lisk Github repository. I will use git in order to clone the repository to my system:

git clone https://github.com/LiskHQ/lisk-sdk-examples

It downloads the lisk-sdk-examples folder to my machine (70 MB big, quite a lot). Let’s go to the project catalog:

cd lisk-sdk-examples/cashback/

Let’s install the dependencies (assuring that we are using Node.js 10.15.3):

npm install

Given command downloads all the dependencies – programming libraries required for running our application. We speak here about products directly developed by Lisk but also about other libraries used by Lisk. When the operation succeeds, we have everything prepared in order to run our application.

Project structure

The structure of project consists of few files and folders. Some of them are part of standard Node.js project configuration. There are three blockchain aplication source code files: index.js, cashback_transaction.js, print_sendable_cashback.js.

 

lisk-cashback-app-pliki
Aplication files based on Lisk – sample project Cashback App.

We do own blockchain

The code which inits and runs the blockchain is in the index.js file. This is the file content:

// imports of required classes and configs from Lisk
const { Application, genesisBlockDevnet, configDevnet } = require('lisk-sdk');
const CashbackTransaction = require('./cashback_transaction');

// app configuration - name
configDevnet.app.label = 'Cashback-blockchain-app';
// configuration of database password 
configDevnet.components.storage.password = 'pass1234';

// the instance of our blockchain application
const app = new Application(genesisBlockDevnet, configDevnet);

// registration of custom transaction type 
app.registerTransaction(CashbackTransaction);

// initialization and start of our blockchain
app
  .run()
  .then(() => app.logger.info('App started...'))
  .catch(error => {
    console.error('Faced error in application', error);
    process.exit(1);
  });

I’ve changed the database password (configDevnet.components.storage.password variable) to match the password of database I run. The code is quite minimalistic and short. There is no blockchain term used in that code. What we do is programming the Application (the Application class and object app). It’s worth to mention that there is nothing like sidechain here – actually we don’t create any sidechain here being in any relation with main Lisk Core blockchain. What we do is completely independent blockchain. In order to initialize the app object of Application class we use 2 other objects imported directly from lisk-sdk. They are genesis block (first blockchain block) and some base configuration. Overall it’s quite easy to create because we can use these already prepared components and change them according to the needs – that for sure makes the work with Lisk easier.

In the created blockchain we register own transaction type, which will be handled by that blockchain: CasbackTransactionIts definition is in the second of key files of our application: cashback_transaction.js. The content:

const {
  transactions: { TransferTransaction },
  BigNum,
} = require('lisk-sdk');


class CashbackTransaction extends TransferTransaction {

  // the transaction type, 1-9 are reserved by Lisk
  static get TYPE () {
    return 11;
  };

  // transaction fee
  static get FEE () {
    return `${10 ** 7}`;
  };

  
  applyAsset(store) {
    const errors = super.applyAsset(store);

    const sender = store.account.get(this.senderId);
    
    // update of sender balance
    // he receives 10% of sending tokens just as bonus
    const updatedSenderBalanceAfterBonus = new BigNum(sender.balance).add(
      new BigNum(this.amount).div(10)
    );
    const updatedSender = {
      ...sender,
      balance: updatedSenderBalanceAfterBonus.toString(),
    };
    store.account.set(sender.address, updatedSender);

    return errors;
  }

  undoAsset(store) {
    const errors = super.undoAsset(store);

    const sender = store.account.get(this.senderId);
    const updatedSenderBalanceAfterBonus = new BigNum(sender.balance).sub(
      new BigNum(this.amount).div(10)
    );
    const updatedSender = {
      ...sender,
      balance: updatedSenderBalanceAfterBonus.toString(),
    };
    store.account.set(sender.address, updatedSender);

    return errors;
  }
}

module.exports = CashbackTransaction;

The CashbackTransaction class represents the transfer transaction (in our case the native cryptocurrency of the blockchain we develop, let’s call it LSK2). In order to create the transaction which will have some custom logic – we create the new transaction type which extends the features of basic transfer transaction type – TransferTransaction (according to OOP logic). Such programming approach gives us the possibility to extend the behavior of blockchain components instead defining the behavior from scratch. This is for sure faster approach than forcing to design everything from zero. You could ask – will it be the model of developing Lisk blockchain applications? I believe yes. It’s worth to mention that Lisk Core, the node of main Lisk blockchain network (with LSK cryptocurrency) – is nothing more than application developed using Lisk SDK. So these components (like transaction) are exactly the same code which is processed by every Lisk Core instance running across the Lisk main network. So the logic is the same like the logic of Lisk Core nodes working now in the mainnet.

The transfer transaction in Lisk is simple sending of cryptocurrency from one account to another. The fee is the transaction cost. This is the way TransferTransaction works. CashbackTransaction changes this logic a little bit: the sender receives 10% of the amount he sends to the receiver e.g. Bob (has 100 tokens) sending 100 tokens to Alice (which has 0 tokens) will receive 10 tokens for free. After all Alice will have 100 tokens and Bob 10. Bob’s tokens are newly created.

cashback_diagram
Cashback App – the transaction gives 10% of amount to sender. Source: https://lisk.io/documentation/lisk-sdk/tutorials/cashback.html

The application we develop was configured to use the CashbackTransaction as default transfer transaction type. The code which registers this transaction type is given (cashback_transaction.js file):

app.registerTransaction(CashbackTransaction);

Running the application

Running the application is simply (bash):

node index.js

The output logs are given:

Logi działającego blockchaina opartego o Lisk SDK.
The logs of Lisk SDK built working blockchain application.

The blockchain is working – it generates the blocks in some time intervals. My application is the only node in created blockchain network, so the whole processing of the blockchain is limited to single running Node.js process.

Interaction with the blockchain

The last of key files is print_sendable_cashback.js. This file contains the single logic of preparing the transfer transaction in JSON format, ready to be sent to the node (our application). This transactions sends 2 LSK2 from sender to the receiver. This script prints the transaction JSON doc to the standard output:

const CashbackTransaction = require('../cashback_transaction');
const transactions = require('@liskhq/lisk-transactions');
const { EPOCH_TIME } = require('@liskhq/lisk-constants');


/**
 *  To directly send the printed transaction:
 *  > node print_sendable_cashback.js | curl -X POST -H "Content-Type: application/json" -d @- localhost:4000/api/transactions
 *  Note: An node needs to run on port 4000 (the default one) before. If the node runs on a different port, adjust the query accordingly.
 */

const getTimestamp = () => {
    // check config file or curl localhost:4000/api/node/constants to verify your epoc time
    const millisSinceEpoc = Date.now() - Date.parse(EPOCH_TIME);
  const inSeconds = ((millisSinceEpoc) / 1000).toFixed(0);
  return  parseInt(inSeconds);
};

// we define CashbackTransaction
const tx = new CashbackTransaction({
    // send 2 LSK2 tokens (converted to the lowest possible Lisk currency fraction)
    amount: `${transactions.utils.convertLSKToBeddows('2')}`,
    fee: `${transactions.utils.convertLSKToBeddows('0.1')}`,
    recipientId: '10881167371402274308L', //delegate genesis_100
    timestamp: getTimestamp(),
});

tx.sign('wagon stock borrow episode laundry kitten salute link globe zero feed marble');

console.log(tx.stringify());
process.exit(1);

As you can read in the code comments, we can run this script and pass the output directly to the curl tool. Curl will send the HTTP request to the application. Communication with our application (node) is based on HTTP protocol. The request should be processed by the application and should be finalized with successful transaction processing. Before I will send the transaction, I will check how many LSK2 has the receiver. His ID is 10881167371402274308L. I run the request:

curl -X GET "http://localhost:4000/api/accounts?address=10881167371402274308L"

The result:

{
  "meta": {
    "offset": 0,
    "limit": 10
  },
  "data": [
    {
      "address": "10881167371402274308L",
      "publicKey": "addb0e15a44b0fdc6ff291be28d8c98f5551d0cd9218d749e30ddb87c6e31ca9",
      "balance": "0",
      "secondPublicKey": "",
      "asset": {},
      "delegate": {
        "username": "genesis_100",
        "vote": "10000000000000000",
        "rewards": "0",
        "producedBlocks": 0,
        "missedBlocks": 0,
        "rank": 70,
        "productivity": 0,
        "approval": 100
      }
    }
  ],
  "links": {}
}

The balance is 0. So I send the transaction:

node print_sendable_cashback.js | curl -X POST -H "Content-Type: application/json" -d @- localhost:4000/api/transactions

The result seems to be success:

{"meta":{"status":true},"data":{"message":"Transaction(s) accepted"},"links":{}}

Again I check the balance of the receiver:

{
  "meta": {
    "offset": 0,
    "limit": 10
  },
  "data": [
    {
      "address": "10881167371402274308L",
      "publicKey": "addb0e15a44b0fdc6ff291be28d8c98f5551d0cd9218d749e30ddb87c6e31ca9",
      "balance": "200000000",
      "secondPublicKey": "",
      "asset": {},
      "delegate": {
        "username": "genesis_100",
        "vote": "10000000000000000",
        "rewards": "0",
        "producedBlocks": 2,
        "missedBlocks": 0,
        "rank": 70,
        "productivity": 100,
        "approval": 100
      }
    }
  ],
  "links": {}
}

Unfortunately current Lisk docs are quite poor – I couldn’t find the easy method to get the identity of the sender. Lisk Commander will be the tool for such kind of purposes. Right now this tool supports the connection with Lisk Core (mainnet) network. Signing the transaction at the moment is based on providing 12 unique words which identify the account. This is what is also required when you use Lisk wallet. We know 12 words, but we don’t know account ID. The way I will identify that the sender actually send the cryptocurrency is checking database – the lisk_dev table in PostgreSQL. There is mem_accounts table in the database. Let’s check the rows:

lisk-dev-tables
Some rows in mem_accounts table in the lisk_dev database.

As you can see in the screen, the balance of account with ID 10881167371402274308L is 200000000, what means that it owns 2 LSK2. The second row in the table which doesn’t have the username defined has 99999998,1 value which would match the expected result (99999999 seems to be the init state of the sender account, 2 LSK2 were send, 0.1 is the transaction fee, and cashback transaction returned 0.2 LSK2 => 2 – 0.1 + 0.2 = 0.1). I invoked the transaction once again and after that transaction: row 2: 9999999620000000, account with address 10881167371402274308L: 400000000. It seems that everything works well, as expected.

The application development remarks

Some of my remarks will be probably addressed in the future, so these true currently only.

  • lack of documentation – current documentation is very limited and doesn’t allow to explore the Lisk possibilities.
  • unintuitive naming of libraries and tools – Lisk SDK is the name which aggregates all of the Lisk products, dedicated to developing blockchain applications. Generally it doesn’t help in understanding what Lisk really is. It consists of Lisk Frameworks and Elements – I struggle to understand what is the real purpose of these libraries (I only know I need to use their features, but not what and when). Naming and descriptions are not informative and intuitive enough, at least for me.
  • lack of Typescript support – developing more complex Node.js applications most often is based on Typescript, which is compiled to the Javascript. This adds the “types” to the JS language. Currently the products developed by Lisk are written mostly in Typescript (Elements, Commander) but Lisk Framework is written in Javascript. This can have various long term impacts – it’s generally easier to maintain the typed code and it can also delay providing the types to the products Lisk develops.

Summary and conclusions

Lisk - access the power of blockchain

Lisk is hard to describe project: it’s purpose is building blockchain applications however it works completely different than current blockchain apps in the: blockchain – smart contract model. Developing the application using Lisk we create own, completely independent blockchain (from main network). Currently defining the logic of the Lisk application is based on modifications of the default behavior of blockchain mechanics and configuration: e.g. modifying the transaction logic or defining the fee amount. 

I’ve noticed that Lisk stopped to use sidechain word – and it seems to be proper. The blockchain we develop using Lisk has not any relation with mainnet blockchain (so I lied a little bit in this article title). You can run, stop, modify the logic of that blockchain changing few source code lines. Currently I couldn’t find any model of designing and creating own blockchain network of nodes – how would look like the democratization of such network, how it would work. The question is also what really means the immutable code processing in Lisk context (only transactions?). Of course some kind of these rules must exist now – because Lisk mainnet works and is running well. The question however is how much Lisk apps developers will be flexible to change it according to the needs. Currently the Alpha SDK gives the possibility to run the Node.js process which seems to follow the Lisk Protocol, so the same like Lisk Core node.

The idea of Lisk is similar to the projects dedicated to build private blockchain networks like Hyperledger Fabric. Fabric is really developed project and is already used in commercial solutions. The benefits of Fabric are it’s modularity and huge configuration possibilities. Private blockchain are dedicated to run across the closed participants group. Lisk semms to allow developing public blockchain applications – accessible for everyone. Anyway it doesn’t change the fact that talking about the Lisk and Hyperledger Fabric we talk about designing, building and running own blockchain network. No matter what type – public or private – the cost and responsibility of maintaining such network belongs to the network creator (developer).

Javascript which initially made Lisk attractive – in my opinion can cause some long term problems. Maintaining complex Javascript application is hard – the Lisk for sure is such kind of project (Lisk doesn’t use Typescript). What can be visible even today, Alpha SDK has already a lot of dependencies which cause many known and common problems of maintaining such code: the need of complex dependencies update (to maintain compatibility or because of some security flaws, issues). What is also worth to mention – that some of these known problems exclude the Javascript from the ecosystem of serious IT solutions (in favor of e.g. Java).

sd
Lisk SDK dependencies.

Node.js is the runtime environment of the Lisk based application. Because of it’s construction (asynchronous, event loop) has also some restrictions. Assuming that Lisk application is something more than simple cryptocurrency transfer and that it will run across the blockchain node – the whole processing will be limited to Node.js runtime (what can be kind of defect, even if currently seen as advantage).

Lisk aspires to be the attractive and modern tool for building blockchain apps with focus on large group of web developers. The vision and products are still created. The investors of the Lisk projects may be interested about the utility of the LSK token in the model Lisk designs the products. Currently mainnet with the LSK token is just the application developed using Lisk SDK. The mainnet LSK token has currently no usability in the Lisk developed applications.

Talking about Lisk purpose it’s worth to mention once again that it’s not the smart contract platform. In Lisk we develop own blockchain which determines the possible usage of Lisk. Maintaining custom blockchain as already said – is expensive and responsible. Additionally the decentralization of such created blockchain is dependent of the blockchain creators (developers). Because of that Lisk probably will not be used in many public blockchain usage branches – for the usages where blockchain should be the final source of truth (e.g. tokenization or digial contracts). For these purposes the blockchains which give the possibility to implement smart contracts (like Ethereum) and which are highly decentralized will be probably the right choice (decentralization is key factor for trust in the blockchain world, because more decentralized system is harder to be broken, lied).

These are some of my remarks about the current state of the Lisk.
If you would like to talk about some topic related to Lisk, let me know in the comments – Przemek.