Blockchain traceability case development based on Ethereum

The demo of the Ethereum traceability solution is easy to be familiar with the blockchain on-chain and traceability process, including the Ethereum network construction, contract development and deployment, and back-end gateway development of a complete set of codes.

More blockchain technology and application classification:

Blockchain applicationBlockchain     development

Ethernet Square | Fabric | BCOS | cryptography | consensus algorithm | bitcoinOther chain

Token EconomyTraditional Financial Scenarios | Decentralized Finance | Anti-counterfeiting Traceability | Data Sharing | Trusted Deposit

 

A traceability solution based on Ethereum, you can run a demo to experience the characteristics of Ethereum. As shown in the figure, the overall architecture design of the demo of this project is divided into three layers: application layer (APP), service layer (Nodejs-service), and blockchain layer (Ethereum). The design ideas and solutions can be seen below content. By requesting the service layer, the application layer transfers the operation of operating the blockchain to the service layer, avoiding direct operation of the blockchain, and many things can be done at the service layer, such as permission control to check user operations, message queues to avoid congestion, etc. , The core function is to separate the requests from the APP according to different business, and further operate different methods on the smart contract. The blockchain network layer runs Ethereum nodes, deploys smart contracts on it, and processes data from the service layer.

 

Blockchain traceability case development based on Ethereum

Figure 0-1 Traceability project architecture design

Based on the above design framework, this article is divided into three parts to elaborate:

The first part, the establishment of the Ethereum network, introduces the construction process of the Ethereum private chain. Regardless of the subsequent contract logic, this chapter is the general technology for building the Ethereum private chain.

The second part, contract development and deployment, introduces the design logic and scheme of the contract, and attaches the source code.

The third part, background development, is the service layer development based on nodejs, as the medium between the user App and the blockchain network, and introduces how to respond to user requests and then operate the blockchain. Then we will introduce how users can interact with the blockchain using this layer of API services.

The first part of the Ethereum network construction

1. Download the geth client

(1) Download

Go to the website https://geth.ethereum.org/downloads/ to download the geth client. You can download the matching geth according to different operating systems.

(2) Installation

Click directly on the binary package to install it.

2. Use geth to generate an account

(1) Use the geth command: geth account new

(2) Enter the password, geth will automatically generate the keystore file according to the user input, (the default path is C:\Users\Administrator.xxx\AppData\Roaming\Ethereum)

(3) Create a data directory data0 anywhere in the system as a directory for synchronizing Ethereum data.

(4) Copy the above keystore file to the data0 folder

(5) Pre-generate n accounts according to the above method, and put the password file (with carriage return and line feed) corresponding to each account into the same level directory of data0 and save it as pwd.

Tip: The keystore of the miner's account must exist in "extraData", such as:

"extraData": "0x0000000000000000000000000000000000000000000000000000000000000000e578252579e5f43fe124fe1d8236f0e5250c11970000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"

The red part is the address of miner.

3. Configure the genesis block

Create a founding block configuration file in the same-level directory of data0, and fill in the alloc field of the configuration file with the account generated above, and allocate the initial Ether in custom:

4. Initialization

Go to the Ethereum data directory and use the geth command:

geth --datadir data0 init Genesis.json

5. Start the geth command

(For detailed explanation of each parameter, please use geth --help to query)

6. Other

After the Ethereum node starts normally, use the built-in API (web3) to perform the following operations:

Start mining: miner.start()

Stop mining: miner.stop()

Generate a new account: personal.newAccount()

View mining rewarders: eth.coinbase

Transfer transactions between accounts:

amount = web3.toWei(5,'ether')
 
personal.unlockAccount(eth.accounts[0])
 
eth.sendTransaction({from:eth.accounts[0],to:eth.accounts[1],value:amount})

The second part of contract development and deployment

1. Business needs

Let's take drug traceability as an example. In the entire business scenario, business nodes can be divided into three categories, drug manufacturers, agents, and retailers; data can be divided into two parts, drug information and circulation information. Drug information is added by drug manufacturers when they produce drugs, and drug circulation information is added by agents and retailers on the circulation channel, as shown in Figure 2-1. When adding data to the blockchain, use the product ID + this business node information to upload.

 

Blockchain traceability case development based on Ethereum

Figure 2-1 Drug traceability business

2. Contract data structure

The contract is developed using solidity, based on the above business requirements, using solidity's built-in struct and mapping data types, and nesting. Get the data structure available for drug traceability:

