Skip to content

Commit c1634c3

Browse files
authored
Merge pull request #16244 from MinaProtocol/al/snark-work-graphql
GraphQL: add a query to fetch specific pending snark work
2 parents c32ec46 + 405fb7b commit c1634c3

File tree

10 files changed

+281
-0
lines changed

10 files changed

+281
-0
lines changed

graphql_schema.json

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6660,6 +6660,107 @@
66606660
"enumValues": null,
66616661
"possibleTypes": null
66626662
},
6663+
{
6664+
"kind": "OBJECT",
6665+
"name": "WorkBundleSpec",
6666+
"description":
6667+
"Witnesses and statements for snark work bundles. Includes optional fees and prover public keys for ones that have proofs in the snark pool",
6668+
"fields": [
6669+
{
6670+
"name": "spec",
6671+
"description": "Snark work specification in json format",
6672+
"args": [],
6673+
"type": {
6674+
"kind": "NON_NULL",
6675+
"name": null,
6676+
"ofType": {
6677+
"kind": "SCALAR",
6678+
"name": "String",
6679+
"ofType": null
6680+
}
6681+
},
6682+
"isDeprecated": false,
6683+
"deprecationReason": null
6684+
},
6685+
{
6686+
"name": "snarkFee",
6687+
"description": "Fee if proof for the spec exists in snark pool",
6688+
"args": [],
6689+
"type": { "kind": "SCALAR", "name": "Fee", "ofType": null },
6690+
"isDeprecated": false,
6691+
"deprecationReason": null
6692+
},
6693+
{
6694+
"name": "snarkProverKey",
6695+
"description":
6696+
"Prover public key if proof for the spec exists in snark pool",
6697+
"args": [],
6698+
"type": {
6699+
"kind": "SCALAR",
6700+
"name": "PublicKey",
6701+
"ofType": null
6702+
},
6703+
"isDeprecated": false,
6704+
"deprecationReason": null
6705+
},
6706+
{
6707+
"name": "workIds",
6708+
"description": "Unique identifier for a snark work",
6709+
"args": [],
6710+
"type": {
6711+
"kind": "NON_NULL",
6712+
"name": null,
6713+
"ofType": {
6714+
"kind": "LIST",
6715+
"name": null,
6716+
"ofType": {
6717+
"kind": "NON_NULL",
6718+
"name": null,
6719+
"ofType": {
6720+
"kind": "SCALAR",
6721+
"name": "Int",
6722+
"ofType": null
6723+
}
6724+
}
6725+
}
6726+
},
6727+
"isDeprecated": false,
6728+
"deprecationReason": null
6729+
}
6730+
],
6731+
"inputFields": null,
6732+
"interfaces": [],
6733+
"enumValues": null,
6734+
"possibleTypes": null
6735+
},
6736+
{
6737+
"kind": "OBJECT",
6738+
"name": "PendingSnarkWorkSpec",
6739+
"description":
6740+
"Snark work witnesses and statements that are yet to be proven or included in blocks",
6741+
"fields": [
6742+
{
6743+
"name": "workBundleSpec",
6744+
"description": "Work bundle spec with one or two snark work",
6745+
"args": [],
6746+
"type": {
6747+
"kind": "NON_NULL",
6748+
"name": null,
6749+
"ofType": {
6750+
"kind": "OBJECT",
6751+
"name": "WorkBundleSpec",
6752+
"ofType": null
6753+
}
6754+
},
6755+
"isDeprecated": false,
6756+
"deprecationReason": null
6757+
}
6758+
],
6759+
"inputFields": null,
6760+
"interfaces": [],
6761+
"enumValues": null,
6762+
"possibleTypes": null
6763+
},
66636764
{
66646765
"kind": "OBJECT",
66656766
"name": "WorkDescription",
@@ -15282,6 +15383,58 @@
1528215383
"isDeprecated": false,
1528315384
"deprecationReason": null
1528415385
},
15386+
{
15387+
"name": "snarkWorkRange",
15388+
"description":
15389+
"Find any sequence of snark work between two indexes in all available snark work. Returns both completed and uncompleted work.",
15390+
"args": [
15391+
{
15392+
"name": "endingIndex",
15393+
"description":
15394+
"The last index to be taken from all available snark work (exclusive). If not specified or greater than the available snark work list,all elements from index [startingIndex] will be returned. An empty list will be returned if startingIndex is not a valid index or if startingIndex >= endingIndex.",
15395+
"type": {
15396+
"kind": "SCALAR",
15397+
"name": "UInt32",
15398+
"ofType": null
15399+
},
15400+
"defaultValue": null
15401+
},
15402+
{
15403+
"name": "startingIndex",
15404+
"description":
15405+
"The first index to be taken from all available snark work",
15406+
"type": {
15407+
"kind": "NON_NULL",
15408+
"name": null,
15409+
"ofType": {
15410+
"kind": "SCALAR",
15411+
"name": "UInt32",
15412+
"ofType": null
15413+
}
15414+
},
15415+
"defaultValue": null
15416+
}
15417+
],
15418+
"type": {
15419+
"kind": "NON_NULL",
15420+
"name": null,
15421+
"ofType": {
15422+
"kind": "LIST",
15423+
"name": null,
15424+
"ofType": {
15425+
"kind": "NON_NULL",
15426+
"name": null,
15427+
"ofType": {
15428+
"kind": "OBJECT",
15429+
"name": "PendingSnarkWorkSpec",
15430+
"ofType": null
15431+
}
15432+
}
15433+
}
15434+
},
15435+
"isDeprecated": false,
15436+
"deprecationReason": null
15437+
},
1528515438
{
1528615439
"name": "snarkedLedgerAccountMembership",
1528715440
"description":

src/lib/mina_graphql/mina_graphql.ml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2216,6 +2216,52 @@ module Queries = struct
22162216
Work_selector.pending_work_statements ~snark_pool ~fee_opt
22172217
snark_job_state )
22182218

