北京大学肖臻老师《区块链技术与应用》公开课笔记(十五):ETH账户
BTC系统是基于交易的账本,系统中并未显示记录账户有多少钱,只能通过UTXO进行推算,A转给B钱的时候,还需要说明币的来源。这与我们实际情况有很大出入,实际中只需要存钱说明来源,花钱直接从账户里扣即可。此外,账户中的钱在花的时候,必须一次性全部花出去,因为没有输入大于输出的钱全给了矿工当小费。
如图1,B收到A的10个BTC,他想要给C3个BTC,那么他就必须要把多的7个比特币转给自己的另一个账户B‘上
以太坊系统则采用了基于账户的模型(account-based ledger),与现实中银行账户相似。系统中显示记录每个账户以太币的数量,转账是否合法只需要查看转账者账户中以太币是否足够即可,不需要说明币的来源,也不必每次都花完。同时,这也也天然地防范了双花攻击(花两次扣两次即可,你总的货币量是固定的)。
重放攻击
这种模式虽然天然防范了双花攻击,但是存在重放攻击的缺陷。A向B转账,过一段时间,B将A的交易重新发布,从而导致A账户被扣钱两次。比特币系统能天然防范重放攻击:大多数节点收到了第一次A->B的订单后,回从UTXO里删除那条转给A的记录,那么B过一段时间重放A->B的订单,那么其他节点在验证订单合法性时,能直接判断出这是非法订单。
为了防范重放攻击,给账户交易添加计数器nonce记录该账户交易过多少次,转账时候将这次交易的转账次数计入交易的内容中,合在一起用自己私钥签名。
系统中其他节点维护账户余额和每个账户的计数器,每次收到交易时除了改变对应账户余额,还要改变nonce值。从而防止重放攻击。
账户余额能不能人为修改
不能。
发布交易时,不需要显式说明自己账户余额。账户余额是系统中全节点维护的系统状态树。状态树是BTC系统中重要的数据结构,就是所有用户的状态组成一颗树,用户的状态里包含账户余额等,要想篡改账户余额,需要所有全节点都认为你的余额发生变化。
以太坊系统中存在两类账户
外部账户(externally owned account)和合约账户(smart contract account)
外部账户: 类似于BTC系统中公私钥对。存在账户余额balance和计数器nonce
合约账户: 并非通过公私钥对控制。存在账户余额balance、计数器nonce(合约账户也会被调用)、 代码code、相关状态storage(包括每个变量的取值)
注意:
- 系统中所有交易只能外部账户发起,外部账户发起一个交易,如果调用了合约账户,合约账户可以发送一个message调用另外一个合约账户
- 创建合约时候会返回一个地址,知道合约的地址,就可以对其调用。调用过程中,代码code不变但状态存储storage会发生改变。
为什么要这么设计,以太坊的创始人Vitalik(19岁小孩)创建ETH时,考虑了诸多因素,比特币中支持每次更换账户,但以太坊是为了支持智能合约,而合约签订双方是需要明确且较少变化的。尤其是对于合约账户来说,需要保持稳定状态,才有了这样的设计