1 Motivation
区块内交易按照顺序一个个执行限制了系统吞吐量,没有利用现代计算机系统多核资源进行并发计算。因此需要并行执行区块内交易。
2 Contribution
- 矿工动态并行执行区块内交易的方法;
- 验证者可以验证矿工指定的交易并行执行序列的正确性,并根据该序列确定性地、并行地来验证矿工的执行结果;
- 使用JVM和ScalaSTM实现了原型。对于矿工而言,有1.33倍的提升,验证者有1.69倍的提升。
3 Method
Miner
每一次合约调用(包括嵌套调用)视为一个ACTION;
一个ACTION包括多个storage operations(SOP),可以简单将SOP视为原子操作;
每个SOP有一个锁,不同SOP的锁不一样,所以一个ACTION有多个锁。当SOP获取到锁时,SOP对应的inverse operation(逆操作)会被记录到log中,便于ACTION执行失败时操作回滚;
如果ACTION-B需要锁LOCK-0,然而LOCK-0现在正在被ACTION-A中的某个SOP-A-0使用,此时ACTION-B就要等待ACTION-A执行完(所有的SOP执行完,不只是SOP-A-0)。
“执行完”有两个含义:1)ACTION-A成功提交,则ACTION-A包含的所有SOP的锁全部释放,所有的log被丢弃;2)ACTION-A中断,则ACTION-A根据log执行inverse operations(逆操作),撤销所有操作,最后释放所有SOP的锁。即无论是成功提交还是中断,ACTION-A中涉及到的所有的锁都要被释放。
每个SOP都具有inverse operaion可以使得虚拟机支持细粒度的并发控制。比如传统并发控制可能会粗粒度的对某段内存区加锁,并记录inverse operation,由于这段内存可能涉及到其他的操作,所以通过inverse operation执行回退时会产生冲突。
每次把一个ACTION提交之后才释放该ACTION所拥有的所有的锁,同时对于ACTION-i的锁LOCK-i,需要将其计数器counter加1,并把{LOCK-i: counter}记录在ACTION的profile中。该计数器的目的是为了能够确定锁LOCK-i的传递队列。
矿工在执行的时候会根据counter构建锁LOCK-i的传递队列,比如ACTION-2拥有锁LOCK-i,然后ACTION-2执行完成,LOCK-i传递到了ACTION-3的手中,ACTION-3继续执行,因此对于每个LOCK-i可以构建一个传递队列,队列的元素是交易的标识符。为什么是交易而不是ACTION?因为一笔交易在合约嵌套的情况下可以产生多个ACTION,子ACTION执行完成后,会将其所拥有的锁返给父ACTION,即这些ACTION中的锁始终被一笔交易所拥有,且只有父ACTION成功提交后,子ACTION的状态变化才算是提交成功。可以理解为一笔交易中的所有ACTION是绑定在一起的,所以锁LOCK-i的传递队列中的元素是交易。
矿工会把所有锁的传递队列H放到区块中,广播给验证者。
Validator
验证者收到锁传递队列H后,将所有锁的传递关系倒置,获得队列~H,即对于锁LOCK-i => {Tx1, Tx2, Tx3....Txn},倒置之后是LOCK-i => {Txn...Tx3, Tx2, Tx1}。那么对于LOCK-i,就可以知道Tx3执行之前,必须执行Tx2,同理,Tx2执行之前,必须执行Tx1,那么将每个锁的传递关系倒置之后,就可以知道交易Txi执行之前,必须执行的交易列表。验证者根据队列~H并行执行交易,检测最终状态是否和矿工的状态一致。
如果矿工发送了一个假的锁传递队列fake-H,该队列的并行程度虽然低于队列H,但是可以正确执行,文章中提到这种“调皮”是无法避免的。
如果矿工发送了一个错误的锁传递队列error-H,那么验证者如何检查出来呢?文章中提到的解决方案是:验证者执行交易的过程中,记录下每个锁的传递路径,如果该路径和矿工提供的profile不同,那么拒绝这个块。我个人认为这里是有问题的:矿工完全可以自己先按照error-H运行一遍,获得每个锁的传递路径,然后根据该路径设计profile,并将profile提供给验证者。
另外,论文中用到了fork-join和work-stealing方案,但是我并没有理解这两个方案的作用。
4 EVALUATION
主要评估两个方面:
- 给定数据冲突的数量,随着交易数量的提升,执行速度如何变化?预期:随着交易数量提升,数据冲突比例越来越低,所以并行化效果越来越好,执行速度越来越快,直到达到硬件限制;
- 给定交易数量,随着数据冲突数量的提升,执行速度如何变化?预期:数据冲突数量较低时,执行速度比顺序执行要好,但是数据冲突数量较高时,执行速度可能会不如顺序执行。
结果:对于矿工而言,可以实现1.33x的提升;对于验证者而言,可以实现1.69x的提升。