Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement eth_getBlockReceipts API #107

Merged
merged 2 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 48 additions & 13 deletions ethapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -930,6 +930,37 @@ func (s *PublicBlockChainAPI) GetStorageAt(ctx context.Context, address common.A
return res[:], state.Error()
}

// GetBlockReceipts returns the block receipts for the given block hash or number or tag.
func (s *PublicBlockChainAPI) GetBlockReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]map[string]interface{}, error) {
var (
block *evmcore.EvmBlock
err error
)
if blockNrOrHash.BlockNumber != nil {
block, err = s.b.BlockByNumber(ctx, *blockNrOrHash.BlockNumber)
} else if blockNrOrHash.BlockHash != nil {
block, err = s.b.BlockByHash(ctx, *blockNrOrHash.BlockHash)
}
if block == nil || err != nil {
return nil, err
}
receipts, err := s.b.GetReceiptsByNumber(ctx, rpc.BlockNumber(block.NumberU64()))
if err != nil {
return nil, err
}
if i, j := len(block.Transactions), len(receipts); i != j {
return nil, fmt.Errorf("receipts length mismatch: %d vs %d", i, j)
}
// Derive the sender.
signer := types.MakeSigner(s.b.ChainConfig(), block.Number)
result := make([]map[string]interface{}, len(receipts))
baseFee := block.Header().BaseFee
for i, receipt := range receipts {
result[i] = marshalReceipt(receipt, signer, block.Transactions[i], uint64(i), baseFee)
}
return result, nil
}

// OverrideAccount indicates the overriding fields of account during the execution
// of a message call.
// Note, state and stateDiff can't be specified at the same time. If state is
Expand Down Expand Up @@ -1791,13 +1822,23 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(ctx context.Context, ha
// Derive the sender.
bigblock := new(big.Int).SetUint64(blockNumber)
signer := gsignercache.Wrap(types.MakeSigner(s.b.ChainConfig(), bigblock))
from, _ := internaltx.Sender(signer, tx)

return marshalReceipt(receipt, signer, tx, index, header.BaseFee), nil
}

// marshalReceipt marshals a transaction receipt into a JSON object.
func marshalReceipt(receipt *types.Receipt, signer types.Signer, tx *types.Transaction, txIndex uint64, baseFee *big.Int) map[string]interface{} {
from, _ := types.Sender(signer, tx)
// Assign the effective gas price paid
gasPrice := tx.GasPrice()
if baseFee != nil {
gasPrice = big.NewInt(0).Add(baseFee, tx.EffectiveGasTipValue(baseFee))
}
khoau2u marked this conversation as resolved.
Show resolved Hide resolved
fields := map[string]interface{}{
"blockHash": header.Hash,
"blockNumber": hexutil.Uint64(blockNumber),
"transactionHash": hash,
"transactionIndex": hexutil.Uint64(index),
"blockHash": receipt.BlockHash,
"blockNumber": hexutil.Uint64(receipt.BlockNumber.Uint64()),
"transactionHash": tx.Hash(),
"transactionIndex": hexutil.Uint64(txIndex),
"from": from,
"to": tx.To(),
"gasUsed": hexutil.Uint64(receipt.GasUsed),
Expand All @@ -1806,13 +1847,7 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(ctx context.Context, ha
"logs": receipt.Logs,
"logsBloom": &receipt.Bloom,
"type": hexutil.Uint(tx.Type()),
}
// Assign the effective gas price paid
if header.BaseFee == nil {
fields["effectiveGasPrice"] = hexutil.Uint64(tx.GasPrice().Uint64())
} else {
gasPrice := new(big.Int).Add(header.BaseFee, tx.EffectiveGasTipValue(header.BaseFee))
fields["effectiveGasPrice"] = hexutil.Uint64(gasPrice.Uint64())
khoau2u marked this conversation as resolved.
Show resolved Hide resolved
"effectiveGasPrice": hexutil.Uint64(gasPrice.Uint64()),
}
// Assign receipt status or post state.
if len(receipt.PostState) > 0 {
Expand All @@ -1827,7 +1862,7 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(ctx context.Context, ha
if tx.To() == nil {
fields["contractAddress"] = receipt.ContractAddress
}
return fields, nil
return fields
}

// sign is a helper function that signs a transaction with the private key of the given address.
Expand Down
9 changes: 9 additions & 0 deletions ethclient/ethclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,15 @@ func (ec *Client) BlockNumber(ctx context.Context) (uint64, error) {
return uint64(result), err
}

func (ec *Client) BlockReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]*types.Receipt, error) {
var r []*types.Receipt
err := ec.c.CallContext(ctx, &r, "eth_getBlockReceipts", blockNrOrHash)
if err == nil && r == nil {
return nil, u2u.NotFound
}
return r, err
}

type rpcBlock struct {
Hash common.Hash `json:"hash"`
Transactions []rpcTransaction `json:"transactions"`
Expand Down
7 changes: 6 additions & 1 deletion internal/web3ext/web3ext.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ web3._extend({
call: 'admin_importChain',
params: 1
}),
new web3._extend.Method({
new web3._extend.Method({
name: 'sleepBlocks',
call: 'admin_sleepBlocks',
params: 2
Expand Down Expand Up @@ -478,6 +478,11 @@ web3._extend({
params: 3,
inputFormatter: [null, web3._extend.formatters.inputBlockNumberFormatter, null]
}),
new web3._extend.Method({
name: 'getBlockReceipts',
call: 'eth_getBlockReceipts',
params: 1,
}),
],
properties: [
new web3._extend.Property({
Expand Down