The storage structure of traceability information is shown in Figure 2-2. It consists of a mapping+struct nested structure. On the left is a mapping set. Each mapping element is a key-value pair, and the "key" is the ID value, through which the corresponding ID can be obtained. The Struct contains two parts: "drug information" and "traceability information". When querying, find out the Strcut whose "key" is "NWRuxXJ75fBWUjBZi" in Mapping through the ID number (such as NWRuxXJ75fBWUjBZi coded by the QR code). The Strcut data is {dragInfo:999 cold medicine, Harbin Medicine Sixth Factory, traceInfo: agent A=>Agent B=>Retailer X}

 

Blockchain traceability case development based on Ethereum

Figure 2-2 Contract storage structure

3. Development preparation

(1) Solidity

Solidity is a high-level language for smart contracts similar to JavaScript. It runs on the Ethereum Virtual Machine (EVM). It is designed to generate Ethereum virtual machine code in a compiled manner. It is the official recommended language for developing Ethereum smart contracts.

(2) Truffle

Truffle is a world-class development environment, test framework, and Ethereum resource management channel. It is dedicated to making development on Ethereum easier. Truffle has the following:

Built-in smart contract compilation, linking, deployment and management of binary files.

Automatic contract testing under rapid development.

Scripted, extensible deployment and release framework.

Network environment management function deployed to no matter how many public or private networks

Use the package management provided by EthPM&NPM and use the ERC190 standard.

A direct interactive console that directly communicates with the contract (you can verify it on the command line after writing the contract).

The configurable build process supports tight integration.

Support the execution of external scripts in the Truffle environment.

4. Contract code

Note: Since solidity0.4 version does not support traversal of nested structure mapping, traceability information is added in the form of character splicing to facilitate direct display.

pragma solidity  ^0.4.24;  
 
import "./strings.sol";  
contract testTraceability_addTime {  
 
 
	using strings for *;  
	string constant optStr = "==>";  
	string constant leftOpt = "(";  
	string constant rightOpt = ")";  
	event SavedProducer(uint256 dragId,string dragInfo,string[] traceInfo);  
 
	struct Drag {  
		string dragInfo;  
		string traceInfo;  
	}  
 
	mapping(string => Drag) allDragsInfo;  
 
	constructor () public{  
	}  
 
	function getDrugInformationWithID(string id) returns(string memory,string memory){  
		return(allDragsInfo[id].dragInfo,allDragsInfo[id].traceInfo);  
	}  
 
	function addDragInfo_init(string ID,string memory dragInfomation,string memory company,string memory time) public {  
		allDragsInfo[ID].dragInfo = dragInfomation;  
		string memory info1 = time.toSlice().concat(rightOpt.toSlice());  
		string memory info2 = leftOpt.toSlice().concat(info1.toSlice());  
		string memory info3 = company.toSlice().concat(info2.toSlice());  
		string memory concatStr = info3.toSlice().concat(optStr.toSlice());  
		allDragsInfo[ID].traceInfo = concatStr;  
	}  
 
 
	function addDragInfo_A(string ID,string memory company,string memory time) public {  
		string memory info1 = time.toSlice().concat(rightOpt.toSlice());  
		string memory info2 = leftOpt.toSlice().concat(info1.toSlice());  
		string memory info3 = company.toSlice().concat(info2.toSlice());  
		string memory concatStr = info3.toSlice().concat(optStr.toSlice());  
		allDragsInfo[ID].traceInfo = allDragsInfo[ID].traceInfo.toSlice().concat(concatStr.toSlice());  
	}  
 
	function addDragInfo_B(string ID,string memory company,string memory time) public {  
		string memory info1 = time.toSlice().concat(rightOpt.toSlice());  
		string memory info2 = leftOpt.toSlice().concat(info1.toSlice());  
		string memory info3 = company.toSlice().concat(info2.toSlice());  
		string memory concatStr = info3.toSlice().concat(optStr.toSlice());  
		allDragsInfo[ID].traceInfo = allDragsInfo[ID].traceInfo.toSlice().concat(concatStr.toSlice());  
	}  
 
	function addDragInfo_C(string ID,string memory company,string memory time) public {  
		string memory info1 = time.toSlice().concat(rightOpt.toSlice());  
		string memory info2 = leftOpt.toSlice().concat(info1.toSlice());  
		string memory info3 = company.toSlice().concat(info2.toSlice());  
		string memory concatStr = info3.toSlice().concat(optStr.toSlice());  
		allDragsInfo[ID].traceInfo = allDragsInfo[ID].traceInfo.toSlice().concat(concatStr.toSlice());  
	}  
}  

