From 63a29685a9de659f570b0d69f216cdfb5617f6f9 Mon Sep 17 00:00:00 2001 From: Matthieu Vachon Date: Fri, 29 Mar 2024 09:17:35 -0400 Subject: [PATCH] Update that brings `go-ethereum` with live tracer support (#1375) * Update that brings `go-ethereum` with live tracer support This only brings the dependency (will need to wait for a merge + tag of the branch before merging this PR) and the required changes to adapt `DBImpl` to support the new interface. Relates to: - https://github.com/sei-protocol/go-ethereum/pull/15 - https://github.com/sei-protocol/sei-chain/pull/1344 * Added missing instrumentation when state changes in `DBImpl` --- app/eth_replay.go | 3 ++- evmrpc/simulate.go | 4 +-- go.mod | 2 +- go.sum | 4 +-- x/evm/module_test.go | 15 ++++++----- x/evm/state/balance.go | 29 ++++++++++++++++---- x/evm/state/balance_test.go | 53 +++++++++++++++++++------------------ x/evm/state/check_test.go | 5 ++-- x/evm/state/code.go | 10 +++++++ x/evm/state/log.go | 4 +++ x/evm/state/nonce.go | 6 +++++ x/evm/state/state.go | 8 +++++- x/evm/state/state_test.go | 5 ++-- x/evm/state/statedb.go | 8 ++++++ 14 files changed, 107 insertions(+), 49 deletions(-) diff --git a/app/eth_replay.go b/app/eth_replay.go index 2414f3f46..a16bae7ed 100644 --- a/app/eth_replay.go +++ b/app/eth_replay.go @@ -10,6 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/core/tracing" ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" ethtests "github.com/ethereum/go-ethereum/tests" @@ -81,7 +82,7 @@ func Replay(a *App) { for _, w := range b.Withdrawals() { amount := new(big.Int).SetUint64(w.Amount) amount = amount.Mul(amount, big.NewInt(params.GWei)) - s.AddBalance(w.Address, amount) + s.AddBalance(w.Address, amount, tracing.BalanceIncreaseWithdrawal) } _, _ = s.Finalize() for _, tx := range b.Txs { diff --git a/evmrpc/simulate.go b/evmrpc/simulate.go index 9f6718f89..8e82ef1b3 100644 --- a/evmrpc/simulate.go +++ b/evmrpc/simulate.go @@ -263,7 +263,7 @@ func (b *Backend) HeaderByNumber(ctx context.Context, bn rpc.BlockNumber) (*etht return b.getHeader(big.NewInt(height)), nil } -func (b *Backend) StateAtTransaction(ctx context.Context, block *ethtypes.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, vm.StateDB, tracers.StateReleaseFunc, error) { +func (b *Backend) StateAtTransaction(ctx context.Context, block *ethtypes.Block, txIndex int, reexec uint64) (*ethtypes.Transaction, vm.BlockContext, vm.StateDB, tracers.StateReleaseFunc, error) { emptyRelease := func() {} // Short circuit if it's genesis block. if block.Number().Int64() == 0 { @@ -289,7 +289,7 @@ func (b *Backend) StateAtTransaction(ctx context.Context, block *ethtypes.Block, blockContext.Time = block.Time() if idx == txIndex { - return msg, *blockContext, statedb, emptyRelease, nil + return tx, *blockContext, statedb, emptyRelease, nil } // Not yet the searched for transaction, execute on top of the current state vmenv := vm.NewEVM(*blockContext, txContext, statedb, b.ChainConfig(), vm.Config{}) diff --git a/go.mod b/go.mod index 3cdf6d9ea..6aaa53393 100644 --- a/go.mod +++ b/go.mod @@ -349,7 +349,7 @@ replace ( github.com/cosmos/cosmos-sdk => github.com/sei-protocol/sei-cosmos v0.2.79-seiv2-hotfix github.com/cosmos/iavl => github.com/sei-protocol/sei-iavl v0.1.9 github.com/cosmos/ibc-go/v3 => github.com/sei-protocol/sei-ibc-go/v3 v3.3.0 - github.com/ethereum/go-ethereum => github.com/sei-protocol/go-ethereum v1.13.5-sei-12 + github.com/ethereum/go-ethereum => github.com/sei-protocol/go-ethereum v1.13.5-sei-9.0.20240327165640-6ab0d196bac6 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/sei-protocol/sei-db => github.com/sei-protocol/sei-db v0.0.35 // Latest goleveldb is broken, we have to stick to this version diff --git a/go.sum b/go.sum index 2c3256a36..c0f414a31 100644 --- a/go.sum +++ b/go.sum @@ -1343,8 +1343,8 @@ github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod github.com/securego/gosec/v2 v2.11.0 h1:+PDkpzR41OI2jrw1q6AdXZCbsNGNGT7pQjal0H0cArI= github.com/securego/gosec/v2 v2.11.0/go.mod h1:SX8bptShuG8reGC0XS09+a4H2BoWSJi+fscA+Pulbpo= github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= -github.com/sei-protocol/go-ethereum v1.13.5-sei-12 h1:sWGD3sV9F3Ilgmn8le8lhpfAwSi6n57I921cYuNvLuo= -github.com/sei-protocol/go-ethereum v1.13.5-sei-12/go.mod h1:kcRZmuzRn1lVejiFNTz4l4W7imnpq1bDAnuKS/RyhbQ= +github.com/sei-protocol/go-ethereum v1.13.5-sei-9.0.20240327165640-6ab0d196bac6 h1:AU9VAvZsTGibuzzVmoX3taGOWjPJJct5ypXDg6vKKu0= +github.com/sei-protocol/go-ethereum v1.13.5-sei-9.0.20240327165640-6ab0d196bac6/go.mod h1:kcRZmuzRn1lVejiFNTz4l4W7imnpq1bDAnuKS/RyhbQ= github.com/sei-protocol/goutils v0.0.2 h1:Bfa7Sv+4CVLNM20QcpvGb81B8C5HkQC/kW1CQpIbXDA= github.com/sei-protocol/goutils v0.0.2/go.mod h1:iYE2DuJfEnM+APPehr2gOUXfuLuPsVxorcDO+Tzq9q8= github.com/sei-protocol/sei-cosmos v0.2.79-seiv2-hotfix h1:Yx2W7/xrGk13rpZfs+bkjx229b9LCbcCpcwTrzbz26Y= diff --git a/x/evm/module_test.go b/x/evm/module_test.go index b7e173c41..ea9dd2b25 100644 --- a/x/evm/module_test.go +++ b/x/evm/module_test.go @@ -7,6 +7,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/tracing" ethtypes "github.com/ethereum/go-ethereum/core/types" testkeeper "github.com/sei-protocol/sei-chain/testutil/keeper" "github.com/sei-protocol/sei-chain/x/evm" @@ -28,19 +29,19 @@ func TestABCI(t *testing.T) { m.BeginBlock(ctx, abci.RequestBeginBlock{}) // 1st tx s := state.NewDBImpl(ctx.WithTxIndex(1), k, false) - s.SubBalance(evmAddr1, big.NewInt(10000000000000)) - s.AddBalance(evmAddr2, big.NewInt(8000000000000)) + s.SubBalance(evmAddr1, big.NewInt(10000000000000), tracing.BalanceChangeUnspecified) + s.AddBalance(evmAddr2, big.NewInt(8000000000000), tracing.BalanceChangeUnspecified) feeCollectorAddr, err := k.GetFeeCollectorAddress(ctx) require.Nil(t, err) - s.AddBalance(feeCollectorAddr, big.NewInt(2000000000000)) + s.AddBalance(feeCollectorAddr, big.NewInt(2000000000000), tracing.BalanceChangeUnspecified) surplus, err := s.Finalize() require.Nil(t, err) require.Equal(t, sdk.ZeroInt(), surplus) k.AppendToEvmTxDeferredInfo(ctx.WithTxIndex(1), ethtypes.Bloom{}, common.Hash{}, surplus) // 3rd tx s = state.NewDBImpl(ctx.WithTxIndex(3), k, false) - s.SubBalance(evmAddr2, big.NewInt(5000000000000)) - s.AddBalance(evmAddr1, big.NewInt(5000000000000)) + s.SubBalance(evmAddr2, big.NewInt(5000000000000), tracing.BalanceChangeUnspecified) + s.AddBalance(evmAddr1, big.NewInt(5000000000000), tracing.BalanceChangeUnspecified) surplus, err = s.Finalize() require.Nil(t, err) require.Equal(t, sdk.ZeroInt(), surplus) @@ -54,8 +55,8 @@ func TestABCI(t *testing.T) { m.BeginBlock(ctx, abci.RequestBeginBlock{}) // 2nd tx s = state.NewDBImpl(ctx.WithTxIndex(2), k, false) - s.SubBalance(evmAddr2, big.NewInt(3000000000000)) - s.AddBalance(evmAddr1, big.NewInt(2000000000000)) + s.SubBalance(evmAddr2, big.NewInt(3000000000000), tracing.BalanceChangeUnspecified) + s.AddBalance(evmAddr1, big.NewInt(2000000000000), tracing.BalanceChangeUnspecified) surplus, err = s.Finalize() require.Nil(t, err) require.Equal(t, sdk.NewInt(1000000000000), surplus) diff --git a/x/evm/state/balance.go b/x/evm/state/balance.go index 0de4863f6..0ed16f6b1 100644 --- a/x/evm/state/balance.go +++ b/x/evm/state/balance.go @@ -5,16 +5,17 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/tracing" "github.com/sei-protocol/sei-chain/x/evm/types" ) -func (s *DBImpl) SubBalance(evmAddr common.Address, amt *big.Int) { +func (s *DBImpl) SubBalance(evmAddr common.Address, amt *big.Int, reason tracing.BalanceChangeReason) { s.k.PrepareReplayedAddr(s.ctx, evmAddr) if amt.Sign() == 0 { return } if amt.Sign() < 0 { - s.AddBalance(evmAddr, new(big.Int).Neg(amt)) + s.AddBalance(evmAddr, new(big.Int).Neg(amt), reason) return } @@ -28,16 +29,25 @@ func (s *DBImpl) SubBalance(evmAddr common.Address, amt *big.Int) { if s.err != nil { return } + + if s.logger != nil && s.logger.OnBalanceChange != nil { + // We could modify AddWei instead so it returns us the old/new balance directly. + newBalance := s.GetBalance(evmAddr) + oldBalance := new(big.Int).Add(newBalance, amt) + + s.logger.OnBalanceChange(evmAddr, oldBalance, newBalance, reason) + } + s.tempStateCurrent.surplus = s.tempStateCurrent.surplus.Add(sdk.NewIntFromBigInt(amt)) } -func (s *DBImpl) AddBalance(evmAddr common.Address, amt *big.Int) { +func (s *DBImpl) AddBalance(evmAddr common.Address, amt *big.Int, reason tracing.BalanceChangeReason) { s.k.PrepareReplayedAddr(s.ctx, evmAddr) if amt.Sign() == 0 { return } if amt.Sign() < 0 { - s.SubBalance(evmAddr, new(big.Int).Neg(amt)) + s.SubBalance(evmAddr, new(big.Int).Neg(amt), reason) return } @@ -51,6 +61,15 @@ func (s *DBImpl) AddBalance(evmAddr common.Address, amt *big.Int) { if s.err != nil { return } + + if s.logger != nil && s.logger.OnBalanceChange != nil { + // We could modify AddWei instead so it returns us the old/new balance directly. + newBalance := s.GetBalance(evmAddr) + oldBalance := new(big.Int).Sub(newBalance, amt) + + s.logger.OnBalanceChange(evmAddr, oldBalance, newBalance, reason) + } + s.tempStateCurrent.surplus = s.tempStateCurrent.surplus.Sub(sdk.NewIntFromBigInt(amt)) } @@ -62,7 +81,7 @@ func (s *DBImpl) GetBalance(evmAddr common.Address) *big.Int { } // should only be called during simulation -func (s *DBImpl) SetBalance(evmAddr common.Address, amt *big.Int) { +func (s *DBImpl) SetBalance(evmAddr common.Address, amt *big.Int, reason tracing.BalanceChangeReason) { if !s.simulation { panic("should never call SetBalance in a non-simulation setting") } diff --git a/x/evm/state/balance_test.go b/x/evm/state/balance_test.go index 639c82f6e..1201d3005 100644 --- a/x/evm/state/balance_test.go +++ b/x/evm/state/balance_test.go @@ -5,6 +5,7 @@ import ( "testing" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/core/tracing" testkeeper "github.com/sei-protocol/sei-chain/testutil/keeper" "github.com/sei-protocol/sei-chain/x/evm/state" "github.com/sei-protocol/sei-chain/x/evm/types" @@ -16,17 +17,17 @@ func TestAddBalance(t *testing.T) { db := state.NewDBImpl(ctx, k, false) seiAddr, evmAddr := testkeeper.MockAddressPair() require.Equal(t, big.NewInt(0), db.GetBalance(evmAddr)) - db.AddBalance(evmAddr, big.NewInt(0)) + db.AddBalance(evmAddr, big.NewInt(0), tracing.BalanceChangeUnspecified) // set association k.SetAddressMapping(db.Ctx(), seiAddr, evmAddr) require.Equal(t, big.NewInt(0), db.GetBalance(evmAddr)) - db.AddBalance(evmAddr, big.NewInt(10000000000000)) + db.AddBalance(evmAddr, big.NewInt(10000000000000), tracing.BalanceChangeUnspecified) require.Nil(t, db.Err()) require.Equal(t, db.GetBalance(evmAddr), big.NewInt(10000000000000)) _, evmAddr2 := testkeeper.MockAddressPair() - db.SubBalance(evmAddr2, big.NewInt(-5000000000000)) // should redirect to AddBalance + db.SubBalance(evmAddr2, big.NewInt(-5000000000000), tracing.BalanceChangeUnspecified) // should redirect to AddBalance require.Nil(t, db.Err()) require.Equal(t, db.GetBalance(evmAddr), big.NewInt(10000000000000)) require.Equal(t, db.GetBalance(evmAddr2), big.NewInt(5000000000000)) @@ -37,7 +38,7 @@ func TestSubBalance(t *testing.T) { db := state.NewDBImpl(ctx, k, false) seiAddr, evmAddr := testkeeper.MockAddressPair() require.Equal(t, big.NewInt(0), db.GetBalance(evmAddr)) - db.SubBalance(evmAddr, big.NewInt(0)) + db.SubBalance(evmAddr, big.NewInt(0), tracing.BalanceChangeUnspecified) // set association k.SetAddressMapping(db.Ctx(), seiAddr, evmAddr) @@ -45,7 +46,7 @@ func TestSubBalance(t *testing.T) { amt := sdk.NewCoins(sdk.NewCoin(k.GetBaseDenom(ctx), sdk.NewInt(20))) k.BankKeeper().MintCoins(db.Ctx(), types.ModuleName, amt) k.BankKeeper().SendCoinsFromModuleToAccount(db.Ctx(), types.ModuleName, seiAddr, amt) - db.SubBalance(evmAddr, big.NewInt(10000000000000)) + db.SubBalance(evmAddr, big.NewInt(10000000000000), tracing.BalanceChangeUnspecified) require.Nil(t, db.Err()) require.Equal(t, db.GetBalance(evmAddr), big.NewInt(10000000000000)) @@ -53,13 +54,13 @@ func TestSubBalance(t *testing.T) { amt = sdk.NewCoins(sdk.NewCoin(k.GetBaseDenom(ctx), sdk.NewInt(10))) k.BankKeeper().MintCoins(db.Ctx(), types.ModuleName, amt) k.BankKeeper().SendCoinsFromModuleToAccount(db.Ctx(), types.ModuleName, sdk.AccAddress(evmAddr2[:]), amt) - db.AddBalance(evmAddr2, big.NewInt(-5000000000000)) // should redirect to SubBalance + db.AddBalance(evmAddr2, big.NewInt(-5000000000000), tracing.BalanceChangeUnspecified) // should redirect to SubBalance require.Nil(t, db.Err()) require.Equal(t, db.GetBalance(evmAddr), big.NewInt(10000000000000)) require.Equal(t, db.GetBalance(evmAddr2), big.NewInt(5000000000000)) // insufficient balance - db.SubBalance(evmAddr2, big.NewInt(10000000000000)) + db.SubBalance(evmAddr2, big.NewInt(10000000000000), tracing.BalanceChangeUnspecified) require.NotNil(t, db.Err()) } @@ -67,12 +68,12 @@ func TestSetBalance(t *testing.T) { k, ctx := testkeeper.MockEVMKeeper() db := state.NewDBImpl(ctx, k, true) _, evmAddr := testkeeper.MockAddressPair() - db.SetBalance(evmAddr, big.NewInt(10000000000000)) + db.SetBalance(evmAddr, big.NewInt(10000000000000), tracing.BalanceChangeUnspecified) require.Equal(t, big.NewInt(10000000000000), db.GetBalance(evmAddr)) seiAddr2, evmAddr2 := testkeeper.MockAddressPair() k.SetAddressMapping(db.Ctx(), seiAddr2, evmAddr2) - db.SetBalance(evmAddr2, big.NewInt(10000000000000)) + db.SetBalance(evmAddr2, big.NewInt(10000000000000), tracing.BalanceChangeUnspecified) require.Equal(t, big.NewInt(10000000000000), db.GetBalance(evmAddr2)) } @@ -82,55 +83,55 @@ func TestSurplus(t *testing.T) { // test negative usei surplus negative wei surplus db := state.NewDBImpl(ctx, k, false) - db.AddBalance(evmAddr, big.NewInt(1_000_000_000_001)) + db.AddBalance(evmAddr, big.NewInt(1_000_000_000_001), tracing.BalanceChangeUnspecified) _, err := db.Finalize() require.NotNil(t, err) require.Contains(t, err.Error(), "negative surplus value") // test negative usei surplus positive wei surplus (negative total) db = state.NewDBImpl(ctx, k, false) - db.AddBalance(evmAddr, big.NewInt(1_000_000_000_000)) - db.SubBalance(evmAddr, big.NewInt(1)) + db.AddBalance(evmAddr, big.NewInt(1_000_000_000_000), tracing.BalanceChangeUnspecified) + db.SubBalance(evmAddr, big.NewInt(1), tracing.BalanceChangeUnspecified) _, err = db.Finalize() require.NotNil(t, err) require.Contains(t, err.Error(), "negative surplus value") // test negative usei surplus positive wei surplus (positive total) db = state.NewDBImpl(ctx, k, false) - db.AddBalance(evmAddr, big.NewInt(1_000_000_000_000)) - db.SubBalance(evmAddr, big.NewInt(2)) - db.SubBalance(evmAddr, big.NewInt(999_999_999_999)) + db.AddBalance(evmAddr, big.NewInt(1_000_000_000_000), tracing.BalanceChangeUnspecified) + db.SubBalance(evmAddr, big.NewInt(2), tracing.BalanceChangeUnspecified) + db.SubBalance(evmAddr, big.NewInt(999_999_999_999), tracing.BalanceChangeUnspecified) surplus, err := db.Finalize() require.Nil(t, err) require.Equal(t, sdk.OneInt(), surplus) // test positive usei surplus negative wei surplus (negative total) db = state.NewDBImpl(ctx, k, false) - db.SubBalance(evmAddr, big.NewInt(1_000_000_000_000)) - db.AddBalance(evmAddr, big.NewInt(2)) - db.AddBalance(evmAddr, big.NewInt(999_999_999_999)) + db.SubBalance(evmAddr, big.NewInt(1_000_000_000_000), tracing.BalanceChangeUnspecified) + db.AddBalance(evmAddr, big.NewInt(2), tracing.BalanceChangeUnspecified) + db.AddBalance(evmAddr, big.NewInt(999_999_999_999), tracing.BalanceChangeUnspecified) _, err = db.Finalize() require.NotNil(t, err) require.Contains(t, err.Error(), "negative surplus value") // test positive usei surplus negative wei surplus (positive total) db = state.NewDBImpl(ctx, k, false) - db.SubBalance(evmAddr, big.NewInt(1_000_000_000_000)) - db.AddBalance(evmAddr, big.NewInt(999_999_999_999)) + db.SubBalance(evmAddr, big.NewInt(1_000_000_000_000), tracing.BalanceChangeUnspecified) + db.AddBalance(evmAddr, big.NewInt(999_999_999_999), tracing.BalanceChangeUnspecified) surplus, err = db.Finalize() require.Nil(t, err) require.Equal(t, sdk.OneInt(), surplus) // test snapshots db = state.NewDBImpl(ctx, k, false) - db.SubBalance(evmAddr, big.NewInt(1_000_000_000_000)) - db.AddBalance(evmAddr, big.NewInt(999_999_999_999)) + db.SubBalance(evmAddr, big.NewInt(1_000_000_000_000), tracing.BalanceChangeUnspecified) + db.AddBalance(evmAddr, big.NewInt(999_999_999_999), tracing.BalanceChangeUnspecified) db.Snapshot() - db.SubBalance(evmAddr, big.NewInt(1_000_000_000_000)) - db.AddBalance(evmAddr, big.NewInt(999_999_999_999)) + db.SubBalance(evmAddr, big.NewInt(1_000_000_000_000), tracing.BalanceChangeUnspecified) + db.AddBalance(evmAddr, big.NewInt(999_999_999_999), tracing.BalanceChangeUnspecified) db.Snapshot() - db.SubBalance(evmAddr, big.NewInt(1_000_000_000_000)) - db.AddBalance(evmAddr, big.NewInt(999_999_999_999)) + db.SubBalance(evmAddr, big.NewInt(1_000_000_000_000), tracing.BalanceChangeUnspecified) + db.AddBalance(evmAddr, big.NewInt(999_999_999_999), tracing.BalanceChangeUnspecified) surplus, err = db.Finalize() require.Nil(t, err) require.Equal(t, sdk.NewInt(3), surplus) diff --git a/x/evm/state/check_test.go b/x/evm/state/check_test.go index d0a4bb67c..8d3d32133 100644 --- a/x/evm/state/check_test.go +++ b/x/evm/state/check_test.go @@ -4,6 +4,7 @@ import ( "math/big" "testing" + "github.com/ethereum/go-ethereum/core/tracing" testkeeper "github.com/sei-protocol/sei-chain/testutil/keeper" "github.com/sei-protocol/sei-chain/x/evm/state" "github.com/stretchr/testify/require" @@ -35,11 +36,11 @@ func TestEmpty(t *testing.T) { require.True(t, statedb.Empty(addr)) // has balance - statedb.AddBalance(addr, big.NewInt(1000000000000)) + statedb.AddBalance(addr, big.NewInt(1000000000000), tracing.BalanceChangeUnspecified) require.False(t, statedb.Empty(addr)) // has non-zero nonce - statedb.SubBalance(addr, big.NewInt(1000000000000)) + statedb.SubBalance(addr, big.NewInt(1000000000000), tracing.BalanceChangeUnspecified) statedb.SetNonce(addr, 1) require.False(t, statedb.Empty(addr)) diff --git a/x/evm/state/code.go b/x/evm/state/code.go index a9a49fc97..f7596db07 100644 --- a/x/evm/state/code.go +++ b/x/evm/state/code.go @@ -2,6 +2,7 @@ package state import ( "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" ) func (s *DBImpl) GetCodeHash(addr common.Address) common.Hash { @@ -16,6 +17,15 @@ func (s *DBImpl) GetCode(addr common.Address) []byte { func (s *DBImpl) SetCode(addr common.Address, code []byte) { s.k.PrepareReplayedAddr(s.ctx, addr) + + if s.logger != nil && s.logger.OnCodeChange != nil { + // The SetCode method could be modified to return the old code/hash directly. + oldCode := s.GetCode(addr) + oldHash := s.GetCodeHash(addr) + + s.logger.OnCodeChange(addr, oldHash, oldCode, common.Hash(crypto.Keccak256(code)), code) + } + s.k.SetCode(s.ctx, addr, code) } diff --git a/x/evm/state/log.go b/x/evm/state/log.go index 8df7ee256..682bca0db 100644 --- a/x/evm/state/log.go +++ b/x/evm/state/log.go @@ -12,6 +12,10 @@ type Logs struct { func (s *DBImpl) AddLog(l *ethtypes.Log) { l.Index = uint(len(s.GetAllLogs())) s.tempStateCurrent.logs = append(s.tempStateCurrent.logs, l) + + if s.logger != nil && s.logger.OnLog != nil { + s.logger.OnLog(l) + } } func (s *DBImpl) GetAllLogs() []*ethtypes.Log { diff --git a/x/evm/state/nonce.go b/x/evm/state/nonce.go index d251b6c81..d6eaef234 100644 --- a/x/evm/state/nonce.go +++ b/x/evm/state/nonce.go @@ -11,5 +11,11 @@ func (s *DBImpl) GetNonce(addr common.Address) uint64 { func (s *DBImpl) SetNonce(addr common.Address, nonce uint64) { s.k.PrepareReplayedAddr(s.ctx, addr) + + if s.logger != nil && s.logger.OnNonceChange != nil { + // The SetCode method could be modified to return the old code/hash directly. + s.logger.OnNonceChange(addr, s.GetNonce(addr), nonce) + } + s.k.SetNonce(s.ctx, addr, nonce) } diff --git a/x/evm/state/state.go b/x/evm/state/state.go index d4b8cc780..5856c8593 100644 --- a/x/evm/state/state.go +++ b/x/evm/state/state.go @@ -6,6 +6,7 @@ import ( storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/tracing" "github.com/sei-protocol/sei-chain/x/evm/types" ) @@ -31,6 +32,11 @@ func (s *DBImpl) getState(ctx sdk.Context, addr common.Address, hash common.Hash func (s *DBImpl) SetState(addr common.Address, key common.Hash, val common.Hash) { s.k.PrepareReplayedAddr(s.ctx, addr) + + if s.logger != nil && s.logger.OnStorageChange != nil { + s.logger.OnStorageChange(addr, key, s.GetState(addr, key), val) + } + s.k.SetState(s.ctx, addr, key, val) } @@ -62,7 +68,7 @@ func (s *DBImpl) SelfDestruct(acc common.Address) { s.k.DeleteAddressMapping(s.ctx, seiAddr, acc) } - s.SubBalance(acc, s.GetBalance(acc)) + s.SubBalance(acc, s.GetBalance(acc), tracing.BalanceDecreaseSelfdestruct) // clear account state s.clearAccountState(acc) diff --git a/x/evm/state/state_test.go b/x/evm/state/state_test.go index a49c8d018..84f1a9c36 100644 --- a/x/evm/state/state_test.go +++ b/x/evm/state/state_test.go @@ -6,6 +6,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/tracing" testkeeper "github.com/sei-protocol/sei-chain/testutil/keeper" "github.com/sei-protocol/sei-chain/x/evm/state" "github.com/sei-protocol/sei-chain/x/evm/types" @@ -19,7 +20,7 @@ func TestState(t *testing.T) { statedb.CreateAccount(evmAddr) require.True(t, statedb.Created(evmAddr)) require.False(t, statedb.HasSelfDestructed(evmAddr)) - statedb.AddBalance(evmAddr, big.NewInt(10)) + statedb.AddBalance(evmAddr, big.NewInt(10), tracing.BalanceChangeUnspecified) k.BankKeeper().MintCoins(statedb.Ctx(), types.ModuleName, sdk.NewCoins(sdk.NewCoin(k.GetBaseDenom(ctx), sdk.NewInt(10)))) key := common.BytesToHash([]byte("abc")) val := common.BytesToHash([]byte("def")) @@ -60,7 +61,7 @@ func TestCreate(t *testing.T) { tval := common.BytesToHash([]byte("mno")) statedb.SetState(evmAddr, key, val) statedb.SetTransientState(evmAddr, tkey, tval) - statedb.AddBalance(evmAddr, big.NewInt(10000000000000)) + statedb.AddBalance(evmAddr, big.NewInt(10000000000000), tracing.BalanceChangeUnspecified) // recreate an account should clear its state, but keep its balance and transient state statedb.CreateAccount(evmAddr) require.Equal(t, tval, statedb.GetTransientState(evmAddr, tkey)) diff --git a/x/evm/state/statedb.go b/x/evm/state/statedb.go index b8db5c770..dcf818781 100644 --- a/x/evm/state/statedb.go +++ b/x/evm/state/statedb.go @@ -5,6 +5,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/tracing" ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/sei-protocol/sei-chain/utils" @@ -29,6 +30,8 @@ type DBImpl struct { k EVMKeeper simulation bool + + logger *tracing.Hooks } func NewDBImpl(ctx sdk.Context, k EVMKeeper, simulation bool) *DBImpl { @@ -44,6 +47,10 @@ func NewDBImpl(ctx sdk.Context, k EVMKeeper, simulation bool) *DBImpl { return s } +func (s *DBImpl) SetLogger(logger *tracing.Hooks) { + s.logger = logger +} + func (s *DBImpl) SetEVM(evm *vm.EVM) { s.ctx = types.SetCtxEVM(s.ctx, evm) s.snapshottedCtxs = utils.Map(s.snapshottedCtxs, func(ctx sdk.Context) sdk.Context { return types.SetCtxEVM(ctx, evm) }) @@ -105,6 +112,7 @@ func (s *DBImpl) Copy() vm.StateDB { coinbaseAddress: s.coinbaseAddress, simulation: s.simulation, err: s.err, + logger: s.logger, } }