Skip to content

Commit

Permalink
Merge branch 'master' into ramtin/evm-delay-block-commit
Browse files Browse the repository at this point in the history
  • Loading branch information
ramtinms committed Jul 16, 2024
2 parents 5135a13 + 9e7fe2c commit 926230a
Show file tree
Hide file tree
Showing 28 changed files with 758 additions and 402 deletions.
8 changes: 4 additions & 4 deletions fvm/evm/debug/tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ const (

type EVMTracer interface {
WithBlockID(identifier flow.Identifier)
TxTracer() tracers.Tracer
TxTracer() *tracers.Tracer
Collect(txID gethCommon.Hash)
}

var _ EVMTracer = &CallTracer{}

type CallTracer struct {
logger zerolog.Logger
tracer tracers.Tracer
tracer *tracers.Tracer
uploader Uploader
blockID flow.Identifier
}
Expand All @@ -48,7 +48,7 @@ func NewEVMCallTracer(uploader Uploader, logger zerolog.Logger) (*CallTracer, er
}, nil
}

func (t *CallTracer) TxTracer() tracers.Tracer {
func (t *CallTracer) TxTracer() *tracers.Tracer {
return t.tracer
}

Expand Down Expand Up @@ -102,7 +102,7 @@ var _ EVMTracer = &nopTracer{}

type nopTracer struct{}

func (n nopTracer) TxTracer() tracers.Tracer {
func (n nopTracer) TxTracer() *tracers.Tracer {
return nil
}

Expand Down
15 changes: 10 additions & 5 deletions fvm/evm/debug/tracer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"testing"

gethCommon "github.com/onflow/go-ethereum/common"
gethTypes "github.com/onflow/go-ethereum/core/types"
"github.com/onflow/go-ethereum/core/vm"
"github.com/rs/zerolog"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -34,15 +35,19 @@ func Test_CallTracer(t *testing.T) {

from := gethCommon.HexToAddress("0x01")
to := gethCommon.HexToAddress("0x02")
nonce := uint64(10)
data := []byte{0x02, 0x04}
amount := big.NewInt(1)

tr := tracer.TxTracer()
require.NotNil(t, tr)

tr.CaptureStart(nil, from, to, true, []byte{0x01, 0x02}, 10, big.NewInt(1))
tr.CaptureTxStart(100)
tr.CaptureEnter(vm.ADD, from, to, []byte{0x02, 0x04}, 20, big.NewInt(2))
tr.CaptureTxEnd(500)
tr.CaptureEnd([]byte{0x02}, 200, nil)
tr.OnEnter(0, 0, from, to, []byte{0x01, 0x02}, 10, big.NewInt(1))
tx := gethTypes.NewTransaction(nonce, to, amount, 100, big.NewInt(10), data)
tr.OnTxStart(nil, tx, from)
tr.OnEnter(1, byte(vm.ADD), from, to, data, 20, big.NewInt(2))
tr.OnTxEnd(&gethTypes.Receipt{}, nil)
tr.OnExit(0, []byte{0x02}, 200, nil, false)

res, err = tr.GetResult()
require.NoError(t, err)
Expand Down
16 changes: 13 additions & 3 deletions fvm/evm/debug/uploader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"cloud.google.com/go/storage"
gethCommon "github.com/onflow/go-ethereum/common"
gethTypes "github.com/onflow/go-ethereum/core/types"
"github.com/onflow/go-ethereum/core/vm"
"github.com/rs/zerolog"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -64,9 +65,18 @@ func Test_TracerUploaderIntegration(t *testing.T) {
tr := tracer.TxTracer()
require.NotNil(t, tr)

tr.CaptureTxStart(1000)
tr.CaptureEnter(vm.ADD, gethCommon.HexToAddress("0x01"), gethCommon.HexToAddress("0x02"), []byte{0x01}, 10, big.NewInt(2))
tr.CaptureTxEnd(500)
from := gethCommon.HexToAddress("0x01")
to := gethCommon.HexToAddress("0x02")
nonce := uint64(10)
gas := uint64(100)
gasPrice := big.NewInt(1)
value := big.NewInt(2)
input := []byte{0x01}
tx := gethTypes.NewTransaction(nonce, to, value, gas, gasPrice, input)

tr.OnTxStart(nil, tx, from)
tr.OnEnter(0, byte(vm.ADD), from, to, input, gas, value)
tr.OnTxEnd(&gethTypes.Receipt{}, nil)

traces, err := tr.GetResult()
require.NoError(t, err)
Expand Down
7 changes: 5 additions & 2 deletions fvm/evm/emulator/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ var DefaultChainConfig = &gethParams.ChainConfig{
ShanghaiTime: &zero, // already on Shanghai
CancunTime: &zero, // already on Cancun
PragueTime: nil, // not on Prague
VerkleTime: nil, // not on Verkle
}

// Default config supports the dynamic fee structure (EIP-1559)
Expand Down Expand Up @@ -213,9 +214,11 @@ func WithRandom(rand *gethCommon.Hash) Option {
}

// WithTransactionTracer sets a transaction tracer
func WithTransactionTracer(tracer tracers.Tracer) Option {
func WithTransactionTracer(tracer *tracers.Tracer) Option {
return func(c *Config) *Config {
c.EVMConfig.Tracer = tracer
if tracer != nil {
c.EVMConfig.Tracer = tracer.Hooks
}
return c
}
}
98 changes: 79 additions & 19 deletions fvm/evm/emulator/emulator.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import (
"errors"
"math/big"

"github.com/holiman/uint256"
"github.com/onflow/atree"
"github.com/onflow/go-ethereum/common"
gethCommon "github.com/onflow/go-ethereum/common"
gethCore "github.com/onflow/go-ethereum/core"
"github.com/onflow/go-ethereum/core/tracing"
gethTypes "github.com/onflow/go-ethereum/core/types"
gethVM "github.com/onflow/go-ethereum/core/vm"
gethCrypto "github.com/onflow/go-ethereum/crypto"
Expand Down Expand Up @@ -76,7 +79,8 @@ type ReadOnlyBlockView struct {

// BalanceOf returns the balance of the given address
func (bv *ReadOnlyBlockView) BalanceOf(address types.Address) (*big.Int, error) {
return bv.state.GetBalance(address.ToCommon()), nil
bal := bv.state.GetBalance(address.ToCommon())
return bal.ToBig(), nil
}

// NonceOf returns the nonce of the given address
Expand Down Expand Up @@ -124,8 +128,6 @@ func (bl *BlockView) DirectCall(call *types.DirectCall) (*types.Result, error) {
}
fallthrough
default:
// TODO: when we support mutiple calls per block, we need
// to update the value zero here for tx index
return proc.runDirect(call.Message(), txHash, 0)
}
}
Expand Down Expand Up @@ -160,7 +162,7 @@ func (bl *BlockView) RunTransaction(
if err != nil {
return nil, err
}
// all commmit errors (StateDB errors) has to be returned
// all commit errors (StateDB errors) has to be returned
if err := proc.commit(true); err != nil {
return nil, err
}
Expand Down Expand Up @@ -197,7 +199,7 @@ func (bl *BlockView) BatchRunTransactions(txs []*gethTypes.Transaction) ([]*type
if err != nil {
return nil, err
}
// all commmit errors (StateDB errors) has to be returned
// all commit errors (StateDB errors) has to be returned
if err := proc.commit(false); err != nil {
return nil, err
}
Expand Down Expand Up @@ -322,6 +324,11 @@ func (proc *procedure) mintTo(
return nil, types.ErrInvalidBalance
}

value, overflow := uint256.FromBig(call.Value)
if overflow {
return nil, types.ErrInvalidBalance
}

bridge := call.From.ToCommon()

// create bridge account if not exist
Expand All @@ -330,7 +337,7 @@ func (proc *procedure) mintTo(
}

// add balance to the bridge account before transfer
proc.state.AddBalance(bridge, call.Value)
proc.state.AddBalance(bridge, value, tracing.BalanceIncreaseWithdrawal)

msg := call.Message()
proc.evm.TxContext.Origin = msg.From
Expand Down Expand Up @@ -361,6 +368,11 @@ func (proc *procedure) withdrawFrom(
return nil, types.ErrInvalidBalance
}

value, overflow := uint256.FromBig(call.Value)
if overflow {
return nil, types.ErrInvalidBalance
}

bridge := call.To.ToCommon()

// create bridge account if not exist
Expand All @@ -383,7 +395,7 @@ func (proc *procedure) withdrawFrom(
}

// now deduct the balance from the bridge
proc.state.SubBalance(bridge, call.Value)
proc.state.SubBalance(bridge, value, tracing.BalanceIncreaseWithdrawal)
// all commmit errors (StateDB errors) has to be returned
return res, proc.commit(true)
}
Expand All @@ -407,16 +419,25 @@ func (proc *procedure) deployAt(
return nil, types.ErrInvalidBalance
}

castedValue, overflow := uint256.FromBig(value)
if overflow {
return nil, types.ErrInvalidBalance
}

res := &types.Result{
TxType: types.DirectCallTxType,
TxHash: txHash,
}

addr := to.ToCommon()
if proc.evm.Config.Tracer != nil {
proc.captureTraceBegin(0, gethVM.CREATE2, caller.ToCommon(), to.ToCommon(), data, gasLimit, value)
defer proc.captureTraceEnd(0, gasLimit, res.ReturnedData, res.Receipt(0), res.VMError)
}

addr := to.ToCommon()
// precheck 1 - check balance of the source
if value.Sign() != 0 &&
!proc.evm.Context.CanTransfer(proc.state, caller.ToCommon(), value) {
!proc.evm.Context.CanTransfer(proc.state, caller.ToCommon(), castedValue) {
res.SetValidationError(gethCore.ErrInsufficientFundsForTransfer)
return res, nil
}
Expand Down Expand Up @@ -445,26 +466,18 @@ func (proc *procedure) deployAt(
proc.state,
caller.ToCommon(),
addr,
value,
uint256.MustFromBig(value),
)
}

if tracer := proc.evm.Config.Tracer; tracer != nil {
tracer.CaptureStart(proc.evm, caller.ToCommon(), to.ToCommon(), true, data, gasLimit, value)

defer func() {
tracer.CaptureEnd(res.ReturnedData, res.GasConsumed, res.VMError)
}()
}

// run code through interpreter
// this would check for errors and computes the final bytes to be stored under account
var err error
inter := gethVM.NewEVMInterpreter(proc.evm)
contract := gethVM.NewContract(
gethVM.AccountRef(caller.ToCommon()),
gethVM.AccountRef(addr),
value,
castedValue,
gasLimit)

contract.SetCallCode(&addr, gethCrypto.Keccak256Hash(data), data)
Expand Down Expand Up @@ -629,6 +642,53 @@ func (proc *procedure) capturePrecompiledCalls() ([]byte, error) {
return apc.Encode()
}

func (proc *procedure) captureTraceBegin(
depth int,
typ gethVM.OpCode,
from common.Address,
to common.Address,
input []byte,
startGas uint64,
value *big.Int) {
tracer := proc.evm.Config.Tracer
if tracer.OnTxStart != nil {
tracer.OnTxStart(nil, gethTypes.NewTransaction(0, to, value, startGas, nil, input), from)
}
if tracer.OnEnter != nil {
tracer.OnEnter(depth, byte(typ), from, to, input, startGas, value)
}
if tracer.OnGasChange != nil {
tracer.OnGasChange(0, startGas, tracing.GasChangeCallInitialBalance)
}
}

func (proc *procedure) captureTraceEnd(
depth int,
startGas uint64,
ret []byte,
receipt *gethTypes.Receipt,
err error,
) {
tracer := proc.evm.Config.Tracer
leftOverGas := startGas - receipt.GasUsed
if leftOverGas != 0 && tracer.OnGasChange != nil {
tracer.OnGasChange(leftOverGas, 0, tracing.GasChangeCallLeftOverReturned)
}
var reverted bool
if err != nil {
reverted = true
}
if errors.Is(err, gethVM.ErrCodeStoreOutOfGas) {
reverted = false
}
if tracer.OnExit != nil {
tracer.OnExit(depth, ret, startGas-leftOverGas, gethVM.VMErrorFromErr(err), reverted)
}
if tracer.OnTxEnd != nil {
tracer.OnTxEnd(receipt, err)
}
}

func AddOne64th(n uint64) uint64 {
// NOTE: Go's integer division floors, but that is desirable here
return n + (n / 64)
Expand Down
Loading

0 comments on commit 926230a

Please sign in to comment.