Skip to content

Commit

Permalink
Merge pull request #248 from o1-labs/feature/async-circuits
Browse files Browse the repository at this point in the history
Async circuits - bindings support
  • Loading branch information
mitschabaude authored Mar 7, 2024
2 parents 6b0be7d + 9ef2916 commit 76697e7
Show file tree
Hide file tree
Showing 11 changed files with 133,009 additions and 132,410 deletions.
2 changes: 1 addition & 1 deletion MINA_COMMIT
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
The mina commit used to generate the backends for node and web is
451e7348cf7811917d1860333d13cc8cbf70dfae
2198f591f4d00aa28c9e1d8786022a5f9204b2e5
264,891 changes: 132,731 additions & 132,160 deletions compiled/node_bindings/o1js_node.bc.cjs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion compiled/node_bindings/o1js_node.bc.map

Large diffs are not rendered by default.

274 changes: 137 additions & 137 deletions compiled/web_bindings/o1js_web.bc.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions crypto/bindings/vector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Field } from './field.js';
import { withPrefix } from './util.js';

export { FpVectorBindings, FqVectorBindings };
export { FieldVector };

type FieldVector = MlArray<Field>;

Expand Down
4 changes: 4 additions & 0 deletions js/snarky-class-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ export default [
name: 'run',
type: 'object',
},
{
name: 'constraintSystem',
type: 'object',
},
{
name: 'field',
type: 'object',
Expand Down
144 changes: 75 additions & 69 deletions ocaml/lib/pickles_bindings.ml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ type pickles_rule_js =
-> < publicOutput : Public_input.t Js.prop
; previousStatements : Statement.t array Js.prop
; shouldVerify : Boolean.var array Js.prop >
Js.t )
Js.t
Promise_js_helpers.js_promise )
Js.prop
; featureFlags : bool Pickles_types.Plonk_types.Features.t Js.prop
; proofsToVerify :
Expand Down Expand Up @@ -145,7 +146,7 @@ module Choices = struct
, 'ret_value
, 'auxiliary_var
, 'auxiliary_value )
Pickles.Inductive_rule.t )
Pickles.Inductive_rule.Promise.t )
-> ( 'var
, 'value
, 'width
Expand Down Expand Up @@ -243,67 +244,68 @@ module Choices = struct
, unit )
t =
let (Prevs prevs) = Prevs.of_rule rule in
Rule
(fun ~(self :
( Field.t array * Field.t array
, Impl.field array * Impl.field array
, 'b3
, 'b4 )
Pickles.Tag.t ) ->
let prevs = prevs ~self in
{ Pickles.Inductive_rule.identifier = Js.to_string rule##.identifier
; feature_flags = rule##.featureFlags
; prevs
; main =
(fun { public_input } ->
dummy_constraints () ;
let result = rule##.main public_input in
let public_output = result##.publicOutput in
let previous_proofs_should_verify =
should_verifys prevs result##.shouldVerify
in
let previous_public_inputs =
prev_statements ~public_input_size ~public_output_size ~self
prevs
result##.previousStatements
in
let previous_proof_statements =
let rec go :
type prev_vars prev_values widths heights.
int
-> prev_vars H1.T(Id).t
-> prev_vars H1.T(E01(Pickles.Inductive_rule.B)).t
-> ( prev_vars
, prev_values
, widths
, heights )
H4.T(Pickles.Tag).t
-> ( prev_vars
, widths )
H2.T(Pickles.Inductive_rule.Previous_proof_statement).t
=
fun i public_inputs should_verifys tags ->
match (public_inputs, should_verifys, tags) with
| [], [], [] ->
[]
| ( public_input :: public_inputs
, proof_must_verify :: should_verifys
, _tag :: tags ) ->
let proof =
Impl.exists (Impl.Typ.Internal.ref ())
~request:(fun () -> Get_prev_proof i)
in
{ public_input; proof; proof_must_verify }
:: go (i + 1) public_inputs should_verifys tags
in
go 0 previous_public_inputs previous_proofs_should_verify
prevs

(* this is called after `picklesRuleFromFunction()` and finishes the circuit *)
let finish_circuit prevs self js_result :
_ Pickles.Inductive_rule.main_return =
(* convert js rule output to pickles rule output *)
let public_output = js_result##.publicOutput in
let previous_proofs_should_verify =
should_verifys prevs js_result##.shouldVerify
in
let previous_public_inputs =
prev_statements ~public_input_size ~public_output_size ~self prevs
js_result##.previousStatements
in
let previous_proof_statements =
let rec go :
type prev_vars prev_values widths heights.
int
-> prev_vars H1.T(Id).t
-> prev_vars H1.T(E01(Pickles.Inductive_rule.B)).t
-> (prev_vars, prev_values, widths, heights) H4.T(Pickles.Tag).t
-> ( prev_vars
, widths )
H2.T(Pickles.Inductive_rule.Previous_proof_statement).t =
fun i public_inputs should_verifys tags ->
match (public_inputs, should_verifys, tags) with
| [], [], [] ->
[]
| ( public_input :: public_inputs
, proof_must_verify :: should_verifys
, _tag :: tags ) ->
let proof =
Impl.exists (Impl.Typ.Internal.ref ()) ~request:(fun () ->
Get_prev_proof i )
in
{ previous_proof_statements
; public_output
; auxiliary_output = ()
} )
} )
{ public_input; proof; proof_must_verify }
:: go (i + 1) public_inputs should_verifys tags
in
go 0 previous_public_inputs previous_proofs_should_verify prevs
in
{ previous_proof_statements; public_output; auxiliary_output = () }
in

let rule ~(self : (Statement.t, Statement.Constant.t, _, _) Pickles.Tag.t)
: _ Pickles.Inductive_rule.Promise.t =
let prevs = prevs ~self in

let main ({ public_input } : _ Pickles.Inductive_rule.main_input) =
(* add dummy constraints *)
dummy_constraints () ;
(* circuit from js *)
rule##.main public_input
|> Promise_js_helpers.of_js
|> Promise.map ~f:(finish_circuit prevs self)
in

{ identifier = Js.to_string rule##.identifier
; feature_flags = rule##.featureFlags
; prevs
; main
}
in
Rule rule
end

type ( 'var
Expand All @@ -329,7 +331,7 @@ module Choices = struct
, 'ret_value
, 'auxiliary_var
, 'auxiliary_value )
H4_6.T(Pickles.Inductive_rule).t )
H4_6.T(Pickles.Inductive_rule.Promise).t )
-> ( 'var
, 'value
, 'width
Expand Down Expand Up @@ -361,7 +363,7 @@ module Choices = struct
Inductive_rule.create ~public_input_size ~public_output_size
(Array.get js_rules index)
in
let rules ~self : _ H4_6.T(Pickles.Inductive_rule).t =
let rules ~self : _ H4_6.T(Pickles.Inductive_rule.Promise).t =
rule ~self :: rules ~self
in
get_rules (Choices rules) (index - 1)
Expand Down Expand Up @@ -663,18 +665,22 @@ let pickles_compile (choices : pickles_rule_js array)
|> Promise.map ~f:(fun x -> Js.bool (Or_error.is_ok x))
|> Promise_js_helpers.to_js
in
let get_vk () =
let vk = Pickles.Side_loaded.Verification_key.of_compiled_promise tag in
Promise.map vk ~f:(fun vk ->
let data = Pickles.Side_loaded.Verification_key.to_base64 vk in
let hash = Mina_base.Zkapp_account.digest_vk vk in
(data |> Js.string, hash) )
|> Promise_js_helpers.to_js
in
object%js
val provers = Obj.magic provers

val verify = Obj.magic verify

val tag = Obj.magic tag

method getVerificationKey =
let vk = Pickles.Side_loaded.Verification_key.of_compiled tag in
let data = Pickles.Side_loaded.Verification_key.to_base64 vk in
let hash = Mina_base.Zkapp_account.digest_vk vk in
(data |> Js.string, hash)
val getVerificationKey = get_vk
end

module Proof0 = Pickles.Proof.Make (Pickles_types.Nat.N0) (Pickles_types.Nat.N0)
Expand Down
9 changes: 7 additions & 2 deletions ocaml/lib/pickles_bindings.mli
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ type pickles_rule_js =
-> < publicOutput : Public_input.t Js.prop
; previousStatements : Statement.t array Js.prop
; shouldVerify : Boolean.var array Js.prop >
Js.t )
Js.t
Promise_js_helpers.js_promise )
Js.prop
; featureFlags : bool Pickles_types.Plonk_types.Features.t Js.prop
; proofsToVerify :
Expand Down Expand Up @@ -65,7 +66,11 @@ val pickles :
; storable : Cache.js_storable Js.optdef_prop
; overrideWrapDomain : int Js.optdef_prop >
Js.t
-> < getVerificationKey : (Js.js_string Js.t * Impl.field) Js.meth
-> < getVerificationKey :
( unit
-> (Js.js_string Js.t * Impl.field) Promise_js_helpers.js_promise
)
Js.readonly_prop
; provers : 'a Js.readonly_prop
; tag : 'b Js.readonly_prop
; verify : 'c Js.readonly_prop >
Expand Down
68 changes: 37 additions & 31 deletions ocaml/lib/snarky_bindings.ml
Original file line number Diff line number Diff line change
Expand Up @@ -35,37 +35,34 @@ module Run = struct

