参考资料:https://medium.com/@mvmurthy/full-stack-hello-world-voting-ethereum-dapp-tutorial-part-1-40d2d0d807c2

这是一个非常简单的应用程序,只需要初始化一组参赛者,任何人都可以给候选人投票,并显示每位候选人收到的总票数。

我们的目标不是只编写一个应用程序,而是学习编译,部署和与之交互的过程。

我故意避免使用任何dapp框架来构建这个应用程序,因为框架抽象掉了很多细节,不利于理解系统的内部结构。不过当你使用框架时,你将更加感激框架为您所做的所有繁重工作!

这个练习的目标是:

  1. 建立开发环境
  2. 了解编写合同,编译并将其部署到开发环境中的过程。
  3. 通过nodejs控制台与区块链上的合约进行交互。
  4. 通过一个简单的网页与合约进行交互。

系统示意图如下:

1.搭建开发环境

我们将使用内存区块链(将其视为区块链模拟器)——ganache,而不是真的区块链开发应用程序。在Part2,我们将使用真的区块链。

以下是在Linux操作系统上安装ganache,web3js和启动测试区块链的步骤。

czk@czk-vm:~$ npm -v
6.1.
czk@czk-vm:~$ node -v
v8.11.2
czk@czk-vm:~$ sudo apt-get install build-essential python
czk@czk-vm:~$ cd work/
czk@czk-vm:~/work$ mkdir hello_world_voting
czk@czk-vm:~/work$ cd hello_world_voting
czk@czk-vm:~/work/hello_world_voting$ mkdir node_modules
czk@czk-vm:~/work/hello_world_voting$ npm install ganache-cli
czk@czk-vm:~/work/hello_world_voting$ npm install web3@0.20.6
czk@czk-vm:~/work/hello_world_voting$ node_modules/.bin/ganache-cli

ganache-cli会创建10个测试帐户,这些帐户预村了100个(假的)Eth。

(以上为局部安装,关于npm 与node_modules, 见https://www.runoob.com/nodejs/nodejs-npm.html

2. 简单的投票合约

我们使用Solidity语言来编写智能合约。我们将编写2种方法,一种是返回候选人收到的总票数,另一种方法是增加候选人的投票数。

注意:当您将合约部署到区块链时,构造函数只会被调用一次。与在Web中,新部署代码会覆盖旧代码不同,区块链中部署的代码是不可修改的。

如果您更新合约并再次进行部署,旧合约仍会保留在区块链中,并保留其中的所有数据,新的部署将创建一个新的合约实例。

以下是投票合约代码:

 pragma solidity^0.4.18;
// We have to specify what version of compiler this code will compile with contract Voting {
mapping(bytes32 => uint8) public votesReceived; /* Solidity doesn't let you pass in an array of strings in the constructor (yet).
We will use an array of bytes32 instead to store the list of candidates
*/
bytes32[] public candidateList; /* This is the constructor which will be called once when you
deploy the contract to the blockchain. When we deploy the contract,
we will pass an array of candidates who will be contesting in the election
*/
constructor (bytes32[] candidateNames) public {
candidateList = candidateNames;
} // This function returns the total votes a candidate has received so far
function candidateVotes(bytes32 candidate) public view returns(uint8) {
require(_candidateValidation(candidate), "Invalid candidate.");
return votesReceived[candidate];
} // This function increments the vote count for the specified candidate. This
// is equivalent to casting a vote
function VoteToCandidate(bytes32 candidate) public {
require(_candidateValidation(candidate), "Invalid candidate.");
votesReceived[candidate]++;
} // This function check the validity of input candidate.
function _candidateValidation(bytes32 candidate) private view returns(bool) {
for(uint i = 0; i < candidateList.length; ++i) {
if(candidateList[i] == candidate)
return true;
}
return false;
}
}

将以上代码复制到Voting.sol文件中,并将该文件置于hello_world_voting目录下。现在让我们编译代码并将其部署到ganache区块链。

为了编译Solidity代码,需要安装npm模块solc:

czk@czk-vm:~/work/hello_world_voting$ npm install solc
+ solc@0.4.

我们将在节点控制台内使用这个库来编译我们的合同。

web3js是一个库,可让您通过RPC与区块链进行交互。我们将使用该库来部署我们的应用程序并与其进行交互。

首先,在终端中运行'node'命令以进入节点控制台并初始化solc和web3对象。下面的所有代码片段都需要在节点控制台中输入。

czk@czk-vm:~/work/hello_world_voting$ node
> Web3 = require('web3')
> web3 = new Web3(new Web3.providers.HttpProvider("http://localhost::8545"));

为了确保web3对象被初始化并且可以与区块链进行通信,我们来查询区块链中的所有帐户。你应该看到如下结果:

将Voting.sol中的代码加载到字符串变量中并进行编译。

> code = fs.readFileSync('Voting.sol').toString()
> solc = require('solc')
> compiledCode = solc.compile(code)