2219+
let snark_work_range =
2220+
field "snarkWorkRange"
2221+
~doc:
2222+
"Find any sequence of snark work between two indexes in all available \
2223+
snark work. Returns both completed and uncompleted work."
2224+
~args:
2225+
Arg.
2226+
[ arg "startingIndex"
2227+
~doc:"The first index to be taken from all available snark work"
2228+
~typ:(non_null Types.Input.UInt32.arg_typ)
2229+
; arg "endingIndex"
2230+
~doc:
2231+
"The last index to be taken from all available snark work \
2232+
(exclusive). If not specified or greater than the available \
2233+
snark work list,all elements from index [startingIndex] will \
2234+
be returned. An empty list will be returned if startingIndex \
2235+
is not a valid index or if startingIndex >= endingIndex."
2236+
~typ:Types.Input.UInt32.arg_typ
2237+
]
2238+
~typ:(non_null @@ list @@ non_null Types.pending_work_spec)
2239+
~resolve:(fun { ctx = mina; _ } () start_idx end_idx ->
2240+
let snark_job_state = Mina_lib.snark_job_state mina in
2241+
let snark_pool = Mina_lib.snark_pool mina in
2242+
let all_work = Work_selector.all_work ~snark_pool snark_job_state in
2243+
let work_size = all_work |> List.length |> Unsigned.UInt32.of_int in
2244+
let less_than uint1 uint2 = Unsigned.UInt32.compare uint1 uint2 < 0 in
2245+
let to_bundle_specs =
2246+
List.map ~f:(fun (spec, fee_prover) ->
2247+
{ Types.Snark_work_bundle.spec; fee_prover } )
2248+
in
2249+
match end_idx with
2250+
| None when less_than start_idx work_size ->
2251+
(* drop handles case when start_idx is greater than pending work and is O(start_idx)*)
2252+
let start = Unsigned.UInt32.to_int start_idx in
2253+
List.drop all_work start |> to_bundle_specs
2254+
| Some end_idx
2255+
when less_than start_idx end_idx && less_than start_idx work_size ->
2256+
let pos = Unsigned.UInt32.to_int start_idx in
2257+
let len =
2258+
Unsigned.UInt32.(
2259+
min (sub end_idx start_idx) (sub work_size start_idx) |> to_int)
2260+
in
2261+
List.sub ~pos ~len all_work |> to_bundle_specs
2262+
| _ ->
2263+
[] )
2264+
22192265
module SnarkedLedgerMembership = struct
22202266
let resolve_membership :
22212267
mapper:(Ledger.path -> Account.t -> 'a)
@@ -2784,6 +2830,7 @@ module Queries = struct
27842830
; trust_status_all
27852831
; snark_pool
27862832
; pending_snark_work
2833+
; snark_work_range
27872834
; SnarkedLedgerMembership.snarked_ledger_account_membership
27882835
; SnarkedLedgerMembership.encoded_snarked_ledger_account_membership
27892836
; genesis_constants

src/lib/mina_graphql/types.ml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,55 @@ let pending_work =
622622
~resolve:(fun _ w -> One_or_two.to_list w)
623623
] )
624624