let in_prover_block () = As_prover.in_prover_block () |> Js.bool

let run_and_check (f : unit -> unit) =
try
Impl.run_and_check_exn (fun () ->
f () ;
fun () -> () )
with exn -> Util.raise_exn exn

let run_unchecked (f : unit -> unit) =
try
Impl.run_and_check_exn (fun () ->
Snarky_backendless.Snark0.set_eval_constraints false ;
f () ;
Snarky_backendless.Snark0.set_eval_constraints true ;
fun () -> () )
with exn -> Util.raise_exn exn

let constraint_system (main : unit -> unit) =
let cs =
Impl.constraint_system ~input_typ:Impl.Typ.unit ~return_typ:Impl.Typ.unit
(fun () -> main)
let set_eval_constraints b = Snarky_backendless.Snark0.set_eval_constraints b

let enter_constraint_system () =
let builder =
Impl.constraint_system_manual ~input_typ:Impl.Typ.unit
~return_typ:Impl.Typ.unit
in
builder.run_circuit (fun () () -> ()) ;
builder.finish_computation

let enter_generate_witness () =
let builder =
Impl.generate_witness_manual ~input_typ:Impl.Typ.unit
~return_typ:Impl.Typ.unit ()
in
object%js
val rows = Backend.R1CS_constraint_system.get_rows_len cs
builder.run_circuit (fun () () -> ()) ;
let finish () = builder.finish_computation () |> fst in
finish
end

