Skip to content
Open
Show file tree
Hide file tree
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
58 changes: 36 additions & 22 deletions evmrpc/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,35 @@ const (
Sei2Namespace = "sei2"
)

// GenesisBlockHash is the block hash returned by GetBlockByNumber("0x0"). Hash-based lookups
// must recognize this so that count/block-by-hash stay consistent with block-by-number.
var GenesisBlockHash = common.HexToHash("0xF9D3845DF25B43B1C6926F3CEDA6845C17F5624E12212FD8847D0BA01DA1AB9E")
Copy link
Collaborator

Choose a reason for hiding this comment

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

I recommend not exporting this variable if we don't need to.

Suggested change
var GenesisBlockHash = common.HexToHash("0xF9D3845DF25B43B1C6926F3CEDA6845C17F5624E12212FD8847D0BA01DA1AB9E")
var genesisBlockHash = common.HexToHash("0xF9D3845DF25B43B1C6926F3CEDA6845C17F5624E12212FD8847D0BA01DA1AB9E")


func encodeGenesisBlock() map[string]interface{} {
Copy link
Collaborator

Choose a reason for hiding this comment

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

use any instead of interface{} whenever you can. I am hoping to slowly phase out the old syntax.

return map[string]interface{}{
"number": (*hexutil.Big)(big.NewInt(0)),
"hash": "0xF9D3845DF25B43B1C6926F3CEDA6845C17F5624E12212FD8847D0BA01DA1AB9E",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Extract the hash as a const and use in both places?

"parentHash": common.Hash{},
"nonce": ethtypes.BlockNonce{}, // inapplicable to Sei
"mixHash": common.Hash{}, // inapplicable to Sei
"sha3Uncles": ethtypes.EmptyUncleHash, // inapplicable to Sei
"logsBloom": ethtypes.Bloom{},
"stateRoot": common.Hash{},
"miner": common.Address{},
"difficulty": (*hexutil.Big)(big.NewInt(0)), // inapplicable to Sei
"extraData": hexutil.Bytes{}, // inapplicable to Sei
"gasLimit": hexutil.Uint64(0),
"gasUsed": hexutil.Uint64(0),
"timestamp": hexutil.Uint64(0),
"transactionsRoot": common.Hash{},
"receiptsRoot": common.Hash{},
"size": hexutil.Uint64(0),
"uncles": []common.Hash{}, // inapplicable to Sei
"transactions": []interface{}{},
"baseFeePerGas": (*hexutil.Big)(big.NewInt(0)),
}
}

type BlockAPI struct {
tmClient rpcclient.Client
keeper *keeper.Keeper
Expand Down Expand Up @@ -143,6 +172,9 @@ func (a *BlockAPI) GetBlockTransactionCountByNumber(ctx context.Context, number
func (a *BlockAPI) GetBlockTransactionCountByHash(ctx context.Context, blockHash common.Hash) (result *hexutil.Uint, returnErr error) {
startTime := time.Now()
defer recordMetricsWithError(fmt.Sprintf("%s_getBlockTransactionCountByHash", a.namespace), a.connectionType, startTime, returnErr)
if blockHash == GenesisBlockHash {
return a.getEvmTxCount(nil, 0), nil
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is correct but i worry that it is fragile. a simple refactor in getEvmTxCount could cause panics given the nil txs passed in.

Why not use hexutil.Uint(0) directly, or whatever that results in? You can even define it as a var/const.

}
block, err := blockByHashRespectingWatermarks(ctx, a.tmClient, a.watermarks, blockHash[:], 1)
if err != nil {
return nil, err
Expand All @@ -158,6 +190,9 @@ func (a *BlockAPI) GetBlockByHash(ctx context.Context, blockHash common.Hash, fu
func (a *BlockAPI) getBlockByHash(ctx context.Context, blockHash common.Hash, fullTx bool, includeSyntheticTxs bool, isPanicTx func(ctx context.Context, hash common.Hash) (bool, error)) (result map[string]interface{}, returnErr error) {
startTime := time.Now()
defer recordMetricsWithError(fmt.Sprintf("%s_getBlockByHash", a.namespace), a.connectionType, startTime, returnErr)
if blockHash == GenesisBlockHash {
return encodeGenesisBlock(), nil
}
block, err := blockByHashRespectingWatermarks(ctx, a.tmClient, a.watermarks, blockHash[:], 1)
if err != nil {
return nil, err
Expand All @@ -181,28 +216,7 @@ func (a *BlockAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockNumber,
defer recordMetricsWithError(fmt.Sprintf("%s_getBlockByNumber", a.namespace), a.connectionType, startTime, returnErr)
if number == 0 {
// for compatibility with the graph, always return genesis block
return map[string]interface{}{
"number": (*hexutil.Big)(big.NewInt(0)),
"hash": "0xF9D3845DF25B43B1C6926F3CEDA6845C17F5624E12212FD8847D0BA01DA1AB9E",
"parentHash": common.Hash{},
"nonce": ethtypes.BlockNonce{}, // inapplicable to Sei
"mixHash": common.Hash{}, // inapplicable to Sei
"sha3Uncles": ethtypes.EmptyUncleHash, // inapplicable to Sei
"logsBloom": ethtypes.Bloom{},
"stateRoot": common.Hash{},
"miner": common.Address{},
"difficulty": (*hexutil.Big)(big.NewInt(0)), // inapplicable to Sei
"extraData": hexutil.Bytes{}, // inapplicable to Sei
"gasLimit": hexutil.Uint64(0),
"gasUsed": hexutil.Uint64(0),
"timestamp": hexutil.Uint64(0),
"transactionsRoot": common.Hash{},
"receiptsRoot": common.Hash{},
"size": hexutil.Uint64(0),
"uncles": []common.Hash{}, // inapplicable to Sei
"transactions": []interface{}{},
"baseFeePerGas": (*hexutil.Big)(big.NewInt(0)),
}, nil
return encodeGenesisBlock(), nil
}
return a.getBlockByNumber(ctx, number, fullTx, a.includeShellReceipts, nil)
}
Expand Down
13 changes: 13 additions & 0 deletions evmrpc/height_availability_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"testing"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/eth/filters"
"github.com/ethereum/go-ethereum/rpc"
"github.com/sei-protocol/sei-chain/sei-cosmos/client"
Expand Down Expand Up @@ -99,6 +100,18 @@ func TestBlockAPIEnsureHeightUnavailable(t *testing.T) {
require.Contains(t, err.Error(), "requested height")
}

// TestGetBlockTransactionCountByHashGenesis verifies that the genesis block hash returned by
// eth_getBlockByNumber("0x0") is accepted by eth_getBlockTransactionCountByHash (consistency).
func TestGetBlockTransactionCountByHashGenesis(t *testing.T) {
t.Parallel()

api := NewBlockAPI(nil, nil, testCtxProvider, testTxConfigProvider, ConnectionTypeHTTP, nil, nil, nil)
count, err := api.GetBlockTransactionCountByHash(context.Background(), GenesisBlockHash)
require.NoError(t, err)
require.NotNil(t, count)
require.Equal(t, hexutil.Uint(0), *count)
}

func TestLogFetcherSkipsUnavailableCachedBlock(t *testing.T) {
t.Parallel()

Expand Down
Loading