5. Contract description

For traceability data structure operations, there are operation methods such as addDragInfo_init, addDragInfo_A, addDragInfo_B, addDragInfo_C, and getDrugInformationWithID C. addDragInfo_init is a method for drug manufacturers to add information, addDragInfo_A, addDragInfo_B, and addDragInfo_C are three methods for node operations on the distribution channel of WithIDDrugInformation. The user uses the product ID to obtain all traceability information.

6. Use truffle for contract deployment

(1) Install truffle

Install truffle's npm package globally:

npm install truffle -g

(2) truffle initialization

Enter the project directory and run the following command:

truffle init

(3) Modify related configuration files

Modify the three files shown in Figure 2-3:

 

Blockchain traceability case development based on Ethereum

Figure 2-3 Related configuration files for truffle operation

Introduce these three files:

1_initial_migration.js (default migration contract)

var Migrations = artifacts.require("./Migrations.sol");  
module.exports = function(deployer) {  
   deployer.deploy(Migrations);  
}; 

2_deploy_contracts.js (Configure the contracts that need to be deployed)

var testTraceability = artifacts.require("./testTraceability.sol");  
var testTraceability_addTime = artifacts.require("./testTraceability_addTime.sol");  
var strings = artifacts.require("./strings.sol");  
 
module.exports = function(deployer) {  
	deployer.deploy(strings,  {from:"0xe578252579e5f43fe124fe1d8236f0e5250c1197"});// 部署合约,使用旷工地址(保证gas费充足)  
	deployer.link(strings, testTraceability);   // 库链接  
	deployer.deploy(testTraceability,  {from:"0xe578252579e5f43fe124fe1d8236f0e5250c1197"});// 部署合约  
	deployer.deploy(testTraceability_addTime,  {from:"0xe578252579e5f43fe124fe1d8236f0e5250c1197"});// 部署合约  
};  

3_truffle.js (Configure information related to the target Ethereum)

/*  
  *  NB:  since  truffle-hdwallet-provider  0.0.5  you  must  wrap  HDWallet  providers  in  a    
  *  function  when  declaring  them.  Failure  to  do  so  will  cause  commands  to  hang.  ex:  
  *  ```  
  *  mainnet:  {  
  *          provider:  function()  {    
  *              return  new  HDWalletProvider(mnemonic,  'https://mainnet.infura.io/<infura-key>')    
  *          },  
  *          network_id:  '1',  
  *          gas:  4500000,  
  *          gasPrice:  10000000000,  
  *      },  
  */    
//  Allows  us  to  use  ES6  in  our  migrations  and  tests.   
 
require('babel-register')({  
	ignore: /node_modules\/(?!zeppelin-solidity)/  
});  
 
require('babel-polyfill');  
module.exports = {  
   //See <http://truffleframework.com/docs/advanced/configuration>  
   //to customize your Truffle configuration!  
    networks: {  
        development: {  
            host: "127.0.0.1",//合约部署的以太坊节点ip  
            port: 7545,       //合约部署的以太坊节点端口  
            network_id: "*",  // 以太坊网络id  
            gas: 8000000      // 合约部署gas上限  
         }  
     },  
     mocha: {  
         useColors: true  
     },  
     solc: {  
         optimizer: {  
             enabled: true,  
             runs: 200  
         }  
     }  
 };  

(4) Compile the contract

Run in the project directory:

truffle compile

truffle compile --all (recompile all)

(5) Migration contract

Run in the project directory

truffle migrate

truffle migrate --reset (all re-execute the migration script)

The third part of background development

1. Background development instructions

This blockchain network is based on the Ethereum private chain. Therefore, in order to ensure data security and reliability, users cannot directly operate the blockchain and must use middleware services. Therefore, the node middleware is developed, which can control the data on the chain, and can do some other necessary services, such as rights management, message queues, block data temporary storage and so on.

2. Demand analysis

