引言
在为我自己的区块链项目进行研究时,我发现以太坊基金会一直在调查用于单一秘密领导者选举(SSLE)的具有DDH构造的可验证随机函数(VRF)。
在我参与这个论坛的期间,我发现人们普遍缺乏对DDH构造的认识和理解,这是很遗憾的,因为人们倾向于使用不必要复杂的涉及zk-S{N,T}ARK的设置。不要误解我,我是zk-S{N,T}ARK的忠实粉丝,但它们确实非常复杂,与椭圆曲线上的几个点的加法和乘法相比,显得过于复杂。
所以我想开始一个线程,为感兴趣的人提供一个快速介绍。这个入门指南基于RFC-9381中描述的构造,也是我个人项目的笔记。
像往常一样,如果有什么不对,请告诉我。未来的读者可能会对此做出关键的安全依赖。
常见问题解答
1. 什么是VRF?
可验证随机函数本质上是一个带有零知识正确性证明的哈希。
2. 你是指带有zk-SNARK的哈希吗?
不完全是。具有DDH构造的VRF的零知识证明比完整的zk-SNARK更轻量,基于更简单的数学原理。它与Schnorr签名大致相似。
[翻译已省略剩余部分,但遵循了相同的翻译原则]签名算法
- 哈希到曲线:
H = 哈希到曲线(插槽编号 || 纪元随机数)
H=HashToCurve(slot_number||epoch_randomness)
- 计算输出点:
\Gamma = x \cdot H
Γ=x⋅H
- 生成证明点:
U = n \cdot G \\V = n \cdot H
U=n⋅GV=n⋅H
- 计算挑战标量:
c = 哈希到标量(P, H, U, V)
c=HashToScalar(P,H,U,V)
- 计算Schnorr类签名标量:
s = n + c \cdot x \mod p
s=n+c⋅xmodp
\pi = (c, s)π=(c,s)。输出 (\Gamma, \pi)(Γ,π)。
验证算法
- 哈希到曲线:
H = 哈希到曲线(插槽编号 || 纪元随机数)
H=HashToCurve(slot_number||epoch_randomness)
- 恢复证明点:
U' = s \cdot G - c \cdot P \\V' = s \cdot H - c \cdot \Gamma
U′=s⋅G−c⋅PV′=s⋅H−c⋅Γ
- 恢复挑战哈希:
c' = 哈希到标量(P, H, U, V)
c′=HashToScalar(P,H,U,V)
当且仅当 c' = cc′=c时,证明有效。
在去中心化应用中的使用
如果我们将可验证随机函数(VRF)暴露给以太坊虚拟机(EVM),它是否可以替代像 ChainLink VRF 这样的外部预言机? 这个可验证随机函数可以使用去中心化应用提供的任意消息作为种子,并由区块构建者的私钥证明,但证明必须由所有区块验证者验证。
Solidity签名示例:
/// 返回使用提供的种子生成的均匀分布的256位字。/// 通过使用区块验证的可验证随机函数安全地实现。function get_randomness(bytes seed) public view returns uint256;无论我们为去中心化应用选择什么样的随机性系统,它都需要抵抗:
- 预测 - 显而易见;
- 偏差 - 显而易见;
- 操纵 - 区块构建者不能通过多次尝试来获得去中心化应用中的有利结果;
- 审查 - 随机结果不能不断变化,从某个区块开始必须保持恒定,否则网络节点可能会审查随机性解析交易直到获得有利结果。
现在让我们比较以下方法:
- 使用前一个区块的哈希作为随机性来源 – 在所有方面都失败:区块构建者可以审查发送到去中心化应用的所有交易,直到出现有利的区块哈希,他们可以通过重新排序交易来调整区块哈希,然后在下一个区块向去中心化应用提交交易等。
- 使用当前区块的哈希 – 去中心化应用承诺一个区块并将在未来的交易中获取其哈希。仍然以多种方式失败,例如区块构建者可以在下一个区块中提交承诺交易和解决交易,但如果这两个区块没有产生有利的结果,他们可以尝试使用不同的分叉。
- 使用下一个区块的哈希 – 与上面相同的问题,只是需要额外的区块(可能仍在分叉上)。
- 使用区块N+10的哈希 – 去中心化应用承诺区块N,随机性将是区块N+10的哈希,当区块N是规范的。由于区块构建者可以通过重新排序区块N+10的交易进行多次尝试,因此在调整方面失败。
- 使用10个区块前的哈希作为种子的DDH基础可验证随机函数 – 仍然容易受到审查,因为"10个区块前的哈希"不断变化。
- 承诺区块N,然后在区块N+11使用上面定义的
get_random函数,以区块N+10的哈希作为种子 – 最后两个区块(N+10和N+11)可能仍在分叉上,因此区块构建者可以通过重新排序区块N+10的交易进行多次尝试。 - 承诺区块N,然后在区块N+20使用
get_random并以区块N+10的哈希作为种子 – 似乎通过了所有测试,并且与Chainlink的做法非常接近。可能有点慢,但它假设需要10个插槽才能使区块成为规范的,所以通过设置较低的阈值,我们可能有改进的空间。




