Blockchain: what should we build PoC?

The eyes are afraid, and the hands itch!



In past articles, we figured out the technologies on which blockchains are built ( What should we build a blockchain for? ) And cases that can be implemented with their help ( What should we build a case? ). It’s time to work with your hands! For the implementation of pilots and PoC (Proof of Concept), I prefer to use clouds, because they can be accessed from anywhere in the world and often do not have to spend time tedious installation of the environment, because There are predefined configurations. So, let's do something simple, for example, a network for transferring coins between participants and call it modestly Citcoin. For this, we will use the IBM cloud and the universal blockchain Hyperledger Fabric. First, let's see why Hyperledger Fabric is called a universal blockchain?



image



Hyperledger Fabric - a universal blockchain



Generally speaking, the universal information system is:





image



The official version of what Hyperledger Fabric is can be read on the site , and in short, Hyperledger Fabric is an opensource platform that allows you to build closed blockchains and execute arbitrary smart contracts written in the JS and Go programming languages. Let's take a look at the architecture of the Hyperledger Fabric in detail and make sure that it is a universal system that only has the specifics of storing and recording data. The specificity is that the data, as in all blockchains, is stored in blocks that are placed on the blockchain only if the participants reached a consensus and after recording the data cannot be discreetly corrected or deleted.



Hyperledger Fabric Architecture



The diagram shows the architecture of the Hyperledger Fabric:



image



Organizations - organizations contain peers, i.e. blockchain exists due to the support of organizations. Different organizations may be members of the same channel.



Channel - a logical structure that unites peers into groups, i.e. Blockchain is set. Hyperledger Fabric can simultaneously process several blockchains with different business logic.



Membership Services Provider (MSP) is a CA (Certificate Authority) for issuing identity and assigning roles. To create a node, you need to interact with MSP.



Peer nodes - verify transactions, store the blockchain, execute smart contracts and interact with applications. Peers have an identity (digital certificate) that issues an MSP. Unlike the Bitcoin or Etherium network, where all nodes are equal, in the Hyperledger Fabric nodes play different roles:





Assets are entities of value that are stored on the blockchain. More specifically, this is key-value data in JSON format. It is these data that are recorded in the Blockchain. They have a story that is stored on the blockchain and the current state, which is stored in the World state database. Data structures are filled randomly depending on business tasks. There are no required fields, the only recommendation is that assets should have an owner and be valuable.



Ledger - consists of the blockchain "Blockchain" and the database "Word state", which stores the current state of the assets. World state uses LevelDB or CouchDB.



Smart contract - using smart contracts, the business logic of the system is implemented. In Hyperledger Fabric, smart contracts are called chaincode. With the help of chaincode, assets and transactions over them are defined. Speaking in technical language, smart contracts are software modules implemented in the JS or Go programming languages.



Endorsement policy - for each chaincode, you can set how many policies and from whom you want to expect confirmations for the transaction. If the policy is not set, then by default it is used: “the transaction must be confirmed by any member of any organization in the channel”. Examples of policies:





Ordering service - packs transactions into blocks and sends peers to the channel. Guarantees delivery of messages to all peers on the network. For industrial systems, the Kafka message broker is used to develop and test Solo .



Callflow



image





Those. it turns out the separation of roles between nodes. This provides scalability and blockchain security:





For more information on Hyperledger Fabric's architectural solutions and why it works this way, you can look here: Architecture Origins or here: Hyperledger Fabric: A Distributed Operating System for Permissioned Blockchains .



So, Hyperledger Fabric is a truly universal system with which you can:





Now that we’ve figured out the specifics of the Hyperledger Fabric a bit, let's finally do something useful!



Expand Blockchain



Formulation of the problem



The task is to implement the Citcoin network with the following functions: create an account, get a balance, replenish an account, transfer coins from one account to another. We will draw an object model, which we will further implement in a smart contract. So, we will have accounts that are identified by names and contain a balance and a list of accounts. Accounts and a list of accounts are in terms of Hyperledger Fabric assets. Accordingly, they have a history and current status. I'll try to draw it clearly:



image



The upper figures are the current state, which is stored in the World state database. Below them are figures showing the story that is stored on the blockchain. The current state of assets is changed by transactions. Asset changes only in its entirety, therefore, as a result of the transaction, a new object is created, and the current value of the asset goes into history.



IBM Cloud



Create an account in the IBM cloud . To use the blockchain platform, you need to upgrade it to Pay-As-You-Go. This process may not be fast, because IBM requests additional information and verifies it manually. From the positive, I can say that IBM has good training materials that allow you to deploy Hyperledger Fabric in their cloud. I liked the following series of articles and examples:





The following are screenshots of the IBM Blockchain platform. This is not an instruction for creating a blockchain, but simply a demonstration of the scope of the task. So, for our purposes, we make one Organization:



image



In it we create nodes: Orderer CA, Org1 CA, Orderer Peer:



image



We start users:



image



Create a Channel and call it citcoin:



image



In essence, Channel is a blockchain, so it starts with a zero block (Genesis block):



image



Writing a Smart Contract



