郝丽锋的专栏

郝丽锋的专栏

智能合约vote部署

智能合约vote部署

1     前言

solidity官方文档上有一个vote智能合约。我使用truffle框架进行编写和部署。

2      环境

2.1   编辑

vscode + 插件

2.2   安装node

到官网下载node 8,解压后安装,配置环境变量。

2.3   solidity编译器

npm install -g solc

2.4   truffle安装

npm install -g truffle

2.5   ethereum安装

https://github.com/ethereum/go-ethereum下载编译,配置环境。

3     ethereum私有链搭建

3.1   创建目录

/home/hlf/eth/data/00

3.2   genesis.json

/home/hlf/eth/genesis.json

{

 "config": {

       "chainId": 168,   //不要为0

       "homesteadBlock": 0,

       "eip155Block": 0,

       "eip158Block": 0

   },

 "alloc"      : {},

 "coinbase"   :"0x0000000000000000000000000000000000000000",

 "difficulty" : "0x400",

 "extraData"  :"",

 "gasLimit"   :"0x2fefd8",

 "nonce"      :"0x0000000000000042",

 "mixhash"    :"0x0000000000000000000000000000000000000000000000000000000000000000",

 "parentHash" :"0x0000000000000000000000000000000000000000000000000000000000000000",

 "timestamp"  :"0x00"

}

3.3   初始化脚本

/home/hlf/eth/init.sh

geth --datadir /home/hlf/eth/data/00 init/home/hlf/eth/genesis.json

3.4   start脚本

geth --identity "TestNode" --rpc--rpcport "8545" --datadir /home/hlf/eth/data/00--port "30303" --rpcapi "db,eth,net,web3" --networkid 168 --nodiscover console

4     truffle编写智能合约

4.1   创建目录

mkdir ~/vote

4.2   初始化框架

cd ~/vote

truffer init

创建目录结构如下:


4.3   编写智能合约

在contracts目录下添加文件vote.sol,使用vscode打开并编辑,内容如下,与官网一致:

pragma solidity ^0.4.22;

contract Ballot {

   struct Voter {  //a single voter.

       uint weight;  //weight isaccumulated by delegation

       bool voted;   //if true, that peson already voted

       address delegate; //person delegated to 委托人

       uint vote;        //index of thevoted proposal

    }

 

   struct Proposal {  //a singleproposal提议

       bytes32 name;  //short name (up to32 bytes)

       uint voteCount;  //number of accumulated votes

    }

   address public chairperson;

 

   /*this declares a state variable that stores a 'voter'

   struct for each possible address.

   */

   mapping(address=> Voter) public voters;

   //a dynamically-sized array of 'proposal' structs.

   Proposal[] public proposals;

   //Create a new ballot to choose one of 'proposalNames'

 

   function Ballot(bytes32[] proposalNames) public {

       chairperson = msg.sender;

       voters[chairperson].weight = 1;

 

       for (uint i=0;i<proposalNames.length;i++) {

           proposals.push(Proposal({

                name:proposalNames[i],

                voteCount: 0

           }));

       }

    }

   //Give 'voter' the right to vote on this ballot.May only be called

   //by `chairperson`

   function giveRightToVote (address voter) public {

       /*if the frist argument of 'require' evaluates to false,

       execution terminates and changes to the state and ether balances arereveerted

       this used to consume all gas in old EVM versions, but not anymore.

       it is often a good idea to use 'require' to check if funcations arecalled

       correctly.

       as a second argument, you can also provide an exaplannation about waht

       went wrong */

       require(

           msg.sender == chairperson,

           "Only chairperson can give right to vote."

       );

       require(

           !voters[voter].voted,

           "the voter already vote."

       );

       require(voters[voter].weight == 0);

       voters[voter].weight = 1;

    }

   //delegate委托 your vote to the voter 'to'

   //msg.sender --表示执行该命令的账户

   function delegate(address to) public {

 

       Voter storage sender = voters[msg.sender];

        require(!sender.voted, "You alreadyvoted.");

       require(to != msg.sender, "Self-delegation is disabllowed.");

       /*forward the delegation as long as to also delegated.

       in general, such loops are very dangerous, because if they run too long,the

       might need more gas than is available in a block.

       in this case, the delegation will not be executed, but in othersituations,

       such loops might cause a contract to get 'stuck' completely, */

       //if to 委托给了别人,就向前委托

       while(voters[to].delegate != address(0)) {

           to = voters[to].delegate;

           require(to != msg.sender,"Found loop in delegation.");

       }

       sender.voted = true;

       sender.delegate = to;

       Voter storage delegate_ = voters[to];

       if(delegate_.voted){

           proposals[delegate_.vote].voteCount += sender.weight;

       }else {

           delegate_.weight+=sender.weight;

       }

    }

   function vote(uint proposal) public {

       Voter storage sender = voters[msg.sender];

       require(!sender.voted,"Already voted.");

       sender.voted = true;

       sender.vote = proposal;

 

       proposals[proposal].voteCount += sender.weight;

    }

   function winningProposal() public view

               returns (uint winningProposal_){

       uint winningVoteCount = 0;

       for (uint p=0;p<proposals.length;p++) {

           if(proposals[p].voteCount > winningVoteCount) {

                winningVoteCount =proposals[p].voteCount;

                winningProposal_ = p;

           }

       }

    }

   function winnerName() public view returns (bytes32 winnerName_)

    {

       winnerName_ = proposals[winningProposal()].name;

    }

 

}

4.4   启动eth,创建4个账户。

eth.accounts

personal.newAccount(“123456”) //该命令执行四次,创建四个账户

miner.start()  -- 挖矿获得gas

4.5   配置部署环境

在truffle.js中添加

module.exports = {

  //See <http://truffleframework.com/docs/advanced/configuration>

  //to customize your Truffle configuration!

 networks:{

   live:{

           host:"localhost",

           port:8545,

           network_id:"168",

                     from:"0x9cf2746d81814730281a72b74e6a84d5f627a78b",//账户[0]

                     gas:3000000

 

 

    }

}

};

4.6   编写部署脚本

在migrations目录添加

var Ballot =artifacts.require("Ballot")

module.exports = function(deployer){

   deployer.deploy(Ballot,["0x9cf2746d81814730281a72b74e6a84d5f627a78b","0x4b2f38a14e6337ef1ac15d1bd56e7ca68b1d181a","0xa06eb7296a0e8eec916eed082b82994b73e3186a", "0xc594cc30c42d92ba668f81f119c994b7f1c8ce88","0x57ef6050eec6bd838744b8b7592387d1489c56ea","0xabc2b333b13135e2fdfdc0d59b9f08de9a98298b"]);

}

4.7   部署过程

1)     解锁账户

2)     在另一个界面中truffle migrations--network live

5    在truffle console 执行智能合约

truffle console --network live

 

使用Ballot.deployed()查看

更详细的:1)实例化contract

Ballot.deployed().then(instance=>contract=instance)

2)调用函数:contract.winnerName()

在eth console中执行智能合约同普通的智能合约,通过abi创建合同,abi在vote/build目录中。该目录在truffle build后创建

 


阅读更多
个人分类: 区块链
上一篇智能合约开发自测环境搭建并简单示例
下一篇以太坊节点发现原理
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