Mina中的区块证明
1. 引言
Mina的Pickles支持2种类型的tag:
- Side_loaded
- Compiled
type ('var, 'value, 'n1, 'n2) t ={ kind : kind; id : ('var, 'value, 'n1, 'n2) tag }
type ('var, 'value, 'n1, 'n2) tag = ('var * 'value * 'n1 * 'n2) Type_equal.Id.ttype kind = Side_loaded | Compiled
tag.create()默认创建为的Compiled类型;而add_side_loaded()(Side_loaded.create(),在transaction_snark中会用到)创建的为Side_loaded类型。调用Pickles.compile或compile_promise函数时,若无self参数,则默认会创建Compiled类型:
let self =match self with| None ->{ Tag.id = Type_equal.Id.create ~name sexp_of_opaque; kind = Compiled }| Some self ->self
调试可为:
$ dune build src/lib/precomputed_values/gen_values/gen_values.exe
$ dune exe src/lib/precomputed_values/gen_values/gen_values.exe zydtest
各环节用时信息为:
$ export PICKLES_PROFILING="true" && dune exe src/lib/precomputed_values/gen_values/gen_values.exe -- zydtest
File "src/lib/pickles/pickles.ml", line 442, characters 16-23 -> File "src/lib/pickles/pickles.ml", line 453, characters 16-23: 13.828us
File "src/lib/pickles/pickles.ml", line 453, characters 16-23 -> File "src/lib/pickles/pickles.ml", line 468, characters 16-23: 49.114us
File "src/lib/pickles/pickles.ml", line 468, characters 16-23 -> File "src/lib/pickles/pickles.ml", line 498, characters 18-25: 5.007us
File "src/lib/pickles/pickles.ml", line 498, characters 18-25 -> File "src/lib/pickles/pickles.ml", line 505, characters 26-33: 2.861us
File "src/lib/pickles/pickles.ml", line 505, characters 26-33 -> File "src/lib/pickles/step_branch_data.ml", line 65, characters 14-21: 8.106us
File "src/lib/pickles/step_branch_data.ml", line 65, characters 14-21 -> File "src/lib/pickles/step_branch_data.ml", line 95, characters 14-21: 1.907us
File "src/lib/pickles/step_branch_data.ml", line 95, characters 14-21 -> File "src/lib/pickles/step_branch_data.ml", line 101, characters 14-21: 4.053us
File "src/lib/pickles/step_branch_data.ml", line 101, characters 14-21 -> File "src/lib/pickles/step_branch_data.ml", line 119, characters 14-21: 1.907us
File "src/lib/pickles/step_branch_data.ml", line 119, characters 14-21 -> File "src/lib/pickles/step_branch_data.ml", line 135, characters 14-21: 230.962ms
make step data: 231.001ms
File "src/lib/pickles/step_branch_data.ml", line 135, characters 14-21 -> File "src/lib/pickles/pickles.ml", line 514, characters 26-33: 45.061us
File "src/lib/pickles/pickles.ml", line 514, characters 26-33 -> File "src/lib/pickles/pickles.ml", line 505, characters 26-33: 2.623us
File "src/lib/pickles/pickles.ml", line 505, characters 26-33 -> File "src/lib/pickles/step_branch_data.ml", line 65, characters 14-21: 9.06us
File "src/lib/pickles/step_branch_data.ml", line 65, characters 14-21 -> File "src/lib/pickles/step_branch_data.ml", line 95, characters 14-21: 4.053us
File "src/lib/pickles/step_branch_data.ml", line 95, characters 14-21 -> File "src/lib/pickles/step_branch_data.ml", line 101, characters 14-21: 3.099us
File "src/lib/pickles/step_branch_data.ml", line 101, characters 14-21 -> File "src/lib/pickles/step_branch_data.ml", line 119, characters 14-21: 2.861us
dummy wrap sg: 893.5ms
File "src/lib/pickles/step_branch_data.ml", line 119, characters 14-21 -> File "src/lib/pickles/step_branch_data.ml", line 135, characters 14-21: 2.469s
make step data: 2.469s
File "src/lib/pickles/step_branch_data.ml", line 135, characters 14-21 -> File "src/lib/pickles/pickles.ml", line 514, characters 26-33: 36.001us
File "src/lib/pickles/pickles.ml", line 514, characters 26-33 -> File "src/lib/pickles/pickles.ml", line 505, characters 26-33: 3.815us
File "src/lib/pickles/pickles.ml", line 505, characters 26-33 -> File "src/lib/pickles/step_branch_data.ml", line 65, characters 14-21: 9.06us
File "src/lib/pickles/step_branch_data.ml", line 65, characters 14-21 -> File "src/lib/pickles/step_branch_data.ml", line 95, characters 14-21: 5.007us
File "src/lib/pickles/step_branch_data.ml", line 95, characters 14-21 -> File "src/lib/pickles/step_branch_data.ml", line 101, characters 14-21: 3.815us
File "src/lib/pickles/step_branch_data.ml", line 101, characters 14-21 -> File "src/lib/pickles/step_branch_data.ml", line 119, characters 14-21: 3.099us
File "src/lib/pickles/step_branch_data.ml", line 119, characters 14-21 -> File "src/lib/pickles/step_branch_data.ml", line 135, characters 14-21: 322.037ms
make step data: 322.075ms
File "src/lib/pickles/step_branch_data.ml", line 135, characters 14-21 -> File "src/lib/pickles/pickles.ml", line 514, characters 26-33: 41.008us
File "src/lib/pickles/pickles.ml", line 514, characters 26-33 -> File "src/lib/pickles/pickles.ml", line 505, characters 26-33: 3.099us
File "src/lib/pickles/pickles.ml", line 505, characters 26-33 -> File "src/lib/pickles/step_branch_data.ml", line 65, characters 14-21: 7.868us
File "src/lib/pickles/step_branch_data.ml", line 65, characters 14-21 -> File "src/lib/pickles/step_branch_data.ml", line 95, characters 14-21: 4.292us
File "src/lib/pickles/step_branch_data.ml", line 95, characters 14-21 -> File "src/lib/pickles/step_branch_data.ml", line 101, characters 14-21: 2.861us
File "src/lib/pickles/step_branch_data.ml", line 101, characters 14-21 -> File "src/lib/pickles/step_branch_data.ml", line 119, characters 14-21: 2.861us
File "src/lib/pickles/step_branch_data.ml", line 119, characters 14-21 -> File "src/lib/pickles/step_branch_data.ml", line 135, characters 14-21: 153.189ms
make step data: 153.231ms
File "src/lib/pickles/step_branch_data.ml", line 135, characters 14-21 -> File "src/lib/pickles/pickles.ml", line 514, characters 26-33: 47.207us
File "src/lib/pickles/pickles.ml", line 514, characters 26-33 -> File "src/lib/pickles/pickles.ml", line 505, characters 26-33: 4.768us
File "src/lib/pickles/pickles.ml", line 505, characters 26-33 -> File "src/lib/pickles/step_branch_data.ml", line 65, characters 14-21: 9.06us
File "src/lib/pickles/step_branch_data.ml", line 65, characters 14-21 -> File "src/lib/pickles/step_branch_data.ml", line 95, characters 14-21: 4.053us
File "src/lib/pickles/step_branch_data.ml", line 95, characters 14-21 -> File "src/lib/pickles/step_branch_data.ml", line 101, characters 14-21: 4.768us
File "src/lib/pickles/step_branch_data.ml", line 101, characters 14-21 -> File "src/lib/pickles/step_branch_data.ml", line 119, characters 14-21: 3.099us
File "src/lib/pickles/step_branch_data.ml", line 119, characters 14-21 -> File "src/lib/pickles/step_branch_data.ml", line 135, characters 14-21: 625.855ms
make step data: 625.899ms
File "src/lib/pickles/step_branch_data.ml", line 135, characters 14-21 -> File "src/lib/pickles/pickles.ml", line 514, characters 26-33: 46.015us
File "src/lib/pickles/pickles.ml", line 514, characters 26-33 -> File "src/lib/pickles/pickles.ml", line 519, characters 16-23: 3.099us
File "src/lib/pickles/pickles.ml", line 519, characters 16-23 -> File "src/lib/pickles/pickles.ml", line 532, characters 16-23: 5.96us
step read or generate: 12.159us
step read or generate: 953.674ns
step read or generate: 953.674ns
step read or generate: 953.674ns
step read or generate: 1.192us
File "src/lib/pickles/pickles.ml", line 532, characters 16-23 -> File "src/lib/pickles/pickles.ml", line 598, characters 16-23: 2.114s
File "src/lib/pickles/pickles.ml", line 598, characters 16-23 -> File "src/lib/pickles/pickles.ml", line 605, characters 16-23: 15.974us
File "src/lib/pickles/pickles.ml", line 605, characters 16-23 -> File "src/lib/pickles/pickles.ml", line 607, characters 18-25: 3.099us
File "src/lib/pickles/pickles.ml", line 607, characters 18-25 -> File "src/lib/pickles/pickles.ml", line 637, characters 18-25: 5.96us
File "src/lib/pickles/pickles.ml", line 637, characters 18-25 -> File "src/lib/pickles/wrap_main.ml", line 161, characters 14-21: 4.053us
File "src/lib/pickles/wrap_main.ml", line 161, characters 14-21 -> File "src/lib/pickles/wrap_main.ml", line 164, characters 14-21: 2.861us
File "src/lib/pickles/wrap_main.ml", line 164, characters 14-21 -> File "src/lib/pickles/wrap_main.ml", line 169, characters 14-21: 3.099us
File "src/lib/pickles/wrap_main.ml", line 169, characters 14-21 -> File "src/lib/pickles/wrap_main.ml", line 173, characters 14-21: 3.099us
File "src/lib/pickles/wrap_main.ml", line 173, characters 14-21 -> File "src/lib/pickles/wrap_main.ml", line 484, characters 14-21: 62.943us
File "src/lib/pickles/wrap_main.ml", line 484, characters 14-21 -> File "src/lib/pickles/pickles.ml", line 642, characters 16-23: 10.014us
step vk read: 953.674ns
step keypair read: 0ns
stepkeygen: 13.399s
File "src/lib/pickles/pickles.ml", line 642, characters 16-23 -> File "src/lib/pickles/cache.ml", line 104, characters 24-31: 14.348s
step vk read: 1.192us
step keypair read: 0ns
stepkeygen: 5.354s
File "src/lib/pickles/cache.ml", line 104, characters 24-31 -> File "src/lib/pickles/cache.ml", line 104, characters 24-31: 5.764s
step vk read: 2.146us
step keypair read: 0ns
stepkeygen: 1.962s
File "src/lib/pickles/cache.ml", line 104, characters 24-31 -> File "src/lib/pickles/cache.ml", line 104, characters 24-31: 2.823s
step vk read: 1.669us
step keypair read: 0ns
stepkeygen: 3.947s
File "src/lib/pickles/cache.ml", line 104, characters 24-31 -> File "src/lib/pickles/cache.ml", line 104, characters 24-31: 5.496s
step vk read: 1.907us
step keypair read: 715.256ns
stepkeygen: 1.745s
File "src/lib/pickles/cache.ml", line 104, characters 24-31 -> File "src/lib/pickles/cache.ml", line 104, characters 24-31: 2.34s
wrap read or generate : 0ns
File "src/lib/pickles/cache.ml", line 104, characters 24-31 -> File "src/lib/pickles/pickles.ml", line 686, characters 16-23: 1.35s
File "src/lib/pickles/pickles.ml", line 686, characters 16-23 -> File "src/lib/pickles/pickles.ml", line 789, characters 16-23: 19.789us
File "src/lib/pickles/pickles.ml", line 789, characters 16-23 -> File "src/lib/pickles/pickles.ml", line 803, characters 16-23: 5.245us
Transaction_snark.system: 38.037s
File "src/lib/pickles/pickles.ml", line 442, characters 16-23 -> File "src/lib/pickles/pickles.ml", line 453, characters 16-23: 5.245us
File "src/lib/pickles/pickles.ml", line 453, characters 16-23 -> File "src/lib/pickles/pickles.ml", line 468, characters 16-23: 4.768us
File "src/lib/pickles/pickles.ml", line 468, characters 16-23 -> File "src/lib/pickles/pickles.ml", line 498, characters 18-25: 3.099us
File "src/lib/pickles/pickles.ml", line 498, characters 18-25 -> File "src/lib/pickles/pickles.ml", line 505, characters 26-33: 2.146us
File "src/lib/pickles/pickles.ml", line 505, characters 26-33 -> File "src/lib/pickles/step_branch_data.ml", line 65, characters 14-21: 4.768us
File "src/lib/pickles/step_branch_data.ml", line 65, characters 14-21 -> File "src/lib/pickles/step_branch_data.ml", line 95, characters 14-21: 3.099us
File "src/lib/pickles/step_branch_data.ml", line 95, characters 14-21 -> File "src/lib/pickles/step_branch_data.ml", line 101, characters 14-21: 4.053us
File "src/lib/pickles/step_branch_data.ml", line 101, characters 14-21 -> File "src/lib/pickles/step_branch_data.ml", line 119, characters 14-21: 1.907us
wrap key read: 953.674ns
wrapkeygen: 12.482s
File "src/lib/pickles/step_branch_data.ml", line 119, characters 14-21 -> File "src/lib/pickles/step_branch_data.ml", line 135, characters 14-21: 14.8s
make step data: 14.8s
File "src/lib/pickles/step_branch_data.ml", line 135, characters 14-21 -> File "src/lib/pickles/pickles.ml", line 514, characters 26-33: 43.631us
File "src/lib/pickles/pickles.ml", line 514, characters 26-33 -> File "src/lib/pickles/pickles.ml", line 519, characters 16-23: 4.292us
File "src/lib/pickles/pickles.ml", line 519, characters 16-23 -> File "src/lib/pickles/pickles.ml", line 532, characters 16-23: 4.053us
step read or generate: 953.674ns
File "src/lib/pickles/pickles.ml", line 532, characters 16-23 -> File "src/lib/pickles/pickles.ml", line 598, characters 16-23: 1.164s
File "src/lib/pickles/pickles.ml", line 598, characters 16-23 -> File "src/lib/pickles/pickles.ml", line 605, characters 16-23: 16.212us
File "src/lib/pickles/pickles.ml", line 605, characters 16-23 -> File "src/lib/pickles/pickles.ml", line 607, characters 18-25: 3.099us
File "src/lib/pickles/pickles.ml", line 607, characters 18-25 -> File "src/lib/pickles/pickles.ml", line 637, characters 18-25: 5.96us
File "src/lib/pickles/pickles.ml", line 637, characters 18-25 -> File "src/lib/pickles/wrap_main.ml", line 161, characters 14-21: 4.053us
File "src/lib/pickles/wrap_main.ml", line 161, characters 14-21 -> File "src/lib/pickles/wrap_main.ml", line 164, characters 14-21: 2.861us
File "src/lib/pickles/wrap_main.ml", line 164, characters 14-21 -> File "src/lib/pickles/wrap_main.ml", line 169, characters 14-21: 2.861us
File "src/lib/pickles/wrap_main.ml", line 169, characters 14-21 -> File "src/lib/pickles/wrap_main.ml", line 173, characters 14-21: 2.146us
File "src/lib/pickles/wrap_main.ml", line 173, characters 14-21 -> File "src/lib/pickles/wrap_main.ml", line 484, characters 14-21: 61.989us
File "src/lib/pickles/wrap_main.ml", line 484, characters 14-21 -> File "src/lib/pickles/pickles.ml", line 642, characters 16-23: 10.967us
step vk read: 2.146us
step keypair read: 0ns
stepkeygen: 24.404s
File "src/lib/pickles/pickles.ml", line 642, characters 16-23 -> File "src/lib/pickles/cache.ml", line 104, characters 24-31: 26.129s
wrap read or generate : 953.674ns
File "src/lib/pickles/cache.ml", line 104, characters 24-31 -> File "src/lib/pickles/pickles.ml", line 686, characters 16-23: 1.045s
File "src/lib/pickles/pickles.ml", line 686, characters 16-23 -> File "src/lib/pickles/pickles.ml", line 789, characters 16-23: 7.868us
File "src/lib/pickles/pickles.ml", line 789, characters 16-23 -> File "src/lib/pickles/pickles.ml", line 803, characters 16-23: 3.099us
dummy wrap sg: 182.949ms
wrap key read: 0ns
wrapkeygen: 3.465s
{"timestamp":"2022-07-11 07:57:34.849793Z","level":"Trace","source":{"module":"Blockchain_snark__Blockchain_snark_state","location":"File \"src/lib/blockchain_snark/blockchain_snark_state.ml\", line 249, characters 12-24"},"message":"blockchain snark update success: $result = (transaction_snark_input_correct=$transaction_snark_input_correct ∨ nothing_changed (no_coinbases_popped=$no_coinbases_popped)=$nothing_changed) ∧ updated_consensus_state=$updated_consensus_state ∧ correct_coinbase_status=$correct_coinbase_status","metadata":{"correct_coinbase_status":true,"no_coinbases_popped":true,"nothing_changed":true,"result":true,"transaction_snark_input_correct":true,"updated_consensus_state":true}}
plonk_checks: 157.118us
plonk_checks: 143.766us
step-prover 0 (65536): 1.72s
wrap proof: 867.031ms
ZYD genesis_proof size:9273
证明相关关键代码有:
- exists:为向R1CS引入value,若request失败,则通过compute计算,若未提供compute,则返回失败。
(** Introduce a value into the R1CS.- The [request] argument functions like {!val:request_witness}, creatinga request and returning the result.- If no [request] argument is given, or if the [request] isn't handled,then [compute] is run to create a value.If [compute] is not given and [request] fails/is also not given, thenthis function raises a [Failure].*)val exists :?request:'value Request.t As_prover.t-> ?compute:'value As_prover.t-> ('var, 'value) Typ.t-> 'var Checked.t
- with_label:为constraint添加label,若验证该constraint为未satisfied,则该label将在错误消息中显示,
(** Add a label to all of the constraints added in the checked computation.If a constraint is checked and isn't satisfied, this label will be shownin the error message.*)val with_label : string -> 'a Checked.t -> 'a Checked.t
- run_state:为用于运行a checked computation的internal sate:
(** The internal state used to run a checked computation. *) type 'field t ={ system : 'field Constraint_system.t option; input : 'field Vector.t; aux : 'field Vector.t; eval_constraints : bool; num_inputs : int; next_auxiliary : int ref; has_witness : bool; stack : string list; handler : Request.Handler.t; is_running : bool; as_prover : bool ref; log_constraint :( ?at_label_boundary:[ `Start | `End ] * string-> ('field Cvar.t, 'field) Constraint.t-> unit)option}
snark0.ml中将其初始状态设置为:
let state =ref{ system = None; input = field_vec (); aux = field_vec (); eval_constraints = false; num_inputs = 0; next_auxiliary = ref 1; has_witness = false; stack = []; handler = Request.Handler.fail; is_running = false; as_prover = ref false; log_constraint = None}
- Random_oracle_input.Chunked模块:定义了a random oracle的输入,由full field elements和‘chunks’ of fields结合为一个或多个field elements。chunks表示为[(field, length)],其中[0 <= field < 2^length]。这样可高效combine values in a known range。如:
{[
{ field_elements= [||]; packeds= [|(x, 64); (y, 32); (z, 16)|] }
]}
表示的为[x * 2^(32+16) + y * 2^(64) + z]。可通过pack_to_fields
函数来实现。type 'field t = { field_elements : 'field array; packeds : ('field * int) array } [@@deriving sexp, compare]let append (t1 : _ t) (t2 : _ t) = { field_elements = Array.append t1.field_elements t2.field_elements ; packeds = Array.append t1.packeds t2.packeds }
- Consensus_state_hooks.next_state_checked:对于特定的consensus state和snark transition,创建a constrainted, checked var for the next consensus state。为一个约束系统,见:
let%snarkydef next_state_checked
。
2. 关键模块代码解析
2.1 pickles.composition_types.branch_data模块
pickles.composition_types.branch_data模块内有:
- Proofs_verified:用于表示某branch wrap proof中deferred-values的finalizing。N0表示[false; false];N1表示[true; false];N2表示[true; true]。
(** Data specific to a branch of a proof-system that's necessary forfinalizing the deferred-values in a wrap proof of that branch. *)(** Inside the circuit, we will represent a value of this typeas a sequence of 2 bits:00: N010: N111: N2 *)
module Proofs_verified = structmodule V1 = structtype t = N0 | N1 | N2
- Domain_log2:type t为char类型,占8个bit。
module Domain_log2 = structmodule V1 = structtype t = char
- branch_data会将proofs_verified(前2个bit)和 domain_log2(后8个bit)pack into为a single field element:
(* We pack this into a single field element as follows:First 2 bits: proofs_verifiedNext 8 bits: domain_log2 *)type t ={ proofs_verified : Proofs_verified.Stable.V1.t; domain_log2 : Domain_log2.Stable.V1.t}
2.2 pickles.composition_types.spec模块
spec模块内有:
- Basic支持Filed、Bool、Digest、Challenge、Bulletproof_challenge、Branch_data类型。
type (_, _, _) t =| Field : ('field1, 'field2, < field1 : 'field1 ; field2 : 'field2 ; .. >) t| Bool : ('bool1, 'bool2, < bool1 : 'bool1 ; bool2 : 'bool2 ; .. >) t| Digest: ( 'digest1, 'digest2, < digest1 : 'digest1 ; digest2 : 'digest2 ; .. > )t| Challenge: ( 'challenge1, 'challenge2, < challenge1 : 'challenge1 ; challenge2 : 'challenge2 ; .. > )t| Bulletproof_challenge: ( 'bp_chal1, 'bp_chal2, < bulletproof_challenge1 : 'bp_chal1; bulletproof_challenge2 : 'bp_chal2; .. > )t| Branch_data: ( 'branch_data1, 'branch_data2, < branch_data1 : 'branch_data1 ; branch_data2 : 'branch_data2 ; .. >)t
2.3 pickles.step_branch_data模块
step_branch_data模块数据来源于将某inductive rule ”编译“ 为a circuit:【在Pickles.ml的Make.compile函数中,会调用Step_branch_data.create()来编译circuit,获得step_data。】【在step_keypairs时,若本地未存储相应的key,会预编译电路来生成k_p,以k_p为输入调用Cache.Step.read_or_generate
最终再次预编译电路生成最终的step_keypairs。log_step
时也会预编译电路生成并记录相应的调试信息。】
(* The data obtained from "compiling" an inductive rule into a circuit. *)
type ( 'a_var, 'a_value, 'max_proofs_verified, 'branches, 'prev_vars, 'prev_values, 'local_widths, 'local_heights )t =| T :{ proofs_verified :'proofs_verified Nat.t * ('prev_vars, 'proofs_verified) Hlist.Length.t; index : int; lte : ('proofs_verified, 'max_proofs_verified) Nat.Lte.t; domains : Domains.t; rule :( 'prev_vars, 'prev_values, 'local_widths, 'local_heights, 'a_avar, 'a_value )Inductive_rule.t; main :step_domains:(Domains.t, 'branches) Vector.t-> unit-> ( (Unfinalized.t, 'max_proofs_verified) Vector.t, Impls.Step.Field.t, (Impls.Step.Field.t, 'max_proofs_verified) Vector.t )Types.Step.Statement.t; requests :(module Requests.Step.Swith type statement = 'a_valueand type max_proofs_verified = 'max_proofs_verifiedand type prev_values = 'prev_valuesand type local_signature = 'local_widthsand type local_branches = 'local_heights )}-> ( 'a_var, 'a_value, 'max_proofs_verified, 'branches, 'prev_vars, 'prev_values, 'local_widths, 'local_heights )t
2.4 pickles.composition_types.composition_types模块
composition_types模块中主要包含2个子模块:
- Wrap模块:主要包含Proof_state、Pass_through、Statement 三个子模块。
- Step模块:主要包含Plonk_polys、Bulletproof、Proof_state和Statement 四个子模块。
Step的Passthrough 为 Wrap.Proof_state.Me_only。
Step的Me_only为Wrap.Pass_through。
module Pass_through = Wrap.Proof_state.Me_onlymodule Me_only = Wrap.Pass_through
2.4.1 Wrap类型模块
Wrap结构表示为:【me_only
在circuit中以digest表示,然后unhashed。pass_through
在circuit中以digest表示。】
type ( 'plonk, 'scalar_challenge, 'fp, 'fq, 'me_only, 'digest, 'bp_chals, 'index )t ={ deferred_values :( 'plonk, 'scalar_challenge, 'fp, 'fq, 'bp_chals, 'index )Deferred_values.Stable.V1.t; sponge_digest_before_evaluations : 'digest; me_only : 'me_only(** Parts of the statement not needed by the other circuit. Represented as a hash inside thecircuit which is then "unhashed". *)}
Wrap模块中包含:
- 1)Proof_state模块:
- 1.1)Deferred_values:即为推迟延缓计算的数据。包含用于finalize circuit中某proof验证所需的scalar-field elements。每个verifier circuit都以 验证某proof中包含group operations的部分开始。最后,必须执行一组scalar-field计算。相比于直接进行一组scalar-field计算,会将允许该计算所需的values作为其自身的public-input暴露,使得下一circuit可进行该计算(由于此时使用的是cycle中的另一曲线),从而可提升scalar field的计算效率。
Deferred_values结构定义为:【Mina实际封装区块时,将branch_data 重命名为了”which_branch“,值类似为"\u0000"或"\u0001"。】【比Step模块的Deferred_values多一个branch_data(which_branch)元素。】(** All the deferred values needed, comprising values from the PLONK IOP verification,values from the inner-product argument, and [which_branch] which is needed to knowthe proper domain to use. *)type ( 'plonk, 'scalar_challenge, 'fp, 'fq, 'bulletproof_challenges, 'branch_data )t ={ plonk : 'plonk; combined_inner_product : 'fp(** combined_inner_product = sum_{i < num_evaluation_points} sum_{j < num_polys} r^i xi^j f_j(pt_i) *); b : 'fp(** b = challenge_poly plonk.zeta + r * challenge_poly (domain_generrator * plonk.zeta)where challenge_poly(x) = \prod_i (1 + bulletproof_challenges.(i) * x^{2^{k - 1 - i}})*); xi : 'scalar_challenge(** The challenge used for combining polynomials *); bulletproof_challenges : 'bulletproof_challenges(** The challenges from the inner-product argument that was partially verified. *); branch_data : 'branch_data (* Mina实际封装区块时,将branch_data重命名为了”which_branch“,值类似为"\u0000"或"\u0001"。 *)(** Data specific to which step branch of the proof-system was verified *)}
- 1.1.1) Plonk模块:
其中:- 1.1.1.1)Minimal类型:为PLONK IOP中的challenges,可用于派生后续In_circuit模块内的所有值。
type ('challenge, 'scalar_challenge) t = { alpha : 'scalar_challenge ; beta : 'challenge ; gamma : 'challenge ; zeta : 'scalar_challenge }```
- 1.1.1.2)In_circuit类型:为a verifier circuit中deferred(推迟)的所有scalar values。[poseidon_selector], [vbmul], [complete_add], [endomul], [endomul_scalar], [perm], and [generic]的值均为scalars,将在计算linearized polynomial commitment期间用于scale selector polynomials。然后将这些值暴露给下一环节(该环节可进行scalar计算),该环节可检查这些值是基于proof evaluations和challenges计算而来的正确结果。
type ('challenge, 'scalar_challenge, 'fp) t = { alpha : 'scalar_challenge ; beta : 'challenge ; gamma : 'challenge ; zeta : 'scalar_challenge(* TODO: zeta_to_srs_length is kind of unnecessary.Try to get rid of it when you can.*) ; zeta_to_srs_length : 'fp ; zeta_to_domain_size : 'fp ; poseidon_selector : 'fp(** scalar used on the poseidon selector *) ; vbmul : 'fp (** scalar used on the vbmul selector *) ; complete_add : 'fp(** scalar used on the complete_add selector *) ; endomul : 'fp (** scalar used on the endomul selector *) ; endomul_scalar : 'fp(** scalar used on the endomul_scalar selector *) ; perm : 'fp(** scalar used on one of the permutation polynomial commitments. *) ; generic : 'fp Generic_coeffs_vec.t (* 为长度为N9的vector *)(** scalars used on the coefficient column commitments. *) }
- 1.1.1.1)Minimal类型:为PLONK IOP中的challenges,可用于派生后续In_circuit模块内的所有值。
- 1.1.2)Minimal模块:
- 1.1.3)In_circuit模块:
- 1.1.1) Plonk模块:
- 1.2)Me_only模块:包含的为proof accumulation状态内的元素,这些元素仅由”wrapping“ proof system compute on,这些元素对任意”step“ circuits来说都可以不透明方式处理。
type ('g1, 'bulletproof_challenges) t ={ challenge_polynomial_commitment : 'g1 (* 实际证明表示时,将该point以Affine坐标系表示,重命名为sg *); old_bulletproof_challenges : 'bulletproof_challenges}
- 1.3)Minimal模块和In_circuit模块。
- 1.1)Deferred_values:即为推迟延缓计算的数据。包含用于finalize circuit中某proof验证所需的scalar-field elements。每个verifier circuit都以 验证某proof中包含group operations的部分开始。最后,必须执行一组scalar-field计算。相比于直接进行一组scalar-field计算,会将允许该计算所需的values作为其自身的public-input暴露,使得下一circuit可进行该计算(由于此时使用的是cycle中的另一曲线),从而可提升scalar field的计算效率。
- 2)Pass_through模块:包含的为proof accumulation状态内的元素,这些元素仅由”stepping“ proof system compute on,这些元素对任意”wrap“ circuits来说都可以不透明方式处理。
- 3)Statement模块:为”wrap“ proofs的full statement,包含:【包含proof_state和pass_through两大要素】
- 应用层的statement(app-state)
- 在运行该proof最终验证时所需的数据,这些数据对应parts of incompletely verified proofs。
type ( 'plonk, 'scalar_challenge, 'fp, 'fq, 'me_only, 'digest, 'pass_through, 'bp_chals, 'index )t ={ proof_state :( 'plonk, 'scalar_challenge, 'fp, 'fq, 'me_only, 'digest, 'bp_chals, 'index )Proof_state.Stable.V1.t; pass_through : 'pass_through}
2.4.2 Step类型模块
Step模块中包含:
- 1)Plonk_polys模块:
- 2)Bulletproof模块:其中的Advice为可通过proof+statement以linear time计算出来,无需通过wire发送给Verifier,但确实需要提供给Verifier的内容。
module Advice = struct(** This is data that can be computed in linear time from the proof + statement.It doesn't need to be sent on the wire, but it does need to be provided to the verifier*)type 'fq t ={ b : 'fq; combined_inner_product : 'fq (* sum_i r^i sum_j xi^j f_j(pt_i) *)}
Bulletproof结构对应Plonk_types.Openings.Bulletproof,为:
(* Plonk_types.Openings.Bulletproof类型: *) module Openings = structmodule Bulletproof = struct[%%versionedmodule Stable = structmodule V1 = structtype ('g, 'fq) t ={ lr : ('g * 'g) array; z_1 : 'fq; z_2 : 'fq; delta : 'g; challenge_polynomial_commitment : 'g}
- 3)Proof_state模块:包含了:step-circuit部分验证的proof列表,该列表内元素为per_proof结构,以"unfinalized_proofs"表示;在proof accumulation状态中仅由”stepping“ proof system计算的元素,这些元素可由任意”wrap“ circuits以不透明方式处理,以”me_only“表示。
type ('unfinalized_proofs, 'me_only) t ={ unfinalized_proofs : 'unfinalized_proofs(** A vector of the "per-proof" structures defined above, one for each proof that the step-circuit partially verifies. *); me_only : 'me_only(** The component of the proof accumulation state that is only computed on by the"stepping" proof system, and that can be handled opaquely by any "wrap" circuits. *)}
- 3.1)Deferred_values:即为推迟延缓计算的数据。包含用于finalize circuit中某proof验证所需的所有scalar-field elements,Verifier将check这些值与”group operations“中所用的值一致。包含了某些PLONK多项式的evaluations(如columns多项式、permutation aggregation多项式等等)。剩下的为与inner product argument相关的值。【比Wrap模块的Deferred_values多一个branch_data(which_branch)元素。】
type ('plonk, 'scalar_challenge, 'fq, 'bulletproof_challenges) t_ = { plonk : 'plonk ; combined_inner_product : 'fq(** combined_inner_product = sum_{i < num_evaluation_points} sum_{j < num_polys} r^i xi^j f_j(pt_i) *) ; xi : 'scalar_challenge(** The challenge used for combining polynomials *) ; bulletproof_challenges : 'bulletproof_challenges(** The challenges from the inner-product argument that was partially verified. *) ; b : 'fq(** b = challenge_poly plonk.zeta + r * challenge_poly (domain_generrator * plonk.zeta)where challenge_poly(x) = \prod_i (1 + bulletproof_challenges.(i) * x^{2^{k - 1 - i}})*) }
- 3.1.1)Plonk模块:Step.Deferred_values.Plonk为Wrap.Proof_state.Deferred_values.Plonk。
- 3.2)Pass_through和Me_only模块:
Step的Passthrough 为 Wrap.Proof_state.Me_only。
Step的Me_only为Wrap.Pass_through。module Pass_through = Wrap.Proof_state.Me_onlymodule Me_only = Wrap.Pass_through
- 3.3)Per_proof模块:step circuit并不会验证整个proof,而是:
a)将包含”other field“的计算推迟(如某proof种包含的该group内的scalar-field运算)
b)并不会验证整个inner-product argument,对其中需要O(n)运算量的部分进行了accumulator trick。
为此,对于step circuit中验证的每个proof,必须暴露与以上情况相关的数据作为step circuit的statement,从而使得这些proof将最终完全验证通过。
Per_proof结构为:type ( 'plonk, 'scalar_challenge, 'fq, 'bulletproof_challenges, 'digest, 'bool )t_ = { deferred_values :( 'plonk, 'scalar_challenge, 'fq, 'bulletproof_challenges )Deferred_values.t_(** Scalar values related to the proof *) ; should_finalize : 'bool(** We allow circuits in pickles proof systems to decide if it's OK that a proof didnot recursively verify. In that case, when we expose the unfinalized bits, we needto communicate that it's OK if those bits do not "finalize". That's what this booleanis for. *) ; sponge_digest_before_evaluations : 'digest }``
- 3.1)Deferred_values:即为推迟延缓计算的数据。包含用于finalize circuit中某proof验证所需的所有scalar-field elements,Verifier将check这些值与”group operations“中所用的值一致。包含了某些PLONK多项式的evaluations(如columns多项式、permutation aggregation多项式等等)。剩下的为与inner product argument相关的值。【比Wrap模块的Deferred_values多一个branch_data(which_branch)元素。】
- 4)Statement模块:
type ('unfinalized_proofs, 'me_only, 'pass_through) t ={ proof_state : ('unfinalized_proofs, 'me_only) Proof_state.t; pass_through : 'pass_through(** The component of the proof accumulation state that is only computed on by the"wrapping" proof system, and that can be handled opaquely by any "step" circuits. *)}
2.5 Pickles.reduced_me_only模块
step-proof “reduced” me-only 包含了标准的me-only数据,但是没有相应的wrap verification key。引入reduced_me_only类型的目的是为了通过wire发送step me-onlys。没必要发送发送wrap-key,因为每个人都知道wrap-key。
reduced_me_only.Step结构为:
type ('s, 'challenge_polynomial_commitments, 'bpcs) t ={ app_state : 's; challenge_polynomial_commitments : 'challenge_polynomial_commitments; old_bulletproof_challenges : 'bpcs}
reduced_me_only.Wrap.Challenges_vector结构为:
type t =Challenge.Constant.t Scalar_challenge.t Bulletproof_challenge.tWrap_bp_vec.t
reduced_me_onlyWrap.Challenges_vector.Prepared结构为:
type t = (Tock.Field.t, Tock.Rounds.n) Vector.t
reduced_me_only.Wrap结构为:
type 'max_local_max_proofs_verified t =( Tock.Inner_curve.Affine.t, (Challenges_vector.t, 'max_local_max_proofs_verified) Vector.t )Types.Wrap.Proof_state.Me_only.t
reduced_me_only.Wrap.Prepared结构为:
type 'max_local_max_proofs_verified t =( Tock.Inner_curve.Affine.t, (Challenges_vector.Prepared.t, 'max_local_max_proofs_verified) Vector.t)
2.6 pickles.proof模块
Proof结构为:
type ('max_width, 'mlmb) t = (unit, 'mlmb, 'max_width) With_data.tmodule With_data = structtype ('s, 'mlmb, 'w) t = ('s, 'mlmb, 'w) with_data
endtype ('s, 'mlmb, _) with_data =| T :( 'mlmb Base.Me_only.Wrap.t, ( 's, (Tock.Curve.Affine.t, 'most_recent_width) Vector.t, ( Challenge.Constant.t Scalar_challenge.Stable.Latest.tBulletproof_challenge.tStep_bp_vec.t, 'most_recent_width )Vector.t )Base.Me_only.Step.t )Base.Wrap.t-> ('s, 'mlmb, _) with_data
pickles.proof模块中包含:
1)Base模块:
- Me_only模块:同上面的reduced_me_only模块。
- Step模块:proof.base.step结构为:
type ( 's, 'unfinalized_proofs, 'sgs, 'bp_chals, 'dlog_me_onlys, 'prev_evals )t = { statement :( 'unfinalized_proofs, ('s, 'sgs, 'bp_chals) Me_only.Step.t, 'dlog_me_onlys )Types.Step.Statement.t ; index : int ; prev_evals : 'prev_evals ; proof : Tick.Proof.t }
- Double模块:表示的为
type 'a t = 'a * 'a
- Wrap模块:proof.base.wrap结构为:
type ('dlog_me_only, 'step_me_only) t =('dlog_me_only, 'step_me_only) Stable.Latest.t = { statement :( Challenge.Constant.t, Challenge.Constant.t Scalar_challenge.t, Tick.Field.t Shifted_value.Type1.t, Tock.Field.t, 'dlog_me_only, Digest.Constant.t, 'step_me_only, Challenge.Constant.t Scalar_challenge.t Bulletproof_challenge.tStep_bp_vec.t, Branch_data.t )Types.Wrap.Statement.Minimal.t ; prev_evals : (Tick.Field.t, Tick.Field.t array) Plonk_types.All_evals.t ; proof : Tock.Proof.t }
2)Make模块:
module Make (W : Nat.Intf) (MLMB : Nat.Intf) = struct module Max_proofs_verified_at_most = At_most.With_length (W) module MLMB_vec = Nvector (MLMB)module Repr = struct type t =( ( Tock.Inner_curve.Affine.t, Reduced_me_only.Wrap.Challenges_vector.t MLMB_vec.t )Types.Wrap.Proof_state.Me_only.t, ( unit, Tock.Curve.Affine.t Max_proofs_verified_at_most.t, Challenge.Constant.t Scalar_challenge.t Bulletproof_challenge.tStep_bp_vec.tMax_proofs_verified_at_most.t )Base.Me_only.Step.t )Base.Wrap.t
3)Proofs_verified_2模块:
4)Proofs_verified_max模块:【与Proofs_verified_2模块相比,在于module T不同以及most verification_key不同】
module Proofs_verified_max = struct module T = Make(Side_loaded_verification_key.Width.Max)(Side_loaded_verification_key.Width.Max)module Repr = struct [%%versioned module Stable = struct[@@@no_toplevel_latest_type]module V2 = structtype t =( ( Tock.Inner_curve.Affine.Stable.V1.t, Reduced_me_only.Wrap.Challenges_vector.Stable.V2.tSide_loaded_verification_key.Width.Max_vector.Stable.V1.t )Types.Wrap.Proof_state.Me_only.Stable.V1.t, ( unit, Tock.Curve.Affine.tSide_loaded_verification_key.Width.Max_at_most.Stable.V1.t, Limb_vector.Constant.Hex64.Stable.V1.t Vector.Vector_2.Stable.V1.tScalar_challenge.Stable.V2.tBulletproof_challenge.Stable.V1.tStep_bp_vec.Stable.V1.tSide_loaded_verification_key.Width.Max_at_most.Stable.V1.t )Base.Me_only.Step.Stable.V1.t )Base.Wrap.Stable.V2.t
2.7 pickles.plonk_checks模块
pickles.plonk_checks模块中定义了vanishing_polynomial_domain、plonk_domain、domain等类型:
type 'field vanishing_polynomial_domain =< vanishing_polynomial : 'field -> 'field >type 'field plonk_domain =< vanishing_polynomial : 'field -> 'field (* x^{2 ^ k} - 1 *); shifts : 'field Plonk_types.Shifts.t (* 为array数组结构 *); generator : 'field >type 'field domain = < size : 'field ; vanishing_polynomial : 'field -> 'field >
其中的Make模块内实现了如下函数:
- 1)
ft_eval0
:实现了Maller优化,可计算the ft evaluation at zeta。 - 2)
derive_plonk
:计算用于linearization中的scalars list。 - 3)
checked
:采用native field来检查所计算的proof scalars与the expected ones匹配。注意,此处的the expected scalars用于检查proof中over 另一field的linearization(在另一field检查效率更高),但是会将该arithmetic checks推迟,直到有the efficiency of the native field。
2.8 pickles.scalar_challenge模块
ocaml的scalar_challenge是与rust版本的proof-systems中的ScalarChallenge绑定的:
/// A challenge which is used as a scalar on a group element in the verifier
#[derive(Clone, Copy, Debug)]
pub struct ScalarChallenge<F>(pub F);type nonrec 'caml_f scalar_challenge = { inner : 'caml_f } [@@boxed]
type 'f t = 'f Kimchi_types.scalar_challenge = { inner : 'f }
在pickles.scalar_challenge模块中,定义了cycle曲线之间变量的来回切换:
let typ f =let there { inner = x } = x inlet back x = create x inSnarky_backendless.Typ.(transport_var (transport f ~there ~back) ~there ~back)let create t = { inner = t }
let map { inner = x } ~f = create (f x)
其中let to_field_checked' (type f) ?(num_bits = num_bits)
函数实现的是Halo论文中的如下算法:
其中的Make模块中,实现了endo
和endo_inv
函数。
2.9 pickles.step模块
step.Make()调用示例为:【第一个参数为变量名;第二个参数为变量值(对应为Tick域);第三个参数为最多验证的proof数。】
let module S = Step.Make (A) (A_value) (Max_proofs_verified)module Make(A : T0) (A_value : sigtype tval to_field_elements : t -> Tick.Field.t arrayend)(Max_proofs_verified : Nat.Add.Intf_transparent)
其中的模块E对应为Tock域:
module E = structtype t = Tock.Field.t array Plonk_types.Evals.t Double.t * Tock.Field.tend(* Plonk_types.Evals.t类型为: *)type 'a t ={ w : 'a Columns_vec.Stable.V1.t; z : 'a; s : 'a Permuts_minus_1_vec.Stable.V1.t; generic_selector : 'a; poseidon_selector : 'a}
(* Columns_vec.Stable.V1.t类型为: *)
type 'a t = ('a, Nat.N15.n) vec
(* Permuts_minus_1_vec.Stable.V1.t类型为: *)
type 'a t = ('a, Nat.N6.n) vec
其中的Plonk_checks模块中,分别实现了名为Type1(对应Tick域的Scalars)和Type2(对应Tock域的Scalars)的Plonk_checks类型模块(具体见上面2.7节):
module Plonk_checks = structinclude Plonk_checksmodule Type1 = Plonk_checks.Make (Shifted_value.Type1) (Scalars.Tick)module Type2 = Plonk_checks.Make (Shifted_value.Type2) (Scalars.Tock)end
(* Shifted_value.Type1和Type2类型为: *)
type 'f t = Shifted_value of 'f
pickles.step模块中的f
函数实现了“step” prover功能:
let f(type (* The maximum number of proofs verified by one of the proof systems verified by this rule :)In other words: each of the proofs verified by this rule comes from some pickles proof system.The ith one of those proof systems has a maximum number of proofs N_i that is verified bya rule in proof system i. max_local_max_proof_verifieds is the max of the N_i.*)max_local_max_proof_verifieds self_branches prev_vars prev_valueslocal_widths local_heights prevs_length ) ?handler(T branch_data :( A.t, A_value.t, Max_proofs_verified.n, self_branches, prev_vars, prev_values, local_widths, local_heights )Step_branch_data.t ) (next_state : A_value.t)~maxes:(module Maxes : Pickles_types.Hlist.Maxes.Swith type length = Max_proofs_verified.nand type ns = max_local_max_proof_verifieds )~(prevs_length : (prev_vars, prevs_length) Length.t) ~self ~step_domains~self_dlog_plonk_index pk self_dlog_vk(prev_values : prev_values H1.T(Id).t)(prev_proofs : (local_widths, local_widths) H2.T(P).t) :( A_value.t, (_, Max_proofs_verified.n) Vector.t, (_, prevs_length) Vector.t, (_, prevs_length) Vector.t, _, (_, Max_proofs_verified.n) Vector.t )P.Base.Step.tPromise.t =
f
函数中:
- 1)X_hat模块:表示的是2个Tock域的field值。
- 2)Statement_with_hashes定义的类型为:
( Challenge.Constant.t, Challenge.Constant.t Scalar_challenge.t, Tick.Field.t Shifted_value.Type1.t, Tock.Field.t, Digest.Constant.t, Digest.Constant.t, Digest.Constant.t, Challenge.Constant.t Scalar_challenge.t Bulletproof_challenge.tStep_bp_vec.t, Branch_data.t )Wrap.Statement.In_circuit.t(* Wrap.statement.in_circuit.t类型为: *)type ( 'challenge, 'scalar_challenge, 'fp (*Tick*), 'fq (*Tock*), 'me_only, 'digest, 'pass_through, 'bp_chals, 'index )t =( ( 'challenge, 'scalar_challenge, 'fp )Proof_state.Deferred_values.Plonk.In_circuit.t, 'scalar_challenge, 'fp, 'fq, 'me_only, 'digest, 'pass_through, 'bp_chals, 'index )Stable.Latest.t(* Stable.Latest.t类型为: *)type ( 'plonk, 'scalar_challenge, 'fp, 'fq, 'me_only, 'digest, 'pass_through, 'bp_chals, 'index )t ={ proof_state :( 'plonk, 'scalar_challenge, 'fp, 'fq, 'me_only, 'digest, 'bp_chals, 'index )Proof_state.Stable.V1.t; pass_through : 'pass_through}(* Bulletproof_challenge.t结构为: *)type 'challenge t = { prechallenge : 'challenge }(* Step_bp_vec.t结构为:【对于Step其向量长度为16,对于Wrap其向量长度为15。】 *)type 'a t = 'a Vector.Vector_16.t
- 3)challenge_polynomial函数:为Tock域的Wrap_verifier的
let challenge_polynomial ~one ~add ~mul chals
函数,本质为计算(* given [chals], compute \prod_i (1 + chals.(i) * x{2{k - 1 - i}}) *)。 - 4)expand_proof函数:
let expand_proof : fun dlog_vk dlog_index app_state (T t) tag ~must_verify ->
,其中:【将输入的proof等参数展开为:app_state、wrap_proof、proof_state、prev_proof_evals、prev_challenges、prev)challenge_polynomial_commitments。】- 1)expand_proof函数输入参数中的
T t
为Base.wrap.t结构:【本质为获得Tock proof】type ('s, 'mlmb, _) with_data =| T :( 'mlmb Base.Me_only.Wrap.t, ( 's, (Tock.Curve.Affine.t, 'most_recent_width) Vector.t, ( Challenge.Constant.t Scalar_challenge.Stable.Latest.tBulletproof_challenge.tStep_bp_vec.t, 'most_recent_width )Vector.t )Base.Me_only.Step.t )Base.Wrap.t-> ('s, 'mlmb, _) with_data (* Base.Me_only.Wrap.t结构为: *) type 'max_local_max_proofs_verified t =( Tock.Inner_curve.Affine.t, (Challenges_vector.t, 'max_local_max_proofs_verified) Vector.t )Types.Wrap.Proof_state.Me_only.t (* Types.Wrap.Proof_state.Me_only.t结构为: *) type ('g1, 'bulletproof_challenges) t ={ challenge_polynomial_commitment : 'g1; old_bulletproof_challenges : 'bulletproof_challenges} (* Base.Me_only.Step.t结构为: *) type ('s, 'challenge_polynomial_commitments, 'bpcs) t ={ app_state : 's; challenge_polynomial_commitments : 'challenge_polynomial_commitments; old_bulletproof_challenges : 'bpcs} (* Base.Wrap.t结构为: *) type ('dlog_me_only, 'step_me_only) t =('dlog_me_only, 'step_me_only) Stable.Latest.t ={ statement :( Challenge.Constant.t, Challenge.Constant.t Scalar_challenge.t, Tick.Field.t Shifted_value.Type1.t, Tock.Field.t, 'dlog_me_only, Digest.Constant.t, 'step_me_only, Challenge.Constant.t Scalar_challenge.t Bulletproof_challenge.tStep_bp_vec.t, Branch_data.t )Types.Wrap.Statement.Minimal.t; prev_evals : (Tick.Field.t, Tick.Field.t array) Plonk_types.All_evals.t; proof : Tock.Proof.t} (* Plonk_types.All_evals.t结构为: *)type ('f, 'f_multi) t ={ evals :('f, 'f_multi) With_public_input.Stable.V1.t* ('f, 'f_multi) With_public_input.Stable.V1.t; ft_eval1 : 'f}
- 4.2)expand_proof输出参数为:
[ `Sg of Tock.Curve.Affine.t ]* Unfinalized.Constant.t* Statement_with_hashes.t* X_hat.t* ( value, local_max_proofs_verified, m )Per_proof_witness.Constant.No_app_state.t (* Per_proof_witness.Constant.No_app_state.t结构为: *) type nonrec (_, 'max_proofs_verified, 'num_branches) t =(unit, 'max_proofs_verified, 'num_branches) t type ('statement, 'max_proofs_verified, _) t ={ app_state : 'statement; wrap_proof : Wrap_proof.Constant.t; proof_state :( Challenge.Constant.t, Challenge.Constant.t Scalar_challenge.t, Tick.Field.t Shifted_value.Type1.t, Tock.Field.t, unit, Digest.Constant.t, Challenge.Constant.t Scalar_challenge.t Types.Bulletproof_challenge.tTypes.Step_bp_vec.t, Branch_data.t )Types.Wrap.Proof_state.In_circuit.t; prev_proof_evals :(Tick.Field.t, Tick.Field.t array) Plonk_types.All_evals.t; prev_challenges :((Tick.Field.t, Tick.Rounds.n) Vector.t, 'max_proofs_verified) Vector.t; prev_challenge_polynomial_commitments :(Tick.Inner_curve.Affine.t, 'max_proofs_verified) Vector.t} (* Types.Wrap.Proof_state.In_circuit.t结构为: *) type ( 'challenge, 'scalar_challenge, 'fp, 'fq, 'me_only, 'digest, 'bp_chals, 'index )t =( ('challenge, 'scalar_challenge, 'fp) Deferred_values.Plonk.In_circuit.t, 'scalar_challenge, 'fp, 'fq, 'me_only, 'digest, 'bp_chals, 'index )Stable.Latest.t (* Deferred_values.Plonk.In_circuit.t结构为: *) type ('challenge, 'scalar_challenge, 'fp) t ={ alpha : 'scalar_challenge; beta : 'challenge; gamma : 'challenge; zeta : 'scalar_challenge(* TODO: zeta_to_srs_length is kind of unnecessary.Try to get rid of it when you can.*); zeta_to_srs_length : 'fp; zeta_to_domain_size : 'fp; poseidon_selector : 'fp(** scalar used on the poseidon selector *); vbmul : 'fp (** scalar used on the vbmul selector *); complete_add : 'fp(** scalar used on the complete_add selector *); endomul : 'fp (** scalar used on the endomul selector *); endomul_scalar : 'fp(** scalar used on the endomul_scalar selector *); perm : 'fp(** scalar used on one of the permutation polynomial commitments. *); generic : 'fp Generic_coeffs_vec.t(** scalars used on the coefficient column commitments. *)} (* Stable.Latest.t结构为: *) type ( 'plonk, 'scalar_challenge, 'fp, 'fq, 'me_only, 'digest, 'bp_chals, 'index )t ={ deferred_values :( 'plonk, 'scalar_challenge, 'fp, 'fq, 'bp_chals, 'index )Deferred_values.Stable.V1.t; sponge_digest_before_evaluations : 'digest; me_only : 'me_only(** Parts of the statement not needed by the other circuit. Represented as a hash inside thecircuit which is then "unhashed". *)} (* Deferred_values.Stable.V1.t结构为: *) type ( 'plonk, 'scalar_challenge, 'fp, 'fq, 'bulletproof_challenges, 'branch_data )t ={ plonk : 'plonk; combined_inner_product : 'fp(** combined_inner_product = sum_{i < num_evaluation_points} sum_{j < num_polys} r^i xi^j f_j(pt_i) *); b : 'fp(** b = challenge_poly plonk.zeta + r * challenge_poly (domain_generrator * plonk.zeta)where challenge_poly(x) = \prod_i (1 + bulletproof_challenges.(i) * x^{2^{k - 1 - i}})*); xi : 'scalar_challenge(** The challenge used for combining polynomials *); bulletproof_challenges : 'bulletproof_challenges(** The challenges from the inner-product argument that was partially verified. *); branch_data : 'branch_data(** Data specific to which step branch of the proof-system was verified *)}
- 1)expand_proof函数输入参数中的
- 5)compute_prev_proof_parts函数:
let compute_prev_proof_parts inners_must_verify
,将prev_values和prev_proofs递归调用expand_proof
函数,相应的输出有:challenge_polynomial_commitments、unfinalized_proofs、statement_with_hashes、x_hats、witnesses。 - 6)将
compute_prev_proof_parts
输出的unfinalized_proofs展开到vector unfinalized_proofs_extended中。 - 7)Extract模块内定义了虚拟类型,可通过
extract_from_proofs
函数,从prev_proofs中提取信息,如old_bulletproof_challenges(t.statement.proof_state.deferred_values.bulletproof_challenges
)、to_fold_in(t.statement.proof_state.me_only.challenge_polynomial_commitment
)、prev_evals((t.proof.openings.evals, t.proof.openings.ft_eval1)
)。 - 8)基于next_state、old_bulletproof_challenges、challenge_polynomial_commitments构建next_statement_me_only(为Reduced_me_only.Step.t结构):
type ('s, 'challenge_polynomial_commitments, 'bpcs) t ={ app_state : 's; challenge_polynomial_commitments : 'challenge_polynomial_commitments; old_bulletproof_challenges : 'bpcs}
- 9)基于self_dlog_plonk_index和next_statement_me_only,调用
Reduced_me_only.Step.prepare
函数获得next_me_only_prepared:let next_me_only_prepared =lazy(Reduced_me_only.Step.prepare ~dlog_plonk_index:self_dlog_plonk_index(Lazy.force next_statement_me_only) )let prepare ~dlog_plonk_index{ app_state; challenge_polynomial_commitments; old_bulletproof_challenges} ={ Types.Step.Proof_state.Me_only.app_state; challenge_polynomial_commitments; dlog_plonk_index; old_bulletproof_challenges =Vector.map ~f:Ipa.Step.compute_challenges old_bulletproof_challenges}
- 10)对statements_with_hashes调用pad函数,获得pass_through_padded。
- 11)实现了handler函数:【为证明过程中的关键】
let handler (Snarky_backendless.Request.With { request; respond } as r) =let k x = respond (Provide x) inmatch request with| Req.Compute_prev_proof_parts inners_must_verify ->compute_prev_proof_parts inners_must_verify ;k ()| Req.Prev_inputs ->k prev_values| Req.Proof_with_datas ->k (Option.value_exn !witnesses)| Req.Wrap_index ->k self_dlog_plonk_index| Req.App_state ->k next_state| Req.Unfinalized_proofs ->k (Lazy.force unfinalized_proofs_extended)| Req.Pass_through ->k (Lazy.force pass_through_padded)| _ -> (match handler with| Some f ->f r| None ->Snarky_backendless.Request.unhandled )
- 12)基于to_fold_in和next_me_only_prepared.old_bulletproof_challenges构建prev_challenge_polynomial_commitments list。
- 13)
let%map.Promise (next_proof : Tick.Proof.t), next_statement_hashed =
为证明最核心部分,基本流程为:- 13.1)调用Impls.Step.input
- 13.2)调用Impls.Step.generate_witness_conv
- 13.3)调用step_branch_data.main->step_main.step_main
- 13.4)根据Impls.Step.Proof_inputs.auxiliary_inputs和public_inputs,调用
Backend.Tick.Proof.create_async
获取next_proof和next_statement_hashed。
3. blockchain_snark与transaction_snark
module T = Transaction_snark.Make (structlet constraint_constants = constraint_constantslet proof_level = proof_levelend)module B = Blockchain_snark.Blockchain_snark_state.Make (structlet tag = T.taglet constraint_constants = constraint_constantslet proof_level = proof_levelend)
Transaction_snark和Blockchain_snark会共用相同的constraint_constants和proof_level。
Transaction_snark.Make()返回的tag作为会作为Blockchian_snark_state.Make()的输入。相应的tag类型为:
type tag =( Statement.With_sok.Checked.t (*为变量名*), Statement.With_sok.t (*为变量值*), Nat.N2.n (* 与transaction_snark的max_proofs_verified对应,即约束系统中需要验证的最多proof数 *), Nat.N5.n ) (* 与transaction_snark的branches数对应。即约束系统中存在的分叉情况数。 *)Pickles.Tag.t(* Pickles.Tag.t类型为: *)
type ('var, 'value, 'n1, 'n2) t ={ kind : kind; id : ('var, 'value, 'n1, 'n2) tag }
- 1)Transaction_snark.Make()返回的Tag: 其id与Transaction_snark约束系统呼应的tag类型(包含变量名、变量值、branches数和max_proofs_verified数),其kind为Compiled。
- 2)Blockchain_snark_state.Make()时,会将Transaction_snark约束系统的tag作为输入,用于构建block的约束系统:
[ rule ~proof_level ~constraint_constants T.tag self ] let rule ~proof_level ~constraint_constants transaction_snark self :_ Pickles.Inductive_rule.t ={ identifier = "step"; prevs = [ self; transaction_snark ] (*此处的transaction_snark即为Transaction_snark约束系统返回的tag*); main =(fun [ x1; x2 ] x ->let b1, b2 =let () = Printf.printf "ZYD before run_checked 111\n" inRun.run_checked(let () = Printf.printf "ZYD before step in run_checked\n" instep ~proof_level ~constraint_constants ~logger:(Logger.create ())[ x1; x2 ] x )inlet () = Printf.printf "ZYD after run_checked 222\n" in[ b1; b2 ] )}
- 3)module B = Blockchain_snark_state.Make()时,会将Pickles.compile返回的
Provers.[step]
封装为一个step
函数,可通过B.step
方式调用:【let h = wrap_handler handler w in
即相当于通过B.step参数handler将witness w进行了包裹,封装为了fun r -> blockchain_handler h w r
函数,此处的h
即为B.step
参数handler,支持stake_proof.ledger、pending_coinbase、VRF等操作。
被包裹后,B.step本质就是调用Pickles.ml中的let wrap ?handler prevs next_state =
函数】let tag, cache_handle, p, Pickles.Provers.[ step ] =Pickles.compile ~cache:Cache_dir.cache ........)let step = with_handler step (*封装的step函数定义为:*) val step :Witness.t-> ( Protocol_state.Value.t * (Transaction_snark.Statement.With_sok.t * unit), N2.n * (N2.n * unit) (* 汇总了transaction_snark和blockchain_snark_state的max_proofs_verified*), N1.n * (N5.n * unit) (* 汇总了transaction_snark和blockchain_snark_state的branches*), Protocol_state.Value.t, Proof.t Async.Deferred.t )Pickles.Prover.t (*这个参数即为Pickles.Provers.[step]*)let with_handler k w ?handler = (* k为上面的Pickles.Provers.[step];w为上面的Witness.t类型参数 *)let h = wrap_handler handler w in (* 将B.step调用时的handler重新封装为fun r -> blockchain_handler h w r,然后再赋值给handler *)k ?handler:(Some h)(* Witness.t类型为: *) module Witness = structtype t ={ prev_state : Protocol_state.Value.t; transition : Snark_transition.Value.t}
详细的调用示例为:
B.step ~handler:(Consensus.Data.Prover_state.precomputed_handler ~constraint_constants~genesis_epoch_ledger ) { transition =Snark_transition.genesis ~constraint_constants ~consensus_constants~genesis_ledger ; prev_state } [ (prev_state, blockchain_dummy); (dummy_txn_stmt, txn_dummy) ] t.protocol_state_with_hashes.data(* 或 *)let t = ledger_proof_opt chain next_state t in (*此处的t即类似为(dummy_txn_stmt, txn_dummy)*)let%map.Async.Deferred proof =B.step~handler:(Consensus.Data.Prover_state.handler~constraint_constants state_for_handler (* state_for_handler为Stake_proof结构 *)~pending_coinbase ) (*会与Witness.t一起,会被with_handler->wrap_handler包裹*){ transition = block; prev_state =Blockchain_snark.Blockchain.state chain} (*即上面的参数w,为Witness.t,会被with_handler->wrap_handler包裹*)[ ( Blockchain_snark.Blockchain.state chain, Blockchain_snark.Blockchain.proof chain ); t (*此处的t即类似为(dummy_txn_stmt, txn_dummy)*)] (* 对应为Pickles.ml中的`let wrap ?handler prevs next_state =`函数的prevs参数。 *)next_state (* 对应为Pickles.ml中的`let wrap ?handler prevs next_state =`函数的next_state参数。*) (* 其中Stake_proof结构为: *) 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 : Mina_ledger.Sparse_ledger.Stable.V2.t; producer_private_key : Private_key.Stable.V1.t; producer_public_key : Public_key.Stable.V1.t}
Consensus.Data.Prover_state.handler(..)
返回的handler操作句柄支持Vrf.Winner_address等操作类型,分别返回state_for_handler结构内的delegator、delegator_pk、coinbase_receiver_pk、producer_private_key、producer_public_key等。若未指定操作类型,则默认运行pending_coinbase_handler(对pending_coinbase支持Checked.Coinbase_stack_path等request)或 ledger_handler(对state_for_handler.ledger支持Ledger_hash.Get_element等request)内操作。
Pickles.ml中的let wrap ?handler prevs next_state =
函数内的let app_states, prevs =
本质是将prevs中的[(prev_state,prev_state_proof); (txn_statement, txn_proof)] 转换为[(prev_state, txn_statement); (prev_state_proof, txn_proof)]表示,其中(prev_state, txn_statement)对应为let step handler prev_values prev_proofs next_state =
的prev_values参数,(prev_state_proof, txn_proof)为prev_proofs参数。
调用step函数,获取step proof(为proof.base.step结构,见上面2.6节):let%bind.Promise proof =step handler ~maxes:(module Maxes) app_states prevs next_statelet step handler prev_values prev_proofs next_state =let wrap_vk = Lazy.force wrap_vk inS.f ?handler branch_data next_state ~prevs_length:prev_vars_length~self ~step_domains ~self_dlog_plonk_index:wrap_vk.commitments(Impls.Step.Keypair.pk (fst (Lazy.force step_pk)))wrap_vk.index prev_values prev_proofsin
会将
prev_proofs
解析为(prev_proofs : (local_widths, local_widths) H2.T(P).t)
。
let%bind.Promise proof = step handler ~maxes:(module Maxes) app_states prevs next_state
返回的proof结果类型为:( A_value.t, (_, Max_proofs_verified.n) Vector.t, (_, prevs_length) Vector.t, (_, prevs_length) Vector.t, _, (_, Max_proofs_verified.n) Vector.t )P.Base.Step.tPromise.t(*P.Base.Step.t结构为:*) type ( 's, 'unfinalized_proofs, 'sgs, 'bp_chals, 'dlog_me_onlys, 'prev_evals )t ={ statement :( 'unfinalized_proofs, ('s, 'sgs, 'bp_chals) Me_only.Step.t, 'dlog_me_onlys )Types.Step.Statement.t; index : int; prev_evals : 'prev_evals; proof : Tick.Proof.t}(* Me_only.Step.t结构为: *) type ('s, 'challenge_polynomial_commitments, 'bpcs) t ={ app_state : 's; challenge_polynomial_commitments : 'challenge_polynomial_commitments; old_bulletproof_challenges : 'bpcs}(* Types.Step.Statement.t *) type ('unfinalized_proofs, 'me_only, 'pass_through) t ={ proof_state : ('unfinalized_proofs, 'me_only) Proof_state.t; pass_through : 'pass_through(** The component of the proof accumulation state that is only computed on by the"wrapping" proof system, and that can be handled opaquely by any "step" circuits. *)}
将
let%bind.Promise proof = step handler ~maxes:(module Maxes) app_states prevs next_state
返回的proof.statement.passthrough进行pad_pass_throughs
重新构建新的proof,再调用Wrap.wrap将step proof包裹为wrap proof。let%map.Promise proof =Wrap.wrap ~max_proofs_verified:Max_proofs_verified.nfull_signature.maxes wrap_requests~dlog_plonk_index:wrap_vk.commitments wrap_mainA_value.to_field_elements ~step_vk~step_plonk_indices:(Lazy.force step_vks) ~wrap_domains(Impls.Wrap.Keypair.pk (fst (Lazy.force wrap_pk)))proof
附录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
- Mina中的VRF
- Mina中的delta_transition_chain_proof/delta_block_chain_proof
- Mina中的stake delegation
- Mina如何实现22KB?
- Mina中的stake_proof
- Mina中的genesis_proof
- Mina中的交易及经济白皮书
- Mina中的ledger proof
- Mina中的基于DLG的Plonk polynomial commitment scheme代码解析
- Mina中的约束系统代码解析
- Mina中的scan state代码解析
Mina中的区块证明相关推荐
- Mina中的zkApp交易snark
1. 引言 前序博客有: Mina中的支付交易snark(针对Payment交易) Mina的zkApp Mina中的树结构 --账号树 Mina中的user_command交易目前有: 1)Sign ...
- Mina中的支付交易snark
1. 引言 前序博客有: Mina的支付流程 Mina中目前的交易类型主要有: Coinbase交易:给产块者激励和手续费的交易,为内部交易. Fee_transfer交易:给snark worker ...
- Mina中的wrap snark
1. 引言 前序博客有: Mina技术白皮书 所谓wrap snark,是将Tick snark(Mina代码中称为step proof)包裹为Tock snark(Mina代码中称为wrap pro ...
- Mina中的Snark Worker
1. 引言 Mina系列博客有: Mina概览 Mina的支付流程 Mina的zkApp Mina中的Pasta(Pallas和Vesta)曲线 Mina中的Schnorr signature Min ...
- Mina中的Kimchi SNARK
1. 引言 Mina系列博客有: Mina概览 Mina的支付流程 Mina的zkApp Mina中的Pasta(Pallas和Vesta)曲线 Mina中的Schnorr signature Min ...
- Mina中的Pickles SNARK
1. 引言 Mina系列博客有: Mina概览 Mina的支付流程 Mina的zkApp Mina中的Pasta(Pallas和Vesta)曲线 Mina中的Schnorr signature 视频可 ...
- 从Jetty、Tomcat和Mina中提炼NIO构架网络服务器的经典模式(三)
2019独角兽企业重金招聘Python工程师标准>>> 从Jetty.Tomcat和Mina中提炼NIO构架网络服务器的经典模式(三) 博客分类: java 最后我们再看看NIO方面 ...
- 中芯区块链公共服务平台即将推出“企业Linktree”新功能
作者 / 杨大侠yanelis 排版 / 安慕曦 中芯区块链公共服务平台运营团队通过一年多的努力,截至2021年5月6日,已完成48685家企业信息上链.企业上链之后,通过中芯平台,无需再多头 ...
- Fabric-iot:物联网中基于区块链的访问控制系统
原文连接https://ieeexplore.ieee.org/abstract/document/8964343/ 摘要:物联网设备具有一些特殊特征,如移动性.性能受限.分布式部署等,使得传统的集中 ...
最新文章
- Nrf51822中设置128bit UUID service
- 僧多粥少?还原 OpenStack 的真实“钱景”
- 工作285:判断绑定逻辑
- C字节对齐与C++类对象内存布局
- mysql 5.6 生产my.cnf_一个生产可用的mysql参数文件my.cnf
- android 获取蓝牙设备id_【报Bug】安卓平台获取不到蓝牙设备服务列表(ios可以)...
- android底部导航栏网络请求有冲突,Android 自定义底部导航栏 CustomizeTabLayout(支持访问网络图片、本地图片)...
- Bibles_Numpy离线文档
- 传智燕青学成在线项目视频分享
- --随笔--带你轻松理解TCP中的三次握手
- 春季养生知识多 吃萝卜可预防上火
- 微信账户如何解除对第三方应用的授权
- 安卓_神坑的scrollbarSize
- 后羿 05 ‖ 九婴
- ElasticSerach7.15.2插件中文分词器(IK+pinyin)
- 基于Arduino的开源四轴飞行器开发学习板
- 发票查验平台验证码识别
- iphone功率测试软件,iPhone充电功率检测方法
- 纯html折叠文字代码,不用JS,教你只用纯HTML做出几个实用网页效果
- 虚拟机安装FreeBSD