|
| 1 | +package ethapi |
| 2 | + |
| 3 | +import ( |
| 4 | + "context" |
| 5 | + |
| 6 | + "github.com/ethereum/go-ethereum/common" |
| 7 | + "github.com/ethereum/go-ethereum/common/hexutil" |
| 8 | + "github.com/ethereum/go-ethereum/core/types" |
| 9 | +) |
| 10 | + |
| 11 | +// GetBlockReceipt returns "system calls" receipt for the block with the given block hash. |
| 12 | +func (s *BlockChainAPI) GetBlockReceipt(ctx context.Context, hash common.Hash) (map[string]interface{}, error) { |
| 13 | + block, err := s.b.BlockByHash(ctx, hash) |
| 14 | + if block == nil || err != nil { |
| 15 | + // If no header with that hash is found, err gives "header for hash not found". |
| 16 | + // But we return nil with no error, to match the behavior of eth_getBlockByHash and eth_getTransactionReceipt in these cases. |
| 17 | + return nil, nil |
| 18 | + } |
| 19 | + index := block.Transactions().Len() |
| 20 | + blockNumber := block.NumberU64() |
| 21 | + receipts, err := s.b.GetReceipts(ctx, block.Hash()) |
| 22 | + // GetReceipts() doesn't return an error if things go wrong, so we also check len(receipts) |
| 23 | + if err != nil || len(receipts) < index { |
| 24 | + return nil, err |
| 25 | + } |
| 26 | + |
| 27 | + var receipt *types.Receipt |
| 28 | + if len(receipts) == index { |
| 29 | + // The block didn't have any logs from system calls and no receipt was created. |
| 30 | + // So we create an empty receipt to return, similarly to how system receipts are created. |
| 31 | + receipt = types.NewReceipt(nil, false, 0) |
| 32 | + receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) |
| 33 | + } else { |
| 34 | + receipt = receipts[index] |
| 35 | + } |
| 36 | + return marshalBlockReceipt(receipt, hash, blockNumber, index), nil |
| 37 | +} |
| 38 | + |
| 39 | +// marshalBlockReceipt marshals a Celo block receipt into a JSON object. See https://docs.celo.org/developer/migrate/from-ethereum#core-contract-calls |
| 40 | +func marshalBlockReceipt(receipt *types.Receipt, blockHash common.Hash, blockNumber uint64, index int) map[string]interface{} { |
| 41 | + fields := map[string]interface{}{ |
| 42 | + "blockHash": blockHash, |
| 43 | + "blockNumber": hexutil.Uint64(blockNumber), |
| 44 | + "transactionHash": blockHash, |
| 45 | + "transactionIndex": hexutil.Uint64(index), |
| 46 | + "from": common.Address{}, |
| 47 | + "to": nil, |
| 48 | + "gasUsed": hexutil.Uint64(0), |
| 49 | + "cumulativeGasUsed": hexutil.Uint64(0), |
| 50 | + "contractAddress": nil, |
| 51 | + "logs": receipt.Logs, |
| 52 | + "logsBloom": receipt.Bloom, |
| 53 | + "type": hexutil.Uint(0), |
| 54 | + "status": hexutil.Uint(types.ReceiptStatusSuccessful), |
| 55 | + } |
| 56 | + if receipt.Logs == nil { |
| 57 | + fields["logs"] = []*types.Log{} |
| 58 | + } |
| 59 | + return fields |
| 60 | +} |
0 commit comments