搜索
NFT元宇宙Web3
近期热门

学习Solidity 的 第 2 部分:提交投票和揭示投票结果

Founder

卡尔弗洛施

学习Solidity 的 第 2 部分:提交投票和揭示投票结果

什么是Solidity ?

Solidity是一种面向契约的高级语言,语法与 JavaScript 相似。它是静态类型的,支持继承、库和复杂的用户定义类型。它编译为 EVM 程序集,由节点运行。

什么是commit-reveal 的“提交和揭示”?

要了解 commit-reveal承诺方案的工作原理,将其分解为两个组成部分很有用:

  1. 提交:你向你的同行表明你的选择。
  2. 揭示:你揭示了你的选择,每个人都可以验证,这到底是不是你所承诺的。

该方案在进行民意调查或选举时特别有用。人们可能希望等待所有选票都投完,然后再透露谁为谁投票。这可以防止选民根据其他选民已经投下的选票做出判断(避免作出跟随大多数人的选择)。

为了更好地理解 commit-reveal 在实践中的工作原理,请考虑以下实现:

物理世界中的提交投票和揭示投票结果

首先,让我们了解如何在物理世界中实现 commit-reveal 投票。下图介绍了每个步骤:

学习Solidity 的 第 2 部分:提交投票和揭示投票结果

遵循这些步骤可确保人们在投票期间不受彼此投票的影响。

虚拟世界中的提交投票和揭示投票结果

在代码中实现 commit-reveal 投票与在物理世界中不同。不同之处在于,在代码中,我们将使用 ahash function而不是投票保险箱。

在本教程中,你可以将哈希函数想象成一个神奇的管道,你可以在其中插入文字,它会吐出疯狂的HEX(十六进制)代码,如下所示:9c22ff5f21f0b8b9a3cb658. 出来的HEX代码有几个重要的属性:

  1. 相同的输入总是产生相同的HEX代码;
  2. 没有办法给出HEX代码并确定输入是什么。

现在你已经是一个哈希斯大师了,让我们来看看如何实现虚拟提交–揭秘吧!

学习Solidity 的 第 2 部分:提交投票和揭示投票结果

现在我们知道了实现生活中提交-显示投票的步骤,让我们开始用 Solidity 编写代码吧!

设置我们的 Commit-Reveal 选举合约

我们将使用 Browser Solidity 编辑器部署一个合约,该合约处理单次选举的提交-显示投票。单击以下链接以打开CommitRevealElection预加载代码的 Browser Solidity:

https://ethereum.github.io/browser-solidity/#gist=0ba69290f5d18823548dc32fe1f6a250

注意:你可以在 GitHub Gist 上找到完整的合约源代码。

你现在应该CommitRevealElection在编辑器中看到所有合约代码。类似于以下内容:

学习Solidity 的 第 2 部分:提交投票和揭示投票结果

在我们开始操作之前,让我们切换浏览器 Solidity 环境以使用本地 VM。本地 VM 对测试很有用,因为交易几乎是即时的并且不要求测试ETH。稍后我们可以使用公共测试网,它可以让我们在互联网上与我们的朋友一起创建投票!

要使用 JavaScript VM,请单击右上角的框图标并选择JavaScript VM。

学习Solidity 的 第 2 部分:提交投票和揭示投票结果

现在我们正在使用JavaScript VM,让我们开始测试!

部署我们的 Commit-Reveal Election 合约

要开始一个新的选举,我们必须部署一个新的CommitRevealElection合约实例。当我们部署时,我们必须指定一些关键参数来定义我们的选举。这些参数在合约构造函数中定义:

学习Solidity 的 第 2 部分:提交投票和揭示投票结果

1、uint
_commitPhaseLengthInSeconds- 我们选举的提交阶段应该持续多长时间。一旦时间到了,将不允许再提交投票,只允许显示投票。

  • 如果你希望提交阶段持续 3 分钟(180秒),请输入180.

2、string _choice1- 我们的第一个候选人,即”Grand Master Doge”。

3、string _choice2- 我们的第二个候选人,即”Apex Alpaca”。

要创建部署合约,请输入你的参数并单击屏幕右侧的红色按钮:

学习Solidity 的 第 2 部分:提交投票和揭示投票结果

现在合约已部署,你会看到一堆蓝色按钮弹出,如

学习Solidity 的 第 2 部分:提交投票和揭示投票结果

这些代表你可以随时访问的值,不会改变区块链状态。你可以单击它们以查看我们选举的当前状态。

如果向下滚动,你还会看到:

学习Solidity 的 第 2 部分:提交投票和揭示投票结果

这是我们最重要的两个功能。很快我们将使用commitVote(bytes32 _voteCommit)提交几票。但首先,我们需要生成并提交哈希。

生成哈希

在我们的虚拟提交-显示投票方案中,我们使用哈希函数来生成我们的_voteCommit. 在这次选举中,我们将使用散列函数keccak256。单击以下链接访问我们将用来散列投票的网站:

https://emn178.github.io/online-tools/keccak_256.html

该页面应如下所示:

学习Solidity 的 第 2 部分:提交投票和揭示投票结果

尝试在Input框中输入。请注意,你键入的每个字符都会创建不同的哈希值。还要注意,同一个词总是产生相同的散列。这就是我们生成投票提交的方式!

投票格式

在此实现中,

投票choice1将采用以下形式:

学习Solidity 的 第 2 部分:提交投票和揭示投票结果

投票choice2将采用以下形式:

