前序博客见:
Mina中的Scan State为一种数据结构,用于解耦transaction SNARKs的生成,可由Snark Worker而不需由产块者来生成。
由于产块者不再需要生成transaction SNARKs,使得不论交易吞吐量如何,可使block production time保持为常量。此外,scan state数据结构支持并行化生成transaction SNARK proof,可由多个竞争的Snark Workers来完成。
scan state由 a forest of full-binary trees组成,其中这些tree的每个节点都为需要snark worker需要完成的job。该scan state会定期返回a single proof from the top of a tree that attests to the correctness of all transactions at the base of the tree。
产块者在其生成的blockchain SNARK中包含发出的ledger proof,证明链的当前状态有效,并证明snarked ledger中包含的所有交易的有效性。
因此,无论交易吞吐量如何,块时间都可能保持不变,scan state能够调整以匹配所需的交易吞吐量。
注意:在稳定状态下,当所有slot都已填满,并且所有必需的证明都已完成时,每个区块都会发出ledger proof。
Mina主网scan_state配置信息:
[%%define scan_state_with_tps_goal true]
(* 0.2TPS * 10 *)
[%%define scan_state_tps_goal_x10 2]
[%%define scan_state_work_delay 2]
(** All the proofs before the last [work_delay] blocks must be
completed to add transactions. [work_delay] is the minimum number
of blocks and will increase if the throughput is less.
- If [work_delay = 0], all the work that was added to the scan
state in the previous block is expected to be completed and
included in the current block if any transactions/coinbase are to
be included.
- [work_delay >= 1] means that there's at least two block times for
completing the proofs.
*)
[%%inject "work_delay", scan_state_work_delay] (* 为2 *)
[%%inject "block_window_duration_ms", block_window_duration] (* 180000,即3分钟 *)
[%%if scan_state_with_tps_goal]
[%%inject "tps_goal_x10", scan_state_tps_goal_x10] (*为2*)
let max_coinbases = 2
(* block_window_duration is in milliseconds, so divide by 1000 divide
by 10 again because we have tps * 10
*)
let max_user_commands_per_block =
tps_goal_x10 * block_window_duration_ms / (1000 * 10) (*为36,即每个区块内最多有36笔用户交易*)
(** Log of the capacity of transactions per transition.
- 1 will only work if we don't have prover fees.
- 2 will work with prover fees, but not if we want a transaction
included in every block.
- At least 3 ensures a transaction per block and the staged-ledger
unit tests pass.
*)
let transaction_capacity_log_2 =
1
+ Core_kernel.Int.ceil_log2 (max_user_commands_per_block + max_coinbases) (* transaction_capacity_log_2值为7 *)
scan state主要有以下参数:【parallel scan state中最多有max_number_of_trees = (transaction_capacity_log_2 + 1) * (work_delay + 1) + 1
(为24)棵树,每棵树有max_no_of_transactions = 2^{transaction_capacity_log_2}
(为128)个叶子节点。】
max_no_of_transactions = 2^{transaction_capacity_log_2}
(为128)。【scan state中单棵树的叶子树=max_base_jobs=2^{transaction_capacity_log_2}=128。】max_number_of_trees = (transaction_capacity_log_2 + 1) * (work_delay + 1) + 1
(为24)。pending_coinbase_depth
为log_2{max_number_of_trees},实际为5。每个区块内允许包含的最大proof数量为:
max_number_of_proofs = 2^{transaction_capacity_log_2 + 1} - 1
(为127)
以上这些对scan state的约束可保证,每个区块仅能释放一个proof,以及the merge node that is to be updated after adding proofs corresponding to its children is always empty。
当确定了最大交易数,就可动态调整交易吞吐量。scan state可处理无上限的交易吞吐量,代价是logarithmically增加transaction proof latency。
【
Mina一个区块内:
2^{transaction_capacity_log_2}
(为128)笔交易。2^{transaction_capacity_log_2}
(为128)个base job。2^{transaction_capacity_log_2 + 1} - 1
(为127)。产块者在构建区块时可包含scan state中定义的最大交易数。在包含交易时,可选择任意可用的交易手续费然后给自己支付a coinbase reward。产块者所增加的每笔交易都被转换为new base jobs,并添加到scan state中。
每增加一笔交易,产块者必须包含等额数量的completed snark work that corresponds to a sequence of jobs that already exist in the scan state。这些completed jobs,当添加到scan state时,create new merge jobs except when it is for the root node, in which case the proof is simply returned as a result。
产块者并不自己完成snark work,而是根据snark pool中的竞价从任意snark workers中购买completed work。
假设scan state的参数为:max_no_of_transactions = 4, work_delay = 1
,则意味着 there can be a maximum amount of work to complete equal to 7 and a maximum number of 7 trees。
可使用如下命令来查看scan state的内容:
mina advanced snark-job-list
基本流程为:【详细也可参看Scan State Refactoring】
【B
表示base job,M
表示merge job,后面的数字表示添加到scan state 的顺序。】
【橙色:表示待由Snark Workers待完成的pending work;
绿色:表示已完成的work,Snark Workers会将已完成的work提交到snark pool中。可能会有多个Snark Worker完成同一work,但是,产块者仅可能购买snark pool中手续费最低的那个。】
【Snark work is bundled into a work package typically containing two workIds, with the exception of the final root proof of a tree. Prorated work for a transaction is two proofs, so this ensures the equality of transactions included and snark work to be purchased.】
新添加到scan state中的job是Snark Workers待完成pending job。Snark Workers完成所需的transaction SNARKs,并为其所完成的work标价。当节点收到并对该completed work验证通过且标价最低后,节点会将该completed work添加到其本地的snark pool中,
【当有多个Snark Workers完成了同一work时,仅有手续费最低的将包含在snark pool中。】
当前的snark pool可通过GraphQL或命令行来查看:
mina advanced snark-pool
当产块者在区块内包含completed proofs来offset any transactions they add时,产块者需从snark pool中购买相应的work。如,仍然继续第4节中的例子,以新区块12为例,若产块者需在Block 12中添加3笔交易,包含a coinbase、a user payment 以及 a fee transfer to the snark worker,产块者需要购买3个completed snark work,因为每个snark work包含2个workIds,因此对应6个proof(1个B9 proof、3个B10 proof和1个M9 Proof以及一个M10 proof)。
在区块生成期间,snark pool可能包括completed work,以及所需job的最佳出价(示例中分别为0.025、0.165、0.1和0.5)。
产块者在选择交易之前,将考虑available work的价格。产块者将添加的第一笔交易为the coinbase transaction(对应有coinbase reward)。若交易手续费无法覆盖包含其所需的snark work fee,则产块者不会将该交易添加到其区块内。除非有利可图,否则产块者将不会购买work。
当需要时无相应的completed snark work可购买时,相应的交易也不会添加到区块内。从而可能会导致empty block,当然也可能是没有交易待添加,也就对产块者没有激励。
[1] Scan State
Mina系列博客有: