Skip to content

Commit

Permalink
Merge pull request #16000 from MinaProtocol/sai/snark-ledger-query-se…
Browse files Browse the repository at this point in the history
…rialized

Sai/snark ledger query serialized
  • Loading branch information
svv232 authored Sep 3, 2024
2 parents 7273e9b + 11db54f commit dceffd7
Show file tree
Hide file tree
Showing 3 changed files with 225 additions and 56 deletions.
113 changes: 113 additions & 0 deletions graphql_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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":
Expand Down
137 changes: 81 additions & 56 deletions src/lib/mina_graphql/mina_graphql.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down
31 changes: 31 additions & 0 deletions src/lib/mina_graphql/types.ml
Original file line number Diff line number Diff line change
Expand Up @@ -772,13 +772,44 @@ 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
; nonce : Account.Nonce.t
; 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"
Expand Down

0 comments on commit dceffd7

Please sign in to comment.