How to save your Ethereum Dapp users from paying gas for transactions

以太坊dapp采用的一个摩擦点是用户必须支付一笔支付天然气(交易(txn)费)才能让他们的交易记录在区块链上。 例如,我有一个简单的投票dapp ,让任何人都可以为候选人投票,并将选票存储在区块链中。 想要在区块链上记录投票的用户必须支付交易/燃气费。 这并不理想,因为作为一个dapp所有者,您希望您的应用程序用户拥有以太网来支付燃气费用,因为他们所要做的只是执行与转账无关的简单操作。 但是如果交易需要在区块链上执行,除了支付费用之外别无选择。 如果用户有安全地执行交易的方式(如我们的例子中为候选人投票),并让其他人(可能是合同拥有者)在区块链上记录交易并自行付款?

感谢John Backus发来的这条推文,我只有足够的信息来帮助我为我的投票dapp实现这样的解决方案。

我想分享有关我如何为我的简单dapp实施此解决方案的详细信息,以便更多人可以在他们自己的dapps中采用这种技术,并且可以有所改进。 这篇文章涵盖以下内容:

  1. 公钥密码学和数字签名的高级概述,这是理解这个解决方案的关键。
  2. 解决方案细节和新的应用程序流程。
  3. 实施细节(前端js和Solidity合同代码)。
  4. 讨论潜在的问题和增强。

数字签名

要使这个解决方案合理化,您需要对数字签名如何在加密中起作用有一个基本的了解。 如果您知道公钥密码术,请随意跳过本节。 我将尽力在非常高的层次上解释公钥/私钥和数字签名的概念,但我强烈建议详细学习 - 维基百科是一个很好的开始

公钥密码术是一个密码系统,你有两个密钥 - 公钥(Pu)和私钥(Pr)。 你把你的公钥交给整个世界,把私钥留给自己。 例如:您的以太坊地址是一个公钥(它实际上是从公钥导出的,但是对于这个练习,我们只是将其视为公钥),并将您的私钥存储在浏览器或手机/计算机上。 如你所知,有人向你发送以太网,他们只需要知道你的公共(帐户)地址。 但是,只有您可以访问您拥有的资金,因为您是唯一知道您私钥的人。

公钥加密算法具有算法,可让您使用一对密钥对消息进行加密,解密,签名和验证。

让我们通过一个例子来看看签名和验证消息的含义。 假设用户Kim有一对公钥/私钥

Pu =“0x44ac12c1e3dfd8edaf83b6f65918229d5279a6f5”

Pr =“dbc226043e390cf39280e5edfd418d7ad61931c76509270867d300f110c46506”

为了签署消息,Kim执行输出字母数字字符串的功能符号(“投票给爱丽丝”,Pr)

签名= 0x9127112de0033555c7f6508d963d484965a953844dfcff092712102c236467a25af57edc53b63880ea39af8ce7334f6d77a8206e805305e7c6ad919d12bfae5c1b

这是Kim用她的私人密钥Pr签名的消息“投票给爱丽丝”的数字签名。

现在,任何人都可以通过执行验证功能验证该消息“投票给爱丽丝”,由Kim执行验证(“投票给爱丽丝”,签名),其输出“0x44ac12c1e3dfd8edaf83b6f65918229d5279a6f5”。 如果你注意到,那输出是Kim的公钥Pu(记住,每个人都知道它是Kim的公钥),这意味着这个消息肯定是由Kim签署的。 如果篡改签名或消息(通过更改一个字符),验证算法会输出完全不同的公钥,并且您将知道该消息被篡改,因为公钥与Pu不同。

解决方案详情

如果你理解数字签名,解决方案是非常微不足道的。 让我们看看如何在我们的投票应用程序中使用它,以免用户在不损害投票的情况下支付燃气费。 您可以在下面看到dapp的所有用户以及他们执行的操作。

  1. 选民表示他们打算通过使用他们的私钥签署消息来投票给候选人。 他们不会将他们的交易提交给区块链,所以不会支付任何费用。 上图中的消息队列只是存储所有投票详情的脱链位置。
  2. 任何愿意支付txn费用的人(通常是合同所有者)都需要签名,候选人姓名和选民的账户地址,并将其提交至区块链。
  3. 智能合约使用验证功能基于候选人姓名和签名来派生公钥(以太坊账户地址)。 如果派生的公钥与签名该消息的用户的地址相匹配,则它记录投票或否则交易失败。

实施细节

现在让我们来看看实际的实现以及所有部分如何组合在一起。

第1步:签署消息

第一步是以选民的身份签署消息。 我们将使用eth_signTypedData函数来签署我们的消息。 这个功能已经在Metamask中实现,这使得签名消息变得非常简单。 你可以在这里找到关于这个建议的更多细节和讨论: https//github.com/ethereum/EIPs/pull/712 您可以在下面找到代码以签署消息。

一个非常重要的要注意的是,内部eth_signTypedData散列消息,散列消息是签名。 您可以在这里参考typedSignatureHash函数以获取有关散列的更多细节。

第2步:将已签署的投票提交给区块链

由于这只是一个演示应用程序,因此我们不会在任何地方存储签名和其他细节。 它在消息签名后直接显示在页面上。 任何人都可以采取这些细节并提交给区块链。 以下是向区块链提交投票的代码:

第3步:验证智能合约中的投票详情

我们现在在智能合约中验证提交的投票信息是否有效,然后记录投票结果。

Zeppelin有一个名为ECRecovery方便库,我们可以使用它来验证签名的消息。 voteForCandidate函数验证签名的消息(恢复功能),并在验证成功时更新投票计数。

如果你还记得,我刚才提到eth_signTypedData在签名之前散列消息(“为Alice投票”)? solidity recover函数没有关于eth_signTypedData中使用的散列函数的任何知识,因此它不能验证消息“为Alice投票”。 它必须生成消息“投票给爱丽丝”的散列,然后验证它。 我们不是在合约内部生成哈希,而是事先对所有消息进行哈希处理,并在构造函数中传递它,这样在验证时很容易查找。 生成哈希的代码位于下面的迁移文件中

这就是获得新应用程序所需的所有代码!

我创建了一个快速演示来展示这个应用程序如何工作

整个工作代码在这里: https : //github.com/maheshmurthy/ethereum_voting_dapp/tree/master/chapter4

演示应用程序位于: https : //www.zastrin.com/voting-dapp-without-paying-gas.html

可能需要解决的问题

使用这种技术构建真正的dapp时需要考虑几个问题。 其中一些列在下面:

  1. 签名邮件存储在哪里? 您可以使用某种排队系统来存储这些消息。
  2. 什么是保证签名的信息最终被提交给区块链?
  3. 将所有消息的散列存储在区块链中并不理想,那么最好的解决方案是什么?

如果您对如何解决这些问题有所想法,或者如果您发现此解决方案中存在任何缺陷,请发表评论!

注意:显然,eth_signTypedData API仍然不稳定,只能通过metamask实现。 如果您打算在mainnet / production中使用这种技术,请小心这一点。

进一步阅读

https://en.wikipedia.org/wiki/Public-key_cryptography

https://en.wikipedia.org/wiki/Digital_signature

https://github.com/danfinlay/js-eth-personal-sign-examples/

https://danfinlay.github.io/js-eth-personal-sign-examples/

https://github.com/ethereum/EIPs/pull/712

感谢Chris WhinfreyFebin John James审阅本文的草稿。


https://medium.com/blockchannel/how-to-save-your-ethereum-dapp-users-from-paying-gas-for-transactions-cfc665891ab4

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值