首页 > 技术文章 > 以太坊 二、账户

lazyuan 2021-02-18 13:01 原文

比特币中用的是基于交易的账本,这种模式下系统中并没有显示的记录每个账户上有多少钱,要知道有多少钱,根据UTXO中的信息推算,这种模式的好处是,隐私保护比较好,你有多少钱可能连你自己都说不清楚,别人就更搞不清楚了,但是这样带来的问题是使用的时候是比较麻烦的,和我们日常的生活体验不太一样,像转账的时候,A要转给B 10个BTC,就要证明币的来源的合法性
 
而我们的日常生活体验是:当我们去银行存钱的时候,需要说明钱的来源,确实是有人转给你钱了,将来你花钱的时候,不需要说明当初每一笔钱是从哪来的
 
比特币这种模式,另外一种让人觉得比较别扭的地方是:你在前面的交易中收到一笔输出,收到一些币,你将来花出去的时候,需要全部都花出去,不能只花一部分
 
比如A转给B 10个比特币,B转给C 3个比特币
 
剩下的7个比特币将会当作transaction free花出去了,矿工是很高兴的,你不会高兴,所以必须得把剩下的7个比特币再转回给自己,比如转给B的另外一个地址,很多比特币钱包可以自动生成这种接受余额的地址,每次交易换一个新地址,这个也是有利于隐私保护的,打一枪换一个地方,但同样和我们的日常生活习惯不太一样
 
上述两个问题都在于:比特币系统中没有显示的维护基于账户的交易的概念,而是每一个交易单独进行处理,以太坊系统采用的是另一种方法:基于账户的模型,这种模型和我们日常生活中的银行账户是比较相似的,即系统中显示的记录账户中有多少个以太币
 
而以太坊中,不用说明B中币的来源是来源于哪个交易,B要转给C 3个以太币,也不用将7个转给自己,因为有显示的余额设置
 
这样做有一个好处是,我们前面讲,比特币面临的一个主要挑战是double spending attack,以太坊这种基于账户的模式,对于double spending attack具有天然的防御作用,因为我反正不用管你币的来源,每花一次,都从账户上扣除一次余额,系统余额是在系统中全节点维护的状态中保存的,系统中的余额没有办法篡改,如果要修改余额,需要所有的全节点都认为发生了变化
 
但是与之相应的出现replay attack(重放)的风险
 
A转给B 10个ETH,A发布一个转账交易到全网上,过一段时间之后,该交易被写到区块链里了,A以为转账交易完成了,假设B是有恶意的,他把这个交易又再往上重新广播了一遍,其他结点看A往B又转了10个ETH,以为是一个新的转账,就把A的钱又扣了一次
 
重放攻击和double spending attack是对称的,double spending attack是花钱的人不诚实,以前花过的钱又重新花了一遍,replay attack 是收钱的人不诚实,别人已经给你转过一遍,你想让他再给你转一遍
 
那为什么以前没有说过replay attack?比特币当中有没有可能出现replay attack?不可能的,因为是太显然的double spending attack,以太坊中怎么解决这个问题?
 
加一个计数器nonce,记录交易次数,记录这个账户交易有史以来一共发布了多少个交易,然后转账的时候交易次数成为交易内容的一部分一起包含进去,都是受到发布交易者签名的保护的
 
 
比如A账户转给B 10个ETH,A账户以前发布过20个交易,这是第21笔交易,设置nonce=21,将这整个内容由A签名,下图是一个完整的交易,将该交易发布到网上,因为有签名的保护,所以nonce值别人无法进行修改,系统中每个结点维护A账户的状态,不光是维护A账上有多少钱,还要维护nonce的值,账户新创立的时候,没有历史交易,因此初始值是0,以后每次发布新的交易,nonce值要加1
以太坊中有两类账户,一类叫做外部账户(externally owned account),外部账户就类似于前面比特币中说的那种账户,用公私钥控制的,本地产生公私钥对,谁拥有私钥,谁就掌握账户的控制权,有时候也管他叫普通账户,一个外部账户的状态有,账户余额(balance)和计数器(nonce)
 
第二类账户叫合约账户(smart contract account),合约账户不是通过公私钥对来控制的,不是说你掌握了某个私钥就有对这个合约账户的控制权,合约账户也是有nonce的,一个合约可以调用另外一个合约,同样通过nonce值记录调用的次数,但是合约账户不能主动发起一个交易,所有的交易只能由外部账户发起,外部账户发起一个交易,如果调用了一个合约账户,这个合约账户可以发送一个message调用另外一个合约,但合约自己不能平白无故的发起一个交易,除此之外合约账户还有代码(code)以及相关的状态存储(storage)
 
那么合约账户怎么被调用呢?创建合约的时候会返回一个地址,知道这个合约地址就可以调用这个合约,调用的过程中状态会发生变化,代码(code)是不变的,状态存储(storage)是改变的
 
为什么要设计这样一种新的模型?比特币已经有比较成熟的代码可以参考,为什么要另搞一套,系统设计上可以进行改进,比如改出块时间、改mining puzzle,不一定非要改账户系统,比特币的基于交易的账户模型优点是隐私保护比较好,每次交易都要换一个新的账户,打一枪换一个地方;而以太坊支持的是智能合约,对于合约来说,要求参与者要有比较稳定的身份,这个和我们日常生活中是类似的,比如说你和某个人签了一个合同,如果说你和他签合同的时候他是一个身份,签完合同之后他又是一个身份,你找不到了,这就是一个问题了,也有可能突然冒出另外一个人,说他就是当初和你签合同的,只不过是换了一个身份,这就给合同的执行带来了一些困难,包括将来出现纠纷的时候,你也要知道当初合同是和谁签的
 
现在有一些人提出用智能合约实现一些金融衍生品,所谓的叫financial derivative ,就比如说期权、期货这种东西,你往合约里投一笔钱,预测未来的价格走势,如果预测的正确,给你一些收益并把钱还给你,但问题是如果你投钱的这个账户,投完钱之后账户就变了,到时候就无法把钱还给你
 
这个不光是外部账户存在这个问题,合约账户问题就更严重了,如果你投钱投了一个合约账户,投完之后合约账户的地址变了,找不到了就麻烦了


推荐阅读