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


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

  • 相关阅读:
    浏览器同源政策及其规避方法---转阮大神
    js跨域详解
    js中top、self、parent
    杂记
    DOM 踩踩踩
    java idea 连接数据库
    数据库mySQL常用命令
    用迭代实现80人围成一圈逢3取出
    如何把通过类建立的对象存入数组中.
    面向对象编程
  • 原文地址:https://www.cnblogs.com/honghongzeng/p/12552032.html
Copyright © 2020-2023  润新知