Develop Blockchain Apps with Sidechain Technology — Part 2

Part 1 — Installing the blockchain
Part 2 — Create your first sidechain
Part 3 — Build Frontend for Sidechain DApp (Coming Soon)
Part 4 — Understanding Blockchain and Sidechain Architecture (Coming Soon)
Part 5 — Issue Own Token (Coming Soon)

In Part 1 we learned how to install the ASCH Blockchain.
In this part, we will create our own separate sidechain. A sidechain with its own history of blocks and an adaptable data structure, that fits our needs.

Download the code for this tutorial as .zip or view it on Github

ASCH Main Chain

The following graphic represents the main chain of ASCH. The main chain is a network of nodes, very much like a distributed database. A blockchain, so to speak.

ASCH Sidechain Technology

Every sidechain is also a blockchain, which operates separately with its own nodes. The sidechain can interact with the mainchain.

The figure below illustrates the relationship between the main chain and its sidechains.

Sidechain Advantages

To better understand sidechain technology, let’s use Ethereum as an example, which is not using sidechain technology. Every transaction on the Ethereum network is recorded on every blockchain nodes, which are verified by miners. In 2017, CryptoKitties, a decentralized application (game) on Ethereum, generated so much traffic on the Ethereum network and caused a congestion to the whole network. (Source: BBC). However, this CryptoKitties incident wouldn’t have happened with sidechain technology.
With sidechain technology, DApps like CryptoKitties can run on a sidechain — a separate blockchain. This sidechain handles all transactions including trading, breeding and the generation of CryptoKitties. The game, therefore, will not congest the main blockchain network anymore.

Sidechain vs DApp Terminology

On the ASCH Blockchain we can use the word Sidechain interchangeably with the word DApp (Decentralized Application). The word Sidechain describes a network of nodes that communicate with the main chain and these nodes work for one Decentralized Application (DApp). We call it decentralized because the application is run by a set of distributed nodes.

Note:
Sidechain = DApp 
These two keyword are the exact same thing on the ASCH blockchain.

Our Development Setup

For development purposes, we make things easier and use only a single node for the main chain and a single node for our sidechain which both run locally on our computer. 
That is how our setup will look like:
The main chain is located in the asch folder, the Sidechain is located in the sidechain folder.

Folder Structure

Firstly, we have to setup our folder structure for our sidechain. The main chain is located in the asch folder (which we have installed in Part 1). We will now build our own blockchain, a side chain that operates on its own and communicates with the main blockchain.

Create the following folder structure:

# create sidechain directory
mkdir sidechain

# change directory
cd sidechain
# create directories
mkdir contract interface model public

New Files

Create the following file structure:

model/article.js

In the model directory create a new file model/article.js. Paste this content into it.

// file-name: model/article.js

module.exports = {
name: 'articles',
fields: [
{
name: 'id',
type: 'String',
length: '20',
not_null: true,
primary_key: true
},
{
name: 'tid',
type: 'String',
length: 64,
not_null: true,
unique: true
},
{
name: 'authorId',
type: 'String',
length: 50,
not_null: true
},
{
name: 'title',
type: 'String',
length: 256,
not_null: true
},
{
name: 'text',
type: 'String',
length: 4096,
not_null: true,
},
{
name: 'votes',
type: 'Number',
not_null: true
},
{
name: 'timestamp',
type: 'Number',
not_null: true
}
]
}

This statement creates a new articles table in our sidechain SQL Database.
This table will be used to save new articles in it.
We will discuss more about this topic later.

contract/article.js

In the contract directory, create a new file contract/article.js. Paste this content into it. Later we will register this contract.

// file-name: contract/article.js

module.exports = {
createArticle: async function (title, text) {
if (!title) {
return 'no_title: Should provide title1'
}
if (!text) {
return 'no_text: Should provide text'
}
if (title.length > 256) {
return 'title_too_long: Title should not be longer than 256 characters'
}
if (text.length > 4096) {
return 'text_too_long: Text should not be longer than 4096 characters'
}

let exists = await app.model.Article.exists({ title: title })
if (exists) {
return `title_already_in_use: Title "${title}" already in use`
}

app.sdb.create('Article', {
id: app.autoID.increment('article_max_id'),
tid: this.trs.id,
authorId: this.trs.senderId,
title: title,
text: text,
votes: 0,
timestamp: this.trs.timestamp
})
}
}

init.js

Now open init.js in your favourite text editor and paste the following content.

// file-name: init.js

