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.2)Minimal模块:
      • 1.1.3)In_circuit模块:
    • 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模块。
  • 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
      }``
      
  • 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模块中,实现了endoendo_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 *)}
      
  • 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中的区块证明相关推荐

  1. Mina中的zkApp交易snark

    1. 引言 前序博客有: Mina中的支付交易snark(针对Payment交易) Mina的zkApp Mina中的树结构 --账号树 Mina中的user_command交易目前有: 1)Sign ...

  2. Mina中的支付交易snark

    1. 引言 前序博客有: Mina的支付流程 Mina中目前的交易类型主要有: Coinbase交易:给产块者激励和手续费的交易,为内部交易. Fee_transfer交易:给snark worker ...

  3. Mina中的wrap snark

    1. 引言 前序博客有: Mina技术白皮书 所谓wrap snark,是将Tick snark(Mina代码中称为step proof)包裹为Tock snark(Mina代码中称为wrap pro ...

  4. Mina中的Snark Worker

    1. 引言 Mina系列博客有: Mina概览 Mina的支付流程 Mina的zkApp Mina中的Pasta(Pallas和Vesta)曲线 Mina中的Schnorr signature Min ...

  5. Mina中的Kimchi SNARK

    1. 引言 Mina系列博客有: Mina概览 Mina的支付流程 Mina的zkApp Mina中的Pasta(Pallas和Vesta)曲线 Mina中的Schnorr signature Min ...

  6. Mina中的Pickles SNARK

    1. 引言 Mina系列博客有: Mina概览 Mina的支付流程 Mina的zkApp Mina中的Pasta(Pallas和Vesta)曲线 Mina中的Schnorr signature 视频可 ...

  7. 从Jetty、Tomcat和Mina中提炼NIO构架网络服务器的经典模式(三)

    2019独角兽企业重金招聘Python工程师标准>>> 从Jetty.Tomcat和Mina中提炼NIO构架网络服务器的经典模式(三) 博客分类: java 最后我们再看看NIO方面 ...

  8. 中芯区块链公共服务平台即将推出“企业Linktree”新功能

    作者 /   杨大侠yanelis 排版 /   安慕曦 中芯区块链公共服务平台运营团队通过一年多的努力,截至2021年5月6日,已完成48685家企业信息上链.企业上链之后,通过中芯平台,无需再多头 ...

  9. Fabric-iot:物联网中基于区块链的访问控制系统

    原文连接https://ieeexplore.ieee.org/abstract/document/8964343/ 摘要:物联网设备具有一些特殊特征,如移动性.性能受限.分布式部署等,使得传统的集中 ...

最新文章

  1. Nrf51822中设置128bit UUID service
  2. 僧多粥少?还原 OpenStack 的真实“钱景”
  3. 工作285:判断绑定逻辑
  4. C字节对齐与C++类对象内存布局
  5. mysql 5.6 生产my.cnf_一个生产可用的mysql参数文件my.cnf
  6. android 获取蓝牙设备id_【报Bug】安卓平台获取不到蓝牙设备服务列表(ios可以)...
  7. android底部导航栏网络请求有冲突,Android 自定义底部导航栏 CustomizeTabLayout(支持访问网络图片、本地图片)...
  8. Bibles_Numpy离线文档
  9. 传智燕青学成在线项目视频分享
  10. --随笔--带你轻松理解TCP中的三次握手
  11. 春季养生知识多 吃萝卜可预防上火
  12. 微信账户如何解除对第三方应用的授权
  13. 安卓_神坑的scrollbarSize
  14. 后羿 05 ‖ 九婴
  15. ElasticSerach7.15.2插件中文分词器(IK+pinyin)
  16. 基于Arduino的开源四轴飞行器开发学习板
  17. 发票查验平台验证码识别
  18. iphone功率测试软件,iPhone充电功率检测方法
  19. 纯html折叠文字代码,不用JS,教你只用纯HTML做出几个实用网页效果
  20. 虚拟机安装FreeBSD

热门文章

  1. 物联网设备预警解决方案
  2. Android刷机 概念整理
  3. 用Scrapy爬取王者皮肤海报~
  4. 【PAT甲级】A1101-A1155刷题记录
  5. [英语语法]词法之副词
  6. 天天写 SQL,这些神奇的特性你知道吗?
  7. 酷派大神f1,酷派大神f2 无法打log的解决方法。
  8. 深度强化学习系列: 最全深度强化学习资料
  9. HUE--hive函数大全
  10. 构建船舶航海用品B2B电商交易平台,健壮产业生态