值得信赖的区块链资讯!
mina – 源代码导读(基础篇)
Mina是个有意思的项目。链上的区块数据永远“压缩”在22k。Mina是一种新的区块链形式,解决了一般链式区块链数据爆炸的问题。看别人的设计,是一种享受。看别人创造出一种新的思路,新事物,真心感叹,是一种美。很早就想看看Mina的设计,网络上的资料几乎都是一些简单的宣传资料,不够深入。这些资料不足以领略Mina的技术。
在查看Mina源代码之前,建议看看Mina的技术文档:
Mina项目是链下验证,链上计算的极致体现。在链上永远只存储最新的证明信息。一些显而易见的问题就出现在脑海中,Coda的共识机制是什么?链上的证明信息证明了什么?当出现新的区块的时候,如何证明新的区块的合法性?如何结合链上的证明,生成新的证明?带着问题看代码。
内容比较多,分成两篇文章。这篇是基础篇,讲述链的结构以及共识,后面会详细分析零知识证明技术在mina中的应用原理和相关细节。
本文中使用的Mina代码的最后一次提交信息如下:
commit ce31b9dfe5f8e148837b4bf2cd19de6f97da663b (HEAD -> develop, origin/develop, origin/HEAD)
Merge: 49ef908cd 7f46d759e
Author: Matthew Ryan <[email protected]>
Date: Tue Mar 9 01:20:24 2021 +0000
Merge pull request #8172 from MinaProtocol/compatible
Merge back to develop
Mina项目使用OCaml语言开发。对OCaml语言不熟悉的小伙伴,可以查看以下链接学习OCaml语言。
http://dev.realworldocaml.org/toc.html
https://ocaml.org/learn/tutorials/index.zh.html
01
Address (地址管理)
介绍账户管理之前简单介绍一下Tick/Tock。Tick/Tock是Pickles证明系统两条曲线的代号。Tick和Tock两条曲线的Fp和Fq是对称的。账户的创建基于Tick曲线。
私钥是在Tick的Scalar范围内的随机数。原始公钥是私钥对应的Tick曲线上的点。真实公钥是三者数据的base58编码结果:1/ 版本信息 2/ 原始公钥信息 3/ 原始公钥的checksum信息。具体的逻辑可以查看lib/cli_lib/commands.ml的generate_keypair函数。
02
Transaction(交易)
交易分为几种类型,比较容易理解:
-
User Command (常见交易)
-
User Command又分为两种:1/ 一种是普通交易 2/ 一种是snapp交易。
-
Payment(支付交易)
-
Stake_delegation(质押交易)
-
Create_new_token(创建新代币交易)
-
Create_token_account (创建代币对应账户)
-
Mint_tokens (代币转账)
-
普通交易:
-
snapp交易
-
Fee Transfer (交易费用转账交易)
-
Coinbase (铸币交易)
详细的逻辑可以查看lib/mina_base/transaction.ml中的定义。
交易签名采用的是schorr算法,详细请查看lib/signature_lib/schnorr.ml的sign函数。
03
Account (账户管理)
一个账户信息定义在lib/mina_base/account.ml,由如下信息组成:
-
基本信息
-
包括公钥信息,Nonce信息
-
权限信息(是否具有发送/接收权限,是否具有质押权限等等)
-
时效信息(是否有时效?释放的时间参数等等),具体查看lib/mina_base/account_timing.ml。
-
Token信息
-
包括Token编号,权限以及余额。Token编号从1开始 (defult token – mina)。
-
Receipt chain hash信息
-
所有交易的信息的hash信息
-
质押信息
-
质押账户的公钥信息等等
-
Snapp信息
如果一个账户发送了若干个交易,这些交易是t_1,t_2,… t_n。每个交易对应的hash值为p_1,p_2,… p_n。Receipt chain hash信息的计算方式如下:
简单的说,就是把历史交易信息的hash链起来,最后的hash记录在账户信息上。
04
Protocol State(世界状态)
mina的世界状态定义在lib/mina_state/protocol_state.ml。整个世界状态由四个状态组成:1/ genesis_state_hash(创世纪的状态)2/ blockchain_state (链的状态)3/consensus_state (共识状态)4/ constants(参数信息)。
module Poly = struct
[%%versioned
module Stable = struct
module V1 = struct
type ('state_hash, 'body) t =
{previous_state_hash: 'state_hash; body: 'body}
[@@deriving eq, ord, hash, sexp, yojson, hlist]
end
end]
end
module Body = struct
module Poly = struct
[%%versioned
module Stable = struct
module V1 = struct
type ('state_hash, 'blockchain_state, 'consensus_state, 'constants) t =
{ genesis_state_hash: 'state_hash
; blockchain_state: 'blockchain_state
; consensus_state: 'consensus_state
; constants: 'constants }
[@@deriving sexp, eq, compare, yojson, hash, version, hlist]
end
end]
end
为了链接上一个区块的状态,世界状态表示为之前一个区块的世界状态和当前世界状态的hash值。
genesis_state_hash比较容易理解,就是创世纪的世界状态。先重点看看block_chain_state,共识状态在共识部分再介绍。block_chain_state中除了genesis ledger状态外,还包括如下的两个状态:
Staged ledger状态
所有的账户信息先通过Poseidon Hash计算,并且形成Merkle树。树根就代表当前所有账户的状态。这个状态也称为"Staged ledger"。
Snarked ledger状态
除了构建Staged ledger,mina还需要对当前的所有账户信息进行证明。由于证明的计算性能比较慢,为了避免证明计算性能拖慢整个链的性能,mina设计了snarked ledger。所谓的snarked ledger,就是已经证明过的所有账户信息。
05
Scan State (Parallel Scan State)
交易对应的状态变化的证明生成过程,称为Scan State。Scan State由多棵Merkle树组成,每棵Merkle树证明若干个交易的状态变化。
两个变量决定了Merkle树的个数以及每棵Merkle树的结点个数。
-
transaction_capacity_log_2
-
work_delay
每棵Merkle树的结点个数为:
max_no_of_transactions = 2^{transaction_capacity_log_2}
总共的Merkle树的个数为:
max_number_of_trees = (transaction_capacity_log_2 + 1) * (work_delay + 1) + 1
work_delay表明有多少棵Merkle树可以作为“buffer”,在work_delay内,可以不提供交易的证明。也就是说,超过了work_delay的交易,必须在生成区块时包含需要的交易证明。如果不能在区块中提供需要的证明,则区块中也不能添加交易。也就是说,在这种情况下,出的是“空块“(空块没有区块奖励)。
每棵树的叶子结点是对单个交易的证明,这样的证明任务称为base。每棵树的中间结点是两个证明的证明,这样的证明任务称为merge(将多个证明合并)。Scan State的叶子结点(交易)的证明可以并行处理,所以也称为Parallel Scan State。Base/Merge定义在lib/transaction_snark/transaction_snark.ml。
注意的是,Scan State上的交易并没有区块的概念。区块确定交易的顺序后,Scan State只需要按照顺序进行相应的证明即可。
06
Transition(区块)
每三分钟出一个区块。区块时间分成:Epoch和Slot。一个Epoch分为7140个Slot。区块分为两种:一种是External Transition,外部区块(从网络同步)和另外一种是Internal Transition,内部区块(节点自己创建的区块)。这两种区块的定义在lib/mina_transition/external_transition.ml和lib/mina_transition/internal_transition.ml。
External Transition
module Stable = struct
module V1 = struct
type t =
{ protocol_state: Protocol_state.Value.Stable.V1.t
; protocol_state_proof: Proof.Stable.V1.t sexp_opaque
; staged_ledger_diff: Staged_ledger_diff.Stable.V1.t
; delta_transition_chain_proof:
State_hash.Stable.V1.t * State_body_hash.Stable.V1.t list
; current_protocol_version: Protocol_version.Stable.V1.t
; proposed_protocol_version_opt: Protocol_version.Stable.V1.t option
; mutable validation_callback: Validate_content.t }
[@@deriving sexp, fields]
External Transition主要包括两个重要信息:1/ protocol state以及相应的证明 2/ Transition中包含的交易信息(staged_ledger_diff)。其中的delta_transition_chain_proof是区块创建时的之前的区块状态转换信息。
Internal Transition
Internal Transition也需要包括区块中的交易信息(staged_ledger_diff)。除此之外,还包括:snark_transition(链的状态变化,包括链的状态和共识), ledger_proof(Snarked ledger的证明信息)和prover_state(共识相关的信息)。
module Stable = struct
[@@@no_toplevel_latest_type]
module V1 = struct
type t =
{ snark_transition: Snark_transition.Value.Stable.V1.t
; ledger_proof: Ledger_proof.Stable.V1.t option
; prover_state: Consensus.Data.Prover_state.Stable.V1.t
; staged_ledger_diff: Staged_ledger_diff.Stable.V1.t }
let to_latest = Fn.id
end
end]
Consensus.Data.Prover_state.Stable.V1.t定义在lib/consensus/stake_proof.ml:
[%%versioned
module Stable = struct
[@@@no_toplevel_latest_type]
module V1 = struct
type t =
{ delegator: Account.Index.Stable.V1.t
; delegator_pk: Public_key.Compressed.Stable.V1.t
; coinbase_receiver_pk: Public_key.Compressed.Stable.V1.t
; ledger: Sparse_ledger.Stable.V1.t
; producer_private_key: Private_key.Stable.V1.t
; producer_public_key: Public_key.Stable.V1.t }
let to_latest = Fn.id
end
end]
Prover_state包括了delegator的账户信息,区块生成者的账户信息以及coinbase的接受者的信息。
07
Transition Frontier Controller
Transition Frontier Controller是核心逻辑。Transition Frontier Controller维护了整个链的世界状态,包括了如下的模块:
Transition Handler – 区块的验证(Validator)和处理(Processor)
Ledger Catchup – 区块同步逻辑
Transition Frontier – 维护区块的“cache”,区块和区块之间的依赖关系以及确定最长链。
Query Handler – 区块查询
这些模块和模块之间通过“pipe”异步通讯。
breadcrumb
lib/transition_frontier/frontier_base/breadcrumb.ml
type t =
{ validated_transition: External_transition.Validated.t
; staged_ledger: Staged_ledger.t sexp_opaque
; just_emitted_a_proof: bool
; transition_receipt_time: Time.t option }
breadcrumb是一个“wrapper”,主要包括了验证过的transition信息,区块中的交易执行后的账本信息以及区块时间信息。最近的一些区块breadcrumb组织成树状结构(KTree)。树上的每个节点定义为(lib/transition_frontier/full_frontier/full_frontier.ml):
module Node = struct
type t =
{breadcrumb: Breadcrumb.t; successor_hashes: State_hash.t list; length: int}
每个节点由一个breadcrumb组成,同时记录了该breadcrumb后续的状态以及个数。
主链确定
当一个breadcrumb需要添加到Transition Frontier时,需要确认主链以及确定区块状态。对应的逻辑在lib/transition_frontier/full_frontier/full_frontier.ml的calculate_diffs函数中:
let diffs =
if
Consensus.Hooks.select
~constants:t.precomputed_values.consensus_constants
~existing:(Breadcrumb.consensus_state_with_hash current_best_tip)
~candidate:(Breadcrumb.consensus_state_with_hash breadcrumb)
~logger:
(Logger.extend t.logger
[ ( "selection_context"
, `String "comparing new breadcrumb to best tip" ) ])
= `Take
then Full.E.E (Best_tip_changed breadcrumb_hash) :: diffs
else diffs
Consensus.Hooks.select函数就是进行主链的确认,实现在lib/consensus/proof_of_stake.ml中:
let less_than_or_equal_when a b ~compare ~condition =
let c = compare a b in
c < 0 || (c = 0 && condition)
in
let candidate_hash_is_bigger =
Mina_base.State_hash.(candidate_hash > existing_hash)
in
let candidate_vrf_is_bigger =
let string_of_blake2 = Blake2.(Fn.compose to_raw_string digest_string) in
let compare_blake2 a b =
String.compare (string_of_blake2 a) (string_of_blake2 b)
in
less_than_or_equal_when existing.last_vrf_output
candidate.last_vrf_output ~compare:compare_blake2
~condition:candidate_hash_is_bigger
in
let blockchain_length_is_longer =
less_than_or_equal_when existing.blockchain_length
candidate.blockchain_length ~compare:Length.compare
~condition:candidate_vrf_is_bigger
in
let long_fork_chain_quality_is_better =
let max_slot =
Global_slot.max candidate.curr_global_slot existing.curr_global_slot
in
let virtual_min_window_density (s : Consensus_state.Value.t) =
if Global_slot.equal s.curr_global_slot max_slot then
s.min_window_density
else
Min_window_density.update_min_window_density ~incr_window:false
~constants ~prev_global_slot:s.curr_global_slot
~next_global_slot:max_slot
~prev_sub_window_densities:s.sub_window_densities
~prev_min_window_density:s.min_window_density
|> fst
in
less_than_or_equal_when
(virtual_min_window_density existing)
(virtual_min_window_density candidate)
~compare:Length.compare ~condition:blockchain_length_is_longer
in
let precondition_msg, choice_msg, should_take =
if is_short_range existing candidate ~constants then
( "most recent finalized checkpoints are equal"
, "candidate length is longer than existing length "
, blockchain_length_is_longer )
else
( "most recent finalized checkpoints are not equal"
, "candidate virtual min-length is longer than existing virtual \
min-length"
, long_fork_chain_quality_is_better )
in
主链的确定逻辑如下:
-
window density最大优先
-
区块长度最长优先
-
VRF的计算结果大者优先
-
State Hash大者优先
08
Consensus(共识算法)
Mina采用的是PoS共识算法,相关逻辑实现在src/lib/consensus/proof_of_stake.ml。针对每个质押账户计算VRF结果,如果VRF结果满足一定的条件,节点即可出块。
VRF计算
针对每个质押账户,结合质押账户的公钥信息/区块高度和节点的私钥信息,采用Poseidon算法生成VRF。
Hashtbl.iteri
( Snapshot.delegators epoch_snapshot public_key_compressed
|> Option.value ~default:(Core_kernel.Int.Table.create ()) )
~f:(fun ~key:delegator ~data:account ->
let vrf_result =
T.eval ~constraint_constants ~private_key
{global_slot; seed; delegator}
in
let eval ~constraint_constants ~private_key m =
let h = Message.hash_to_group ~constraint_constants m in
let u = Group.scale h private_key in
Output_hash.hash ~constraint_constants m u
VRF的计算方法如下:
共识判断
简单的说,如果VRF的结果“大于”节点质押占比,则该节点拥有出块权。
vrf_output / 2^256 <= c * (1 – (1 – f)^(amount / total_stake))
总结:
Mina链上的区块数据永远“压缩”在22k。Mina是一种新的区块链形式,解决了一般链式区块链数据爆炸的问题。Mina采用PoS的共识机制,“最长/最重”链确认为主链。为了压缩链上的数据,Mina世界状态包括证明(Snarked)和非证明(Staged)的状态。非证明的状态通过链下的零知识证明的计算生成证明,证明证明状态正确。
比推快讯
更多 >>- 数据:过去 24 小时全网爆仓 4.18 亿美元,多单爆仓 3.26 亿美元,空单爆仓 9,212.93 万美元
- 美国财长:50 天的物价上涨可以换来 50 年伊朗无核
- SIREN 控盘者归集总供应量 66.5%代币,价值 10.4 亿美元
- 伊朗提出 4 项措施回应特朗普威胁
- 0xSun:AI 行业热度领先但 Crypto 仍具价值分配优势
- Abraxas Capital 开始平仓其黄金空单获利了结,盈利约为 267 万美元
- 伊朗希望将霍尔木兹变现,并称特朗普若不接受等同于政治自杀
- 某巨鲸重仓做空 BTC 并开多原油,账户浮盈超 660 万美元
- Michael Saylor 再次发布比特币 Tracker 信息,下周或将披露增持数据
- SIREN 上涨突破 2 USDT,24H 涨幅 131%
- 数据:过去 1 小时 Binance 净流出 3,460.54 万 USDT
- SIREN 24 小时暴涨 152%,控盘地址集群浮盈已超 9.5 亿美元
- Ju.com 第 9 期 Meme 打新项目 APEACE 上线涨幅超 370 亿倍,第 10 期 HAJIME 3 月 23 日 16:00 开启认购
- USR 现已回升至 0.577 USDT
- 博雅互动拟斥资不超过 7000 万美元购买加密货币
- 伊朗媒体称伊官员提出停战六项条件
- 以总理称将直接打击伊朗伊斯兰革命卫队领导人
- 中国国家互联网应急中心等发布 OpenClaw 安全使用实践指南
- 伊朗议长回应特朗普开放霍尔木兹海峡的最后通牒
- 蔡崇信:发展 AI 终极目标并非仅研发前沿模型,而是推动 AI 应用普及
- 黑客伪造 Google Play 商店页面,针对巴西用户实施加密货币挖矿与钱包劫持攻击
- 数据:若 ETH 突破 2,185 美元,主流 CEX 累计空单清算强度将达 8.83 亿美元
- 伊朗议会议长卡利巴夫:若伊朗发电厂和基础设施遭到攻击,国际油价将在很长一段时期内居高不下
- 某巨鲸近 1 月增持 8,662 枚 ETH,价值 1805 万美元
- 某巨鲸向币安转入 5000 万枚 SKY,盈利 272 万美元
- 数据:监测到 5 亿 USDT 转出 Okx
- Fluid:USR 市场已暂停交易,将全额赔偿潜在用户损失
- 印度加密平台 CoinDCX 两名联创被当地警方传唤
- Venus 与 Resolv 攻击者今日共计为 ETH 提供价值 2856 万美元买单
- 伊朗武装部队称已从防御转为进攻
- 数据:6499.99 万枚 FF 从匿名地址转入 BitGo,价值约 460 万美元
- Resolv 攻击者剩余 3674 万枚 USR,价值降至 204 万美元
- Bithumb 正推动现任 CEO 李在元连任,以维持运营连续性和稳定性
- Stani.eth:Aave 对 Resolv USR 无风险敞口,对协议影响为零
- Euler Labs:获悉 USR 攻击事件并紧急禁用 RLP 抵押品功能
- Resolv 攻击者目前已买入 11422 枚 ETH,价值 2366 万美元
- Strategy 比特币持仓目前浮亏 8.8%,约为 50.8 亿美元
- 美法院驳回 Sam Altman 妹妹对其提起的性虐待指控
- 数据:中国 AI 大模型周调用量达 4.69 万亿 Token,连续第二周超越美国
- 受 Resolv 遭攻击影响,USR 严重脱锚跌至 0.29 美元、RESOLV 24 小时跌超 10%
- Lido 回应 Resolv 攻击事件影响,用户暂无需采取任何行动
- 分析:能源危机挤压比特币挖矿利润,若矿工难以承压或引发新一轮 BTC 抛售
- 伊朗表示允许非敌方船只通过霍尔木兹海峡
- Resolv Labs:抵押资产池目前仍保持充足,未发生底层资产损失
- Ju.com 狂欢继续:Meme 第二轮打新将于 3 月 28 日开启
- 分析:特朗普对伊朗发出“48 小时通牒”引发避险情绪,主流加密资产普跌
- Vitalik 称赞 Qwen:不到 3 分钟解析 Willans 公式
- 潘功胜:将稳步推动金融业的高水平开放
- 香港发生亿元黄金劫案,警方拘 5 人找回 73 公斤金条
- Twitter 首条推文发布 20 周年,其 NFT 曾售出超 291 万美元高价
比推专栏
更多 >>观点
比推热门文章
- 数据:过去 24 小时全网爆仓 4.18 亿美元,多单爆仓 3.26 亿美元,空单爆仓 9,212.93 万美元
- 美国财长:50 天的物价上涨可以换来 50 年伊朗无核
- SIREN 控盘者归集总供应量 66.5%代币,价值 10.4 亿美元
- 伊朗提出 4 项措施回应特朗普威胁
- 0xSun:AI 行业热度领先但 Crypto 仍具价值分配优势
- Abraxas Capital 开始平仓其黄金空单获利了结,盈利约为 267 万美元
- 伊朗希望将霍尔木兹变现,并称特朗普若不接受等同于政治自杀
- 某巨鲸重仓做空 BTC 并开多原油,账户浮盈超 660 万美元
- Michael Saylor 再次发布比特币 Tracker 信息,下周或将披露增持数据
- SIREN 上涨突破 2 USDT,24H 涨幅 131%
比推 APP



