diff --git a/db/migrations/00006_create_eth_transaction_cids_table.sql b/db/migrations/00006_create_eth_transaction_cids_table.sql index fc65932d..2ac1ca39 100644 --- a/db/migrations/00006_create_eth_transaction_cids_table.sql +++ b/db/migrations/00006_create_eth_transaction_cids_table.sql @@ -10,6 +10,7 @@ CREATE TABLE eth.transaction_cids ( src VARCHAR(66) NOT NULL, tx_data BYTEA, tx_type BYTEA, + gas INTEGER NOT NULL, UNIQUE (header_id, tx_hash) ); diff --git a/db/migrations/00007_create_eth_receipt_cids_table.sql b/db/migrations/00007_create_eth_receipt_cids_table.sql index 5ee8c92c..1c82db23 100644 --- a/db/migrations/00007_create_eth_receipt_cids_table.sql +++ b/db/migrations/00007_create_eth_receipt_cids_table.sql @@ -9,6 +9,7 @@ CREATE TABLE eth.receipt_cids ( post_state VARCHAR(66), post_status INTEGER, log_root VARCHAR(66), + gas_used INTEGER NOT NULL, UNIQUE (tx_id) ); diff --git a/go.mod b/go.mod index a7d1b5a8..f68ee8cd 100644 --- a/go.mod +++ b/go.mod @@ -27,6 +27,6 @@ require ( github.com/vulcanize/ipfs-ethdb v0.0.4-0.20210824131459-7bb49801fc12 ) -replace github.com/ethereum/go-ethereum v1.10.8 => github.com/vulcanize/go-ethereum v1.10.8-statediff-0.0.26 +replace github.com/ethereum/go-ethereum v1.10.8 => /Users/arijitdas/go/src/github.com/ethereum/go-ethereum replace github.com/vulcanize/ipfs-ethdb v0.0.2-alpha => github.com/vulcanize/pg-ipfs-ethdb v0.0.2-alpha diff --git a/go.sum b/go.sum index 5a5f3b5a..0908dec0 100644 --- a/go.sum +++ b/go.sum @@ -711,8 +711,6 @@ github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPU github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/vulcanize/gap-filler v0.3.1 h1:N5d+jCJo/VTWFvBSbTD7biRhK/OqDZzi1tgA85SIBKs= github.com/vulcanize/gap-filler v0.3.1/go.mod h1:qowG1cgshVpBqMokiWro/1xhh0uypw7oAu8FQ42JMy4= -github.com/vulcanize/go-ethereum v1.10.8-statediff-0.0.26 h1:1UBVQpeJnHkmSKxXanbNGE8w+LR0iZhfGr0QrQ62+C4= -github.com/vulcanize/go-ethereum v1.10.8-statediff-0.0.26/go.mod h1:nXs5fPBjAVzBmIGtrc0f7akQwkXI5Mi+6I1QcbD2br0= github.com/vulcanize/ipfs-ethdb v0.0.4-0.20210824131459-7bb49801fc12 h1:IKqHA89qA+VZBYt1nZ1EInVrAgB3iA5U+klkF4l8mn4= github.com/vulcanize/ipfs-ethdb v0.0.4-0.20210824131459-7bb49801fc12/go.mod h1:IueWysMbZu0uFmu+ia6mEnyWsTvwe2q2lbYdy2muRUM= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= diff --git a/pkg/eth/api.go b/pkg/eth/api.go index e9e9c922..be0cb2ac 100644 --- a/pkg/eth/api.go +++ b/pkg/eth/api.go @@ -524,12 +524,18 @@ func (pea *PublicEthAPI) localGetTransactionReceipt(ctx context.Context, hash co "logsBloom": receipt.Bloom, } - // Assign receipt status or post state. - if len(receipt.PostState) > 0 { + if blockNumber <= pea.B.Config.ChainConfig.ByzantiumBlock.Uint64() { + if receipt.GasUsed > tx.Gas() { + fields["status"] = hexutil.Uint(types.ReceiptStatusFailed) + } else { + fields["status"] = hexutil.Uint(types.ReceiptStatusSuccessful) + } + } else if len(receipt.PostState) > 0 { fields["root"] = hexutil.Bytes(receipt.PostState) } else { fields["status"] = hexutil.Uint(receipt.Status) } + if receipt.Logs == nil { fields["logs"] = []*types.Log{} } diff --git a/pkg/eth/api_test.go b/pkg/eth/api_test.go index 57866cab..b72eec99 100644 --- a/pkg/eth/api_test.go +++ b/pkg/eth/api_test.go @@ -43,15 +43,16 @@ import ( ) var ( - randomAddr = common.HexToAddress("0x1C3ab14BBaD3D99F4203bd7a11aCB94882050E6f") - randomHash = crypto.Keccak256Hash(randomAddr.Bytes()) - number = rpc.BlockNumber(test_helpers.BlockNumber.Int64()) - londonBlockNum = rpc.BlockNumber(test_helpers.LondonBlockNum.Int64()) - wrongNumber = number + 1 - blockHash = test_helpers.MockBlock.Header().Hash() - baseFee = test_helpers.MockLondonBlock.BaseFee() - ctx = context.Background() - expectedBlock = map[string]interface{}{ + randomAddr = common.HexToAddress("0x1C3ab14BBaD3D99F4203bd7a11aCB94882050E6f") + randomHash = crypto.Keccak256Hash(randomAddr.Bytes()) + number = rpc.BlockNumber(test_helpers.BlockNumber.Int64()) + londonBlockNum = rpc.BlockNumber(test_helpers.LondonBlockNum.Int64()) + byzantiumBlockNum = rpc.BlockNumber(test_helpers.ByzantiumBlockNum.Int64()) + wrongNumber = number + 1 + blockHash = test_helpers.MockBlock.Header().Hash() + baseFee = test_helpers.MockLondonBlock.BaseFee() + ctx = context.Background() + expectedBlock = map[string]interface{}{ "number": (*hexutil.Big)(test_helpers.MockBlock.Number()), "hash": test_helpers.MockBlock.Hash(), "parentHash": test_helpers.MockBlock.ParentHash(), @@ -131,14 +132,15 @@ var ( "receiptsRoot": test_helpers.MockUncles[1].ReceiptHash, "uncles": []common.Hash{}, } - expectedTransaction = eth.NewRPCTransaction(test_helpers.MockTransactions[0], test_helpers.MockBlock.Hash(), test_helpers.MockBlock.NumberU64(), 0, test_helpers.MockBlock.BaseFee()) - expectedTransaction2 = eth.NewRPCTransaction(test_helpers.MockTransactions[1], test_helpers.MockBlock.Hash(), test_helpers.MockBlock.NumberU64(), 1, test_helpers.MockBlock.BaseFee()) - expectedTransaction3 = eth.NewRPCTransaction(test_helpers.MockTransactions[2], test_helpers.MockBlock.Hash(), test_helpers.MockBlock.NumberU64(), 2, test_helpers.MockBlock.BaseFee()) - expectedLondonTransaction = eth.NewRPCTransaction(test_helpers.MockLondonTransactions[0], test_helpers.MockLondonBlock.Hash(), test_helpers.MockLondonBlock.NumberU64(), 0, test_helpers.MockLondonBlock.BaseFee()) - expectRawTx, _ = rlp.EncodeToBytes(test_helpers.MockTransactions[0]) - expectRawTx2, _ = rlp.EncodeToBytes(test_helpers.MockTransactions[1]) - expectRawTx3, _ = rlp.EncodeToBytes(test_helpers.MockTransactions[2]) - expectedReceipt = map[string]interface{}{ + expectedTransaction = eth.NewRPCTransaction(test_helpers.MockTransactions[0], test_helpers.MockBlock.Hash(), test_helpers.MockBlock.NumberU64(), 0, test_helpers.MockBlock.BaseFee()) + expectedTransaction2 = eth.NewRPCTransaction(test_helpers.MockTransactions[1], test_helpers.MockBlock.Hash(), test_helpers.MockBlock.NumberU64(), 1, test_helpers.MockBlock.BaseFee()) + expectedTransaction3 = eth.NewRPCTransaction(test_helpers.MockTransactions[2], test_helpers.MockBlock.Hash(), test_helpers.MockBlock.NumberU64(), 2, test_helpers.MockBlock.BaseFee()) + expectedLondonTransaction = eth.NewRPCTransaction(test_helpers.MockLondonTransactions[0], test_helpers.MockLondonBlock.Hash(), test_helpers.MockLondonBlock.NumberU64(), 0, test_helpers.MockLondonBlock.BaseFee()) + expectedByzantiumTransaction = eth.NewRPCTransaction(test_helpers.MockByzantiumTransactions[0], test_helpers.MockByzantiumBlock.Hash(), test_helpers.MockByzantiumBlock.NumberU64(), 0, test_helpers.MockByzantiumBlock.BaseFee()) + expectRawTx, _ = rlp.EncodeToBytes(test_helpers.MockTransactions[0]) + expectRawTx2, _ = rlp.EncodeToBytes(test_helpers.MockTransactions[1]) + expectRawTx3, _ = rlp.EncodeToBytes(test_helpers.MockTransactions[2]) + expectedReceipt = map[string]interface{}{ "blockHash": blockHash, "blockNumber": hexutil.Uint64(uint64(number.Int64())), "transactionHash": expectedTransaction.Hash, @@ -180,6 +182,20 @@ var ( "logsBloom": test_helpers.MockReceipts[2].Bloom, "root": hexutil.Bytes(test_helpers.MockReceipts[2].PostState), } + expectedByzantiumReceipt = map[string]interface{}{ + "blockHash": test_helpers.MockByzantiumBlock.Hash(), + "blockNumber": hexutil.Uint64(uint64(byzantiumBlockNum)), + "transactionHash": expectedByzantiumTransaction.Hash, + "transactionIndex": hexutil.Uint64(0), + "from": expectedByzantiumTransaction.From, + "to": expectedByzantiumTransaction.To, + "gasUsed": hexutil.Uint64(test_helpers.MockByzantiumReceipts[0].GasUsed), + "cumulativeGasUsed": hexutil.Uint64(test_helpers.MockByzantiumReceipts[0].CumulativeGasUsed), + "contractAddress": nil, + "logs": test_helpers.MockByzantiumReceipts[0].Logs, + "logsBloom": test_helpers.MockByzantiumReceipts[0].Bloom, + "status": hexutil.Uint(test_helpers.MockByzantiumReceipts[0].Status), + } ) // SetupDB is use to setup a db for watcher tests @@ -210,6 +226,13 @@ var _ = Describe("API", func() { db, err = SetupDB() Expect(err).ToNot(HaveOccurred()) + + // setting chain config to for byzantium block + chainConfig.ByzantiumBlock = big.NewInt(1) + + // setting chain config to for london block + chainConfig.LondonBlock = big.NewInt(3) + indexAndPublisher := indexer.NewStateDiffIndexer(chainConfig, db) backend, err := eth.NewEthBackend(db, ð.Config{ ChainConfig: chainConfig, @@ -249,14 +272,17 @@ var _ = Describe("API", func() { } expectedBlock["uncles"] = uncleHashes - // setting chain config to for london block - chainConfig.LondonBlock = big.NewInt(2) - indexAndPublisher = indexer.NewStateDiffIndexer(chainConfig, db) tx, err = indexAndPublisher.PushBlock(test_helpers.MockLondonBlock, test_helpers.MockLondonReceipts, test_helpers.MockLondonBlock.Difficulty()) Expect(err).ToNot(HaveOccurred()) err = tx.Close(err) Expect(err).ToNot(HaveOccurred()) + + tx, err = indexAndPublisher.PushBlock(test_helpers.MockByzantiumBlock, test_helpers.MockByzantiumReceipts, test_helpers.MockByzantiumBlock.Difficulty()) + Expect(err).ToNot(HaveOccurred()) + + err = tx.Close(err) + Expect(err).ToNot(HaveOccurred()) }) // Single test db tear down at end of all tests @@ -644,6 +670,13 @@ var _ = Describe("API", func() { _, err := api.GetTransactionReceipt(ctx, randomHash) Expect(err).To(HaveOccurred()) }) + + It("Retrieve receipt for pre byzantium block transaction", func() { + hash := test_helpers.MockByzantiumTransactions[0].Hash() + tx, err := api.GetTransactionReceipt(ctx, hash) + Expect(err).ToNot(HaveOccurred()) + Expect(tx).To(Equal(expectedByzantiumReceipt)) + }) }) Describe("eth_getLogs", func() { diff --git a/pkg/eth/backend.go b/pkg/eth/backend.go index 16e3a6bc..4f3bdecf 100644 --- a/pkg/eth/backend.go +++ b/pkg/eth/backend.go @@ -22,6 +22,7 @@ import ( "errors" "fmt" "math/big" + "strconv" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -472,6 +473,7 @@ func (b *Backend) GetTransaction(ctx context.Context, txHash common.Hash) (*type BlockHash string `db:"block_hash"` BlockNumber uint64 `db:"block_number"` Index uint64 `db:"index"` + Gas uint64 `db:"gas"` } if err := b.DB.Get(&tempTxStruct, RetrieveRPCTransaction, txHash.String()); err != nil { return nil, common.Hash{}, 0, 0, err @@ -799,6 +801,67 @@ func (b *Backend) RPCGasCap() *big.Int { return b.Config.RPCGasCap } +type logsCID struct { + Log *types.Log + CID string + RctCID string + LogLeafData []byte + RctStatus uint64 +} + +// DecomposeGQLLogs return logs for graphql. +func (b *Backend) DecomposeGQLLogs(logCIDs []LogResult) ([]logsCID, error) { + 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)) + } + + // TODO: should we convert string to uint ? + blockNum, err := strconv.ParseUint(l.BlockNumber, 10, 64) + if err != nil { + return nil, err + } + + var status uint64 + if blockNum <= b.Config.ChainConfig.ByzantiumBlock.Uint64() { + if l.RctGasUsed > l.Gas { + status = types.ReceiptStatusFailed + } else { + status = types.ReceiptStatusSuccessful + } + } else { + status = l.RctStatus + } + + 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: status, + } + } + + return logs, nil +} + func (b *Backend) SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription { panic("implement me") } diff --git a/pkg/eth/cid_retriever.go b/pkg/eth/cid_retriever.go index dac04955..ec41dcc0 100644 --- a/pkg/eth/cid_retriever.go +++ b/pkg/eth/cid_retriever.go @@ -316,7 +316,8 @@ func (ecr *CIDRetriever) RetrieveFilteredGQLLogs(tx *sqlx.Tx, rctFilter ReceiptF id := 1 pgStr := `SELECT eth.log_cids.leaf_cid, eth.log_cids.index, eth.log_cids.receipt_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, data, eth.receipt_cids.cid, eth.receipt_cids.post_status + eth.log_cids.log_data, eth.transaction_cids.tx_hash, eth.transaction_cids.gas, data, eth.receipt_cids.cid, eth.receipt_cids.post_status, + eth.receipt_cids.gas_used,header_cids.block_number FROM eth.log_cids, eth.receipt_cids, eth.transaction_cids, eth.header_cids, public.blocks WHERE eth.log_cids.receipt_id = receipt_cids.id AND receipt_cids.tx_id = transaction_cids.id @@ -375,7 +376,7 @@ func (ecr *CIDRetriever) RetrieveFilteredLog(tx *sqlx.Tx, rctFilter ReceiptFilte return logCIDs, nil } -// RetrieveRctCIDs retrieves and returns all of the rct cids at the provided blockheight or block hash that conform to the provided +// RetrieveRctCIDs retrieves and returns all the rct cIDs at the provided blockHeight or block hash that conform to the provided // filter parameters and correspond to the provided tx ids func (ecr *CIDRetriever) RetrieveRctCIDs(tx *sqlx.Tx, rctFilter ReceiptFilter, blockNumber int64, blockHash *common.Hash, trxIds []int64) ([]models.ReceiptModel, error) { log.Debug("retrieving receipt cids for block ", blockNumber) diff --git a/pkg/eth/cid_retriever_test.go b/pkg/eth/cid_retriever_test.go index e972aee3..c624b4e6 100644 --- a/pkg/eth/cid_retriever_test.go +++ b/pkg/eth/cid_retriever_test.go @@ -37,7 +37,7 @@ import ( var ( openFilter = eth.SubscriptionSettings{ Start: big.NewInt(0), - End: big.NewInt(1), + End: big.NewInt(number.Int64()), HeaderFilter: eth.HeaderFilter{}, TxFilter: eth.TxFilter{}, ReceiptFilter: eth.ReceiptFilter{}, @@ -46,7 +46,7 @@ var ( } rctAddressFilter = eth.SubscriptionSettings{ Start: big.NewInt(0), - End: big.NewInt(1), + End: big.NewInt(number.Int64()), HeaderFilter: eth.HeaderFilter{ Off: true, }, @@ -65,7 +65,7 @@ var ( } rctTopicsFilter = eth.SubscriptionSettings{ Start: big.NewInt(0), - End: big.NewInt(1), + End: big.NewInt(number.Int64()), HeaderFilter: eth.HeaderFilter{ Off: true, }, @@ -84,7 +84,7 @@ var ( } rctTopicsAndAddressFilter = eth.SubscriptionSettings{ Start: big.NewInt(0), - End: big.NewInt(1), + End: big.NewInt(number.Int64()), HeaderFilter: eth.HeaderFilter{ Off: true, }, @@ -107,7 +107,7 @@ var ( } rctTopicsAndAddressFilterFail = eth.SubscriptionSettings{ Start: big.NewInt(0), - End: big.NewInt(1), + End: big.NewInt(number.Int64()), HeaderFilter: eth.HeaderFilter{ Off: true, }, @@ -130,7 +130,7 @@ var ( } rctAddressesAndTopicFilter = eth.SubscriptionSettings{ Start: big.NewInt(0), - End: big.NewInt(1), + End: big.NewInt(number.Int64()), HeaderFilter: eth.HeaderFilter{ Off: true, }, @@ -150,7 +150,7 @@ var ( } rctsForAllCollectedTrxs = eth.SubscriptionSettings{ Start: big.NewInt(0), - End: big.NewInt(1), + End: big.NewInt(number.Int64()), HeaderFilter: eth.HeaderFilter{ Off: true, }, @@ -169,7 +169,7 @@ var ( } rctsForSelectCollectedTrxs = eth.SubscriptionSettings{ Start: big.NewInt(0), - End: big.NewInt(1), + End: big.NewInt(number.Int64()), HeaderFilter: eth.HeaderFilter{ Off: true, }, @@ -190,7 +190,7 @@ var ( } stateFilter = eth.SubscriptionSettings{ Start: big.NewInt(0), - End: big.NewInt(1), + End: big.NewInt(number.Int64()), HeaderFilter: eth.HeaderFilter{ Off: true, }, @@ -239,7 +239,7 @@ var _ = Describe("Retriever", func() { Expect(err).ToNot(HaveOccurred()) }) It("Retrieves all CIDs for the given blocknumber when provided an open filter", func() { - cids, empty, err := retriever.Retrieve(openFilter, 1) + cids, empty, err := retriever.Retrieve(openFilter, number.Int64()) Expect(err).ToNot(HaveOccurred()) Expect(empty).ToNot(BeTrue()) Expect(len(cids)).To(Equal(1)) @@ -279,7 +279,7 @@ var _ = Describe("Retriever", func() { }) It("Applies filters from the provided config.Subscription", func() { - cids1, empty, err := retriever.Retrieve(rctAddressFilter, 1) + cids1, empty, err := retriever.Retrieve(rctAddressFilter, number.Int64()) Expect(err).ToNot(HaveOccurred()) Expect(empty).ToNot(BeTrue()) Expect(len(cids1)).To(Equal(1)) @@ -294,7 +294,7 @@ var _ = Describe("Retriever", func() { expectedReceiptCID.TxID = cids1[0].Receipts[0].TxID Expect(cids1[0].Receipts[0]).To(Equal(expectedReceiptCID)) - cids2, empty, err := retriever.Retrieve(rctTopicsFilter, 1) + cids2, empty, err := retriever.Retrieve(rctTopicsFilter, number.Int64()) Expect(err).ToNot(HaveOccurred()) Expect(empty).ToNot(BeTrue()) Expect(len(cids2)).To(Equal(1)) @@ -309,7 +309,7 @@ var _ = Describe("Retriever", func() { expectedReceiptCID.TxID = cids2[0].Receipts[0].TxID Expect(cids2[0].Receipts[0]).To(Equal(expectedReceiptCID)) - cids3, empty, err := retriever.Retrieve(rctTopicsAndAddressFilter, 1) + cids3, empty, err := retriever.Retrieve(rctTopicsAndAddressFilter, number.Int64()) Expect(err).ToNot(HaveOccurred()) Expect(empty).ToNot(BeTrue()) Expect(len(cids3)).To(Equal(1)) @@ -324,7 +324,7 @@ var _ = Describe("Retriever", func() { expectedReceiptCID.TxID = cids3[0].Receipts[0].TxID Expect(cids3[0].Receipts[0]).To(Equal(expectedReceiptCID)) - cids4, empty, err := retriever.Retrieve(rctAddressesAndTopicFilter, 1) + cids4, empty, err := retriever.Retrieve(rctAddressesAndTopicFilter, number.Int64()) Expect(err).ToNot(HaveOccurred()) Expect(empty).ToNot(BeTrue()) Expect(len(cids4)).To(Equal(1)) @@ -339,7 +339,7 @@ var _ = Describe("Retriever", func() { expectedReceiptCID.TxID = cids4[0].Receipts[0].TxID Expect(cids4[0].Receipts[0]).To(Equal(expectedReceiptCID)) - cids5, empty, err := retriever.Retrieve(rctsForAllCollectedTrxs, 1) + cids5, empty, err := retriever.Retrieve(rctsForAllCollectedTrxs, number.Int64()) Expect(err).ToNot(HaveOccurred()) Expect(empty).ToNot(BeTrue()) Expect(len(cids5)).To(Equal(1)) @@ -356,7 +356,7 @@ var _ = Describe("Retriever", func() { Expect(eth.ReceiptModelsContainsCID(cids5[0].Receipts, test_helpers.Rct2CID.String())).To(BeTrue()) Expect(eth.ReceiptModelsContainsCID(cids5[0].Receipts, test_helpers.Rct3CID.String())).To(BeTrue()) - cids6, empty, err := retriever.Retrieve(rctsForSelectCollectedTrxs, 1) + cids6, empty, err := retriever.Retrieve(rctsForSelectCollectedTrxs, number.Int64()) Expect(err).ToNot(HaveOccurred()) Expect(empty).ToNot(BeTrue()) Expect(len(cids6)).To(Equal(1)) @@ -375,7 +375,7 @@ var _ = Describe("Retriever", func() { expectedReceiptCID.TxID = cids6[0].Receipts[0].TxID Expect(cids6[0].Receipts[0]).To(Equal(expectedReceiptCID)) - cids7, empty, err := retriever.Retrieve(stateFilter, 1) + cids7, empty, err := retriever.Retrieve(stateFilter, number.Int64()) Expect(err).ToNot(HaveOccurred()) Expect(empty).ToNot(BeTrue()) Expect(len(cids7)).To(Equal(1)) @@ -415,7 +415,7 @@ var _ = Describe("Retriever", func() { num, err := retriever.RetrieveFirstBlockNumber() Expect(err).ToNot(HaveOccurred()) - Expect(num).To(Equal(int64(1))) + Expect(num).To(Equal(number.Int64())) }) It("Gets the number of the first block that has data in the database", func() { @@ -466,7 +466,7 @@ var _ = Describe("Retriever", func() { num, err := retriever.RetrieveLastBlockNumber() Expect(err).ToNot(HaveOccurred()) - Expect(num).To(Equal(int64(1))) + Expect(num).To(Equal(number.Int64())) }) It("Gets the number of the latest block that has data in the database", func() { diff --git a/pkg/eth/eth_state_test.go b/pkg/eth/eth_state_test.go index d8ba5e73..bca1cce2 100644 --- a/pkg/eth/eth_state_test.go +++ b/pkg/eth/eth_state_test.go @@ -97,7 +97,7 @@ var _ = Describe("eth state reading tests", func() { IntermediateStateNodes: true, IntermediateStorageNodes: true, } - canonicalHeader := blocks[1].Header() + canonicalHeader := blocks[2].Header() expectedCanonicalHeader = map[string]interface{}{ "number": (*hexutil.Big)(canonicalHeader.Number), "hash": canonicalHeader.Hash(), diff --git a/pkg/eth/test_helpers/test_data.go b/pkg/eth/test_helpers/test_data.go index f769315c..622ed9d4 100644 --- a/pkg/eth/test_helpers/test_data.go +++ b/pkg/eth/test_helpers/test_data.go @@ -47,7 +47,7 @@ import ( // Test variables var ( // block data - BlockNumber = big.NewInt(1) + BlockNumber = big.NewInt(2) MockHeader = types.Header{ Time: 0, Number: new(big.Int).Set(BlockNumber), @@ -110,6 +110,7 @@ var ( mockTopic43 = common.HexToHash("0x0b") mockTopic51 = common.HexToHash("0x0c") mockTopic61 = common.HexToHash("0x0d") + mockTopic71 = common.HexToHash("0x0e") MockLog1 = &types.Log{ Address: Address, Topics: []common.Hash{mockTopic11, mockTopic12}, @@ -159,6 +160,14 @@ var ( TxIndex: 3, Index: 5, } + MockLog7 = &types.Log{ + Address: AnotherAddress2, + Topics: []common.Hash{mockTopic71}, + Data: []byte{}, + BlockNumber: BlockNumber.Uint64(), + TxIndex: 1, + Index: 6, + } Tx1 = GetTxnRlp(0, MockTransactions) Tx2 = GetTxnRlp(1, MockTransactions) @@ -170,31 +179,32 @@ var ( Rct3 = GetRctRlp(2, MockReceipts) Rct4 = GetRctRlp(3, MockReceipts) - HeaderCID, _ = ipld.RawdataToCid(ipld.MEthHeader, MockHeaderRlp, multihash.KECCAK_256) - HeaderMhKey = shared.MultihashKeyFromCID(HeaderCID) - Trx1CID, _ = ipld.RawdataToCid(ipld.MEthTx, Tx1, multihash.KECCAK_256) - Trx1MhKey = shared.MultihashKeyFromCID(Trx1CID) - Trx2CID, _ = ipld.RawdataToCid(ipld.MEthTx, Tx2, multihash.KECCAK_256) - 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) - State2MhKey = shared.MultihashKeyFromCID(State2CID) - StorageCID, _ = ipld.RawdataToCid(ipld.MEthStorageTrie, StorageLeafNode, multihash.KECCAK_256) - StorageMhKey = shared.MultihashKeyFromCID(StorageCID) - MockTrxMeta = []models.TxModel{ + HeaderCID, _ = ipld.RawdataToCid(ipld.MEthHeader, MockHeaderRlp, multihash.KECCAK_256) + HeaderMhKey = shared.MultihashKeyFromCID(HeaderCID) + Trx1CID, _ = ipld.RawdataToCid(ipld.MEthTx, Tx1, multihash.KECCAK_256) + Trx1MhKey = shared.MultihashKeyFromCID(Trx1CID) + Trx2CID, _ = ipld.RawdataToCid(ipld.MEthTx, Tx2, multihash.KECCAK_256) + 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) + ByzantiumRctCID, _ = ipld.RawdataToCid(ipld.MEthTxReceipt, GetRctRlp(0, MockByzantiumReceipts), multihash.KECCAK_256) + State1CID, _ = ipld.RawdataToCid(ipld.MEthStateTrie, ContractLeafNode, multihash.KECCAK_256) + State1MhKey = shared.MultihashKeyFromCID(State1CID) + State2CID, _ = ipld.RawdataToCid(ipld.MEthStateTrie, AccountLeafNode, multihash.KECCAK_256) + State2MhKey = shared.MultihashKeyFromCID(State2CID) + StorageCID, _ = ipld.RawdataToCid(ipld.MEthStorageTrie, StorageLeafNode, multihash.KECCAK_256) + StorageMhKey = shared.MultihashKeyFromCID(StorageCID) + MockTrxMeta = []models.TxModel{ { CID: "", // This is empty until we go to publish to ipfs MhKey: "", @@ -442,7 +452,7 @@ var ( MockCIDWrapper = ð.CIDWrapper{ BlockNumber: new(big.Int).Set(BlockNumber), Header: models.HeaderModel{ - BlockNumber: "1", + BlockNumber: "2", BlockHash: MockBlock.Hash().String(), ParentHash: "0x0000000000000000000000000000000000000000000000000000000000000000", CID: HeaderCID.String(), @@ -574,6 +584,19 @@ var ( MockLondonTransactions, MockLondonReceipts, _ = createDynamicTransactionsAndReceipts(LondonBlockNum) MockLondonBlock = createNewBlock(&MockLondonHeader, MockLondonTransactions, nil, MockLondonReceipts, new(trie.Trie)) + + ByzantiumBlockNum = big.NewInt(1) + MockByzantiumHeader = types.Header{ + Time: 0, + Number: ByzantiumBlockNum, + Root: common.HexToHash("0x00"), + Difficulty: big.NewInt(5000000), + Extra: []byte{}, + BaseFee: big.NewInt(params.InitialBaseFee), + } + + MockByzantiumTransactions, MockByzantiumReceipts, _ = createByzantiumTransactionsAndReceipts(ByzantiumBlockNum) + MockByzantiumBlock = createNewBlock(&MockByzantiumHeader, MockByzantiumTransactions, nil, MockByzantiumReceipts, new(trie.Trie)) ) func createNewBlock(header *types.Header, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, hasher types.TrieHasher) *types.Block { @@ -614,13 +637,12 @@ func createDynamicTransactionsAndReceipts(blockNumber *big.Int) (types.Transacti log.Fatal(err.Error()) } - senderAddr, err := types.Sender(transactionSigner, signedTrx1) // same for both trx + senderAddr, err := types.Sender(transactionSigner, signedTrx1) if err != nil { log.Fatal(err.Error()) } // make receipts - // TODO: Change the receipt type to DynamicFeeTxType once this PR is merged. // https://github.com/ethereum/go-ethereum/pull/22806 mockReceipt1 := &types.Receipt{ Type: types.DynamicFeeTxType, @@ -634,6 +656,39 @@ func createDynamicTransactionsAndReceipts(blockNumber *big.Int) (types.Transacti return types.Transactions{signedTrx1}, types.Receipts{mockReceipt1}, senderAddr } +// createByzantiumTransactionsAndReceipts is a helper function to generate signed mock transactions and mock receipts with mock logs +func createByzantiumTransactionsAndReceipts(blockNumber *big.Int) (types.Transactions, types.Receipts, common.Address) { + // make transactions + trx1 := types.NewTransaction(0, AnotherAddress1, big.NewInt(1000), 50, big.NewInt(100), []byte{}) + config := params.TestChainConfig + config.ByzantiumBlock = blockNumber + transactionSigner := types.MakeSigner(config, new(big.Int).Set(BlockNumber)) + mockCurve := elliptic.P256() + mockPrvKey, err := ecdsa.GenerateKey(mockCurve, rand.Reader) + if err != nil { + log.Fatal(err) + } + signedTrx, err := types.SignTx(trx1, transactionSigner, mockPrvKey) + if err != nil { + log.Fatal(err) + } + SenderAddr, err = types.Sender(transactionSigner, signedTrx) + if err != nil { + log.Fatal(err) + } + + // make receipts + mockReceipt := types.NewReceipt(common.HexToHash("0x1").Bytes(), false, 50) + hash := signedTrx.Hash() + MockLog7.TxHash = hash + + mockReceipt.Logs = []*types.Log{MockLog7} + mockReceipt.TxHash = hash + mockReceipt.GasUsed = mockReceipt.CumulativeGasUsed + + return types.Transactions{signedTrx}, types.Receipts{mockReceipt}, SenderAddr +} + // createLegacyTransactionsAndReceipts is a helper function to generate signed mock transactions and mock receipts with mock logs func createLegacyTransactionsAndReceipts() (types.Transactions, types.Receipts, common.Address) { // make transactions diff --git a/pkg/eth/types.go b/pkg/eth/types.go index 291f0da6..0c7906db 100644 --- a/pkg/eth/types.go +++ b/pkg/eth/types.go @@ -181,8 +181,10 @@ type LogResult struct { LogLeafData []byte `db:"data"` RctCID string `db:"cid"` RctStatus uint64 `db:"post_status"` + RctGasUsed uint64 `db:"gas_used"` BlockNumber string `db:"block_number"` BlockHash string `db:"block_hash"` TxnIndex int64 `db:"txn_index"` TxHash string `db:"tx_hash"` + Gas uint64 `db:"gas"` } diff --git a/pkg/graphql/graphql.go b/pkg/graphql/graphql.go index d12838e2..42d84443 100644 --- a/pkg/graphql/graphql.go +++ b/pkg/graphql/graphql.go @@ -1046,7 +1046,7 @@ func (r *Resolver) GetLogs(ctx context.Context, args struct { return nil, err } - rctLog := decomposeGQLLogs(filteredLogs) + rctLog, err := r.backend.DecomposeGQLLogs(filteredLogs) if err != nil { return nil, err } @@ -1068,47 +1068,3 @@ 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 c3ca3b70..4cc1aab7 100644 --- a/pkg/graphql/graphql_test.go +++ b/pkg/graphql/graphql_test.go @@ -167,6 +167,11 @@ var _ = Describe("GraphQL", func() { err = tx.Close(err) Expect(err).ToNot(HaveOccurred()) + tx, err = indexAndPublisher.PushBlock(test_helpers.MockByzantiumBlock, test_helpers.MockByzantiumReceipts, test_helpers.MockByzantiumBlock.Difficulty()) + Expect(err).ToNot(HaveOccurred()) + err = tx.Close(err) + Expect(err).ToNot(HaveOccurred()) + graphQLServer, err = graphql.New(backend, gqlEndPoint, nil, []string{"*"}, rpc.HTTPTimeouts{}) Expect(err).ToNot(HaveOccurred()) @@ -216,6 +221,22 @@ var _ = Describe("GraphQL", func() { Expect(logs).To(Equal(expectedLogs)) }) + It("Retrieve logs for pre byzantium block", func() { + logs, err := client.GetLogs(ctx, test_helpers.MockByzantiumBlock.Hash(), nil) + Expect(err).ToNot(HaveOccurred()) + expectedLogs := []graphql.LogResponse{ + { + Topics: test_helpers.MockLog7.Topics, + Data: hexutil.Bytes(test_helpers.MockLog1.Data), + Transaction: graphql.TransactionResp{Hash: test_helpers.MockByzantiumTransactions[0].Hash()}, + ReceiptCID: test_helpers.ByzantiumRctCID.String(), + Status: int32(test_helpers.MockByzantiumReceipts[0].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())