学习Solidity 的 第 2 部分:提交投票和揭示投票结果

请注意1和2是实际投票。包含密码是为了确保投票在揭晓之前保持秘密。每次投票都需要使用唯一的密码。如果两个投票使用相同的密码,那么投票提交将是相同的。如果投票提交相同,则只计算一票!

提交投票

首先,我们需要生成我们的投票提交。为此,请在输入部分输入格式正确的投票。然后复制生成的哈希。(确保你不要忘记密码!)

学习Solidity 的 第 2 部分:提交投票和揭示投票结果

现在打开 Browser Solidity,我们将在其中提交我们的投票提交。

重要提示:浏览器 Solidity 要求所有都HEX以0x. 你复制的哈希包括0x前缀。不要忘记在你的哈希前面添加0x

要提交,请向下滚动找到红色commitVote按钮。然后输入你的哈希,前缀0x并用引号括起来。格式正确后,单击红色按钮提交。

学习Solidity 的 第 2 部分:提交投票和揭示投票结果

提交后,很可能会收到错误:

学习Solidity 的 第 2 部分:提交投票和揭示投票结果

这是 Solidity 中极为常见的错误。在这种情况下,这意味着你在提交阶段之后提交了提交(读起来有点绕,但是意思没问题)。如果是这种情况,只需重新部署 CommitRevealElection合约!

如果你的提交成功,你应该会收到一个记录“投票已提交”的事件。

学习Solidity 的 第 2 部分:提交投票和揭示投票结果

要提交更多投票,只需重复此过程,每次更改密码即可。在这个过程中,对同一个账户多次投票会没有限制。只需确保每张投票的格式正确,再说一次,不要忘记密码!

公开投票结果

投票期结束后,我们就可以开始公开投票结果了!为此,我们将调用该函数:

学习Solidity 的 第 2 部分:提交投票和揭示投票结果

投票是我们放入哈希计算器的输入文本,提交是对应的输出哈希。不要忘记在哈希前面加上0x。格式正确后,单击红色按钮提交。

学习Solidity 的 第 2 部分:提交投票和揭示投票结果

如果你再次收到错误VM Exception: invalid JUMP,这可能是因为你试图在提交阶段完成之前就显示投票结果。你必须等到时间到了才能开始揭示投票结果。

如果你的投票结果成功显示,你应该会看到相应的事件。

学习Solidity 的 第 2 部分:提交投票和揭示投票结果

重复这个过程,直到每一张选票都被揭晓。请注意,在此过程中,如果有任何未公开的未决选票,则选举过程将不会结束。如果你不想这么麻烦的计算每张选票,你可以轻松地更改合约,让合约包括揭示结果的阶段是否超时的设定。

现在可以看到选举到底谁赢啦?

getWinner统计完所有选票后,点击蓝色按钮,看看谁赢了!

学习Solidity 的 第 2 部分:提交投票和揭示投票结果

使用 MetaMask 部署到公共测试网

既然我们知道如何使用本地 JavaScript VM 进行选举,那么在公共测试网上进行相同的选举就很容易了。这使你可以与所有朋友一起进行选举!

注意:如果你不知道如何使用MetaMask,请参阅学习 Solidity 第 1 部分:使用 MetaMask 进行合约开发

首先,我们需要告诉 Browser Solidity 使用 MetaMask 的Injected Web3对象而不是JavaScript VM. 导航回该框,这次选择Injected Web3。

学习Solidity 的 第 2 部分:提交投票和揭示投票结果

现在只需按照用于JavaScript VM的方法来操作。 唯一的区别是,你必须在 MetaMask 中批准你的所有交易,然后等着就行。

简单测试一下,让朋友们来参与投票

自己和自己玩确实很无聊,让我们试试呼朋唤友来测试一下这个投票吧。为此,首先他们必须打开相同的 Browser Solidity 链接:

https://ethereum.github.io/browser-solidity/#gist=0ba69290f5d18823548dc32fe1f6a250

接下来,他们需要将你的选举地址输入 Browser Solidity。要查找你的选举地址,请打开 MetaMask。然后Contract Published在你的历史记录中查找交易。找到后,单击复制图标:

学习Solidity 的 第 2 部分:提交投票和揭示投票结果

将地址发送给他们后,他们需要将其添加到 Browser Solidity。为此,请单击标有 的绿色按钮At Address。

学习Solidity 的 第 2 部分:提交投票和揭示投票结果

将弹出一个询问地址的窗口。接下来,将MetaMask提供的地址,复制到文本字段中。然后,去掉开头的0x,找到的正确的地址!这里操作有点小麻烦,MetaMask 复制的地址是包括最前面的0x,但 Browser Solidity 不喜欢0x。,所以记得去掉 [本文写于2017年,可能会和现在的情况有出入]。

学习Solidity 的 第 2 部分:提交投票和揭示投票结果

添加后,你的朋友应该会立即看到你创建的新合约,同时弹出的所有相同按钮。从那里,他们可以按照我们用于JavaScript VM.的操作来实施。

下一步

  • 当前CommitRevealElection合约不限制一个账户可以投票多少次!你可以试试对这种限制进行修改。提示:检查msg.sender!
  • 目前,每张选票都必须公开,否则选举永远不会有结果。你可能希望在显示阶段添加超时设置或其他一些机制以避免此问题。提示:检查now和time units
编辑于 2022-05-05 08:13
「 真诚赞赏,手留余香 」
赞赏

发表评论已发布0

手机APP 意见反馈 返回顶部 返回底部