diff --git a/pkg/eth/api.go b/pkg/eth/api.go index 8d880cd8..e9e9c922 100644 --- a/pkg/eth/api.go +++ b/pkg/eth/api.go @@ -24,6 +24,7 @@ import ( "fmt" "io" "math/big" + "strconv" "time" "github.com/ethereum/go-ethereum/common" @@ -120,12 +121,7 @@ func (pea *PublicEthAPI) GetHeaderByHash(ctx context.Context, hash common.Hash) // rpcMarshalHeader uses the generalized output filler, then adds the total difficulty field func (pea *PublicEthAPI) rpcMarshalHeader(header *types.Header) (map[string]interface{}, error) { - var extractMiner bool - if pea.B.Config.ChainConfig.Clique != nil { - extractMiner = true - } - - fields := RPCMarshalHeader(header, extractMiner) + fields := RPCMarshalHeader(header, pea.B.Config.ChainConfig.Clique != nil) td, err := pea.B.GetTd(header.Hash()) if err != nil { return nil, err @@ -628,7 +624,7 @@ func (pea *PublicEthAPI) localGetLogs(crit filters.FilterCriteria) ([]*types.Log return nil, err } - return pea.B.Fetcher.FetchLogs(filteredLogs) + return decomposeLogs(filteredLogs) } // Otherwise, create block range from criteria @@ -651,12 +647,12 @@ func (pea *PublicEthAPI) localGetLogs(crit filters.FilterCriteria) ([]*types.Log end := endingBlock.Int64() var logs []*types.Log for i := start; i <= end; i++ { - filteredLog, err := pea.B.Retriever.RetrieveFilteredLog(tx, filter, i, nil) + filteredLogs, err := pea.B.Retriever.RetrieveFilteredLog(tx, filter, i, nil) if err != nil { return nil, err } - logCIDs, err := pea.B.Fetcher.FetchLogs(filteredLog) + logCIDs, err := decomposeLogs(filteredLogs) if err != nil { return nil, err } @@ -1084,12 +1080,7 @@ func (pea *PublicEthAPI) writeStateDiffFor(blockHash common.Hash) { // rpcMarshalBlock uses the generalized output filler, then adds the total difficulty field func (pea *PublicEthAPI) rpcMarshalBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) { - var extractMiner bool - if pea.B.Config.ChainConfig.Clique != nil { - extractMiner = true - } - - fields, err := RPCMarshalBlock(b, inclTx, fullTx, extractMiner) + fields, err := RPCMarshalBlock(b, inclTx, fullTx, pea.B.Config.ChainConfig.Clique != nil) if err != nil { return nil, err } @@ -1105,12 +1096,7 @@ func (pea *PublicEthAPI) rpcMarshalBlock(b *types.Block, inclTx bool, fullTx boo // rpcMarshalBlockWithUncleHashes uses the generalized output filler, then adds the total difficulty field func (pea *PublicEthAPI) rpcMarshalBlockWithUncleHashes(b *types.Block, uncleHashes []common.Hash, inclTx bool, fullTx bool) (map[string]interface{}, error) { - var extractMiner bool - if pea.B.Config.ChainConfig.Clique != nil { - extractMiner = true - } - - fields, err := RPCMarshalBlockWithUncleHashes(b, uncleHashes, inclTx, fullTx, extractMiner) + fields, err := RPCMarshalBlockWithUncleHashes(b, uncleHashes, inclTx, fullTx, pea.B.Config.ChainConfig.Clique != nil) if err != nil { return nil, err } @@ -1130,3 +1116,42 @@ func toHexSlice(b [][]byte) []string { } return r } + +// decomposeLogs return logs from LogResult. +func decomposeLogs(logCIDs []LogResult) ([]*types.Log, error) { + logs := make([]*types.Log, len(logCIDs)) + for i, l := range logCIDs { + topics := make([]common.Hash, 0) + if l.Topic0 != "" { + topics = append(topics, common.HexToHash(l.Topic0)) + } + if l.Topic1 != "" { + topics = append(topics, common.HexToHash(l.Topic1)) + } + if l.Topic2 != "" { + topics = append(topics, common.HexToHash(l.Topic2)) + } + if l.Topic3 != "" { + topics = append(topics, common.HexToHash(l.Topic3)) + } + + // TODO: should we convert string to uint ? + blockNum, err := strconv.ParseUint(l.BlockNumber, 10, 64) + if err != nil { + return nil, err + } + + logs[i] = &types.Log{ + Address: common.HexToAddress(l.Address), + Topics: topics, + Data: l.Data, + BlockNumber: blockNum, + TxHash: common.HexToHash(l.TxHash), + TxIndex: uint(l.TxnIndex), + BlockHash: common.HexToHash(l.BlockHash), + Index: uint(l.Index), + } + } + + return logs, nil +} diff --git a/pkg/eth/api_test.go b/pkg/eth/api_test.go index 7a60c0ef..57866cab 100644 --- a/pkg/eth/api_test.go +++ b/pkg/eth/api_test.go @@ -34,7 +34,6 @@ import ( "github.com/ethereum/go-ethereum/statediff/indexer" "github.com/ethereum/go-ethereum/statediff/indexer/node" "github.com/ethereum/go-ethereum/statediff/indexer/postgres" - "github.com/ethereum/go-ethereum/statediff/indexer/shared" sdtypes "github.com/ethereum/go-ethereum/statediff/types" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -48,7 +47,7 @@ var ( randomHash = crypto.Keccak256Hash(randomAddr.Bytes()) number = rpc.BlockNumber(test_helpers.BlockNumber.Int64()) londonBlockNum = rpc.BlockNumber(test_helpers.LondonBlockNum.Int64()) - wrongNumber = rpc.BlockNumber(number + 1) + wrongNumber = number + 1 blockHash = test_helpers.MockBlock.Header().Hash() baseFee = test_helpers.MockLondonBlock.BaseFee() ctx = context.Background() @@ -482,14 +481,14 @@ var _ = Describe("API", func() { Describe("eth_getBlockTransactionCountByNumber", func() { It("Retrieves the number of transactions in the canonical block with the provided number", func() { count := api.GetBlockTransactionCountByNumber(ctx, number) - Expect(uint64(*count)).To(Equal(uint64(3))) + Expect(uint64(*count)).To(Equal(uint64(4))) }) }) Describe("eth_getBlockTransactionCountByHash", func() { It("Retrieves the number of transactions in the block with the provided hash ", func() { count := api.GetBlockTransactionCountByHash(ctx, blockHash) - Expect(uint64(*count)).To(Equal(uint64(3))) + Expect(uint64(*count)).To(Equal(uint64(4))) }) }) @@ -875,8 +874,8 @@ var _ = Describe("API", func() { } logs, err = api.GetLogs(ctx, crit) Expect(err).ToNot(HaveOccurred()) - Expect(len(logs)).To(Equal(5)) - Expect(logs).To(Equal([]*types.Log{test_helpers.MockLog1, test_helpers.MockLog2, test_helpers.MockLog3, test_helpers.MockLog4, test_helpers.MockLog5})) + Expect(len(logs)).To(Equal(6)) + Expect(logs).To(Equal([]*types.Log{test_helpers.MockLog1, test_helpers.MockLog2, test_helpers.MockLog3, test_helpers.MockLog4, test_helpers.MockLog5, test_helpers.MockLog6})) }) It("Uses the provided blockhash if one is provided", func() { @@ -1011,8 +1010,8 @@ var _ = Describe("API", func() { } logs, err = api.GetLogs(ctx, crit) Expect(err).ToNot(HaveOccurred()) - Expect(len(logs)).To(Equal(5)) - Expect(logs).To(Equal([]*types.Log{test_helpers.MockLog1, test_helpers.MockLog2, test_helpers.MockLog3, test_helpers.MockLog4, test_helpers.MockLog5})) + Expect(len(logs)).To(Equal(6)) + Expect(logs).To(Equal([]*types.Log{test_helpers.MockLog1, test_helpers.MockLog2, test_helpers.MockLog3, test_helpers.MockLog4, test_helpers.MockLog5, test_helpers.MockLog6})) }) It("Filters on contract address if any are provided", func() { @@ -1134,20 +1133,3 @@ var _ = Describe("API", func() { }) }) }) - -func publishCode(db *postgres.DB, codeHash common.Hash, code []byte) error { - tx, err := db.Beginx() - if err != nil { - return err - } - mhKey, err := shared.MultihashKeyFromKeccak256(codeHash) - if err != nil { - tx.Rollback() - return err - } - if err := shared.PublishDirect(tx, mhKey, code); err != nil { - tx.Rollback() - return err - } - return tx.Commit() -} diff --git a/pkg/eth/cid_retriever.go b/pkg/eth/cid_retriever.go index e0908395..4c491b44 100644 --- a/pkg/eth/cid_retriever.go +++ b/pkg/eth/cid_retriever.go @@ -310,7 +310,7 @@ func (ecr *CIDRetriever) RetrieveRctCIDsByHeaderID(tx *sqlx.Tx, rctFilter Receip // RetrieveFilteredGQLLogs retrieves and returns all the log cIDs provided blockHash that conform to the provided // filter parameters. -func (ecr *CIDRetriever) RetrieveFilteredGQLLogs(tx *sqlx.Tx, rctFilter ReceiptFilter, blockHash *common.Hash) ([]logResult, error) { +func (ecr *CIDRetriever) RetrieveFilteredGQLLogs(tx *sqlx.Tx, rctFilter ReceiptFilter, blockHash *common.Hash) ([]LogResult, error) { log.Debug("retrieving log cids for receipt ids") args := make([]interface{}, 0, 4) id := 1 @@ -321,7 +321,7 @@ func (ecr *CIDRetriever) RetrieveFilteredGQLLogs(tx *sqlx.Tx, rctFilter ReceiptF WHERE eth.log_cids.receipt_id = receipt_cids.id AND receipt_cids.tx_id = transaction_cids.id AND transaction_cids.header_id = header_cids.id - AND receipt_cids.mh_key = blocks.key AND header_cids.block_hash = $1` + AND log_cids.leaf_mh_key = blocks.key AND header_cids.block_hash = $1` args = append(args, blockHash.String()) id++ @@ -329,7 +329,7 @@ func (ecr *CIDRetriever) RetrieveFilteredGQLLogs(tx *sqlx.Tx, rctFilter ReceiptF pgStr, args = logFilterCondition(&id, pgStr, args, rctFilter) pgStr += ` ORDER BY log_cids.index` - logCIDs := make([]logResult, 0) + logCIDs := make([]LogResult, 0) err := tx.Select(&logCIDs, pgStr, args...) if err != nil { return nil, err @@ -340,7 +340,7 @@ func (ecr *CIDRetriever) RetrieveFilteredGQLLogs(tx *sqlx.Tx, rctFilter ReceiptF // RetrieveFilteredLog retrieves and returns all the log cIDs provided blockHeight or blockHash that conform to the provided // filter parameters. -func (ecr *CIDRetriever) RetrieveFilteredLog(tx *sqlx.Tx, rctFilter ReceiptFilter, blockNumber int64, blockHash *common.Hash) ([]logResult, error) { +func (ecr *CIDRetriever) RetrieveFilteredLog(tx *sqlx.Tx, rctFilter ReceiptFilter, blockNumber int64, blockHash *common.Hash) ([]LogResult, error) { log.Debug("retrieving log cids for receipt ids") args := make([]interface{}, 0, 4) pgStr := `SELECT eth.log_cids.id,eth.log_cids.leaf_cid, eth.log_cids.index, eth.log_cids.receipt_id, @@ -366,7 +366,7 @@ func (ecr *CIDRetriever) RetrieveFilteredLog(tx *sqlx.Tx, rctFilter ReceiptFilte pgStr, args = logFilterCondition(&id, pgStr, args, rctFilter) pgStr += ` ORDER BY log_cids.index` - logCIDs := make([]logResult, 0) + logCIDs := make([]LogResult, 0) err := tx.Select(&logCIDs, pgStr, args...) if err != nil { return nil, err diff --git a/pkg/eth/cid_retriever_test.go b/pkg/eth/cid_retriever_test.go index 414dbd47..e972aee3 100644 --- a/pkg/eth/cid_retriever_test.go +++ b/pkg/eth/cid_retriever_test.go @@ -249,11 +249,11 @@ var _ = Describe("Retriever", func() { expectedHeaderCID.ID = cids[0].Header.ID expectedHeaderCID.NodeID = cids[0].Header.NodeID Expect(cids[0].Header).To(Equal(expectedHeaderCID)) - Expect(len(cids[0].Transactions)).To(Equal(3)) + Expect(len(cids[0].Transactions)).To(Equal(4)) Expect(eth.TxModelsContainsCID(cids[0].Transactions, test_helpers.MockCIDWrapper.Transactions[0].CID)).To(BeTrue()) Expect(eth.TxModelsContainsCID(cids[0].Transactions, test_helpers.MockCIDWrapper.Transactions[1].CID)).To(BeTrue()) Expect(eth.TxModelsContainsCID(cids[0].Transactions, test_helpers.MockCIDWrapper.Transactions[2].CID)).To(BeTrue()) - Expect(len(cids[0].Receipts)).To(Equal(3)) + Expect(len(cids[0].Receipts)).To(Equal(4)) Expect(eth.ReceiptModelsContainsCID(cids[0].Receipts, test_helpers.MockCIDWrapper.Receipts[0].CID)).To(BeTrue()) Expect(eth.ReceiptModelsContainsCID(cids[0].Receipts, test_helpers.MockCIDWrapper.Receipts[1].CID)).To(BeTrue()) Expect(eth.ReceiptModelsContainsCID(cids[0].Receipts, test_helpers.MockCIDWrapper.Receipts[2].CID)).To(BeTrue()) @@ -345,13 +345,13 @@ var _ = Describe("Retriever", func() { Expect(len(cids5)).To(Equal(1)) Expect(cids5[0].BlockNumber).To(Equal(test_helpers.MockCIDWrapper.BlockNumber)) Expect(cids5[0].Header).To(Equal(models.HeaderModel{})) - Expect(len(cids5[0].Transactions)).To(Equal(3)) + Expect(len(cids5[0].Transactions)).To(Equal(4)) Expect(eth.TxModelsContainsCID(cids5[0].Transactions, test_helpers.Trx1CID.String())).To(BeTrue()) Expect(eth.TxModelsContainsCID(cids5[0].Transactions, test_helpers.Trx2CID.String())).To(BeTrue()) Expect(eth.TxModelsContainsCID(cids5[0].Transactions, test_helpers.Trx3CID.String())).To(BeTrue()) Expect(len(cids5[0].StateNodes)).To(Equal(0)) Expect(len(cids5[0].StorageNodes)).To(Equal(0)) - Expect(len(cids5[0].Receipts)).To(Equal(3)) + Expect(len(cids5[0].Receipts)).To(Equal(4)) Expect(eth.ReceiptModelsContainsCID(cids5[0].Receipts, test_helpers.Rct1CID.String())).To(BeTrue()) Expect(eth.ReceiptModelsContainsCID(cids5[0].Receipts, test_helpers.Rct2CID.String())).To(BeTrue()) Expect(eth.ReceiptModelsContainsCID(cids5[0].Receipts, test_helpers.Rct3CID.String())).To(BeTrue()) diff --git a/pkg/eth/filterer_test.go b/pkg/eth/filterer_test.go index cfa64a3b..950b281d 100644 --- a/pkg/eth/filterer_test.go +++ b/pkg/eth/filterer_test.go @@ -48,11 +48,11 @@ var _ = Describe("Filterer", func() { Expect(iplds.Header).To(Equal(test_helpers.MockIPLDs.Header)) var expectedEmptyUncles []ipfs.BlockModel Expect(iplds.Uncles).To(Equal(expectedEmptyUncles)) - Expect(len(iplds.Transactions)).To(Equal(3)) + Expect(len(iplds.Transactions)).To(Equal(4)) Expect(shared.IPLDsContainBytes(iplds.Transactions, test_helpers.Tx1)).To(BeTrue()) Expect(shared.IPLDsContainBytes(iplds.Transactions, test_helpers.Tx2)).To(BeTrue()) Expect(shared.IPLDsContainBytes(iplds.Transactions, test_helpers.Tx3)).To(BeTrue()) - Expect(len(iplds.Receipts)).To(Equal(3)) + Expect(len(iplds.Receipts)).To(Equal(4)) Expect(shared.IPLDsContainBytes(iplds.Receipts, test_helpers.Rct1)).To(BeTrue()) Expect(shared.IPLDsContainBytes(iplds.Receipts, test_helpers.Rct2)).To(BeTrue()) Expect(shared.IPLDsContainBytes(iplds.Receipts, test_helpers.Rct3)).To(BeTrue()) @@ -142,13 +142,13 @@ var _ = Describe("Filterer", func() { Expect(iplds5.BlockNumber.Int64()).To(Equal(test_helpers.MockIPLDs.BlockNumber.Int64())) Expect(iplds5.Header).To(Equal(ipfs.BlockModel{})) Expect(len(iplds5.Uncles)).To(Equal(0)) - Expect(len(iplds5.Transactions)).To(Equal(3)) + Expect(len(iplds5.Transactions)).To(Equal(4)) Expect(shared.IPLDsContainBytes(iplds5.Transactions, test_helpers.Tx1)).To(BeTrue()) Expect(shared.IPLDsContainBytes(iplds5.Transactions, test_helpers.Tx2)).To(BeTrue()) Expect(shared.IPLDsContainBytes(iplds5.Transactions, test_helpers.Tx3)).To(BeTrue()) Expect(len(iplds5.StorageNodes)).To(Equal(0)) Expect(len(iplds5.StateNodes)).To(Equal(0)) - Expect(len(iplds5.Receipts)).To(Equal(3)) + Expect(len(iplds5.Receipts)).To(Equal(4)) Expect(shared.IPLDsContainBytes(iplds5.Receipts, test_helpers.Rct1)).To(BeTrue()) Expect(shared.IPLDsContainBytes(iplds5.Receipts, test_helpers.Rct2)).To(BeTrue()) Expect(shared.IPLDsContainBytes(iplds5.Receipts, test_helpers.Rct3)).To(BeTrue()) diff --git a/pkg/eth/ipld_fetcher.go b/pkg/eth/ipld_fetcher.go index 193a98a9..18330143 100644 --- a/pkg/eth/ipld_fetcher.go +++ b/pkg/eth/ipld_fetcher.go @@ -20,10 +20,8 @@ import ( "errors" "fmt" "math/big" - "strconv" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/statediff/indexer/ipfs" "github.com/ethereum/go-ethereum/statediff/indexer/models" "github.com/ethereum/go-ethereum/statediff/indexer/postgres" @@ -167,93 +165,6 @@ func (f *IPLDFetcher) FetchRcts(tx *sqlx.Tx, cids []models.ReceiptModel) ([]ipfs return rctIPLDs, nil } -// FetchLogs fetches logs. -func (f *IPLDFetcher) FetchLogs(logCIDs []logResult) ([]*types.Log, error) { - log.Debug("fetching logs") - - logs := make([]*types.Log, len(logCIDs)) - for i, l := range logCIDs { - topics := make([]common.Hash, 0) - if l.Topic0 != "" { - topics = append(topics, common.HexToHash(l.Topic0)) - } - if l.Topic1 != "" { - topics = append(topics, common.HexToHash(l.Topic1)) - } - if l.Topic2 != "" { - topics = append(topics, common.HexToHash(l.Topic2)) - } - if l.Topic3 != "" { - topics = append(topics, common.HexToHash(l.Topic3)) - } - - // TODO: should we convert string to uint ? - blockNum, err := strconv.ParseUint(l.BlockNumber, 10, 64) - if err != nil { - return nil, err - } - - logs[i] = &types.Log{ - Address: common.HexToAddress(l.Address), - Topics: topics, - Data: l.Data, - BlockNumber: blockNum, - TxHash: common.HexToHash(l.TxHash), - TxIndex: uint(l.TxnIndex), - BlockHash: common.HexToHash(l.BlockHash), - Index: uint(l.Index), - } - } - - return logs, nil -} - -type logsCID struct { - Log *types.Log - CID string - RctCID string - RctData []byte - RctStatus uint64 -} - -// FetchGQLLogs fetches logs for graphql. -func (f *IPLDFetcher) FetchGQLLogs(logCIDs []logResult) ([]logsCID, error) { - log.Debug("fetching logs") - - logs := make([]logsCID, len(logCIDs)) - for i, l := range logCIDs { - topics := make([]common.Hash, 0) - if l.Topic0 != "" { - topics = append(topics, common.HexToHash(l.Topic0)) - } - if l.Topic1 != "" { - topics = append(topics, common.HexToHash(l.Topic1)) - } - if l.Topic2 != "" { - topics = append(topics, common.HexToHash(l.Topic2)) - } - if l.Topic3 != "" { - topics = append(topics, common.HexToHash(l.Topic3)) - } - - logs[i] = logsCID{ - Log: &types.Log{ - Address: common.HexToAddress(l.Address), - Topics: topics, - Data: l.Data, - Index: uint(l.Index), - TxHash: common.HexToHash(l.TxHash), - }, - CID: l.LeafCID, - RctCID: l.RctCID, - RctData: l.RctData, - RctStatus: l.RctStatus, - } - } - - return logs, nil -} - // FetchState fetches state nodes func (f *IPLDFetcher) FetchState(tx *sqlx.Tx, cids []models.StateNodeModel) ([]StateNode, error) { log.Debug("fetching state iplds") diff --git a/pkg/eth/test_helpers/test_data.go b/pkg/eth/test_helpers/test_data.go index 3536224d..f769315c 100644 --- a/pkg/eth/test_helpers/test_data.go +++ b/pkg/eth/test_helpers/test_data.go @@ -96,6 +96,7 @@ var ( Address = common.HexToAddress("0xaE9BEa628c4Ce503DcFD7E305CaB4e29E7476592") AnotherAddress = common.HexToAddress("0xaE9BEa628c4Ce503DcFD7E305CaB4e29E7476593") AnotherAddress1 = common.HexToAddress("0xaE9BEa628c4Ce503DcFD7E305CaB4e29E7476594") + AnotherAddress2 = common.HexToAddress("0xaE9BEa628c4Ce503DcFD7E305CaB4e29E7476596") ContractAddress = crypto.CreateAddress(SenderAddr, MockTransactions[2].Nonce()) ContractHash = crypto.Keccak256Hash(ContractAddress.Bytes()).String() MockContractByteCode = []byte{0, 1, 2, 3, 4, 5} @@ -108,6 +109,7 @@ var ( mockTopic42 = common.HexToHash("0x0a") mockTopic43 = common.HexToHash("0x0b") mockTopic51 = common.HexToHash("0x0c") + mockTopic61 = common.HexToHash("0x0d") MockLog1 = &types.Log{ Address: Address, Topics: []common.Hash{mockTopic11, mockTopic12}, @@ -129,8 +131,8 @@ var ( Topics: []common.Hash{mockTopic31}, Data: []byte{}, BlockNumber: BlockNumber.Uint64(), - TxIndex: 1, - Index: 1, + TxIndex: 2, + Index: 2, } MockLog4 = &types.Log{ @@ -138,25 +140,35 @@ var ( Topics: []common.Hash{mockTopic41, mockTopic42, mockTopic43}, Data: []byte{}, BlockNumber: BlockNumber.Uint64(), - TxIndex: 1, - Index: 1, + TxIndex: 2, + Index: 3, } MockLog5 = &types.Log{ Address: AnotherAddress1, Topics: []common.Hash{mockTopic51}, Data: []byte{}, BlockNumber: BlockNumber.Uint64(), - TxIndex: 1, - Index: 1, + TxIndex: 2, + Index: 4, + } + MockLog6 = &types.Log{ + Address: AnotherAddress2, + Topics: []common.Hash{mockTopic61}, + Data: []byte{}, + BlockNumber: BlockNumber.Uint64(), + TxIndex: 3, + Index: 5, } Tx1 = GetTxnRlp(0, MockTransactions) Tx2 = GetTxnRlp(1, MockTransactions) Tx3 = GetTxnRlp(2, MockTransactions) + Tx4 = GetTxnRlp(3, MockTransactions) Rct1 = GetRctRlp(0, MockReceipts) Rct2 = GetRctRlp(1, MockReceipts) Rct3 = GetRctRlp(2, MockReceipts) + Rct4 = GetRctRlp(3, MockReceipts) HeaderCID, _ = ipld.RawdataToCid(ipld.MEthHeader, MockHeaderRlp, multihash.KECCAK_256) HeaderMhKey = shared.MultihashKeyFromCID(HeaderCID) @@ -166,12 +178,16 @@ var ( Trx2MhKey = shared.MultihashKeyFromCID(Trx2CID) Trx3CID, _ = ipld.RawdataToCid(ipld.MEthTx, Tx3, multihash.KECCAK_256) Trx3MhKey = shared.MultihashKeyFromCID(Trx3CID) + Trx4CID, _ = ipld.RawdataToCid(ipld.MEthTx, Tx4, multihash.KECCAK_256) + Trx4MhKey = shared.MultihashKeyFromCID(Trx4CID) Rct1CID, _ = ipld.RawdataToCid(ipld.MEthTxReceipt, Rct1, multihash.KECCAK_256) Rct1MhKey = shared.MultihashKeyFromCID(Rct1CID) Rct2CID, _ = ipld.RawdataToCid(ipld.MEthTxReceipt, Rct2, multihash.KECCAK_256) Rct2MhKey = shared.MultihashKeyFromCID(Rct2CID) Rct3CID, _ = ipld.RawdataToCid(ipld.MEthTxReceipt, Rct3, multihash.KECCAK_256) Rct3MhKey = shared.MultihashKeyFromCID(Rct3CID) + Rct4CID, _ = ipld.RawdataToCid(ipld.MEthTxReceipt, Rct4, multihash.KECCAK_256) + Rct4MhKey = shared.MultihashKeyFromCID(Rct4CID) State1CID, _ = ipld.RawdataToCid(ipld.MEthStateTrie, ContractLeafNode, multihash.KECCAK_256) State1MhKey = shared.MultihashKeyFromCID(State1CID) State2CID, _ = ipld.RawdataToCid(ipld.MEthStateTrie, AccountLeafNode, multihash.KECCAK_256) @@ -206,6 +222,15 @@ var ( TxHash: MockTransactions[2].Hash().String(), Data: MockContractByteCode, }, + { + CID: "", + MhKey: "", + Src: SenderAddr.Hex(), + Dst: "", + Index: 3, + TxHash: MockTransactions[3].Hash().String(), + Data: []byte{}, + }, } MockTrxMetaPostPublsh = []models.TxModel{ { @@ -235,6 +260,15 @@ var ( TxHash: MockTransactions[2].Hash().String(), Data: MockContractByteCode, }, + { + CID: Trx4CID.String(), + MhKey: Trx4MhKey, + Src: SenderAddr.Hex(), + Dst: "", + Index: 2, + TxHash: MockTransactions[2].Hash().String(), + Data: MockContractByteCode, + }, } MockRctMeta = []models.ReceiptModel{ { @@ -255,6 +289,12 @@ var ( Contract: ContractAddress.String(), ContractHash: ContractHash, }, + { + CID: "", + MhKey: "", + Contract: "", + ContractHash: "", + }, } MockRctMetaPostPublish = []models.ReceiptModel{ { @@ -275,6 +315,12 @@ var ( Contract: ContractAddress.String(), ContractHash: ContractHash, }, + { + CID: Rct4CID.String(), + MhKey: Rct4MhKey, + Contract: "", + ContractHash: "", + }, } // statediff data @@ -431,9 +477,11 @@ var ( Trx1IPLD, _ = blocks.NewBlockWithCid(Tx1, Trx1CID) Trx2IPLD, _ = blocks.NewBlockWithCid(Tx2, Trx2CID) Trx3IPLD, _ = blocks.NewBlockWithCid(Tx3, Trx3CID) + Trx4IPLD, _ = blocks.NewBlockWithCid(Tx4, Trx4CID) Rct1IPLD, _ = blocks.NewBlockWithCid(Rct1, Rct1CID) Rct2IPLD, _ = blocks.NewBlockWithCid(Rct2, Rct2CID) Rct3IPLD, _ = blocks.NewBlockWithCid(Rct3, Rct3CID) + Rct4IPLD, _ = blocks.NewBlockWithCid(Rct4, Rct4CID) State1IPLD, _ = blocks.NewBlockWithCid(ContractLeafNode, State1CID) State2IPLD, _ = blocks.NewBlockWithCid(AccountLeafNode, State2CID) StorageIPLD, _ = blocks.NewBlockWithCid(StorageLeafNode, StorageCID) @@ -457,6 +505,10 @@ var ( Data: Trx3IPLD.RawData(), CID: Trx3IPLD.Cid().String(), }, + { + Data: Trx4IPLD.RawData(), + CID: Trx4IPLD.Cid().String(), + }, }, Receipts: []ipfs.BlockModel{ { @@ -471,6 +523,10 @@ var ( Data: Rct3IPLD.RawData(), CID: Rct3IPLD.Cid().String(), }, + { + Data: Rct4IPLD.RawData(), + CID: Rct4IPLD.Cid().String(), + }, }, StateNodes: []eth.StateNode{ { @@ -584,6 +640,7 @@ func createLegacyTransactionsAndReceipts() (types.Transactions, types.Receipts, trx1 := types.NewTransaction(0, Address, big.NewInt(1000), 50, big.NewInt(100), []byte{}) trx2 := types.NewTransaction(1, AnotherAddress, big.NewInt(2000), 100, big.NewInt(200), []byte{}) trx3 := types.NewContractCreation(2, big.NewInt(1500), 75, big.NewInt(150), MockContractByteCode) + trx4 := types.NewTransaction(3, AnotherAddress1, big.NewInt(2000), 100, big.NewInt(200), []byte{}) transactionSigner := types.MakeSigner(params.MainnetChainConfig, new(big.Int).Set(BlockNumber)) mockCurve := elliptic.P256() mockPrvKey, err := ecdsa.GenerateKey(mockCurve, rand.Reader) @@ -602,6 +659,10 @@ func createLegacyTransactionsAndReceipts() (types.Transactions, types.Receipts, if err != nil { log.Fatal(err) } + signedTrx4, err := types.SignTx(trx4, transactionSigner, mockPrvKey) + if err != nil { + log.Fatal(err) + } SenderAddr, err := types.Sender(transactionSigner, signedTrx1) // same for both trx if err != nil { log.Fatal(err) @@ -629,7 +690,13 @@ func createLegacyTransactionsAndReceipts() (types.Transactions, types.Receipts, mockReceipt3.TxHash = signedTrx3.Hash() mockReceipt3.GasUsed = mockReceipt3.CumulativeGasUsed - mockReceipt2.CumulativeGasUsed - return types.Transactions{signedTrx1, signedTrx2, signedTrx3}, types.Receipts{mockReceipt1, mockReceipt2, mockReceipt3}, SenderAddr + // Receipt with failed status. + mockReceipt4 := types.NewReceipt(nil, true, 250) + mockReceipt4.Logs = []*types.Log{MockLog6} + mockReceipt4.TxHash = signedTrx4.Hash() + mockReceipt4.GasUsed = mockReceipt4.CumulativeGasUsed - mockReceipt3.CumulativeGasUsed + + return types.Transactions{signedTrx1, signedTrx2, signedTrx3, signedTrx4}, types.Receipts{mockReceipt1, mockReceipt2, mockReceipt3, mockReceipt4}, SenderAddr } func GetTxnRlp(num int, txs types.Transactions) []byte { diff --git a/pkg/eth/types.go b/pkg/eth/types.go index eeecbb2a..2522bc83 100644 --- a/pkg/eth/types.go +++ b/pkg/eth/types.go @@ -167,8 +167,8 @@ type ConvertedPayload struct { StorageNodes map[string][]sdtypes.StorageNode } -// logResult represent a log. -type logResult struct { +// LogResult represent a log. +type LogResult struct { ID int64 `db:"id"` LeafCID string `db:"leaf_cid"` LeafMhKey string `db:"leaf_mh_key"` @@ -180,7 +180,7 @@ type logResult struct { Topic1 string `db:"topic1"` Topic2 string `db:"topic2"` Topic3 string `db:"topic3"` - RctData []byte `db:"data"` + LogLeafData []byte `db:"data"` RctCID string `db:"cid"` RctStatus uint64 `db:"post_status"` BlockNumber string `db:"block_number"` diff --git a/pkg/graphql/client.go b/pkg/graphql/client.go index 9c903c40..5954060a 100644 --- a/pkg/graphql/client.go +++ b/pkg/graphql/client.go @@ -24,6 +24,7 @@ type LogResponse struct { Topics []common.Hash `json:"topics"` Data hexutil.Bytes `json:"data"` Transaction TransactionResp `json:"transaction"` + ReceiptCID string `json:"receiptCID"` Status int32 `json:"status"` } @@ -54,6 +55,7 @@ func (c *Client) GetLogs(ctx context.Context, hash common.Hash, address common.A hash } status + receiptCID } } `, hash.String(), address.String()) diff --git a/pkg/graphql/graphql.go b/pkg/graphql/graphql.go index 0ecd84b6..d6029f91 100644 --- a/pkg/graphql/graphql.go +++ b/pkg/graphql/graphql.go @@ -94,15 +94,17 @@ type Log struct { log *types.Log cid string receiptCID string - ipldBlock []byte + ipldBlock []byte // log leaf node IPLD block data status uint64 } -func (l *Log) Transaction(ctx context.Context) *Transaction { +// Transaction returns transaction that generated this log entry. +func (l *Log) Transaction(_ context.Context) *Transaction { return l.transaction } -func (l *Log) Account(ctx context.Context, args BlockNumberArgs) *Account { +// Account returns the contract account which generated this log. +func (l *Log) Account(_ context.Context, args BlockNumberArgs) *Account { return &Account{ backend: l.backend, address: l.log.Address, @@ -110,30 +112,41 @@ func (l *Log) Account(ctx context.Context, args BlockNumberArgs) *Account { } } -func (l *Log) Index(ctx context.Context) int32 { +// Index returns the index of this log in the block +func (l *Log) Index(_ context.Context) int32 { return int32(l.log.Index) } -func (l *Log) Topics(ctx context.Context) []common.Hash { +// Topics returns the list of 0-4 indexed topics for the log. +func (l *Log) Topics(_ context.Context) []common.Hash { return l.log.Topics } -func (l *Log) Data(ctx context.Context) hexutil.Bytes { - return hexutil.Bytes(l.log.Data) +// Data returns data of this log. +func (l *Log) Data(_ context.Context) hexutil.Bytes { + return l.log.Data } -func (l *Log) Cid(ctx context.Context) string { +// Cid returns cid of the leaf node of this log. +func (l *Log) Cid(_ context.Context) string { return l.cid } -func (l *Log) IpldBlock(ctx context.Context) hexutil.Bytes { - return hexutil.Bytes(l.ipldBlock) +// IpldBlock returns IPLD block of the leaf node of this log. +func (l *Log) IpldBlock(_ context.Context) hexutil.Bytes { + return l.ipldBlock } -func (l *Log) Status(ctx context.Context) int32 { +// Status returns the status of the receipt IPLD block this Log exists in. +func (l *Log) Status(_ context.Context) int32 { return int32(l.status) } +// ReceiptCID returns the receipt CID of the receipt IPLD block this Log exists in. +func (l *Log) ReceiptCID(_ context.Context) string { + return l.receiptCID +} + // Transaction represents an Ethereum transaction. // backend and hash are mandatory; all others will be fetched when required. type Transaction struct { @@ -1033,7 +1046,7 @@ func (r *Resolver) GetLogs(ctx context.Context, args struct { return nil, err } - rctLog, err := r.backend.Fetcher.FetchGQLLogs(filteredLogs) + rctLog := decomposeGQLLogs(filteredLogs) if err != nil { return nil, err } @@ -1044,7 +1057,7 @@ func (r *Resolver) GetLogs(ctx context.Context, args struct { log: l.Log, cid: l.CID, receiptCID: l.RctCID, - ipldBlock: l.RctData, + ipldBlock: l.LogLeafData, transaction: &Transaction{ hash: l.Log.TxHash, }, @@ -1054,3 +1067,47 @@ func (r *Resolver) GetLogs(ctx context.Context, args struct { return &ret, nil } + +type logsCID struct { + Log *types.Log + CID string + RctCID string + LogLeafData []byte + RctStatus uint64 +} + +// decomposeGQLLogs return logs for graphql. +func decomposeGQLLogs(logCIDs []eth.LogResult) []logsCID { + logs := make([]logsCID, len(logCIDs)) + for i, l := range logCIDs { + topics := make([]common.Hash, 0) + if l.Topic0 != "" { + topics = append(topics, common.HexToHash(l.Topic0)) + } + if l.Topic1 != "" { + topics = append(topics, common.HexToHash(l.Topic1)) + } + if l.Topic2 != "" { + topics = append(topics, common.HexToHash(l.Topic2)) + } + if l.Topic3 != "" { + topics = append(topics, common.HexToHash(l.Topic3)) + } + + logs[i] = logsCID{ + Log: &types.Log{ + Address: common.HexToAddress(l.Address), + Topics: topics, + Data: l.Data, + Index: uint(l.Index), + TxHash: common.HexToHash(l.TxHash), + }, + CID: l.LeafCID, + RctCID: l.RctCID, + LogLeafData: l.LogLeafData, + RctStatus: l.RctStatus, + } + } + + return logs +} diff --git a/pkg/graphql/graphql_test.go b/pkg/graphql/graphql_test.go index af73b94f..afd01694 100644 --- a/pkg/graphql/graphql_test.go +++ b/pkg/graphql/graphql_test.go @@ -191,9 +191,28 @@ var _ = Describe("GraphQL", func() { Topics: test_helpers.MockLog1.Topics, Data: hexutil.Bytes(test_helpers.MockLog1.Data), Transaction: graphql.TransactionResp{Hash: test_helpers.MockTransactions[0].Hash()}, + ReceiptCID: test_helpers.Rct1CID.String(), Status: int32(test_helpers.MockReceipts[0].Status), }, } + + Expect(logs).To(Equal(expectedLogs)) + }) + + 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) + Expect(err).ToNot(HaveOccurred()) + + expectedLogs := []graphql.LogResponse{ + { + Topics: test_helpers.MockLog6.Topics, + Data: hexutil.Bytes(test_helpers.MockLog6.Data), + Transaction: graphql.TransactionResp{Hash: test_helpers.MockTransactions[3].Hash()}, + ReceiptCID: test_helpers.Rct4CID.String(), + Status: int32(test_helpers.MockReceipts[3].Status), + }, + } + Expect(logs).To(Equal(expectedLogs)) }) diff --git a/pkg/graphql/schema.go b/pkg/graphql/schema.go index 9b219e08..4a534297 100644 --- a/pkg/graphql/schema.go +++ b/pkg/graphql/schema.go @@ -67,14 +67,17 @@ const schema string = ` # Transaction is the transaction that generated this log entry. transaction: Transaction - # CID for the Receipt IPLD block this Log exists in. + # CID for the Receipt IPLD block of leaf node. cid: String! - # IPLD block data for the Receipt this Log exists in. + # ReceiptCID for the Receipt IPLD block this Log exists in. + receiptCID: String! + + # IPLD block data for the Log Leaf node. ipldBlock: Bytes! - # Status of the Receipt IPLD block this Log exists in. - status: Int! + # Status of the Receipt IPLD block this Log exists in. + status: Int! } # Transaction is an Ethereum transaction.