当成功编译代码并打印'contract'对象(只需在node控制台中键入compiledCode)时,其中有两个重要的字段:

1. compiledCode.contracts[‘:Voting’].bytecode: 这是在编译Voting.sol中的源代码时获得的字节码。这是会被部署到区块链的代码。

2. compiledCode.contracts[‘:Voting’].interface: 这是合约的接口或模板(称为abi, Application Binary Interface),它告诉合约用户合约中有哪些方法可用。无论何时需要与合同进行交互,都需要此abi。

现在我们来部署合约。您首先创建一个合约对象(下面的VotingContract),用于在区块链中部署和启动合约。

> abiDefinition = JSON.parse(compiledCode.contracts[':Voting'].interface)
> VotingContract = web3.eth.contract(abiDefinition)
> byteCode = compiledCode.contracts[':Voting'].bytecode
> deployedContract = VotingContract.new(['Rama','Nick','Jose'],{data: byteCode, from: web3.eth.accounts[], gas: })
> deployedContract.address
> contractInstance = VotingContract.at(deployedContract.address)

上面的VotingContract.new将合约部署到区块链。我们现在已经部署了合约,并且有一个合约实例(上面的可变contractInstance),我们可以使用它来与合约进行交互。在区块链上部署了数十万个合约。那么,你如何在区块链中识别你的合约呢?答案:deployedContract.address。

当与的合约进行交互时,需要合约部署地址和合约的abi。

3. 在nodejs控制台中与合约进行交互

4. 通过网页与区块链上的合约交互

现在大部分工作都已完成,现在我们所要做的就是创建一个带候选人名字的简单html文件,并在js文件中调用投票命令(我们已经在nodejs控制台中测试过)。 以下是index.html文件和index.js代码,将它们都放在hello_world_voting目录中,然后在浏览器中打开index.html。

 <!DOCTYPE html>
<html>
<head>
<title>Hello World DApp</title>
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'>
<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 Hello World 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>Rama</td>
<td id="candidate-1"></td>
</tr>
<tr>
<td>Nick</td>
<td id="candidate-2"></td>
</tr>
<tr>
<td>Jose</td>
<td id="candidate-3"></td>
</tr>
</tbody>
</table>
</div>
<input type="text" id="candidate" />
<a href="#" onclick="VoteToCandidate()" class="btn btn-primary">Vote</a>
</body>
<script src="https://cdn.rawgit.com/ethereum/web3.js/develop/dist/web3.js"></script>
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js"></script>
<script src="./index.js"></script>
</html>

注:以上代码运行时,可能会出现无法连接到网站错误。在虚拟机中无法打开这个网页,但是在windows中浏览器中可以打开。。。。将该网页中的js代码保存为web3.js文件,放入工作index.html同一目录,将37行改为 如下代码即可。

<script src="./web3.js"></script>

index.js:

 web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
abi = JSON.parse('[{"constant":true,"inputs":[{"name":"candidate","type":"bytes32"}],"name":"candidateVotes","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"candidate","type":"bytes32"}],"name":"VoteToCandidate","outputs":[],"payable":false,"stateMutability":"nonpayable","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"},{"inputs":[{"name":"candidateNames","type":"bytes32[]"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]')
VotingContract = web3.eth.contract(abi);
// In your nodejs console, execute contractInstance.address to get the address at which the contract is deployed and change the line below to use your deployed address
contractInstance = VotingContract.at('0x5367391364f427209e5f08acd260f21abb15ba30');
candidates = {"Rama": "candidate-1", "Nick": "candidate-2", "Jose": "candidate-3"} function VoteToCandidate() {
candidateName = $("#candidate").val();
contractInstance.VoteToCandidate(candidateName, {from: web3.eth.accounts[0]}, function() {
let div_id = candidates[candidateName];
$("#" + div_id).html(contractInstance.candidateVotes.call(candidateName).toString());
});
} $(document).ready(function() {
candidateNames = Object.keys(candidates);
for (var i = 0; i < candidateNames.length; i++) {
let name = candidateNames[i];
let val = contractInstance.candidateVotes.call(name).toString()
$("#" + candidates[name]).html(val);
}
});

用浏览器打开index.html文件,你将看到一下内容。

如果您可以在文本框中输入候选人姓名并进行投票,可以看到查看投票计数增加,那么您已经成功创建了第一个应用程序!恭喜!

总结一下,本文设置了开发环境,编写简单的合同,在区块链上编译和部署合同,并通过nodejs控制台和网页与其交互。

在Part2部分,我们将把这个合同部署到公共测试网络,以便全世界都可以看到它并投票给候选人。并使用Truffle框架进行开发(而不必使用nodejs控制台来管理整个过程)。

