论文作者 Pingcheng Ruan, Gang Chen, Tien Tuan Anh Dinh, Qian Lin, Beng Chin Ooi
简介
区块链实现了一个可以防篡改的账本,可以用来记录交易信息(transactions)进而改变一些存储的全局状态。整个系统记录所有的状态演化的历史信息。对于这些历史信息的管理,通常被称作数据的溯源(data provenance or lineage)。在传统的数据库领域,这一方向已经被广泛研究。但在区块链中对历史数据进行检索,目前的方法只能依赖于分析所有的交易信息。这样的方法适用于大规模的离线分析,而对于在线交易信息的处理是不合适的。
这篇论文实现了LineageChain系统,支持细粒度的、安全高效的区块链数据溯源功能。LineageChain通过简单的API将溯源信息传给给智能合约,从而实现了一类新的区块链应用程序,其执行逻辑依赖于运行时的产生的溯源信息。在智能合约执行的过程当中,LinageChain会获取到溯源信息,然后高效地存储在Merkle Tree当中。LineageChain提供了基于跳表索引的结构来支持更加高效率的数据溯源的检索。整个系统基于Hyperledger来实现。存储系统基于ForkBase实现。论文对LineageChain的性能做出了分析,证实其的高效、安全、需要更少的存储代价等诸多优势。
背景
区块链影响着很多产业,比如金融业、供应链、医疗等。和传统数据管理系统相比,产业界更多看重区块链所具备的两点优势:1) 区块链为一个去中心化系统,这使得互相不信任的人可以共同维护一个共同认可的数据而不需要相信一个可信第三方。2) 区块链提供了对于所存储的交易信息的数据完备性保护(不可篡改)。换言之,区块链保证了完整的交易历史信息的安全性。
对于数据历史的管理,或是数据溯源,已经被数据库方向广泛研究。很多系统也支持了数据溯源。在现有的区块链系统中,可以支持粗粒度的数据溯源功能。进一步讲,区块链可以被视作存有许多的状态(state,并已知其初始状态),每一笔交易信息都会将现有状态更新至新的状态。对于历史状态的演化可以通过对所有交易信息的重放来安全地、完整地重新构建出来。这样的重新构建可以被离线分析完成。但在智能合约执行的过程当中,没有任何溯源信息可以被智能合约使用。换言之,智能合约不可以访问在区块链存储的历史数据状态,从而做到数据溯源。缺乏对于运行时的细粒度的数据溯源功能限制了为了实现商务逻辑对智能合约的使用。
考虑下面这个智能合约的例子
这个智能合约包含一个方法,可以将一部分代币从一个账户转账到另一个账户。假设用户A想要将一部分代币转给B,转账条件基于B的过去几个月的历史账户余额。例如,只有B的每日平均账户余额超过t的时候A才会转账给B。使用现有的智能合约目前不能简单实现这一操作。要解决这一问题,A需要首先查询然后重放有关B的所有历史交易数据,然后基于得到的结果决定是否发起Transfer这笔交易。除去在与区块链网络多次交互所带来的性能开销的缺点,这一做法实际上并不安全:它不能实现交易的可串行化。假设A想要基于B的历史余额发起Transfer交易tx,但在tx被区块链网络认可前,另一个可以使B的余额小于t的交易被区块链认可。这样的后果就是当tx过后被认可,它会基于一个旧的状态。这样的结果会违反最初设定的商业逻辑。在区块链中,违反可串行化会导致用户严重的财产损失。
概念介绍
区块链系统
由多个互相不信任的节点构成。现有的区块链可大致分为公有链和私有链。对于前者,任何节点都可以加入或离开网络。对于后者,加入与否被严格限制。一个节点必须经过认证才会被基于加入网络的权利。
共识。 所有的区块链都假定了Byzantine Failure模型。在这个模型中,故障的节点可以做出任何行为。在这样的设定下,区块链使用Byzantine Fault Tolerance (BFT) 共识协议来保证诚实地节点可以达成一致的状态。BFT协议包括比特币使用的Proof of Work (PoW),Hyperledger使用的PBFT。传统的BFT协议,例如PBFT,保证了诚实节点达到相同的区块链结构。PoW和它的变种允许不一致性,也就是分叉(forks)。这些协议使用确定性选择一个分支的方法来解决分叉。比如在PoW中,最长的分支会被选择。
数据模型。不同的区块链对状态有不同的数据模型。比特币使用Unspent Transaction Outputs (UTXOs) 模型,包括交易输出没有被其他交易当做输出。UTXO模型可以支持简单的交易验证。节点只需要检查交易的输出没有被之前的交易使用。而以太坊Ethereum和Hyperledger都使用了更加广泛地状态类型,使用智能合约来管理区块链上的状态。他们使用了基于账户的数据模型(account-based data model)。每个账户在区块链上都有其本地的状态。智能合约交易可以在对应的存储写入任何数据。这种灵活的数据模型以保护完整性和验证帐户状态为代价。这篇论文只考虑account-based 数据模型。
区块结构。 区块存储对应的交易和全局状态信息(global states)。区块头包含以下信息:
- PreviuosBlockHash: 对应前一个区块的哈希信息
- Nonce: 被用来查看此区块的有效性。在PoW共识中,Nonce是PoW的答案。
- TransactionDigest: 被用来做区块内交易信息的完备性保证。
- StateDigest: 被用来做在执行过交易之后的全局状态的完备性保证。
TransactionDigest和StateDigest均为由Merkle树构成的根哈希信息。它们支持高效率的区块传递。区块头和区块体可以分开传输。它们也使得对于交易和全局状态的验证更加高效。
首先根据PoW验证Nonce的正确性。如果是确定性的公式算法,这一步可以跳过。接下来查看存储的交易信息没有被篡改,根据验证TransactionDigest来判断。再重新执行包含的交易,之后节点可以检查结果的状态是否和StateDigest匹配。如果都验证通过,新的状态可以被提交到区块链存储。否则状态就会被回滚到之前的状态。
状态的组织(State Organization)
对于区块链来说最重要的特点就是保障数据的完备性,这意味着其存储的全局状态必须保证防篡改。上述的区块验证算法对于区块链的安全至关重要。算法需要访问所存有状态的所有历史快照(history snapshots),同时还要保证可以批量的更新状态。这些需求给设计用于组织区块链状态的索引结构带来了新的挑战。特别的,传统的数据库索引比如B+树不能被直接使用。接下来我们讨论有关设计索引的需求。
- 防止篡改的证据。用户可能想要读取其中一些状态值而不愿意下载并执行所有的区块链交易。由此,所设计的索引必须可以生成对于任何状态读取的完备性证明。进一步讲,索引必须提供一个惟一的信息摘要 (digest) 来代表整个全局状态。这样,区块链节点就可以快速查看区块链网络上执行后的状态值是否相同。
- 增量更新。 整个全局状态在区块链应用中会变得十分庞大。但一个区块只会改变一部分状态。比如,有些状态可能在每一个区块中都会被更新,其他状态的更新频率可能更低一些。因为索引会在每一个区块被更新,对于增量更新的支持显得尤为重要。
- 快照(snapshot)。一个索引的快照(snapshot)和对应全局状态都会在每一个新的区块产生时发生变化。当一个接收到的新的区块产生了一个分叉(fork),旧的状态快照(snapshot)必须被用作验证程序的输入。当区块链不允许有分叉时,当接收到的区块在执行交易后被发现为失效交易则可以回滚到之前的状态(算法1的第四步)。
现有的区块链系统使用基于Merkle结构的索引。进一步讲,以太坊Ethereum平台使用Merkle Patricia Trie (MPT)索引结构,为Merkle结构和前缀树的结合体。Hyperledger使用Merkle Bucket Tree (MBT)。在Merkle树中,父节点的哈希值是根据子节点哈希值算出的。根节点代表了整个数据内容的唯一标识符。验证完备性的证明可以快速的通过Merkle树来生成而不需要读取整个数据。所以,Merkle树符合第一个要求。这一结构同样适合做增量更新(第二点要求),因为只有在更新中被影响的节点才需要发生变化。为了支持高校的快照,在Merkle树更新时要递归化地在更新路径上生成新的节点。新的根节点可以作为新的快照的索引,其可以被添加到区块头中。
LineageChain的概括
给定一个智能合约,LineageChain支持更加细粒度的、安全的、高效的数据溯源。智能合约可以实现一个helper方法来定义对应在合约被调用时需要被记录的数据溯源信息。默认的情况下,所有的状态的读写依赖都会被记录。获取到的信息会被存储到一个区块链存储上来保证高效的数据追踪和防止篡改的数据溯源。系统有在存储结构之上构建一个基于跳表的索引结构以支持更加快速的数据溯源查询。这些对于区块链存储的改变对于合约开发者来讲是不可见的。