不再拖延!100天完美打造的智能合约区块链优化方案如约而至
智能合约区块链优化方案发布,告别MPT,历经100天耗时最终问世
作者:KJ
亲爱的 LXDAO 的朋友们,大家好!
听说大家在学习了默克尔前缀树、前缀树和以太坊的虚拟机知识后,对区块链底层设计很感兴趣。那么今天我来给大家讲一讲 MPT(默克尔前缀树)的改进和优化,以及一个更快、更高效的智能合约存储方案。
背景和动机
首先,让我给大家介绍一下我自己。我正在读博士学位,并且专注于公链的设计。最近,我设计了一个公链,不仅升级了核心共识机制,还实现了与以太坊兼容的智能合约系统。在测试过程中,我们发现了一个严重的问题:MPT 树的性能太慢了!你没听错,就是慢到让我们惊掉下巴。
请听我慷慨陈词,向你们介绍一下我们的实验。当我们试图用 Trie(前缀树)和 MPT 插入一亿个键值对的数据时,我们惊讶地发现:MPT 树的性能太差了!插入一千万个键值对,Trie 只需要几分钟,而 MPT 却需要几小时。当我们将测试数据增加到一亿个时,MPT 插入程序需要运行数天!这意味着,区块链在使用 MPT 数据结构运行智能合约时,速度将受到巨大限制。
实验证明,使用 MPT 数据结构会拖慢智能合约的执行速度,降低区块链节点的同步速度。然而,由于以太坊的数据结构设计很难被修改,区块链将很难突破性能的限制。
发现瓶颈
这就是我们面临的困境,MPT 在性能和同步速度方面限制了区块链的发展。那么,有没有办法绕过 MPT,直接在 Trie 之上实现智能合约呢?答案是肯定的!我们可以说不用 MPT、不用默克尔树,在 Trie 数据结构上设计一个更快、更高效的智能合约存储方案。
前置知识
Rocksdb 和 Trie
首先,让我来简单介绍一下 Rocksdb 和 Trie。Trie 是一种高级的树结构,我们可以把它认为是一个存在于内存中的字典树。但在工程上,我们需要在硬盘上持久化数据,所以我们一般会使用 Rocksdb 来实现 MPT 树。Rocksdb 是基于 leveldb 的开源 Fork,使用了优化过的字典树。在使用 Rocksdb 时,我们主要使用 Get、Put 和 Iterate 查询操作。
状态机
另一个重要的概念是状态机。状态机是建模区块链的工具,它非常简单:给定一个原始状态和一个输入,得到一个新状态。以太坊的全局状态可以看作是状态机的状态,所有交易可以看作是状态机的输入。一个容易被忽视的概念是状态转换函数,它定义了输入的规则。如果输入不合理,状态转换函数将拒绝输入信息。
MPT 介绍
在介绍 MPT 之前,我们先来回顾一下以太坊的三棵树:交易树、状态树和回执树。它们都是 MPT 树,全称是 Merkle LianGuaitricia Tries。其中,状态树是最适合使用 MPT 数据结构的。MPT 树基于 Trie 数据结构构建,能够像默克尔树一样计算全局状态数据的根哈希,并将其放在区块头中。通过区块头中的三棵树根哈希,我们可以查找到区块链对应的状态,并节省了重复数据占用的空间。
然而,MPT 的优势也伴随着一些问题。MPT 在写入时的性能开销较大,限制了智能合约的执行速度和区块链节点的同步速度。
但是没关系!我们已经找到了一个解决方案,通过绕过基于 MPT 的智能合约存储,直接基于 Trie 实现智能合约存储,将大大提高性能和同步速度。
设计
让我们来看一下新方案的设计。我们设计了一个基于 Trie 的方案来存储链上状态。我们将状态存储在 Rocksdb 中,并使用特定的键值格式来进行索引。通过这种方式,我们可以快速查询和更新智能合约的状态。
合约存储状态变量
对于存储简单变量类型,我们只需要查询以合约地址和变量名为前缀的键值,就可以得到最新的状态值。
存储 Mapping 类型
对于存储 Mapping 类型的变量,我们需要将合约地址、变量名和 Mapping 字典的键组合为键值。
验证区块
区块头中的 MPT 树根代表着对全局状态的验证。为了解决性能问题,我们设计了一个包含交易数据块和状态更新数据块两部分的区块头。交易数据块包含了所有交易的哈希值,而状态更新数据块则包含了交易执行后更新的状态键值。
通过这种设计,我们可以节约节点的计算资源,加快区块链的同步速度。
实现
经过几个月的设计和编码实现,我们终于完成了这个想法的落地。
首先,我们将 Python VM 整合到区块链系统中,能够使用 Python 的虚拟机执行智能合约。注意,我们并没有使用 Solidity 编译器,而是直接将 Python 代码编译成字节码。这样做的好处是可以借助现有的编译器基础设施,减少编译时间。
其次,我们实现了一个 Python 版本的 ERC20 合约,可以通过 MetaMask 进行转账。与 Solidity 不同,我们没有使用关键字来标识变量的存储方式,而是使用 _get 和 _put 函数来读取和写入状态。
最后,我们实现了 _get 和 _put 函数,通过这些函数将智能合约执行中读取和写入的状态数据存储在区块链中。这样,在交易成功执行后,对状态的修改将被汇总成状态更新数据块,并广播到整个区块链网络中。
落地和改进
经过数月的研究和实践,我们成功地实现了一个基于 Trie 的智能合约存储方案,能够代替 MPT,在性能和同步速度方面取得了显著的改进。我们的区块链测试网已经部署,大家可以使用 MetaMask 连接并进行测试。
当然,我们的工作还远未完毕。我们欢迎社区的参与,共同推动这一新型智能合约存储方案的发展。
总结
通过绕过 MPT,并设计了一个基于 Trie 的智能合约存储方案,我们成功地优化了区块链的性能和同步速度。这个过程中我们遇到了一些困难,但最终取得了成功。这次研究给我们带来了深刻的启示:在实践中积极思考,才能找到灵感,进一步创新。
非常感谢 LXDAO 对我们研究的支持,希望在社区中认识更多对区块链底层设计感兴趣的朋友。让我们一起推动区块链技术的发展,创造更加快速、高效的智能合约存储方案。
请大家留言,欢迎讨论和提问!⬇️⬇️⬇️
We will continue to update 算娘; if you have any questions or suggestions, please contact us!
Was this article helpful?
93 out of 132 found this helpful
Related articles





