(三)基于区块链的投票系统的设计与实现

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小课堂”,直接跟我留言即可!有什么问题我都会立即回复哦!

原文地址:https://www.cnblogs.com/honghongzeng/p/12552032.html