A demonstração da solução de rastreabilidade Ethereum é fácil de se familiarizar com o processo de cadeia e rastreabilidade blockchain, incluindo a construção da rede Ethereum, desenvolvimento e implantação de contrato e desenvolvimento de gateway de back-end de um conjunto completo de códigos.
Mais tecnologia de blockchain e classificação de aplicativos:
Blockchain applicationBlockchain development
Ethernet Square | Tecido | BCOS | criptografia | algoritmo de consenso | bitcoin | Outra cadeia
Economia de token | Cenários financeiros tradicionais | Finanças descentralizadas | Rastreabilidade antifalsificação | Compartilhamento de dados | Depósito confiável
Uma solução de rastreabilidade baseada no Ethereum, você pode executar uma demonstração para experimentar as características do Ethereum. Conforme mostrado na figura, o design geral da arquitetura da demonstração deste projeto é dividido em três camadas: camada de aplicativo (APP), camada de serviço (Nodejs-serviço) e camada de blockchain (Ethereum). As ideias de design e soluções podem ser vistas abaixo conteúdo. Ao solicitar a camada de serviço, a camada de aplicativo transfere a operação de operação do blockchain para a camada de serviço, evitando a operação direta do blockchain, e muitas coisas podem ser feitas na camada de serviço, como controle de permissão para verificar as operações do usuário, filas de mensagens para evitar congestionamento, etc. , A função principal é separar as solicitações do APP de acordo com os diferentes negócios e, posteriormente, operar diferentes métodos no contrato inteligente. A camada de rede blockchain executa nós Ethereum, implanta contratos inteligentes nela e processa dados da camada de serviço.
Figura 0-1 Projeto de arquitetura do projeto de rastreabilidade
Com base na estrutura de design acima, este artigo é dividido em três partes para elaborar:
A primeira parte, o estabelecimento da rede Ethereum, apresenta o processo de construção da rede privada Ethereum Independentemente da lógica contratual subsequente, este capítulo é a tecnologia geral para a construção da rede privada Ethereum.
A segunda parte, desenvolvimento e implantação do contrato, apresenta a lógica de design e o esquema do contrato e anexa o código-fonte.
A terceira parte, desenvolvimento em segundo plano, é o desenvolvimento da camada de serviço com base em nodejs, como o meio entre o aplicativo do usuário e a rede blockchain, e apresenta como responder às solicitações do usuário e, em seguida, operar o blockchain. Em seguida, apresentaremos como os usuários podem interagir com o blockchain usando essa camada de serviços de API.
A primeira parte da construção da rede Ethereum
1. Baixe o cliente geth
(1) Baixar
Vá para o site https://geth.ethereum.org/downloads/ para baixar o cliente geth.Você pode baixar o geth correspondente de acordo com os diferentes sistemas operacionais.
(2) Instalação
Clique diretamente no pacote binário para instalá-lo.
2. Use geth para gerar uma conta
(1) Use o comando geth: geth account new
(2) Digite a senha, geth irá gerar automaticamente o arquivo keystore de acordo com a entrada do usuário, (o caminho padrão é C: \ Users \ Administrator.xxx \ AppData \ Roaming \ Ethereum)
(3) Crie um diretório de dados data0 em qualquer lugar do sistema como um diretório para sincronizar os dados Ethereum.
(4) Copie o arquivo keystore acima para a pasta data0
(5) Pré-gere n contas de acordo com o método acima e coloque o arquivo de senha (com retorno de carro e alimentação de linha) correspondente a cada conta no mesmo diretório de nível de data0 e salve-o como pwd.
Dica: O armazenamento de chaves da conta do mineiro deve existir em "extraData", como:
"extraData": "0x0000000000000000000000000000000000000000000000000000000000000000e578252579e5f43fe124fe1d8236f0e5250c11970000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
A parte vermelha é o endereço do mineiro.
3. Configure o bloco genesis
Crie um arquivo de configuração de bloco de fundação no diretório de mesmo nível de data0 e preencha a conta gerada acima no campo de alocação do arquivo de configuração para personalizar a alocação inicial de ether:
4. Inicialização
Vá para o diretório de dados Ethereum e use o comando geth:
geth --datadir data0 init Genesis.json
5. Inicie o comando geth
(Para obter uma explicação detalhada de cada parâmetro, use geth --help para consultar)
6. Outro
Depois que o nó Ethereum iniciar normalmente, use a API integrada (web3) para realizar as seguintes operações:
Comece a minerar: miner.start ()
Pare de minerar: miner.stop ()
Gere uma nova conta: personal.newAccount ()
Veja os recompensadores de mineração: eth.coinbase
Transfira transações entre contas:
amount = web3.toWei(5,'ether')
personal.unlockAccount(eth.accounts[0])
eth.sendTransaction({from:eth.accounts[0],to:eth.accounts[1],value:amount})
A segunda parte do desenvolvimento e implantação do contrato
1. Necessidades de negócios
Vamos tomar a rastreabilidade de medicamentos como exemplo. Em todo o cenário de negócios, os nós de negócios podem ser divididos em três categorias, fabricantes de medicamentos, agentes e varejistas; os dados podem ser divididos em duas partes, informações sobre medicamentos e informações de circulação. As informações sobre medicamentos são adicionadas pelos fabricantes quando eles os produzem, e as informações sobre a circulação dos medicamentos são adicionadas pelos agentes e varejistas no canal de circulação, conforme mostrado na Figura 2-1. Ao adicionar dados ao blockchain, use o ID do produto + essas informações do nó de negócios para fazer o upload.
Figura 2-1 Negócio de rastreabilidade de medicamentos
2. Estrutura de dados do contrato
O contrato é desenvolvido usando solidez, com base nos requisitos de negócios acima, usando estrutura embutida de solidez e tipos de dados de mapeamento e aninhamento. Obtenha a estrutura de dados disponível para rastreabilidade do medicamento:
A estrutura de armazenamento de informações de rastreabilidade é mostrada na Figura 2-2. Consiste em um mapeamento + estrutura aninhada de estrutura. À esquerda está um conjunto de mapeamento. Cada elemento de mapeamento é um par de valor-chave e a "chave" é o valor de ID, por meio do qual o ID correspondente pode ser obtido. O Struct contém duas partes: "informações sobre medicamentos" e "informações de rastreabilidade". Ao consultar, descubra o Strcut cuja "chave" é "NWRuxXJ75fBWUjBZi" em Mapeamento por meio do número de ID (como NWRuxXJ75fBWUjBZi codificado pelo código QR). Os dados do Strcut são {dragInfo: 999 remédio para resfriado, Harbin Medicineth Factory, traceInfo: agent A => Agente B => Varejista X}
Figura 2-2 Estrutura de armazenamento de contrato
3. Preparação de desenvolvimento
(1) Solidez
Solidity é uma linguagem de alto nível para contratos inteligentes semelhante ao JavaScript. É executada na Máquina Virtual Ethereum (EVM). Foi projetada para gerar o código da máquina virtual Ethereum de forma compilada. É a linguagem oficial recomendada para o desenvolvimento de contratos inteligentes Ethereum.
(2) Trufa
Truffle é um ambiente de desenvolvimento de classe mundial, estrutura de teste e canal de gerenciamento de recursos Ethereum. Ele se dedica a tornar o desenvolvimento no Ethereum mais fácil. O Truffle tem o seguinte:
Compilação de contrato inteligente integrada, vinculação, implantação e gerenciamento de arquivos binários.
Teste de contrato automático em rápido desenvolvimento.
Implantação extensível com script e estrutura de lançamento.
Função de gerenciamento de ambiente de rede implantada, não importa quantas redes públicas ou privadas
Use o gerenciamento de pacotes fornecido pelo EthPM & NPM e use o padrão ERC190.
Console interativo direto que se comunica diretamente com o contrato (você pode verificá-lo na linha de comando depois de escrever o contrato).
O processo de construção configurável oferece suporte à integração estreita.
Suporta a execução de scripts externos no ambiente Truffle.
4. Código do contrato
Nota: Como a versão solidity0.4 não oferece suporte ao mapeamento da estrutura aninhada, as informações de rastreabilidade são adicionadas na forma de emenda de caracteres para facilitar a exibição direta.
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. Descrição do contrato
Para operações de estrutura de dados de rastreabilidade, existem métodos de operação como addDragInfo_init, addDragInfo_A, addDragInfo_B, addDragInfo_C e getDrugInformationWithID C. addDragInfo_init é um método para os fabricantes de medicamentos adicionarem informações, addDragInfo_A, addDragInfo_C e getDrugInformationWithID C. addDragInfo_init é um método para os fabricantes de medicamentos adicionarem informações, addDragInfo_A, addDragInfo_C e getDrugInformationWithID C. addDragInfo_init é um método para os fabricantes de drogas adicionarem informações, addDragInfo_A, addDragInfo_A, addDragInfo_C e getDrugInformationWithID. O usuário usa o ID do produto para obter todas as informações de rastreabilidade.
6. Use trufas para implantação de contrato
(1) Instale trufa
Instale o pacote npm do truffle globalmente:
npm install truffle -g
(2) inicialização de trufa
Insira o diretório do projeto e execute o seguinte comando:
trufa de inicialização
(3) Modificar arquivos de configuração relacionados
Modifique os três arquivos mostrados na Figura 2-3:
Figura 2-3 Arquivos de configuração relacionados para a operação de trufas
Apresente estes três arquivos:
1_initial_migration.js (contrato de migração padrão)
var Migrations = artifacts.require("./Migrations.sol");
module.exports = function(deployer) {
deployer.deploy(Migrations);
};
2_deploy_contracts.js (configure os contratos que precisam ser implantados)
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 as informações relacionadas ao Ethereum de destino)
/*
* 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) Compilar o contrato
Execute no diretório do projeto:
compilar trufa
trufa compilar --all (recompilar tudo)
(5) Contrato de migração
Executar no diretório do projeto
trufa migrar
truffle migrate --reset (todos reexecutam o script de migração)
A terceira parte do desenvolvimento em segundo plano
1. Instruções de desenvolvimento de plano de fundo
Esta rede de blockchain é baseada na rede privada Ethereum, portanto, para garantir a segurança e confiabilidade dos dados, os usuários não podem operar diretamente a blockchain e devem utilizar serviços de middleware. Portanto, o middleware de nó é desenvolvido, o que pode controlar os dados na cadeia e pode fazer alguns outros serviços necessários, como gerenciamento de direitos, filas de mensagens, armazenamento temporário de dados de bloco e assim por diante.
2. Análise de demanda
É sabido da segunda parte que os três tipos de nós de negócios (produtores, vendedores e varejistas) precisam fazer upload de dados para o blockchain, respectivamente, e devem ser baseados em serviços intermediários, em vez de operar diretamente o blockchain. Portanto, a arquitetura de plano de fundo mostrada na Figura 3-1 é adotada, ou seja, todos os usuários no lado B e no lado C são baseados no serviço de nó de middleware para operar ou acessar indiretamente o blockchain. Portanto, de acordo com as diferentes funções de cada usuário, diferentes serviços de API são abertos e cada usuário realiza diferentes transações no blockchain. Conforme mostrado na figura, em termos simples, o fabricante do medicamento, o agente A, o agente B e o varejista gravam dados no blockchain e os usuários leem os dados no blockchain.
Figura 3-1 Diagrama da arquitetura de fundo do nó
3. Preparação de desenvolvimento
(1) Nodejs
JavaScript é o mais amplamente usado em toda a comunidade de código aberto. No momento, a maioria dos projetos correspondentes à linguagem JavaScript são baseados na plataforma Node.js, então Nodejs é bem merecido e uma das plataformas de desenvolvimento mais populares. Nodejs é uma plataforma JavaScript de execução instantânea no Chrome V8 em construção. Ele usa um modelo de E / S não bloqueante e orientado por tempo. É leve e eficiente e é muito adequado para aplicativos em tempo real com grande quantidade de dados, como ações, fundos e criptomoedas. Esperar. Em particular, a ferramenta de gerenciamento de pacotes npm do Nodejs se tornou a comunidade mais ativa do mundo. Existem muitos pacotes de terceiros para os desenvolvedores escolherem, e a maioria dos componentes relacionados ao blockchain são desenvolvidos e aplicados na forma de pacotes npm. , Portanto, o Nodejs é uma ferramenta poderosa para o desenvolvimento de blockchain.
Uso: instalação do ambiente Nodejs
(2) Expresso
Express é uma estrutura de aplicativo da web node.js simples e flexível, fornecendo uma série de recursos poderosos para ajudá-lo a criar vários aplicativos da web e uma grande variedade de ferramentas HTTP. O uso do Express pode criar rapidamente um site com todos os recursos e oferece suporte a vários utilitários HTTP e middleware para criar APIs poderosas de maneira rápida e fácil.
Uso: Importar pacote npm.
(3) API web3
A rede Ethereum é composta por nós, e cada nó contém uma cópia do blockchain. Quando precisamos chamar um método em um contrato inteligente, precisamos encontrá-lo e identificá-lo a partir de um dos nós. Os nós Ethereum só podem reconhecer uma linguagem chamada JSON-RPC, que não é muito legível. Web3.js pode ocultar essas declarações de consulta obscuras e só precisa interagir com a interface JavaScript de fácil compreensão.
web3.js é uma biblioteca Javascript fornecida pela Ethereum. Ela encapsula a API JSON RPC da Ethereum e fornece uma série de objetos e funções Javascript que interagem com o blockchain, incluindo visualização do status da rede, visualização de contas locais, visualização de transações e zonas Bloqueia, envio de transações, compilação / implantação de contratos inteligentes, chamada de contratos inteligentes, etc. O mais importante deles é a API que interage com contratos inteligentes. Portanto, para desenvolver projetos baseados em Ethereum, você deve estar familiarizado com as APIs comuns em web3js.
Uso: Importar pacote npm.
4. código do nó
Desenvolva um servidor de nó simples por meio de nodejs + express + web3js e exponha interfaces de API para o mundo externo. O serviço de API de chamada externa por meio de solicitação Http para operar o 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. descrição do serviço de nó
De acordo com a análise de demanda, fabricantes de medicamentos, agentes e varejistas gravam dados no blockchain e os usuários leem os dados do blockchain. Portanto, diferentes usuários podem acessar diferentes APIs por meio de http para atingir seus respectivos objetivos de negócios, conforme mostrado abaixo:
Operação de upload de dados do fabricante: http: // localhost: 8546 / addDragInfo_produce
Operação de cadeia de dados do Agente A: http: // localhost: 8546 / addDragInfo_A
Operação em cadeia de dados do Agente B: http: // localhost: 8546 / addDragInfo_B
Operação de informações de rastreabilidade de consulta do usuário: http: // localhost: 8546 // getDrugInformationWithID
Link original: Desenvolvimento de caso de rastreabilidade de Blockchain baseado em Ethereum