module Constraint_system = struct
let rows cs = Backend.R1CS_constraint_system.get_rows_len cs

val digest =
Backend.R1CS_constraint_system.digest cs |> Md5.to_hex |> Js.string
let digest cs =
Backend.R1CS_constraint_system.digest cs |> Md5.to_hex |> Js.string

val json =
Backend.R1CS_constraint_system.to_json cs
|> Js.string |> Util.json_parse
end
let to_json cs =
Backend.R1CS_constraint_system.to_json cs |> Js.string |> Util.json_parse
end

module Field' = struct
Expand Down Expand Up @@ -498,11 +495,20 @@ let snarky =

val inProverBlock = in_prover_block

method runAndCheck = run_and_check
val setEvalConstraints = set_eval_constraints

val enterConstraintSystem = enter_constraint_system

val enterGenerateWitness = enter_generate_witness
end

val constraintSystem =
object%js
method rows = Constraint_system.rows

method runUnchecked = run_unchecked
method digest = Constraint_system.digest

method constraintSystem = constraint_system
method toJson = Constraint_system.to_json
end

val field =
Expand Down
20 changes: 11 additions & 9 deletions ocaml/lib/snarky_bindings.mli
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,18 @@ val snarky :
; existsVar : ((unit -> field) -> Field.t) Js.meth
; run :
< asProver : ((unit -> unit) -> unit) Js.meth
; constraintSystem :
( (unit -> unit)
-> < digest : Js.js_string Js.t Js.readonly_prop
; json : 'b Js.readonly_prop
; rows : int Js.readonly_prop >
Js.t )
Js.meth
; inProverBlock : (unit -> bool Js.t) Js.readonly_prop
; runAndCheck : ((unit -> unit) -> unit) Js.meth
; runUnchecked : ((unit -> unit) -> unit) Js.meth >
; setEvalConstraints : (bool -> unit) Js.readonly_prop
; enterConstraintSystem :
(unit -> unit -> Backend.R1CS_constraint_system.t) Js.readonly_prop
; enterGenerateWitness :
(unit -> unit -> Impl.Proof_inputs.t) Js.readonly_prop >
Js.t
Js.readonly_prop
; constraintSystem :
< rows : (Backend.R1CS_constraint_system.t -> int) Js.meth
; digest : (Backend.R1CS_constraint_system.t -> Js.js_string Js.t) Js.meth
; toJson : (Backend.R1CS_constraint_system.t -> 'a) Js.meth >
Js.t
Js.readonly_prop
; field :
Expand Down
4 changes: 4 additions & 0 deletions ocaml/lib/util.ml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ let _console_dir s : unit =
in
Js.Unsafe.(fun_call f [| inject s |])

let _console_trace s : unit =
let f = Js.Unsafe.eval_string {js|(function(s) { console.trace(s); })|js} in
Js.Unsafe.(fun_call f [| inject s |])

let raise_error s =
Js.Js_error.(raise_ @@ of_error (new%js Js.error_constr (Js.string s)))

Expand Down

0 comments on commit 76697e7

Please sign in to comment.