It is known from the second part that the three types of business nodes (producers, sellers, and retailers) need to upload data to the blockchain respectively, and must be based on intermediate services, rather than directly operating the blockchain. Therefore, the background architecture shown in Figure 3-1 is adopted, that is, all users on the B-side and C-side are based on the middleware node service to indirectly operate or access the blockchain. Therefore, according to the different functions of each user, different API services are opened, and each user performs different transactions on the blockchain. As shown in the figure, in simple terms, the drug manufacturer, agent A, agent B, and retailer write data to the blockchain, and users read data from the blockchain.

 

Blockchain traceability case development based on Ethereum

Figure 3-1 Node background architecture diagram

3. Development preparation

(1) Nodejs

JavaScript is the most widely used in the entire open source community. At present, most of the projects corresponding to the JavaScript language are based on the Node.js platform, so Nodejs is well-deserved and one of the most popular development platforms. Nodejs is a JavaScript instant running platform on Chrome V8 under construction. It uses a time-driven and non-blocking I/O model. It is lightweight and efficient, and is very suitable for data-intensive, real-time applications, such as stocks, funds, and cryptocurrencies. Wait. In particular, Nodejs' package management tool npm has become the most active community in the world. There are a lot of third-party packages for developers to choose from, and most of the blockchain-related components are developed and applied in the form of npm packages. , So Nodejs is a powerful tool for blockchain development.

Use: Nodejs environment installation

(2) Express

Express is a simple and flexible node.js web application framework, providing a series of powerful features to help you create various web applications, and a wealth of HTTP tools. Using Express can quickly build a full-featured website, and supports various HTTP utilities and middleware, quickly and easily create powerful APIs.

Use: Import npm package.

(3) web3 API

The Ethereum network is composed of nodes, and each node contains a copy of the blockchain. When we need to call a method in a smart contract, we need to find and tell it from one of the nodes. Ethereum nodes can only recognize a language called JSON-RPC, which is not very readable. Web3.js can hide these obscure query statements, and only need to interact with the easy-to-understand JavaScript interface.

web3.js is a Javascript library provided by Ethereum. It encapsulates the JSON RPC API of Ethereum and provides a series of Javascript objects and functions that interact with the blockchain, including viewing network status, viewing local accounts, viewing transactions and zones Blocks, sending transactions, compiling/deploying smart contracts, calling smart contracts, etc. The most important of these is the API that interacts with smart contracts. Therefore, to develop projects based on Ethereum, you must be familiar with the common APIs in web3js.

Use: Import npm package.

4.node code

Develop a simple node server through nodejs+express+web3js and expose API interfaces to the outside world. The external call API service through Http request to operate the blockchain.

const web3 = require('web3');  
const ethRPC = "ws://localhost:8546";  
const serverPort = 10999;  
const provider = new web3.providers.WebsocketProvider(ethRPC);  
const web3Client = new web3(provider);  
const coinbase = '0xe578252579e5f43fe124fe1d8236f0e5250c1197';  
const contract = require("truffle-contract");  
const express = require('express');  
const app = express();  
const cors = require('cors');  
 
app.use(cors());  
   
var Resp = (function(yj) {  
 
    yj = function() {  
       this.dragId = '';  
       this.dragName = '';  
       this.trace = '';  
    };  
 
    yj.prototype = {  
 
        toJson: function() {  
           return JSON.stringify(this);  
        }  
   };  
        return yj;  
 
 }(Resp || function(){}));  
 
 
function eraseErrorOfContract(arr) {  
 
    for (let contrc of arr) {  
           if (typeof contrc.currentProvider.sendAsync !== "function") {  
           contrc.currentProvider.sendAsync = function () {  
                return contrc.currentProvider.send.apply(  
                    contrc.currentProvider, arguments  
               );  
           }  
       }  
   }  
}  
 
   
const traceabilityJSON = require('../build/contracts/testTraceability_addTime');  
const traceability = contract(traceabilityJSON);  
 
