Skip to content
Merged
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
2 changes: 1 addition & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -2565,7 +2565,7 @@ func (app *App) RegisterLocalServices(node client.LocalClient, txConfig client.T
rpcCtxProvider := app.RPCContextProvider
traceCtxProvider := app.SnapshotAwareRPCContextProvider()
if app.evmRPCConfig.HTTPEnabled {
evmHTTPServer, err := evmrpc.NewEVMHTTPServer(app.evmRPCConfig, node, &app.EvmKeeper, app.BeginBlockKeepers, app.BaseApp, app.TracerAnteHandler, app.RPCContextProvider, txConfigProvider, DefaultNodeHome, app.GetStateStore(), nil, traceCtxProvider)
evmHTTPServer, err := evmrpc.NewEVMHTTPServer(app.evmRPCConfig, node, &app.EvmKeeper, app.BeginBlockKeepers, app.BaseApp, app.TracerAnteHandler, app.RPCContextProvider, txConfigProvider, DefaultNodeHome, app.GetStateStore(), traceCtxProvider)
if err != nil {
panic(err)
}
Expand Down
9 changes: 1 addition & 8 deletions evmrpc/server.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package evmrpc

import (
"context"
"strings"
"sync"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rpc"

"github.com/sei-protocol/sei-chain/app/legacyabci"
Expand Down Expand Up @@ -43,7 +41,6 @@ func NewEVMHTTPServer(
txConfigProvider func(int64) client.TxConfig,
homeDir string,
stateStore types.StateStore,
isPanicOrSyntheticTxFunc func(ctx context.Context, hash common.Hash) (bool, error), // used in *ExcludeTraceFail endpoints
traceCtxProviders ...TraceContextProvider,
) (EVMServer, error) {

Expand Down Expand Up @@ -105,11 +102,7 @@ func NewEVMHTTPServer(
TipFn: func() int64 { return ctxProvider(LatestCtxHeight).BlockHeight() },
})
}
if isPanicOrSyntheticTxFunc == nil {
isPanicOrSyntheticTxFunc = func(ctx context.Context, hash common.Hash) (bool, error) {
return debugAPI.isPanicOrSyntheticTx(ctx, hash)
}
}
isPanicOrSyntheticTxFunc := debugAPI.isPanicOrSyntheticTx
seiLegacyAllowlist := BuildSeiLegacyEnabledSet(config.EnabledLegacySeiApis)

seiTxAPI := NewSeiTransactionAPI(tmClient, k, ctxProvider, txConfigProvider, homeDir, ConnectionTypeHTTP, isPanicOrSyntheticTxFunc, watermarks, globalBlockCache, cacheCreationMutex)
Expand Down
11 changes: 2 additions & 9 deletions evmrpc/setup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ func init() {
goodConfig.MaxLogNoBlock = 10
goodConfig.EnabledLegacySeiApis = evmrpc.SeiLegacyAllGatedMethodNames()
txConfigProvider := func(int64) client.TxConfig { return TxConfig }
HttpServer, err := evmrpc.NewEVMHTTPServer(goodConfig, &MockClient{}, EVMKeeper, testApp.BeginBlockKeepers, testApp.BaseApp, testApp.TracerAnteHandler, ctxProvider, txConfigProvider, "", nil, isPanicTxFunc)
HttpServer, err := evmrpc.NewEVMHTTPServer(goodConfig, &MockClient{}, EVMKeeper, testApp.BeginBlockKeepers, testApp.BaseApp, testApp.TracerAnteHandler, ctxProvider, txConfigProvider, "", nil)
if err != nil {
panic(err)
}
Expand All @@ -611,7 +611,7 @@ func init() {
badConfig := evmrpcconfig.DefaultConfig
badConfig.HTTPPort = TestBadPort
badConfig.FilterTimeout = 500 * time.Millisecond
badHTTPServer, err := evmrpc.NewEVMHTTPServer(badConfig, &MockBadClient{}, EVMKeeper, testApp.BeginBlockKeepers, testApp.BaseApp, testApp.TracerAnteHandler, ctxProvider, txConfigProvider, "", nil, nil)
badHTTPServer, err := evmrpc.NewEVMHTTPServer(badConfig, &MockBadClient{}, EVMKeeper, testApp.BeginBlockKeepers, testApp.BaseApp, testApp.TracerAnteHandler, ctxProvider, txConfigProvider, "", nil)
if err != nil {
panic(err)
}
Expand All @@ -636,7 +636,6 @@ func init() {
txConfigProvider,
"",
nil,
isPanicTxFunc,
)
if err != nil {
panic(err)
Expand All @@ -661,7 +660,6 @@ func init() {
txConfigProvider,
"",
nil,
isPanicTxFunc,
)
if err != nil {
panic(err)
Expand Down Expand Up @@ -1296,8 +1294,3 @@ func TestEcho(t *testing.T) {
require.Nil(t, err)
require.Equal(t, "{\"jsonrpc\":\"2.0\",\"id\":\"test\",\"result\":\"something\"}\n", string(buf))
}

func isPanicTxFunc(ctx context.Context, hash common.Hash) (bool, error) {
result := hash == common.HexToHash(TestPanicTxHash) || hash == common.HexToHash(TestSyntheticTxHash)
return result, nil
}
3 changes: 0 additions & 3 deletions evmrpc/tests/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,6 @@ func setupTestServer(
func(int64) client.TxConfig { return a.GetTxConfig() },
"",
nil,
func(ctx context.Context, hash common.Hash) (bool, error) {
return false, nil
},
)
if err != nil {
panic(err)
Expand Down
8 changes: 3 additions & 5 deletions evmrpc/tracers.go
Original file line number Diff line number Diff line change
Expand Up @@ -484,11 +484,9 @@ func (api *DebugAPI) isPanicOrSyntheticTx(ctx context.Context, hash common.Hash)
sdkctx := api.ctxProvider(LatestCtxHeight)
receipt, rerr := api.keeper.GetReceipt(sdkctx, hash)
if rerr != nil {
// No receipt: treat as panic/synthetic. Ante-rejected txs and unknown
// hashes both land here; either way, no trace to surface.
if api.isPanicCache != nil {
api.isPanicCache.Add(hash, true)
}
// No receipt: treat as panic/synthetic. Not cached — the receipt
// store can lag the RPC for a freshly committed tx, so this answer
// may flip to "include" once the write lands.
return true, nil
}

Expand Down
48 changes: 48 additions & 0 deletions evmrpc/tx_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package evmrpc_test

import (
"crypto/rand"
"encoding/json"
"fmt"
"io"
Expand Down Expand Up @@ -157,6 +158,53 @@ func TestGetTransactionReceiptExcludeTraceFail(t *testing.T) {
require.Nil(t, resObj["result"])
}

// The panic/synthetic decision for a missing receipt must not be cached.
// Receipt-store writes can lag the RPC for a freshly committed tx, so a hash
// that initially looks panic-like must flip to "include" once its receipt
// (Status=1) lands within the cache TTL.
func TestGetTransactionReceiptExcludeTraceFailLateReceipt(t *testing.T) {
// Fresh hash per invocation so the test stays correct under -count>1
// (the receipt store and isPanicCache persist across iterations).
var hashBytes [32]byte
_, err := rand.Read(hashBytes[:])
require.NoError(t, err)
hash := common.Hash(hashBytes)

call := func() map[string]interface{} {
body := fmt.Sprintf("{\"jsonrpc\": \"2.0\",\"method\": \"sei_getTransactionReceiptExcludeTraceFail\",\"params\":[\"%s\"],\"id\":\"test\"}", hash.Hex())
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s:%d", TestAddr, TestPort), strings.NewReader(body))
require.Nil(t, err)
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
require.Nil(t, err)
resBody, err := io.ReadAll(res.Body)
require.Nil(t, err)
resObj := map[string]interface{}{}
require.Nil(t, json.Unmarshal(resBody, &resObj))
return resObj
}

// First call: no receipt → endpoint reports the tx as panic.
resObj := call()
errObj, ok := resObj["error"].(map[string]interface{})
require.True(t, ok)
require.Equal(t, evmrpc.ErrPanicTx.Error(), errObj["message"])

// Receipt lands with Status=1. The next call must NOT still report the
// tx as panic — that would mean the prior "no receipt" answer was cached.
require.NoError(t, EVMKeeper.MockReceipt(Ctx, hash, &types.Receipt{
BlockNumber: MockHeight8,
TransactionIndex: 0,
TxHashHex: hash.Hex(),
Status: 1,
EffectiveGasPrice: 1000000,
}))
resObj = call()
if errObj, ok := resObj["error"].(map[string]interface{}); ok {
require.NotEqual(t, evmrpc.ErrPanicTx.Error(), errObj["message"], "cache was poisoned by the prior missing-receipt lookup")
}
}

func TestCumulativeGasUsedPopulation(t *testing.T) {
blockHeight := int64(1000)
Ctx = Ctx.WithBlockHeight(blockHeight)
Expand Down
Loading