Hello World投票以太坊Dapp教程-Part1的更多相关文章

  1. 智能合约开发——以太坊 DApp 实现 购买通证token

    合约的buy()方法用于提供购买股票的接口.注意关键字payable,有了它买股票的人才可以付钱给你. 接收钱没有比这个再简单的了! function buy() payable public ret ...

  2. 链上链下交互 以太坊Dapp接口开发

    主要是指的是用NodeJs调用 提供接口供前端使用 用户查询和转账 以太坊Dapp项目 众筹项目 功能需求 路人 查看所有众筹项目, 2 @ OK 根据众筹项目的address获取该众筹的详情 (参与 ...

  3. 以太坊开发教程(二) 利用truffle发布宠物商店 DAPP 到 以太坊测试环境Ropsten

    1.环境安装 1) node安装 设置镜像地址: curl --silent --location https://rpm.nodesource.com/setup_8.x | bash -下载安装 ...

  4. 关于书籍《区块链以太坊DApp开发实战》的内容告示

    书中所列举的以太坊 etherscan 浏览器,原链接已经不能使用国内网络正常访问了,需要翻墙,下面的链接不需要翻墙,也是 etherscan 的官方浏览器链接: 以太坊浏览器:https://cn. ...

  5. 部署开发以太坊dapp的四种方式

    我们已经学习了4种开发和部署智能合约的方法: 第1种是使用 Truffle 和 Ganache .由于我们从上一篇教程中复制了代码,所以我想告诉你,有些插件可用于目前最流行的文本编辑器和 IDEs.有 ...

  6. 以太坊开发教程(一) truffle框架简介/安装/使用

    通常一个DAPP的开发包括两部分:智能合约的开发和提供合约进行调用的前端页面. truffle提供了对这两部分内容比较简单的开发方式,特别是在开发/测试阶段.给开发人员提供快捷的打包/部署,已经本地服 ...

  7. 以太坊(ethereum)开发DApp应用的入门区块链技术教程

    概述 对初学者,首先要了解以太坊开发相关的基本概念.   学习以太坊开发的一般前序知识要求,最好对以下技术已经有一些基本了解: 一种面向对象的开发语言,例如:Python,Ruby,Java... 前 ...

  8. 如何从零开始学习区块链技术——推荐从以太坊开发DApp开始

    很多人迷惑于区块链和以太坊,不知如何学习,本文简单说了一下学习的一些方法和资源. 一. 以太坊和区块链的关系 从区块链历史上来说,先诞生了比特币,当时并没有区块链这个技术和名词,然后业界从比特币中提取 ...

  9. 智能合约开发solidity编程语言开发一个以太坊应用区块链投票实例

    智能合约开发用solidity编程语言部署在以太坊这个区块链平台,本文提供一个官方实战示例快速入门,用例子深入浅出智能合约开发,体会以太坊构建去中心化可信交易技术魅力.智能合约其实是"执行合 ...

随机推荐

  1. CodeForces599D【数学】

    题意: 给出一个x,求有多少个矩阵中满足存在x个不同的正方形. 思路: (数学渣+推理渣) #include<bits/stdc++.h> using namespace std; typ ...

  2. laravel 遍历循环

    @foreach($xxx as $k=>$y) {{$y->id}} @endforeach

  3. 剑指OFFER之最大子向量和(连续子数组的最大和)(九度OJ1372)

    题目描述: HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学.今天JOBDU测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决.但 ...

  4. [Xcode 实际操作]九、实用进阶-(17)使用CGBlendMode改变UIImage颜色,实现对图片进行混合着色

    目录:[Swift]Xcode实际操作 本文将演示如何使用CGBlendMode改变UIImage颜色,实现对图片进行混合着色. 在项目文件夹[DemoApp]上点击鼠标右键 ->[New Fi ...

  5. java 三大基本特征

    java中的面向对象的三大基本特征是:[封装].[继承].[多态] 封装:对象要有一个明确的边界:边界的划分(对象各司其职.对象的粒度.对象的可重用性) 属性(bean.pojo):私有的privat ...

  6. PHP不重新编译,单独添加模块扩展的方法

    php自身提供了很多扩展,比如curl,gmp, mbstring等.我们在编译安装php时未必安装了所有扩展.那么在安装完php后,如果想单独安装某个php自身的扩展怎么办呢? 我们以curl扩展模 ...

  7. iReport - 无法正常启动的解决方法

    问题与分析 最近需要用到iReport报表工具,但是在启动客户端时却发现只出现了启动界面,很快就界面消失没反应了.反复打开了好几次客户端,都无法正常打开.问了下同事,说是因为jdk升级的原因,以前项目 ...

  8. 解读ping -n 4 127.1 >nul 2>nul

    命令解读 ping是Windows.Unix和Linux系统下的一个命令.ping也属于一个通信协议,是TCP/IP协议的一部分.利用"ping"命令可以检查网络是否连通,可以很好 ...

  9. JS中一个new到底做了哪些事情?

    1.https://www.cnblogs.com/faith3/p/6209741.html 2.https://www.cnblogs.com/AaronNotes/p/6529492.html

  10. python快排

    代码: def partition(data,left,right): tmp = data[left] while left<right: while left < right and ...