Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Misc EVM fixes #2884

Merged
merged 7 commits into from
Sep 21, 2023
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
10 changes: 9 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ compile-solidity:
build-cli:
cd tools/wasp-cli && go mod tidy && go build -ldflags $(BUILD_LD_FLAGS) -o ../../

# use like: make build-tool TOOL=./tools/dbinspector
build-tool:
$(BUILD_CMD) $(TOOL)
Comment on lines +33 to +35
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion:

Suggested change
# use like: make build-tool TOOL=./tools/dbinspector
build-tool:
$(BUILD_CMD) $(TOOL)
# use like: make build-tool TOOL=dbinspector
build-tool:
$(BUILD_CMD) ./tools/$(TOOL)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Idk, I like both options. I'll leave it as it is because the evmemulator is in tools/evm/evmemulator and it would be awkwardish to say TOOL=evm/evmemulator 🤷‍♂️


build-full: build-cli
$(BUILD_CMD) ./...

Expand All @@ -53,6 +57,10 @@ test-short:
install-cli:
cd tools/wasp-cli && go mod tidy && go install -ldflags $(BUILD_LD_FLAGS)

# use like: make install-tool TOOL=./tools/dbinspector
install-tool:
$(INSTALL_CMD) $(TOOL)

install-full: install-cli
$(INSTALL_CMD) ./...

Expand Down Expand Up @@ -103,4 +111,4 @@ deps-versions:
awk -F ":" '{ print $$1 }' | \
{ read from ; read to; awk -v s="$$from" -v e="$$to" 'NR>1*s&&NR<1*e' packages/testutil/privtangle/privtangle.go; }

.PHONY: all wasm compile-solidity build-cli build-full build build-lint test-full test test-short install-cli install-full install lint gofumpt-list docker-build deps-versions
.PHONY: all wasm compile-solidity build-tool install-tool build-cli build-full build build-lint test-full test test-short install-cli install-full install lint gofumpt-list docker-build deps-versions
4 changes: 2 additions & 2 deletions components/logger/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package logger

import (
"github.com/iotaledger/hive.go/app"
"github.com/iotaledger/wasp/packages/evm/evmlogger"
)