module.exports = async function () {
app.logger.info('enter dapp init')

// register createArticle smart contract
app.registerContract(1000, 'article.createArticle')
// set fee for createArticle to 1 XAS
app.registerFee(1000, '100000000', 'XAS')
}

With the call to app.registerContract , we register the createArticle contract-function as the contract 1000. The number 1000 has no special meaning. If we want to refer to this contract later in the code we will simply call 1000.
We set the fee for creating a new article to 1 XAS. XAS has 8 decimal places. Therefore we write '100000000' instead of '1'.

Detail documentation on how to register contracts: Register Contract

interface/article.js

In order to get access to new articles we need to add a public REST-Endpoint to our blockchain.

Endpoint: http://localhost:4096/api/dapps/<dappId>/articles 
HTTP Verb: GET 
Returns: JSON

Add a new file article.js into the directory interface.

// file-name: interface/article.js

app.route.get('/articles', async (req) => {

// load all articles
let articles = await app.model.Article.findAll({
limit: 50,
offset: 0,
sort: { timestamp: -1 }
})
return articles
})

dapp.json

Create a new file dapp.json

{
"name": "test",
"link": "https://test.zip",
"category": 1,
"description": "A hello world demo for asch dapp",
"tags": "asch,dapp,demo",
"icon": "http://o7dyh3w0x.bkt.clouddn.com/hello.png",
"type": 0,
"delegates": [
"db18d5799944030f76b6ce0879b1ca4b0c2c1cee51f53ce9b43f78259950c2fd",
"590e28d2964b0aa4d7c7b98faee4676d467606c6761f7f41f99c52bb4813b5e4",
"bfe511158d674c3a1e21111223a49770bee93611d998e88a5d2ea3145de2b68b",
"7bbf62931cf3c596591a580212631aff51d6bc0577c54769953caadb23f6ab00",
"452df9213aedb3b9fed6db3e2ea9f49d3db226e2dac01828bc3dcd73b7a953b4"
],
"unlockDelegates": 3
}

genesis.json

Create a new file genesis.json. This is the genesis block of our sidechain. The genesis block is the first block on our Sidechain.

{
"delegate": "a7cfd49d25ce247568d39b17fca221d9b2ff8402a9f6eb6346d2291a5c81374c",
"height": 1,
"pointId": null,
"pointHeight": null,
"transactions": [],
"timestamp": 0,
"payloadLength": 0,
"payloadHash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"count": 0,
"signature": "287818ef81b51375cc1cc36b62e3f3b8027d8334633828fee0801d9033a0da60a9ca182ac4435c663aabae141563c06c6cd55d494bce1d2dae92e9da8ace0205",
"id": "cee2f87f98d0344646ae726af4df3bb1bddcceecc64053f36d16d1281aa90215"
}

config.json

Create a new file config.json. With this file we enable 5 different accounts for forging on our Sidechain. Forging is the process that creates new blocks and verifies transactions. Forging is very similar to Mining on the Etherium network.

{
"peers": [],
"secrets": [
"flame bottom dragon rely endorse garage supply urge turtle team demand put",
"thrive veteran child enforce puzzle buzz valley crew genuine basket start top",
"black tool gift useless bring nothing huge vendor asset mix chimney weird",
"ribbon crumble loud chief turn maid neglect move day churn share fabric",
"scan prevent agent close human pair aerobic sad forest wave toe dust"
]
}

public/index.html

Create an empty html file in the public folder.

touch public/index.html

Now we should have the following new file structure.

Create Articles with REST calls

Our decentralized application is ready for the creation of some articles.

In this part of the series, we create articles only through HTTP node.js requests. This is for demonstration purposes only.
In Part 3, we will build a Vue.js GUI around our DApp backend.

Our folder structure will look like this:

Create a new directory api_access in the sidechain directory

mkdir api_access

Change directory to api_access

cd api_access

Create a package.json file with the following command

npm init --yes

Install all needed dependencies:

npm install asch-js axios commander --save

Create a new file index.js for the api access.

// file-name api_access/index.js
const axios = require('axios')
const aschJS = require('asch-js')
const program = require('commander')
let dappId = '4a5e158db7248d5e8b0eb503d048320bbf21a935a74d63e5f98f578bd8fb2d2b'
let mySecret = 'sentence weasel match weather apple onion release keen lens deal fruit matrix'

