Mina 架构简介

每个 Mina 智能合约的帐户可容纳 8 个任意字段的元素。每个字段的大小大约为 32 个bytes。这看起来可能不多,但考虑到在底层,以太坊使用了类似的机制,其中一个元素(world state trie)引用了储存在其他地方的任意数量的合约状态。该引用字段称为 storageRoot,顾名思义,它保存包含合约帐户所有存储状态(the Account Storage trie)的 trie 的root hash。 Mina 合约帐户上的 8 个字段元素中的每一个都类似于以太坊的 storageRoot,能够保存对储存在其他地方的任意数量的资料的承诺。以太坊将所有这些额外的状态尝试作为全域网路状态,并为您管理它(需要gas成本)。然而Mina却没有。您需要将自己的资料结构储存在链下,并将这些结构提交到链上帐户的状态字段中。这通常是透过将实际状态保存在 Merkle 树中并将该树的root hash储存在帐户字段之一中来完成的。它的机制基本上相同,但与网路分离。无论使用多少储存量,这都允许固定的交易成本。

Mina 本质上是一个证明验证层。例如链下计算和固定交易费用,但这只是一部分。 Mina 上的 zkApps 为开发人员提供了产生、排序和验证事物证明的能力。例如身份、社区中身份验证、签名方案或其他网路的汇总状态等等。当您提交 zkApp 的交易时,Mina 会对您的证明进行排序及将它们与其他证明组合起来,以创建迄今为止提交到网路对所有事实的单一聚合验证。可以将您的自订证明转化为进一步的证明,然后同以验证交易、区块生产以及最终的整个网路状态。类似的递归可组合性功能也掌握在您的手中。这意味着您可以採用无需信任、分散且去中心化的方式来建立可组合证明并对其进行排序。您可以建立一个既是独立事实陈述的应用程序,也可以是由社群创建的更大和可验证计算的一个片段。

Mina 特别的地方是某些状态可以保留在区块链上,但只要它被包装在零知识电路中,执行计算的动作就可以在任何地方执行。 而 o1js 可以允许开发人员编写在最终用户的浏览器中执行的应用程序,但依然可靠地将状态提交到公共帐簿。因为状态的改变是由原计算的有效性证明授权的,而不是由执行计算的环境来授权。

在交易中是如何发挥作用?

Mina 不是 RPC,当与用 o1js 编写的 zkApp 互动时,并不是要求区块链执行智能合约中的方法。当一个交易提交给 Mina 时,相对应的方法已经被呼叫。同一时间应用逻辑已在零知识电路内执行。只要满足电路中定义的所有约束,交易就可以简单地描述一组应应用于公共帐簿的状态更改,还有在零知识证明之下可以表明这些更改是可以信任。 Mina 协议只是验证证明,如果证明有效,则将这些变更提交到公共帐簿。所以可以看到计算和状态已经分离。这使得每个 zkApp 都成为一个汇总(rollup),因为网路状态变化被证明是源自于任何地方。这就是为去中心化应用程式提供固定交易费用的原因。这也是为什么独特的 Action/Reducer 模型对于管理排序和并发存取状态是必要的。

排序(Sequencing)、动作(Actions)和减速器(Reducers)

排序在任何分散式系统中都是一个关键挑战。在区块链中,区块生产者决定交易的次序。应用程式开发人员无法控制此次序,并且必须将其交易设计为可交换的(可按任何顺序处理),因为影响状态的计算发生在交易排序之后。在基于 Mina 创建的 zkApps 中,计算发生在链下,甚至在交易提交之前。可惜的是交换性是不够的,因为不单是顺序不受我们的控制,而且在计算发生时它甚至还没有确定。

那要如何在没有竞争条件的情况下改变状态呢?

利用动作(actions)和减速器(reducers)。 zkApps 应该发布一个包含稍后时间更改状态所需的资料的操作,而不是直接更改状态。这让协议有机会在处理这些操作之前对操作进行排序。然后在一个单独的过程使用一个减速器来消耗这些操作及处理它们,并在另一个交易中提交最终状态。基本上是拆分聚合步骤并在完成排序之后才执行它。