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.jsconst 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
- CCTime
2. Hello-World
- Sidechain Frontend and Backend
Learn More About ASCH:
Website: https://www.asch.io/
Github: https://github.com/AschPlatform
Telegram: https://t.me/Asch_En
Twitter: https://twitter.com/Asch_io
ASCH BBS: https://bbs.asch.io/
Facebook: https://www.facebook.com/AschHQ/
Reddit: https://www.reddit.com/r/Asch_Platform/
Gitter Chatroom: https://gitter.im/asch-development