let post = (title, text) => {
console.log('post')
const signedTransactionsUrl = `http://localhost:4096/api/dapps/${dappId}/transactions/signed`
let option = {
fee: '100000000',
type: 1000,
args: JSON.stringify([title, text])
}
  // sign transaction
let transaction = aschJS.dapp.createInnerTransaction(option, mySecret)
let data = {
transaction: transaction
}
let headers = {
headers: {
'magic': '594fe0f3', 'version': ''
}
}
  // send signed transaction to Sidechain
return axios.put(signedTransactionsUrl, data, headers)
.then((result) => {
console.log('result:')
console.log(JSON.stringify(result.data, null, 2))
})
.catch((error) => {
console.log('Be sure to have the right "<dapp Id>" set!')
console.error(error.message)
})
}
let get = (id) => {
const url = `http://localhost:4096/api/dapps/${dappId}/articles`
  return axios.get(url)
.then((result) => {
console.log(JSON.stringify(result.data, null, 2))
})
.catch((error) => {
console.log('Be sure to have the right "<dapp Id>" set!')
console.error(error.message)
})
}
program
.command('postArticle [title] [content]')
.action(function (title, content) {
post(title, content)
.then(() => {
})
})

program
.command('getArticle [id]')
.action(function (id) {
get(id)
.then(() => {
})
})
program.on('--help', function () {
console.log('')
console.log(' Examples:')
console.log(' postArticle "hello" "my first article"')
console.log(' getArticle 2')
console.log('')
})
if (!process.argv.slice(2).length) {
program.outputHelp()
}
program.parse(process.argv)

Warning:
Be sure to set the correct <dapp Id> in index.js after the DApp has been registered (no worries, we will register it in the next step)

Install necessary Tooling

With the asch-redeploy tool we can continuously register and install our DApp to the local blockchain every time a file changes.

npm install --global asch-redeploy

Register our DApp

We installed asch-redeploy. Now we can use it to register our DApp on the local blockchain.

Check that you are located in the sidechain folder:

pwd
# output
/home/sidechain

Start

Run asch-redeploy to watch for file changes on our DApp.

asch-redeploy

Asch-redeploy will automatically register our new DApp on the mainchain.
This process can take a few seconds. You will get the dappId from the registration. This is the unique identifier for your DApp.

DAppID

The new <dapp Id> for my DApp is 59d24769645a04b2a759d61d874cde3a5033eacab00cdedce77d4f21a8ea9bce (yours will be different)

Edit file api_access/index.js

Your new <dapp Id> should be pasted into api_access/index.js

const axios = require('axios')
const aschJS = require('asch-js')
const program = require('commander')
// paste your unique dappId here
let dappId = 'paste <dapp Id> here'

Change Directory

Be sure to start a new terminal window and change directory to api_access.
In the other terminal windows should still run our asch-redeploy process:

cd api_access

Create new article

Now execute the following command that adds a new article to our Dapp in our new terminal window:

node index.js postArticle "My Title" "My Content"
# return message from the Sidechain (Dapp)
{
"transactionId": "ad83258e73679d15a539f774f9f003b416d00817dab2232bbc17cec9adea69bd",
"success": true
}

Get articles

In order to see the articles that were already saved on the DApp, execute the following code in our new terminal window:

node index.js getArticle
# return message from the Dapp
[
{
"id": "1",
"tid": "ad83258e73679d15a539f774f9f003b416d00817dab2232bbc17cec9adea69bd",
"authorId": "AHMCKebuL2nRYDgszf9J2KjVZzAw95WUyB",
"title": "Title",
"text": "Content",
"votes": 0,
"timestamp": 62705044,
"t_timestamp": 62705044,
"t_type": 1000,
"t_height": 99
}
]

Saved articles

Here can you see the new saved articles we created through our REST API calls? This is a SQL table of our DApp. We adopted the sidechain SQL database to our needs and addedarticles table to it.

Sidechain uncustomized

Without customization, the sidechain SQL Database schema would look like this:

Sidechain customized

After the addition of the articles table, our sidechain SQL database looks like this:

Conclusion

We have built our first very simple decentralized application (DApp) in this tutorial.
In Part 3 we will build a GUI in Vue.js for our simple DApp.

Task

Your task will be to implement the upvoting of articles. Be sure to register a new contract.

Download

Download the code for this tutorial as .zip or view it on Github

Further Learning

Question

If you have any sort of question, please ask them on the gitter-chat gitter.im/asch-development

Documentation

If you want to dig deeper into DApp Development on your own, you can read these documents:

Sample DApps

  1. CCTime

2. Hello-World