1. 引言
相关代码见:
- https://github.com/zkvalidator/mina-vrf-rs(Rust)
- https://github.com/MinaProtocol/mina/blob/develop/src/lib/vrf_evaluator/vrf_evaluator.ml(OCaml)
https://github.com/zkvalidator/mina-vrf-rs为ZKValidtor(Mian的产块候选人之一)贡献给Mina社区的工具:
- 委托者:可用于评估产块者的表现,即判断该产块者是否produced all the blocks they could win。
- 产块者:可用于预测其未来将赢得的区块,以改进其性能。也可用于分析为何赢得某区块的产块者未能正常产块。
同一slot可能会有多个合格的产块者,若对同一slot生成了2个或更多个区块,则会引起short fork,仅有一个区块会被选中(此时,winner为基于每个产块者的VRF ouput随机选出)。当处于catchup模式时,也可能会产块,不过该区块将迅速被孤立,因为其不是基于正确的区块高度构建的。
Mina采用类似Cardano Ouroboros共识的Ouroboros Samisika共识,通过VRF(Verifiable Random Function)来选产块者。选产块者的过程可看成是每个产块者为每个slot独立运行该VRF函数的彩票抽奖过程。若VRF输出结果大于该产块者质押的某个比例阈值,则该产块者有机会为特定slot产块。
VRF的输入为:
- 1)a random seed:为前一epoch的前2/3产块者的VRF结果的哈希值。
- 2)产块者的私钥
- 3)当前的质押分布
VRF结果是确定性的。该输出结果本身也将成为下一epoch的randomness。
只有产块者本人知道其赢得了哪些slot,这有助于保护安全,避免adversary对特定slot的已知产块者进行攻击,如denial of service或targeted attack。
这个过程的一个问题是,要可靠地推断出staking pool的性能是很有挑战性的。当前的方法为观察各Validtor的reward分布,不过这适合长期平均来看。更合适的方案是比较 赢得的slot数 与 在经典链上实际产的区块数。
在Mina的1.2.0+新版本中,增加了一个新工具Vrf evaluation commands:
- 使产块者可生成witnesses to attest to the slots they won for an epoch。
这些witnesses可独立验证,可用于evaluate a delegate’s performance reliably。
产块者也可使用工具在epoch到来之前确定其能赢得的所有slots。
2. Mina VRF commands
通过mina advanced vrf
来生成和验证VRF witnesses,可单个或批量:
- generate-witness
- batch-check-witness
- batch-generate-witness
$ opam switch import src/opam.export
$ scripts/pin-external-packages.sh
$ dune build src/app/cli/src/mina.exe
$ dune exe src/app/cli/src/mina.exe -- advanced vrf
Commands for vrf evaluations
mina.exe advanced vrf SUBCOMMAND
=== subcommands ===
batch-check-witness Check a batch of vrf evaluation witnesses read on
stdin. Outputs the verified vrf evaluations (or no vrf
output if the witness is invalid), and whether the vrf
output satisfies the threshold values if given. The
threshold should be included in the JSON for each vrf
as the 'vrfThreshold' field, of format
{delegatedStake: 1000, totalStake: 1000000000}. The
threshold is not checked against a ledger; this should
be done manually to confirm whether threshold_met in
the output corresponds to an actual won block.
batch-generate-witness Generate a batch of vrf evaluation witnesses from
{"globalSlot": _, "epochSeed": _, "delegatorIndex": _}
JSON message objects read on stdin
generate-witness Generate a vrf evaluation witness. This may be used to
calculate whether a given private key will win a given
slot (by checking threshold_met = true in the JSON
output), or to generate a witness that a 3rd party can
use to verify a vrf evaluation.
help explain a given subcommand (perhaps recursively)
missing subcommand for command mina.exe advanced vrf
此外,还有2个GraphQL端口用于生成和验证少量的witnesses,但是受限于性能,不适合用于评估很多slots和delegators:【Mina-VRF-rs主要使用者2个接口,封装了https://github.com/zkvalidator/mina-graphql-rs。】
- checkVrf
- evaluateVrf
2.1 生成VRF——evaluateVrf
生成VRF——evaluateVrf
的输入有:
- 1)message:对应为:
- 1.1)globalSlot:非空,为uint32。
- 1.2)epochSeed:非空,string。为base58check格式。会进行
of_base58_check_exn
校验。 - 1.3)delegatorIndex:为delegator账号在staking ledger中的位置。
- 2)publicKey:为delegator账号对应的压缩公钥。为base58check格式。会进行
Public_key.Compressed.of_base58_check
校验。 - 3)vrfThreshold:对应为:
- 3.1)delegatedStake:非空,为uint64。为该delegator账号在当前epoch的staking ledger中的质押金额。
- 3.2)totalStake:非空,为uint64。为当前epoch的staking ledger中所有账号质押的总金额。
evaluateVrf
生成VRF的基本流程为:
- 1)
find_identity
:查找publicKey是否为unlocked,若不是unlocked则直接报错返回;若为unlocked,则获得相应的私钥sk。 - 2)constraint_constants:获取Mina链预计算的一些常量:
type t =
{ runtime_config : Runtime_config.t
; constraint_constants : Genesis_constants.Constraint_constants.t
; genesis_constants : Genesis_constants.t
; proof_level : Genesis_constants.Proof_level.t
; genesis_ledger : Genesis_ledger.Packed.t
; genesis_epoch_data : Consensus.Genesis_epoch_data.t
; consensus_constants : Consensus.Constants.t
; protocol_state_with_hashes :
Protocol_state.value State_hash.With_state_hashes.t
; constraint_system_digests : (string * Md5_lib.t) list Lazy.t
; proof_data : Proof_data.t option
}
- 3)
of_message_and_sk
:- 3.1)
create
:- 3.1.1)计算公钥:pk=sk*G;(其中 G G G为generator)
- 3.1.2)计算message hash:H=Hash_To_Group(“CodaVrfMessagePrefix”, message);(H为曲线上的point)
- 3.1.3)选择随机数r,计算g1=rG,g2=rH;
- 3.1.4)
hash_for_proof
:c=Hash_For_Proof(“MinaVrfEvaluationPrefix”, message, pk, g1,g2);(c为scalar field域值) - 3.1.5)计算s=r+kc,令t=(c,s),返回standalone_eval=(H_s,sk,t)。其中H_s=skH。
- 3.2)context=(message, pk_affine)
- 3.3)
of_evaluation_and_context
:最终生成的vrf proof为(message, pk,c,s,H_s)。其中H_s=sk*H。
- 3.1)
- 4)计算vrf结果
compute_vrf
:- 4.1)有standalone_eval=(c,s,H_s),context=(message, pk)。
- 4.2)
verified_output
:- 4.2.1)计算H=Hash_To_Group(“CodaVrfMessagePrefix”, message);(H为曲线上的point)
- 4.2.2)比较Hash_For_Proof(“MinaVrfEvaluationPrefix”, message, pk, (sG-cpk),(sH-cH_s))与c是否相等,若相等则返回Some()
- 4.2.3)计算vrf=Hash("CodaVrfOutputPrefix’, message, H_s)
3. 确定epoch内赢得的所有slots
产块者常使用VRF command来提前知道当前和下一epoch内赢得的所有slots。
batch-generate-witness
和batch-check-witness
的输入有:
- Global slots to evaluate
- Epoch seed for the epoch
- The total stake of the epoch staking ledger
- Account indexes for all delegators
- The stake of each delegator, in the staking ledger
这些输入可手工从一个Mina节点中提取,也可使用https://github.com/zkvalidator/mina-vrf-rs这个工具来收集和格式化这些输入。
运行Mina-VRF-rs,需要:
- 安装Rust;
- 下载https://github.com/zkvalidator/mina-vrf-rs代码;
- 一个至少运行1.2.0版本的节点,其可访问GraphQL。
接下来,将使用Mina-VRF-rs来决定MinaExplorer pool在epoch 0 赢得的所有slots。
参考资料
[1] 2021年7月博客 Evaluating a Mina staking pool’s performance
[2] ZKValidator – Block Producer Analysis
[3] Mina术语表
[4] Mina FAQ
附录1. Mina系列博客
Mina系列博客有:
- Mina概览
- Mina的支付流程
- Mina的zkApp
- Mina中的Pasta(Pallas和Vesta)曲线
- Mina中的Schnorr signature
- Mina中的Pickles SNARK
- Mina中的Kimchi SNARK
- Mina Kimchi SNARK 代码解析
- Mina Berkeley QANet测试网zkApp初体验
- Mina中的Poseidon hash
- Mina中的多项式承诺方案
- Recursive SNARKs总览
- Mina技术白皮书
- Mina代码解析
- Mina中的Snark Worker
- Mina中的Scan State
附录2. Mina中的常见术语
- Transition:等同于block区块。
- Transition Frontier:为本地data store中包含的网络中的最新 k k k个区块。为rose tree-type数据结构,该tree中的每个节点可能有多个children,即分叉。该tree中的每个节点都可称为breadcrumb。
- Root (of Transition Frontier):The root of the transition frontier is the block k blocks from the best tip. The root is obtained from peers during bootstrap. Once a new best tip is seen, the root is moved, so only k blocks are persisted. The root is the point where the block has been finalized due to consensus.【即固化点】
- breadcrumb:为Transition Frontier的一个节点。每个breadcrumb中包含了:
- external transition:也是a block,由另一产块者生成并广播到本节点的区块。
- staged ledger
- pending coinbase
- best tip:当前已知的具有最高chain strength的最新区块。
- internal transition:即由产块者在本地生成的区块,该生成的区块会applied locally,并在广播到其它节点之前添加到transition frontier中。
- chain strength:由于Mina中没有full history available,新加入的节点无法sync from genesis by applying all prior transitions。为了帮助节点判断最强链,a minimum chain density is stored for a sliding window of time。为此,诚实的节点会选择具有higher minimum density或chain strength的链。
- archive node:Mina节点默认是succinct的,即意味着不需要维护关于网络、区块或交易的历史信息。archive node会存储历史chain data to a persistent data source so it can later be retrieved。
- full node:Mina中每个节点都是全节点,都可receive and verify zk-SNARKs。
- delegating:质押mina要求节点在线,某些节点可将其mina委托给运行质押服务的其它节点,该过程称为委托质押,通常服务提供商或质押池运营商会收取一定的费用来运行该服务,一旦委托人被选中为产块者,该费用将从中扣除。
- Epoch:Mina主网每个epoch对应7140个slot,每个slot约3分钟。
- Kademlia:为A distributed hash table (DHT) for decentralized peer-to-peer networks. Mina uses Kademlia for peer discovery so that nodes can find neighbor nodes to share information about the network state.
- nonce:为交易中的一个递增值,用于防止交易重放。Transactions are always included in blocks in the sequential order of the nonce.
- snarked ledger:为仅包含具有关联proof的ledger。一旦有proof从scan state中释放,就会更新snarked ledger。该proof可证明由之前的产块者添加到该tree的所有交易的真实性。
- staged ledger:为当前的account state,包含了a pending accounts ledger以及a pending queue of un-SNARKed transactions known as the scan state。
- staking ledger:用于决定某slot产块者的ledger,赢得该slot的概率与质押的金额呈正比。当前epoch的stake distribution为上上epoch(当前epoch-2)的最后一个区块的snarked ledger。
staking ledger的修改是在每个epoch的开始阶段进行更新。当前epoch的staking ledger为the snarked ledger of the last block ofcurrent_epoch - 2
。若你在epoch 4的开始阶段收到了资金,直到epoch 6才会生效。发送delegation transactions也类似,任何委托仅在staking ledger更新后才会生效。 - staking pool:由staking pool owner运行的委托资金池。其它节点可选择将资金委托给质押池,从而避免一直在线。
- time-locked account:是指账号具有一定数量的非既得利益token,直到满足某特定条件(如区块数)后才能使用。