1. 引言
前序博客见:
- Mina中的Scan State
(* prover/prover.ml中有: *)
module Extend_blockchain_input = struct
[%%versioned
module Stable = struct
[@@@no_toplevel_latest_type]
module V2 = struct
type t =
{ chain : Blockchain.Stable.V2.t
; next_state : Protocol_state.Value.Stable.V2.t
; block : Snark_transition.Value.Stable.V2.t
; ledger_proof : Ledger_proof.Stable.V2.t option
; prover_state : Consensus.Data.Prover_state.Stable.V2.t
; pending_coinbase : Pending_coinbase_witness.Stable.V2.t
}
(* ledger_proof/ledger_proof.ml中有: *)
module Prod : Ledger_proof_intf.S with type t = Transaction_snark.t = struct
[%%versioned
module Stable = struct
module V2 = struct
type t = Transaction_snark.Stable.V2.t
(* transaction_snark/transaction_snark.ml中有: *)
module Stable = struct
module V2 = struct
type t =
{ statement : Statement.With_sok.Stable.V2.t; proof : Proof.Stable.V2.t }
module With_sok = struct
[%%versioned
module Stable = struct
module V2 = struct
type t =
( Frozen_ledger_hash.Stable.V1.t
, Currency.Amount.Stable.V1.t
, Pending_coinbase.Stack_versioned.Stable.V1.t
, Fee_excess.Stable.V1.t
, Sok_message.Digest.Stable.V1.t (* 为string类型 *)
, Local_state.Stable.V1.t )
module Proof = struct
[%%versioned
module Stable = struct
module V2 = struct
type t = Pickles.Proof.Branching_2.Stable.V2.t
Verifier端验证transaction_snark的输入为 [ledger_proof, sok_message] 数组:【其中sok_digest=BLAKE2_HASH(sok_message)】
val verify_transaction_snarks :
t
-> (ledger_proof * Mina_base.Sok_message.t) list
-> bool Or_error.t Deferred.t
(* Mina_base.Sok_message.t结构定义为: *)
module Stable = struct
module V1 = struct
type t =
{ fee : Currency.Fee.Stable.V1.t
; prover : Public_key.Compressed.Stable.V1.t
}
(* verify_transaction_snarks函数实际实现为: *)
let verify_transaction_snarks ts =
match Or_error.try_with (fun () -> T.verify ts) with
| Ok result ->
result
| Error e ->
[%log error]
~metadata:[ ("error", Error_json.error_to_yojson e) ]
"Verifier threw an exception while verifying transaction \
snark" ;
failwith "Verifier crashed"
let verify ts =
if
List.for_all ts ~f:(fun (p, m) -> (* 【其中sok_digest=BLAKE2_HASH(sok_message)】 *)
Sok_message.Digest.equal (Sok_message.digest m) p.statement.sok_digest)
then
Proof.verify
(List.map ts ~f:(fun ({ statement; proof }, _) -> (statement, proof)))
else Async.return false
(* Pickles Proof中的verify为: *)
let verify (type a n) (max_branching : (module Nat.Intf with type n = n))
(a_value : (module Intf.Statement_value with type t = a))
(key : Verification_key.t) (ts : (a * (n, n) Proof.t) list) =
verify_heterogenous
(List.map ts ~f:(fun (x, p) ->
Instance.T (max_branching, a_value, key, x, p)))
let verify_heterogenous (ts : Instance.t list) =
let module Plonk = Types.Wrap.Proof_state.Deferred_values.Plonk in
let module Tick_field = Backend.Tick.Field in
let tick_field : _ Plonk_checks.field = (module Tick_field) in
let check, result =
let r = ref [] in
let result () =
match !r with
| [] ->
Ok ()
| _ ->
Error
(String.concat ~sep:"\n"
(List.map !r ~f:(fun lab -> Lazy.force lab)))
in
((fun (lab, b) -> if not b then r := lab :: !r), result)
in
let in_circuit_plonks =
List.map ts
~f:(fun
(T
( _max_branching
, _statement
, key
, app_state
, T
{ statement
(* TODO
; prev_x_hat = (x_hat1, _) as prev_x_hat
*)
; prev_evals = evals
} ))
->
Timer.start __LOC__ ;
let statement =
{ statement with
pass_through = { statement.pass_through with app_state }
}
in
let open Types.Wrap.Proof_state in
let sc =
SC.to_field_constant tick_field ~endo:Endo.Wrap_inner_curve.scalar
in
Timer.clock __LOC__ ;
let { Deferred_values.xi
; plonk = plonk0
; combined_inner_product
; which_branch
; bulletproof_challenges
} =
Deferred_values.map_challenges ~f:Challenge.Constant.to_tick_field
~scalar:sc statement.proof_state.deferred_values
in
let zeta = sc plonk0.zeta in
let alpha = sc plonk0.alpha in
let step_domains = key.step_domains.(Index.to_int which_branch) in
let w =
Tick.Field.domain_generator
~log2_size:(Domain.log2_size step_domains.h)
in
let zetaw = Tick.Field.mul zeta w in
let tick_plonk_minimal :
_ Composition_types.Wrap.Proof_state.Deferred_values.Plonk.Minimal.t
=
let chal = Challenge.Constant.to_tick_field in
{ zeta; alpha; beta = chal plonk0.beta; gamma = chal plonk0.gamma }
in
let tick_combined_evals =
Plonk_checks.evals_of_split_evals
(module Tick.Field)
(Double.map evals.evals ~f:(fun e -> e.evals))
~rounds:(Nat.to_int Tick.Rounds.n) ~zeta ~zetaw
in
let tick_domain =
Plonk_checks.domain
(module Tick.Field)
step_domains.h ~shifts:Common.tick_shifts
~domain_generator:Backend.Tick.Field.domain_generator
in
let tick_env =
Plonk_checks.scalars_env
(module Tick.Field)
~endo:Endo.Step_inner_curve.base ~mds:Tick_field_sponge.params.mds
~srs_length_log2:Common.Max_degree.step_log2
~field_of_hex:(fun s ->
Kimchi_pasta.Pasta.Bigint256.of_hex_string s
|> Kimchi_pasta.Pasta.Fp.of_bigint)
~domain:tick_domain tick_plonk_minimal tick_combined_evals
in
let plonk =
let p =
Plonk_checks.Type1.derive_plonk
(module Tick.Field)
~shift:Shifts.tick1 ~env:tick_env tick_plonk_minimal
tick_combined_evals
in
{ p with
zeta = plonk0.zeta
; alpha = plonk0.alpha
; beta = plonk0.beta
; gamma = plonk0.gamma
}
in
Timer.clock __LOC__ ;
let absorb, squeeze =
let open Tick_field_sponge.Bits in
let sponge =
let s = create Tick_field_sponge.params in
absorb s
(Digest.Constant.to_tick_field
statement.proof_state.sponge_digest_before_evaluations) ;
s
in
let squeeze () =
let underlying =
Challenge.Constant.of_bits
(squeeze sponge ~length:Challenge.Constant.length)
in
sc (Scalar_challenge.create underlying)
in
(absorb sponge, squeeze)
in
let absorb_evals
{ Plonk_types.All_evals.With_public_input.public_input = x_hat
; evals = e
} =
let xs, ys = Plonk_types.Evals.to_vectors e in
List.iter
Vector.([| x_hat |] :: (to_list xs @ to_list ys))
~f:(Array.iter ~f:absorb)
in
Double.(iter ~f:absorb_evals evals.evals) ;
absorb evals.ft_eval1 ;
let xi_actual = squeeze () in
let r_actual = squeeze () in
Timer.clock __LOC__ ;
(* TODO: The deferred values "bulletproof_challenges" should get routed
into a "batch dlog Tick acc verifier" *)
let actual_branching =
Vector.length statement.pass_through.old_bulletproof_challenges
in
Timer.clock __LOC__ ;
let combined_inner_product_actual =
Wrap.combined_inner_product ~env:tick_env ~plonk:tick_plonk_minimal
~domain:tick_domain ~ft_eval1:evals.ft_eval1
~actual_branching:(Nat.Add.create actual_branching)
(Double.map evals.evals ~f:(fun e -> e.evals))
~x_hat:(Double.map evals.evals ~f:(fun e -> e.public_input))
~old_bulletproof_challenges:
(Vector.map ~f:Ipa.Step.compute_challenges
statement.pass_through.old_bulletproof_challenges)
~r:r_actual ~xi ~zeta ~zetaw ~step_branch_domains:step_domains
in
let check_eq lab x y =
check
( lazy
(sprintf
!"%s: %{sexp:Tick_field.t} != %{sexp:Tick_field.t}"
lab x y)
, Tick_field.equal x y )
in
Timer.clock __LOC__ ;
Timer.clock __LOC__ ;
List.iter
~f:(fun (s, x, y) -> check_eq s x y)
(* Both these values can actually be omitted from the proof on the wire since we recompute them
anyway. *)
[ ("xi", xi, xi_actual)
; ( "combined_inner_product"
, Shifted_value.Type1.to_field
(module Tick.Field)
combined_inner_product ~shift:Shifts.tick1
, combined_inner_product_actual )
] ;
plonk)
in
let open Backend.Tock.Proof in
let open Promise.Let_syntax in
let%bind accumulator_check =
Ipa.Step.accumulator_check
(List.map ts ~f:(fun (T (_, _, _, _, T t)) ->
( t.statement.proof_state.me_only.sg
, Ipa.Step.compute_challenges
t.statement.proof_state.deferred_values.bulletproof_challenges )))
in
Common.time "batch_step_dlog_check" (fun () ->
check (lazy "batch_step_dlog_check", accumulator_check)) ;
let%map dlog_check =
batch_verify
(List.map2_exn ts in_circuit_plonks
~f:(fun
(T
((module Max_branching), (module A_value), key, app_state, T t))
plonk
->
let prepared_statement : _ Types.Wrap.Statement.In_circuit.t =
{ pass_through =
Common.hash_step_me_only ~app_state:A_value.to_field_elements
(Reduced_me_only.Step.prepare
~dlog_plonk_index:key.commitments
{ t.statement.pass_through with app_state })
; proof_state =
{ t.statement.proof_state with
deferred_values =
{ t.statement.proof_state.deferred_values with plonk }
; me_only =
Common.hash_dlog_me_only Max_branching.n
(Reduced_me_only.Wrap.prepare
t.statement.proof_state.me_only)
}
}
in
let input =
tock_unpadded_public_input_of_statement prepared_statement
in
( key.index
, t.proof
, input
, Some
(Vector.to_list
(Vector.map2
~f:(fun g cs ->
{ Challenge_polynomial.challenges =
Vector.to_array (Ipa.Wrap.compute_challenges cs)
; commitment = g
})
(Vector.extend_exn t.statement.pass_through.sg
Max_branching.n
(Lazy.force Dummy.Ipa.Wrap.sg))
t.statement.proof_state.me_only.old_bulletproof_challenges))
)))
in
Common.time "dlog_check" (fun () -> check (lazy "dlog_check", dlog_check)) ;
match result () with
| Ok () ->
true
| Error e ->
eprintf !"bad verify: %s\n%!" e ;
false
1.1 Mina交易结构
当前Mina中支持的交易类型有:
let to_preunion (t : Transaction.t) =
match t with
| Command (Signed_command x) ->
`Transaction (Transaction.Command x)
| Fee_transfer x ->
`Transaction (Fee_transfer x)
| Coinbase x ->
`Transaction (Coinbase x)
| Command (Parties x) ->
`Parties x
Mina中的交易失败类型有:
module Failure = struct
[%%versioned
module Stable = struct
module V2 = struct
type t =
| Predicate [@value 1]
| Source_not_present
| Receiver_not_present
| Amount_insufficient_to_create_account
| Cannot_pay_creation_fee_in_token
| Source_insufficient_balance
| Source_minimum_balance_violation
| Receiver_already_exists
| Not_token_owner
| Mismatched_token_permissions
| Overflow
| Signed_command_on_zkapp_account
| Zkapp_account_not_present
| Update_not_permitted_balance
| Update_not_permitted_timing_existing_account
| Update_not_permitted_delegate
| Update_not_permitted_app_state
| Update_not_permitted_verification_key
| Update_not_permitted_sequence_state
| Update_not_permitted_zkapp_uri
| Update_not_permitted_token_symbol
| Update_not_permitted_permissions
| Update_not_permitted_nonce
| Update_not_permitted_voting_for
| Parties_replay_check_failed
| Fee_payer_nonce_must_increase
| Account_precondition_unsatisfied
| Protocol_state_precondition_unsatisfied
| Incorrect_nonce
| Invalid_fee_excess
transaction结构为:
(* transaction结构为: *)
module Stable = struct
module V2 = struct
type t = User_command.Stable.V2.t Poly.Stable.V2.t
module Poly = struct
[%%versioned
module Stable = struct
module V2 = struct
type 'command t = (* 分为:普通的用户签名交易、Fee transfer、coinbase *)
| Command of 'command
| Fee_transfer of Fee_transfer.Stable.V2.t
| Coinbase of Coinbase.Stable.V1.t
(* User_command结构为: *)
module Stable = struct
module V2 = struct
type t = (Signed_command.Stable.V2.t, Parties.Stable.V1.t) Poly.Stable.V2.t
(* Signed_command结构为: *)
module Stable = struct
module V2 = struct
type t =
( Payload.Stable.V2.t
, Public_key.Stable.V1.t
, Signature.Stable.V1.t )
Poly.Stable.V1.t
(* Payload结构为: *)
module Stable = struct
module V2 = struct
type t = (Common.Stable.V2.t, Body.Stable.V2.t) Poly.Stable.V1.t
(* Public_key结构为: *)
module Stable = struct
module V1 = struct
type t = Field.t * Field.t
(* Signature结构为: *)
module Stable = struct
module V1 = struct
type t = (Field.t, Inner_curve.Scalar.t) Signature_poly.Stable.V1.t
(* Common结构为: *)
type t =
( Currency.Fee.Stable.V1.t
, Public_key.Compressed.Stable.V1.t
, Account_nonce.Stable.V1.t
, Global_slot.Stable.V1.t
, Memo.Stable.V1.t ) (* 为string *)
Poly.Stable.V2.t
(* Body结构为:根据是普通支付还是质押委托交易,body有所不同 *)
module Stable = struct
module V2 = struct
type t = Binable_arg.Stable.V2.t =
| Payment of Payment_payload.Stable.V2.t
| Stake_delegation of Stake_delegation.Stable.V1.t
transaction_witness结构为:
(* transaction_witness为: *)
module Stable = struct
module V2 = struct
type t =
{ transaction : Mina_transaction.Transaction.Stable.V2.t
; ledger : Mina_ledger.Sparse_ledger.Stable.V2.t
; protocol_state_body : Mina_state.Protocol_state.Body.Value.Stable.V2.t
; init_stack : Mina_base.Pending_coinbase.Stack_versioned.Stable.V1.t
; status : Mina_base.Transaction_status.Stable.V2.t
}
(* Mina_ledger.Sparse_ledger结构为: *)
module Stable = struct
module V2 = struct
type t =
( Ledger_hash.Stable.V1.t (* 为Field.t,Tick曲线的 *)
, Account_id.Stable.V2.t
, Account.Stable.V2.t )
Sparse_ledger_lib.Sparse_ledger.T.Stable.V2.t
(* account_id结构为: *)
module Stable = struct
module V2 = struct (* 为压缩公钥 和 Pickles.Backend.Tick.Field.Stable.V1.t *)
type t = Public_key.Compressed.Stable.V1.t * Digest.Stable.V1.t
(* account结构为: *)
type t =
( Public_key.Compressed.Stable.V1.t
, Token_id.Stable.V1.t
, Token_permissions.Stable.V1.t
, Token_symbol.Stable.V1.t
, Balance.Stable.V1.t
, Nonce.Stable.V1.t
, Receipt.Chain_hash.Stable.V1.t
, Public_key.Compressed.Stable.V1.t option
, State_hash.Stable.V1.t
, Timing.Stable.V1.t
, Permissions.Stable.V2.t
, Zkapp_account.Stable.V2.t option
, string )
(* TODO: Cache the digest of this? *)
Poly.Stable.V2.t
(* Sparse_ledger_lib.Sparse_ledger结构为: *)
type ('hash, 'key, 'account) t =
{ indexes : ('key * int) list
; depth : int
; tree : ('hash, 'account) Tree.Stable.V1.t
}
(* Sparse_ledger中的Tree为account tree,其结构为: *)
type ('hash, 'key, 'account) t =
{ indexes : ('key * int) list
; depth : int
; tree : ('hash, 'account) Tree.Stable.V1.t
}
2. ledger_proof由snark worker生成
snark worker启动时,其选择的proof_level有3种状态:
- full
- check
- none
module Proof_level = struct
type t = Full | Check | None
module Single = struct
module Spec = struct
[%%versioned
module Stable = struct
[@@@no_toplevel_latest_type]
module V2 = struct
type ('witness, 'ledger_proof) t =
| Transition of Transaction_snark.Statement.Stable.V2.t * 'witness
| Merge of
Transaction_snark.Statement.Stable.V2.t
* 'ledger_proof
* 'ledger_proof
(* bin_io is for uptime service SNARK worker *)
type single_spec =
( Transaction_witness.Stable.Latest.t
, Transaction_snark.Stable.Latest.t )
Snark_work_lib.Work.Single.Spec.Stable.Latest.t
ledger_proof由snark worker生成,scan state中的tree中有base snark和merge snark,根据交易类型的不同,采取不同的生成snark proof和ledger proof方案:
(* snark_worker/prod.ml中生成ledger proof和snark proof的流程为: *)
let perform_single ({ m; cache; proof_level } : Worker_state.t) ~message =
.......
match proof_level with
| Genesis_constants.Proof_level.Full -> (
........
match Cache.find cache statement with
| Some proof ->
Deferred.Or_error.return (proof, Time.Span.zero)
| None -> (
match single with
| Work.Single.Spec.Transition (input, (w : Transaction_witness.t))
->
...........
match w.transaction with
| Command (Parties parties) -> (
.........
let log_base_snark f ~statement ~spec ~all_inputs =
match%map.Deferred
Deferred.Or_error.try_with (fun () ->
f ~statement ~spec)
let log_merge_snark ~sok_digest prev curr ~all_inputs
=
match%map.Deferred
M.merge ~sok_digest prev curr
........
| _ ->
let%bind t =
Deferred.return
@@
(* Validate the received transaction *)
match w.transaction with
| Command (Signed_command cmd) -> (
match Signed_command.check cmd with
| Some cmd ->
( Ok (Command (Signed_command cmd))
: Transaction.Valid.t Or_error.t )
| None ->
Or_error.errorf
"Command has an invalid signature" )
| Command (Parties _) ->
assert false
| Fee_transfer ft ->
Ok (Fee_transfer ft)
| Coinbase cb ->
Ok (Coinbase cb)
in
Deferred.Or_error.try_with ~here:[%here] (fun () ->
M.of_non_parties_transaction
~statement:{ input with sok_digest }
{ Transaction_protocol_state.Poly.transaction =
t
; block_data = w.protocol_state_body
}
~init_stack:w.init_stack
(unstage
(Mina_ledger.Sparse_ledger.handler w.ledger))))
..........
)
| Merge (_, proof1, proof2) ->
process (fun () -> M.merge ~sok_digest proof1 proof2) )
........
)
| Check | None ->
(* Use a dummy proof. *)
let stmt =
match single with
| Work.Single.Spec.Transition (stmt, _) ->
stmt
| Merge (stmt, _, _) ->
stmt
in
Deferred.Or_error.return
@@ ( Transaction_snark.create ~statement:{ stmt with sok_digest }
~proof:Proof.transaction_dummy
, Time.Span.zero )
- snark worker:
main
->perform
->perform_single
,会将base snark或merge snark proof放入Snark_work_lib.Work.Result.proofs中,并提交到snark pool中? - 产块者:
generate_next_state
->Staged_ledger.apply_diff_unchecked
->apply_diff
->fill_work_and_enqueue_transactions
->fill_in_transaction_snark_work
->completed_work_to_scanable_work
来将snark proof添加到区块内。
|> Deferred.Or_error.map ~f:(function
| `One (proof1, metrics1) ->
{ Snark_work_lib.Work.Result.proofs = `One proof1
; metrics = `One metrics1
; spec
; prover = public_key
}
| `Two ((proof1, metrics1), (proof2, metrics2)) ->
{ Snark_work_lib.Work.Result.proofs = `Two (proof1, proof2)
; metrics = `Two (metrics1, metrics2)
; spec
; prover = public_key
})
2.1 Parties交易proof生成
所谓Parties交易,是指为支持zkApps智能合约创建的交易类型。 对于Parties交易类型,生成proof的方案为:【分为log_base_snark
和log_merge_snark
】
match witnesses_specs_stmts with
| [] ->
Deferred.Or_error.error_string
"no witnesses generated"
| (witness, spec, stmt, snapp_statement) :: rest as
inputs ->
let%bind (p1 : Ledger_proof.t) =
log_base_snark
~statement:{ stmt with sok_digest } ~spec
~all_inputs:inputs
(M.of_parties_segment_exn ~snapp_statement
~witness)
in
let%map (p : Ledger_proof.t) =
Deferred.List.fold ~init:(Ok p1) rest
~f:(fun
acc
(witness, spec, stmt, snapp_statement)
->
let%bind (prev : Ledger_proof.t) =
Deferred.return acc
in
let%bind (curr : Ledger_proof.t) =
log_base_snark
~statement:{ stmt with sok_digest }
~spec ~all_inputs:inputs
(M.of_parties_segment_exn
~snapp_statement ~witness)
in
log_merge_snark ~sok_digest prev curr
~all_inputs:inputs)
对于Parties交易,会调用Pickles proof system相关证明接口:
let of_parties_segment_exn ~statement ~snapp_statement ~witness
~(spec : Parties_segment.Basic.t) : t Async.Deferred.t =
Base.Parties_snark.witness := Some witness ;
let res =
match spec with
| Opt_signed ->
opt_signed [] statement
| Opt_signed_unsigned ->
opt_signed_unsigned [] statement
| Opt_signed_opt_signed ->
opt_signed_opt_signed [] statement
| Proved -> (
match snapp_proof_data ~snapp_statement ~witness with
| None ->
failwith "of_parties_segment: Expected exactly one proof"
| Some (s, p, v, tag) ->
(* TODO: We should not have to pass the statement in here. *)
proved
( Pickles.Side_loaded.in_prover (Base.side_loaded tag) v.data ;
[ (s, p) ] )
statement )
in
let open Async in
let%map proof = res in
Base.Parties_snark.witness := None ;
{ proof; statement }
2.2 非Parties交易proof生成
非Parties交易是指用户签名交易、给snark worker的fee交易 以及 给产块者奖励的coinbase交易。
match w.transaction with
| Command (Signed_command cmd) -> (
match Signed_command.check cmd with
| Some cmd ->
( Ok (Command (Signed_command cmd))
: Transaction.Valid.t Or_error.t )
| None ->
Or_error.errorf
"Command has an invalid signature" )
| Command (Parties _) ->
assert false
| Fee_transfer ft ->
Ok (Fee_transfer ft)
| Coinbase cb ->
Ok (Coinbase cb)
in
Deferred.Or_error.try_with ~here:[%here] (fun () ->
M.of_non_parties_transaction
~statement:{ input with sok_digest }
{ Transaction_protocol_state.Poly.transaction =
t
; block_data = w.protocol_state_body
}
~init_stack:w.init_stack
(unstage
(Mina_ledger.Sparse_ledger.handler w.ledger)))
非Parties交易生成proof方案为:
let of_non_parties_transaction ~statement ~init_stack transaction_in_block
handler =
let transaction : Transaction.t =
Transaction.forget
(Transaction_protocol_state.transaction transaction_in_block)
in
let state_body =
Transaction_protocol_state.block_data transaction_in_block
in
match to_preunion transaction with
| `Parties _ ->
failwith "Called Non-parties transaction with parties transaction"
| `Transaction t ->
of_transaction_union ~statement ~init_stack
(Transaction_union.of_transaction t)
state_body handler
let of_transaction_union ~statement ~init_stack transaction state_body handler
=
let open Async in
let%map proof =
base []
~handler:
(Base.transaction_union_handler handler transaction state_body
init_stack)
statement
in
{ statement; proof }
let transaction_union_handler handler (transaction : Transaction_union.t)
(state_body : Mina_state.Protocol_state.Body.Value.t)
(init_stack : Pending_coinbase.Stack.t) :
Snarky_backendless.Request.request -> _ =
fun (With { request; respond } as r) ->
match request with
| Transaction ->
respond (Provide transaction)
| State_body ->
respond (Provide state_body)
| Init_stack ->
respond (Provide init_stack)
| _ ->
handler r
of_transaction_union
函数中的base会调用Pickles proof system相关证明接口:
let system ~proof_level ~constraint_constants =
time "Transaction_snark.system" (fun () ->
Pickles.compile ~cache:Cache_dir.cache
(module Statement.With_sok.Checked)
(module Statement.With_sok)
~typ:Statement.With_sok.typ
~branches:(module Nat.N6)
~max_branching:(module Nat.N2)
~name:"transaction-snark"
~constraint_constants:
(Genesis_constants.Constraint_constants.to_snark_keys_header
constraint_constants)
~choices:(fun ~self ->
let parties x =
Base.Parties_snark.rule ~constraint_constants ~proof_level x
in
[ Base.rule ~constraint_constants
; Merge.rule ~proof_level self
; parties Opt_signed_unsigned
; parties Opt_signed_opt_signed
; parties Opt_signed
; parties Proved
]))
let compile ?self ?cache ?disk_keys a_var a_value ~typ ~branches ~max_branching
~name ~constraint_constants ~choices =
let self, cache_handle, proof_module, provers =
compile_promise ?self ?cache ?disk_keys a_var a_value ~typ ~branches
~max_branching ~name ~constraint_constants ~choices
in
let rec adjust_provers :
type a1 a2 a3 s1 s2_inner.
(a1, a2, a3, s1, s2_inner Promise.t) H3_2.T(Prover).t
-> (a1, a2, a3, s1, s2_inner Deferred.t) H3_2.T(Prover).t = function
| [] ->
[]
| prover :: tl ->
(fun ?handler stmt_with_proof public_input ->
Promise.to_deferred (prover ?handler stmt_with_proof public_input))
:: adjust_provers tl
in
(self, cache_handle, proof_module, adjust_provers provers)
附录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中的交易及经济白皮书