本文讨论了加密货币中最大可提取价值(MEV)的问题,以及如何使用可信执行环境(TEE)和不经意随机存取存储器(ORAM)来缓解MEV攻击。文章介绍了Flashbots的BuilderNet架构和Oblivious Labs在实现私有订单流和数据访问层面的工作,以保护用户隐私和防止信息泄露。
如今,许多加密货币面临的一个重要问题叫做最大可提取价值 (MEV)。交易以明文形式提交,容易受到抢先交易和滞后交易攻击。这种攻击使套利者能够获得不公平的利润,而用户则被迫以较低的价格买卖。由于此类 MEV 攻击,出现了一个链下生态系统:区块构建者现在将区块中的有利位置出售给套利者和用户,从而导致中心化效应。如今,80%-90% 的以太坊区块是由最大的两个区块构建者生成的 [ Yang et al.]。
为了缓解 MEV,社区投入了大量精力来构建新的私有订单流架构,其中交易以加密格式提交,并且在不泄露交易的情况下组装区块。
一种实现私有订单流的有前途的方法是使用可信执行环境 (TEE)。从高层次上讲,TEE 建立了一个沙箱(通常称为飞地),其安全性通过防篡改硬件强制执行。传输中或静态的数据始终被加密,只有在飞地内部才能对其进行解密和计算。在私有订单流的情况下,区块构建者的机器(也称为服务器)配备了 TEE。用户正在向服务器的飞地提交加密交易,并且服务器还维护着一个加密的 mempool 和一个区块链数据的加密副本。区块构建发生在飞地内部,交易在那里被推测性地执行。
例如,Flashbot 的 BuilderNet 架构提供了一个用于分散区块构建的平台。BuilderNet 支持 TEE 以允许安全/可验证的交易执行,同时也启用了私有区块构建的选项。
图 1:使用 TEE 的私有订单流
仅靠加密不足以实现隐私。如前所述,要私下构建一个新区块,区块构建者会在飞地内部推测性地执行交易。智能合约的执行需要访问区块链的状态,并且访问模式可以被服务器观察到。
通过访问模式泄露了什么?
在流行的以太坊应用程序中,这些访问泄露了高度敏感的信息。例如,下面我们展示了一个 Uniswap 合约的核心部分。高亮显示的行泄露了敏感信息,例如 1) 正在交易的代币;2) 发布订单的帐户;以及 3) 转移的方向。这正是我们希望保护的信息,而仅靠加密几乎无法保护它。
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock {
...
// 追踪是谁在 swap
ensure(msg.sender == token0 || msg.sender == token1);
// 追踪交易对
(address token0, address token1) = (token0, token1);
// 追踪交易的方向
_safeTransfer(token0, to, amount0Out);
_safeTransfer(token1, to, amount1Out);
...
}
服务器如何学习访问模式?
不受信任的服务器可以通过多种方式观察访问模式。
首先,如果区块链的状态不适合放入飞地的受保护内存中,那么飞地需要操作系统的(或虚拟机管理程序的)帮助才能从飞地外部获取内存页。在这里,页面交换可以是从不安全的 RAM 或磁盘获取数据。在任何一种情况下,OS/虚拟机管理程序都会直接观察到页面级别的访问模式,而无需发起任何复杂的攻击。
即使区块链的状态可以放入飞地的受保护内存中,服务器仍然可以通过几种类型的攻击来观察飞地内的内存访问:
我们还要强调的是,简单地置换不受信任的存储中的数据是行不通的。通过利用频率和共现性,对手很容易通过统计推断来推断哪个位置存储了什么。这类似于确定性加密不安全的原因。
那么,我们该怎么做才能防止访问模式泄漏?我们可以使用不经意 RAM (ORAM) 的帮助。ORAM 是一种算法技术,可以可靠地隐藏程序对数据的访问模式。下面我们将快速介绍一下 Path ORAM 算法。
主要数据结构。首先,主要的数据结构是一棵二叉树。树中的每个节点都称为桶 (bucket)。根桶具有超对数容量,而其他每个桶的容量为 4。每个桶存储真实块和填充块的组合。真实块是实际数据的加密,而填充块是 0 的加密。填充块是安全所必需的。
路径不变性 (Path invariant)。路径不变性是指在任何时间点,一个块都会被分配到一条随机路径,即从根到随机叶节点的路径。每个块都必须位于其所属的路径上的某个位置。
操作。要获取一个块,我们只需要访问该块所在的路径即可。关键的见解是,我们需要在读取一个块后立即将其重新定位到一条新的随机路径。而且,我们不能泄露新路径的选择。实现此目的的一种方法是将该块写回根桶。但是,随着我们不断发出更多请求,根桶很快就会被填满。
因此,我们引入了以下驱逐过程以及每个数据请求:对于我们刚刚访问过的路径,我们将尽可能靠近叶子地重新打包该路径上的块,而不会破坏路径不变性。我们可以证明,通过这种驱逐过程,除了概率可以忽略不计之外,不会发生溢出。
递归位置图 (Recursive position map)。最后一个问题是,我们如何才能知道一个块位于哪条路径上?这是通过递归来实现的。想象一下,我们有一个位置图,记录了每个块的路径。只要块的大小足够大,这个位置图就小于原始数据集。我们现在递归并将这个位置图存储在一个较小的 ORAM 树中,直到位置图(的位置图的位置图……)是常数大小。在实践中,块大小(即页面大小)通常为 4KB,对于以太坊大小的数据集,递归深度最多为 3。
总之,在 Path ORAM 中,忽略递归,则每个请求仅涉及访问单个树路径。
现在,你应该看到 ORAM 只是一个简单的基于树的数据结构,并且与许多人认为的相反,它不涉及任何加密!因此,ORAM 的性能与将数据存储在数据库中相当,也就是说,我们可以享受几乎原生的性能。事实上,ORAM 的可扩展性已经在 Web2 应用程序中得到了证明。值得注意的是,私有消息应用 Signal 在其私有联系人发现服务中使用了 ORAM --- 请参阅 Signal 的博客文章了解有关此主题的信息。在采用 ORAM 之前,他们依靠一种幼稚的批量线性扫描算法来实现隐私,需要 ~500 台服务器。在推出 ORAM 之后,他们能够减少到只有 6 台服务器,从而节省了近 100 倍的计算成本。
微基准测试。如下表所示,我们的实现比 Signal 和 Meta 的实现快一个数量级或更多。具体来说,在 2^30 的数据库大小下,我们的不经意键值存储实现的延迟为 50μs。使用 4096 的批量大小,我们的吞吐量为 20 万个请求/秒(在数据大小为 2^28 时)。
我们的不经意键值存储的性能:数字以微秒 (μs) 为单位
如果你确信并且想要使用 ORAM,你可以查看 Oblivious Labs Inc. 提供的 开源实现(MIT 许可证)。
区块链应用中的预计性能。如果我们想在区块构建期间使用 ORAM 来保护所有 Uniswap 交易的访问,那么我们预计会有多少延迟?我们查看了最近的以太坊区块数据。平均而言,每个区块有 ~20 个 Uniswap 交易。每个 Uniswap 交易都会进行 3 次内存访问(sload/sstore 操作),这些访问很敏感。使用我们上面的微基准测试,如果我们将整个以太坊状态存储在 ORAM 中,那么构建一个区块的预计延迟将为 3 毫秒。如果我们将每个 uniswap 合约存储在单独的 ORAM 中,则延迟可以进一步降低到 0.5 毫秒,但这会泄露正在交换哪一对代币。
在 Oblivious Labs Inc.,我们创建了一个不经意的以太坊 ERC20 代币余额检查器的演示,允许用户检查其 ERC20 代币余额,而无需识别查询的帐户。我们的演示可在https://obliviouslabs.com/WBTCdemo/ 上找到。
我们的余额检查器演示(如上所示)是针对 WBTC 代币的。我们在一个不经意的键值存储中维护着一份 WBTC 合约状态的最新副本。我们还实现了一个更新器 (updater),它不断地从 geth 节点读取新铸造的区块。然后,更新器会验证 Merkle Patricia 树 (MPT) 证明,然后再将状态更新添加到不经意的键值存储中。通过不经意的键值存储,用户可以查询其余额而无需识别自己。
我们当前的不经意余额检查器仅为单个合约的状态提供不经意的访问,但我们的下一步是扩展它,并在相同架构的基础上支持对整个以太坊状态以及区块链数据的不经意查询。最终结果将是一个用于以太坊的不经意数据访问层,支持对以太坊完整状态和日志的快速支持查询,同时隐藏用户的意图。
如果你有兴趣与我们合作,请联系 obliviouslabs@gmail.com。
- 原文链接: writings.flashbots.net/s...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!