(三)基于区块链的投票系统的设计与实现
1、本地环境的搭建(Windows 10)
1.1 安装nodejs,npm,git,web3,solc
(1)nodejs:官网下载最新版本https://nodejs.org/en/download/current/
node.js后续还需安装python2.7与visual studio的c++开发工具包(建议手动)。
(2)npm:在Windows下安装nodejs会自带npm
(3)git:官网下载即可https://git-scm.com/downloads
(4)web3:命令行npm install web3@0.20.0
(5)solc:命令行npm install solc
期间可能会经历各种安装error,但根据提示都可以解决。
2. 用Truffle完成一个智能合约的部署:
这里我们实现以太坊开发框架Truffle的配置和运行,并借助Truffle完成一个智能合约的部署。
Truffle是一个世界级的开发环境,测试框架,以太坊的资源管理通道,致力于让以太坊上的开发变得简单,Truffle有以下:
-内置的智能合约编译,链接,部署和二进制文件的管理。
-快速开发下的自动合约测试。
-脚本化的,可扩展的部署与发布框架。
-部署到不管多少的公网或私网的网络环境管理功能
-使用EthPM&NPM提供的包管理,使用ERC190标准。
-与合约直接通信的直接交互控制台(写完合约就可以命令行里验证了)。
-可配的构建流程,支持紧密集成。
-在Truffle环境里支持执行外部的脚本。
2.1 TRUFFLE的安装
2.2 Truffle客户端
有许多的以太坊客户端可以选择。我们推荐在开发时使用客户端EtherumJS TestRPC(后改名为Ganache)
当开发基于Truffle的应用时,我们推荐使用EthereumJS TestRPC。它是一个完整的在内存中的区块链仅仅存在于你开发的设备上。它在执行交易时是实时返回,而不等待默认的出块时间,这样你可以快速验证你新写的代码,当出现错误时,也能即时反馈给你。它同时还是一个支持自动化测试的功能强大的客户端。Truffle充分利用它的特性,能将测试运行时间提速近90%。
3、用Truffle框架运行一个投票的智能合约
3.1 创建工程目录并初始化框架
3.2 新建新合约
在contract目录下创建一个自己的合约文件Voting.sol。由于solidity的编译器更新很快,对应的语法可能会有改变,建议先在浏览器的Remix IDE中修改好,再到命令行运行
pragma solidity ^0.5.0;
contract Voting {
mapping (bytes32 => uint8) public votesReceived;
bytes32[] public candidateList;
constructor() public {
candidateList.push("zhang");
candidateList.push("bin");
candidateList.push("cheng");
}
function totalVotesFor(bytes32 candidate) view public returns (uint8) {
require(validCandidate(candidate));
return votesReceived[candidate];
}
function voteForCandidate(bytes32 candidate) public {
require(validCandidate(candidate));
votesReceived[candidate] += 1;
}
function validCandidate(bytes32 candidate) view public returns (bool) {
for(uint i = 0; i < candidateList.length; i++) {
if (candidateList[i] == candidate) {
return true;
}
}
return false;
}
}
3.4 新建发布脚本
在./migrations/目录下新建一个文件:2_deploy_contracts.js,增加发布代码。
var Voting = artifacts.require("Voting");
module.exports = function(deployer) {
deployer.deploy(Voting); //配置合约的发布
};
3.5 编译
进入到工程目录下,进行编译:
3.6 启动客户端Ganache
如果之前没有启动Ganache客户端的话,则需要启动之前安装好的Ganache客户端,如果已启动的则忽略此步。Ganache图形化界面可以实时显示账户的余额变化以及交易情况。
3.7 修改文件truffle-config.js文件,增加网络配置:
如果用命令行启动Ganache-cli客户端,port选择8545
3.8部署合约(migrate)
Ganache图形化界面显示新出的块:
4、在控制台中与智能合约进行交互
Truffle提供了一种更加简单的方式,通过交互式控制台来与你的那些准备好的合约进行交互。
4.1 进入控制台,输入Voting智能合约命令
控制台显示打印出一个json结构,展示了Voting的各种属性内容。
4.2 运行Voting智能合约命令:
5、利用网页与智能合约进行交互
5.1 文件结构
在上一步的交互中我们是在控制台中进行投票和查询的,现在我们就要把这些命令写到js中,并写一个简单的html文件,通过网页来与智能合约进行交互。html和js文件见下。
js文件夹包含:
其中app.js实现了系统的整个逻辑运行过程,app.js的内容如下:
App = {
web3Provider: null,
contracts: {},
initWeb3: function () {
if (typeof web3 !== \'undefined\') {
App.web3Provider = web3.currentProvider;
} else {
App.web3Provider = new Web3.providers.HttpProvider(\'http://localhost:7545\');
}
web3 = new Web3(App.web3Provider);
App.initContract();
},
initContract: function () {
$.getJSON(\'Voting.json\', function (data) {
var Artifact = data;
App.contracts.Voting = TruffleContract(Artifact);
App.contracts.Voting.setProvider(App.web3Provider);
console.log(App.contracts.Voting);
App.setCounts();
});
App.bindEvents();
},
setCounts: function () {
var candidates = {"zhang": "one", "bin": "two", "cheng": "three"};
var candidateNames = Object.keys(candidates);
for (var i = 0; i < candidateNames.length; i++) {
App.update(candidateNames[i]);
}
},
bindEvents: function () {
$(document).on(\'click\', \'.btn-vote\', App.handleVoting);
},
update: function (name) {
var Instance;
var candidates = {"zhang": "one", "bin": "two", "cheng": "three"};
App.contracts.Voting.deployed().then(function (instance) {
Instance = instance;
return Instance.totalVotesFor.call(name);
}).then(function (val) {
console.log(val.toNumber());
$("#" + candidates[name]).html(val.toNumber());
}).catch(function (err) {
console.log(err.message);
});
},
handleVoting: function () {
var VotingInstance;
var candidateName = $("#candidate").val();
console.log(candidateName);
// 获取用户账号
web3.eth.getAccounts(function (error, accounts) {
if (error) {
console.log(error);
}
var account = accounts[0];
console.log(accounts);
App.contracts.Voting.deployed().then(function (instance) {
VotingInstance = instance;
return VotingInstance.voteForCandidate(candidateName, {from: account});
}).then(function (result) {
return App.update();
}).catch(function (err) {
console.log(err.message);
});
});
}
};
$(function () {
$(window).load(function () {
App.initWeb3();
});
});
5.2 启动lite-server
lite-server 是一个全功能的网站架设工具软件包轻量级的、仅适用于开发的 node 服务器,它仅支持web app。它能够为你打开浏览器,当你的html或是JavaScript文件变化时,它会识别到并自动帮你刷新浏览器, 还能使用套接字自动注入变化的CSS,当路由没有被找到时,它将自动后退页面。
启动lite-server:
5.3 前端index.html页面自动执行,网址为localhost:3000
结果展示:
6、总结
目前我已经在本地部署好了运行环境,也运行了基本的Demo。
由于向我咨询的人太多,我的时间真的有限!!着急的朋友可以通过扫描下面的二维码关注我的微信公众号,“区块链Dapp小课堂”,直接跟我留言即可!有什么问题我都会立即回复哦!