Dapp简单的投票小例子

准备工作

相关命令

  • mkdir simple_voting_dapp //创建文件夹
  • cd simple_voting_dapp //进入文件夹
  • npm init  //初始化npm包管理文件,输入ls 可以看到创建的package.json文件
  • npm intsall web3@0.20.1 //安装web3
  • npm install solc@0.4.25   //安装solc
  • npm install -g ganache-cli   //安装ganache-cli  参考文档 
  • 输入ganache-cli 启动,出现如下界面,表示启动成功,列出10个账户以及各自的秘钥,每个账户都有100以太,这个类似dev私链的模式

Solidity合约

合约内容

  • 构造函数,用来初始化一些候选者
  • 用来投票的方法(对于票数加 1)
  • 返回候选者获得的总的票数的方法

合约代码

pragma solidity ^0.4.22;contract Voting{mapping (bytes32 => uint8)public votesReceived;bytes32[] public candidateList;constructor(bytes32[] candidateNames)public{candidateList = candidateNames;}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;}}
}

合约编译

编译前测试

  • 查看安装的版本 npm list web3;npm list solc
  • node 进入命令行
  • var Web3 =  require('web3')
  • var web3 = new Web3(new Web3.providers.HttpProvider('Http://localhost:8545'))//这个需要和ganache-cli设置的一致,才可以连接上。
  • 使用web3.isConnected()//查看是否连接上,此时需要将ganache-cli启动
  • 使用命令web3.eth.accounts,获取目前的账户,需要注意每次启动ganache-cli都会产生全新的账号和秘钥

正式开始编译

  • var solc = require('solc')
  • 输入solc. 查看可以使用的命令
  • var sourceCode = fs.readFileSync('Voting.sol').toString()  //需要注意,必须给与文件读取权限
  • 输入sourceCode 可以查看编码文件
  • var compiledCode = solc.compile(sourceCode)  //这个就是正式的编译过程
  • 输入compiledCode可以查看字节码文件,编译结果如下图所示

  • 这是一个js对象,最关键的是bytecode(字节码)和interface接口(ABI),这两个文件是部署合约最关键的文件
  • 部署合约 var abi = JSON.parse(compiledCode.contracts[':Voting'].interface);    输入abi进行验证,是否取到正确的值,JSON.parse是为了Json格式化代码
  • var byteCode = compiledCode.contracts[':Voting'].bytecode 取到字节码     其中:Voting是合约名称
  • 创建合约对象 var VotingContract = web3.eth.contract(abi)
  • var deployTxObj = {data:byteCode,from:web3.eth.accounts[0],gas:30000000}  定义一笔交易
  • 定义合约实例 var contractInstance = VotingContract.new(["Alice","Bob","Cary"],deployTxObj);
  • contractInstance = VotingContract.new(["Alice","Bob","Cary"],{data:byteCode,from:web3.eth.accounts[0],gas:5000000});
  • 上面这一条命令是 定义合约实例 和 定义一笔交易的结合体,如果分开,有可能会报错
  • 取到合约实例的地址 contractInstance.address  这就将合约部署在区块链上,这个区块链是本地起的ganache-cli模拟区块链
  • contractInstance.vote("Alice",{from:web3.eth.accounts[0]})  账号0给Alice投出一票
  • contractINstance.totalVotesFor("Alice").toString()  查看Alice的总共的票数
  • contractINstance.totalVotesFor.call("Alice").toString() 查看
  • contractInstance.vote.sendTransaction("Alice",{from:web3.eth.accounts[0]}) 

页面交互

页面 index.html

<!DOCTYPE html>
<html><head><title>Voting DApp</title><link href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css' rel='stylesheet' type='text/css'></head><body class="container"><h1>A Simple Voting Application</h1><div class="table-responsive"><table class="table table-bordered"><thead><tr><th>Candidate</th><th>Votes</th></tr></thead><tbody><tr><td>Alice</td><td id="candidate-1"></td></tr><tr><td>Bob</td><td id="candidate-2"></td></tr><tr><td>Cary</td><td id="candidate-3"></td></tr></tbody></table></div><input type="text" id="candidate" /><a href="#" onclick="voteForCandidate()" class="btn btn-primary">Vote</a></body><script src="https://cdn.jsdelivr.net/gh/ethereum/web3.js/dist/web3.min.js"></script><script src="https://code.jquery.com/jquery-3.1.1.slim.min.js"></script><script src="./index.js"></script></html>

注意

  • 不再需要引入web3对象,因为页面里面就包含了web3对象,https://cdn.jsdelivr.net/gh/ethereum/web3.js/dist/web3.min.js,打开这个链接之后,在页面的最下面会显示,

index.js

