智能合约vote部署
solidity官方文档上有一个vote智能合约。我使用truffle框架进行编写和部署。
vscode + 插件
到官网下载node 8,解压后安装,配置环境变量。
npm install -g solc
npm install -g truffle
从https://github.com/ethereum/go-ethereum下载编译,配置环境。
/home/hlf/eth/data/00
/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"
}
/home/hlf/eth/init.sh
geth --datadir /home/hlf/eth/data/00 init/home/hlf/eth/genesis.json
geth --identity "TestNode" --rpc--rpcport "8545" --datadir /home/hlf/eth/data/00--port "30303" --rpcapi "db,eth,net,web3" --networkid 168 --nodiscover console
mkdir ~/vote
cd ~/vote
truffer init
创建目录结构如下:
在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 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 if(proposals[p].voteCount > winningVoteCount) { winningVoteCount =proposals[p].voteCount; winningProposal_ = p; } } } function winnerName() public view returns (bytes32 winnerName_) { winnerName_ = proposals[winningProposal()].name; } } eth.accounts personal.newAccount(“123456”) //该命令执行四次,创建四个账户 miner.start() -- 挖矿获得gas 在truffle.js中添加 module.exports = { //See //to customize your Truffle configuration! networks:{ live:{ host:"localhost", port:8545, network_id:"168", from:"0x9cf2746d81814730281a72b74e6a84d5f627a78b",//账户[0] gas:3000000 } } }; 在migrations目录添加 var Ballot =artifacts.require("Ballot") module.exports = function(deployer){ deployer.deploy(Ballot,["0x9cf2746d81814730281a72b74e6a84d5f627a78b","0x4b2f38a14e6337ef1ac15d1bd56e7ca68b1d181a","0xa06eb7296a0e8eec916eed082b82994b73e3186a", "0xc594cc30c42d92ba668f81f119c994b7f1c8ce88","0x57ef6050eec6bd838744b8b7592387d1489c56ea","0xabc2b333b13135e2fdfdc0d59b9f08de9a98298b"]); } 1) 解锁账户 2) 在另一个界面中truffle migrations--network live 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后创建 4.4 启动eth,创建4个账户。
4.5 配置部署环境
4.6 编写部署脚本
4.7 部署过程
5 在truffle console 执行智能合约