Skip to content
Merged
32 changes: 4 additions & 28 deletions evmrpc/association.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rpc"
"github.com/sei-protocol/sei-chain/sei-cosmos/client"
sdk "github.com/sei-protocol/sei-chain/sei-cosmos/types"
sdkerrors "github.com/sei-protocol/sei-chain/sei-cosmos/types/errors"
Expand Down Expand Up @@ -157,37 +156,14 @@ func (t *AssociationAPI) GetCosmosTx(ctx context.Context, ethHash common.Hash) (
return "", fmt.Errorf("invalid block number: %d", receipt.BlockNumber)
}
height := int64(receipt.BlockNumber) //nolint:gosec
number := rpc.BlockNumber(height)
numberPtr, err := getBlockNumber(ctx, t.tmClient, number)
block, err := blockByNumberRespectingWatermarks(ctx, t.tmClient, t.watermarks, &height, 1)
if err != nil {
return "", err
}
block, err := blockByNumberRespectingWatermarks(ctx, t.tmClient, t.watermarks, numberPtr, 1)
if err != nil {
return "", err
}
blockRes, err := blockResultsWithRetry(ctx, t.tmClient, &height)
if err != nil {
return "", err
if int(receipt.TransactionIndex) >= len(block.Block.Txs) {
return "", fmt.Errorf("transaction index %d out of range (block has %d txs)", receipt.TransactionIndex, len(block.Block.Txs))
}
for i := range blockRes.TxsResults {
tmTx := block.Block.Txs[i]
decoded, err := t.txConfigProvider(block.Block.Height).TxDecoder()(block.Block.Txs[i])
if err != nil {
return "", err
}
for _, msg := range decoded.GetMsgs() {
switch m := msg.(type) {
case *types.MsgEVMTransaction:
ethtx, _ := m.AsTransaction()
hash := ethtx.Hash()
if hash == ethHash {
return fmt.Sprintf("%X", tmTx.Hash()), nil
}
}
}
}
return "", fmt.Errorf("transaction not found")
return fmt.Sprintf("%X", block.Block.Txs[receipt.TransactionIndex].Hash()), nil
}

