起因
希望完成一些合约(操作内容大于等于交易),但不借助第三方的力量。
Bitcoin
见上文
如P2PKSH
Bitcoin都是直接使用Opcode来保证速度,他是图灵不完整的。不如直接有一个语言可以来编程。
Namecoin
Bitcoin的第一个分支,增加了三个Opcodes
- NAME_NEW: Hash(random_nonce, ‘your_domain_name’)
记录你的域名,绑定你的域名和你的私钥- 加nonce是就是加salt
- 加Hash是为了防止有人可以直接知道你的domain name进而顶替你update
- NAME_FIRST_UPDATE: random_nonce, ‘your_domain_name’, {‘ip’: ‘234.22.34.23’}
- NAME_UPDATE: random_nonce, ‘your_domain_name’, {‘ip’: “new ip address”}
问题:
- 为什么要先有第一步而不可以直接做第二步:
因为第二步中domain name是明文,这个transcation所有人都可以看到,那么别人就可以抢注你的域名(因为矿工会根据手续费的高低安排先后顺序)
所以这么做就是commit-reveal的protocol - 在第一步和第二步之间有什么要考虑的?
需要等待12个block来让矿工完成你的注册,以防止提前公布你的域名,而导致被抢注
出现的问题:
绑定但不注册的现象很严重,需要调整注册费
NameCoin提供给我们可以在区块链中实现账户的概念
Unspent Transcation Output
Bitcoin中有两种交易,一种是直接奖励给矿工的tx,另一种是普通用户之间的转账。因为一个BTC是不可分割的,引入UTXO来实现小额交易,同时也能防止双花攻击。即每一个交易的结果都是UTXO,一对一,一对多,多对一,多对多都可能发生。
其次,如同上文Transaction一节中所说的,当一个UTXO被花出去时,它自身也会变成一个新的UTXO。比如,在一个TX中,Alice知道自己有0.75BTC,想要给Bob交易0.5BTC,Bob会得到一个0.5BTC的UTXO,而剩下的0.15BTC就是在一个新的UTXO中属于Alice。
如果要验证这个tx是否合格,那么需要回溯到最早的UTXO即奖励矿工的UTXO,然后将其分化出的各个UTXO的input value(在每个UTXO中,找零给那个人的UTXO就是unspent)相加,再将所有的output value相加,如果两者相减大于等于手续费时则合格。
输入:
- 上一笔交易的输出方便回溯到之前的UTXO
- 解锁脚本是用私钥对上一笔交易的输出加密
, - 并加上共钥
,即构造成P2SH形式(同上),矿工可以验证上一笔交易的确属于发送者
优点是
- 计算是在链外的,交易本身既是结果也是证明。节点只做验证即可,不需要对交易进行额外的计算,也没有额外的状态存储。交易本身的输出 UTXO 的计算是在钱包完成的,这样交易的计算负担完全由钱包来承担,一定程度上减少了链的负担。
- 除 Coinbase 交易外,交易的 Input 始终是链接在某个 UTXO 后面。交易无法被重放,并且交易的先后顺序和依赖关系容易被验证,交易是否被消费也容易被举证。
UTXO 模型是无状态的,更容易并发处理。 - 对于 P2SH 类型的交易,具有更好的隐私性。交易中的 Input 是互不相关联的,可以使用 CoinJoin 这样的技术,来增加一定的隐私性。
缺点:
- 无法实现一些比较复杂的逻辑,可编程性差。对于复杂逻辑,或者需要状态保存的合约,实现难度大,且状态空间利用率比较低。
- 当 Input 较多时,见证脚本也会增多。而签名本身是比较消耗 CPU 和存储空间的。
State Machines
因为在UTXO中我们要余额的话需要回溯整个交易链来计算,同时不支持余额使得每个用户没有账户可言,阻止了向可编程货币的发展。
EVM引入了状态机,即在每次transaction后记录state并commit,
比如上面的例子,
- A有4个BTC,那么起始阶段 state: {A:4}
- A给B 0.25个BTC,那么经过这个TX state: {A:3.75, B:0.25}
注意到我们没有了UTXO的回溯机制,如何防止双花攻击呢?
引入了nonce,在每次交易后nonce加1。矿工检验交易顺序,如果已有nonce=4,再再次出现nonce=4的交易则为双花。
这样做的好处:不用回溯所有交易,两个state之间的交易可以快速计算,light client可以快速同步了
Replicated State Machine
- Set of possible states: S
- Set of possible inputs: I
- Set of possible outputs: O
- Transition function $f: S \times I \rightarrow S \times O$
- Start state s $\in$ S (genesis block)
Ethereum
细节
State是Account,包括以下信息
Input就是每个transcation,包括以下信息
最后的区块链如下
其中state root是state组成的merkle patricia tree,transaction root也是。即非满merkle tree,这是因为EVM允许smart contracct来做交易以外的其他操作。
在Ethereum中,有两种账户,account和contract,他们不同之处在于:
Account | Contract | |
---|---|---|
Address | Hash(pubkey) | Hash(creator,nounce) |
Code | $\emptyset$ | EVM code |
Storage | $\emptyset$ | Merkle Storage Root |
Balance | ETH Balance | ETH Balance |
Nonce | 发送过的交易tx数量 | 发送过的交易tx数量 |
Transaction种类:
- create: 创建合约
- send: 发送以太币
- call: 使用合约
以太币内存
- Storage: ${\{0,1\}}^{256} —> {\{0,1\}}^{256}$ map (permanent)
- Memory: ${\{0,1\}}^{256} —> {\{0,1\}}^{256}$ map (volatile)
- Storage很贵,Memory限制在256bit
Gas
相当于Bitcoin的Transaction Fee
- 根据opcode计算基本的gas cost
- 限制计算量和防止DOS攻击
- 矿工根据Gas Price选择做哪些交易
- 较高优先
- 每个Block的有Gas Limit上限
- Gas不够会终止执行
如果GAS_LIMIT ⨉ GAS_PRICE > accounts[from].balance,那么终止
如果终止,state返回到最初,但是钱还是花了的