以太坊上的秘密

 
作者:Monaj
 
翻译:西溪明月
 
编辑:格鲁特

以太坊因缔造“区块链2.0”时代而出道

以方便应用创建,其社区庞大驰名全球

然而

……

技术进步的道路漫漫

……

漫漫

……

所以

……

各种各样的Bug

肯定很多嘛 

以太猫这种耳朵长茧的梗就不提了

今天再给大家介绍一款Bug!

程序员都知道 建议回避

(或者你可以看完,说不定有纠错的机会

本文举了一个基于游戏里智能合约的例子

所以主要场景也是围绕此讨论

 

Step1:直接进入正文

(意不意外惊不惊喜)

许多合约,比如游戏合约,通常需要保密一些数值。比如,存储玩家的下一步行动或等着被猜的数字。虽然用户或合约都不能直接读取私有变量,但这仍难以保证一定能够保密。在Solidity语言中,使用private似乎是存储秘密值的一个非常简单的方法。然而,这并不会限制任何人读取合约的状态。这是因为合约交易中存储的数据具有可读性。

我们以多人奇-偶游戏合约为例,该合约基于被猜的数字来选出获胜者。每个玩家选择一个数字,如果所选数字之和为偶数,那么第一个玩家获胜,若为奇数,则第二个玩家获胜。

// WARNING: This is a sample contract to demonstrate the functionality. Don't use it in your project.
pragma solidity ^0.4.21;

contract OddEven {
   struct Player {
     address addr;
     uint number;
   }

   Player[2] private players;
   uint8 count = 0;

   function play(uint number) payable public {
        require(msg.value == 1 ether);
        players[count] = Player(msg.sender, number);
        count++;
        if (count == 2) selectWinner();
   }

   function selectWinner() private {
        uint n = players[0].number + players[1].number;
        players[n%2].addr.transfer(address(this).balance);
        delete players;
        count = 0;
   }
 }

游戏合约将两个玩家的赌注(即选出的数字)存储在players映射中。由于这个变量是不公开的,所以第二个玩家不能读取到这个数据。而每个玩家必须向合约转1个以太币游戏才能开始。这个条件要用require来核查。

一旦第二个玩家下好赌注(即选好数字),按照奇-偶逻辑会选出获胜者,他将得到两个玩家下的所有赌注金额。如果心怀不轨的玩家实施攻击,他就可以一直赢。攻击者会等对方先走第一步,自己扮演第二个玩家。现在,尽管变量是隐私的,但通过解码所使用的以太坊交易攻击者能够读取第一个玩家所选的数字。这样他就可以选择让自己赢的那些数值。

上面这个例子中的合约代码仅用于说明,可能存在漏洞。强烈建议使用前进行审核。

 

如何读取私有状态变量

How to read private state variables

 

以太坊上的状态变更通常通过交易来实现。如果接收账户是交易的合约,那么EVM(以太坊虚拟机)将运行合约代码,或直到代码运行完毕或直到执行过程耗尽所有gas。

每项交易的数据字段规定了细节(如调用哪种方法和输入参数等)。比如,在合约中修改私有状态的变量,你需要通过交易将“private”数值传递给setter方法。考虑到每个交易数据都对所有节点可见,所以如果知道一项交易,就可以轻易读取其中的私有变量。

我们回顾一下上文讨论的奇-偶合约,看看应如何解码交易数据。对于每一种方法调用,交易数据都将有2个字段:

1、Method selector     方法选择器

2、Method parameters   方法参数

在我们的智能合约中,调用方法会输出以下交易数据。我们来尝试对此解码。

0x6587f6ec0000000000000000000000000000000000000000000000000000000000000064

交易数据的前4个字节指向方法签名。它是通过计算方法签名的keccak散列的前4个字节得出的。在我们的例子中,是通过计算bytes4(keccak256(‘play(uint)’))函数得出的0x6587f6ec。以下字符指向指定方法的参数。每个参数由填充至32字节的输入的十六进制值表示。如果100是play方法的输入参数,那么该参数的交易数据就是:

0x0000000000000000000000000000000000000000000000000000000000000064

如果有更多参数且这些参数是动态的,情况就会变得更加复杂。你可以从solidity文件中获得更多信息。

 

存储私有信息的一些建议

Recommendations for storing private information

 

在合约中,你可能会有存储私有变量的需求,但这个问题会很复杂。对于存储私有信息,人们已经进行了大量的模拟尝试,其中有一个方法很有趣,它采用的是提交显示模式(commit reveal pattern)。在这个方法中,用户需要首先提交私有信息的哈希,当所有其他人也提交了他们的私有信息的哈希时,每个参与者再亮出自己的投票,之后可以对此进行验证。

这并不适合所有的应用程序,并使用户的操作变得更加复杂了,但抛砖引玉,它为未来的探索打开了一扇门。

作者简介 Manoj

开发人员、顾问、作者,以太坊爱好者。

项目采访

首发|发币谁都会,你会发“货”么?是时候用Token干点“正经事”了正逢数字货币乱世,他们想用技术来保护投资人的最基本权益

数字货币交易所何去何从?

用区块链技术实现影响力的商业价值

用区块链技术拉起股权交易市场新的增长曲线

基于智能合约和区块链技术的创新信贷交换平台

“双链合璧”:他们想利用区块链打造更透明、更高效的供应链体系

专家专栏

EOS起源

硅谷资深投资人讲析区块链项目投资|教程

解决集成需求才是未来区块链业务的重点

不可篡改、可靠、安全——区块链安全性简史

信仰和投机:币圈没有奇迹

与元道对话三:区块链经济正在进行“动力切换”

百家观点

区块链+物联网+共享经济是什么玩法?

基于区块链的智能锁设计与实现

如何设计区块链项目的通证(token)模型

加密货币和区块链(一):历史的重演

裸照与区块链社群

疯狂的韩国比特币市场:“全民”炒币,人均收益率425%

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注