625+
module Snark_work_bundle = struct
626+
type t =
627+
{ spec : Work_selector.work One_or_two.t
628+
; fee_prover : (Currency.Fee.t * Public_key.Compressed.t) option
629+
}
630+
631+
let spec =
632+
obj "WorkBundleSpec"
633+
~doc:
634+
"Witnesses and statements for snark work bundles. Includes optional \
635+
fees and prover public keys for ones that have proofs in the snark \
636+
pool" ~fields:(fun _ ->
637+
[ field "spec" ~typ:(non_null string)
638+
~doc:"Snark work specification in json format"
639+
~args:Arg.[]
640+
~resolve:(fun _ { spec; _ } ->
641+
One_or_two.to_yojson Work_selector.work_to_yojson spec
642+
|> Yojson.Safe.to_string )
643+
; field "snarkFee" ~typ:fee
644+
~doc:"Fee if proof for the spec exists in snark pool"
645+
~args:Arg.[]
646+
~resolve:(fun _ w -> Option.map w.fee_prover ~f:fst)
647+
; field "snarkProverKey" ~typ:public_key
648+
~doc:"Prover public key if proof for the spec exists in snark pool"
649+
~args:Arg.[]
650+
~resolve:(fun _ w -> Option.map w.fee_prover ~f:snd)
651+
; field "workIds" ~doc:"Unique identifier for a snark work"
652+
~typ:(non_null (list (non_null int)))
653+
~args:Arg.[]
654+
~resolve:(fun _ { spec; _ } ->
655+
One_or_two.map spec ~f:(fun w ->
656+
Transaction_snark.Statement.hash
657+
(Snark_work_lib.Work.Single.Spec.statement w) )
658+
|> One_or_two.to_list )
659+
] )
660+
end
661+
662+
let pending_work_spec =
663+
obj "PendingSnarkWorkSpec"
664+
~doc:
665+
"Snark work witnesses and statements that are yet to be proven or \
666+
included in blocks" ~fields:(fun _ ->
667+
[ field "workBundleSpec"
668+
~args:Arg.[]
669+
~doc:"Work bundle spec with one or two snark work"
670+
~typ:(non_null Snark_work_bundle.spec)
671+
~resolve:(fun _ w -> w)
672+
] )
673+
625674
let state_stack =
626675
let module M = Pending_coinbase.State_stack in
627676
obj "StateStack" ~fields:(fun _ ->

src/lib/transaction_snark_work/transaction_snark_work.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,5 @@ end
122122
let forget = Fn.id
123123

124124
let fee { fee; _ } = fee
125+
126+
let prover { prover; _ } = prover

src/lib/transaction_snark_work/transaction_snark_work.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ type t = Mina_wire_types.Transaction_snark_work.V2.t =
6060

6161
val fee : t -> Fee.t
6262

63+
val prover : t -> Public_key.Compressed.t
64+
6365
val info : t -> Info.t
6466

6567
val statement : t -> Statement.t

src/lib/work_selector/inputs.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ module Test_inputs = struct
2121

2222
let fee = Fn.id
2323

24+
let prover _ = Key_gen.Sample_keypairs.genesis_winner |> fst
25+
2426
module Statement = struct
2527
type t = Transaction_snark.Statement.t One_or_two.t
2628
end

src/lib/work_selector/intf.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ module type Inputs_intf = sig
2727

2828
val fee : t -> Fee.t
2929

30+
val prover : t -> Signature_lib.Public_key.Compressed.t
31+
3032
module Statement : sig
3133
type t = Transaction_snark.Statement.t One_or_two.t
3234
end

src/lib/work_selector/work_lib.ml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,19 @@ module Make (Inputs : Intf.Inputs_intf) = struct
147147
List.filter statements ~f:(fun st ->
148148
Option.is_none (Inputs.Snark_pool.get_completed_work snark_pool st) )
149149

150+
let all_work ~snark_pool (state : State.t) =
151+
O1trace.sync_thread "work_lib_all_unseen_works" (fun () ->
152+
List.map state.available_jobs ~f:(fun job ->
153+
let statement = One_or_two.map ~f:Work_spec.statement job in
154+
let fee_prover_opt =
155+
Option.map
156+
(Inputs.Snark_pool.get_completed_work snark_pool statement)
157+
~f:(fun (p : Inputs.Transaction_snark_work.t) ->
158+
( Inputs.Transaction_snark_work.fee p
159+
, Inputs.Transaction_snark_work.prover p ) )
160+
in
161+
(job, fee_prover_opt) ) )
162+
150163
let all_completed_work ~snark_pool statements =
151164
List.filter_map statements ~f:(fun st ->
152165
Inputs.Snark_pool.get_completed_work snark_pool st )

src/lib/work_selector/work_selector.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module State = Lib.State
33

44
type work =
55
(Transaction_witness.t, Ledger_proof.t) Snark_work_lib.Work.Single.Spec.t
6+
[@@deriving yojson]
67

78
type snark_pool = Network_pool.Snark_pool.t
89

@@ -24,4 +25,6 @@ let remove = Lib.State.remove
2425

2526
let pending_work_statements = Lib.pending_work_statements
2627

28+
let all_work = Lib.all_work
29+
2730
let completed_work_statements = Lib.completed_work_statements

src/lib/work_selector/work_selector.mli

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module State :
33

44
type work =
55
(Transaction_witness.t, Ledger_proof.t) Snark_work_lib.Work.Single.Spec.t
6+
[@@deriving yojson]
67

78
type snark_pool = Network_pool.Snark_pool.t
89

@@ -32,5 +33,12 @@ val pending_work_statements :
3233
-> State.t
3334
-> Transaction_snark.Statement.t One_or_two.t list
3435

36+
val all_work :
37+
snark_pool:snark_pool
38+
-> State.t
39+
-> ( work One_or_two.t
40+
* (Currency.Fee.t * Signature_lib.Public_key.Compressed.t) option )
41+
list
42+
3543
val completed_work_statements :
3644
snark_pool:snark_pool -> State.t -> Transaction_snark_work.unchecked list

0 commit comments

Comments
 (0)