From 15c4d25af177e2dfc9ce8e97dc1a66e9f1889f4f Mon Sep 17 00:00:00 2001 From: Gustavo Madeira Krieger Date: Thu, 23 Nov 2023 13:16:39 -0300 Subject: [PATCH] feat(cli): add read input command --- api/schema.graphql | 218 +++++++++++++++ .../root/read/input/input.go | 53 ++++ cmd/cartesi-rollups-cli/root/read/read.go | 20 ++ cmd/cartesi-rollups-cli/root/root.go | 2 + go.mod | 12 +- go.sum | 27 ++ pkg/readerclient/generate/input.graphql | 10 + pkg/readerclient/generated.go | 250 ++++++++++++++++++ pkg/readerclient/genqlient.yaml | 15 ++ pkg/readerclient/input.go | 65 +++++ pkg/readerclient/main.go | 8 + 11 files changed, 677 insertions(+), 3 deletions(-) create mode 100644 api/schema.graphql create mode 100644 cmd/cartesi-rollups-cli/root/read/input/input.go create mode 100644 cmd/cartesi-rollups-cli/root/read/read.go create mode 100644 pkg/readerclient/generate/input.graphql create mode 100644 pkg/readerclient/generated.go create mode 100644 pkg/readerclient/genqlient.yaml create mode 100644 pkg/readerclient/input.go create mode 100644 pkg/readerclient/main.go diff --git a/api/schema.graphql b/api/schema.graphql new file mode 100644 index 000000000..26f72a9cf --- /dev/null +++ b/api/schema.graphql @@ -0,0 +1,218 @@ +"Data that can be used as proof to validate notices and execute vouchers on the base layer blockchain" +type Proof { + "Validity proof for an output" + validity: OutputValidityProof! + "Data that allows the validity proof to be contextualized within submitted claims, given as a payload in Ethereum hex binary format, starting with '0x'" + context: String! +} + +enum CompletionStatus { + UNPROCESSED + ACCEPTED + REJECTED + EXCEPTION + MACHINE_HALTED + CYCLE_LIMIT_EXCEEDED + TIME_LIMIT_EXCEEDED + PAYLOAD_LENGTH_LIMIT_EXCEEDED +} + +"Request submitted to the application to advance its state" +type Input { + "Input index starting from genesis" + index: Int! + "Status of the input" + status: CompletionStatus! + "Address responsible for submitting the input" + msgSender: String! + "Timestamp associated with the input submission, as defined by the base layer's block in which it was recorded" + timestamp: BigInt! + "Number of the base layer block in which the input was recorded" + blockNumber: BigInt! + "Input payload in Ethereum hex binary format, starting with '0x'" + payload: String! + "Get voucher from this particular input given the voucher's index" + voucher(index: Int!): Voucher! + "Get notice from this particular input given the notice's index" + notice(index: Int!): Notice! + "Get report from this particular input given the report's index" + report(index: Int!): Report! + "Get vouchers from this particular input with support for pagination" + vouchers(first: Int, last: Int, after: String, before: String): VoucherConnection! + "Get notices from this particular input with support for pagination" + notices(first: Int, last: Int, after: String, before: String): NoticeConnection! + "Get reports from this particular input with support for pagination" + reports(first: Int, last: Int, after: String, before: String): ReportConnection! +} + +"Validity proof for an output" +type OutputValidityProof { + "Local input index within the context of the related epoch" + inputIndexWithinEpoch: Int! + "Output index within the context of the input that produced it" + outputIndexWithinInput: Int! + "Merkle root of all output hashes of the related input, given in Ethereum hex binary format (32 bytes), starting with '0x'" + outputHashesRootHash: String! + "Merkle root of all voucher hashes of the related epoch, given in Ethereum hex binary format (32 bytes), starting with '0x'" + vouchersEpochRootHash: String! + "Merkle root of all notice hashes of the related epoch, given in Ethereum hex binary format (32 bytes), starting with '0x'" + noticesEpochRootHash: String! + "Hash of the machine state claimed for the related epoch, given in Ethereum hex binary format (32 bytes), starting with '0x'" + machineStateHash: String! + "Proof that this output hash is in the output-hashes merkle tree. This array of siblings is bottom-up ordered (from the leaf to the root). Each hash is given in Ethereum hex binary format (32 bytes), starting with '0x'." + outputHashInOutputHashesSiblings: [String!]! + "Proof that this output-hashes root hash is in epoch's output merkle tree. This array of siblings is bottom-up ordered (from the leaf to the root). Each hash is given in Ethereum hex binary format (32 bytes), starting with '0x'." + outputHashesInEpochSiblings: [String!]! +} + +"Representation of a transaction that can be carried out on the base layer blockchain, such as a transfer of assets" +type Voucher { + "Voucher index within the context of the input that produced it" + index: Int! + "Input whose processing produced the voucher" + input: Input! + "Transaction destination address in Ethereum hex binary format (20 bytes), starting with '0x'" + destination: String! + "Transaction payload in Ethereum hex binary format, starting with '0x'" + payload: String! + "Proof object that allows this voucher to be validated and executed on the base layer blockchain" + proof: Proof +} + +"Top level queries" +type Query { + "Get input based on its identifier" + input(index: Int!): Input! + "Get voucher based on its index" + voucher(voucherIndex: Int!, inputIndex: Int!): Voucher! + "Get notice based on its index" + notice(noticeIndex: Int!, inputIndex: Int!): Notice! + "Get report based on its index" + report(reportIndex: Int!, inputIndex: Int!): Report! + "Get inputs with support for pagination" + inputs(first: Int, last: Int, after: String, before: String, where: InputFilter): InputConnection! + "Get vouchers with support for pagination" + vouchers(first: Int, last: Int, after: String, before: String): VoucherConnection! + "Get notices with support for pagination" + notices(first: Int, last: Int, after: String, before: String): NoticeConnection! + "Get reports with support for pagination" + reports(first: Int, last: Int, after: String, before: String): ReportConnection! +} + +"Pagination entry" +type NoticeEdge { + "Node instance" + node: Notice! + "Pagination cursor" + cursor: String! +} + +"Pagination result" +type InputConnection { + "Total number of entries that match the query" + totalCount: Int! + "Pagination entries returned for the current page" + edges: [InputEdge!]! + "Pagination metadata" + pageInfo: PageInfo! +} + +"Pagination result" +type VoucherConnection { + "Total number of entries that match the query" + totalCount: Int! + "Pagination entries returned for the current page" + edges: [VoucherEdge!]! + "Pagination metadata" + pageInfo: PageInfo! +} + +"Informational statement that can be validated in the base layer blockchain" +type Notice { + "Notice index within the context of the input that produced it" + index: Int! + "Input whose processing produced the notice" + input: Input! + "Notice data as a payload in Ethereum hex binary format, starting with '0x'" + payload: String! + "Proof object that allows this notice to be validated by the base layer blockchain" + proof: Proof +} + +"Pagination entry" +type ReportEdge { + "Node instance" + node: Report! + "Pagination cursor" + cursor: String! +} + +"Pagination result" +type ReportConnection { + "Total number of entries that match the query" + totalCount: Int! + "Pagination entries returned for the current page" + edges: [ReportEdge!]! + "Pagination metadata" + pageInfo: PageInfo! +} + +"Filter object to restrict results depending on input properties" +input InputFilter { + "Filter only inputs with index lower than a given value" indexLowerThan: Int + "Filter only inputs with index greater than a given value" indexGreaterThan: Int +} + +scalar BigInt + +"Pagination result" +type NoticeConnection { + "Total number of entries that match the query" + totalCount: Int! + "Pagination entries returned for the current page" + edges: [NoticeEdge!]! + "Pagination metadata" + pageInfo: PageInfo! +} + +"Pagination entry" +type InputEdge { + "Node instance" + node: Input! + "Pagination cursor" + cursor: String! +} + +"Page metadata for the cursor-based Connection pagination pattern" +type PageInfo { + "Cursor pointing to the first entry of the page" + startCursor: String + "Cursor pointing to the last entry of the page" + endCursor: String + "Indicates if there are additional entries after the end curs" + hasNextPage: Boolean! + "Indicates if there are additional entries before the start curs" + hasPreviousPage: Boolean! +} + +"Application log or diagnostic information" +type Report { + "Report index within the context of the input that produced it" + index: Int! + "Input whose processing produced the report" + input: Input! + "Report data as a payload in Ethereum hex binary format, starting with '0x'" + payload: String! +} + +"Pagination entry" +type VoucherEdge { + "Node instance" + node: Voucher! + "Pagination cursor" + cursor: String! +} + +schema { + query: Query +} diff --git a/cmd/cartesi-rollups-cli/root/read/input/input.go b/cmd/cartesi-rollups-cli/root/read/input/input.go new file mode 100644 index 000000000..c1d88adbd --- /dev/null +++ b/cmd/cartesi-rollups-cli/root/read/input/input.go @@ -0,0 +1,53 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +package input + +import ( + "encoding/json" + + "github.com/Khan/genqlient/graphql" + "github.com/cartesi/rollups-node/internal/logger" + "github.com/cartesi/rollups-node/pkg/readerclient" + "github.com/spf13/cobra" +) + +var Cmd = &cobra.Command{ + Use: "input", + Short: "Reads input from node GraphQL", + Example: examples, + Run: run, +} + +const examples = `# Read specific input from GraphQL: +cartesi-rollups-cli read input --index 5` + +var ( + index int + graphqlEndpoint string +) + +func init() { + Cmd.Flags().IntVar(&index, "index", 0, + "index of the input") + + cobra.CheckErr(Cmd.MarkFlagRequired("index")) + + Cmd.Flags().StringVar(&graphqlEndpoint, "graphql-endpoint", "http://0.0.0.0:4000/graphql", + "address used to connect to graphql") +} + +func run(cmd *cobra.Command, args []string) { + logger.Init("info", true) + + ctx := cmd.Context() + client := graphql.NewClient(graphqlEndpoint, nil) + + resp, err := readerclient.GetInput(ctx, client, int(index)) + cobra.CheckErr(err) + + val, err := json.MarshalIndent(resp, "", " ") + cobra.CheckErr(err) + + logger.Info.Printf(string(val)) +} diff --git a/cmd/cartesi-rollups-cli/root/read/read.go b/cmd/cartesi-rollups-cli/root/read/read.go new file mode 100644 index 000000000..f9fc2f9bf --- /dev/null +++ b/cmd/cartesi-rollups-cli/root/read/read.go @@ -0,0 +1,20 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +package read + +import ( + "github.com/cartesi/rollups-node/cmd/cartesi-rollups-cli/root/read/input" + "github.com/cartesi/rollups-node/cmd/cartesi-rollups-cli/root/read/inputs" + "github.com/spf13/cobra" +) + +var Cmd = &cobra.Command{ + Use: "read", + Short: "Read the node state from the GraphQL API", +} + +func init() { + Cmd.AddCommand(input.Cmd) + Cmd.AddCommand(inputs.Cmd) +} diff --git a/cmd/cartesi-rollups-cli/root/root.go b/cmd/cartesi-rollups-cli/root/root.go index 3d923358a..1d88d3cc2 100644 --- a/cmd/cartesi-rollups-cli/root/root.go +++ b/cmd/cartesi-rollups-cli/root/root.go @@ -4,6 +4,7 @@ package root import ( + "github.com/cartesi/rollups-node/cmd/cartesi-rollups-cli/root/read" "github.com/cartesi/rollups-node/cmd/cartesi-rollups-cli/root/send" "github.com/spf13/cobra" ) @@ -17,4 +18,5 @@ Cartesi Rollups node.`, func init() { Cmd.AddCommand(send.Cmd) + Cmd.AddCommand(read.Cmd) } diff --git a/go.mod b/go.mod index 61b422a3e..345b80a12 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.21.1 require ( github.com/ethereum/go-ethereum v1.13.5 - github.com/spf13/cobra v1.7.0 + github.com/spf13/cobra v1.8.0 github.com/stretchr/testify v1.8.4 github.com/testcontainers/testcontainers-go v0.26.0 github.com/tyler-smith/go-bip32 v1.0.0 @@ -16,9 +16,13 @@ require ( github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect + github.com/Khan/genqlient v0.6.0 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/Microsoft/hcsshim v0.11.1 // indirect github.com/StackExchange/wmi v1.2.1 // indirect + github.com/agnivade/levenshtein v1.1.1 // indirect + github.com/alexflint/go-arg v1.4.2 // indirect + github.com/alexflint/go-scalar v1.0.0 // indirect github.com/bits-and-blooms/bitset v1.7.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect @@ -27,7 +31,7 @@ require ( github.com/containerd/containerd v1.7.7 // indirect github.com/containerd/log v0.1.0 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/deckarep/golang-set/v2 v2.1.0 // indirect @@ -43,7 +47,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/uuid v1.3.1 // indirect - github.com/gorilla/websocket v1.4.2 // indirect + github.com/gorilla/websocket v1.5.0 // indirect github.com/holiman/uint256 v1.2.3 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/klauspost/compress v1.16.0 // indirect @@ -69,6 +73,7 @@ require ( github.com/supranational/blst v0.3.11 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect + github.com/vektah/gqlparser/v2 v2.5.1 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect golang.org/x/crypto v0.14.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect @@ -80,6 +85,7 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect google.golang.org/grpc v1.57.1 // indirect google.golang.org/protobuf v1.30.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index d108c747d..4393fd801 100644 --- a/go.sum +++ b/go.sum @@ -11,6 +11,8 @@ github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25Yn github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= +github.com/Khan/genqlient v0.6.0 h1:Bwb1170ekuNIVIwTJEqvO8y7RxBxXu639VJOkKSrwAk= +github.com/Khan/genqlient v0.6.0/go.mod h1:rvChwWVTqXhiapdhLDV4bp9tz/Xvtewwkon4DpWWCRM= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.11.1 h1:hJ3s7GbWlGK4YVV92sO88BQSyF4ZLVy7/awqOlPxFbA= @@ -19,6 +21,15 @@ github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDO github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= +github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= +github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8= +github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= +github.com/alexflint/go-arg v1.4.2 h1:lDWZAXxpAnZUq4qwb86p/3rIJJ2Li81EoMbTMujhVa0= +github.com/alexflint/go-arg v1.4.2/go.mod h1:9iRbDxne7LcR/GSvEr7ma++GLpdIU1zrghf2y2768kM= +github.com/alexflint/go-scalar v1.0.0 h1:NGupf1XV/Xb04wXskDFzS0KWOLH632W/EO4fAFi+A70= +github.com/alexflint/go-scalar v1.0.0/go.mod h1:GpHzbCOZXEKMEcygYQ5n/aa4Aq84zbxjy3MxYW0gjYw= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bits-and-blooms/bitset v1.7.0 h1:YjAGVd3XmtK9ktAbX8Zg2g2PwLIMjGREZJHlV4j7NEo= @@ -64,6 +75,8 @@ github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHf github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= @@ -78,6 +91,7 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v24.0.6+incompatible h1:hceabKCtUgDqPu+qm0NgsaXf28Ljf4/pWFL7xjWWDgE= @@ -126,6 +140,8 @@ github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw= @@ -144,6 +160,7 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -169,6 +186,7 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zk github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= @@ -218,6 +236,7 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/gopsutil/v3 v3.23.9 h1:ZI5bWVeu2ep4/DIxB4U9okeYJ7zp/QLTO4auRb/ty/E= @@ -232,6 +251,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= @@ -241,6 +262,7 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -265,6 +287,8 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX github.com/urfave/cli v1.22.12 h1:igJgVw1JdKH+trcLWLeLwZjU9fEfPesQ+9/e4MQ44S8= github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= +github.com/vektah/gqlparser/v2 v2.5.1 h1:ZGu+bquAY23jsxDRcYpWjttRZrUz07LbiY77gUOHcr4= +github.com/vektah/gqlparser/v2 v2.5.1/go.mod h1:mPgqFBu/woKTVYWyNk8cO3kh4S/f4aRFZrvOnp3hmCs= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= @@ -345,11 +369,14 @@ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pkg/readerclient/generate/input.graphql b/pkg/readerclient/generate/input.graphql new file mode 100644 index 000000000..cf462e2de --- /dev/null +++ b/pkg/readerclient/generate/input.graphql @@ -0,0 +1,10 @@ +query getInput($index: Int!) { + input(index: $index) { + index + status + msgSender + timestamp + blockNumber + payload + } +} diff --git a/pkg/readerclient/generated.go b/pkg/readerclient/generated.go new file mode 100644 index 000000000..48833bdae --- /dev/null +++ b/pkg/readerclient/generated.go @@ -0,0 +1,250 @@ +// Code generated by github.com/Khan/genqlient, DO NOT EDIT. + +package readerclient + +import ( + "context" + + "github.com/Khan/genqlient/graphql" +) + +type CompletionStatus string + +const ( + CompletionStatusUnprocessed CompletionStatus = "UNPROCESSED" + CompletionStatusAccepted CompletionStatus = "ACCEPTED" + CompletionStatusRejected CompletionStatus = "REJECTED" + CompletionStatusException CompletionStatus = "EXCEPTION" + CompletionStatusMachineHalted CompletionStatus = "MACHINE_HALTED" + CompletionStatusCycleLimitExceeded CompletionStatus = "CYCLE_LIMIT_EXCEEDED" + CompletionStatusTimeLimitExceeded CompletionStatus = "TIME_LIMIT_EXCEEDED" + CompletionStatusPayloadLengthLimitExceeded CompletionStatus = "PAYLOAD_LENGTH_LIMIT_EXCEEDED" +) + +// __getInputInput is used internally by genqlient +type __getInputInput struct { + Index int `json:"index"` +} + +// GetIndex returns __getInputInput.Index, and is useful for accessing the field via an interface. +func (v *__getInputInput) GetIndex() int { return v.Index } + +// __getInputsInput is used internally by genqlient +type __getInputsInput struct { + First int `json:"first"` +} + +// GetFirst returns __getInputsInput.First, and is useful for accessing the field via an interface. +func (v *__getInputsInput) GetFirst() int { return v.First } + +// getInputInput includes the requested fields of the GraphQL type Input. +// The GraphQL type's documentation follows. +// +// Request submitted to the application to advance its state +type getInputInput struct { + // Input index starting from genesis + Index int `json:"index"` + // Status of the input + Status CompletionStatus `json:"status"` + // Address responsible for submitting the input + MsgSender string `json:"msgSender"` + // Timestamp associated with the input submission, as defined by the base layer's block in which it was recorded + Timestamp string `json:"timestamp"` + // Number of the base layer block in which the input was recorded + BlockNumber string `json:"blockNumber"` + // Input payload in Ethereum hex binary format, starting with '0x' + Payload string `json:"payload"` +} + +// GetIndex returns getInputInput.Index, and is useful for accessing the field via an interface. +func (v *getInputInput) GetIndex() int { return v.Index } + +// GetStatus returns getInputInput.Status, and is useful for accessing the field via an interface. +func (v *getInputInput) GetStatus() CompletionStatus { return v.Status } + +// GetMsgSender returns getInputInput.MsgSender, and is useful for accessing the field via an interface. +func (v *getInputInput) GetMsgSender() string { return v.MsgSender } + +// GetTimestamp returns getInputInput.Timestamp, and is useful for accessing the field via an interface. +func (v *getInputInput) GetTimestamp() string { return v.Timestamp } + +// GetBlockNumber returns getInputInput.BlockNumber, and is useful for accessing the field via an interface. +func (v *getInputInput) GetBlockNumber() string { return v.BlockNumber } + +// GetPayload returns getInputInput.Payload, and is useful for accessing the field via an interface. +func (v *getInputInput) GetPayload() string { return v.Payload } + +// getInputResponse is returned by getInput on success. +type getInputResponse struct { + // Get input based on its identifier + Input getInputInput `json:"input"` +} + +// GetInput returns getInputResponse.Input, and is useful for accessing the field via an interface. +func (v *getInputResponse) GetInput() getInputInput { return v.Input } + +// getInputsInputsInputConnection includes the requested fields of the GraphQL type InputConnection. +// The GraphQL type's documentation follows. +// +// Pagination result +type getInputsInputsInputConnection struct { + // Pagination entries returned for the current page + Edges []getInputsInputsInputConnectionEdgesInputEdge `json:"edges"` +} + +// GetEdges returns getInputsInputsInputConnection.Edges, and is useful for accessing the field via an interface. +func (v *getInputsInputsInputConnection) GetEdges() []getInputsInputsInputConnectionEdgesInputEdge { + return v.Edges +} + +// getInputsInputsInputConnectionEdgesInputEdge includes the requested fields of the GraphQL type InputEdge. +// The GraphQL type's documentation follows. +// +// Pagination entry +type getInputsInputsInputConnectionEdgesInputEdge struct { + // Node instance + Node getInputsInputsInputConnectionEdgesInputEdgeNodeInput `json:"node"` +} + +// GetNode returns getInputsInputsInputConnectionEdgesInputEdge.Node, and is useful for accessing the field via an interface. +func (v *getInputsInputsInputConnectionEdgesInputEdge) GetNode() getInputsInputsInputConnectionEdgesInputEdgeNodeInput { + return v.Node +} + +// getInputsInputsInputConnectionEdgesInputEdgeNodeInput includes the requested fields of the GraphQL type Input. +// The GraphQL type's documentation follows. +// +// Request submitted to the application to advance its state +type getInputsInputsInputConnectionEdgesInputEdgeNodeInput struct { + // Input index starting from genesis + Index int `json:"index"` + // Status of the input + Status CompletionStatus `json:"status"` + // Address responsible for submitting the input + MsgSender string `json:"msgSender"` + // Timestamp associated with the input submission, as defined by the base layer's block in which it was recorded + Timestamp string `json:"timestamp"` + // Number of the base layer block in which the input was recorded + BlockNumber string `json:"blockNumber"` + // Input payload in Ethereum hex binary format, starting with '0x' + Payload string `json:"payload"` +} + +// GetIndex returns getInputsInputsInputConnectionEdgesInputEdgeNodeInput.Index, and is useful for accessing the field via an interface. +func (v *getInputsInputsInputConnectionEdgesInputEdgeNodeInput) GetIndex() int { return v.Index } + +// GetStatus returns getInputsInputsInputConnectionEdgesInputEdgeNodeInput.Status, and is useful for accessing the field via an interface. +func (v *getInputsInputsInputConnectionEdgesInputEdgeNodeInput) GetStatus() CompletionStatus { + return v.Status +} + +// GetMsgSender returns getInputsInputsInputConnectionEdgesInputEdgeNodeInput.MsgSender, and is useful for accessing the field via an interface. +func (v *getInputsInputsInputConnectionEdgesInputEdgeNodeInput) GetMsgSender() string { + return v.MsgSender +} + +// GetTimestamp returns getInputsInputsInputConnectionEdgesInputEdgeNodeInput.Timestamp, and is useful for accessing the field via an interface. +func (v *getInputsInputsInputConnectionEdgesInputEdgeNodeInput) GetTimestamp() string { + return v.Timestamp +} + +// GetBlockNumber returns getInputsInputsInputConnectionEdgesInputEdgeNodeInput.BlockNumber, and is useful for accessing the field via an interface. +func (v *getInputsInputsInputConnectionEdgesInputEdgeNodeInput) GetBlockNumber() string { + return v.BlockNumber +} + +// GetPayload returns getInputsInputsInputConnectionEdgesInputEdgeNodeInput.Payload, and is useful for accessing the field via an interface. +func (v *getInputsInputsInputConnectionEdgesInputEdgeNodeInput) GetPayload() string { return v.Payload } + +// getInputsResponse is returned by getInputs on success. +type getInputsResponse struct { + // Get inputs with support for pagination + Inputs getInputsInputsInputConnection `json:"inputs"` +} + +// GetInputs returns getInputsResponse.Inputs, and is useful for accessing the field via an interface. +func (v *getInputsResponse) GetInputs() getInputsInputsInputConnection { return v.Inputs } + +// The query or mutation executed by getInput. +const getInput_Operation = ` +query getInput ($index: Int!) { + input(index: $index) { + index + status + msgSender + timestamp + blockNumber + payload + } +} +` + +func getInput( + ctx context.Context, + client graphql.Client, + index int, +) (*getInputResponse, error) { + req := &graphql.Request{ + OpName: "getInput", + Query: getInput_Operation, + Variables: &__getInputInput{ + Index: index, + }, + } + var err error + + var data getInputResponse + resp := &graphql.Response{Data: &data} + + err = client.MakeRequest( + ctx, + req, + resp, + ) + + return &data, err +} + +// The query or mutation executed by getInputs. +const getInputs_Operation = ` +query getInputs ($first: Int!) { + inputs(first: $first) { + edges { + node { + index + status + msgSender + timestamp + blockNumber + payload + } + } + } +} +` + +func getInputs( + ctx context.Context, + client graphql.Client, + first int, +) (*getInputsResponse, error) { + req := &graphql.Request{ + OpName: "getInputs", + Query: getInputs_Operation, + Variables: &__getInputsInput{ + First: first, + }, + } + var err error + + var data getInputsResponse + resp := &graphql.Response{Data: &data} + + err = client.MakeRequest( + ctx, + req, + resp, + ) + + return &data, err +} diff --git a/pkg/readerclient/genqlient.yaml b/pkg/readerclient/genqlient.yaml new file mode 100644 index 000000000..f296f079c --- /dev/null +++ b/pkg/readerclient/genqlient.yaml @@ -0,0 +1,15 @@ +# Default genqlient config; for full documentation see: +# https://github.com/Khan/genqlient/blob/main/docs/genqlient.yaml + + +schema: ../../api/schema.graphql + +operations: +- generate/input.graphql +- generate/inputs.graphql +generated: generated.go +package: readerclient + +bindings: + BigInt: + type: string diff --git a/pkg/readerclient/input.go b/pkg/readerclient/input.go new file mode 100644 index 000000000..e0c7d51ff --- /dev/null +++ b/pkg/readerclient/input.go @@ -0,0 +1,65 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +package readerclient + +import ( + "context" + "strconv" + "time" + + "github.com/Khan/genqlient/graphql" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" +) + +type Input struct { + // Input index starting from genesis + Index int `json:"index"` + // Status of the input + Status CompletionStatus `json:"status"` + // Address responsible for submitting the input + MsgSender common.Address `json:"msgSender"` + // Timestamp associated with the input submission, as defined by the base layer's block in which it was recorded + Timestamp time.Duration `json:"timestamp"` + // Number of the base layer block in which the input was recorded + BlockNumber uint64 `json:"blockNumber"` + // Input payload in Ethereum hex binary format, starting with '0x' + Payload hexutil.Bytes `json:"payload"` +} + +func GetInput( + ctx context.Context, + client graphql.Client, + index int, +) (*Input, error) { + resp, err := getInput(ctx, client, int(index)) + if err != nil { + return nil, err + } + + timestamp, err := strconv.ParseUint(resp.Input.Timestamp, 0, 64) + if err != nil { + return nil, err + } + + blocknumber, err := strconv.ParseUint(resp.Input.BlockNumber, 0, 64) + if err != nil { + return nil, err + } + payload, err := hexutil.Decode(resp.Input.Payload) + if err != nil { + return nil, err + } + + input := Input{ + resp.Input.Index, + resp.Input.Status, + common.HexToAddress(resp.Input.MsgSender), + time.Duration(timestamp), + blocknumber, + payload, + } + + return &input, err +} diff --git a/pkg/readerclient/main.go b/pkg/readerclient/main.go new file mode 100644 index 000000000..bdf102465 --- /dev/null +++ b/pkg/readerclient/main.go @@ -0,0 +1,8 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +// This package contains auxiliary functions generated with genqlient +// to read from GraphQL database +package readerclient + +//go:generate go run github.com/Khan/genqlient