traceability.setProvider(provider);  
var traceabilityInst;  
eraseErrorOfContract([traceability]);  
 
 
traceability.deployed({  
    from: coinbase,  
    gas: 600000  
}).then(instance => {  
    traceabilityInst = instance;  
    // traceabilityInst.addDragInfo_init('NWRuxXJ75fBWUjBZiDIyR16PdFLIOG/odIos/Z8ggxNqrvQyPMcnXjAVB0JAmHYu4LGxyOaA4FIlOJgzGrPvcIndf0EbYZ80l',"999pai","hayao",{from:coinbase,gas:600000}).then(result => {  
 
    //     console.log(result);  
    //     return traceabilityInst.addDragInfo_A('NWRuxXJ75fBWUjBZiDIyR16PdFLIOG/odIos/Z8ggxNqrvQyPMcnXjAVB0JAmHYu4LGxyOaA4FIlOJgzGrPvcIndf0EbYZ80l',"经销商1",{from:coinbase,gas:600000})  
 
    // }).then(result2 => {  
    //     console.log(result2);  
    //     return traceabilityInst.getDrugInformationWithID.call('NWRuxXJ75fBWUjBZiDIyR16PdFLIOG/odIos/Z8ggxNqrvQyPMcnXjAVB0JAmHYu4LGxyOaA4FIlOJgzGrPvcIndf0EbYZ80l',{from:coinbase,gas:600000});  
 
    // }).then(result3 =>{  
    //     console.log(result3);  
    // }).catch(err => {  
    //     console.log(err)  
    // });  
 
});  
 
   
app.get('/addDragInfo_produce',function (req,res) {  // app => router  
 
    let currentTime = new Date().toLocaleString();  
    traceabilityInst.addDragInfo_init(req.query.id,req.query.dragInfo,req.query.company,currentTime,{from:coinbase,gas:600000}).then(result => {  
        console.log(result);  
        res.end("您(生产商)已将药品信息上链!交易hash:"+result.tx);  
    }).catch(err => {  
        console.log(err);  
        res.end(JSON.stringify(err))  
    });  
});  
 
   
 
app.get('/addDragInfo_A',function (req,res) {  // app => router  
 
    let currentTime = new Date().toLocaleString();  
    traceabilityInst.addDragInfo_A(req.query.id,req.query.company,currentTime,{from:coinbase,gas:600000}).then(result => {  
        res.end("您(销售商A)已将信息上链!交易hash:"+result.tx)  
    }).catch(err => {  
        res.end(JSON.stringify(err))  
    });  
 
});  
 
   
app.get('/addDragInfo_B',function (req,res) {  // app => router  
 
    let currentTime = new Date().toLocaleString();  
    traceabilityInst.addDragInfo_B(req.query.id,req.query.company,currentTime,{from:coinbase,gas:600000}).then(result => {  
        res.end("您(销售商B)已将信息上链!交易hash:"+result.tx)  
    }).catch(err => {  
        res.end(JSON.stringify(err))  
    });  
});  
 
   
 
app.get('/addDragInfo_C',function (req,res) {  // app => router  
    let currentTime = new Date().toLocaleString();  
    traceabilityInst.addDragInfo_C(req.query.id,req.query.company,currentTime,{from:coinbase,gas:600000}).then(result => {  
        res.end("您(销售商C)已将信息上链!交易hash:"+result.tx)  
    }).catch(err => {  
        res.end(JSON.stringify(err))  
    });  
});  
 
 
app.get('/getDrugInformationWithID',function (req,res) {  // app => router  
 
    let ret = new Resp();  
    traceabilityInst.getDrugInformationWithID.call(req.query.id,{from:coinbase,gas:600000}).then(result => {  
 
        ret.dragId = req.query.id;  
        ret.dragName = result[0] ;  
        ret.trace = result[1];  
        res.setHeader('Content-Type', 'text/plain;charset=utf-8');  
        res.end("药品ID:"+ret.dragId+'\n'+"药品名称:"+ret.dragName+'\n'+"溯源信息:"+ret.trace);  
 
    }).catch(err => {  
 
        res.end(JSON.stringify(err))  
 
    });  
});  
 
 
var server = app.listen(serverPort, function () {  
 
    var host = server.address().address;  
    var port = server.address().port;  
    console.log( 'Express started on http://'+ host +':' + port  );  
 
}); 

5.node service description

According to demand analysis, drug manufacturers, agents, and retailers write data to the blockchain, and users read data from the blockchain. Therefore, different users can access different APIs through http to achieve their respective business goals, as shown below:

Manufacturer data upload operation: http://localhost:8546/addDragInfo_produce

Agent A data chain operation: http://localhost:8546/ addDragInfo_A

Agent B data on-chain operation: http://localhost:8546/ addDragInfo_B

User query traceability information operation: http://localhost:8546//getDrugInformationWithID


Original link: Blockchain traceability case development based on Ethereum

Guess you like

Origin blog.csdn.net/JonasErosonAtsea/article/details/109236358