以太坊
1.UTXO模型和账户模式
1.什么是UTXO?
- UTXO(Unspent Transaction Outputs)是未花费的交易输出,它是比特币交易生成及验证的一个核心概念。交易构成了一组链式结构,所有合法的比特币交易都可以追溯到前向一个或多个交易的输出,这些链条的源头都是挖矿奖励,末尾则是当前未花费的交易输出。所有的未花费的输出即整个比特币网络的UXTO。
- 比特币规定每一笔新的交易的输入必须是某笔交易未花费的输出,每一笔输入同时也需要上一笔输出所对应的私钥进行签名,并且每个比特币的节点都会存储当前整个区块链上的UXTO,整个网络上的节点通过UXTO及签名算法来验证新交易的合法性。这样,节点不需要追溯历史就可以验证新交易的合法性。
2.UTXO如何构建用户余额?
- 比特币在基于UTXO的结构中存储有关用户余额的数据:系统整个状态就是一组UXTO的集合,每个UXTO都有一个所有者和一个面值(就像不同的硬币),而交易会话费若干个输入的UTXO,并根据规则创建若干个新的UTXO
- 每个引用的输入必须有效且尚未花费;对于一个交易,必须包含有与每个输入的所有者匹配的签名;总输入必须大于等于总输出值
- 所以,系统的用户余额(balance)是用户具有私钥的UTXO的总值
3.以太坊的做法?
- 以太坊的"状态",就是系统中所有账户的列表
- 每个账户都包括了一个余额(balance),和以太坊特殊定义的数据(代码和内部存储)
- 如果发送账户有足够的余额来支付,则交易有效;在这种情况下发送账户先扣款,而收款账户将记入这笔收入
- 如果接收账户有相关代码,则代码会自动运行,并且它的内部存储也可能被更改,或者代码还可能向其他账户发送额外的消息,这就会导致进一步的借贷资金关系
1.1以太坊账户类型
- EOA(Externally owned account),外部账户/用户账户/普通账户
- 有对应的以太币余额
- 可发送交易(转币或触发合约代码)
- 由用户私钥控制
- 没有关联代码
- 合约账户(Contract Accounts)
- 有对应的以太币余额
- 有关联代码
- 由代码控制
- 可通过交易或来自其他合约的调用来触发代码执行
- 执行代码时可以操作自己的存储空间,也可以调用其他合约
1.2以太坊交易
交易即签名的数据包,由EOA发送到另一个账户。
- 消息的接收方地址
- 发送方签名
- 金额(value)
- 数据(Data,可选)
- Start Gas
- Gas Price
1.3消息(message)——合约之间的通信方式
-
合约可以向其他合约发送“消息”
-
消息是不会被序列化的虚拟对象,只存在于以太坊执行环境(EVM)中
-
可以看作函数调用
- 消息发送方
- 消息接收方
- 金额(value)
- 数据(Data,可选)
- Start Gas
2.去中心化货币的好处
- 跨国转账很便利
3.去中心化合约的好处
- 当合约发生在多个国家的时候,不同国家的法律体系不同,司法管辖的范围不同。而去中心化的合约则提供了一个统一的标准。
- 即便合约在同一个司法管辖体系下,打官司也是一个费时费力的过程。而智能合约则是强制执行的,效率高的多。
涉及工具
- MetaMask-浏览器插件钱包
- Remix-基于浏览器的Solidity在线编辑器
- Geth-以太坊客户端
- web.js-以太坊javascript API库
- Ganache-以太坊客户端(测试环境私链)
- Truffle-以太坊开发框架
与BitCoin的区别
-
从proof of work(工作量证明机制) -> proof of stake(股份证明机制)
-
增加了对去中心化合约的支持,即smart contract。注意:不是所有的合同都能够写成智能合约的形式的,只有逻辑相对来说比较简单的合同才行。
以太坊账户
- 以太坊账户和银行一样是account-based ledger(基于账户账本)。
- double spending attack(双花攻击):花钱的人不诚实,把钱重复花了两次。
- replay attack(重放攻击):收钱的人不诚实,把钱收了两次。以太坊利用计数器nonce解决该问题,每次进行交易时,都有一个不同的nonce数,而nonce数无法被篡改;故收钱账户无法将交易重放一次。
4.智能合约
-
智能合约是运行在区块链上的一段代码,代码的逻辑定义了合约的内容
-
智能合约的账户保存了合约当前的运行状态
-
solidity:是智能合约最常用的语言,语法上与JavaScript很接近
balance:当前余额
nonce:交易次数
code:合约代码
storage:存储,数据结构是一棵MPT(默克尔压缩前缀树)
注意: 只有bid()函数有payable,因为规定了如果你的合约是能够接收外部转账的话,则标注payable。
外部账户如何调用智能合约?
一个合约如何调用另一个合约
fallback:智能合约中的一个特殊的函数(编写智能合约时可以写也可以不写)。
作用:当一个账户data域是空的,即什么也不说就往这里转一笔钱,则会调用fallback()函数。
5.智能合约的创建和运行
- 智能合约的代码写完后,要编译成bytecode
- 创建合约:外部账户发起一个转账交易到0x0的地址
- 转账金额是0,但是要支付汽油费
- 合约的代码放在data域里
- 智能合约运行在EVM(Ethereum Virtual Machine)上
- EVM的作用是提高可移植性,保证在不同的平台都有相同的运行环境
- 以太坊是一个交易驱动的状态机
- 调用智能合约的交易发布到区块链上后,每个矿工都会执行这个交易,从当前状态确定性地转移到下一个状态
汽油费(gas fee)
-
智能合约是一个Turing-complete Programming Model(图灵完备的计算模型)
-
若智能合约时一个死循环代码肿么办?
-
执行合约中的指令要收取汽油费,汽油费由发起交易的人来支付
- Price:每gas的价格
- GasLimit:限制的最大Gas数量
- AccountNonce:相当于ID,防止重放攻击
-
EVM中不同指令消耗的汽油费是不一样的
- 简单的指令很便宜,复杂的或者需要存储状态的指令就很贵
错误处理
Tip:回滚(Rollback)指的是程序或数据处理错误,将程序或数据恢复到上一次正确状态的行为。回滚包括程序回滚和数据回滚等类型。
交易只有执行和不执行两种,没有执行到一半这种情况。为了防止有人每次发起复杂的合约,却又不提供足够的汽油费,白白浪费矿工的算力,故使用矿工算力的这部分gas是不进行退回的。
- 智能合约中不存在自定义的try-catch结构
- 一旦遇到异常,除特殊情况外,本次执行操作全部回滚
- 可以抛出错误处理语句:
- assert(bool condition):如果条件不满足就抛出—用于内部错误。
- require(bool condition):如果条件不满足就抛掉—用于输入或者外部组件引起的错误。
- revert():终止运行并回滚状态变动。
嵌套调用
- 智能合约的执行具有原子性:执行过程中出现错误,会导致回滚
- 嵌套调用是指一个合约调用另一个合约中的函数
- 嵌套调用是否会触发连锁式的回滚?
- 如果被调用的合约执行过程中发生异常,会不会导致发起调用的这个合约也跟着一起回滚?
- 有些调用方法会引起连锁式回滚,有些则不会
- 一个合约直接向一个合约账户里转账,没有指明调用哪个函数,仍然会引起嵌套调用
BTC和以太坊
BTC的出块速度是十分钟一个,以太坊的出块速度是几十秒一个。
BTC中区块是有限制的,规定了每个区块不超过1M(1024KB)。为了防止矿工将大量的交易都存储在一个区块中进行存储,这样会消耗大量的资源。
以太坊的GasLimit是可以进行调整的,每个获得记账权(即出块)的矿工可以将GasLimit上调或下降1/1024。最后的结果是GasLimit便趋向于所有矿工的总体意见。
一些问题
问题1:先挖矿还是先执行?
回答:现执行。
问题2:没有获得记账权的节点有补偿么?
回答:实际情况是没有补偿的,汽油费全给了有记账权的全节点。因为目前汽油费和出块奖励相比而言是很少的,所以目前问题没有很严重。
问题3:会不会有节点不对新挖出的区块进行验证,然后继续挖?因为验证也没有奖励。
回答:不会,因为对新产生的区块进行验证了之后才会更新本地的三棵树。才能够继续进行挖矿,否则当之后你自己挖到了区块了之后便无法进行发布了,因为跟其他区块数据不同步。
问题4:智能合约执行的过程中出现了错误,还需要发布到区块链上么?
回答:需要的,因为需要扣除汽油费。
问题5:智能合约支持多线程吗?
回答:不支持。因为以太坊是一个交易支持的状态机,需要足够的稳定性。多线程问题在于多个核对内存访问顺序不同的话,执行的结果也可能不同。
1.状态树、交易树、数据树均在全节点,由全节点在本地进行维护的数据结构。
2.当一个账户A发布一个智能合约之后,每个全节点都在它的本地账户将账户A的汽油费扣除,若汽油费不够的话则根本不会执行智能合约;若汽油费过多的话,则会将多出的汽油费返回账户A。
3.当其中一个全节点获得记账权之后,它将本地的交易记录在新产生的区块中。而其他全节点的三棵状态树会进行回滚,再将新产生的区块的交易信息更新到本地三棵树的数据结构中。
Receipt数据结构
地址类型
addr.balance:某个地址的余额
addr.transfer(12345):向addr这个地址转入12345wei。
智能合约的缺点
如果智能合约设计的不好的话,可能会导致投入的所有以太币均被锁死在合约账户里,永远取不出来。
以太坊钱包
transfer(12345):向addr这个地址转入12345wei。
智能合约的缺点
如果智能合约设计的不好的话,可能会导致投入的所有以太币均被锁死在合约账户里,永远取不出来。