getLogs API changes to return txHash, make contract arg optional. (#81)

* getLogs API changes to return txHash, make contract arg optional.

* Populate log index.

* Add test for txn hash in GetLogs request.

* Convert tx string to common.Hash after fetching.

Co-authored-by: Arijit Das <arijitad.in@gmail.com>
This commit is contained in:
Ashwin Phatak 2021-07-26 15:43:38 +05:30 committed by GitHub
parent afc63ac960
commit 70f7face75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 43 additions and 16 deletions

View File

@ -482,7 +482,7 @@ func (b *Backend) GetTransaction(ctx context.Context, txHash common.Hash) (*type
// GetReceipts retrieves receipts for provided block hash // GetReceipts retrieves receipts for provided block hash
func (b *Backend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { func (b *Backend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
_, receiptBytes, err := b.IPLDRetriever.RetrieveReceiptsByBlockHash(hash) _, receiptBytes, txs, err := b.IPLDRetriever.RetrieveReceiptsByBlockHash(hash)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -492,6 +492,7 @@ func (b *Backend) GetReceipts(ctx context.Context, hash common.Hash) (types.Rece
if err := rlp.DecodeBytes(rctBytes, rct); err != nil { if err := rlp.DecodeBytes(rctBytes, rct); err != nil {
return nil, err return nil, err
} }
rct.TxHash = txs[i]
rcts[i] = rct rcts[i] = rct
} }
return rcts, nil return rcts, nil
@ -499,7 +500,7 @@ func (b *Backend) GetReceipts(ctx context.Context, hash common.Hash) (types.Rece
// GetLogs returns all the logs for the given block hash // GetLogs returns all the logs for the given block hash
func (b *Backend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types.Log, error) { func (b *Backend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types.Log, error) {
_, receiptBytes, err := b.IPLDRetriever.RetrieveReceiptsByBlockHash(hash) _, receiptBytes, txs, err := b.IPLDRetriever.RetrieveReceiptsByBlockHash(hash)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -510,6 +511,10 @@ func (b *Backend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types.Log
return nil, err return nil, err
} }
for _, log := range rct.Logs {
log.TxHash = txs[i]
}
logs[i] = rct.Logs logs[i] = rct.Logs
} }
return logs, nil return logs, nil

View File

@ -83,7 +83,7 @@ const (
INNER JOIN eth.transaction_cids ON (receipt_cids.tx_id = transaction_cids.id) INNER JOIN eth.transaction_cids ON (receipt_cids.tx_id = transaction_cids.id)
INNER JOIN public.blocks ON (receipt_cids.mh_key = blocks.key) INNER JOIN public.blocks ON (receipt_cids.mh_key = blocks.key)
WHERE tx_hash = ANY($1::VARCHAR(66)[])` WHERE tx_hash = ANY($1::VARCHAR(66)[])`
RetrieveReceiptsByBlockHashPgStr = `SELECT receipt_cids.cid, data RetrieveReceiptsByBlockHashPgStr = `SELECT receipt_cids.cid, data, eth.transaction_cids.tx_hash
FROM eth.receipt_cids FROM eth.receipt_cids
INNER JOIN eth.transaction_cids ON (receipt_cids.tx_id = transaction_cids.id) INNER JOIN eth.transaction_cids ON (receipt_cids.tx_id = transaction_cids.id)
INNER JOIN eth.header_cids ON (transaction_cids.header_id = header_cids.id) INNER JOIN eth.header_cids ON (transaction_cids.header_id = header_cids.id)
@ -163,7 +163,9 @@ const (
type ipldResult struct { type ipldResult struct {
CID string `db:"cid"` CID string `db:"cid"`
Data []byte `db:"data"` Data []byte `db:"data"`
TxHash string `db:"tx_hash"`
} }
type IPLDRetriever struct { type IPLDRetriever struct {
db *postgres.DB db *postgres.DB
} }
@ -345,18 +347,22 @@ func (r *IPLDRetriever) RetrieveReceiptsByTxHashes(hashes []common.Hash) ([]stri
} }
// RetrieveReceiptsByBlockHash returns the cids and rlp bytes for the receipts corresponding to the provided block hash // RetrieveReceiptsByBlockHash returns the cids and rlp bytes for the receipts corresponding to the provided block hash
func (r *IPLDRetriever) RetrieveReceiptsByBlockHash(hash common.Hash) ([]string, [][]byte, error) { func (r *IPLDRetriever) RetrieveReceiptsByBlockHash(hash common.Hash) ([]string, [][]byte, []common.Hash, error) {
rctResults := make([]ipldResult, 0) rctResults := make([]ipldResult, 0)
if err := r.db.Select(&rctResults, RetrieveReceiptsByBlockHashPgStr, hash.Hex()); err != nil { if err := r.db.Select(&rctResults, RetrieveReceiptsByBlockHashPgStr, hash.Hex()); err != nil {
return nil, nil, err return nil, nil, nil, err
} }
cids := make([]string, len(rctResults)) cids := make([]string, len(rctResults))
rcts := make([][]byte, len(rctResults)) rcts := make([][]byte, len(rctResults))
txs := make([]common.Hash, len(rctResults))
for i, res := range rctResults { for i, res := range rctResults {
cids[i] = res.CID cids[i] = res.CID
rcts[i] = res.Data rcts[i] = res.Data
txs[i] = common.HexToHash(res.TxHash)
} }
return cids, rcts, nil
return cids, rcts, txs, nil
} }
// RetrieveReceiptsByBlockNumber returns the cids and rlp bytes for the receipts corresponding to the provided block hash // RetrieveReceiptsByBlockNumber returns the cids and rlp bytes for the receipts corresponding to the provided block hash

View File

@ -23,6 +23,11 @@ type GetStorageAt struct {
type LogResponse struct { type LogResponse struct {
Topics []common.Hash `json:"topics"` Topics []common.Hash `json:"topics"`
Data hexutil.Bytes `json:"data"` Data hexutil.Bytes `json:"data"`
Transaction TransactionResp `json:"transaction"`
}
type TransactionResp struct {
Hash common.Hash `json:"hash"`
} }
type GetLogs struct { type GetLogs struct {
@ -44,6 +49,9 @@ func (c *Client) GetLogs(ctx context.Context, hash common.Hash, address common.A
getLogs(blockHash: "%s", contract: "%s") { getLogs(blockHash: "%s", contract: "%s") {
data data
topics topics
transaction {
hash
}
} }
} }
`, hash.String(), address.String()) `, hash.String(), address.String())

View File

@ -1005,15 +1005,16 @@ func (r *Resolver) GetStorageAt(ctx context.Context, args struct {
func (r *Resolver) GetLogs(ctx context.Context, args struct { func (r *Resolver) GetLogs(ctx context.Context, args struct {
BlockHash common.Hash BlockHash common.Hash
Contract common.Address Contract *common.Address
}) (*[]*Log, error) { }) (*[]*Log, error) {
ret := make([]*Log, 0, 10) ret := make([]*Log, 0, 10)
receiptCIDs, receiptsBytes, err := r.backend.IPLDRetriever.RetrieveReceiptsByBlockHash(args.BlockHash) receiptCIDs, receiptsBytes, txs, err := r.backend.IPLDRetriever.RetrieveReceiptsByBlockHash(args.BlockHash)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var logIndexInBlock uint = 0
receipts := make(types.Receipts, len(receiptsBytes)) receipts := make(types.Receipts, len(receiptsBytes))
for index, receiptBytes := range receiptsBytes { for index, receiptBytes := range receiptsBytes {
receiptCID := receiptCIDs[index] receiptCID := receiptCIDs[index]
@ -1024,12 +1025,18 @@ func (r *Resolver) GetLogs(ctx context.Context, args struct {
receipts[index] = receipt receipts[index] = receipt
for _, log := range receipt.Logs { for _, log := range receipt.Logs {
if log.Address == args.Contract { log.Index = logIndexInBlock
logIndexInBlock++
if args.Contract == nil || *args.Contract == log.Address {
ret = append(ret, &Log{ ret = append(ret, &Log{
backend: r.backend, backend: r.backend,
log: log, log: log,
cid: receiptCID, cid: receiptCID,
ipldBlock: receiptBytes, ipldBlock: receiptBytes,
transaction: &Transaction{
hash: txs[index],
},
}) })
} }
} }

View File

@ -163,6 +163,7 @@ var _ = Describe("GraphQL", func() {
{ {
Topics: test_helpers.MockLog1.Topics, Topics: test_helpers.MockLog1.Topics,
Data: hexutil.Bytes(test_helpers.MockLog1.Data), Data: hexutil.Bytes(test_helpers.MockLog1.Data),
Transaction: graphql.TransactionResp{Hash: test_helpers.MockTransactions[0].Hash()},
}, },
} }
Expect(logs).To(Equal(expectedLogs)) Expect(logs).To(Equal(expectedLogs))

View File

@ -295,6 +295,6 @@ const schema string = `
getStorageAt(blockHash: Bytes32!, contract: Address!, slot: Bytes32!): StorageResult getStorageAt(blockHash: Bytes32!, contract: Address!, slot: Bytes32!): StorageResult
# Get contract logs by block hash and contract address. # Get contract logs by block hash and contract address.
getLogs(blockHash: Bytes32!, contract: Address!): [Log!] getLogs(blockHash: Bytes32!, contract: Address): [Log!]
} }
` `