# 详解最小化反共谋基础设施MACI：链上治理中的抗勾结框架

By [PAUL](https://paragraph.com/@paul-4) · 2021-11-13

---

详解最小化反共谋基础设施MACI：链上治理中的抗勾结框架
============================

_作者：Eric Zhang_

关于这篇文章的背景，请参考《[二次方投票和二次方资助](https://matataki.io/p/6113)》。在这篇文章发布后的一个月，BSC基金会在DoraHacks开发者平台HackerLink上运行了BSC生态第一轮[二次方资助](https://hackerlink.io/grant)‌，并在其后的15天中收到了全球超过60个开发者团队提交的项目。

在《二次方投票和二次方资助》中，我介绍了Vitalik的博客《Quadratic Payments》所提到的三个问题：身份伪造攻击（Identity Bribery）、勾结（Collusion）、理性忽视问题（Rational Ignorance）。这三个问题其实不限于二次方投票，而是链上治理机制所遇到的通用问题。因此，这些问题的解决方案不仅可以使得二次方投票更规模化和更安全，还可以惠及更多链上治理的机制。

这篇文章的目标是为设计一种“非合作二次方投票”，或“抗勾结二次方投票”的机制做准备。在这种场景下，投票者无法相互之间合作，因此就没有了勾结的可能性。这种机制一个基础框架是，Vitalik Buterin在Ethresear上发表的文章《Minimal anti-collusion infrastructure》\[1\] （MACI）。因此，我们先解释MACI的机制，从而为进一步探讨如何使用MACI改进二次方投票，消除勾结（Collusion）的可能性。

MACI: Minimal Anti-Collusion Infrastructure
-------------------------------------------

MACI是“最小化抗勾结框架”。背景材料参考Vitalik Buterin 的博客[https://ethresear.ch/t/minimal-anti-collusion-infrastructure/5413](https://ethresear.ch/t/minimal-anti-collusion-infrastructure/5413) ，以及《On Collusion》 [https://vitalik.ca/general/2019/04/03/collusion.html](https://vitalik.ca/general/2019/04/03/collusion.html)

很多的链上治理应用需要“抗勾结”这个特性，但同时又需要区块链对交易执行以及抗审查、保护隐私的保证。投票是有这种需求的一个重要场景，因为很明显在投票中，抗勾结是必须的，同时对执行结果的正确性的要求是很高的，需要保护计票过程，最后，还需要防止对投票者的审查。

设置
--

假设有一个智能合约\\(R\\)，包含一个公钥的列表 \\(K\_1 ... K\_n\\), 以及一些必要的函数，可以把这些公钥注册到智能合约中。另外，只有符合以下两个条件验证身份的参与者的公钥可以进入到R中：

账户属于一个“合法”的参与者（一个独立的人，某个社区的成员，比如拥有某个国家的国籍、在一个论坛上有足够高的声誉、持有不少于某个数量的Token…）

账户持有人个人控制密钥（例如，如果需要的话，可以打印出来以证明）

每一个用户需要stake一笔钱: 如果任何人泄漏了自己的私钥，那么得到私钥的人可以直接取走这笔钱，从而这个账户就会从列表中被移除。这个机制抑制了任何人把私钥交给别人。

另外，假设有一个操作员(\\(operator\\))，他有一个私钥\\(k\_\\omega\\), 和一个对应的公钥\\(K\_\\omega\\).

最后，假设有一个机制 \\(M\\), 它是一个函数 \\(action^n \\rightarrow Outputs\\), 其中，函数的输入是\\(n\\)个参与者的行为，输出是这个函数定义的某种输出结果。例如，一个简单的投票机制是一个函数，根据输入的值，输出出现次数最多的那个值。

执行
--

在起始时间\\(T\_{start}\\)，\\(operator\\)开始一个其实状态\\(S\_{start} = {i: (key=K\_i, action = \\phi)}, i \\in 1...n\\).

在起始时间\\(T\_{start}\\)和结束时间\\(T\_{end}\\)之间，任何注册的参与者可以向R发送消息，消息用参与者自己的私钥\\(k\\)加密。有两种消息：

约定行为: 例如投票。参与者需要发送加密过的消息 \\(enc(msg = (i, sign(msg = action, key = k\_i)), pubkey = K\_\\omega)\\), 其中\\(k\_i\\)是这个参与者当前的私钥，\\(i\\)是参与者在\\(R\\)中的id

更新密钥: 参与者需要发送加密过的消息\\(enc(msg = (i, sign(msg = NewK\_i, key = k\_i)), pubkey = K\_\\omega)\\), 其中\\(NewK\_i\\)是参与者要变更的公钥, \\(k\_i\\)是这个参与者当前的私钥

这时，操作员的工作是按照消息上链的先后顺序处理每一个消息。具体的处理过程：

使用操作员私钥解密消息。如果解密失败，或者解密对应的信息无法解码成为以上的两类信息，则直接跳过这条信息

**使用\\(state\[i\].key\\)验证消息的签名**

如果解码后的消息是约定的行为(\\(action\\))，那么设置\\(state\[i\] = action\\), 如果解码后的消息是一个新的公钥，那么设置\\(state\[i\].key = NewK\_i\\)

在\\(T\_{end}\\)之后，操作员必须公布输出状态 \\(M(state\[1\].action, ... , state\[n\].action)\\), 同时给出一个ZK-SNARK，证明这个输出是正确的结果。

为什么这个机制是抗勾结的
------------

假设一个参与者想要证明他做过什么，例如做过\\(action\\) \\(A\\)，他可以引用一个链上的交易\\(enc(msg = (i, sign(msg = A, key = k\_i)), pubkey = K\_\\omega)\\)，并且提供一个零知识证明，验证这笔交易的确是包含\\(A\\)的加密信息。但是，他无法证明他没有发出别的交易，例如他可能发出过一笔更早的交易，把公钥换成了一个新的\\(NewK\_i\\)，因此前面的证明也就变得没有意义了，因为如果他更换过密钥的话，他可能已经做了别的动作。

参与者还可能把私钥给其他人，但是这样做的话那个人拿到私钥后就可以立即试图修改密钥。这样的话 1) 有50%的成功率，2) 会导致拿到密钥的人直接拿走之前stake的存款。

MACI未解决的问题
----------

接收方在可信硬件环境中，或者接收方在可信多签的情况下，卖出私钥

原有的私钥在一个可信的硬件环境中的攻击，这个环境可以防止私钥变更为任何攻击者们不事先知道的私钥

第一种情况，可以通过特别设计的复杂签名机制，而这种设计对可信硬件和多签不友好。不过这种设计需要确保验证函数对ZKP友好。

第二种情况可以通过“面对面零知识证明”解决，例如，参与者可以把私钥拆解为\\(x + y = k\_i\\)，公布\\(X = x\*G\\) 和 \\(Y = y\*G\\), 并且给验证者展示两个信封，分别包含\\(x\\)和\\(y\\); 验证者打开一个，检查公布的\\(Y\\)是正确的，然后检查\\(X + Y = K\_i\\)。

非合作二次方投票
--------

这种机制可以用来改进包括投票在内的多种链上治理机制。在二次方资助中，当资金池规模非常大的时候，或者当二次方资助被用于更大的场景时(例如大选、国会审批预算等场景)，勾结就会成为一个必须被解决的问题。因此，设计一个抗勾结二次方投票(Anti-collusion quadratic funding)机制，可以规模化二次方资助。

转自_作者：Eric Zhang_

---

*Originally published on [PAUL](https://paragraph.com/@paul-4/maci)*
