您现在的位置是:主页 > 行业动态 >

TokenPocket钱包安卓APP下载|深入探讨MUD引擎的存储结构

2024-03-17 12:30行业动态 人已围观

简介 三年前开始开发全链游戏时,开发体验糟糕,因此创建了MUD引擎来解决问题。逐步改进开发流程,实现当前存储架构。考虑到客户端同步大量数据状态,提出实现状态变更自动同步、避...

三年前开始开发全链游戏时,开发体验糟糕,因此创建了MUD引擎来解决问题。逐步改进开发流程,实现当前存储架构。考虑到客户端同步大量数据状态,提出实现状态变更自动同步、避免自定义getter、event和reducer的愿望。通过实现泛型事件、自定义库来解决这些问题,最终达到目标。通过压缩存储字节、编码方式实现状态读取和解码。虽然Solidity不支持通用返回类型,但通过代码生成成功实现理想的开发体验。MUD引擎已通过审核,稳定版2.0.0即将发布。

三年前,当我们开始开发全链游戏时,开发体验还非常糟糕。因此,我们有了MUD引擎,以减少开发过程中遇到的各种问题。

接下来,我将详细介绍我们是如何在开发过程中逐步完善,并最终实现了当前的存储架构。

回看2021年(即MUD成立的前一年),我们按照当时的“最佳实践”在自定义的结构体(custom struct)、映射(mapping)和备份(array)中保存链上状态,通过自定义的查看函数(视图函数)来获取状态,对每一次状态变化编写自定义的事件(自定义事件),并在客户端和索引器上实现自定义事件处理的reducer函数。

数据

这种方法对于小规模的链上应用是可行的,但是全链游戏需要客户端同步大量的数据状态。很快,我们发现自己大部分时间都在处理数据模型的变更,并通过他们自定义网络堆栈来实现这些变化,而不是一股能量中心化在游戏机制的开发上。

数据

当开发过程中遇到困难和挑战变得难以忍受时,我们决定暂停一下体验,应该重新思考理想中的开发所关注的。

我们唯一的愿望是在智能合约上设置一个状态变量,并且能够自动与客户端同步,不用自定义getter、event和reducer,只需简单地读取状态。

数据

解决方案的第一步是实现一个泛型事件(generic event),他能够在每次状态改变时被触发,使得索引器或客户端能够自动同步链上的状态。

数据

但问题是,在Solidity中并没有现成的“泛型事件”。不过,我们还是找到了替代方案。

本质上,类型(Type)不过是对字节(Byte)的分层封装。因此,我们通过使用原始字节(raw byte)作为事件数据,实现了一种能够覆盖所有状态变更的通用事件机制。

数据

接下来,我们需要一个能够在每次状态变化时触发事件的泛型库(通用库),从而避免自定义setter函数的需求。

数据

Solidity并没有提供这样的泛型库,但我们采用了类似的策略来实现这一目标。我们没有使用泛型类型(generic type),而是虽然采用了所有类型(type)的共同基础——字节,作为函数签名的参数。

数据

这带来了一个新的挑战:如何将各种类型的数据转换成字节,再传递给这个库呢?最直接的方法是使用Solidity内置的abi.encode函数。然而,因为到处都添加填充而不一致用于编码后的值。

数据

一个更好的选择是使用 abi.encodePacked 函数,它能够紧凑地压缩数据,避免了重建填充。不过这个方法不能填充阵列(array)类型。

数据

为此,我们不得不在Solidity中自行实现阵列的紧凑编码方法。这种方法类似于提案中的abi.encodeTightlyPacked(https://github.com/ethereum/solidity/issues/8441…)。

数据

更进一步,我们如何实现一个 Solidity 函数,能够接受任何类型的集群并返回其紧凑备份的字节形式呢?我们首先为所有基本类型集群的共同基础——bytes32[] 实现资源逻辑。

数据

然后,我们为Solidity支持的98种基本类型备份(如uint8)[]uint16[]…, 字节32[])各添加了一个特定的处理逻辑。这样,我们便拥有了一个能够接受任意基本类型仓库并返回其压缩存储字节的函数。

我们越来越接近目标了。

数据

最后的挑战是如何从中存储读取并解码这些值。我们需要一个类似 abi.decode 的函数,但是要适用于我们自定义能够的压缩编码方式:一个根据给定的编码字节和一个“模式(schema)”返回解码值及其原类型的函数。

数据

由于Solidity不支持通用返回类型,我们也无法像以前一样将其转化为通用类型。因此,我们转而采用了代码生成的方式。您只需要在一个配置文件中定义您的数据结构,MUD就可以为您生成具有类型信息的读写库。

数据

至此,我们的目标就实现了

消耗任何自定义的getter、event和reducer。只需简单地进行读写操作。每次状态的写入操作都会触发一个事件,该事件用于自动将链上状态同步到索引器和客户端。

数据

虽然Solidity本身不支持类型类型,但通过一些泛化的解决技巧,我们仍然能实现理想中的开发体验。

数据

我们投入大量时间开发MUD引擎,旨在提升构建可扩展的全链上应用的开发体验。目前,MUD已通过OpenZeppelin的全面审核,稳定版2.0.0即将发布。

Tags:

本栏推荐

标签云

站点信息

  • 文章统计14578篇文章
  • 标签管理标签云
  • 微信公众号:扫描二维码,关注我们