func init() {
Expand All @@ -14,7 +15,6 @@ func init() {
var Component *app.Component

func configure() error {
initGoEthLogger(Component.App().NewLogger("go-ethereum"))

evmlogger.Init(Component.App().NewLogger("go-ethereum"))
return nil
}
2 changes: 1 addition & 1 deletion packages/chain/mempool/typed_pool_by_nonce.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func (p *TypedPoolByNonce[V]) Add(request V) {
}

defer func() {
p.log.Debugf("ADD %v as key=%v, senderAccount: ", request.ID(), ref, account)
p.log.Debugf("ADD %v as key=%v, senderAccount: %s", request.ID(), ref, account)
p.sizeMetric(p.refLUT.Size())
p.waitReq.MarkAvailable(request)
}()
Expand Down
54 changes: 33 additions & 21 deletions packages/chainutil/evmestimategas.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
"github.com/iotaledger/wasp/packages/vm/gas"
)

var evmErrorsRegex = regexp.MustCompile("out of gas|intrinsic gas too low|(execution reverted$)")
var evmErrOutOfGasRegex = regexp.MustCompile("out of gas|intrinsic gas too low")

// EVMEstimateGas executes the given request and discards the resulting chain state. It is useful
// for estimating gas.
Expand All @@ -39,29 +39,14 @@ func EVMEstimateGas(ch chain.ChainCore, aliasOutput *isc.AliasOutputWithID, call

// Create a helper to check if a gas allowance results in an executable transaction
blockTime := time.Now()
executable := func(gas uint64) (failed bool, used uint64, err error) {
executable := func(gas uint64) (failed bool, result *vm.RequestResult, err error) {
call.Gas = gas
iscReq := isc.NewEVMOffLedgerCallRequest(ch.ID(), call)
res, err := runISCRequest(ch, aliasOutput, blockTime, iscReq, true)
if err != nil {
return true, 0, err
return true, nil, err
}
if res.Receipt.Error != nil {
if res.Receipt.Error.ErrorCode == vm.ErrGasBudgetExceeded.Code() {
// out of gas when charging ISC gas
return true, 0, nil
}
vmerr, resolvingErr := ResolveError(ch, res.Receipt.Error)
if resolvingErr != nil {
panic(fmt.Errorf("error resolving vmerror %w", resolvingErr))
}
if evmErrorsRegex.Match([]byte(vmerr.Error())) {
// increase gas
return true, 0, nil
}
return true, 0, vmerr
}
return false, res.Receipt.GasBurned, nil
return res.Receipt.Error != nil, res, nil
}

// Execute the binary search and hone in on an executable gas limit
Expand All @@ -83,13 +68,15 @@ func EVMEstimateGas(ch chain.ChainCore, aliasOutput *isc.AliasOutputWithID, call

var failed bool
var err error
failed, lastUsed, err = executable(mid)
failed, res, err := executable(mid)
if err != nil {
return 0, err
}
if failed {
lastUsed = 0
lo = mid
} else {
lastUsed = res.Receipt.GasBurned
hi = mid
if lastUsed == mid {
// if used gas == gas limit, then use this as the estimation.
Expand All @@ -103,11 +90,20 @@ func EVMEstimateGas(ch chain.ChainCore, aliasOutput *isc.AliasOutputWithID, call

// Reject the transaction as invalid if it still fails at the highest allowance
if hi == gasCap {
failed, _, err := executable(hi)
failed, res, err := executable(hi)
if err != nil {
return 0, err
}
if failed {
if res.Receipt.Error != nil {
isOutOfGas, resolvedErr, err := resolveError(ch, res.Receipt.Error)
if err != nil {
return 0, err
}
if resolvedErr != nil && !isOutOfGas {
return 0, resolvedErr
}
}
if hi == maximumPossibleGas {
return 0, fmt.Errorf("request might require more gas than it is allowed by the VM (%d), or will never succeed", gasCap)
}
Expand All @@ -122,3 +118,19 @@ func getMaxCallGasLimit(ch chain.ChainCore) uint64 {
info := governance.NewStateAccess(mustLatestState(ch)).ChainInfo(ch.ID())
return gas.EVMCallGasLimit(info.GasLimits, &info.GasFeePolicy.EVMGasRatio)
}

func resolveError(ch chain.ChainCore, receiptError *isc.UnresolvedVMError) (isOutOfGas bool, resolved *isc.VMError, err error) {
if receiptError.ErrorCode == vm.ErrGasBudgetExceeded.Code() {
// out of gas when charging ISC gas
return true, nil, nil
}
vmerr, resolvingErr := ResolveError(ch, receiptError)
if resolvingErr != nil {
return true, nil, fmt.Errorf("error resolving vmerror: %w", resolvingErr)
}
if evmErrOutOfGasRegex.Match([]byte(vmerr.Error())) {
// increase gas
return true, vmerr, nil
}
return false, vmerr, nil
}
15 changes: 10 additions & 5 deletions components/logger/evm.go → packages/evm/evmlogger/evmlogger.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
package logger
package evmlogger

import (
"strings"

"github.com/ethereum/go-ethereum/log"

"github.com/iotaledger/hive.go/logger"
)

func initGoEthLogger(waspLogger *logger.Logger) {
var format = log.TerminalFormat(false)

func Init(waspLogger *logger.Logger) {
log.Root().SetHandler(log.FuncHandler(func(r *log.Record) error {
s := strings.TrimRight(string(format.Format(r)), "\n")
switch r.Lvl {
case log.LvlCrit, log.LvlError:
waspLogger.Errorf("[%s] %s", r.Lvl.AlignedString(), r.Msg)
waspLogger.Error(s)
case log.LvlTrace, log.LvlDebug:
waspLogger.Debugf("[%s] %s", r.Lvl.AlignedString(), r.Msg)
waspLogger.Debug(s)
default:
waspLogger.Infof("[%s] %s", r.Lvl.AlignedString(), r.Msg)
waspLogger.Info(s)
}
return nil
}))
Expand Down
19 changes: 0 additions & 19 deletions packages/evm/evmtest/env.go

This file was deleted.

11 changes: 4 additions & 7 deletions packages/evm/jsonrpc/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import (

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"golang.org/x/exp/slices"
)

type AccountManager struct {
accounts map[common.Address]*ecdsa.PrivateKey
addrs []common.Address
}

func NewAccountManager(accounts []*ecdsa.PrivateKey) *AccountManager {
Expand All @@ -30,18 +32,13 @@ func (a *AccountManager) Add(keyPair *ecdsa.PrivateKey) {
return
}
a.accounts[addr] = keyPair
a.addrs = append(a.addrs, addr)
}

func (a *AccountManager) Get(addr common.Address) *ecdsa.PrivateKey {
return a.accounts[addr]
}

func (a *AccountManager) Addresses() []common.Address {
ret := make([]common.Address, len(a.accounts))
i := 0
for addr := range a.accounts {
ret[i] = addr
i++
}
return ret
return slices.Clone(a.addrs)
}
2 changes: 2 additions & 0 deletions packages/evm/jsonrpc/chainbackend.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,6 @@ type ChainBackend interface {
ISCStateByBlockIndex(blockIndex uint32) (state.State, error)
ISCStateByTrieRoot(trieRoot trie.Hash) (state.State, error)
BaseToken() *parameters.BaseToken
TakeSnapshot() (int, error)
RevertToSnapshot(int) error
}
2 changes: 0 additions & 2 deletions packages/evm/jsonrpc/jsonrpctest/jsonrpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ type soloTestEnv struct {
}

func newSoloTestEnv(t testing.TB) *soloTestEnv {
evmtest.InitGoEthLogger(t)

var log *logger.Logger
if _, ok := t.(*testing.B); ok {
log = testlogger.NewSilentLogger(t.Name(), true)
Expand Down
1 change: 1 addition & 0 deletions packages/evm/jsonrpc/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func NewServer(
{"eth", NewEthService(evmChain, accountManager, metrics)},
{"debug", NewDebugService(evmChain, metrics)},
{"txpool", NewTxPoolService()},
{"evm", NewEVMService(evmChain)},
} {
err := rpcsrv.RegisterName(srv.namespace, srv.service)
if err != nil {
Expand Down
19 changes: 19 additions & 0 deletions packages/evm/jsonrpc/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -684,3 +684,22 @@ func (d *DebugService) TraceTransaction(txHash common.Hash, config *tracers.Trac
},
)
}

type EVMService struct {
evmChain *EVMChain
}

func NewEVMService(evmChain *EVMChain) *EVMService {
return &EVMService{
evmChain: evmChain,
}
}

func (e *EVMService) Snapshot() (hexutil.Uint, error) {
n, err := e.evmChain.backend.TakeSnapshot()
return hexutil.Uint(n), err
}

func (e *EVMService) Revert(snapshot hexutil.Uint) error {
return e.evmChain.backend.RevertToSnapshot(int(snapshot))
}
11 changes: 11 additions & 0 deletions packages/evm/jsonrpc/waspevmbackend.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package jsonrpc

import (
"errors"
"fmt"
"time"

Expand Down Expand Up @@ -141,3 +142,13 @@ func (b *WaspEVMBackend) ISCChainID() *isc.ChainID {
chID := b.chain.ID()
return &chID
}

var errNotImplemented = errors.New("method not implemented")

func (*WaspEVMBackend) RevertToSnapshot(int) error {
return errNotImplemented
}

func (*WaspEVMBackend) TakeSnapshot() (int, error) {
return 0, errNotImplemented
}
4 changes: 2 additions & 2 deletions packages/metrics/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func NewChainMetricsProvider() *ChainMetricsProvider {
StateManager: newChainStateManagerMetricsProvider(),
Snapshots: newChainSnapshotsMetricsProvider(),
NodeConn: newChainNodeConnMetricsProvider(),
WebAPI: newChainWebAPIMetricsProvider(),
WebAPI: NewChainWebAPIMetricsProvider(),
State: newChainStateMetricsProvider(),
}
}
Expand Down Expand Up @@ -91,7 +91,7 @@ func (m *ChainMetricsProvider) GetChainMetrics(chainID isc.ChainID) *ChainMetric
StateManager: m.StateManager.createForChain(chainID),
Snapshots: m.Snapshots.createForChain(chainID),
NodeConn: m.NodeConn.createForChain(chainID),
WebAPI: m.WebAPI.createForChain(chainID),
WebAPI: m.WebAPI.CreateForChain(chainID),
State: m.State.createForChain(chainID),
}
m.chains[chainID] = cm
Expand Down
4 changes: 2 additions & 2 deletions packages/metrics/chain_webapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type ChainWebAPIMetricsProvider struct {
evmRPCCalls *prometheus.HistogramVec
}

func newChainWebAPIMetricsProvider() *ChainWebAPIMetricsProvider {
func NewChainWebAPIMetricsProvider() *ChainWebAPIMetricsProvider {
return &ChainWebAPIMetricsProvider{
requests: prometheus.NewHistogramVec(prometheus.HistogramOpts{
Namespace: "iota_wasp",
Expand All @@ -40,7 +40,7 @@ func (p *ChainWebAPIMetricsProvider) register(reg prometheus.Registerer) {
)
}

func (p *ChainWebAPIMetricsProvider) createForChain(chainID isc.ChainID) *ChainWebAPIMetrics {
func (p *ChainWebAPIMetricsProvider) CreateForChain(chainID isc.ChainID) *ChainWebAPIMetrics {
return newChainWebAPIMetrics(p, chainID)
}

Expand Down
4 changes: 2 additions & 2 deletions packages/parameters/l1parameters.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ var (
l1ParamsMutex = &sync.RWMutex{}
l1Params *L1Params

l1ForTesting = &L1Params{
L1ForTesting = &L1Params{
// There are no limits on how big from a size perspective an essence can be, so it is just derived from 32KB - Message fields without payload = max size of the payload
MaxPayloadSize: MaxPayloadSize,
Protocol: &iotago.ProtocolParameters{
Expand Down Expand Up @@ -80,7 +80,7 @@ func L1() *L1Params {
func L1NoLock() *L1Params {
if l1Params == nil {
if isTestContext() {
l1Params = l1ForTesting
l1Params = L1ForTesting
} else if l1ParamsLazyInit != nil {
l1ParamsLazyInit()
}
Expand Down
12 changes: 12 additions & 0 deletions packages/solo/context.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package solo

import "github.com/stretchr/testify/require"

type Context interface {
require.TestingT
Name() string
Cleanup(func())
Helper()
Logf(string, ...any)
Fatalf(string, ...any)
}
Loading
Loading