前言
昨天发布了关于自己学习区块链和DAPP的学习小结式的文章,朋友对我提了几点意见说:合约没有身份,一个人可以很多次的投票只要舍得花gas这是个刷票漏洞。
仔细想来是有点偷懒了,所以今天补一篇。就两点:1,补上身份认证避免反复投票;2,对web3.0以及他的部署和调用再做一些介绍,其实功能和昨天是一样的但是方法会有所不同。
solidity的合约优化
pragma solidity ^0.4.0;
contract Voting{
//投票列表
bytes32[] public candidateList;
//对应的票数
mapping(bytes32=>uint8) public votesReceived;
//投票人列表
mapping(address=>People) public Peoples;
//投票人信息及投票时间
struct People{
address account;
uint voingtime;
}
//构造投票列表
constructor(bytes32[] memory candidateListName) public{
candidateList = candidateListName;
}
//获取投票人账号
function getAccountAddress() public returns(uint32)
{
People memory people = Peoples[msg.sender];
return uint32(people.account);
}
//设置已投票地址
function setAccountAddress() private
{
People memory people = People(msg.sender,now);
Peoples[msg.sender] = people;
}
//判断投票信息是否在待投票列表
function valiCandidate(bytes32 candidateName) internal view returns(bool)
{
for(uint8 i=0;i<candidateList.length;i++)
{
if (candidateName==candidateList[i])
{
return true;
}
}
return false;
}
//对投票人增加投票
function voteForCandidate(bytes32 candidateName) public{
require(valiCandidate(candidateName));
//判断是否已投票 0 为未投票
require(getAccountAddress()==0);
setAccountAddress();
votesReceived[candidateName] = votesReceived[candidateName] + 1;
}
function totalVotesFor(bytes32 candidateName) view public returns(uint8){
require(valiCandidate(candidateName));
//返回票数
return votesReceived[candidateName];
}
}
代码附上,具体可以看注释;其实很简单就是用mapping记录投票人地址(用struct记录)
接下来聊聊 如何初始化简单web3.0
mkdir web3.0
cd web3.0
npm init
一路回车初始化一个node js项目
npm install web3 -save
通过node js web3 部署合约
在web3.0目录下新建deploy.js
var Web3 = require('web3');
// 链接本地 ganache 记得启动
var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
打开remix 我们可以看到web3的部署文件就这么简单
var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
var candidateListName = ["0x4100000000000000000000000000000000000000000000000000000000000000","0x4200000000000000000000000000000000000000000000000000000000000000"] ;
var votingContract = new web3.eth.Contract([{"constant":false,"inputs":[],"name":"getAccountAddress","outputs":[{"name":"","type":"uint32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"candidateName","type":"bytes32"}],"name":"totalVotesFor","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"Peoples","outputs":[{"name":"account","type":"address"},{"name":"voingtime","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"votesReceived","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"candidateList","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"candidateName","type":"bytes32"}],"name":"voteForCandidate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"candidateListName","type":"bytes32[]"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]);
var voting = votingContract.deploy({
data: '0x608060405234801561001057600080fd5b506040516106d93803806106d9833981018060405281019080805182019291905050508060009080519060200190610049929190610050565b50506100c8565b828054828255906000526020600020908101928215610092579160200282015b82811115610091578251829060001916905591602001919060010190610070565b5b50905061009f91906100a3565b5090565b6100c591905b808211156100c15760008160009055506001016100a9565b5090565b90565b610602806100d76000396000f300608060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630e2562d91461007d5780632f265cf7146100b457806355f503d5146100ff5780637021939f14610189578063b13c744b146101d4578063cc9ab2671461021d575b600080fd5b34801561008957600080fd5b5061009261024e565b604051808263ffffffff1663ffffffff16815260200191505060405180910390f35b3480156100c057600080fd5b506100e3600480360381019080803560001916906020019092919050505061030f565b604051808260ff1660ff16815260200191505060405180910390f35b34801561010b57600080fd5b50610140600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610355565b604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390f35b34801561019557600080fd5b506101b86004803603810190808035600019169060200190929190505050610399565b604051808260ff1660ff16815260200191505060405180910390f35b3480156101e057600080fd5b506101ff600480360381019080803590602001909291905050506103b9565b60405180826000191660001916815260200191505060405180910390f35b34801561022957600080fd5b5061024c60048036038101908080356000191690602001909291905050506103dc565b005b60006102586105a6565b600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040805190810160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820154815250509050806000015191505090565b600061031a82610475565b151561032557600080fd5b60016000836000191660001916815260200190815260200160002060009054906101000a900460ff169050919050565b60026020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010154905082565b60016020528060005260406000206000915054906101000a900460ff1681565b6000818154811015156103c857fe5b906000526020600020016000915090505481565b6103e581610475565b15156103f057600080fd5b60006103fa61024e565b63ffffffff1614151561040c57600080fd5b6104146104da565b6001806000836000191660001916815260200190815260200160002060009054906101000a900460ff160160016000836000191660001916815260200190815260200160002060006101000a81548160ff021916908360ff16021790555050565b600080600090505b6000805490508160ff1610156104cf5760008160ff1681548110151561049f57fe5b906000526020600020015460001916836000191614156104c257600191506104d4565b808060010191505061047d565b600091505b50919050565b6104e26105a6565b60408051908101604052803373ffffffffffffffffffffffffffffffffffffffff16815260200142815250905080600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151816001015590505050565b6040805190810160405280600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815250905600a165627a7a72305820230b9460ef4d9c98dc2ad603c8d560d384d66df56e19cce527bbdda332014b4e0029',
arguments: [
candidateListName,
]
}).send({
//from: web3.eth.accounts[0],
from: '0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0',
gas: '4700000'
}, function (e, contract){
console.log(e, contract);
if (typeof contract.address !== 'undefined') {
console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);
}
}).then(function(contract){
console.log('Contract ! address: ', contract.options.address);
});
from: web3.eth.accounts[0], 记得改成你ganache个你的账号 现在通过node 部署 合约
node deploy.js
这时候你可以看到合约地址(Contract ! address: 0x32Cf1f3a98aeAF57b88b3740875D19912A522c1A)
合约部署好了,那怎么调用呢?我们还是用昨天的项目去调用都在一个本地虚拟链上当然都可以调用
下面是昨天APP项目调用合同的核心代码我直接在注释上写:
//node js 部署 我们没有这个json文件注释掉
// import votingArtifact from "../../build/contracts/Voting.json";
start: async function() {
const { web3 } = this;
try {
// get contract instance
const networkId = await web3.eth.net.getId();
//这里既然前面注释了,这里应该也没用了
const deployedNetwork = votingArtifact.networks[networkId];
//调用合同部分votingArtifact.abi这个哪里找呢?
//deployedNetwork.address 这个不就是合同地址吗
this.voting = new web3.eth.Contract(
votingArtifact.abi,
//deployedNetwork.address,
'0x32Cf1f3a98aeAF57b88b3740875D19912A522c1A',
);
// get accounts
const accounts = await web3.eth.getAccounts();
this.account = accounts[0];
this.ready();
this.refreshBalance();
} catch (error) {
console.error("Could not connect to contract or chain.");
}
},
现在的问题votingArtifact.abi哪里找呢?好吧原来remix里有复制下来 附上所有代码
import Web3 from "web3";
//import votingArtifact from "../../build/contracts/Voting.json";
const aInBytes32 ="0x4100000000000000000000000000000000000000000000000000000000000000";
const bInBytes32 ="0x4200000000000000000000000000000000000000000000000000000000000000";
const App = {
web3: null,
account: null,
meta: null,
start: async function() {
const { web3 } = this;
try {
// get contract instance
const networkId = await web3.eth.net.getId();
// const deployedNetwork = votingArtifact.networks[networkId];
// this.voting = new web3.eth.Contract(
// votingArtifact.abi,
// deployedNetwork.address,
// );
this.voting = new web3.eth.Contract(
[
{
"constant": false,
"inputs": [],
"name": "getAccountAddress",
"outputs": [
{
"name": "",
"type": "uint32"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "candidateName",
"type": "bytes32"
}
],
"name": "totalVotesFor",
"outputs": [
{
"name": "",
"type": "uint8"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "address"
}
],
"name": "Peoples",
"outputs": [
{
"name": "account",
"type": "address"
},
{
"name": "voingtime",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "bytes32"
}
],
"name": "votesReceived",
"outputs": [
{
"name": "",
"type": "uint8"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "",
"type": "uint256"
}
],
"name": "candidateList",
"outputs": [
{
"name": "",
"type": "bytes32"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "candidateName",
"type": "bytes32"
}
],
"name": "voteForCandidate",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"name": "candidateListName",
"type": "bytes32[]"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "constructor"
}
],
'0x32Cf1f3a98aeAF57b88b3740875D19912A522c1A',
);
// get accounts
const accounts = await web3.eth.getAccounts();
this.account = accounts[0];
this.ready();
this.refreshBalance();
} catch (error) {
console.error("Could not connect to contract or chain.");
}
},
ready:async function(){
try{
this.refresh("Alice",aInBytes32);
this.refresh("Bob",bInBytes32);
}catch(err){
console.log(err)
}
},
refresh:async function(id,nameBytes32){
const {totalVotesFor} = this.voting.methods;
const tickets = await totalVotesFor(nameBytes32).call();
const el = document.getElementById(id);
el.innerHTML = tickets.toString();
},
voteForCandidate:async function(){
try{
const {voteForCandidate} = this.voting.methods;
const condidateName = document.getElementById("candidate").value;
console.log(condidateName)
if (condidateName == "Alice")
{
await voteForCandidate(aInBytes32).send({from:this.account});
this.refresh("Alice",aInBytes32);
}
else{
await voteForCandidate(bInBytes32).send({from:this.account});
this.refresh("Bob",bInBytes32);
}
}catch(err){
console.log(err)
}
}
};
window.App = App;
window.addEventListener("load", function() {
if (window.ethereum) {
// use MetaMask's provider
App.web3 = new Web3(window.ethereum);
window.ethereum.enable(); // get permission to access accounts
} else {
console.warn(
"No web3 detected. Falling back to http://127.0.0.1:8545. You should remove this fallback when you deploy live",
);
// fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
App.web3 = new Web3(
new Web3.providers.HttpProvider("http://127.0.0.1:8545"),
);
}
App.start();
});
好了 程序都ok了 进入上次那个项目app目录(细节省略了)
cd app
npm run dev
开始投票第一次投票成功第二次投票好了不给投了,终于不能刷票了。文章来源:https://www.toymoban.com/news/detail-401666.html
总结
上次用的是脚手架一下子全好了,很多细节不到位,今天细一点也是对自己学习的终结。文章来源地址https://www.toymoban.com/news/detail-401666.html
到了这里,关于浅谈区块链DAPP学习·续的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!