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.t

type 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}, creating
            a 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, then
          this 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 shown
          in 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 for
    finalizing the deferred-values in a wrap proof of that branch. *)

(** Inside the circuit, we will represent a value of this type
    as a sequence of 2 bits:
    00: N0
    10: N1
    11: N2 *)
module Proofs_verified = struct
    module V1 = struct
      type t = N0 | N1 | N2
  • Domain_log2:type t为char类型,占8个bit。
module Domain_log2 = struct
    module V1 = struct
      type 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_verified
   Next 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.S
             with type statement = 'a_value
              and type max_proofs_verified = 'max_proofs_verified
              and type prev_values = 'prev_values
              and type local_signature = 'local_widths
              and 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_only
    module 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 the
              circuit 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 know
            the 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 = struct
      module Bulletproof = struct
        [%%versioned
        module Stable = struct
          module V1 = struct
            type ('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_only
          module 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 did
            not recursively verify. In that case, when we expose the unfinalized bits, we need
            to communicate that it's OK if those bits do not "finalize". That's what this boolean
            is 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.t
      Wrap_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.t

module With_data = struct
  type ('s, 'mlmb, 'w) t = ('s, 'mlmb, 'w) with_data
end

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.t
            Bulletproof_challenge.t
            Step_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.t
          Step_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.t
          Step_bp_vec.t
          Max_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 = struct
        type t =
          ( ( Tock.Inner_curve.Affine.Stable.V1.t
            , Reduced_me_only.Wrap.Challenges_vector.Stable.V2.t
              Side_loaded_verification_key.Width.Max_vector.Stable.V1.t )
            Types.Wrap.Proof_state.Me_only.Stable.V1.t
          , ( unit
            , Tock.Curve.Affine.t
              Side_loaded_verification_key.Width.Max_at_most.Stable.V1.t
            , Limb_vector.Constant.Hex64.Stable.V1.t Vector.Vector_2.Stable.V1.t
              Scalar_challenge.Stable.V2.t
              Bulletproof_challenge.Stable.V1.t
              Step_bp_vec.Stable.V1.t
              Side_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 in
  let back x = create x in
  Snarky_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 : sig
      type t

      val to_field_elements : t -> Tick.Field.t array
    end)
    (Max_proofs_verified : Nat.Add.Intf_transparent)

其中的模块E对应为Tock域:

module E = struct
    type t = Tock.Field.t array Plonk_types.Evals.t Double.t * Tock.Field.t
  end

(* 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 = struct
    include Plonk_checks
    module 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 by
               a 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_values
      local_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.S
          with type length = Max_proofs_verified.n
           and 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.t
      Promise.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.t
          Step_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.t
                  Bulletproof_challenge.t
                  Step_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.t
              Step_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.t
                Types.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 the
            circuit 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) in
      match 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 (struct
                 let constraint_constants = constraint_constants

                 let proof_level = proof_level
               end)

               module B = Blockchain_snark.Blockchain_snark_state.Make (struct
                 let tag = T.tag

                 let constraint_constants = constraint_constants

                 let proof_level = proof_level
               end)

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" in
              Run.run_checked
                (
                  let () = Printf.printf "ZYD before step in run_checked\n" in
                  step ~proof_level ~constraint_constants ~logger:(Logger.create ())
                   [ x1; x2 ] x )
            in
            let () = 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 = struct
      type 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_state
    
    let step handler prev_values prev_proofs next_state =
          let wrap_vk = Lazy.force wrap_vk in
          S.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_proofs
        in
    
    会将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.t
      Promise.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.n
              full_signature.maxes wrap_requests
              ~dlog_plonk_index:wrap_vk.commitments wrap_main
              A_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系列博客有:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值