diff --git a/graphql_schema.json b/graphql_schema.json index 95c11fb176d..78fe292b1c0 100644 --- a/graphql_schema.json +++ b/graphql_schema.json @@ -6470,6 +6470,57 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "EncodedAccount", + "description": null, + "fields": [ + { + "name": "account", + "description": "Base64 encoded account as binable wire type", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "merklePath", + "description": "Membership proof in the snarked ledger", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "MerklePathElement", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "INPUT_OBJECT", "name": "AccountInput", @@ -15293,6 +15344,68 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "encodedSnarkedLedgerAccountMembership", + "description": + "obtain a membership proof for an account in the snarked ledger along with the accounts full information encoded as base64 binable type", + "args": [ + { + "name": "stateHash", + "description": "Hash of the snarked ledger to check", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "accountInfos", + "description": "Token id of the account to check", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "AccountInput", + "ofType": null + } + } + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EncodedAccount", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "genesisConstants", "description": diff --git a/src/lib/mina_graphql/mina_graphql.ml b/src/lib/mina_graphql/mina_graphql.ml index 0783e1351a8..e5131b794a0 100644 --- a/src/lib/mina_graphql/mina_graphql.ml +++ b/src/lib/mina_graphql/mina_graphql.ml @@ -2192,61 +2192,85 @@ module Queries = struct let (module S) = Mina_lib.work_selection_method mina in S.pending_work_statements ~snark_pool ~fee_opt snark_job_state ) - let snarked_ledger_account_membership = - io_field "snarkedLedgerAccountMembership" - ~doc: - "obtain a membership proof for an account in the snarked ledger along \ - with the account's balance, timing information, and nonce" - ~args: - Arg. - [ arg "accountInfos" ~doc:"Token id of the account to check" - ~typ:(non_null (list (non_null Types.Input.AccountInfo.arg_typ))) - ; arg "stateHash" ~doc:"Hash of the snarked ledger to check" - ~typ:(non_null string) - ] - ~typ:(non_null (list (non_null Types.SnarkedLedgerMembership.obj))) - ~resolve:(fun { ctx = mina; _ } () account_infos state_hash -> - let open Deferred.Let_syntax in - let state_hash = State_hash.of_base58_check_exn state_hash in - let%bind ledger = - Mina_lib.get_snarked_ledger_full mina (Some state_hash) - in - let ledger = - match ledger with - | Ok ledger -> - ledger - | Error err -> - raise - (Failure - ("Failed to get snarked ledger: " ^ Error.to_string_hum err) - ) - in - let%map memberships = - Deferred.List.map account_infos ~f:(fun (pk, token) -> - let token = Option.value ~default:Token_id.default token in - let account_id = Account_id.create pk token in - let location = Ledger.location_of_account ledger account_id in - match location with - | None -> - raise (Failure "Account not found in snarked ledger") - | Some location -> ( - let account = Ledger.get ledger location in - match account with - | None -> - raise (Failure "Account not found in snarked ledger") - | Some account -> - let account_balance = account.balance in - let timing_info = account.timing in - let nonce = account.nonce in - let proof = Ledger.merkle_path ledger location in - { Types.SnarkedLedgerMembership.account_balance - ; timing_info - ; nonce - ; proof - } - |> Deferred.return ) ) - in - Ok memberships ) + module SnarkedLedgerMembership = struct + let resolve_membership : + mapper:(Ledger.path -> Account.t -> 'a) + -> Mina_lib.t resolve_info + -> unit + -> (Account.key * Token_id.t option) list + -> string + -> ('a list, string) result Io.t = + fun ~mapper { ctx = mina; _ } () account_infos state_hash -> + let open Deferred.Let_syntax in + let state_hash = State_hash.of_base58_check_exn state_hash in + let%bind ledger = + Mina_lib.get_snarked_ledger_full mina (Some state_hash) + in + let ledger = + match ledger with + | Ok ledger -> + ledger + | Error err -> + raise + (Failure + ("Failed to get snarked ledger: " ^ Error.to_string_hum err) ) + in + let%map memberships = + Deferred.List.map account_infos ~f:(fun (pk, token) -> + let token = Option.value ~default:Token_id.default token in + let account_id = Account_id.create pk token in + let location = Ledger.location_of_account ledger account_id in + match location with + | None -> + raise (Failure "Account not found in snarked ledger") + | Some location -> ( + let account = Ledger.get ledger location in + match account with + | None -> + raise (Failure "Account not found in snarked ledger") + | Some account -> + let proof = Ledger.merkle_path ledger location in + mapper proof account |> Deferred.return ) ) + in + Ok memberships + + let snarked_ledger_account_membership = + io_field "snarkedLedgerAccountMembership" + ~doc: + "obtain a membership proof for an account in the snarked ledger \ + along with the account's balance, timing information, and nonce" + ~args: + Arg. + [ arg "accountInfos" ~doc:"Token id of the account to check" + ~typ: + (non_null (list (non_null Types.Input.AccountInfo.arg_typ))) + ; arg "stateHash" ~doc:"Hash of the snarked ledger to check" + ~typ:(non_null string) + ] + ~typ:(non_null (list (non_null Types.SnarkedLedgerMembership.obj))) + ~resolve: + (resolve_membership ~mapper:Types.SnarkedLedgerMembership.of_account) + + let encoded_snarked_ledger_account_membership = + io_field "encodedSnarkedLedgerAccountMembership" + ~doc: + "obtain a membership proof for an account in the snarked ledger \ + along with the accounts full information encoded as base64 binable \ + type" + ~args: + Arg. + [ arg "accountInfos" ~doc:"Token id of the account to check" + ~typ: + (non_null (list (non_null Types.Input.AccountInfo.arg_typ))) + ; arg "stateHash" ~doc:"Hash of the snarked ledger to check" + ~typ:(non_null string) + ] + ~typ: + (non_null (list (non_null Types.SnarkedLedgerMembership.encoded_obj))) + ~resolve: + (resolve_membership + ~mapper:Types.SnarkedLedgerMembership.of_encoded_account ) + end let genesis_constants = field "genesisConstants" @@ -2733,7 +2757,8 @@ module Queries = struct ; trust_status_all ; snark_pool ; pending_snark_work - ; snarked_ledger_account_membership + ; SnarkedLedgerMembership.snarked_ledger_account_membership + ; SnarkedLedgerMembership.encoded_snarked_ledger_account_membership ; genesis_constants ; time_offset ; validate_payment diff --git a/src/lib/mina_graphql/types.ml b/src/lib/mina_graphql/types.ml index e027aa9632c..a1c017cc9f7 100644 --- a/src/lib/mina_graphql/types.ml +++ b/src/lib/mina_graphql/types.ml @@ -772,6 +772,30 @@ let snarked_ledger_state : ] ) module SnarkedLedgerMembership = struct + type encoded_account = { account : string; proof : Ledger.path } + + let encoded_obj = + obj "EncodedAccount" ~fields:(fun _ -> + [ field "account" + ~args:Arg.[] + ~doc:"Base64 encoded account as binable wire type" + ~typ:(non_null string) + ~resolve:(fun _ { account; _ } -> account) + ; field "merklePath" + ~args:Arg.[] + ~doc:"Membership proof in the snarked ledger" + ~typ:(non_null (list (non_null merkle_path_element))) + ~resolve:(fun _ { proof; _ } -> proof) + ] ) + + let of_encoded_account (proof : Ledger.path) (account : Account.t) : + encoded_account = + let account = + Binable.to_string (module Account.Binable_arg.Stable.Latest) account + |> Base64.encode_exn + in + { account; proof } + type t = { account_balance : Currency.Balance.t ; timing_info : Account_timing.t @@ -779,6 +803,13 @@ module SnarkedLedgerMembership = struct ; proof : Ledger.path } + let of_account (proof : Ledger.path) (account : Account.t) : t = + { account_balance = account.balance + ; timing_info = account.timing + ; nonce = account.nonce + ; proof + } + let obj = obj "MembershipInfo" ~fields:(fun _ -> [ field "accountBalance"