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

Implementation of endpoints eth_getBlockReceipts and eth_getBlockTransactionCountByHash #169

Merged
merged 1 commit into from
Sep 25, 2024
Merged
Changes from all commits
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
98 changes: 98 additions & 0 deletions portalnetwork/ethapi/api.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package ethapi

import (
"errors"
"fmt"
"math/big"

"github.com/ethereum/go-ethereum/common"
Expand All @@ -10,8 +12,53 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/portalnetwork/history"
"github.com/ethereum/go-ethereum/rpc"
)

var errParameterNotImplemented = errors.New("parameter not implemented")

// marshalReceipt marshals a transaction receipt into a JSON object.
func marshalReceipt(receipt *types.Receipt, blockHash common.Hash, blockNumber uint64, signer types.Signer, tx *types.Transaction, txIndex int) map[string]interface{} {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we make the origin function public to avoid copying it?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes we could, and it'd be better because avoid redundant code. My only concern is in the scenario:

  1. We make marshalReceipt public (MarshalReceipt)
  2. Someone developing geth calls marshalReceipt
  3. Geth is merged into Shisui

I am not entirely sure but it potentially may cause a merge conflict. Anyway this conflict is simple to solve.

@GrapeBaBa should I make the origin function public?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand your thoughts, and I have similar considerations. I feel this method should be relatively easy to merge, what do you think? @fearlessfe @thinkAfCod

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if take issue #22 into consideration, may be copy will be better

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

from, _ := types.Sender(signer, tx)

fields := map[string]interface{}{
"blockHash": blockHash,
"blockNumber": hexutil.Uint64(blockNumber),
"transactionHash": tx.Hash(),
"transactionIndex": hexutil.Uint64(txIndex),
"from": from,
"to": tx.To(),
"gasUsed": hexutil.Uint64(receipt.GasUsed),
"cumulativeGasUsed": hexutil.Uint64(receipt.CumulativeGasUsed),
"contractAddress": nil,
"logs": receipt.Logs,
"logsBloom": receipt.Bloom,
"type": hexutil.Uint(tx.Type()),
"effectiveGasPrice": (*hexutil.Big)(receipt.EffectiveGasPrice),
}

// Assign receipt status or post state.
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{}
}

if tx.Type() == types.BlobTxType {
fields["blobGasUsed"] = hexutil.Uint64(receipt.BlobGasUsed)
fields["blobGasPrice"] = (*hexutil.Big)(receipt.BlobGasPrice)
}

// If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation
if receipt.ContractAddress != (common.Address{}) {
fields["contractAddress"] = receipt.ContractAddress
}
return fields
}

type API struct {
History *history.HistoryNetwork
ChainID *big.Int
Expand All @@ -38,3 +85,54 @@ func (p *API) GetBlockByHash(hash *common.Hash, fullTransactions bool) (map[stri
//static configuration of Config, currently only mainnet implemented
return ethapi.RPCMarshalBlock(block, true, fullTransactions, params.MainnetChainConfig), nil
}

func (p *API) GetBlockReceipts(blockNrOrHash rpc.BlockNumberOrHash) ([]map[string]interface{}, error) {
hash, isHhash := blockNrOrHash.Hash()
if !isHhash {
return nil, errParameterNotImplemented
}

blockReceipts, err := p.History.GetReceipts(hash.Bytes())
if err != nil {
log.Error(err.Error())
return nil, err
}

blockBody, err := p.History.GetBlockBody(hash.Bytes())
if err != nil {
log.Error(err.Error())
return nil, err
}

blockHeader, err := p.History.GetBlockHeader(hash.Bytes())
if err != nil {
log.Error(err.Error())
return nil, err
}

txs := blockBody.Transactions
if len(txs) != len(blockReceipts) {
return nil, fmt.Errorf("receipts length mismatch: %d vs %d", len(txs), len(blockReceipts))
}

// Derive the sender.
signer := types.MakeSigner(params.MainnetChainConfig, blockHeader.Number, blockHeader.Time)

result := make([]map[string]interface{}, len(blockReceipts))
for i, receipt := range blockReceipts {
result[i] = marshalReceipt(receipt, blockHeader.Hash(), blockHeader.Number.Uint64(), signer, txs[i], i)
}

return result, nil
}

func (p *API) GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Uint {
blockBody, err := p.History.GetBlockBody(hash.Bytes())
if err != nil {
log.Error(err.Error())
return nil
}

n := hexutil.Uint(len(blockBody.Transactions))
return &n
}