var web3 = new Web3(new Web3.providers.HttpProvider("Http://localhost:8545"));
var abi = JSON.parse('[{"constant":true,"inputs":[{"name":"candidate","type":"bytes32"}],"name":"totalVotesFor","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"candidate","type":"bytes32"}],"name":"validCandidate","outputs":[{"name":"","type":"bool"}],"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":"candidate","type":"bytes32"}],"name":"voteForCandidate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"candidateNames","type":"bytes32[]"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]');
// var contractAddr = "0x3577f4d4902f4766753056468bd08ef68df6c623";
var VotingContract = new web3.eth.Contract(abi); 
// var contractInstance =new web3.eth.Contract(abi,contractAddr);
// contractInstance = VotingContract.at(contractAddr);
var contractInstance = VotingContract.at('0x3577f4d4902f4766753056468bd08ef68df6c623');
var candidates = {"Alice":"candidate-1","Bob":"candidate-2","Cary":"candidate-3"
};
function voteForCandidate(){let candidateName = $("#candidate").val();try{contractInstance.voteForCandidate(candidateName),{from:web3.eth.accounts[0]},(err,res)=>{if(err)console.log("Error:",err);else{let div_id = candidates[candidateName];let count = contractInstance.totalVotesFor(candidateName).toString();$("#" + id).html(count);}}}catch(err){}
};$(document).ready(function(){candidateNames = Object.keys(candidates);for(let i=0;i<candidateNames.length;i++){let name = candidateNames[i];let val = contractInstance.totalVotesFor.call(name).toString();$("#" + candidates[name]).html(val);}
});

报错

无解

  • at无法使用
  • 如果使用 var contractInstance =new web3.eth.Contract(abi,contractAddr);避免了at,但是无法使用call回调函数,依然报错

部署服务

server.js

  • 异步的方式启动,同步的会报错
var http = require('http');
var fs = require('fs');
var url = require('url');http.createServer(function(req,res){var pathName = url.parse(req.url).pathname;console.log("Request for:"+pathName + "received.");fs.readFile(pathName.substr(1),function(err,data){if(err){console.log(err);res.writeHead(400,{'Content-Type':"text/html"});}else{res.writeHead(200,{'Content-Type':"text/html"});res.write(data.toString());}res.end();});
}).listen(8888);
  • 使用命令 node server.js启动服务器
  • 浏览器输入 http://127.0.0.1:8888/index.html 查看

  • 如果报错 没有favicon.ico  直接创建一个就好,这个是图标文件

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/447147.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用mocha进行测试 区块链

mocha安装 npm install mocha --save-dev mocha简介 mocha是一个JavaScript的单元测试的框架&#xff0c;既可以运行在浏览器环境中&#xff0c;也可以运行在node.js环境中&#xff0c;只需要编写测试用例&#xff0c;mocha就会将测试自动的运行&#xff0c;并且给出测试的结…

Linux学习笔记(六)

参考书籍&#xff1a;linux就该这么学 6.存储结构与磁盘划分 6.1 文件系统与数据资料 6.2 挂载硬件设备 6.2.1 mount 命令用于挂载文件系统 6.2.2 umount 命令用于撤销已经挂载的设备文件 6.3 添加硬盘 6.3.1 fdisk 命令用于管理磁盘分区 6.3.2 用于查看文件数据占用量的 du 命…

实现Linux系统外部和容器内部的文件传输

主机和容器之间进行文件传输&#xff0c;需要使用容器的ID即可 获取方法如下 输入指令 docker ps -a只需要CONTAINER ID传输命令 docker cp 本地文件路径 容器ID:容器的路径将文件从容器拷贝到本地的原理是一致的&#xff0c;只需要将对应路径的位置进行更换即可

Linux学习笔记(五)

参考书籍&#xff1a;linux就该这么学 5 用户身份与文件权限 5.1 用户身份与能力 强烈推荐大家在学习时使用 root 管理员权限&#xff01;因为在 Linux 的学习过程中如果使用普通用户身份进行操作&#xff0c;则在配置服务之后出现错误时很难判断是系统自身的问题还是因为权限不…

清除Docker的占用空间问题

使用命令查看磁盘的空间 docker system df &#xff0c;类似于Linux的df命令&#xff0c;用于查看Docker使用的磁盘空间Docker镜像占据了4.789GBDocker容器占据了348BDocker数据卷占据了0B 执行删除命令 docker system prune命令可以用于清理磁盘&#xff0c;删除关闭的容器、…

区块链的完整流程 自动化执行代码

通过npm script机制&#xff0c; 在package.json文件中&#xff0c;输入对应的代码&#xff0c;就可以自动化执行相关的函数使用npm run test执行package.json中的内容&#xff0c;因为package.json包含test&#xff0c;所以可行&#xff0c;但是使用npm run compile会报错

windows版本的clion软件除了使用wsl配置Ubuntu子系统外,还可以使用MinGW-w64来配置gcc和g++

主要内容 MinGW-w64安装CMake安装环境配置参考链接 MinGW-w64安装配置 安装配置分为在线版本和离线版本&#xff0c;推荐使用离线版本&#xff0c;因为在线版本很慢&#xff0c;需要插入网线进行操作参考链接 这个是百度云下载地址&#xff0c;相对于从官网下载速度稍微快一些…

