Skip to content

Commit

Permalink
Add support for "system calls receipt" in eth_getTransactionReceipt
Browse files Browse the repository at this point in the history
If systems calls made by celo-blockchain result in logs, we add a receipt including those logs, which lists the block's hash as the transaction hash field on the receipt.  This PR adds support to eth_getTransactionReceipt to return this receipt when given a block hash.  One key difference, however, is that no receipt is added in case there were no logs, whereas eth_getTransactionReceipt will return an empty receipt in such cases, so that the case of no logs can't be confused with the case of not having the block.  We may in the future wish to change it so that the receipt is also created during block processing, but that would be a hard fork change.
  • Loading branch information
Or Neeman committed Jul 16, 2021
1 parent e7edbe3 commit 52e3072
Showing 1 changed file with 36 additions and 10 deletions.
46 changes: 36 additions & 10 deletions internal/ethapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1335,28 +1335,54 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(ctx context.Context, ha
if err != nil {
return nil, nil
}
if tx == nil {
// There is no such transaction, so we check whether it's a block hash, so that
// we can return the "system calls receipt" for the block if that's the case.
// Note that for blocks without any logs from system calls we don't actually
// generate a receipt, but for the API we will return an empty receipt in such cases.
// And we may choose to add empty receipts to the block itself as well, though that
// would be a hard fork change.
if block, _ := s.b.BlockByHash(ctx, hash); block != nil {
blockHash = hash
blockNumber = block.NumberU64()
index = uint64(block.Transactions().Len())
} else {
return nil, nil
}
}

receipts, err := s.b.GetReceipts(ctx, blockHash)
if err != nil {
// GetReceipts() doesn't return an error if things go wrong, so we also check len(receipts)
if err != nil || len(receipts) < int(index) {
return nil, err
}
if len(receipts) <= int(index) {
return nil, nil
}
receipt := receipts[index]

var signer types.Signer = types.FrontierSigner{}
if tx.Protected() {
signer = types.NewEIP155Signer(tx.ChainId())
var receipt *types.Receipt
if len(receipts) == int(index) {
// The block didn't have any logs from system calls and no receipt was created.
// So we create an empty receipt to return, similarly to how system receipts are created.
receipt = types.NewReceipt(nil, false, 0)
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
} else {
receipt = receipts[index]
}
from, _ := types.Sender(signer, tx)

var from, to common.Address
if tx != nil {
var signer types.Signer = types.FrontierSigner{}
if tx.Protected() {
signer = types.NewEIP155Signer(tx.ChainId())
}
from, _ = types.Sender(signer, tx)
to = *tx.To()
}
fields := map[string]interface{}{
"blockHash": blockHash,
"blockNumber": hexutil.Uint64(blockNumber),
"transactionHash": hash,
"transactionIndex": hexutil.Uint64(index),
"from": from,
"to": tx.To(),
"to": to,
"gasUsed": hexutil.Uint64(receipt.GasUsed),
"cumulativeGasUsed": hexutil.Uint64(receipt.CumulativeGasUsed),
"contractAddress": nil,
Expand Down

0 comments on commit 52e3072

Please sign in to comment.