/* * Citcoin smart-contract v1.5 for Hyperledger Fabric * (c) Alexey Sushkov, 2019 */ 'use strict'; const { Contract } = require('fabric-contract-api'); const maxAccounts = 5; class CitcoinEvents extends Contract { async instantiate(ctx) { console.info('instantiate'); let emptyList = []; await ctx.stub.putState('accounts', Buffer.from(JSON.stringify(emptyList))); } // Get all accounts async GetAccounts(ctx) { // Get account list: let accounts = '{}' let accountsData = await ctx.stub.getState('accounts'); if (accountsData) { accounts = JSON.parse(accountsData.toString()); } else { throw new Error('accounts not found'); } return accountsData.toString() } // add a account object to the blockchain state identifited by their name async AddAccount(ctx, name, balance) { // this is account data: let account = { name: name, balance: Number(balance), type: 'account', }; // create account: await ctx.stub.putState(name, Buffer.from(JSON.stringify(account))); // Add account to list: let accountsData = await ctx.stub.getState('accounts'); if (accountsData) { let accounts = JSON.parse(accountsData.toString()); if (accounts.length < maxAccounts) { accounts.push(name); await ctx.stub.putState('accounts', Buffer.from(JSON.stringify(accounts))); } else { throw new Error('Max accounts number reached'); } } else { throw new Error('accounts not found'); } // return object return JSON.stringify(account); } // Sends money from Account to Account async SendFrom(ctx, fromAccount, toAccount, value) { // get Account from let fromData = await ctx.stub.getState(fromAccount); let from; if (fromData) { from = JSON.parse(fromData.toString()); if (from.type !== 'account') { throw new Error('wrong from type'); } } else { throw new Error('Accout from not found'); } // get Account to let toData = await ctx.stub.getState(toAccount); let to; if (toData) { to = JSON.parse(toData.toString()); if (to.type !== 'account') { throw new Error('wrong to type'); } } else { throw new Error('Accout to not found'); } // update the balances if ((from.balance - Number(value)) >= 0 ) { from.balance -= Number(value); to.balance += Number(value); } else { throw new Error('From Account: not enought balance'); } await ctx.stub.putState(from.name, Buffer.from(JSON.stringify(from))); await ctx.stub.putState(to.name, Buffer.from(JSON.stringify(to))); // define and set Event let Event = { type: "SendFrom", from: from.name, to: to.name, balanceFrom: from.balance, balanceTo: to.balance, value: value }; await ctx.stub.setEvent('SendFrom', Buffer.from(JSON.stringify(Event))); // return to object return JSON.stringify(from); } // get the state from key async GetState(ctx, key) { let data = await ctx.stub.getState(key); let jsonData = JSON.parse(data.toString()); return JSON.stringify(jsonData); } // GetBalance async GetBalance(ctx, accountName) { let data = await ctx.stub.getState(accountName); let jsonData = JSON.parse(data.toString()); return JSON.stringify(jsonData); } // Refill own balance async RefillBalance(ctx, toAccount, value) { // get Account to let toData = await ctx.stub.getState(toAccount); let to; if (toData) { to = JSON.parse(toData.toString()); if (to.type !== 'account') { throw new Error('wrong to type'); } } else { throw new Error('Accout to not found'); } // update the balance to.balance += Number(value); await ctx.stub.putState(to.name, Buffer.from(JSON.stringify(to))); // define and set Event let Event = { type: "RefillBalance", to: to.name, balanceTo: to.balance, value: value }; await ctx.stub.setEvent('RefillBalance', Buffer.from(JSON.stringify(Event))); // return to object return JSON.stringify(from); } } module.exports = CitcoinEvents;
      
      





Intuitively, everything should be clear here:





Next, upload the smart contract to Channel and install it:



image



We look at the transaction for installing Smart Contract:



image



We look at the details of our Channel:



image



As a result, we get the following blockchain network diagram in the IBM cloud. Also on the diagram there is a demo program running in the Amazon cloud on a virtual server (it will be described in detail in the next section):



image



Creating a GUI for Hyperledger Fabric API Calls



Hyperledger Fabric has an API that can be used to:





Application development



In our demo program, we will use the API only to invoke transactions and request information, because we have already taken the remaining steps using the IBM blockchain platform. We write a GUI using a standard technology stack: Express.js + Vue.js + Node.js. You can write a separate article on how to start creating modern web applications. Here I will leave a link to the lecture series that I liked the most: Full Stack Web App using Vue.js & Express.js . The result is a client-server application with a familiar graphical interface in the style of Material Design from Google. The REST API between a client and a server consists of several calls:





I put the API description with examples on the Postman website , a well-known program for testing the HTTP API.



Amazon Cloud Demo App



The application was uploaded to Amazon, because IBM has so far failed to upgrade my account and allow the creation of virtual servers. How the cherry attached the domain: www.citcoin.info . I will keep the server turned on for a bit, then turn it off, because cents for rent are dripping, and citcoin coins are not yet quoted on the exchange) I place screenshots of a demo in the article so that the logic of work is clear. Demo application can:





First, initialize the blockchain:



image



Next, start your account, do not trifle with balance:



image



We get a list of all available accounts:



image



We select the sender and the recipient, we get their balances. If the sender and the recipient are the same, then their account will be replenished:



image



In the log, we monitor the execution of transactions:



image



Actually, with a demo program, that's all. Next, you can see our transaction in the blockchain:



image



And a general list of transactions:



image



With this, we successfully completed the implementation of PoC to create the Citcoin network. What else needs to be done for Citcoin to become a full-fledged coin transfer network? Very little:





Conclusion



We have implemented a Citcoin network with functions: add an account, get a balance, replenish your account, transfer coins from one account to another. So, what did it cost us to build PoC?





Of course, not rocket science, but you have to sweat!



GitHub sources



He put the source code on GitHub . A brief description of the repository:

Directory " server " - Node.js server

Directory " client " - Node.js client

The " blockchain " directory (parameter values ​​and keys, of course, are inoperative and are given only as an example):





It's only the beginning!



All Articles