python学习路线

自用 Task1: 如果对一个列表&#xff0c;既要遍历索引又要遍历元素时&#xff0c;首先可以这样写&#xff1a; list1 ["这", "是", "一个", "测试"] for i in range (len(list1)):print i ,list1[i]#上述方法有些累赘&#xff0c…

解决使用MinGW编译C++代码报cannot find -lxxxx的问题

报错的截图如下面所示 我一开始使用target_link_libraries(ThreadTest libsdf_core.dll)这条命令来将dll库文件和项目文件关联起来&#xff0c;但是解决不了问题也尝试在编译代码的环境时候&#xff0c;将dll库文件的绝对路径加入到编译环境中&#xff0c;但是也没有用解决办法…

Linux搭建深度学习环境使用指南

本文档归纳不收悉的linux知识点&#xff0c;自用 终端美化&#xff1a;https://zhuanlan.zhihu.com/p/37195261&#xff08;unix终端通用&#xff09; 基础linux命令&#xff1a;https://blog.csdn.net/q357010621/article/details/80248611 shell是什么&#xff1f;shell是一…

CLion 输出遇到乱码解决办法,GBK和utf-8的转换

具体操作 File -> Settings -> Default Settings -> Editor -> File Encodings:Global Encoding: UTF-8Project Encoding : UTF-8Default encoding for properties files: UTF-8 图片展示 然后&#xff0c;在main.cpp右下角选择语言编码格式为GBK&#xff0c;在弹…

Vim使用方法归纳

编辑模式i 0 &#xff1a;光标移至行首d0 : 删除到行首$ &#xff1a;光标移至行尾D/d$ : 删除到行尾dd &#xff1a; 删除当前行yy/nyy : 复制当前行/复制n行p/P &#xff1a; 粘贴&#xff08;vim中删除是剪切&#xff0c;可以删除后用p粘贴&#xff09;u &#xff1a; 撤回…

epoll 转kqueue的用法介绍和实例 实现跨平台Macos

网上关于kqueue的博客很少 我来补充一个例子echo 的例子 #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include<stdio.h> #include<arpa/inet.h> #include<sys/event.…

区块链中的密码学,使用ABE结合区块链

ABE 密码学&#xff0c;以及与区块链结合的价值 背景 区块链技术具备篡改难度高、使用成本低、分布式的优点&#xff0c;本应成为各行各业的重要助力。但是由于链上参与方担心自己的核心数据外泄&#xff0c;不愿将自己的核心数据上链&#xff0c;这个原因成为阻止区块链落地…

VMware虚拟机安装Ubuntu系统教程

所使用的文件如下&#xff1a; VMware Workstation 17 Pro ubuntu-22.04.3-desktop-amd64.iso 一、ubuntu 命名规则及各版本一览表 1.ubuntu 命名规则&#xff1a; 例如&#xff1a;ubuntu 16.04 LTS 是长期维护版本&#xff1b;ubuntu 17.04 是新特性版本 前两位数字为发…

C++静态类型成员变量的初始化顺序(单例模式)

对编译器来说&#xff0c;静态成员变量的初始化顺序和析构顺序是一个未定义的行为 #include <string> #include <iostream> using namespace std; class Base{ public:static int b;static int a;}; int Base::b 2; int Base::a b 1;int main() {Base base;cou…

区块链中密码学与安全技术

区块链的定义 区块链的定义&#xff0c;应当是&#xff1a;区块链是一种按照时间顺序将数据进行分布式存储的块链式数据结构&#xff0c;它利用共识机制进行数据验证&#xff0c;利用密码学进行数据保护和用户安全访问&#xff0c;利用智能合约来操作数据&#xff0c;从而成为…

面经:单例模式

侯捷单例 和剑指不同 &#xfffc; 饿汉式 饿汉式的特点是一开始就加载了&#xff0c;如果说懒汉式是“时间换空间”&#xff0c;那么饿汉式就是“空间换时间”&#xff0c;因为一开始就创建了实例&#xff0c;所以每次用到的之后直接返回就好了。饿汉式有两种常见的写法&…

属性加密技术及基于属性的ABE算法的访问控制技术介绍

属性加密技术 基于身份的加密体制简介 基于身份的加密体制可以看作一种特殊的公钥加密&#xff0c;它有如下特点:系统中用户的公钥可以由任意的字符串组成。这些字符串可以是用户在现实中的身份信息&#xff0c;如:身份证号码、用户姓名、电话号码、Email地址等&#xff0c;因…

基于属性加密的ABE算法的应用场景思考展望

ABE算法先前使用在云计算场景中&#xff0c;和区块链存在交叉应用场景&#xff0c;具体问题体现在 数据的异地存储、云服务器提供商的不可信、管理员能否对自身数据拥有足够的控制能力以及如何保证数据的安全有效共享都是亟需解决的问题。 研究背景&#xff1a; 云计算越来越…