func (t *AssociationAPI) GetEvmTx(ctx context.Context, cosmosHash string) (result string, returnErr error) {
Expand Down
15 changes: 4 additions & 11 deletions evmrpc/simulate.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,11 +364,6 @@ func (b Backend) BlockByNumber(ctx context.Context, bn rpc.BlockNumber) (*ethtyp
if err != nil {
return nil, nil, err
}
blockRes, err := b.tmClient.BlockResults(ctx, &tmBlock.Block.Height)
if err != nil {
return nil, nil, err
}
TraceTendermintIfApplicable(ctx, "BlockResults", []string{stringifyInt64Ptr(&tmBlock.Block.Height)}, blockRes)
sdkCtx := b.ctxProvider(LatestCtxHeight)
var txs []*ethtypes.Transaction
var metadata []tracersutils.TraceBlockMetadata
Expand All @@ -377,8 +372,8 @@ func (b Backend) BlockByNumber(ctx context.Context, bn rpc.BlockNumber) (*ethtyp
for _, msg := range msgs {
idxToMsgs[msg.index] = msg.msg
}
for i := range blockRes.TxsResults {
decoded, err := b.txConfigProvider(blockRes.Height).TxDecoder()(tmBlock.Block.Txs[i])
for i := range tmBlock.Block.Txs {
decoded, err := b.txConfigProvider(tmBlock.Block.Height).TxDecoder()(tmBlock.Block.Txs[i])
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -687,11 +682,9 @@ func (b *Backend) getHeader(ctx context.Context, tmBlock *coretypes.ResultBlock)
baseFee = nil
}
var gasLimit uint64
blockRes, blockResErr := blockResultsWithRetry(ctx, b.tmClient, &height)
if blockResErr == nil && blockRes.ConsensusParamUpdates != nil && blockRes.ConsensusParamUpdates.Block != nil {
gasLimit = uint64(blockRes.ConsensusParamUpdates.Block.MaxGas) //nolint:gosec
if cp := sdkCtx.ConsensusParams(); cp != nil && cp.Block != nil {
gasLimit = uint64(cp.Block.MaxGas) //nolint:gosec
} else {
// Fallback to default if block results unavailable
gasLimit = keeper.DefaultBlockGasLimit
}

Expand Down
37 changes: 17 additions & 20 deletions evmrpc/simulate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ import (
"github.com/sei-protocol/sei-chain/example/contracts/simplestorage"
"github.com/sei-protocol/sei-chain/sei-cosmos/client"
sdk "github.com/sei-protocol/sei-chain/sei-cosmos/types"
receipt "github.com/sei-protocol/sei-chain/sei-db/ledger_db/receipt"
"github.com/sei-protocol/sei-chain/sei-db/ledger_db/receipt"
"github.com/sei-protocol/sei-chain/sei-tendermint/libs/bytes"
tenderminttypes "github.com/sei-protocol/sei-chain/sei-tendermint/proto/tendermint/types"
"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"
Expand All @@ -33,13 +34,6 @@ import (
"github.com/stretchr/testify/require"
)

// brFailClient fails BlockResults
type brFailClient struct{ *MockClient }

func (br brFailClient) BlockResults(ctx context.Context, h *int64) (*coretypes.ResultBlockResults, error) {
return nil, fmt.Errorf("fail br")
}

func primeReceiptStore(t *testing.T, store receipt.ReceiptStore, latest int64) {
t.Helper()
if store == nil {
Expand Down Expand Up @@ -411,10 +405,11 @@ func TestPreV620UpgradeUsesBaseFeeNil(t *testing.T) {
require.NotNil(t, headerDifferentChain.BaseFee, "Base fee should not be nil for non-pacific-1 chains")
}

// Concise gas-limit sanity test
// Header gasLimit comes from the active SDK ConsensusParams at the block's height.
func TestGasLimitUsesConsensusOrConfig(t *testing.T) {
testApp := app.Setup(t, false, false, false)
baseCtx := testApp.GetContextForDeliverTx([]byte{}).WithBlockHeight(1)
baseCtx := testApp.GetContextForDeliverTx([]byte{}).WithBlockHeight(1).
WithConsensusParams(&tenderminttypes.ConsensusParams{Block: &tenderminttypes.BlockParams{MaxGas: 200_000_000}})

ctxProvider := func(h int64) sdk.Context { return baseCtx.WithBlockHeight(h) }
cfg := &evmrpc.SimulateConfig{GasCap: 10_000_000, EVMTimeout: time.Second}
Expand All @@ -435,25 +430,27 @@ func TestGasLimitUsesConsensusOrConfig(t *testing.T) {
require.Equal(t, uint64(200_000_000), header2.GasLimit)
}

// Gaslimit fallback tests
// Gas-limit fallback tests
func TestGasLimitFallbackToDefault(t *testing.T) {
testApp := app.Setup(t, false, false, false)
baseCtx := testApp.GetContextForDeliverTx([]byte{}).WithBlockHeight(1)
ctxProvider := func(h int64) sdk.Context { return baseCtx.WithBlockHeight(h) }
cfg := &evmrpc.SimulateConfig{GasCap: 20_000_000, EVMTimeout: time.Second}

// Case 1: BlockResults fails
brClient := &brFailClient{MockClient: &MockClient{}}
watermarks1 := evmrpc.NewWatermarkManager(brClient, ctxProvider, nil, testApp.EvmKeeper.ReceiptStore())
backend1 := evmrpc.NewBackend(ctxProvider, &testApp.EvmKeeper, legacyabci.BeginBlockKeepers{}, func(int64) client.TxConfig { return TxConfig }, brClient, cfg, testApp.BaseApp, testApp.TracerAnteHandler, evmrpc.NewBlockCache(3000), &sync.Mutex{}, watermarks1)
// Case 1: ConsensusParams is nil → DefaultBlockGasLimit.
nilParamsCtx := testApp.GetContextForDeliverTx([]byte{}).WithBlockHeight(1).WithConsensusParams(nil)
ctxProvider1 := func(h int64) sdk.Context { return nilParamsCtx.WithBlockHeight(h) }
tmClient1 := &MockClient{}
watermarks1 := evmrpc.NewWatermarkManager(tmClient1, ctxProvider1, nil, testApp.EvmKeeper.ReceiptStore())
backend1 := evmrpc.NewBackend(ctxProvider1, &testApp.EvmKeeper, legacyabci.BeginBlockKeepers{}, func(int64) client.TxConfig { return TxConfig }, tmClient1, cfg, testApp.BaseApp, testApp.TracerAnteHandler, evmrpc.NewBlockCache(3000), &sync.Mutex{}, watermarks1)
h1, err := backend1.HeaderByNumber(context.Background(), 1)
require.NoError(t, err)
require.Equal(t, uint64(10_000_000), h1.GasLimit) // DefaultBlockGasLimit

// Case 2: Block fails — with one RPC path for the block, resolution errors out entirely.
// Case 2: Block fails — resolution errors out entirely.
baseCtx := testApp.GetContextForDeliverTx([]byte{}).WithBlockHeight(1)
ctxProvider2 := func(h int64) sdk.Context { return baseCtx.WithBlockHeight(h) }
bcClient := &bcAlwaysFailClient{MockClient: &MockClient{}}
watermarks2 := evmrpc.NewWatermarkManager(bcClient, ctxProvider, nil, testApp.EvmKeeper.ReceiptStore())
backend2 := evmrpc.NewBackend(ctxProvider, &testApp.EvmKeeper, legacyabci.BeginBlockKeepers{}, func(int64) client.TxConfig { return TxConfig }, bcClient, cfg, testApp.BaseApp, testApp.TracerAnteHandler, evmrpc.NewBlockCache(3000), &sync.Mutex{}, watermarks2)
watermarks2 := evmrpc.NewWatermarkManager(bcClient, ctxProvider2, nil, testApp.EvmKeeper.ReceiptStore())
backend2 := evmrpc.NewBackend(ctxProvider2, &testApp.EvmKeeper, legacyabci.BeginBlockKeepers{}, func(int64) client.TxConfig { return TxConfig }, bcClient, cfg, testApp.BaseApp, testApp.TracerAnteHandler, evmrpc.NewBlockCache(3000), &sync.Mutex{}, watermarks2)
_, err = backend2.HeaderByNumber(context.Background(), 1)
require.Error(t, err)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Data-dependent: bind block hash from latest, then debug_traceBlockByHash(blockHash). Run evm_rpc_tests.sh when local.
>> {"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["latest",false]}
// Resolve the deploy tx's block hash, then trace that block. The deploy is a known EVM tx,
// so the result must be non-empty. expect_body_contains "txHash" rejects an empty result (`[]`).
>> {"jsonrpc":"2.0","id":1,"method":"eth_getTransactionReceipt","params":["${deployTxHash}"]}
<< {"jsonrpc":"2.0","id":1,"result":{}}
@ bind blockHash = result.hash
@ bind blockHash = result.blockHash
>> {"jsonrpc":"2.0","id":1,"method":"debug_traceBlockByHash","params":["${blockHash}",{"tracer":"callTracer"}]}
<< {"jsonrpc":"2.0","id":1,"result":[]}
@ expect_body_contains "txHash"
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Data-dependent: bind block number from latest, then debug_traceBlockByNumber(blockNum). Run evm_rpc_tests.sh when local.
>> {"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["latest",false]}
// Resolve the deploy tx's block number, then trace that block. The deploy is a known EVM tx,
// so the result must be non-empty. expect_body_contains "txHash" rejects an empty result (`[]`).
>> {"jsonrpc":"2.0","id":1,"method":"eth_getTransactionReceipt","params":["${deployTxHash}"]}
<< {"jsonrpc":"2.0","id":1,"result":{}}
@ bind blockNum = result.number
@ bind blockNum = result.blockNumber
>> {"jsonrpc":"2.0","id":1,"method":"debug_traceBlockByNumber","params":["${blockNum}",{"tracer":"callTracer"}]}
<< {"jsonrpc":"2.0","id":1,"result":[]}
@ expect_body_contains "txHash"
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Positive case: look up the cosmos tx hash for the seeded deploy tx.
// Spec-only matcher: a regression in the lookup returns `error` (kind mismatch) and fails this test.
>> {"jsonrpc":"2.0","id":1,"method":"sei_getCosmosTx","params":["${deployTxHash}"]}
<< {"jsonrpc":"2.0","id":1,"result":""}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Data-dependent: bind block hash from latest, then sei_traceBlockByHashExcludeTraceFail(blockHash). Run evm_rpc_tests.sh when local.
>> {"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["latest",false]}
// Resolve the deploy tx's block hash, then trace that block. The deploy is a known-successful EVM tx,
// so the result must be non-empty. expect_body_contains "txHash" rejects an empty result (`[]`).
>> {"jsonrpc":"2.0","id":1,"method":"eth_getTransactionReceipt","params":["${deployTxHash}"]}
<< {"jsonrpc":"2.0","id":1,"result":{}}
@ bind blockHash = result.hash
@ bind blockHash = result.blockHash
>> {"jsonrpc":"2.0","id":1,"method":"sei_traceBlockByHashExcludeTraceFail","params":["${blockHash}",{"tracer":"callTracer"}]}
<< {"jsonrpc":"2.0","id":1,"result":[]}
@ expect_body_contains "txHash"
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Data-dependent: bind block number from latest, then sei_traceBlockByNumberExcludeTraceFail(blockNum). Run evm_rpc_tests.sh when local.
>> {"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["latest",false]}
// Resolve the deploy tx's block number, then trace that block. The deploy is a known-successful EVM tx,
// so the result must be non-empty. expect_body_contains "txHash" rejects an empty result (`[]`).
>> {"jsonrpc":"2.0","id":1,"method":"eth_getTransactionReceipt","params":["${deployTxHash}"]}
<< {"jsonrpc":"2.0","id":1,"result":{}}
@ bind blockNum = result.number
@ bind blockNum = result.blockNumber
>> {"jsonrpc":"2.0","id":1,"method":"sei_traceBlockByNumberExcludeTraceFail","params":["${blockNum}",{"tracer":"callTracer"}]}
<< {"jsonrpc":"2.0","id":1,"result":[]}
@ expect_body_contains "txHash"
Loading