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
59 changes: 45 additions & 14 deletions evmrpc/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
banktypes "github.com/sei-protocol/sei-chain/sei-cosmos/x/bank/types"
rpcclient "github.com/sei-protocol/sei-chain/sei-tendermint/rpc/client"
"github.com/sei-protocol/sei-chain/sei-tendermint/rpc/coretypes"
tmtypes "github.com/sei-protocol/sei-chain/sei-tendermint/types"
wasmtypes "github.com/sei-protocol/sei-chain/sei-wasmd/x/wasm/types"
"github.com/sei-protocol/sei-chain/x/evm/keeper"
"github.com/sei-protocol/sei-chain/x/evm/state"
Expand Down Expand Up @@ -179,7 +178,7 @@ func (a *BlockAPI) GetBlockTransactionCountByNumber(ctx context.Context, number
if err != nil {
return nil, err
}
return a.getEvmTxCount(block.Block.Txs, block.Block.Height), nil
return a.getEvmTxCount(block), nil
}

func (a *BlockAPI) GetBlockTransactionCountByHash(ctx context.Context, blockHash common.Hash) (result *hexutil.Uint, returnErr error) {
Expand All @@ -192,7 +191,7 @@ func (a *BlockAPI) GetBlockTransactionCountByHash(ctx context.Context, blockHash
if err != nil {
return nil, err
}
return a.getEvmTxCount(block.Block.Txs, block.Block.Height), nil
return a.getEvmTxCount(block), nil
}

func (a *BlockAPI) GetBlockByHash(ctx context.Context, blockHash common.Hash, fullTx bool) (result map[string]interface{}, returnErr error) {
Expand Down Expand Up @@ -512,17 +511,49 @@ func FullBloom() ethtypes.Bloom {
return ethtypes.BytesToBloom(bz)
}

// filters out non-evm txs
func (a *BlockAPI) getEvmTxCount(txs tmtypes.Txs, height int64) *hexutil.Uint {
cnt := 0
// Only count eth txs
for _, tx := range txs {
ethtx := getEthTxForTxBz(tx, a.txConfigProvider(height).TxDecoder())
if ethtx != nil {
cnt += 1
}
// getEvmTxCount returns the same transaction count as EncodeTmBlock exposes: filterTransactions
// plus the same per-msg rules as EncodeTmBlock (EVM messages need GetReceipt to succeed).
func (a *BlockAPI) getEvmTxCount(block *coretypes.ResultBlock) *hexutil.Uint {
n := countBlockTxsLikeEncodeTmBlock(
a.ctxProvider,
a.txConfigProvider,
block,
a.keeper,
a.includeShellReceipts,
a.includeBankTransfers,
a.cacheCreationMutex,
a.globalBlockCache,
)
cntHex := hexutil.Uint(n) //nolint:gosec
return &cntHex
}

func countBlockTxsLikeEncodeTmBlock(
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Would exporting this break something as opposed to creating the helper below that delegates?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Not at all. just trying to hide the logic in an unexported func. and that exported is also to serve the evm_test which is another pkg.

ctxProvider func(int64) sdk.Context,
txConfigProvider func(int64) client.TxConfig,
block *coretypes.ResultBlock,
k *keeper.Keeper,
includeShellReceipts bool,
includeBankTransfers bool,
cacheCreationMutex *sync.Mutex,
globalBlockCache BlockCache,
) int {
latestCtx := ctxProvider(LatestCtxHeight)
msgs := filterTransactions(k, ctxProvider, txConfigProvider, block, includeShellReceipts, includeBankTransfers, cacheCreationMutex, globalBlockCache)
n := 0
for _, msg := range msgs {
switch m := msg.msg.(type) {
case *types.MsgEVMTransaction:
ethtx, _ := m.AsTransaction()
if _, err := k.GetReceipt(latestCtx, ethtx.Hash()); err != nil {
continue
}
n++
case *wasmtypes.MsgExecuteContract:
n++
case *banktypes.MsgSend:
n++
}
}
cntHex := hexutil.Uint(cnt) //nolint:gosec
return &cntHex
return n
}
141 changes: 141 additions & 0 deletions evmrpc/block_txcount_parity_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package evmrpc_test

import (
"context"
"fmt"
"sync"
"testing"
"time"

ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rpc"
"github.com/stretchr/testify/require"

"github.com/sei-protocol/sei-chain/evmrpc"
"github.com/sei-protocol/sei-chain/sei-cosmos/client"
sdk "github.com/sei-protocol/sei-chain/sei-cosmos/types"
abci "github.com/sei-protocol/sei-chain/sei-tendermint/abci/types"
types2 "github.com/sei-protocol/sei-chain/sei-tendermint/proto/tendermint/types"
tmmock "github.com/sei-protocol/sei-chain/sei-tendermint/rpc/client/mock"
"github.com/sei-protocol/sei-chain/sei-tendermint/rpc/coretypes"
tmtypes "github.com/sei-protocol/sei-chain/sei-tendermint/types"
testkeeper "github.com/sei-protocol/sei-chain/testutil/keeper"
"github.com/sei-protocol/sei-chain/x/evm/types"
)

const parityTestHeight int64 = 771

// Tendermint client stub: only Block(height) and Status are used by GetBlockTransactionCountByNumber.
type parityTxCountTMClient struct {
tmmock.Client
block *coretypes.ResultBlock
}

func (c *parityTxCountTMClient) Block(_ context.Context, h *int64) (*coretypes.ResultBlock, error) {
if h != nil && *h == parityTestHeight {
return c.block, nil
}
return nil, fmt.Errorf("unexpected height %v", h)
}

func (c *parityTxCountTMClient) Status(context.Context) (*coretypes.ResultStatus, error) {
return &coretypes.ResultStatus{
SyncInfo: coretypes.SyncInfo{
LatestBlockHeight: parityTestHeight,
EarliestBlockHeight: 1,
},
}, nil
}

func TestBlockTransactionCountMatchesGetBlockByNumber(t *testing.T) {
k := &testkeeper.EVMTestApp.EvmKeeper
ctx := testkeeper.EVMTestApp.GetContextForDeliverTx(nil).
WithBlockHeight(parityTestHeight).
WithBlockTime(time.Unix(1700000000, 0)).
WithClosestUpgradeName("v6.0.0")

bz1, err := Encoder(Tx1)
require.NoError(t, err)
bz2, err := Encoder(MultiTxBlockTx1)
require.NoError(t, err)

msg := Tx1.GetMsgs()[0].(*types.MsgEVMTransaction)
eth1, _ := msg.AsTransaction()
hash1 := eth1.Hash()

bloom := ethtypes.CreateBloom(&ethtypes.Receipt{})
require.NoError(t, k.MockReceipt(ctx, hash1, &types.Receipt{
From: "0x1234567890123456789012345678901234567890",
To: "0x1234567890123456789012345678901234567890",
TransactionIndex: 0,
BlockNumber: uint64(parityTestHeight), //nolint:gosec
TxType: 2,
TxHashHex: hash1.Hex(),
GasUsed: 21000,
Status: 1,
EffectiveGasPrice: 1,
LogsBloom: bloom[:],
}))

block := &coretypes.ResultBlock{
BlockID: MockBlockID,
Block: &tmtypes.Block{
Header: mockBlockHeader(parityTestHeight),
Data: tmtypes.Data{Txs: []tmtypes.Tx{bz1, bz2}},
LastCommit: &tmtypes.Commit{
Height: parityTestHeight - 1,
},
},
}
blockRes := &coretypes.ResultBlockResults{
TxsResults: []*abci.ExecTxResult{{Data: bz1}, {Data: bz2}},
ConsensusParamUpdates: &types2.ConsensusParams{
Block: &types2.BlockParams{
MaxBytes: 100000000,
MaxGas: 200000000,
},
},
}

ctxProvider := func(h int64) sdk.Context {
if h == evmrpc.LatestCtxHeight {
return ctx
}
return ctx.WithBlockHeight(h)
}
txConfigProvider := func(int64) client.TxConfig { return TxConfig }
cache := evmrpc.NewBlockCache(3000)
mu := &sync.Mutex{}

decodeOnly := countDecodeOnlyEvmTxs(block.Block.Txs, TxConfig.TxDecoder())
require.Equal(t, 2, decodeOnly)

encoded, err := evmrpc.EncodeTmBlock(ctxProvider, txConfigProvider, block, blockRes, k, false, false, false, nil, cache, mu)
require.NoError(t, err)
list := encoded["transactions"].([]interface{})

tm := &parityTxCountTMClient{block: block}
wm := evmrpc.NewWatermarkManager(tm, ctxProvider, nil, nil)
api := evmrpc.NewBlockAPI(tm, k, ctxProvider, txConfigProvider, evmrpc.ConnectionTypeHTTP, wm, cache, mu)
rpcCount, err := api.GetBlockTransactionCountByNumber(context.Background(), rpc.BlockNumber(parityTestHeight))
require.NoError(t, err)
require.NotNil(t, rpcCount)
require.Equal(t, len(list), int(*rpcCount))
require.Greater(t, decodeOnly, len(list))
}

func countDecodeOnlyEvmTxs(txs tmtypes.Txs, dec sdk.TxDecoder) int {
n := 0
for _, tx := range txs {
decoded, err := dec(tx)
if err != nil || len(decoded.GetMsgs()) != 1 {
continue
}
evmTx, ok := decoded.GetMsgs()[0].(*types.MsgEVMTransaction)
if !ok || evmTx.IsAssociateTx() {
continue
}
n++
}
return n
}
Loading