From 33602aa0e06b70f629e59afc86dabd59b7998eb8 Mon Sep 17 00:00:00 2001 From: prathamesh0 <42446521+prathamesh0@users.noreply.github.com> Date: Wed, 5 Oct 2022 15:14:17 +0530 Subject: [PATCH] Optimize `getLogs` GQL API (#198) * Avoid joins with header and transaction tables while getting logs * Update getLogs GQL API to accept multiple addresses * Update version * Update unit tests --- .github/workflows/run_unit_test.sh | 1 + Makefile | 2 +- pkg/eth/cid_retriever.go | 23 +++++++++-------------- pkg/graphql/client.go | 13 ++++++++++--- pkg/graphql/graphql.go | 11 +++++++---- pkg/graphql/graphql_test.go | 30 +++++++++++++++++++++++++++--- pkg/graphql/schema.go | 2 +- version/version.go | 4 ++-- 8 files changed, 58 insertions(+), 28 deletions(-) diff --git a/.github/workflows/run_unit_test.sh b/.github/workflows/run_unit_test.sh index 050c074f..63fbb99f 100755 --- a/.github/workflows/run_unit_test.sh +++ b/.github/workflows/run_unit_test.sh @@ -6,6 +6,7 @@ set -e start_dir=$(pwd) temp_dir=$(mktemp -d) cd $temp_dir +echo "git clone -b $(cat /tmp/git_head_ref) https://github.com/$(cat /tmp/git_repository).git" git clone -b $(cat /tmp/git_head_ref) "https://github.com/$(cat /tmp/git_repository).git" cd ipld-eth-server diff --git a/Makefile b/Makefile index 83f82238..2ca31916 100644 --- a/Makefile +++ b/Makefile @@ -54,7 +54,7 @@ TEST_CONNECT_STRING_LOCAL = postgresql://$(USER)@$(HOST_NAME):$(PORT)/$(TEST_DB) test: go vet ./... go fmt ./... - go run github.com/onsi/ginkgo/ginkgo -r --skipPackage=test + go run github.com/onsi/ginkgo/ginkgo -r --skipPackage=test .PHONY: integrationtest integrationtest: diff --git a/pkg/eth/cid_retriever.go b/pkg/eth/cid_retriever.go index 63302af7..d2f12ecf 100644 --- a/pkg/eth/cid_retriever.go +++ b/pkg/eth/cid_retriever.go @@ -364,22 +364,17 @@ func (ecr *CIDRetriever) RetrieveFilteredGQLLogs(tx *sqlx.Tx, rctFilter ReceiptF log.Debug("retrieving log cids for receipt ids with block hash", blockHash.String()) args := make([]interface{}, 0, 4) id := 1 - pgStr := `SELECT CAST(eth.log_cids.block_number as Text), eth.log_cids.leaf_cid, eth.log_cids.index, eth.log_cids.rct_id, - eth.log_cids.address, eth.log_cids.topic0, eth.log_cids.topic1, eth.log_cids.topic2, eth.log_cids.topic3, - eth.log_cids.log_data, eth.transaction_cids.tx_hash, eth.transaction_cids.index as txn_index, data, - eth.receipt_cids.leaf_cid as cid, eth.receipt_cids.post_status, header_cids.block_hash - FROM eth.log_cids, eth.receipt_cids, eth.transaction_cids, eth.header_cids, public.blocks + pgStr := `SELECT CAST(eth.log_cids.block_number as Text), eth.log_cids.header_id as block_hash, + eth.log_cids.leaf_cid, eth.log_cids.index, eth.log_cids.rct_id, eth.log_cids.address, + eth.log_cids.topic0, eth.log_cids.topic1, eth.log_cids.topic2, eth.log_cids.topic3, eth.log_cids.log_data, + data, eth.receipt_cids.leaf_cid as cid, eth.receipt_cids.post_status, eth.receipt_cids.tx_id AS tx_hash + FROM eth.log_cids, eth.receipt_cids, public.blocks WHERE eth.log_cids.rct_id = receipt_cids.tx_id - AND eth.log_cids.header_id = eth.receipt_cids.header_id - AND eth.log_cids.block_number = eth.receipt_cids.block_number - AND receipt_cids.tx_id = transaction_cids.tx_hash - AND receipt_cids.header_id = transaction_cids.header_id - AND receipt_cids.block_number = transaction_cids.block_number - AND transaction_cids.header_id = header_cids.block_hash - AND transaction_cids.block_number = header_cids.block_number - AND log_cids.leaf_mh_key = blocks.key + AND eth.log_cids.header_id = receipt_cids.header_id + AND eth.log_cids.block_number = receipt_cids.block_number + AND log_cids.leaf_mh_key = blocks.key AND log_cids.block_number = blocks.block_number - AND header_cids.block_hash = $1` + AND receipt_cids.header_id = $1` args = append(args, blockHash.String()) id++ diff --git a/pkg/graphql/client.go b/pkg/graphql/client.go index 096b7a06..f7650e29 100644 --- a/pkg/graphql/client.go +++ b/pkg/graphql/client.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "strings" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -91,10 +92,16 @@ func NewClient(endpoint string) *Client { return &Client{client: client} } -func (c *Client) GetLogs(ctx context.Context, hash common.Hash, address *common.Address) ([]LogResponse, error) { +func (c *Client) GetLogs(ctx context.Context, hash common.Hash, addresses []common.Address) ([]LogResponse, error) { params := fmt.Sprintf(`blockHash: "%s"`, hash.String()) - if address != nil { - params += fmt.Sprintf(`, contract: "%s"`, address.String()) + + if addresses != nil { + addressStrings := make([]string, len(addresses)) + for i, address := range addresses { + addressStrings[i] = fmt.Sprintf(`"%s"`, address.String()) + } + + params += fmt.Sprintf(`, addresses: [%s]`, strings.Join(addressStrings, ",")) } getLogsQuery := fmt.Sprintf(`query{ diff --git a/pkg/graphql/graphql.go b/pkg/graphql/graphql.go index b4dc9ffe..97282037 100644 --- a/pkg/graphql/graphql.go +++ b/pkg/graphql/graphql.go @@ -1037,12 +1037,15 @@ func (r *Resolver) GetStorageAt(ctx context.Context, args struct { func (r *Resolver) GetLogs(ctx context.Context, args struct { BlockHash common.Hash - Contract *common.Address + Addresses *[]common.Address }) (*[]*Log, error) { - var filter eth.ReceiptFilter - if args.Contract != nil { - filter.LogAddresses = []string{args.Contract.String()} + + if args.Addresses != nil { + filter.LogAddresses = make([]string, len(*args.Addresses)) + for i, address := range *args.Addresses { + filter.LogAddresses[i] = address.String() + } } // Begin tx diff --git a/pkg/graphql/graphql_test.go b/pkg/graphql/graphql_test.go index aae047ce..258d6afe 100644 --- a/pkg/graphql/graphql_test.go +++ b/pkg/graphql/graphql_test.go @@ -174,7 +174,7 @@ var _ = Describe("GraphQL", func() { Describe("eth_getLogs", func() { It("Retrieves logs that matches the provided blockHash and contract address", func() { - logs, err := client.GetLogs(ctx, blockHash, &contractAddress) + logs, err := client.GetLogs(ctx, blockHash, []common.Address{contractAddress}) Expect(err).ToNot(HaveOccurred()) expectedLogs := []graphql.LogResponse{ @@ -191,7 +191,7 @@ var _ = Describe("GraphQL", func() { }) It("Retrieves logs for the failed receipt status that matches the provided blockHash and another contract address", func() { - logs, err := client.GetLogs(ctx, blockHash, &test_helpers.AnotherAddress2) + logs, err := client.GetLogs(ctx, blockHash, []common.Address{test_helpers.AnotherAddress2}) Expect(err).ToNot(HaveOccurred()) expectedLogs := []graphql.LogResponse{ @@ -207,6 +207,30 @@ var _ = Describe("GraphQL", func() { Expect(logs).To(Equal(expectedLogs)) }) + It("Retrieves logs that matches the provided blockHash and multiple contract addresses", func() { + logs, err := client.GetLogs(ctx, blockHash, []common.Address{contractAddress, test_helpers.AnotherAddress2}) + Expect(err).ToNot(HaveOccurred()) + + expectedLogs := []graphql.LogResponse{ + { + Topics: test_helpers.MockLog1.Topics, + Data: hexutil.Bytes(test_helpers.MockLog1.Data), + Transaction: graphql.TransactionResponse{Hash: test_helpers.MockTransactions[0].Hash()}, + ReceiptCID: test_helpers.Rct1CID.String(), + Status: int32(test_helpers.MockReceipts[0].Status), + }, + { + Topics: test_helpers.MockLog6.Topics, + Data: hexutil.Bytes(test_helpers.MockLog6.Data), + Transaction: graphql.TransactionResponse{Hash: test_helpers.MockTransactions[3].Hash()}, + ReceiptCID: test_helpers.Rct4CID.String(), + Status: int32(test_helpers.MockReceipts[3].Status), + }, + } + + Expect(logs).To(Equal(expectedLogs)) + }) + It("Retrieves all the logs for the receipt that matches the provided blockHash and nil contract address", func() { logs, err := client.GetLogs(ctx, blockHash, nil) Expect(err).ToNot(HaveOccurred()) @@ -214,7 +238,7 @@ var _ = Describe("GraphQL", func() { }) It("Retrieves logs with random hash", func() { - logs, err := client.GetLogs(ctx, randomHash, &contractAddress) + logs, err := client.GetLogs(ctx, randomHash, []common.Address{contractAddress}) Expect(err).ToNot(HaveOccurred()) Expect(len(logs)).To(Equal(0)) }) diff --git a/pkg/graphql/schema.go b/pkg/graphql/schema.go index eb0d89fc..d07d311b 100644 --- a/pkg/graphql/schema.go +++ b/pkg/graphql/schema.go @@ -343,7 +343,7 @@ const schema string = ` getStorageAt(blockHash: Bytes32!, contract: Address!, slot: Bytes32!): StorageResult # Get contract logs by block hash and contract address. - getLogs(blockHash: Bytes32!, contract: Address): [Log!] + getLogs(blockHash: Bytes32!, addresses: [Address!]): [Log!] # PostGraphile alternative to get headers with transactions using block number or block hash. allEthHeaderCids(condition: EthHeaderCidCondition): EthHeaderCidsConnection diff --git a/version/version.go b/version/version.go index e5a88848..a9868599 100644 --- a/version/version.go +++ b/version/version.go @@ -20,8 +20,8 @@ import "fmt" const ( Major = 4 // Major version component of the current release - Minor = 1 // Minor version component of the current release - Patch = 9 // Patch version component of the current release + Minor = 2 // Minor version component of the current release + Patch = 0 // Patch version component of the current release Meta = "alpha" // Version metadata to append to the version string )