diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go
index bdfddfff06f6..ae57ed31d607 100644
--- a/consensus/beacon/consensus.go
+++ b/consensus/beacon/consensus.go
@@ -365,9 +365,9 @@ func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.
// FinalizeAndAssemble implements consensus.Engine, setting the final state and
// assembling the block.
-func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error) {
+func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, statedb vm.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error) {
if !beacon.IsPoSHeader(header) {
- return beacon.ethone.FinalizeAndAssemble(chain, header, state, body, receipts)
+ return beacon.ethone.FinalizeAndAssemble(chain, header, statedb, body, receipts)
}
shanghai := chain.Config().IsShanghai(header.Number, header.Time)
if shanghai {
@@ -381,10 +381,10 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
}
}
// Finalize and assemble the block.
- beacon.Finalize(chain, header, state, body)
+ beacon.Finalize(chain, header, statedb, body)
// Assign the final state root to header.
- header.Root = state.IntermediateRoot(true)
+ header.Root = statedb.IntermediateRoot(true)
// Assemble the final block.
block := types.NewBlock(header, body, receipts, trie.NewStackTrie(nil))
@@ -392,19 +392,19 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
// Create the block witness and attach to block.
// This step needs to happen as late as possible to catch all access events.
if chain.Config().IsVerkle(header.Number, header.Time) {
- keys := state.AccessEvents().Keys()
+ keys := statedb.AccessEvents().Keys()
// Open the pre-tree to prove the pre-state against
parent := chain.GetHeaderByNumber(header.Number.Uint64() - 1)
if parent == nil {
return nil, fmt.Errorf("nil parent header for block %d", header.Number)
}
- preTrie, err := state.Database().OpenTrie(parent.Root)
+ preTrie, err := statedb.(*state.StateDB).Database().OpenTrie(parent.Root)
if err != nil {
return nil, fmt.Errorf("error opening pre-state tree root: %w", err)
}
vktPreTrie, okpre := preTrie.(*trie.VerkleTrie)
- vktPostTrie, okpost := state.GetTrie().(*trie.VerkleTrie)
+ vktPostTrie, okpost := statedb.(*state.StateDB).GetTrie().(*trie.VerkleTrie)
// The witness is only attached iff both parent and current block are
// using verkle tree.
diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go
index d31efd744510..5acf76dec6d8 100644
--- a/consensus/clique/clique.go
+++ b/consensus/clique/clique.go
@@ -33,7 +33,6 @@ import (
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
- "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
@@ -580,7 +579,7 @@ func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Heade
// FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set,
// nor block rewards given, and returns the final block.
-func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error) {
+func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error) {
if len(body.Withdrawals) > 0 {
return nil, errors.New("clique does not support withdrawals")
}
diff --git a/consensus/consensus.go b/consensus/consensus.go
index c59b9a474474..9c53920ea06f 100644
--- a/consensus/consensus.go
+++ b/consensus/consensus.go
@@ -21,7 +21,6 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
@@ -93,7 +92,7 @@ type Engine interface {
//
// Note: The block header and state database might be updated to reflect any
// consensus rules that happen at finalization (e.g. block rewards).
- FinalizeAndAssemble(chain ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error)
+ FinalizeAndAssemble(chain ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error)
// Seal generates a new sealing request for the given input block and pushes
// the result into the given channel.
diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go
index 4f92f1282b9e..4368e57892de 100644
--- a/consensus/ethash/consensus.go
+++ b/consensus/ethash/consensus.go
@@ -27,7 +27,6 @@ import (
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
- "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
@@ -511,7 +510,7 @@ func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.
// FinalizeAndAssemble implements consensus.Engine, accumulating the block and
// uncle rewards, setting the final state and assembling the block.
-func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error) {
+func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body, receipts []*types.Receipt) (*types.Block, error) {
if len(body.Withdrawals) > 0 {
return nil, errors.New("ethash does not support withdrawals")
}
diff --git a/core/chain_makers.go b/core/chain_makers.go
index 8d09390b72d8..d067eaf2f2ec 100644
--- a/core/chain_makers.go
+++ b/core/chain_makers.go
@@ -43,7 +43,7 @@ type BlockGen struct {
cm *chainMaker
parent *types.Block
header *types.Header
- statedb *state.StateDB
+ statedb vm.StateDB
gasPool *GasPool
txs []*types.Transaction
@@ -124,7 +124,7 @@ func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transacti
}
// Merge the tx-local access event into the "block-local" one, in order to collect
// all values, so that the witness can be built.
- if b.statedb.GetTrie().IsVerkle() {
+ if b.statedb.(*state.StateDB).GetTrie().IsVerkle() {
b.statedb.AccessEvents().Merge(evm.AccessEvents)
}
b.txs = append(b.txs, tx)
diff --git a/core/sender_cacher.go b/core/sender_cacher.go
index 73bd5c85f200..83ba1d788e2b 100644
--- a/core/sender_cacher.go
+++ b/core/sender_cacher.go
@@ -17,7 +17,6 @@
package core
import (
- "runtime"
"sync"
"github.com/ethereum/go-ethereum/core/types"
@@ -25,7 +24,7 @@ import (
// senderCacherOnce is used to ensure that the SenderCacher is initialized only once.
var senderCacherOnce = sync.OnceValue(func() *txSenderCacher {
- return newTxSenderCacher(runtime.NumCPU())
+ return newTxSenderCacher(0)
})
// SenderCacher returns the singleton instance of SenderCacher, initializing it if called for the first time.
diff --git a/core/state/statedb.go b/core/state/statedb.go
index efafdc1aa224..b586c7c09a55 100644
--- a/core/state/statedb.go
+++ b/core/state/statedb.go
@@ -32,6 +32,7 @@ import (
"github.com/ethereum/go-ethereum/core/stateless"
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
@@ -126,7 +127,7 @@ type StateDB struct {
// Per-transaction access list
accessList *accessList
- accessEvents *AccessEvents
+ accessEvents *vm.AccessEvents
// Transient storage
transientStorage transientStorage
@@ -182,7 +183,7 @@ func New(root common.Hash, db Database) (*StateDB, error) {
transientStorage: newTransientStorage(),
}
if db.TrieDB().IsVerkle() {
- sdb.accessEvents = NewAccessEvents(db.PointCache())
+ sdb.accessEvents = vm.NewAccessEvents(db.PointCache())
}
return sdb, nil
}
@@ -649,7 +650,7 @@ func (s *StateDB) CreateContract(addr common.Address) {
// Copy creates a deep, independent copy of the state.
// Snapshots of the copied state cannot be applied to the copy.
-func (s *StateDB) Copy() *StateDB {
+func (s *StateDB) Copy() vm.StateDB {
// Copy all the basic fields, initialize the memory ones
reader, _ := s.db.Reader(s.originalRoot) // impossible to fail
state := &StateDB{
@@ -1432,6 +1433,8 @@ func (s *StateDB) Witness() *stateless.Witness {
return s.witness
}
-func (s *StateDB) AccessEvents() *AccessEvents {
+func (s *StateDB) AccessEvents() *vm.AccessEvents {
return s.accessEvents
}
+
+func (s *StateDB) SetEVM(evm *vm.EVM) {}
diff --git a/core/state/statedb_hooked.go b/core/state/statedb_hooked.go
index a2fdfe9a217a..1fdf15c086b7 100644
--- a/core/state/statedb_hooked.go
+++ b/core/state/statedb_hooked.go
@@ -23,146 +23,147 @@ import (
"github.com/ethereum/go-ethereum/core/stateless"
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie/utils"
"github.com/holiman/uint256"
)
-// hookedStateDB represents a statedb which emits calls to tracing-hooks
+// HookedStateDB represents a statedb which emits calls to tracing-hooks
// on state operations.
-type hookedStateDB struct {
- inner *StateDB
+type HookedStateDB struct {
+ vm.StateDB
hooks *tracing.Hooks
}
// NewHookedState wraps the given stateDb with the given hooks
-func NewHookedState(stateDb *StateDB, hooks *tracing.Hooks) *hookedStateDB {
- s := &hookedStateDB{stateDb, hooks}
+func NewHookedState(stateDb vm.StateDB, hooks *tracing.Hooks) *HookedStateDB {
+ s := &HookedStateDB{stateDb, hooks}
if s.hooks == nil {
s.hooks = new(tracing.Hooks)
}
return s
}
-func (s *hookedStateDB) CreateAccount(addr common.Address) {
- s.inner.CreateAccount(addr)
+func (s *HookedStateDB) CreateAccount(addr common.Address) {
+ s.StateDB.CreateAccount(addr)
}
-func (s *hookedStateDB) CreateContract(addr common.Address) {
- s.inner.CreateContract(addr)
+func (s *HookedStateDB) CreateContract(addr common.Address) {
+ s.StateDB.CreateContract(addr)
}
-func (s *hookedStateDB) GetBalance(addr common.Address) *uint256.Int {
- return s.inner.GetBalance(addr)
+func (s *HookedStateDB) GetBalance(addr common.Address) *uint256.Int {
+ return s.StateDB.GetBalance(addr)
}
-func (s *hookedStateDB) GetNonce(addr common.Address) uint64 {
- return s.inner.GetNonce(addr)
+func (s *HookedStateDB) GetNonce(addr common.Address) uint64 {
+ return s.StateDB.GetNonce(addr)
}
-func (s *hookedStateDB) GetCodeHash(addr common.Address) common.Hash {
- return s.inner.GetCodeHash(addr)
+func (s *HookedStateDB) GetCodeHash(addr common.Address) common.Hash {
+ return s.StateDB.GetCodeHash(addr)
}
-func (s *hookedStateDB) GetCode(addr common.Address) []byte {
- return s.inner.GetCode(addr)
+func (s *HookedStateDB) GetCode(addr common.Address) []byte {
+ return s.StateDB.GetCode(addr)
}
-func (s *hookedStateDB) GetCodeSize(addr common.Address) int {
- return s.inner.GetCodeSize(addr)
+func (s *HookedStateDB) GetCodeSize(addr common.Address) int {
+ return s.StateDB.GetCodeSize(addr)
}
-func (s *hookedStateDB) AddRefund(u uint64) {
- s.inner.AddRefund(u)
+func (s *HookedStateDB) AddRefund(u uint64) {
+ s.StateDB.AddRefund(u)
}
-func (s *hookedStateDB) SubRefund(u uint64) {
- s.inner.SubRefund(u)
+func (s *HookedStateDB) SubRefund(u uint64) {
+ s.StateDB.SubRefund(u)
}
-func (s *hookedStateDB) GetRefund() uint64 {
- return s.inner.GetRefund()
+func (s *HookedStateDB) GetRefund() uint64 {
+ return s.StateDB.GetRefund()
}
-func (s *hookedStateDB) GetCommittedState(addr common.Address, hash common.Hash) common.Hash {
- return s.inner.GetCommittedState(addr, hash)
+func (s *HookedStateDB) GetCommittedState(addr common.Address, hash common.Hash) common.Hash {
+ return s.StateDB.GetCommittedState(addr, hash)
}
-func (s *hookedStateDB) GetState(addr common.Address, hash common.Hash) common.Hash {
- return s.inner.GetState(addr, hash)
+func (s *HookedStateDB) GetState(addr common.Address, hash common.Hash) common.Hash {
+ return s.StateDB.GetState(addr, hash)
}
-func (s *hookedStateDB) GetStorageRoot(addr common.Address) common.Hash {
- return s.inner.GetStorageRoot(addr)
+func (s *HookedStateDB) GetStorageRoot(addr common.Address) common.Hash {
+ return s.StateDB.GetStorageRoot(addr)
}
-func (s *hookedStateDB) GetTransientState(addr common.Address, key common.Hash) common.Hash {
- return s.inner.GetTransientState(addr, key)
+func (s *HookedStateDB) GetTransientState(addr common.Address, key common.Hash) common.Hash {
+ return s.StateDB.GetTransientState(addr, key)
}
-func (s *hookedStateDB) SetTransientState(addr common.Address, key, value common.Hash) {
- s.inner.SetTransientState(addr, key, value)
+func (s *HookedStateDB) SetTransientState(addr common.Address, key, value common.Hash) {
+ s.StateDB.SetTransientState(addr, key, value)
}
-func (s *hookedStateDB) HasSelfDestructed(addr common.Address) bool {
- return s.inner.HasSelfDestructed(addr)
+func (s *HookedStateDB) HasSelfDestructed(addr common.Address) bool {
+ return s.StateDB.HasSelfDestructed(addr)
}
-func (s *hookedStateDB) Exist(addr common.Address) bool {
- return s.inner.Exist(addr)
+func (s *HookedStateDB) Exist(addr common.Address) bool {
+ return s.StateDB.Exist(addr)
}
-func (s *hookedStateDB) Empty(addr common.Address) bool {
- return s.inner.Empty(addr)
+func (s *HookedStateDB) Empty(addr common.Address) bool {
+ return s.StateDB.Empty(addr)
}
-func (s *hookedStateDB) AddressInAccessList(addr common.Address) bool {
- return s.inner.AddressInAccessList(addr)
+func (s *HookedStateDB) AddressInAccessList(addr common.Address) bool {
+ return s.StateDB.AddressInAccessList(addr)
}
-func (s *hookedStateDB) SlotInAccessList(addr common.Address, slot common.Hash) (addressOk bool, slotOk bool) {
- return s.inner.SlotInAccessList(addr, slot)
+func (s *HookedStateDB) SlotInAccessList(addr common.Address, slot common.Hash) (addressOk bool, slotOk bool) {
+ return s.StateDB.SlotInAccessList(addr, slot)
}
-func (s *hookedStateDB) AddAddressToAccessList(addr common.Address) {
- s.inner.AddAddressToAccessList(addr)
+func (s *HookedStateDB) AddAddressToAccessList(addr common.Address) {
+ s.StateDB.AddAddressToAccessList(addr)
}
-func (s *hookedStateDB) AddSlotToAccessList(addr common.Address, slot common.Hash) {
- s.inner.AddSlotToAccessList(addr, slot)
+func (s *HookedStateDB) AddSlotToAccessList(addr common.Address, slot common.Hash) {
+ s.StateDB.AddSlotToAccessList(addr, slot)
}
-func (s *hookedStateDB) PointCache() *utils.PointCache {
- return s.inner.PointCache()
+func (s *HookedStateDB) PointCache() *utils.PointCache {
+ return s.StateDB.PointCache()
}
-func (s *hookedStateDB) Prepare(rules params.Rules, sender, coinbase common.Address, dest *common.Address, precompiles []common.Address, txAccesses types.AccessList) {
- s.inner.Prepare(rules, sender, coinbase, dest, precompiles, txAccesses)
+func (s *HookedStateDB) Prepare(rules params.Rules, sender, coinbase common.Address, dest *common.Address, precompiles []common.Address, txAccesses types.AccessList) {
+ s.StateDB.Prepare(rules, sender, coinbase, dest, precompiles, txAccesses)
}
-func (s *hookedStateDB) RevertToSnapshot(i int) {
- s.inner.RevertToSnapshot(i)
+func (s *HookedStateDB) RevertToSnapshot(i int) {
+ s.StateDB.RevertToSnapshot(i)
}
-func (s *hookedStateDB) Snapshot() int {
- return s.inner.Snapshot()
+func (s *HookedStateDB) Snapshot() int {
+ return s.StateDB.Snapshot()
}
-func (s *hookedStateDB) AddPreimage(hash common.Hash, bytes []byte) {
- s.inner.AddPreimage(hash, bytes)
+func (s *HookedStateDB) AddPreimage(hash common.Hash, bytes []byte) {
+ s.StateDB.AddPreimage(hash, bytes)
}
-func (s *hookedStateDB) Witness() *stateless.Witness {
- return s.inner.Witness()
+func (s *HookedStateDB) Witness() *stateless.Witness {
+ return s.StateDB.Witness()
}
-func (s *hookedStateDB) AccessEvents() *AccessEvents {
- return s.inner.AccessEvents()
+func (s *HookedStateDB) AccessEvents() *vm.AccessEvents {
+ return s.StateDB.AccessEvents()
}
-func (s *hookedStateDB) SubBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) uint256.Int {
- prev := s.inner.SubBalance(addr, amount, reason)
+func (s *HookedStateDB) SubBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) uint256.Int {
+ prev := s.StateDB.SubBalance(addr, amount, reason)
if s.hooks.OnBalanceChange != nil && !amount.IsZero() {
newBalance := new(uint256.Int).Sub(&prev, amount)
s.hooks.OnBalanceChange(addr, prev.ToBig(), newBalance.ToBig(), reason)
@@ -170,8 +171,8 @@ func (s *hookedStateDB) SubBalance(addr common.Address, amount *uint256.Int, rea
return prev
}
-func (s *hookedStateDB) AddBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) uint256.Int {
- prev := s.inner.AddBalance(addr, amount, reason)
+func (s *HookedStateDB) AddBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) uint256.Int {
+ prev := s.StateDB.AddBalance(addr, amount, reason)
if s.hooks.OnBalanceChange != nil && !amount.IsZero() {
newBalance := new(uint256.Int).Add(&prev, amount)
s.hooks.OnBalanceChange(addr, prev.ToBig(), newBalance.ToBig(), reason)
@@ -179,9 +180,9 @@ func (s *hookedStateDB) AddBalance(addr common.Address, amount *uint256.Int, rea
return prev
}
-func (s *hookedStateDB) SetNonce(address common.Address, nonce uint64, reason tracing.NonceChangeReason) {
- prev := s.inner.GetNonce(address)
- s.inner.SetNonce(address, nonce, reason)
+func (s *HookedStateDB) SetNonce(address common.Address, nonce uint64, reason tracing.NonceChangeReason) {
+ prev := s.StateDB.GetNonce(address)
+ s.StateDB.SetNonce(address, nonce, reason)
if s.hooks.OnNonceChangeV2 != nil {
s.hooks.OnNonceChangeV2(address, prev, nonce, reason)
} else if s.hooks.OnNonceChange != nil {
@@ -189,8 +190,8 @@ func (s *hookedStateDB) SetNonce(address common.Address, nonce uint64, reason tr
}
}
-func (s *hookedStateDB) SetCode(address common.Address, code []byte) []byte {
- prev := s.inner.SetCode(address, code)
+func (s *HookedStateDB) SetCode(address common.Address, code []byte) []byte {
+ prev := s.StateDB.SetCode(address, code)
if s.hooks.OnCodeChange != nil {
prevHash := types.EmptyCodeHash
if len(prev) != 0 {
@@ -201,24 +202,24 @@ func (s *hookedStateDB) SetCode(address common.Address, code []byte) []byte {
return prev
}
-func (s *hookedStateDB) SetState(address common.Address, key common.Hash, value common.Hash) common.Hash {
- prev := s.inner.SetState(address, key, value)
+func (s *HookedStateDB) SetState(address common.Address, key common.Hash, value common.Hash) common.Hash {
+ prev := s.StateDB.SetState(address, key, value)
if s.hooks.OnStorageChange != nil && prev != value {
s.hooks.OnStorageChange(address, key, prev, value)
}
return prev
}
-func (s *hookedStateDB) SelfDestruct(address common.Address) uint256.Int {
+func (s *HookedStateDB) SelfDestruct(address common.Address) uint256.Int {
var prevCode []byte
var prevCodeHash common.Hash
if s.hooks.OnCodeChange != nil {
- prevCode = s.inner.GetCode(address)
- prevCodeHash = s.inner.GetCodeHash(address)
+ prevCode = s.StateDB.GetCode(address)
+ prevCodeHash = s.StateDB.GetCodeHash(address)
}
- prev := s.inner.SelfDestruct(address)
+ prev := s.StateDB.SelfDestruct(address)
if s.hooks.OnBalanceChange != nil && !prev.IsZero() {
s.hooks.OnBalanceChange(address, prev.ToBig(), new(big.Int), tracing.BalanceDecreaseSelfdestruct)
@@ -231,16 +232,16 @@ func (s *hookedStateDB) SelfDestruct(address common.Address) uint256.Int {
return prev
}
-func (s *hookedStateDB) SelfDestruct6780(address common.Address) (uint256.Int, bool) {
+func (s *HookedStateDB) SelfDestruct6780(address common.Address) (uint256.Int, bool) {
var prevCode []byte
var prevCodeHash common.Hash
if s.hooks.OnCodeChange != nil {
- prevCodeHash = s.inner.GetCodeHash(address)
- prevCode = s.inner.GetCode(address)
+ prevCodeHash = s.StateDB.GetCodeHash(address)
+ prevCode = s.StateDB.GetCode(address)
}
- prev, changed := s.inner.SelfDestruct6780(address)
+ prev, changed := s.StateDB.SelfDestruct6780(address)
if s.hooks.OnBalanceChange != nil && changed && !prev.IsZero() {
s.hooks.OnBalanceChange(address, prev.ToBig(), new(big.Int), tracing.BalanceDecreaseSelfdestruct)
@@ -253,21 +254,25 @@ func (s *hookedStateDB) SelfDestruct6780(address common.Address) (uint256.Int, b
return prev, changed
}
-func (s *hookedStateDB) AddLog(log *types.Log) {
+func (s *HookedStateDB) AddLog(log *types.Log) {
// The inner will modify the log (add fields), so invoke that first
- s.inner.AddLog(log)
+ s.StateDB.AddLog(log)
if s.hooks.OnLog != nil {
s.hooks.OnLog(log)
}
}
-func (s *hookedStateDB) Finalise(deleteEmptyObjects bool) {
- defer s.inner.Finalise(deleteEmptyObjects)
+func (s *HookedStateDB) Finalise(deleteEmptyObjects bool) {
+ defer s.StateDB.Finalise(deleteEmptyObjects)
if s.hooks.OnBalanceChange == nil {
return
}
- for addr := range s.inner.journal.dirties {
- obj := s.inner.stateObjects[addr]
+ statedb, ok := s.StateDB.(*StateDB)
+ if !ok {
+ return
+ }
+ for addr := range statedb.journal.dirties {
+ obj := statedb.stateObjects[addr]
if obj != nil && obj.selfDestructed {
// If ether was sent to account post-selfdestruct it is burnt.
if bal := obj.Balance(); bal.Sign() != 0 {
diff --git a/core/state/statedb_test.go b/core/state/statedb_test.go
index e740c64faa3a..aedc2f3e576d 100644
--- a/core/state/statedb_test.go
+++ b/core/state/statedb_test.go
@@ -184,16 +184,16 @@ func TestCopy(t *testing.T) {
// modify all in memory
for i := byte(0); i < 255; i++ {
origObj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i}))
- copyObj := copy.getOrNewStateObject(common.BytesToAddress([]byte{i}))
- ccopyObj := ccopy.getOrNewStateObject(common.BytesToAddress([]byte{i}))
+ copyObj := copy.(*StateDB).getOrNewStateObject(common.BytesToAddress([]byte{i}))
+ ccopyObj := ccopy.(*StateDB).getOrNewStateObject(common.BytesToAddress([]byte{i}))
origObj.AddBalance(uint256.NewInt(2 * uint64(i)))
copyObj.AddBalance(uint256.NewInt(3 * uint64(i)))
ccopyObj.AddBalance(uint256.NewInt(4 * uint64(i)))
orig.updateStateObject(origObj)
- copy.updateStateObject(copyObj)
- ccopy.updateStateObject(copyObj)
+ copy.(*StateDB).updateStateObject(copyObj)
+ ccopy.(*StateDB).updateStateObject(copyObj)
}
// Finalise the changes on all concurrently
@@ -205,15 +205,15 @@ func TestCopy(t *testing.T) {
var wg sync.WaitGroup
wg.Add(3)
go finalise(&wg, orig)
- go finalise(&wg, copy)
- go finalise(&wg, ccopy)
+ go finalise(&wg, copy.(*StateDB))
+ go finalise(&wg, ccopy.(*StateDB))
wg.Wait()
// Verify that the three states have been updated independently
for i := byte(0); i < 255; i++ {
origObj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i}))
- copyObj := copy.getOrNewStateObject(common.BytesToAddress([]byte{i}))
- ccopyObj := ccopy.getOrNewStateObject(common.BytesToAddress([]byte{i}))
+ copyObj := copy.(*StateDB).getOrNewStateObject(common.BytesToAddress([]byte{i}))
+ ccopyObj := ccopy.(*StateDB).getOrNewStateObject(common.BytesToAddress([]byte{i}))
if want := uint256.NewInt(3 * uint64(i)); origObj.Balance().Cmp(want) != 0 {
t.Errorf("orig obj %d: balance mismatch: have %v, want %v", i, origObj.Balance(), want)
@@ -288,13 +288,13 @@ func TestCopyObjectState(t *testing.T) {
}
orig.Finalise(true)
cpy := orig.Copy()
- for _, op := range cpy.mutations {
+ for _, op := range cpy.(*StateDB).mutations {
if have, want := op.applied, false; have != want {
t.Fatalf("Error in test itself, the 'done' flag should not be set before Commit, have %v want %v", have, want)
}
}
orig.Commit(0, true, false)
- for _, op := range cpy.mutations {
+ for _, op := range cpy.(*StateDB).mutations {
if have, want := op.applied, false; have != want {
t.Fatalf("Error: original state affected copy, have %v want %v", have, want)
}
@@ -537,7 +537,7 @@ func (test *snapshotTest) run() bool {
for i, action := range test.actions {
if len(test.snapshots) > sindex && i == test.snapshots[sindex] {
snapshotRevs[sindex] = state.Snapshot()
- checkstates[sindex] = state.Copy()
+ checkstates[sindex] = state.Copy().(*StateDB)
sindex++
}
action.fn(action, state)
@@ -1186,7 +1186,7 @@ func TestStateDBAccessList(t *testing.T) {
}
// Check the copy
// Make a copy
- state = stateCopy1
+ state = stateCopy1.(*StateDB)
verifyAddrs("aa", "bb")
verifySlots("bb", "01", "02")
if got, exp := len(state.accessList.addresses), 2; got != exp {
diff --git a/core/state_processor.go b/core/state_processor.go
index 902ff582e8ba..d813c9f800c8 100644
--- a/core/state_processor.go
+++ b/core/state_processor.go
@@ -54,7 +54,7 @@ func NewStateProcessor(config *params.ChainConfig, chain *HeaderChain) *StatePro
// Process returns the receipts and logs accumulated during the process and
// returns the amount of gas that was used in the process. If any of the
// transactions failed to execute due to insufficient gas it will return an error.
-func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (*ProcessResult, error) {
+func (p *StateProcessor) Process(block *types.Block, statedb vm.StateDB, cfg vm.Config) (*ProcessResult, error) {
var (
receipts types.Receipts
usedGas = new(uint64)
@@ -132,7 +132,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
// ApplyTransactionWithEVM attempts to apply a transaction to the given state database
// and uses the input parameters for its environment similar to ApplyTransaction. However,
// this method takes an already created EVM instance as input.
-func ApplyTransactionWithEVM(msg *Message, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (receipt *types.Receipt, err error) {
+func ApplyTransactionWithEVM(msg *Message, gp *GasPool, statedb vm.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (receipt *types.Receipt, err error) {
if hooks := evm.Config.Tracer; hooks != nil {
if hooks.OnTxStart != nil {
hooks.OnTxStart(evm.GetVMContext(), tx, msg.From)
@@ -157,7 +157,7 @@ func ApplyTransactionWithEVM(msg *Message, gp *GasPool, statedb *state.StateDB,
// Merge the tx-local access event into the "block-local" one, in order to collect
// all values, so that the witness can be built.
- if statedb.GetTrie().IsVerkle() {
+ if s, ok := statedb.(*state.StateDB); ok && s.GetTrie().IsVerkle() {
statedb.AccessEvents().Merge(evm.AccessEvents)
}
@@ -165,7 +165,7 @@ func ApplyTransactionWithEVM(msg *Message, gp *GasPool, statedb *state.StateDB,
}
// MakeReceipt generates the receipt object for a transaction given its execution result.
-func MakeReceipt(evm *vm.EVM, result *ExecutionResult, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas uint64, root []byte) *types.Receipt {
+func MakeReceipt(evm *vm.EVM, result *ExecutionResult, statedb vm.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas uint64, root []byte) *types.Receipt {
// Create a new receipt for the transaction, storing the intermediate root and gas used
// by the tx.
receipt := &types.Receipt{Type: tx.Type(), PostState: root, CumulativeGasUsed: usedGas}
@@ -200,7 +200,7 @@ func MakeReceipt(evm *vm.EVM, result *ExecutionResult, statedb *state.StateDB, b
// and uses the input parameters for its environment. It returns the receipt
// for the transaction, gas used and an error if the transaction failed,
// indicating the block was invalid.
-func ApplyTransaction(evm *vm.EVM, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64) (*types.Receipt, error) {
+func ApplyTransaction(evm *vm.EVM, gp *GasPool, statedb vm.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64) (*types.Receipt, error) {
msg, err := TransactionToMessage(tx, types.MakeSigner(evm.ChainConfig(), header.Number, header.Time), header.BaseFee)
if err != nil {
return nil, err
diff --git a/core/state_transition.go b/core/state_transition.go
index e7edd76ced9e..31b94c33a55f 100644
--- a/core/state_transition.go
+++ b/core/state_transition.go
@@ -99,7 +99,7 @@ func IntrinsicGas(data []byte, accessList types.AccessList, authList []types.Set
gas += z * params.TxDataZeroGas
if isContractCreation && isEIP3860 {
- lenWords := toWordSize(dataLen)
+ lenWords := ToWordSize(dataLen)
if (math.MaxUint64-gas)/params.InitCodeWordGas < lenWords {
return 0, ErrGasUintOverflow
}
@@ -131,8 +131,8 @@ func FloorDataGas(data []byte) (uint64, error) {
return params.TxGas + tokens*params.TxCostFloorPerToken, nil
}
-// toWordSize returns the ceiled word size required for init code payment calculation.
-func toWordSize(size uint64) uint64 {
+// ToWordSize returns the ceiled word size required for init code payment calculation.
+func ToWordSize(size uint64) uint64 {
if size > math.MaxUint64-31 {
return math.MaxUint64/32 + 1
}
@@ -205,10 +205,10 @@ func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.In
// state and would never be accepted within a block.
func ApplyMessage(evm *vm.EVM, msg *Message, gp *GasPool) (*ExecutionResult, error) {
evm.SetTxContext(NewEVMTxContext(msg))
- return newStateTransition(evm, msg, gp).execute()
+ return NewStateTransition(evm, msg, gp, false).Execute()
}
-// stateTransition represents a state transition.
+// StateTransition represents a state transition.
//
// == The State Transitioning Model
//
@@ -230,34 +230,36 @@ func ApplyMessage(evm *vm.EVM, msg *Message, gp *GasPool) (*ExecutionResult, err
//
// 5. Run Script section
// 6. Derive new state root
-type stateTransition struct {
+type StateTransition struct {
gp *GasPool
msg *Message
gasRemaining uint64
initialGas uint64
state vm.StateDB
evm *vm.EVM
+ feeCharged bool
}
-// newStateTransition initialises and returns a new state transition object.
-func newStateTransition(evm *vm.EVM, msg *Message, gp *GasPool) *stateTransition {
- return &stateTransition{
- gp: gp,
- evm: evm,
- msg: msg,
- state: evm.StateDB,
+// NewStateTransition initialises and returns a new state transition object.
+func NewStateTransition(evm *vm.EVM, msg *Message, gp *GasPool, feeCharged bool) *StateTransition {
+ return &StateTransition{
+ gp: gp,
+ evm: evm,
+ msg: msg,
+ state: evm.StateDB,
+ feeCharged: feeCharged,
}
}
// to returns the recipient of the message.
-func (st *stateTransition) to() common.Address {
+func (st *StateTransition) to() common.Address {
if st.msg == nil || st.msg.To == nil /* contract creation */ {
return common.Address{}
}
return *st.msg.To
}
-func (st *stateTransition) buyGas() error {
+func (st *StateTransition) BuyGas() error {
mgval := new(big.Int).SetUint64(st.msg.GasLimit)
mgval.Mul(mgval, st.msg.GasPrice)
balanceCheck := new(big.Int).Set(mgval)
@@ -286,6 +288,12 @@ func (st *stateTransition) buyGas() error {
if have, want := st.state.GetBalance(st.msg.From), balanceCheckU256; have.Cmp(want) < 0 {
return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From.Hex(), have, want)
}
+ mgvalU256, _ := uint256.FromBig(mgval)
+ st.state.SubBalance(st.msg.From, mgvalU256, tracing.BalanceDecreaseGasBuy)
+ return nil
+}
+
+func (st *StateTransition) initGas() error {
if err := st.gp.SubGas(st.msg.GasLimit); err != nil {
return err
}
@@ -296,12 +304,10 @@ func (st *stateTransition) buyGas() error {
st.gasRemaining = st.msg.GasLimit
st.initialGas = st.msg.GasLimit
- mgvalU256, _ := uint256.FromBig(mgval)
- st.state.SubBalance(st.msg.From, mgvalU256, tracing.BalanceDecreaseGasBuy)
return nil
}
-func (st *stateTransition) preCheck() error {
+func (st *StateTransition) StatelessChecks() error {
// Only check transactions that are not fake
msg := st.msg
if !msg.SkipNonceChecks {
@@ -392,7 +398,19 @@ func (st *stateTransition) preCheck() error {
return fmt.Errorf("%w (sender %v)", ErrEmptyAuthList, msg.From)
}
}
- return st.buyGas()
+ return nil
+}
+
+func (st *StateTransition) preCheck() error {
+ if !st.feeCharged {
+ if err := st.StatelessChecks(); err != nil {
+ return err
+ }
+ if err := st.BuyGas(); err != nil {
+ return err
+ }
+ }
+ return st.initGas()
}
// execute will transition the state by applying the current message and
@@ -405,7 +423,7 @@ func (st *stateTransition) preCheck() error {
//
// However if any consensus issue encountered, return the error directly with
// nil evm execution result.
-func (st *stateTransition) execute() (*ExecutionResult, error) {
+func (st *StateTransition) Execute() (*ExecutionResult, error) {
// First check this message satisfies all consensus rules before
// applying the message. The rules include these clauses
//
@@ -532,7 +550,6 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
effectiveTip = msg.GasTipCap
}
}
- effectiveTipU256, _ := uint256.FromBig(effectiveTip)
if st.evm.Config.NoBaseFee && msg.GasFeeCap.Sign() == 0 && msg.GasTipCap.Sign() == 0 {
// Skip fee payment when NoBaseFee is set and the fee fields
@@ -540,7 +557,9 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
// the coinbase when simulating calls.
} else {
fee := new(uint256.Int).SetUint64(st.gasUsed())
- fee.Mul(fee, effectiveTipU256)
+ // Sei doesn't don't burn the base fee and instead funds the Coinbase address with the base fee
+ totalFeePerGas := new(big.Int).Add(st.evm.Context.BaseFee, effectiveTip)
+ fee.Mul(fee, uint256.MustFromBig(totalFeePerGas))
st.state.AddBalance(st.evm.Context.Coinbase, fee, tracing.BalanceIncreaseRewardTransactionFee)
// add the coinbase to the witness iff the fee is greater than 0
@@ -558,7 +577,7 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
}
// validateAuthorization validates an EIP-7702 authorization against the state.
-func (st *stateTransition) validateAuthorization(auth *types.SetCodeAuthorization) (authority common.Address, err error) {
+func (st *StateTransition) validateAuthorization(auth *types.SetCodeAuthorization) (authority common.Address, err error) {
// Verify chain ID is null or equal to current chain ID.
if !auth.ChainID.IsZero() && auth.ChainID.CmpBig(st.evm.ChainConfig().ChainID) != 0 {
return authority, ErrAuthorizationWrongChainID
@@ -589,7 +608,7 @@ func (st *stateTransition) validateAuthorization(auth *types.SetCodeAuthorizatio
}
// applyAuthorization applies an EIP-7702 code delegation to the state.
-func (st *stateTransition) applyAuthorization(auth *types.SetCodeAuthorization) error {
+func (st *StateTransition) applyAuthorization(auth *types.SetCodeAuthorization) error {
authority, err := st.validateAuthorization(auth)
if err != nil {
return err
@@ -616,7 +635,7 @@ func (st *stateTransition) applyAuthorization(auth *types.SetCodeAuthorization)
}
// calcRefund computes refund counter, capped to a refund quotient.
-func (st *stateTransition) calcRefund() uint64 {
+func (st *StateTransition) calcRefund() uint64 {
var refund uint64
if !st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) {
// Before EIP-3529: refunds were capped to gasUsed / 2
@@ -636,7 +655,7 @@ func (st *stateTransition) calcRefund() uint64 {
// returnGas returns ETH for remaining gas,
// exchanged at the original rate.
-func (st *stateTransition) returnGas() {
+func (st *StateTransition) returnGas() {
remaining := uint256.NewInt(st.gasRemaining)
remaining.Mul(remaining, uint256.MustFromBig(st.msg.GasPrice))
st.state.AddBalance(st.msg.From, remaining, tracing.BalanceIncreaseGasReturn)
@@ -651,11 +670,11 @@ func (st *stateTransition) returnGas() {
}
// gasUsed returns the amount of gas used up by the state transition.
-func (st *stateTransition) gasUsed() uint64 {
+func (st *StateTransition) gasUsed() uint64 {
return st.initialGas - st.gasRemaining
}
// blobGasUsed returns the amount of blob gas used by the message.
-func (st *stateTransition) blobGasUsed() uint64 {
+func (st *StateTransition) blobGasUsed() uint64 {
return uint64(len(st.msg.BlobHashes) * params.BlobTxBlobGasPerBlob)
}
diff --git a/core/txpool/legacypool/noncer.go b/core/txpool/legacypool/noncer.go
index 2c65dd2caea7..f97b54320f72 100644
--- a/core/txpool/legacypool/noncer.go
+++ b/core/txpool/legacypool/noncer.go
@@ -21,13 +21,14 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/vm"
)
// noncer is a tiny virtual state database to manage the executable nonces of
// accounts in the pool, falling back to reading from a real state database if
// an account is unknown.
type noncer struct {
- fallback *state.StateDB
+ fallback vm.StateDB
nonces map[common.Address]uint64
lock sync.Mutex
}
diff --git a/core/types.go b/core/types.go
index bed20802ab51..41997cfda4dc 100644
--- a/core/types.go
+++ b/core/types.go
@@ -48,7 +48,7 @@ type Processor interface {
// Process processes the state changes according to the Ethereum rules by running
// the transaction messages using the statedb and applying any rewards to both
// the processor (coinbase) and any included uncles.
- Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (*ProcessResult, error)
+ Process(block *types.Block, statedb vm.StateDB, cfg vm.Config) (*ProcessResult, error)
}
// ProcessResult contains the values computed by Process.
diff --git a/core/types/block.go b/core/types/block.go
index c3db4d89e820..91e3bba6c7bf 100644
--- a/core/types/block.go
+++ b/core/types/block.go
@@ -204,10 +204,10 @@ type Body struct {
// - We do not copy body data on access because it does not affect the caches, and also
// because it would be too expensive.
type Block struct {
- header *Header
- uncles []*Header
- transactions Transactions
- withdrawals Withdrawals
+ Header_ *Header
+ uncles []*Header
+ Txs Transactions
+ withdrawals Withdrawals
// witness is not an encoded part of the block body.
// It is held in Block in order for easy relaying to the places
@@ -249,24 +249,24 @@ func NewBlock(header *Header, body *Body, receipts []*Receipt, hasher TrieHasher
)
if len(txs) == 0 {
- b.header.TxHash = EmptyTxsHash
+ b.Header_.TxHash = EmptyTxsHash
} else {
- b.header.TxHash = DeriveSha(Transactions(txs), hasher)
- b.transactions = make(Transactions, len(txs))
- copy(b.transactions, txs)
+ b.Header_.TxHash = DeriveSha(Transactions(txs), hasher)
+ b.Txs = make(Transactions, len(txs))
+ copy(b.Txs, txs)
}
if len(receipts) == 0 {
- b.header.ReceiptHash = EmptyReceiptsHash
+ b.Header_.ReceiptHash = EmptyReceiptsHash
} else {
- b.header.ReceiptHash = DeriveSha(Receipts(receipts), hasher)
- b.header.Bloom = CreateBloom(receipts)
+ b.Header_.ReceiptHash = DeriveSha(Receipts(receipts), hasher)
+ b.Header_.Bloom = CreateBloom(receipts)
}
if len(uncles) == 0 {
- b.header.UncleHash = EmptyUncleHash
+ b.Header_.UncleHash = EmptyUncleHash
} else {
- b.header.UncleHash = CalcUncleHash(uncles)
+ b.Header_.UncleHash = CalcUncleHash(uncles)
b.uncles = make([]*Header, len(uncles))
for i := range uncles {
b.uncles[i] = CopyHeader(uncles[i])
@@ -274,13 +274,13 @@ func NewBlock(header *Header, body *Body, receipts []*Receipt, hasher TrieHasher
}
if withdrawals == nil {
- b.header.WithdrawalsHash = nil
+ b.Header_.WithdrawalsHash = nil
} else if len(withdrawals) == 0 {
- b.header.WithdrawalsHash = &EmptyWithdrawalsHash
+ b.Header_.WithdrawalsHash = &EmptyWithdrawalsHash
b.withdrawals = Withdrawals{}
} else {
hash := DeriveSha(Withdrawals(withdrawals), hasher)
- b.header.WithdrawalsHash = &hash
+ b.Header_.WithdrawalsHash = &hash
b.withdrawals = slices.Clone(withdrawals)
}
@@ -333,7 +333,7 @@ func (b *Block) DecodeRLP(s *rlp.Stream) error {
if err := s.Decode(&eb); err != nil {
return err
}
- b.header, b.uncles, b.transactions, b.withdrawals = eb.Header, eb.Uncles, eb.Txs, eb.Withdrawals
+ b.Header_, b.uncles, b.Txs, b.withdrawals = eb.Header, eb.Uncles, eb.Txs, eb.Withdrawals
b.size.Store(rlp.ListSize(size))
return nil
}
@@ -341,8 +341,8 @@ func (b *Block) DecodeRLP(s *rlp.Stream) error {
// EncodeRLP serializes a block as RLP.
func (b *Block) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, &extblock{
- Header: b.header,
- Txs: b.transactions,
+ Header: b.Header_,
+ Txs: b.Txs,
Uncles: b.uncles,
Withdrawals: b.withdrawals,
})
@@ -351,18 +351,18 @@ func (b *Block) EncodeRLP(w io.Writer) error {
// Body returns the non-header content of the block.
// Note the returned data is not an independent copy.
func (b *Block) Body() *Body {
- return &Body{b.transactions, b.uncles, b.withdrawals}
+ return &Body{b.Txs, b.uncles, b.withdrawals}
}
// Accessors for body data. These do not return a copy because the content
// of the body slices does not affect the cached hash/size in block.
func (b *Block) Uncles() []*Header { return b.uncles }
-func (b *Block) Transactions() Transactions { return b.transactions }
+func (b *Block) Transactions() Transactions { return b.Txs }
func (b *Block) Withdrawals() Withdrawals { return b.withdrawals }
func (b *Block) Transaction(hash common.Hash) *Transaction {
- for _, transaction := range b.transactions {
+ for _, transaction := range b.Txs {
if transaction.Hash() == hash {
return transaction
}
@@ -372,53 +372,53 @@ func (b *Block) Transaction(hash common.Hash) *Transaction {
// Header returns the block header (as a copy).
func (b *Block) Header() *Header {
- return CopyHeader(b.header)
+ return CopyHeader(b.Header_)
}
// Header value accessors. These do copy!
-func (b *Block) Number() *big.Int { return new(big.Int).Set(b.header.Number) }
-func (b *Block) GasLimit() uint64 { return b.header.GasLimit }
-func (b *Block) GasUsed() uint64 { return b.header.GasUsed }
-func (b *Block) Difficulty() *big.Int { return new(big.Int).Set(b.header.Difficulty) }
-func (b *Block) Time() uint64 { return b.header.Time }
-
-func (b *Block) NumberU64() uint64 { return b.header.Number.Uint64() }
-func (b *Block) MixDigest() common.Hash { return b.header.MixDigest }
-func (b *Block) Nonce() uint64 { return binary.BigEndian.Uint64(b.header.Nonce[:]) }
-func (b *Block) Bloom() Bloom { return b.header.Bloom }
-func (b *Block) Coinbase() common.Address { return b.header.Coinbase }
-func (b *Block) Root() common.Hash { return b.header.Root }
-func (b *Block) ParentHash() common.Hash { return b.header.ParentHash }
-func (b *Block) TxHash() common.Hash { return b.header.TxHash }
-func (b *Block) ReceiptHash() common.Hash { return b.header.ReceiptHash }
-func (b *Block) UncleHash() common.Hash { return b.header.UncleHash }
-func (b *Block) Extra() []byte { return common.CopyBytes(b.header.Extra) }
+func (b *Block) Number() *big.Int { return new(big.Int).Set(b.Header_.Number) }
+func (b *Block) GasLimit() uint64 { return b.Header_.GasLimit }
+func (b *Block) GasUsed() uint64 { return b.Header_.GasUsed }
+func (b *Block) Difficulty() *big.Int { return new(big.Int).Set(b.Header_.Difficulty) }
+func (b *Block) Time() uint64 { return b.Header_.Time }
+
+func (b *Block) NumberU64() uint64 { return b.Header_.Number.Uint64() }
+func (b *Block) MixDigest() common.Hash { return b.Header_.MixDigest }
+func (b *Block) Nonce() uint64 { return binary.BigEndian.Uint64(b.Header_.Nonce[:]) }
+func (b *Block) Bloom() Bloom { return b.Header_.Bloom }
+func (b *Block) Coinbase() common.Address { return b.Header_.Coinbase }
+func (b *Block) Root() common.Hash { return b.Header_.Root }
+func (b *Block) ParentHash() common.Hash { return b.Header_.ParentHash }
+func (b *Block) TxHash() common.Hash { return b.Header_.TxHash }
+func (b *Block) ReceiptHash() common.Hash { return b.Header_.ReceiptHash }
+func (b *Block) UncleHash() common.Hash { return b.Header_.UncleHash }
+func (b *Block) Extra() []byte { return common.CopyBytes(b.Header_.Extra) }
func (b *Block) BaseFee() *big.Int {
- if b.header.BaseFee == nil {
+ if b.Header_.BaseFee == nil {
return nil
}
- return new(big.Int).Set(b.header.BaseFee)
+ return new(big.Int).Set(b.Header_.BaseFee)
}
-func (b *Block) BeaconRoot() *common.Hash { return b.header.ParentBeaconRoot }
-func (b *Block) RequestsHash() *common.Hash { return b.header.RequestsHash }
+func (b *Block) BeaconRoot() *common.Hash { return b.Header_.ParentBeaconRoot }
+func (b *Block) RequestsHash() *common.Hash { return b.Header_.RequestsHash }
func (b *Block) ExcessBlobGas() *uint64 {
var excessBlobGas *uint64
- if b.header.ExcessBlobGas != nil {
+ if b.Header_.ExcessBlobGas != nil {
excessBlobGas = new(uint64)
- *excessBlobGas = *b.header.ExcessBlobGas
+ *excessBlobGas = *b.Header_.ExcessBlobGas
}
return excessBlobGas
}
func (b *Block) BlobGasUsed() *uint64 {
var blobGasUsed *uint64
- if b.header.BlobGasUsed != nil {
+ if b.Header_.BlobGasUsed != nil {
blobGasUsed = new(uint64)
- *blobGasUsed = *b.header.BlobGasUsed
+ *blobGasUsed = *b.Header_.BlobGasUsed
}
return blobGasUsed
}
@@ -441,7 +441,7 @@ func (b *Block) Size() uint64 {
// SanityCheck can be used to prevent that unbounded fields are
// stuffed with junk data to add processing overhead
func (b *Block) SanityCheck() error {
- return b.header.SanityCheck()
+ return b.Header_.SanityCheck()
}
type writeCounter uint64
@@ -477,18 +477,18 @@ func CalcRequestsHash(requests [][]byte) common.Hash {
// header data is copied, changes to header and to the field values
// will not affect the block.
func NewBlockWithHeader(header *Header) *Block {
- return &Block{header: CopyHeader(header)}
+ return &Block{Header_: CopyHeader(header)}
}
// WithSeal returns a new block with the data from b but the header replaced with
// the sealed one.
func (b *Block) WithSeal(header *Header) *Block {
return &Block{
- header: CopyHeader(header),
- transactions: b.transactions,
- uncles: b.uncles,
- withdrawals: b.withdrawals,
- witness: b.witness,
+ Header_: CopyHeader(header),
+ Txs: b.Txs,
+ uncles: b.uncles,
+ withdrawals: b.withdrawals,
+ witness: b.witness,
}
}
@@ -496,11 +496,11 @@ func (b *Block) WithSeal(header *Header) *Block {
// provided body.
func (b *Block) WithBody(body Body) *Block {
block := &Block{
- header: b.header,
- transactions: slices.Clone(body.Transactions),
- uncles: make([]*Header, len(body.Uncles)),
- withdrawals: slices.Clone(body.Withdrawals),
- witness: b.witness,
+ Header_: b.Header_,
+ Txs: slices.Clone(body.Transactions),
+ uncles: make([]*Header, len(body.Uncles)),
+ withdrawals: slices.Clone(body.Withdrawals),
+ witness: b.witness,
}
for i := range body.Uncles {
block.uncles[i] = CopyHeader(body.Uncles[i])
@@ -510,11 +510,11 @@ func (b *Block) WithBody(body Body) *Block {
func (b *Block) WithWitness(witness *ExecutionWitness) *Block {
return &Block{
- header: b.header,
- transactions: b.transactions,
- uncles: b.uncles,
- withdrawals: b.withdrawals,
- witness: witness,
+ Header_: b.Header_,
+ Txs: b.Txs,
+ uncles: b.uncles,
+ withdrawals: b.withdrawals,
+ witness: witness,
}
}
@@ -524,7 +524,7 @@ func (b *Block) Hash() common.Hash {
if hash := b.hash.Load(); hash != nil {
return *hash
}
- h := b.header.Hash()
+ h := b.Header_.Hash()
b.hash.Store(&h)
return h
}
diff --git a/core/state/access_events.go b/core/vm/access_events.go
similarity index 99%
rename from core/state/access_events.go
rename to core/vm/access_events.go
index b745c383b15c..ac451e561642 100644
--- a/core/state/access_events.go
+++ b/core/vm/access_events.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-package state
+package vm
import (
"maps"
diff --git a/core/state/access_events_test.go b/core/vm/access_events_test.go
similarity index 95%
rename from core/state/access_events_test.go
rename to core/vm/access_events_test.go
index 10630b3181b5..c702db3d9163 100644
--- a/core/state/access_events_test.go
+++ b/core/vm/access_events_test.go
@@ -14,12 +14,13 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-package state
+package vm_test
import (
"testing"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie/utils"
)
@@ -37,7 +38,7 @@ func init() {
}
func TestAccountHeaderGas(t *testing.T) {
- ae := NewAccessEvents(utils.NewPointCache(1024))
+ ae := vm.NewAccessEvents(utils.NewPointCache(1024))
// Check cold read cost
gas := ae.BasicDataGas(testAddr, false)
@@ -92,7 +93,7 @@ func TestAccountHeaderGas(t *testing.T) {
// TestContractCreateInitGas checks that the gas cost of contract creation is correctly
// calculated.
func TestContractCreateInitGas(t *testing.T) {
- ae := NewAccessEvents(utils.NewPointCache(1024))
+ ae := vm.NewAccessEvents(utils.NewPointCache(1024))
var testAddr [20]byte
for i := byte(0); i < 20; i++ {
@@ -115,7 +116,7 @@ func TestContractCreateInitGas(t *testing.T) {
// TestMessageCallGas checks that the gas cost of message calls is correctly
// calculated.
func TestMessageCallGas(t *testing.T) {
- ae := NewAccessEvents(utils.NewPointCache(1024))
+ ae := vm.NewAccessEvents(utils.NewPointCache(1024))
// Check cold read cost, without a value
gas := ae.MessageCallGas(testAddr)
diff --git a/core/vm/analysis_eof.go b/core/vm/analysis_eof.go
index eb78904cfd21..fe4e76021c3a 100644
--- a/core/vm/analysis_eof.go
+++ b/core/vm/analysis_eof.go
@@ -17,17 +17,17 @@
package vm
// eofCodeBitmap collects data locations in code.
-func eofCodeBitmap(code []byte) bitvec {
+func eofCodeBitmap(code []byte) Bitvec {
// The bitmap is 4 bytes longer than necessary, in case the code
// ends with a PUSH32, the algorithm will push zeroes onto the
// bitvector outside the bounds of the actual code.
- bits := make(bitvec, len(code)/8+1+4)
- return eofCodeBitmapInternal(code, bits)
+ bits := make(Bitvec, len(code)/8+1+4)
+ return EofCodeBitmapInternal(code, bits)
}
// eofCodeBitmapInternal is the internal implementation of codeBitmap for EOF
// code validation.
-func eofCodeBitmapInternal(code, bits bitvec) bitvec {
+func EofCodeBitmapInternal(code, bits Bitvec) Bitvec {
for pc := uint64(0); pc < uint64(len(code)); {
var (
op = OpCode(code[pc])
diff --git a/core/vm/analysis_legacy.go b/core/vm/analysis_legacy.go
index 38af9084aca1..7307b9a705fa 100644
--- a/core/vm/analysis_legacy.go
+++ b/core/vm/analysis_legacy.go
@@ -28,13 +28,13 @@ const (
// bitvec is a bit vector which maps bytes in a program.
// An unset bit means the byte is an opcode, a set bit means
// it's data (i.e. argument of PUSHxx).
-type bitvec []byte
+type Bitvec []byte
-func (bits bitvec) set1(pos uint64) {
+func (bits Bitvec) set1(pos uint64) {
bits[pos/8] |= 1 << (pos % 8)
}
-func (bits bitvec) setN(flag uint16, pos uint64) {
+func (bits Bitvec) setN(flag uint16, pos uint64) {
a := flag << (pos % 8)
bits[pos/8] |= byte(a)
if b := byte(a >> 8); b != 0 {
@@ -42,13 +42,13 @@ func (bits bitvec) setN(flag uint16, pos uint64) {
}
}
-func (bits bitvec) set8(pos uint64) {
+func (bits Bitvec) set8(pos uint64) {
a := byte(0xFF << (pos % 8))
bits[pos/8] |= a
bits[pos/8+1] = ^a
}
-func (bits bitvec) set16(pos uint64) {
+func (bits Bitvec) set16(pos uint64) {
a := byte(0xFF << (pos % 8))
bits[pos/8] |= a
bits[pos/8+1] = 0xFF
@@ -56,23 +56,23 @@ func (bits bitvec) set16(pos uint64) {
}
// codeSegment checks if the position is in a code segment.
-func (bits *bitvec) codeSegment(pos uint64) bool {
+func (bits *Bitvec) codeSegment(pos uint64) bool {
return (((*bits)[pos/8] >> (pos % 8)) & 1) == 0
}
// codeBitmap collects data locations in code.
-func codeBitmap(code []byte) bitvec {
+func CodeBitmap(code []byte) Bitvec {
// The bitmap is 4 bytes longer than necessary, in case the code
// ends with a PUSH32, the algorithm will set bits on the
// bitvector outside the bounds of the actual code.
- bits := make(bitvec, len(code)/8+1+4)
- return codeBitmapInternal(code, bits)
+ bits := make(Bitvec, len(code)/8+1+4)
+ return CodeBitmapInternal(code, bits)
}
// codeBitmapInternal is the internal implementation of codeBitmap.
// It exists for the purpose of being able to run benchmark tests
// without dynamic allocations affecting the results.
-func codeBitmapInternal(code, bits bitvec) bitvec {
+func CodeBitmapInternal(code, bits Bitvec) Bitvec {
for pc := uint64(0); pc < uint64(len(code)); {
op := OpCode(code[pc])
pc++
diff --git a/core/vm/analysis_legacy_test.go b/core/vm/analysis_legacy_test.go
index 7f5de225e280..61ba246b7355 100644
--- a/core/vm/analysis_legacy_test.go
+++ b/core/vm/analysis_legacy_test.go
@@ -14,12 +14,13 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-package vm
+package vm_test
import (
"math/bits"
"testing"
+ "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
)
@@ -29,30 +30,30 @@ func TestJumpDestAnalysis(t *testing.T) {
exp byte
which int
}{
- {[]byte{byte(PUSH1), 0x01, 0x01, 0x01}, 0b0000_0010, 0},
- {[]byte{byte(PUSH1), byte(PUSH1), byte(PUSH1), byte(PUSH1)}, 0b0000_1010, 0},
- {[]byte{0x00, byte(PUSH1), 0x00, byte(PUSH1), 0x00, byte(PUSH1), 0x00, byte(PUSH1)}, 0b0101_0100, 0},
- {[]byte{byte(PUSH8), byte(PUSH8), byte(PUSH8), byte(PUSH8), byte(PUSH8), byte(PUSH8), byte(PUSH8), byte(PUSH8), 0x01, 0x01, 0x01}, bits.Reverse8(0x7F), 0},
- {[]byte{byte(PUSH8), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0001, 1},
- {[]byte{0x01, 0x01, 0x01, 0x01, 0x01, byte(PUSH2), byte(PUSH2), byte(PUSH2), 0x01, 0x01, 0x01}, 0b1100_0000, 0},
- {[]byte{0x01, 0x01, 0x01, 0x01, 0x01, byte(PUSH2), 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0000, 1},
- {[]byte{byte(PUSH3), 0x01, 0x01, 0x01, byte(PUSH1), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0010_1110, 0},
- {[]byte{byte(PUSH3), 0x01, 0x01, 0x01, byte(PUSH1), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0000, 1},
- {[]byte{0x01, byte(PUSH8), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b1111_1100, 0},
- {[]byte{0x01, byte(PUSH8), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0011, 1},
- {[]byte{byte(PUSH16), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b1111_1110, 0},
- {[]byte{byte(PUSH16), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b1111_1111, 1},
- {[]byte{byte(PUSH16), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0001, 2},
- {[]byte{byte(PUSH8), 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, byte(PUSH1), 0x01}, 0b1111_1110, 0},
- {[]byte{byte(PUSH8), 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, byte(PUSH1), 0x01}, 0b0000_0101, 1},
- {[]byte{byte(PUSH32)}, 0b1111_1110, 0},
- {[]byte{byte(PUSH32)}, 0b1111_1111, 1},
- {[]byte{byte(PUSH32)}, 0b1111_1111, 2},
- {[]byte{byte(PUSH32)}, 0b1111_1111, 3},
- {[]byte{byte(PUSH32)}, 0b0000_0001, 4},
+ {[]byte{byte(vm.PUSH1), 0x01, 0x01, 0x01}, 0b0000_0010, 0},
+ {[]byte{byte(vm.PUSH1), byte(vm.PUSH1), byte(vm.PUSH1), byte(vm.PUSH1)}, 0b0000_1010, 0},
+ {[]byte{0x00, byte(vm.PUSH1), 0x00, byte(vm.PUSH1), 0x00, byte(vm.PUSH1), 0x00, byte(vm.PUSH1)}, 0b0101_0100, 0},
+ {[]byte{byte(vm.PUSH8), byte(vm.PUSH8), byte(vm.PUSH8), byte(vm.PUSH8), byte(vm.PUSH8), byte(vm.PUSH8), byte(vm.PUSH8), byte(vm.PUSH8), 0x01, 0x01, 0x01}, bits.Reverse8(0x7F), 0},
+ {[]byte{byte(vm.PUSH8), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0001, 1},
+ {[]byte{0x01, 0x01, 0x01, 0x01, 0x01, byte(vm.PUSH2), byte(vm.PUSH2), byte(vm.PUSH2), 0x01, 0x01, 0x01}, 0b1100_0000, 0},
+ {[]byte{0x01, 0x01, 0x01, 0x01, 0x01, byte(vm.PUSH2), 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0000, 1},
+ {[]byte{byte(vm.PUSH3), 0x01, 0x01, 0x01, byte(vm.PUSH1), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0010_1110, 0},
+ {[]byte{byte(vm.PUSH3), 0x01, 0x01, 0x01, byte(vm.PUSH1), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0000, 1},
+ {[]byte{0x01, byte(vm.PUSH8), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b1111_1100, 0},
+ {[]byte{0x01, byte(vm.PUSH8), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0011, 1},
+ {[]byte{byte(vm.PUSH16), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b1111_1110, 0},
+ {[]byte{byte(vm.PUSH16), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b1111_1111, 1},
+ {[]byte{byte(vm.PUSH16), 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 0b0000_0001, 2},
+ {[]byte{byte(vm.PUSH8), 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, byte(vm.PUSH1), 0x01}, 0b1111_1110, 0},
+ {[]byte{byte(vm.PUSH8), 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, byte(vm.PUSH1), 0x01}, 0b0000_0101, 1},
+ {[]byte{byte(vm.PUSH32)}, 0b1111_1110, 0},
+ {[]byte{byte(vm.PUSH32)}, 0b1111_1111, 1},
+ {[]byte{byte(vm.PUSH32)}, 0b1111_1111, 2},
+ {[]byte{byte(vm.PUSH32)}, 0b1111_1111, 3},
+ {[]byte{byte(vm.PUSH32)}, 0b0000_0001, 4},
}
for i, test := range tests {
- ret := codeBitmap(test.code)
+ ret := vm.CodeBitmap(test.code)
if ret[test.which] != test.exp {
t.Fatalf("test %d: expected %x, got %02x", i, test.exp, ret[test.which])
}
@@ -67,7 +68,7 @@ func BenchmarkJumpdestAnalysis_1200k(bench *testing.B) {
bench.SetBytes(analysisCodeSize)
bench.ResetTimer()
for i := 0; i < bench.N; i++ {
- codeBitmap(code)
+ vm.CodeBitmap(code)
}
bench.StopTimer()
}
@@ -83,53 +84,53 @@ func BenchmarkJumpdestHashing_1200k(bench *testing.B) {
}
func BenchmarkJumpdestOpAnalysis(bench *testing.B) {
- var op OpCode
+ var op vm.OpCode
bencher := func(b *testing.B) {
code := make([]byte, analysisCodeSize)
b.SetBytes(analysisCodeSize)
for i := range code {
code[i] = byte(op)
}
- bits := make(bitvec, len(code)/8+1+4)
+ bits := make(vm.Bitvec, len(code)/8+1+4)
b.ResetTimer()
for i := 0; i < b.N; i++ {
clear(bits)
- codeBitmapInternal(code, bits)
+ vm.CodeBitmapInternal(code, bits)
}
}
- for op = PUSH1; op <= PUSH32; op++ {
+ for op = vm.PUSH1; op <= vm.PUSH32; op++ {
bench.Run(op.String(), bencher)
}
- op = JUMPDEST
+ op = vm.JUMPDEST
bench.Run(op.String(), bencher)
- op = STOP
+ op = vm.STOP
bench.Run(op.String(), bencher)
}
func BenchmarkJumpdestOpEOFAnalysis(bench *testing.B) {
- var op OpCode
+ var op vm.OpCode
bencher := func(b *testing.B) {
code := make([]byte, analysisCodeSize)
b.SetBytes(analysisCodeSize)
for i := range code {
code[i] = byte(op)
}
- bits := make(bitvec, len(code)/8+1+4)
+ bits := make(vm.Bitvec, len(code)/8+1+4)
b.ResetTimer()
for i := 0; i < b.N; i++ {
clear(bits)
- eofCodeBitmapInternal(code, bits)
+ vm.EofCodeBitmapInternal(code, bits)
}
}
- for op = PUSH1; op <= PUSH32; op++ {
+ for op = vm.PUSH1; op <= vm.PUSH32; op++ {
bench.Run(op.String(), bencher)
}
- op = JUMPDEST
+ op = vm.JUMPDEST
bench.Run(op.String(), bencher)
- op = STOP
+ op = vm.STOP
bench.Run(op.String(), bencher)
- op = RJUMPV
+ op = vm.RJUMPV
bench.Run(op.String(), bencher)
- op = EOFCREATE
+ op = vm.EOFCREATE
bench.Run(op.String(), bencher)
}
diff --git a/core/vm/common.go b/core/vm/common.go
index 658803b82010..b34f235ce48e 100644
--- a/core/vm/common.go
+++ b/core/vm/common.go
@@ -76,8 +76,8 @@ func getDataAndAdjustedBounds(data []byte, start uint64, size uint64) (codeCopyP
return common.RightPadBytes(data[start:end], int(size)), start, end - start
}
-// toWordSize returns the ceiled word size required for memory expansion.
-func toWordSize(size uint64) uint64 {
+// ToWordSize returns the ceiled word size required for memory expansion.
+func ToWordSize(size uint64) uint64 {
if size > math.MaxUint64-31 {
return math.MaxUint64/32 + 1
}
diff --git a/core/vm/contract.go b/core/vm/contract.go
index 5670244e1714..483f5d249892 100644
--- a/core/vm/contract.go
+++ b/core/vm/contract.go
@@ -49,8 +49,8 @@ type Contract struct {
caller ContractRef
self ContractRef
- jumpdests map[common.Hash]bitvec // Aggregated result of JUMPDEST analysis.
- analysis bitvec // Locally cached result of JUMPDEST analysis
+ jumpdests map[common.Hash]Bitvec // Aggregated result of JUMPDEST analysis.
+ analysis Bitvec // Locally cached result of JUMPDEST analysis
Code []byte
CodeHash common.Hash
@@ -73,7 +73,7 @@ func NewContract(caller ContractRef, object ContractRef, value *uint256.Int, gas
// Reuse JUMPDEST analysis from parent context if available.
c.jumpdests = parent.jumpdests
} else {
- c.jumpdests = make(map[common.Hash]bitvec)
+ c.jumpdests = make(map[common.Hash]Bitvec)
}
// Gas should be a pointer so it can safely be reduced through the run
@@ -115,7 +115,7 @@ func (c *Contract) isCode(udest uint64) bool {
if !exist {
// Do the analysis and save in parent context
// We do not need to store it in c.analysis
- analysis = codeBitmap(c.Code)
+ analysis = CodeBitmap(c.Code)
c.jumpdests[c.CodeHash] = analysis
}
// Also stash it in current contract for faster access
@@ -127,7 +127,7 @@ func (c *Contract) isCode(udest uint64) bool {
// we don't have to recalculate it for every JUMP instruction in the execution
// However, we don't save it within the parent context
if c.analysis == nil {
- c.analysis = codeBitmap(c.Code)
+ c.analysis = CodeBitmap(c.Code)
}
return c.analysis.codeSegment(udest)
}
diff --git a/core/vm/contracts.go b/core/vm/contracts.go
index 06849e65ade3..1f9b828d8952 100644
--- a/core/vm/contracts.go
+++ b/core/vm/contracts.go
@@ -43,8 +43,12 @@ import (
// requires a deterministic gas count based on the input size of the Run method of the
// contract.
type PrecompiledContract interface {
- RequiredGas(input []byte) uint64 // RequiredPrice calculates the contract gas use
- Run(input []byte) ([]byte, error) // Run runs the precompiled contract
+ RequiredGas(input []byte) uint64 // RequiredPrice calculates the contract gas use
+ Run(evm *EVM, sender common.Address, callingContract common.Address, input []byte, value *big.Int, readOnly bool, isFromDelegateCall bool) ([]byte, error) // Run runs the precompiled contract
+}
+
+type DynamicGasPrecompiledContract interface {
+ RunAndCalculateGas(evm *EVM, sender common.Address, callingContract common.Address, input []byte, suppliedGas uint64, value *big.Int, hooks *tracing.Hooks, readOnly bool, isFromDelegateCall bool) (ret []byte, remainingGas uint64, err error) // Run runs the precompiled contract and calculate gas dynamically
}
// PrecompiledContracts contains the precompiled contracts supported at the given fork.
@@ -53,20 +57,20 @@ type PrecompiledContracts map[common.Address]PrecompiledContract
// PrecompiledContractsHomestead contains the default set of pre-compiled Ethereum
// contracts used in the Frontier and Homestead releases.
var PrecompiledContractsHomestead = PrecompiledContracts{
- common.BytesToAddress([]byte{0x1}): &ecrecover{},
- common.BytesToAddress([]byte{0x2}): &sha256hash{},
- common.BytesToAddress([]byte{0x3}): &ripemd160hash{},
- common.BytesToAddress([]byte{0x4}): &dataCopy{},
+ common.BytesToAddress([]byte{0x1}): &Ecrecover{},
+ common.BytesToAddress([]byte{0x2}): &Sha256hash{},
+ common.BytesToAddress([]byte{0x3}): &Ripemd160hash{},
+ common.BytesToAddress([]byte{0x4}): &DataCopy{},
}
// PrecompiledContractsByzantium contains the default set of pre-compiled Ethereum
// contracts used in the Byzantium release.
var PrecompiledContractsByzantium = PrecompiledContracts{
- common.BytesToAddress([]byte{0x1}): &ecrecover{},
- common.BytesToAddress([]byte{0x2}): &sha256hash{},
- common.BytesToAddress([]byte{0x3}): &ripemd160hash{},
- common.BytesToAddress([]byte{0x4}): &dataCopy{},
- common.BytesToAddress([]byte{0x5}): &bigModExp{eip2565: false},
+ common.BytesToAddress([]byte{0x1}): &Ecrecover{},
+ common.BytesToAddress([]byte{0x2}): &Sha256hash{},
+ common.BytesToAddress([]byte{0x3}): &Ripemd160hash{},
+ common.BytesToAddress([]byte{0x4}): &DataCopy{},
+ common.BytesToAddress([]byte{0x5}): &BigModExp{Eip2565: false},
common.BytesToAddress([]byte{0x6}): &bn256AddByzantium{},
common.BytesToAddress([]byte{0x7}): &bn256ScalarMulByzantium{},
common.BytesToAddress([]byte{0x8}): &bn256PairingByzantium{},
@@ -75,66 +79,66 @@ var PrecompiledContractsByzantium = PrecompiledContracts{
// PrecompiledContractsIstanbul contains the default set of pre-compiled Ethereum
// contracts used in the Istanbul release.
var PrecompiledContractsIstanbul = PrecompiledContracts{
- common.BytesToAddress([]byte{0x1}): &ecrecover{},
- common.BytesToAddress([]byte{0x2}): &sha256hash{},
- common.BytesToAddress([]byte{0x3}): &ripemd160hash{},
- common.BytesToAddress([]byte{0x4}): &dataCopy{},
- common.BytesToAddress([]byte{0x5}): &bigModExp{eip2565: false},
- common.BytesToAddress([]byte{0x6}): &bn256AddIstanbul{},
- common.BytesToAddress([]byte{0x7}): &bn256ScalarMulIstanbul{},
- common.BytesToAddress([]byte{0x8}): &bn256PairingIstanbul{},
- common.BytesToAddress([]byte{0x9}): &blake2F{},
+ common.BytesToAddress([]byte{0x1}): &Ecrecover{},
+ common.BytesToAddress([]byte{0x2}): &Sha256hash{},
+ common.BytesToAddress([]byte{0x3}): &Ripemd160hash{},
+ common.BytesToAddress([]byte{0x4}): &DataCopy{},
+ common.BytesToAddress([]byte{0x5}): &BigModExp{Eip2565: false},
+ common.BytesToAddress([]byte{0x6}): &Bn256AddIstanbul{},
+ common.BytesToAddress([]byte{0x7}): &Bn256ScalarMulIstanbul{},
+ common.BytesToAddress([]byte{0x8}): &Bn256PairingIstanbul{},
+ common.BytesToAddress([]byte{0x9}): &Blake2F{},
}
// PrecompiledContractsBerlin contains the default set of pre-compiled Ethereum
// contracts used in the Berlin release.
var PrecompiledContractsBerlin = PrecompiledContracts{
- common.BytesToAddress([]byte{0x1}): &ecrecover{},
- common.BytesToAddress([]byte{0x2}): &sha256hash{},
- common.BytesToAddress([]byte{0x3}): &ripemd160hash{},
- common.BytesToAddress([]byte{0x4}): &dataCopy{},
- common.BytesToAddress([]byte{0x5}): &bigModExp{eip2565: true},
- common.BytesToAddress([]byte{0x6}): &bn256AddIstanbul{},
- common.BytesToAddress([]byte{0x7}): &bn256ScalarMulIstanbul{},
- common.BytesToAddress([]byte{0x8}): &bn256PairingIstanbul{},
- common.BytesToAddress([]byte{0x9}): &blake2F{},
+ common.BytesToAddress([]byte{0x1}): &Ecrecover{},
+ common.BytesToAddress([]byte{0x2}): &Sha256hash{},
+ common.BytesToAddress([]byte{0x3}): &Ripemd160hash{},
+ common.BytesToAddress([]byte{0x4}): &DataCopy{},
+ common.BytesToAddress([]byte{0x5}): &BigModExp{Eip2565: true},
+ common.BytesToAddress([]byte{0x6}): &Bn256AddIstanbul{},
+ common.BytesToAddress([]byte{0x7}): &Bn256ScalarMulIstanbul{},
+ common.BytesToAddress([]byte{0x8}): &Bn256PairingIstanbul{},
+ common.BytesToAddress([]byte{0x9}): &Blake2F{},
}
// PrecompiledContractsCancun contains the default set of pre-compiled Ethereum
// contracts used in the Cancun release.
var PrecompiledContractsCancun = PrecompiledContracts{
- common.BytesToAddress([]byte{0x1}): &ecrecover{},
- common.BytesToAddress([]byte{0x2}): &sha256hash{},
- common.BytesToAddress([]byte{0x3}): &ripemd160hash{},
- common.BytesToAddress([]byte{0x4}): &dataCopy{},
- common.BytesToAddress([]byte{0x5}): &bigModExp{eip2565: true},
- common.BytesToAddress([]byte{0x6}): &bn256AddIstanbul{},
- common.BytesToAddress([]byte{0x7}): &bn256ScalarMulIstanbul{},
- common.BytesToAddress([]byte{0x8}): &bn256PairingIstanbul{},
- common.BytesToAddress([]byte{0x9}): &blake2F{},
- common.BytesToAddress([]byte{0xa}): &kzgPointEvaluation{},
+ common.BytesToAddress([]byte{0x1}): &Ecrecover{},
+ common.BytesToAddress([]byte{0x2}): &Sha256hash{},
+ common.BytesToAddress([]byte{0x3}): &Ripemd160hash{},
+ common.BytesToAddress([]byte{0x4}): &DataCopy{},
+ common.BytesToAddress([]byte{0x5}): &BigModExp{Eip2565: true},
+ common.BytesToAddress([]byte{0x6}): &Bn256AddIstanbul{},
+ common.BytesToAddress([]byte{0x7}): &Bn256ScalarMulIstanbul{},
+ common.BytesToAddress([]byte{0x8}): &Bn256PairingIstanbul{},
+ common.BytesToAddress([]byte{0x9}): &Blake2F{},
+ common.BytesToAddress([]byte{0xa}): &KzgPointEvaluation{},
}
// PrecompiledContractsPrague contains the set of pre-compiled Ethereum
// contracts used in the Prague release.
var PrecompiledContractsPrague = PrecompiledContracts{
- common.BytesToAddress([]byte{0x01}): &ecrecover{},
- common.BytesToAddress([]byte{0x02}): &sha256hash{},
- common.BytesToAddress([]byte{0x03}): &ripemd160hash{},
- common.BytesToAddress([]byte{0x04}): &dataCopy{},
- common.BytesToAddress([]byte{0x05}): &bigModExp{eip2565: true},
- common.BytesToAddress([]byte{0x06}): &bn256AddIstanbul{},
- common.BytesToAddress([]byte{0x07}): &bn256ScalarMulIstanbul{},
- common.BytesToAddress([]byte{0x08}): &bn256PairingIstanbul{},
- common.BytesToAddress([]byte{0x09}): &blake2F{},
- common.BytesToAddress([]byte{0x0a}): &kzgPointEvaluation{},
- common.BytesToAddress([]byte{0x0b}): &bls12381G1Add{},
- common.BytesToAddress([]byte{0x0c}): &bls12381G1MultiExp{},
- common.BytesToAddress([]byte{0x0d}): &bls12381G2Add{},
- common.BytesToAddress([]byte{0x0e}): &bls12381G2MultiExp{},
- common.BytesToAddress([]byte{0x0f}): &bls12381Pairing{},
- common.BytesToAddress([]byte{0x10}): &bls12381MapG1{},
- common.BytesToAddress([]byte{0x11}): &bls12381MapG2{},
+ common.BytesToAddress([]byte{0x01}): &Ecrecover{},
+ common.BytesToAddress([]byte{0x02}): &Sha256hash{},
+ common.BytesToAddress([]byte{0x03}): &Ripemd160hash{},
+ common.BytesToAddress([]byte{0x04}): &DataCopy{},
+ common.BytesToAddress([]byte{0x05}): &BigModExp{Eip2565: true},
+ common.BytesToAddress([]byte{0x06}): &Bn256AddIstanbul{},
+ common.BytesToAddress([]byte{0x07}): &Bn256ScalarMulIstanbul{},
+ common.BytesToAddress([]byte{0x08}): &Bn256PairingIstanbul{},
+ common.BytesToAddress([]byte{0x09}): &Blake2F{},
+ common.BytesToAddress([]byte{0x0a}): &KzgPointEvaluation{},
+ common.BytesToAddress([]byte{0x0b}): &Bls12381G1Add{},
+ common.BytesToAddress([]byte{0x0c}): &Bls12381G1MultiExp{},
+ common.BytesToAddress([]byte{0x0d}): &Bls12381G2Add{},
+ common.BytesToAddress([]byte{0x0e}): &Bls12381G2MultiExp{},
+ common.BytesToAddress([]byte{0x0f}): &Bls12381Pairing{},
+ common.BytesToAddress([]byte{0x10}): &Bls12381MapG1{},
+ common.BytesToAddress([]byte{0x11}): &Bls12381MapG2{},
}
var PrecompiledContractsBLS = PrecompiledContractsPrague
@@ -218,7 +222,12 @@ func ActivePrecompiles(rules params.Rules) []common.Address {
// - the returned bytes,
// - the _remaining_ gas,
// - any error that occurred
-func RunPrecompiledContract(p PrecompiledContract, input []byte, suppliedGas uint64, logger *tracing.Hooks) (ret []byte, remainingGas uint64, err error) {
+func RunPrecompiledContract(p PrecompiledContract, evm *EVM, sender common.Address, callingContract common.Address, input []byte, suppliedGas uint64, value *big.Int, logger *tracing.Hooks, readOnly bool, isFromDelegateCall bool) (ret []byte, remainingGas uint64, err error) {
+ evm.depth++
+ defer func() { evm.depth-- }()
+ if dp, ok := p.(DynamicGasPrecompiledContract); ok {
+ return dp.RunAndCalculateGas(evm, sender, callingContract, input, suppliedGas, value, logger, readOnly, isFromDelegateCall)
+ }
gasCost := p.RequiredGas(input)
if suppliedGas < gasCost {
return nil, 0, ErrOutOfGas
@@ -227,23 +236,23 @@ func RunPrecompiledContract(p PrecompiledContract, input []byte, suppliedGas uin
logger.OnGasChange(suppliedGas, suppliedGas-gasCost, tracing.GasChangeCallPrecompiledContract)
}
suppliedGas -= gasCost
- output, err := p.Run(input)
+ output, err := p.Run(evm, sender, callingContract, input, value, readOnly, isFromDelegateCall)
return output, suppliedGas, err
}
-// ecrecover implemented as a native contract.
-type ecrecover struct{}
+// Ecrecover implemented as a native contract.
+type Ecrecover struct{}
-func (c *ecrecover) RequiredGas(input []byte) uint64 {
+func (c *Ecrecover) RequiredGas(input []byte) uint64 {
return params.EcrecoverGas
}
-func (c *ecrecover) Run(input []byte) ([]byte, error) {
- const ecRecoverInputLength = 128
+func (c *Ecrecover) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) {
+ const EcrecoverInputLength = 128
- input = common.RightPadBytes(input, ecRecoverInputLength)
+ input = common.RightPadBytes(input, EcrecoverInputLength)
// "input" is (hash, v, r, s), each 32 bytes
- // but for ecrecover we want (r, s, v)
+ // but for Ecrecover we want (r, s, v)
r := new(big.Int).SetBytes(input[64:96])
s := new(big.Int).SetBytes(input[96:128])
@@ -270,53 +279,53 @@ func (c *ecrecover) Run(input []byte) ([]byte, error) {
}
// SHA256 implemented as a native contract.
-type sha256hash struct{}
+type Sha256hash struct{}
// RequiredGas returns the gas required to execute the pre-compiled contract.
//
// This method does not require any overflow checking as the input size gas costs
// required for anything significant is so high it's impossible to pay for.
-func (c *sha256hash) RequiredGas(input []byte) uint64 {
+func (c *Sha256hash) RequiredGas(input []byte) uint64 {
return uint64(len(input)+31)/32*params.Sha256PerWordGas + params.Sha256BaseGas
}
-func (c *sha256hash) Run(input []byte) ([]byte, error) {
+func (c *Sha256hash) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) {
h := sha256.Sum256(input)
return h[:], nil
}
// RIPEMD160 implemented as a native contract.
-type ripemd160hash struct{}
+type Ripemd160hash struct{}
// RequiredGas returns the gas required to execute the pre-compiled contract.
//
// This method does not require any overflow checking as the input size gas costs
// required for anything significant is so high it's impossible to pay for.
-func (c *ripemd160hash) RequiredGas(input []byte) uint64 {
+func (c *Ripemd160hash) RequiredGas(input []byte) uint64 {
return uint64(len(input)+31)/32*params.Ripemd160PerWordGas + params.Ripemd160BaseGas
}
-func (c *ripemd160hash) Run(input []byte) ([]byte, error) {
+func (c *Ripemd160hash) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) {
ripemd := ripemd160.New()
ripemd.Write(input)
return common.LeftPadBytes(ripemd.Sum(nil), 32), nil
}
// data copy implemented as a native contract.
-type dataCopy struct{}
+type DataCopy struct{}
// RequiredGas returns the gas required to execute the pre-compiled contract.
//
// This method does not require any overflow checking as the input size gas costs
// required for anything significant is so high it's impossible to pay for.
-func (c *dataCopy) RequiredGas(input []byte) uint64 {
+func (c *DataCopy) RequiredGas(input []byte) uint64 {
return uint64(len(input)+31)/32*params.IdentityPerWordGas + params.IdentityBaseGas
}
-func (c *dataCopy) Run(in []byte) ([]byte, error) {
+func (c *DataCopy) Run(_ *EVM, _ common.Address, _ common.Address, in []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) {
return common.CopyBytes(in), nil
}
-// bigModExp implements a native big integer exponential modular operation.
-type bigModExp struct {
- eip2565 bool
+// BigModExp implements a native big integer exponential modular operation.
+type BigModExp struct {
+ Eip2565 bool
}
var (
@@ -362,7 +371,7 @@ func modexpMultComplexity(x *big.Int) *big.Int {
}
// RequiredGas returns the gas required to execute the pre-compiled contract.
-func (c *bigModExp) RequiredGas(input []byte) uint64 {
+func (c *BigModExp) RequiredGas(input []byte) uint64 {
var (
baseLen = new(big.Int).SetBytes(getData(input, 0, 32))
expLen = new(big.Int).SetBytes(getData(input, 32, 32))
@@ -402,7 +411,7 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 {
} else {
gas.Set(modLen)
}
- if c.eip2565 {
+ if c.Eip2565 {
// EIP-2565 has three changes
// 1. Different multComplexity (inlined here)
// in EIP-2565 (https://eips.ethereum.org/EIPS/eip-2565):
@@ -441,7 +450,7 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 {
return gas.Uint64()
}
-func (c *bigModExp) Run(input []byte) ([]byte, error) {
+func (c *BigModExp) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) {
var (
baseLen = new(big.Int).SetBytes(getData(input, 0, 32)).Uint64()
expLen = new(big.Int).SetBytes(getData(input, 32, 32)).Uint64()
@@ -512,16 +521,16 @@ func runBn256Add(input []byte) ([]byte, error) {
return res.Marshal(), nil
}
-// bn256AddIstanbul implements a native elliptic curve point addition conforming to
+// Bn256AddIstanbul implements a native elliptic curve point addition conforming to
// Istanbul consensus rules.
-type bn256AddIstanbul struct{}
+type Bn256AddIstanbul struct{}
// RequiredGas returns the gas required to execute the pre-compiled contract.
-func (c *bn256AddIstanbul) RequiredGas(input []byte) uint64 {
+func (c *Bn256AddIstanbul) RequiredGas(input []byte) uint64 {
return params.Bn256AddGasIstanbul
}
-func (c *bn256AddIstanbul) Run(input []byte) ([]byte, error) {
+func (c *Bn256AddIstanbul) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) {
return runBn256Add(input)
}
@@ -534,7 +543,7 @@ func (c *bn256AddByzantium) RequiredGas(input []byte) uint64 {
return params.Bn256AddGasByzantium
}
-func (c *bn256AddByzantium) Run(input []byte) ([]byte, error) {
+func (c *bn256AddByzantium) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) {
return runBn256Add(input)
}
@@ -550,16 +559,16 @@ func runBn256ScalarMul(input []byte) ([]byte, error) {
return res.Marshal(), nil
}
-// bn256ScalarMulIstanbul implements a native elliptic curve scalar
+// Bn256ScalarMulIstanbul implements a native elliptic curve scalar
// multiplication conforming to Istanbul consensus rules.
-type bn256ScalarMulIstanbul struct{}
+type Bn256ScalarMulIstanbul struct{}
// RequiredGas returns the gas required to execute the pre-compiled contract.
-func (c *bn256ScalarMulIstanbul) RequiredGas(input []byte) uint64 {
+func (c *Bn256ScalarMulIstanbul) RequiredGas(input []byte) uint64 {
return params.Bn256ScalarMulGasIstanbul
}
-func (c *bn256ScalarMulIstanbul) Run(input []byte) ([]byte, error) {
+func (c *Bn256ScalarMulIstanbul) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) {
return runBn256ScalarMul(input)
}
@@ -572,7 +581,7 @@ func (c *bn256ScalarMulByzantium) RequiredGas(input []byte) uint64 {
return params.Bn256ScalarMulGasByzantium
}
-func (c *bn256ScalarMulByzantium) Run(input []byte) ([]byte, error) {
+func (c *bn256ScalarMulByzantium) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) {
return runBn256ScalarMul(input)
}
@@ -618,16 +627,16 @@ func runBn256Pairing(input []byte) ([]byte, error) {
return false32Byte, nil
}
-// bn256PairingIstanbul implements a pairing pre-compile for the bn256 curve
+// Bn256PairingIstanbul implements a pairing pre-compile for the bn256 curve
// conforming to Istanbul consensus rules.
-type bn256PairingIstanbul struct{}
+type Bn256PairingIstanbul struct{}
// RequiredGas returns the gas required to execute the pre-compiled contract.
-func (c *bn256PairingIstanbul) RequiredGas(input []byte) uint64 {
+func (c *Bn256PairingIstanbul) RequiredGas(input []byte) uint64 {
return params.Bn256PairingBaseGasIstanbul + uint64(len(input)/192)*params.Bn256PairingPerPointGasIstanbul
}
-func (c *bn256PairingIstanbul) Run(input []byte) ([]byte, error) {
+func (c *Bn256PairingIstanbul) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) {
return runBn256Pairing(input)
}
@@ -640,25 +649,25 @@ func (c *bn256PairingByzantium) RequiredGas(input []byte) uint64 {
return params.Bn256PairingBaseGasByzantium + uint64(len(input)/192)*params.Bn256PairingPerPointGasByzantium
}
-func (c *bn256PairingByzantium) Run(input []byte) ([]byte, error) {
+func (c *bn256PairingByzantium) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) {
return runBn256Pairing(input)
}
-type blake2F struct{}
+type Blake2F struct{}
-func (c *blake2F) RequiredGas(input []byte) uint64 {
+func (c *Blake2F) RequiredGas(input []byte) uint64 {
// If the input is malformed, we can't calculate the gas, return 0 and let the
// actual call choke and fault.
- if len(input) != blake2FInputLength {
+ if len(input) != Blake2FInputLength {
return 0
}
return uint64(binary.BigEndian.Uint32(input[0:4]))
}
const (
- blake2FInputLength = 213
- blake2FFinalBlockBytes = byte(1)
- blake2FNonFinalBlockBytes = byte(0)
+ Blake2FInputLength = 213
+ Blake2FFinalBlockBytes = byte(1)
+ Blake2FNonFinalBlockBytes = byte(0)
)
var (
@@ -666,18 +675,18 @@ var (
errBlake2FInvalidFinalFlag = errors.New("invalid final flag")
)
-func (c *blake2F) Run(input []byte) ([]byte, error) {
+func (c *Blake2F) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) {
// Make sure the input is valid (correct length and final flag)
- if len(input) != blake2FInputLength {
+ if len(input) != Blake2FInputLength {
return nil, errBlake2FInvalidInputLength
}
- if input[212] != blake2FNonFinalBlockBytes && input[212] != blake2FFinalBlockBytes {
+ if input[212] != Blake2FNonFinalBlockBytes && input[212] != Blake2FFinalBlockBytes {
return nil, errBlake2FInvalidFinalFlag
}
// Parse the input into the Blake2b call parameters
var (
rounds = binary.BigEndian.Uint32(input[0:4])
- final = input[212] == blake2FFinalBlockBytes
+ final = input[212] == Blake2FFinalBlockBytes
h [8]uint64
m [16]uint64
@@ -707,20 +716,20 @@ func (c *blake2F) Run(input []byte) ([]byte, error) {
var (
errBLS12381InvalidInputLength = errors.New("invalid input length")
- errBLS12381InvalidFieldElementTopBytes = errors.New("invalid field element top bytes")
+ errBLS12381InvalidFieldElementTOpBytes = errors.New("invalid field element top bytes")
errBLS12381G1PointSubgroup = errors.New("g1 point is not on correct subgroup")
errBLS12381G2PointSubgroup = errors.New("g2 point is not on correct subgroup")
)
-// bls12381G1Add implements EIP-2537 G1Add precompile.
-type bls12381G1Add struct{}
+// Bls12381G1Add implements EIP-2537 G1Add precompile.
+type Bls12381G1Add struct{}
// RequiredGas returns the gas required to execute the pre-compiled contract.
-func (c *bls12381G1Add) RequiredGas(input []byte) uint64 {
+func (c *Bls12381G1Add) RequiredGas(input []byte) uint64 {
return params.Bls12381G1AddGas
}
-func (c *bls12381G1Add) Run(input []byte) ([]byte, error) {
+func (c *Bls12381G1Add) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) {
// Implements EIP-2537 G1Add precompile.
// > G1 addition call expects `256` bytes as an input that is interpreted as byte concatenation of two G1 points (`128` bytes each).
// > Output is an encoding of addition operation result - single G1 point (`128` bytes).
@@ -748,11 +757,11 @@ func (c *bls12381G1Add) Run(input []byte) ([]byte, error) {
return encodePointG1(p0), nil
}
-// bls12381G1MultiExp implements EIP-2537 G1MultiExp precompile.
-type bls12381G1MultiExp struct{}
+// Bls12381G1MultiExp implements EIP-2537 G1MultiExp precompile.
+type Bls12381G1MultiExp struct{}
// RequiredGas returns the gas required to execute the pre-compiled contract.
-func (c *bls12381G1MultiExp) RequiredGas(input []byte) uint64 {
+func (c *Bls12381G1MultiExp) RequiredGas(input []byte) uint64 {
// Calculate G1 point, scalar value pair length
k := len(input) / 160
if k == 0 {
@@ -770,7 +779,7 @@ func (c *bls12381G1MultiExp) RequiredGas(input []byte) uint64 {
return (uint64(k) * params.Bls12381G1MulGas * discount) / 1000
}
-func (c *bls12381G1MultiExp) Run(input []byte) ([]byte, error) {
+func (c *Bls12381G1MultiExp) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) {
// Implements EIP-2537 G1MultiExp precompile.
// G1 multiplication call expects `160*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes).
// Output is an encoding of multiexponentiation operation result - single G1 point (`128` bytes).
@@ -808,15 +817,15 @@ func (c *bls12381G1MultiExp) Run(input []byte) ([]byte, error) {
return encodePointG1(r), nil
}
-// bls12381G2Add implements EIP-2537 G2Add precompile.
-type bls12381G2Add struct{}
+// Bls12381G2Add implements EIP-2537 G2Add precompile.
+type Bls12381G2Add struct{}
// RequiredGas returns the gas required to execute the pre-compiled contract.
-func (c *bls12381G2Add) RequiredGas(input []byte) uint64 {
+func (c *Bls12381G2Add) RequiredGas(input []byte) uint64 {
return params.Bls12381G2AddGas
}
-func (c *bls12381G2Add) Run(input []byte) ([]byte, error) {
+func (c *Bls12381G2Add) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) {
// Implements EIP-2537 G2Add precompile.
// > G2 addition call expects `512` bytes as an input that is interpreted as byte concatenation of two G2 points (`256` bytes each).
// > Output is an encoding of addition operation result - single G2 point (`256` bytes).
@@ -845,11 +854,11 @@ func (c *bls12381G2Add) Run(input []byte) ([]byte, error) {
return encodePointG2(r), nil
}
-// bls12381G2MultiExp implements EIP-2537 G2MultiExp precompile.
-type bls12381G2MultiExp struct{}
+// Bls12381G2MultiExp implements EIP-2537 G2MultiExp precompile.
+type Bls12381G2MultiExp struct{}
// RequiredGas returns the gas required to execute the pre-compiled contract.
-func (c *bls12381G2MultiExp) RequiredGas(input []byte) uint64 {
+func (c *Bls12381G2MultiExp) RequiredGas(input []byte) uint64 {
// Calculate G2 point, scalar value pair length
k := len(input) / 288
if k == 0 {
@@ -867,7 +876,7 @@ func (c *bls12381G2MultiExp) RequiredGas(input []byte) uint64 {
return (uint64(k) * params.Bls12381G2MulGas * discount) / 1000
}
-func (c *bls12381G2MultiExp) Run(input []byte) ([]byte, error) {
+func (c *Bls12381G2MultiExp) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) {
// Implements EIP-2537 G2MultiExp precompile logic
// > G2 multiplication call expects `288*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes).
// > Output is an encoding of multiexponentiation operation result - single G2 point (`256` bytes).
@@ -905,15 +914,15 @@ func (c *bls12381G2MultiExp) Run(input []byte) ([]byte, error) {
return encodePointG2(r), nil
}
-// bls12381Pairing implements EIP-2537 Pairing precompile.
-type bls12381Pairing struct{}
+// Bls12381Pairing implements EIP-2537 Pairing precompile.
+type Bls12381Pairing struct{}
// RequiredGas returns the gas required to execute the pre-compiled contract.
-func (c *bls12381Pairing) RequiredGas(input []byte) uint64 {
+func (c *Bls12381Pairing) RequiredGas(input []byte) uint64 {
return params.Bls12381PairingBaseGas + uint64(len(input)/384)*params.Bls12381PairingPerPairGas
}
-func (c *bls12381Pairing) Run(input []byte) ([]byte, error) {
+func (c *Bls12381Pairing) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) {
// Implements EIP-2537 Pairing precompile logic.
// > Pairing call expects `384*k` bytes as an inputs that is interpreted as byte concatenation of `k` slices. Each slice has the following structure:
// > - `128` bytes of G1 point encoding
@@ -1028,7 +1037,7 @@ func decodeBLS12381FieldElement(in []byte) (fp.Element, error) {
// check top bytes
for i := 0; i < 16; i++ {
if in[i] != byte(0x00) {
- return fp.Element{}, errBLS12381InvalidFieldElementTopBytes
+ return fp.Element{}, errBLS12381InvalidFieldElementTOpBytes
}
}
var res [48]byte
@@ -1057,15 +1066,15 @@ func encodePointG2(p *bls12381.G2Affine) []byte {
return out
}
-// bls12381MapG1 implements EIP-2537 MapG1 precompile.
-type bls12381MapG1 struct{}
+// Bls12381MapG1 implements EIP-2537 MapG1 precompile.
+type Bls12381MapG1 struct{}
// RequiredGas returns the gas required to execute the pre-compiled contract.
-func (c *bls12381MapG1) RequiredGas(input []byte) uint64 {
+func (c *Bls12381MapG1) RequiredGas(input []byte) uint64 {
return params.Bls12381MapG1Gas
}
-func (c *bls12381MapG1) Run(input []byte) ([]byte, error) {
+func (c *Bls12381MapG1) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) {
// Implements EIP-2537 Map_To_G1 precompile.
// > Field-to-curve call expects an `64` bytes input that is interpreted as an element of the base field.
// > Output of this call is `128` bytes and is G1 point following respective encoding rules.
@@ -1086,15 +1095,15 @@ func (c *bls12381MapG1) Run(input []byte) ([]byte, error) {
return encodePointG1(&r), nil
}
-// bls12381MapG2 implements EIP-2537 MapG2 precompile.
-type bls12381MapG2 struct{}
+// Bls12381MapG2 implements EIP-2537 MapG2 precompile.
+type Bls12381MapG2 struct{}
// RequiredGas returns the gas required to execute the pre-compiled contract.
-func (c *bls12381MapG2) RequiredGas(input []byte) uint64 {
+func (c *Bls12381MapG2) RequiredGas(input []byte) uint64 {
return params.Bls12381MapG2Gas
}
-func (c *bls12381MapG2) Run(input []byte) ([]byte, error) {
+func (c *Bls12381MapG2) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) {
// Implements EIP-2537 Map_FP2_TO_G2 precompile logic.
// > Field-to-curve call expects an `128` bytes input that is interpreted as an element of the quadratic extension field.
// > Output of this call is `256` bytes and is G2 point following respective encoding rules.
@@ -1119,11 +1128,11 @@ func (c *bls12381MapG2) Run(input []byte) ([]byte, error) {
return encodePointG2(&r), nil
}
-// kzgPointEvaluation implements the EIP-4844 point evaluation precompile.
-type kzgPointEvaluation struct{}
+// KzgPointEvaluation implements the EIP-4844 point evaluation precompile.
+type KzgPointEvaluation struct{}
// RequiredGas estimates the gas required for running the point evaluation precompile.
-func (b *kzgPointEvaluation) RequiredGas(input []byte) uint64 {
+func (b *KzgPointEvaluation) RequiredGas(input []byte) uint64 {
return params.BlobTxPointEvaluationPrecompileGas
}
@@ -1140,7 +1149,7 @@ var (
)
// Run executes the point evaluation precompile.
-func (b *kzgPointEvaluation) Run(input []byte) ([]byte, error) {
+func (b *KzgPointEvaluation) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) {
if len(input) != blobVerifyInputLength {
return nil, errBlobVerifyInvalidInputLength
}
diff --git a/core/vm/contracts_fuzz_test.go b/core/vm/contracts_fuzz_test.go
index 1e5cc8007471..f722d78cae7e 100644
--- a/core/vm/contracts_fuzz_test.go
+++ b/core/vm/contracts_fuzz_test.go
@@ -14,12 +14,13 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-package vm
+package vm_test
import (
"testing"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/vm"
)
func FuzzPrecompiledContracts(f *testing.F) {
@@ -36,7 +37,7 @@ func FuzzPrecompiledContracts(f *testing.F) {
return
}
inWant := string(input)
- RunPrecompiledContract(p, input, gas, nil)
+ vm.RunPrecompiledContract(p, nil, common.Address{}, common.Address{}, input, gas, nil, nil, false, false)
if inHave := string(input); inWant != inHave {
t.Errorf("Precompiled %v modified input data", a)
}
diff --git a/core/vm/contracts_test.go b/core/vm/contracts_test.go
index b627f2ada506..70297e23bf41 100644
--- a/core/vm/contracts_test.go
+++ b/core/vm/contracts_test.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-package vm
+package vm_test
import (
"bytes"
@@ -25,6 +25,7 @@ import (
"time"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/vm"
)
// precompiledTest defines the input/output pairs for precompiled contract tests.
@@ -45,48 +46,48 @@ type precompiledFailureTest struct {
// allPrecompiles does not map to the actual set of precompiles, as it also contains
// repriced versions of precompiles at certain slots
-var allPrecompiles = map[common.Address]PrecompiledContract{
- common.BytesToAddress([]byte{1}): &ecrecover{},
- common.BytesToAddress([]byte{2}): &sha256hash{},
- common.BytesToAddress([]byte{3}): &ripemd160hash{},
- common.BytesToAddress([]byte{4}): &dataCopy{},
- common.BytesToAddress([]byte{5}): &bigModExp{eip2565: false},
- common.BytesToAddress([]byte{0xf5}): &bigModExp{eip2565: true},
- common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
- common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
- common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
- common.BytesToAddress([]byte{9}): &blake2F{},
- common.BytesToAddress([]byte{0x0a}): &kzgPointEvaluation{},
-
- common.BytesToAddress([]byte{0x0f, 0x0a}): &bls12381G1Add{},
- common.BytesToAddress([]byte{0x0f, 0x0b}): &bls12381G1MultiExp{},
- common.BytesToAddress([]byte{0x0f, 0x0c}): &bls12381G2Add{},
- common.BytesToAddress([]byte{0x0f, 0x0d}): &bls12381G2MultiExp{},
- common.BytesToAddress([]byte{0x0f, 0x0e}): &bls12381Pairing{},
- common.BytesToAddress([]byte{0x0f, 0x0f}): &bls12381MapG1{},
- common.BytesToAddress([]byte{0x0f, 0x10}): &bls12381MapG2{},
+var allPrecompiles = map[common.Address]vm.PrecompiledContract{
+ common.BytesToAddress([]byte{1}): &vm.Ecrecover{},
+ common.BytesToAddress([]byte{2}): &vm.Sha256hash{},
+ common.BytesToAddress([]byte{3}): &vm.Ripemd160hash{},
+ common.BytesToAddress([]byte{4}): &vm.DataCopy{},
+ common.BytesToAddress([]byte{5}): &vm.BigModExp{Eip2565: false},
+ common.BytesToAddress([]byte{0xf5}): &vm.BigModExp{Eip2565: true},
+ common.BytesToAddress([]byte{6}): &vm.Bn256AddIstanbul{},
+ common.BytesToAddress([]byte{7}): &vm.Bn256ScalarMulIstanbul{},
+ common.BytesToAddress([]byte{8}): &vm.Bn256PairingIstanbul{},
+ common.BytesToAddress([]byte{9}): &vm.Blake2F{},
+ common.BytesToAddress([]byte{0x0a}): &vm.KzgPointEvaluation{},
+
+ common.BytesToAddress([]byte{0x0f, 0x0a}): &vm.Bls12381G1Add{},
+ common.BytesToAddress([]byte{0x0f, 0x0b}): &vm.Bls12381G1MultiExp{},
+ common.BytesToAddress([]byte{0x0f, 0x0c}): &vm.Bls12381G2Add{},
+ common.BytesToAddress([]byte{0x0f, 0x0d}): &vm.Bls12381G2MultiExp{},
+ common.BytesToAddress([]byte{0x0f, 0x0e}): &vm.Bls12381Pairing{},
+ common.BytesToAddress([]byte{0x0f, 0x0f}): &vm.Bls12381MapG1{},
+ common.BytesToAddress([]byte{0x0f, 0x10}): &vm.Bls12381MapG2{},
}
// EIP-152 test vectors
var blake2FMalformedInputTests = []precompiledFailureTest{
{
Input: "",
- ExpectedError: errBlake2FInvalidInputLength.Error(),
+ ExpectedError: "invalid input length",
Name: "vector 0: empty input",
},
{
Input: "00000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001",
- ExpectedError: errBlake2FInvalidInputLength.Error(),
+ ExpectedError: "invalid input length",
Name: "vector 1: less than 213 bytes input",
},
{
Input: "000000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001",
- ExpectedError: errBlake2FInvalidInputLength.Error(),
+ ExpectedError: "invalid input length",
Name: "vector 2: more than 213 bytes input",
},
{
Input: "0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000002",
- ExpectedError: errBlake2FInvalidFinalFlag.Error(),
+ ExpectedError: "invalid final flag",
Name: "vector 3: malformed final block indicator flag",
},
}
@@ -96,7 +97,7 @@ func testPrecompiled(addr string, test precompiledTest, t *testing.T) {
in := common.Hex2Bytes(test.Input)
gas := p.RequiredGas(in)
t.Run(fmt.Sprintf("%s-Gas=%d", test.Name, gas), func(t *testing.T) {
- if res, _, err := RunPrecompiledContract(p, in, gas, nil); err != nil {
+ if res, _, err := vm.RunPrecompiledContract(p, nil, common.Address{}, common.Address{}, in, gas, nil, nil, false, false); err != nil {
t.Error(err)
} else if common.Bytes2Hex(res) != test.Expected {
t.Errorf("Expected %v, got %v", test.Expected, common.Bytes2Hex(res))
@@ -118,7 +119,7 @@ func testPrecompiledOOG(addr string, test precompiledTest, t *testing.T) {
gas := p.RequiredGas(in) - 1
t.Run(fmt.Sprintf("%s-Gas=%d", test.Name, gas), func(t *testing.T) {
- _, _, err := RunPrecompiledContract(p, in, gas, nil)
+ _, _, err := vm.RunPrecompiledContract(p, nil, common.Address{}, common.Address{}, in, gas, nil, nil, false, false)
if err.Error() != "out of gas" {
t.Errorf("Expected error [out of gas], got [%v]", err)
}
@@ -135,7 +136,7 @@ func testPrecompiledFailure(addr string, test precompiledFailureTest, t *testing
in := common.Hex2Bytes(test.Input)
gas := p.RequiredGas(in)
t.Run(test.Name, func(t *testing.T) {
- _, _, err := RunPrecompiledContract(p, in, gas, nil)
+ _, _, err := vm.RunPrecompiledContract(p, nil, common.Address{}, common.Address{}, in, gas, nil, nil, false, false)
if err.Error() != test.ExpectedError {
t.Errorf("Expected error [%v], got [%v]", test.ExpectedError, err)
}
@@ -167,7 +168,7 @@ func benchmarkPrecompiled(addr string, test precompiledTest, bench *testing.B) {
bench.ResetTimer()
for i := 0; i < bench.N; i++ {
copy(data, in)
- res, _, err = RunPrecompiledContract(p, data, reqGas, nil)
+ res, _, err = vm.RunPrecompiledContract(p, nil, common.Address{}, common.Address{}, data, reqGas, nil, nil, false, false)
}
bench.StopTimer()
elapsed := uint64(time.Since(start))
@@ -191,7 +192,7 @@ func benchmarkPrecompiled(addr string, test precompiledTest, bench *testing.B) {
})
}
-// Benchmarks the sample inputs from the ECRECOVER precompile.
+// Benchmarks the sample inputs from the vm.Ecrecover precompile.
func BenchmarkPrecompiledEcrecover(bench *testing.B) {
t := precompiledTest{
Input: "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02",
@@ -270,7 +271,7 @@ func TestPrecompileBlake2FMalformedInput(t *testing.T) {
}
}
-func TestPrecompiledEcrecover(t *testing.T) { testJson("ecRecover", "01", t) }
+func TestPrecompiledEcrecover(t *testing.T) { testJson("vm.Ecrecover", "01", t) }
func testJson(name, addr string, t *testing.T) {
tests, err := loadJson(name)
diff --git a/core/vm/eips.go b/core/vm/eips.go
index 515999bd19aa..265050b36351 100644
--- a/core/vm/eips.go
+++ b/core/vm/eips.go
@@ -90,7 +90,7 @@ func enable1884(jt *JumpTable) {
func opSelfBalance(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address())
- scope.Stack.push(balance)
+ scope.Stack.Push(balance)
return nil, nil
}
@@ -109,7 +109,7 @@ func enable1344(jt *JumpTable) {
// opChainID implements CHAINID opcode
func opChainID(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
chainId, _ := uint256.FromBig(interpreter.evm.chainConfig.ChainID)
- scope.Stack.push(chainId)
+ scope.Stack.Push(chainId)
return nil, nil
}
@@ -183,36 +183,36 @@ func enable3198(jt *JumpTable) {
// - Adds TSTORE that writes to transient storage
func enable1153(jt *JumpTable) {
jt[TLOAD] = &operation{
- execute: opTload,
+ execute: OpTload,
constantGas: params.WarmStorageReadCostEIP2929,
minStack: minStack(1, 1),
maxStack: maxStack(1, 1),
}
jt[TSTORE] = &operation{
- execute: opTstore,
+ execute: OpTstore,
constantGas: params.WarmStorageReadCostEIP2929,
minStack: minStack(2, 0),
maxStack: maxStack(2, 0),
}
}
-// opTload implements TLOAD opcode
-func opTload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- loc := scope.Stack.peek()
+// OpTload implements TLOAD opcode
+func OpTload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ loc := scope.Stack.Peek()
hash := common.Hash(loc.Bytes32())
val := interpreter.evm.StateDB.GetTransientState(scope.Contract.Address(), hash)
loc.SetBytes(val.Bytes())
return nil, nil
}
-// opTstore implements TSTORE opcode
-func opTstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+// OpTstore implements TSTORE opcode
+func OpTstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
if interpreter.readOnly {
return nil, ErrWriteProtection
}
- loc := scope.Stack.pop()
- val := scope.Stack.pop()
+ loc := scope.Stack.Pop()
+ val := scope.Stack.Pop()
interpreter.evm.StateDB.SetTransientState(scope.Contract.Address(), loc.Bytes32(), val.Bytes32())
return nil, nil
}
@@ -220,7 +220,7 @@ func opTstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b
// opBaseFee implements BASEFEE opcode
func opBaseFee(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
baseFee, _ := uint256.FromBig(interpreter.evm.Context.BaseFee)
- scope.Stack.push(baseFee)
+ scope.Stack.Push(baseFee)
return nil, nil
}
@@ -237,7 +237,7 @@ func enable3855(jt *JumpTable) {
// opPush0 implements the PUSH0 opcode
func opPush0(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- scope.Stack.push(new(uint256.Int))
+ scope.Stack.Push(new(uint256.Int))
return nil, nil
}
@@ -252,21 +252,21 @@ func enable3860(jt *JumpTable) {
// https://eips.ethereum.org/EIPS/eip-5656
func enable5656(jt *JumpTable) {
jt[MCOPY] = &operation{
- execute: opMcopy,
+ execute: OpMcopy,
constantGas: GasFastestStep,
- dynamicGas: gasMcopy,
+ dynamicGas: GasMcopy,
minStack: minStack(3, 0),
maxStack: maxStack(3, 0),
- memorySize: memoryMcopy,
+ memorySize: MemoryMcopy,
}
}
-// opMcopy implements the MCOPY opcode (https://eips.ethereum.org/EIPS/eip-5656)
-func opMcopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+// OpMcopy implements the MCOPY opcode (https://eips.ethereum.org/EIPS/eip-5656)
+func OpMcopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
var (
- dst = scope.Stack.pop()
- src = scope.Stack.pop()
- length = scope.Stack.pop()
+ dst = scope.Stack.Pop()
+ src = scope.Stack.Pop()
+ length = scope.Stack.Pop()
)
// These values are checked for overflow during memory expansion calculation
// (the memorySize function on the opcode).
@@ -274,9 +274,9 @@ func opMcopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by
return nil, nil
}
-// opBlobHash implements the BLOBHASH opcode
-func opBlobHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- index := scope.Stack.peek()
+// OpBlobHash implements the BLOBHASH opcode
+func OpBlobHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ index := scope.Stack.Peek()
if index.LtUint64(uint64(len(interpreter.evm.TxContext.BlobHashes))) {
blobHash := interpreter.evm.TxContext.BlobHashes[index.Uint64()]
index.SetBytes32(blobHash[:])
@@ -289,14 +289,14 @@ func opBlobHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
// opBlobBaseFee implements BLOBBASEFEE opcode
func opBlobBaseFee(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
blobBaseFee, _ := uint256.FromBig(interpreter.evm.Context.BlobBaseFee)
- scope.Stack.push(blobBaseFee)
+ scope.Stack.Push(blobBaseFee)
return nil, nil
}
// enable4844 applies EIP-4844 (BLOBHASH opcode)
func enable4844(jt *JumpTable) {
jt[BLOBHASH] = &operation{
- execute: opBlobHash,
+ execute: OpBlobHash,
constantGas: GasFastestStep,
minStack: minStack(1, 1),
maxStack: maxStack(1, 1),
@@ -327,10 +327,10 @@ func enable6780(jt *JumpTable) {
func opExtCodeCopyEIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
var (
stack = scope.Stack
- a = stack.pop()
- memOffset = stack.pop()
- codeOffset = stack.pop()
- length = stack.pop()
+ a = stack.Pop()
+ memOffset = stack.Pop()
+ codeOffset = stack.Pop()
+ length = stack.Pop()
)
uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow()
if overflow {
@@ -365,7 +365,7 @@ func opPush1EIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
)
*pc += 1
if *pc < codeLen {
- scope.Stack.push(integer.SetUint64(uint64(scope.Contract.Code[*pc])))
+ scope.Stack.Push(integer.SetUint64(uint64(scope.Contract.Code[*pc])))
if !scope.Contract.IsDeployment && !scope.Contract.IsSystemCall && *pc%31 == 0 {
// touch next chunk if PUSH1 is at the boundary. if so, *pc has
@@ -378,19 +378,19 @@ func opPush1EIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
}
}
} else {
- scope.Stack.push(integer.Clear())
+ scope.Stack.Push(integer.Clear())
}
return nil, nil
}
-func makePushEIP4762(size uint64, pushByteSize int) executionFunc {
+func makePushEIP4762(size uint64, pushByteSize int) ExecutionFunc {
return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
var (
codeLen = len(scope.Contract.Code)
start = min(codeLen, int(*pc+1))
end = min(codeLen, start+pushByteSize)
)
- scope.Stack.push(new(uint256.Int).SetBytes(
+ scope.Stack.Push(new(uint256.Int).SetBytes(
common.RightPadBytes(
scope.Contract.Code[start:end],
pushByteSize,
diff --git a/core/vm/eof.go b/core/vm/eof.go
index a5406283d5a4..be733c13b393 100644
--- a/core/vm/eof.go
+++ b/core/vm/eof.go
@@ -42,7 +42,7 @@ const (
maxInputItems = 127
maxOutputItems = 128
- maxStackHeight = 1023
+ MaxStackHeight = 1023
maxContainerSections = 256
)
@@ -66,39 +66,39 @@ func isEOFVersion1(code []byte) bool {
// Container is an EOF container object.
type Container struct {
- types []*functionMetadata
- codeSections [][]byte
- subContainers []*Container
- subContainerCodes [][]byte
- data []byte
- dataSize int // might be more than len(data)
+ Types []*FunctionMetadata
+ CodeSections [][]byte
+ SubContainers []*Container
+ SubContainerCodes [][]byte
+ Data []byte
+ DataSize int // might be more than len(data)
}
-// functionMetadata is an EOF function signature.
-type functionMetadata struct {
- inputs uint8
- outputs uint8
- maxStackHeight uint16
+// FunctionMetadata is an EOF function signature.
+type FunctionMetadata struct {
+ Inputs uint8
+ Outputs uint8
+ MaxStackHeight uint16
}
-// stackDelta returns the #outputs - #inputs
-func (meta *functionMetadata) stackDelta() int {
- return int(meta.outputs) - int(meta.inputs)
+// stackDelta returns the #Outputs - #Inputs
+func (meta *FunctionMetadata) stackDelta() int {
+ return int(meta.Outputs) - int(meta.Inputs)
}
-// checkInputs checks the current minimum stack (stackMin) against the required inputs
+// checkInputs checks the current minimum stack (stackMin) against the required Inputs
// of the metadata, and returns an error if the stack is too shallow.
-func (meta *functionMetadata) checkInputs(stackMin int) error {
- if int(meta.inputs) > stackMin {
- return ErrStackUnderflow{stackLen: stackMin, required: int(meta.inputs)}
+func (meta *FunctionMetadata) checkInputs(stackMin int) error {
+ if int(meta.Inputs) > stackMin {
+ return ErrStackUnderflow{StackLen: stackMin, Required: int(meta.Inputs)}
}
return nil
}
// checkStackMax checks the if current maximum stack combined with the
// function max stack will result in a stack overflow, and if so returns an error.
-func (meta *functionMetadata) checkStackMax(stackMax int) error {
- newMaxStack := stackMax + int(meta.maxStackHeight) - int(meta.inputs)
+func (meta *FunctionMetadata) checkStackMax(stackMax int) error {
+ newMaxStack := stackMax + int(meta.MaxStackHeight) - int(meta.Inputs)
if newMaxStack > int(params.StackLimit) {
return ErrStackOverflow{stackLen: newMaxStack, limit: int(params.StackLimit)}
}
@@ -114,37 +114,37 @@ func (c *Container) MarshalBinary() []byte {
// Write section headers.
b = append(b, kindTypes)
- b = binary.BigEndian.AppendUint16(b, uint16(len(c.types)*4))
+ b = binary.BigEndian.AppendUint16(b, uint16(len(c.Types)*4))
b = append(b, kindCode)
- b = binary.BigEndian.AppendUint16(b, uint16(len(c.codeSections)))
- for _, codeSection := range c.codeSections {
+ b = binary.BigEndian.AppendUint16(b, uint16(len(c.CodeSections)))
+ for _, codeSection := range c.CodeSections {
b = binary.BigEndian.AppendUint16(b, uint16(len(codeSection)))
}
var encodedContainer [][]byte
- if len(c.subContainers) != 0 {
+ if len(c.SubContainers) != 0 {
b = append(b, kindContainer)
- b = binary.BigEndian.AppendUint16(b, uint16(len(c.subContainers)))
- for _, section := range c.subContainers {
+ b = binary.BigEndian.AppendUint16(b, uint16(len(c.SubContainers)))
+ for _, section := range c.SubContainers {
encoded := section.MarshalBinary()
b = binary.BigEndian.AppendUint16(b, uint16(len(encoded)))
encodedContainer = append(encodedContainer, encoded)
}
}
b = append(b, kindData)
- b = binary.BigEndian.AppendUint16(b, uint16(c.dataSize))
+ b = binary.BigEndian.AppendUint16(b, uint16(c.DataSize))
b = append(b, 0) // terminator
// Write section contents.
- for _, ty := range c.types {
- b = append(b, []byte{ty.inputs, ty.outputs, byte(ty.maxStackHeight >> 8), byte(ty.maxStackHeight & 0x00ff)}...)
+ for _, ty := range c.Types {
+ b = append(b, []byte{ty.Inputs, ty.Outputs, byte(ty.MaxStackHeight >> 8), byte(ty.MaxStackHeight & 0x00ff)}...)
}
- for _, code := range c.codeSections {
+ for _, code := range c.CodeSections {
b = append(b, code...)
}
for _, section := range encodedContainer {
b = append(b, section...)
}
- b = append(b, c.data...)
+ b = append(b, c.Data...)
return b
}
@@ -231,7 +231,7 @@ func (c *Container) unmarshalContainer(b []byte, isInitcode bool, topLevel bool)
if kind != kindData {
return fmt.Errorf("%w: found section %x instead", errMissingDataHeader, kind)
}
- c.dataSize = dataSize
+ c.DataSize = dataSize
// Check for terminator.
offsetTerminator := offset + 3
@@ -257,28 +257,28 @@ func (c *Container) unmarshalContainer(b []byte, isInitcode bool, topLevel bool)
// Parse types section.
idx := offsetTerminator + 1
- var types = make([]*functionMetadata, 0, typesSize/4)
+ var types = make([]*FunctionMetadata, 0, typesSize/4)
for i := 0; i < typesSize/4; i++ {
- sig := &functionMetadata{
- inputs: b[idx+i*4],
- outputs: b[idx+i*4+1],
- maxStackHeight: binary.BigEndian.Uint16(b[idx+i*4+2:]),
+ sig := &FunctionMetadata{
+ Inputs: b[idx+i*4],
+ Outputs: b[idx+i*4+1],
+ MaxStackHeight: binary.BigEndian.Uint16(b[idx+i*4+2:]),
}
- if sig.inputs > maxInputItems {
- return fmt.Errorf("%w for section %d: have %d", errTooManyInputs, i, sig.inputs)
+ if sig.Inputs > maxInputItems {
+ return fmt.Errorf("%w for section %d: have %d", errTooManyInputs, i, sig.Inputs)
}
- if sig.outputs > maxOutputItems {
- return fmt.Errorf("%w for section %d: have %d", errTooManyOutputs, i, sig.outputs)
+ if sig.Outputs > maxOutputItems {
+ return fmt.Errorf("%w for section %d: have %d", errTooManyOutputs, i, sig.Outputs)
}
- if sig.maxStackHeight > maxStackHeight {
- return fmt.Errorf("%w for section %d: have %d", errTooLargeMaxStackHeight, i, sig.maxStackHeight)
+ if sig.MaxStackHeight > MaxStackHeight {
+ return fmt.Errorf("%w for section %d: have %d", errTooLargeMaxStackHeight, i, sig.MaxStackHeight)
}
types = append(types, sig)
}
- if types[0].inputs != 0 || types[0].outputs != 0x80 {
- return fmt.Errorf("%w: have %d, %d", errInvalidSection0Type, types[0].inputs, types[0].outputs)
+ if types[0].Inputs != 0 || types[0].Outputs != 0x80 {
+ return fmt.Errorf("%w: have %d, %d", errInvalidSection0Type, types[0].Inputs, types[0].Outputs)
}
- c.types = types
+ c.Types = types
// Parse code sections.
idx += typesSize
@@ -290,7 +290,7 @@ func (c *Container) unmarshalContainer(b []byte, isInitcode bool, topLevel bool)
codeSections[i] = b[idx : idx+size]
idx += size
}
- c.codeSections = codeSections
+ c.CodeSections = codeSections
// Parse the optional container sizes.
if len(containerSizes) != 0 {
if len(containerSizes) > maxContainerSections {
@@ -315,8 +315,8 @@ func (c *Container) unmarshalContainer(b []byte, isInitcode bool, topLevel bool)
idx += size
}
- c.subContainers = subContainers
- c.subContainerCodes = subContainerCodes
+ c.SubContainers = subContainers
+ c.SubContainerCodes = subContainerCodes
}
//Parse data section.
@@ -327,7 +327,7 @@ func (c *Container) unmarshalContainer(b []byte, isInitcode bool, topLevel bool)
if topLevel && len(b) != idx+dataSize {
return errTruncatedTopLevelContainer
}
- c.data = b[idx:end]
+ c.Data = b[idx:end]
return nil
}
@@ -355,10 +355,10 @@ func (c *Container) validateSubContainer(jt *JumpTable, refBy int) error {
// should not mean 2 and 3 should be visited twice
var (
index = toVisit[0]
- code = c.codeSections[index]
+ code = c.CodeSections[index]
)
if _, ok := visited[index]; !ok {
- res, err := validateCode(code, index, c, jt, refBy == refByEOFCreate)
+ res, err := ValidateCode(code, index, c, jt, refBy == refByEOFCreate)
if err != nil {
return err
}
@@ -387,10 +387,10 @@ func (c *Container) validateSubContainer(jt *JumpTable, refBy int) error {
toVisit = toVisit[1:]
}
// Make sure every code section is visited at least once.
- if len(visited) != len(c.codeSections) {
- return errUnreachableCode
+ if len(visited) != len(c.CodeSections) {
+ return ErrUnreachableCode
}
- for idx, container := range c.subContainers {
+ for idx, container := range c.SubContainers {
reference, ok := subContainerVisited[idx]
if !ok {
return errOrphanedSubcontainer
@@ -469,33 +469,33 @@ func (c *Container) String() string {
fmt.Sprintf(" - EOFMagic: %02x", eofMagic),
fmt.Sprintf(" - EOFVersion: %02x", eof1Version),
fmt.Sprintf(" - KindType: %02x", kindTypes),
- fmt.Sprintf(" - TypesSize: %04x", len(c.types)*4),
+ fmt.Sprintf(" - TypesSize: %04x", len(c.Types)*4),
fmt.Sprintf(" - KindCode: %02x", kindCode),
fmt.Sprintf(" - KindData: %02x", kindData),
- fmt.Sprintf(" - DataSize: %04x", len(c.data)),
- fmt.Sprintf(" - Number of code sections: %d", len(c.codeSections)),
+ fmt.Sprintf(" - DataSize: %04x", len(c.Data)),
+ fmt.Sprintf(" - Number of code sections: %d", len(c.CodeSections)),
}
- for i, code := range c.codeSections {
+ for i, code := range c.CodeSections {
output = append(output, fmt.Sprintf(" - Code section %d length: %04x", i, len(code)))
}
- output = append(output, fmt.Sprintf(" - Number of subcontainers: %d", len(c.subContainers)))
- if len(c.subContainers) > 0 {
- for i, section := range c.subContainers {
+ output = append(output, fmt.Sprintf(" - Number of subcontainers: %d", len(c.SubContainers)))
+ if len(c.SubContainers) > 0 {
+ for i, section := range c.SubContainers {
output = append(output, fmt.Sprintf(" - subcontainer %d length: %04x\n", i, len(section.MarshalBinary())))
}
}
output = append(output, "Body")
- for i, typ := range c.types {
+ for i, typ := range c.Types {
output = append(output, fmt.Sprintf(" - Type %v: %x", i,
- []byte{typ.inputs, typ.outputs, byte(typ.maxStackHeight >> 8), byte(typ.maxStackHeight & 0x00ff)}))
+ []byte{typ.Inputs, typ.Outputs, byte(typ.MaxStackHeight >> 8), byte(typ.MaxStackHeight & 0x00ff)}))
}
- for i, code := range c.codeSections {
+ for i, code := range c.CodeSections {
output = append(output, fmt.Sprintf(" - Code section %d: %#x", i, code))
}
- for i, section := range c.subContainers {
+ for i, section := range c.SubContainers {
output = append(output, fmt.Sprintf(" - Subcontainer %d: %x", i, section.MarshalBinary()))
}
- output = append(output, fmt.Sprintf(" - Data: %#x", c.data))
+ output = append(output, fmt.Sprintf(" - Data: %#x", c.Data))
return strings.Join(output, "\n")
}
diff --git a/core/vm/eof_control_flow.go b/core/vm/eof_control_flow.go
index c0a44599067d..9a9bfaaebb28 100644
--- a/core/vm/eof_control_flow.go
+++ b/core/vm/eof_control_flow.go
@@ -22,9 +22,9 @@ import (
"github.com/ethereum/go-ethereum/params"
)
-func validateControlFlow(code []byte, section int, metadata []*functionMetadata, jt *JumpTable) (int, error) {
+func validateControlFlow(code []byte, section int, metadata []*FunctionMetadata, jt *JumpTable) (int, error) {
var (
- maxStackHeight = int(metadata[section].inputs)
+ maxStackHeight = int(metadata[section].Inputs)
visitCount = 0
next = make([]int, 0, 1)
)
@@ -54,14 +54,14 @@ func validateControlFlow(code []byte, section int, metadata []*functionMetadata,
return true, int(stackBoundsMin[pos]), int(maxi - 1)
}
// set the initial stack bounds
- setBounds(0, int(metadata[section].inputs), int(metadata[section].inputs))
+ setBounds(0, int(metadata[section].Inputs), int(metadata[section].Inputs))
qualifiedExit := false
for pos := 0; pos < len(code); pos++ {
op := OpCode(code[pos])
ok, currentStackMin, currentStackMax := getStackMaxMin(pos)
if !ok {
- return 0, errUnreachableCode
+ return 0, ErrUnreachableCode
}
switch op {
@@ -84,14 +84,14 @@ func validateControlFlow(code []byte, section int, metadata []*functionMetadata,
In other words: RETF must unambiguously return all items remaining on the stack.
*/
if currentStackMax != currentStackMin {
- return 0, fmt.Errorf("%w: max %d, min %d, at pos %d", errInvalidOutputs, currentStackMax, currentStackMin, pos)
+ return 0, fmt.Errorf("%w: max %d, min %d, at pos %d", ErrInvalidOutputs, currentStackMax, currentStackMin, pos)
}
- numOutputs := int(metadata[section].outputs)
+ numOutputs := int(metadata[section].Outputs)
if numOutputs >= maxOutputItems {
return 0, fmt.Errorf("%w: at pos %d", errInvalidNonReturningFlag, pos)
}
if numOutputs != currentStackMin {
- return 0, fmt.Errorf("%w: have %d, want %d, at pos %d", errInvalidOutputs, numOutputs, currentStackMin, pos)
+ return 0, fmt.Errorf("%w: have %d, want %d, at pos %d", ErrInvalidOutputs, numOutputs, currentStackMin, pos)
}
qualifiedExit = true
case JUMPF:
@@ -102,40 +102,40 @@ func validateControlFlow(code []byte, section int, metadata []*functionMetadata,
return 0, fmt.Errorf("%w: at pos %d", err, pos)
}
- if newSection.outputs == 0x80 {
+ if newSection.Outputs == 0x80 {
if err := newSection.checkInputs(currentStackMin); err != nil {
return 0, fmt.Errorf("%w: at pos %d", err, pos)
}
} else {
if currentStackMax != currentStackMin {
- return 0, fmt.Errorf("%w: max %d, min %d, at pos %d", errInvalidOutputs, currentStackMax, currentStackMin, pos)
+ return 0, fmt.Errorf("%w: max %d, min %d, at pos %d", ErrInvalidOutputs, currentStackMax, currentStackMin, pos)
}
- wantStack := int(metadata[section].outputs) - newSection.stackDelta()
+ wantStack := int(metadata[section].Outputs) - newSection.stackDelta()
if currentStackMax != wantStack {
- return 0, fmt.Errorf("%w: at pos %d", errInvalidOutputs, pos)
+ return 0, fmt.Errorf("%w: at pos %d", ErrInvalidOutputs, pos)
}
}
- qualifiedExit = qualifiedExit || newSection.outputs < maxOutputItems
+ qualifiedExit = qualifiedExit || newSection.Outputs < maxOutputItems
case DUPN:
arg := int(code[pos+1]) + 1
if want, have := arg, currentStackMin; want > have {
- return 0, fmt.Errorf("%w: at pos %d", ErrStackUnderflow{stackLen: have, required: want}, pos)
+ return 0, fmt.Errorf("%w: at pos %d", ErrStackUnderflow{StackLen: have, Required: want}, pos)
}
case SWAPN:
arg := int(code[pos+1]) + 1
if want, have := arg+1, currentStackMin; want > have {
- return 0, fmt.Errorf("%w: at pos %d", ErrStackUnderflow{stackLen: have, required: want}, pos)
+ return 0, fmt.Errorf("%w: at pos %d", ErrStackUnderflow{StackLen: have, Required: want}, pos)
}
case EXCHANGE:
arg := int(code[pos+1])
n := arg>>4 + 1
m := arg&0x0f + 1
if want, have := n+m+1, currentStackMin; want > have {
- return 0, fmt.Errorf("%w: at pos %d", ErrStackUnderflow{stackLen: have, required: want}, pos)
+ return 0, fmt.Errorf("%w: at pos %d", ErrStackUnderflow{StackLen: have, Required: want}, pos)
}
default:
if want, have := jt[op].minStack, currentStackMin; want > have {
- return 0, fmt.Errorf("%w: at pos %d", ErrStackUnderflow{stackLen: have, required: want}, pos)
+ return 0, fmt.Errorf("%w: at pos %d", ErrStackUnderflow{StackLen: have, Required: want}, pos)
}
}
if !terminals[op] && op != CALLF {
@@ -156,7 +156,7 @@ func validateControlFlow(code []byte, section int, metadata []*functionMetadata,
return 0, errInvalidBackwardJump
}
if nextMax != currentStackMax || nextMin != currentStackMin {
- return 0, errInvalidMaxStackHeight
+ return 0, ErrInvalidMaxStackHeight
}
} else {
ok, nextMin, nextMax := getStackMaxMin(nextPos + 1)
@@ -190,7 +190,7 @@ func validateControlFlow(code []byte, section int, metadata []*functionMetadata,
for _, instr := range next {
nextPC := instr + 1
if nextPC >= len(code) {
- return 0, fmt.Errorf("%w: end with %s, pos %d", errInvalidCodeTermination, op, pos)
+ return 0, fmt.Errorf("%w: end with %s, pos %d", ErrInvalidCodeTermination, op, pos)
}
if nextPC > pos {
// target reached via forward jump or seq flow
@@ -222,14 +222,14 @@ func validateControlFlow(code []byte, section int, metadata []*functionMetadata,
pos = next[0]
}
}
- if qualifiedExit != (metadata[section].outputs < maxOutputItems) {
+ if qualifiedExit != (metadata[section].Outputs < maxOutputItems) {
return 0, fmt.Errorf("%w no RETF or qualified JUMPF", errInvalidNonReturningFlag)
}
if maxStackHeight >= int(params.StackLimit) {
return 0, ErrStackOverflow{maxStackHeight, int(params.StackLimit)}
}
- if maxStackHeight != int(metadata[section].maxStackHeight) {
- return 0, fmt.Errorf("%w in code section %d: have %d, want %d", errInvalidMaxStackHeight, section, maxStackHeight, metadata[section].maxStackHeight)
+ if maxStackHeight != int(metadata[section].MaxStackHeight) {
+ return 0, fmt.Errorf("%w in code section %d: have %d, want %d", ErrInvalidMaxStackHeight, section, maxStackHeight, metadata[section].MaxStackHeight)
}
return visitCount, nil
}
diff --git a/core/vm/eof_test.go b/core/vm/eof_test.go
index 0a9cf638ceba..a206c8ffec19 100644
--- a/core/vm/eof_test.go
+++ b/core/vm/eof_test.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-package vm
+package vm_test
import (
"encoding/hex"
@@ -22,48 +22,49 @@ import (
"testing"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/vm"
)
func TestEOFMarshaling(t *testing.T) {
for i, test := range []struct {
- want Container
+ want vm.Container
err error
}{
{
- want: Container{
- types: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 1}},
- codeSections: [][]byte{common.Hex2Bytes("604200")},
- data: []byte{0x01, 0x02, 0x03},
- dataSize: 3,
+ want: vm.Container{
+ Types: []*vm.FunctionMetadata{{Inputs: 0, Outputs: 0x80, MaxStackHeight: 1}},
+ CodeSections: [][]byte{common.Hex2Bytes("604200")},
+ Data: []byte{0x01, 0x02, 0x03},
+ DataSize: 3,
},
},
{
- want: Container{
- types: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 1}},
- codeSections: [][]byte{common.Hex2Bytes("604200")},
- data: []byte{0x01, 0x02, 0x03},
- dataSize: 3,
+ want: vm.Container{
+ Types: []*vm.FunctionMetadata{{Inputs: 0, Outputs: 0x80, MaxStackHeight: 1}},
+ CodeSections: [][]byte{common.Hex2Bytes("604200")},
+ Data: []byte{0x01, 0x02, 0x03},
+ DataSize: 3,
},
},
{
- want: Container{
- types: []*functionMetadata{
- {inputs: 0, outputs: 0x80, maxStackHeight: 1},
- {inputs: 2, outputs: 3, maxStackHeight: 4},
- {inputs: 1, outputs: 1, maxStackHeight: 1},
+ want: vm.Container{
+ Types: []*vm.FunctionMetadata{
+ {Inputs: 0, Outputs: 0x80, MaxStackHeight: 1},
+ {Inputs: 2, Outputs: 3, MaxStackHeight: 4},
+ {Inputs: 1, Outputs: 1, MaxStackHeight: 1},
},
- codeSections: [][]byte{
+ CodeSections: [][]byte{
common.Hex2Bytes("604200"),
common.Hex2Bytes("6042604200"),
common.Hex2Bytes("00"),
},
- data: []byte{},
+ Data: []byte{},
},
},
} {
var (
b = test.want.MarshalBinary()
- got Container
+ got vm.Container
)
t.Logf("b: %#x", b)
if err := got.UnmarshalBinary(b, true); err != nil && err != test.err {
@@ -76,20 +77,20 @@ func TestEOFMarshaling(t *testing.T) {
}
func TestEOFSubcontainer(t *testing.T) {
- var subcontainer = new(Container)
+ var subcontainer = new(vm.Container)
if err := subcontainer.UnmarshalBinary(common.Hex2Bytes("ef000101000402000100010400000000800000fe"), true); err != nil {
t.Fatal(err)
}
- container := Container{
- types: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 1}},
- codeSections: [][]byte{common.Hex2Bytes("604200")},
- subContainers: []*Container{subcontainer},
- data: []byte{0x01, 0x02, 0x03},
- dataSize: 3,
+ container := vm.Container{
+ Types: []*vm.FunctionMetadata{{Inputs: 0, Outputs: 0x80, MaxStackHeight: 1}},
+ CodeSections: [][]byte{common.Hex2Bytes("604200")},
+ SubContainers: []*vm.Container{subcontainer},
+ Data: []byte{0x01, 0x02, 0x03},
+ DataSize: 3,
}
var (
b = container.MarshalBinary()
- got Container
+ got vm.Container
)
if err := got.UnmarshalBinary(b, true); err != nil {
t.Fatal(err)
@@ -109,7 +110,7 @@ func TestMarshaling(t *testing.T) {
if err != nil {
t.Fatalf("test %d: error decoding: %v", i, err)
}
- var got Container
+ var got vm.Container
if err := got.UnmarshalBinary(s, true); err != nil {
t.Fatalf("test %d: got error %v", i, err)
}
diff --git a/core/vm/eof_validation.go b/core/vm/eof_validation.go
index 514f9fb58cf9..070f23ad880f 100644
--- a/core/vm/eof_validation.go
+++ b/core/vm/eof_validation.go
@@ -27,22 +27,22 @@ import (
var (
errInvalidMagic = errors.New("invalid magic")
errUndefinedInstruction = errors.New("undefined instruction")
- errTruncatedImmediate = errors.New("truncated immediate")
+ ErrTruncatedImmediate = errors.New("truncated immediate")
errInvalidSectionArgument = errors.New("invalid section argument")
errInvalidCallArgument = errors.New("callf into non-returning section")
errInvalidDataloadNArgument = errors.New("invalid dataloadN argument")
- errInvalidJumpDest = errors.New("invalid jump destination")
+ ErrInvalidJumpDest = errors.New("invalid jump destination")
errInvalidBackwardJump = errors.New("invalid backward jump")
- errInvalidOutputs = errors.New("invalid number of outputs")
- errInvalidMaxStackHeight = errors.New("invalid max stack height")
- errInvalidCodeTermination = errors.New("invalid code termination")
+ ErrInvalidOutputs = errors.New("invalid number of outputs")
+ ErrInvalidMaxStackHeight = errors.New("invalid max stack height")
+ ErrInvalidCodeTermination = errors.New("invalid code termination")
errEOFCreateWithTruncatedSection = errors.New("eofcreate with truncated section")
errOrphanedSubcontainer = errors.New("subcontainer not referenced at all")
errIncompatibleContainerKind = errors.New("incompatible container kind")
- errStopAndReturnContract = errors.New("Stop/Return and Returncontract in the same code section")
+ errStOpAndReturnContract = errors.New("Stop/Return and Returncontract in the same code section")
errStopInInitCode = errors.New("initcode contains a RETURN or STOP opcode")
errTruncatedTopLevelContainer = errors.New("truncated top level container")
- errUnreachableCode = errors.New("unreachable code")
+ ErrUnreachableCode = errors.New("unreachable code")
errInvalidNonReturningFlag = errors.New("invalid non-returning flag, bad RETF")
errInvalidVersion = errors.New("invalid version")
errMissingTypeHeader = errors.New("missing type header")
@@ -73,7 +73,7 @@ type validationResult struct {
}
// validateCode validates the code parameter against the EOF v1 validity requirements.
-func validateCode(code []byte, section int, container *Container, jt *JumpTable, isInitCode bool) (*validationResult, error) {
+func ValidateCode(code []byte, section int, container *Container, jt *JumpTable, isInitCode bool) (*validationResult, error) {
var (
i = 0
// Tracks the number of actual instructions in the code (e.g.
@@ -81,7 +81,7 @@ func validateCode(code []byte, section int, container *Container, jt *JumpTable,
// if each instruction is reachable.
count = 0
op OpCode
- analysis bitvec
+ analysis Bitvec
visitedCode map[int]struct{}
visitedSubcontainers map[int]int
hasReturnContract bool
@@ -101,7 +101,7 @@ func validateCode(code []byte, section int, container *Container, jt *JumpTable,
}
size := int(immediates[op])
if size != 0 && len(code) <= i+size {
- return nil, fmt.Errorf("%w: op %s, pos %d", errTruncatedImmediate, op, i)
+ return nil, fmt.Errorf("%w: op %s, pos %d", ErrTruncatedImmediate, op, i)
}
switch op {
case RJUMP, RJUMPI:
@@ -112,7 +112,7 @@ func validateCode(code []byte, section int, container *Container, jt *JumpTable,
maxSize := int(code[i+1])
length := maxSize + 1
if len(code) <= i+length {
- return nil, fmt.Errorf("%w: jump table truncated, op %s, pos %d", errTruncatedImmediate, op, i)
+ return nil, fmt.Errorf("%w: jump table truncated, op %s, pos %d", ErrTruncatedImmediate, op, i)
}
offset := i + 2
for j := 0; j < length; j++ {
@@ -123,10 +123,10 @@ func validateCode(code []byte, section int, container *Container, jt *JumpTable,
i += 2 * maxSize
case CALLF:
arg, _ := parseUint16(code[i+1:])
- if arg >= len(container.types) {
- return nil, fmt.Errorf("%w: arg %d, last %d, pos %d", errInvalidSectionArgument, arg, len(container.types), i)
+ if arg >= len(container.Types) {
+ return nil, fmt.Errorf("%w: arg %d, last %d, pos %d", errInvalidSectionArgument, arg, len(container.Types), i)
}
- if container.types[arg].outputs == 0x80 {
+ if container.Types[arg].Outputs == 0x80 {
return nil, fmt.Errorf("%w: section %v", errInvalidCallArgument, arg)
}
if visitedCode == nil {
@@ -135,11 +135,11 @@ func validateCode(code []byte, section int, container *Container, jt *JumpTable,
visitedCode[arg] = struct{}{}
case JUMPF:
arg, _ := parseUint16(code[i+1:])
- if arg >= len(container.types) {
- return nil, fmt.Errorf("%w: arg %d, last %d, pos %d", errInvalidSectionArgument, arg, len(container.types), i)
+ if arg >= len(container.Types) {
+ return nil, fmt.Errorf("%w: arg %d, last %d, pos %d", errInvalidSectionArgument, arg, len(container.Types), i)
}
- if container.types[arg].outputs != 0x80 && container.types[arg].outputs > container.types[section].outputs {
- return nil, fmt.Errorf("%w: arg %d, last %d, pos %d", errInvalidOutputs, arg, len(container.types), i)
+ if container.Types[arg].Outputs != 0x80 && container.Types[arg].Outputs > container.Types[section].Outputs {
+ return nil, fmt.Errorf("%w: arg %d, last %d, pos %d", ErrInvalidOutputs, arg, len(container.Types), i)
}
if visitedCode == nil {
visitedCode = make(map[int]struct{})
@@ -148,16 +148,16 @@ func validateCode(code []byte, section int, container *Container, jt *JumpTable,
case DATALOADN:
arg, _ := parseUint16(code[i+1:])
// TODO why are we checking this? We should just pad
- if arg+32 > len(container.data) {
- return nil, fmt.Errorf("%w: arg %d, last %d, pos %d", errInvalidDataloadNArgument, arg, len(container.data), i)
+ if arg+32 > len(container.Data) {
+ return nil, fmt.Errorf("%w: arg %d, last %d, pos %d", errInvalidDataloadNArgument, arg, len(container.Data), i)
}
case RETURNCONTRACT:
if !isInitCode {
return nil, errIncompatibleContainerKind
}
arg := int(code[i+1])
- if arg >= len(container.subContainers) {
- return nil, fmt.Errorf("%w: arg %d, last %d, pos %d", errUnreachableCode, arg, len(container.subContainers), i)
+ if arg >= len(container.SubContainers) {
+ return nil, fmt.Errorf("%w: arg %d, last %d, pos %d", ErrUnreachableCode, arg, len(container.SubContainers), i)
}
if visitedSubcontainers == nil {
visitedSubcontainers = make(map[int]int)
@@ -167,17 +167,17 @@ func validateCode(code []byte, section int, container *Container, jt *JumpTable,
return nil, fmt.Errorf("section already referenced, arg :%d", arg)
}
if hasStop {
- return nil, errStopAndReturnContract
+ return nil, errStOpAndReturnContract
}
hasReturnContract = true
visitedSubcontainers[arg] = refByReturnContract
case EOFCREATE:
arg := int(code[i+1])
- if arg >= len(container.subContainers) {
- return nil, fmt.Errorf("%w: arg %d, last %d, pos %d", errUnreachableCode, arg, len(container.subContainers), i)
+ if arg >= len(container.SubContainers) {
+ return nil, fmt.Errorf("%w: arg %d, last %d, pos %d", ErrUnreachableCode, arg, len(container.SubContainers), i)
}
- if ct := container.subContainers[arg]; len(ct.data) != ct.dataSize {
- return nil, fmt.Errorf("%w: container %d, have %d, claimed %d, pos %d", errEOFCreateWithTruncatedSection, arg, len(ct.data), ct.dataSize, i)
+ if ct := container.SubContainers[arg]; len(ct.Data) != ct.DataSize {
+ return nil, fmt.Errorf("%w: container %d, have %d, claimed %d, pos %d", errEOFCreateWithTruncatedSection, arg, len(ct.Data), ct.DataSize, i)
}
if visitedSubcontainers == nil {
visitedSubcontainers = make(map[int]int)
@@ -192,7 +192,7 @@ func validateCode(code []byte, section int, container *Container, jt *JumpTable,
return nil, errStopInInitCode
}
if hasReturnContract {
- return nil, errStopAndReturnContract
+ return nil, errStOpAndReturnContract
}
hasStop = true
}
@@ -201,13 +201,13 @@ func validateCode(code []byte, section int, container *Container, jt *JumpTable,
// Code sections may not "fall through" and require proper termination.
// Therefore, the last instruction must be considered terminal or RJUMP.
if !terminals[op] && op != RJUMP {
- return nil, fmt.Errorf("%w: end with %s, pos %d", errInvalidCodeTermination, op, i)
+ return nil, fmt.Errorf("%w: end with %s, pos %d", ErrInvalidCodeTermination, op, i)
}
- if paths, err := validateControlFlow(code, section, container.types, jt); err != nil {
+ if paths, err := validateControlFlow(code, section, container.Types, jt); err != nil {
return nil, err
} else if paths != count {
// TODO(matt): return actual position of unreachable code
- return nil, errUnreachableCode
+ return nil, ErrUnreachableCode
}
return &validationResult{
visitedCode: visitedCode,
@@ -218,7 +218,7 @@ func validateCode(code []byte, section int, container *Container, jt *JumpTable,
}
// checkDest parses a relative offset at code[0:2] and checks if it is a valid jump destination.
-func checkDest(code []byte, analysis *bitvec, imm, from, length int) error {
+func checkDest(code []byte, analysis *Bitvec, imm, from, length int) error {
if len(code) < imm+2 {
return io.ErrUnexpectedEOF
}
@@ -228,10 +228,10 @@ func checkDest(code []byte, analysis *bitvec, imm, from, length int) error {
offset := parseInt16(code[imm:])
dest := from + offset
if dest < 0 || dest >= length {
- return fmt.Errorf("%w: out-of-bounds offset: offset %d, dest %d, pos %d", errInvalidJumpDest, offset, dest, imm)
+ return fmt.Errorf("%w: out-of-bounds offset: offset %d, dest %d, pos %d", ErrInvalidJumpDest, offset, dest, imm)
}
if !analysis.codeSegment(uint64(dest)) {
- return fmt.Errorf("%w: offset into immediate: offset %d, dest %d, pos %d", errInvalidJumpDest, offset, dest, imm)
+ return fmt.Errorf("%w: offset into immediate: offset %d, dest %d, pos %d", ErrInvalidJumpDest, offset, dest, imm)
}
return nil
}
diff --git a/core/vm/eof_validation_test.go b/core/vm/eof_validation_test.go
index f7b0e78f2695..a1a84d529473 100644
--- a/core/vm/eof_validation_test.go
+++ b/core/vm/eof_validation_test.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-package vm
+package vm_test
import (
"encoding/binary"
@@ -22,6 +22,7 @@ import (
"testing"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
)
@@ -29,229 +30,229 @@ func TestValidateCode(t *testing.T) {
for i, test := range []struct {
code []byte
section int
- metadata []*functionMetadata
+ metadata []*vm.FunctionMetadata
err error
}{
{
code: []byte{
- byte(CALLER),
- byte(POP),
- byte(STOP),
+ byte(vm.CALLER),
+ byte(vm.POP),
+ byte(vm.STOP),
},
section: 0,
- metadata: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 1}},
+ metadata: []*vm.FunctionMetadata{{Inputs: 0, Outputs: 0x80, MaxStackHeight: 1}},
},
{
code: []byte{
- byte(CALLF), 0x00, 0x00,
- byte(RETF),
+ byte(vm.CALLF), 0x00, 0x00,
+ byte(vm.RETF),
},
section: 0,
- metadata: []*functionMetadata{{inputs: 0, outputs: 0, maxStackHeight: 0}},
+ metadata: []*vm.FunctionMetadata{{Inputs: 0, Outputs: 0, MaxStackHeight: 0}},
},
{
code: []byte{
- byte(ADDRESS),
- byte(CALLF), 0x00, 0x00,
- byte(POP),
- byte(RETF),
+ byte(vm.ADDRESS),
+ byte(vm.CALLF), 0x00, 0x00,
+ byte(vm.POP),
+ byte(vm.RETF),
},
section: 0,
- metadata: []*functionMetadata{{inputs: 0, outputs: 0, maxStackHeight: 1}},
+ metadata: []*vm.FunctionMetadata{{Inputs: 0, Outputs: 0, MaxStackHeight: 1}},
},
{
code: []byte{
- byte(CALLER),
- byte(POP),
+ byte(vm.CALLER),
+ byte(vm.POP),
},
section: 0,
- metadata: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 1}},
- err: errInvalidCodeTermination,
+ metadata: []*vm.FunctionMetadata{{Inputs: 0, Outputs: 0x80, MaxStackHeight: 1}},
+ err: vm.ErrInvalidCodeTermination,
},
{
code: []byte{
- byte(RJUMP),
+ byte(vm.RJUMP),
byte(0x00),
byte(0x01),
- byte(CALLER),
- byte(STOP),
+ byte(vm.CALLER),
+ byte(vm.STOP),
},
section: 0,
- metadata: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 0}},
- err: errUnreachableCode,
+ metadata: []*vm.FunctionMetadata{{Inputs: 0, Outputs: 0x80, MaxStackHeight: 0}},
+ err: vm.ErrUnreachableCode,
},
{
code: []byte{
- byte(PUSH1),
+ byte(vm.PUSH1),
byte(0x42),
- byte(ADD),
- byte(STOP),
+ byte(vm.ADD),
+ byte(vm.STOP),
},
section: 0,
- metadata: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 1}},
- err: ErrStackUnderflow{stackLen: 1, required: 2},
+ metadata: []*vm.FunctionMetadata{{Inputs: 0, Outputs: 0x80, MaxStackHeight: 1}},
+ err: vm.ErrStackUnderflow{StackLen: 1, Required: 2},
},
{
code: []byte{
- byte(PUSH1),
+ byte(vm.PUSH1),
byte(0x42),
- byte(POP),
- byte(STOP),
+ byte(vm.POP),
+ byte(vm.STOP),
},
section: 0,
- metadata: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 2}},
- err: errInvalidMaxStackHeight,
+ metadata: []*vm.FunctionMetadata{{Inputs: 0, Outputs: 0x80, MaxStackHeight: 2}},
+ err: vm.ErrInvalidMaxStackHeight,
},
{
code: []byte{
- byte(PUSH0),
- byte(RJUMPI),
+ byte(vm.PUSH0),
+ byte(vm.RJUMPI),
byte(0x00),
byte(0x01),
- byte(PUSH1),
+ byte(vm.PUSH1),
byte(0x42), // jumps to here
- byte(POP),
- byte(STOP),
+ byte(vm.POP),
+ byte(vm.STOP),
},
section: 0,
- metadata: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 1}},
- err: errInvalidJumpDest,
+ metadata: []*vm.FunctionMetadata{{Inputs: 0, Outputs: 0x80, MaxStackHeight: 1}},
+ err: vm.ErrInvalidJumpDest,
},
{
code: []byte{
- byte(PUSH0),
- byte(RJUMPV),
+ byte(vm.PUSH0),
+ byte(vm.RJUMPV),
byte(0x01),
byte(0x00),
byte(0x01),
byte(0x00),
byte(0x02),
- byte(PUSH1),
- byte(0x42), // jumps to here
- byte(POP), // and here
- byte(STOP),
+ byte(vm.PUSH1),
+ byte(0x42), // jumps to here
+ byte(vm.POP), // and here
+ byte(vm.STOP),
},
section: 0,
- metadata: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 1}},
- err: errInvalidJumpDest,
+ metadata: []*vm.FunctionMetadata{{Inputs: 0, Outputs: 0x80, MaxStackHeight: 1}},
+ err: vm.ErrInvalidJumpDest,
},
{
code: []byte{
- byte(PUSH0),
- byte(RJUMPV),
+ byte(vm.PUSH0),
+ byte(vm.RJUMPV),
byte(0x00),
- byte(STOP),
+ byte(vm.STOP),
},
section: 0,
- metadata: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 1}},
- err: errTruncatedImmediate,
+ metadata: []*vm.FunctionMetadata{{Inputs: 0, Outputs: 0x80, MaxStackHeight: 1}},
+ err: vm.ErrTruncatedImmediate,
},
{
code: []byte{
- byte(RJUMP), 0x00, 0x03,
- byte(JUMPDEST), // this code is unreachable to forward jumps alone
- byte(JUMPDEST),
- byte(RETURN),
- byte(PUSH1), 20,
- byte(PUSH1), 39,
- byte(PUSH1), 0x00,
- byte(DATACOPY),
- byte(PUSH1), 20,
- byte(PUSH1), 0x00,
- byte(RJUMP), 0xff, 0xef,
+ byte(vm.RJUMP), 0x00, 0x03,
+ byte(vm.JUMPDEST), // this code is unreachable to forward jumps alone
+ byte(vm.JUMPDEST),
+ byte(vm.RETURN),
+ byte(vm.PUSH1), 20,
+ byte(vm.PUSH1), 39,
+ byte(vm.PUSH1), 0x00,
+ byte(vm.DATACOPY),
+ byte(vm.PUSH1), 20,
+ byte(vm.PUSH1), 0x00,
+ byte(vm.RJUMP), 0xff, 0xef,
},
section: 0,
- metadata: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 3}},
- err: errUnreachableCode,
+ metadata: []*vm.FunctionMetadata{{Inputs: 0, Outputs: 0x80, MaxStackHeight: 3}},
+ err: vm.ErrUnreachableCode,
},
{
code: []byte{
- byte(PUSH1), 1,
- byte(RJUMPI), 0x00, 0x03,
- byte(JUMPDEST),
- byte(JUMPDEST),
- byte(STOP),
- byte(PUSH1), 20,
- byte(PUSH1), 39,
- byte(PUSH1), 0x00,
- byte(DATACOPY),
- byte(PUSH1), 20,
- byte(PUSH1), 0x00,
- byte(RETURN),
+ byte(vm.PUSH1), 1,
+ byte(vm.RJUMPI), 0x00, 0x03,
+ byte(vm.JUMPDEST),
+ byte(vm.JUMPDEST),
+ byte(vm.STOP),
+ byte(vm.PUSH1), 20,
+ byte(vm.PUSH1), 39,
+ byte(vm.PUSH1), 0x00,
+ byte(vm.DATACOPY),
+ byte(vm.PUSH1), 20,
+ byte(vm.PUSH1), 0x00,
+ byte(vm.RETURN),
},
section: 0,
- metadata: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 3}},
+ metadata: []*vm.FunctionMetadata{{Inputs: 0, Outputs: 0x80, MaxStackHeight: 3}},
},
{
code: []byte{
- byte(PUSH1), 1,
- byte(RJUMPV), 0x01, 0x00, 0x03, 0xff, 0xf8,
- byte(JUMPDEST),
- byte(JUMPDEST),
- byte(STOP),
- byte(PUSH1), 20,
- byte(PUSH1), 39,
- byte(PUSH1), 0x00,
- byte(DATACOPY),
- byte(PUSH1), 20,
- byte(PUSH1), 0x00,
- byte(RETURN),
+ byte(vm.PUSH1), 1,
+ byte(vm.RJUMPV), 0x01, 0x00, 0x03, 0xff, 0xf8,
+ byte(vm.JUMPDEST),
+ byte(vm.JUMPDEST),
+ byte(vm.STOP),
+ byte(vm.PUSH1), 20,
+ byte(vm.PUSH1), 39,
+ byte(vm.PUSH1), 0x00,
+ byte(vm.DATACOPY),
+ byte(vm.PUSH1), 20,
+ byte(vm.PUSH1), 0x00,
+ byte(vm.RETURN),
},
section: 0,
- metadata: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 3}},
+ metadata: []*vm.FunctionMetadata{{Inputs: 0, Outputs: 0x80, MaxStackHeight: 3}},
},
{
code: []byte{
- byte(STOP),
- byte(STOP),
- byte(INVALID),
+ byte(vm.STOP),
+ byte(vm.STOP),
+ byte(vm.INVALID),
},
section: 0,
- metadata: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 0}},
- err: errUnreachableCode,
+ metadata: []*vm.FunctionMetadata{{Inputs: 0, Outputs: 0x80, MaxStackHeight: 0}},
+ err: vm.ErrUnreachableCode,
},
{
code: []byte{
- byte(RETF),
+ byte(vm.RETF),
},
section: 0,
- metadata: []*functionMetadata{{inputs: 0, outputs: 1, maxStackHeight: 0}},
- err: errInvalidOutputs,
+ metadata: []*vm.FunctionMetadata{{Inputs: 0, Outputs: 1, MaxStackHeight: 0}},
+ err: vm.ErrInvalidOutputs,
},
{
code: []byte{
- byte(RETF),
+ byte(vm.RETF),
},
section: 0,
- metadata: []*functionMetadata{{inputs: 3, outputs: 3, maxStackHeight: 3}},
+ metadata: []*vm.FunctionMetadata{{Inputs: 3, Outputs: 3, MaxStackHeight: 3}},
},
{
code: []byte{
- byte(CALLF), 0x00, 0x01,
- byte(POP),
- byte(STOP),
+ byte(vm.CALLF), 0x00, 0x01,
+ byte(vm.POP),
+ byte(vm.STOP),
},
section: 0,
- metadata: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 1}, {inputs: 0, outputs: 1, maxStackHeight: 0}},
+ metadata: []*vm.FunctionMetadata{{Inputs: 0, Outputs: 0x80, MaxStackHeight: 1}, {Inputs: 0, Outputs: 1, MaxStackHeight: 0}},
},
{
code: []byte{
- byte(ORIGIN),
- byte(ORIGIN),
- byte(CALLF), 0x00, 0x01,
- byte(POP),
- byte(RETF),
+ byte(vm.ORIGIN),
+ byte(vm.ORIGIN),
+ byte(vm.CALLF), 0x00, 0x01,
+ byte(vm.POP),
+ byte(vm.RETF),
},
section: 0,
- metadata: []*functionMetadata{{inputs: 0, outputs: 0, maxStackHeight: 2}, {inputs: 2, outputs: 1, maxStackHeight: 2}},
+ metadata: []*vm.FunctionMetadata{{Inputs: 0, Outputs: 0, MaxStackHeight: 2}, {Inputs: 2, Outputs: 1, MaxStackHeight: 2}},
},
} {
- container := &Container{
- types: test.metadata,
- data: make([]byte, 0),
- subContainers: make([]*Container, 0),
+ container := &vm.Container{
+ Types: test.metadata,
+ Data: make([]byte, 0),
+ SubContainers: make([]*vm.Container, 0),
}
- _, err := validateCode(test.code, test.section, container, &eofInstructionSet, false)
+ _, err := vm.ValidateCode(test.code, test.section, container, &vm.EofInstructionSet, false)
if !errors.Is(err, test.err) {
t.Errorf("test %d (%s): unexpected error (want: %v, got: %v)", i, common.Bytes2Hex(test.code), test.err, err)
}
@@ -262,22 +263,22 @@ func TestValidateCode(t *testing.T) {
// For this we do a bunch of RJUMPIs that jump backwards (in a potential infinite loop).
func BenchmarkRJUMPI(b *testing.B) {
snippet := []byte{
- byte(PUSH0),
- byte(RJUMPI), 0xFF, 0xFC,
+ byte(vm.PUSH0),
+ byte(vm.RJUMPI), 0xFF, 0xFC,
}
code := []byte{}
for i := 0; i < params.MaxCodeSize/len(snippet)-1; i++ {
code = append(code, snippet...)
}
- code = append(code, byte(STOP))
- container := &Container{
- types: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 1}},
- data: make([]byte, 0),
- subContainers: make([]*Container, 0),
+ code = append(code, byte(vm.STOP))
+ container := &vm.Container{
+ Types: []*vm.FunctionMetadata{{Inputs: 0, Outputs: 0x80, MaxStackHeight: 1}},
+ Data: make([]byte, 0),
+ SubContainers: make([]*vm.Container, 0),
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
- _, err := validateCode(code, 0, container, &eofInstructionSet, false)
+ _, err := vm.ValidateCode(code, 0, container, &vm.EofInstructionSet, false)
if err != nil {
b.Fatal(err)
}
@@ -288,8 +289,8 @@ func BenchmarkRJUMPI(b *testing.B) {
// for this we set up as many RJUMPV opcodes with a full jumptable (containing 0s) as possible.
func BenchmarkRJUMPV(b *testing.B) {
snippet := []byte{
- byte(PUSH0),
- byte(RJUMPV),
+ byte(vm.PUSH0),
+ byte(vm.RJUMPV),
0xff, // count
0x00, 0x00,
}
@@ -300,16 +301,16 @@ func BenchmarkRJUMPV(b *testing.B) {
for i := 0; i < 24576/len(snippet)-1; i++ {
code = append(code, snippet...)
}
- code = append(code, byte(PUSH0))
- code = append(code, byte(STOP))
- container := &Container{
- types: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 1}},
- data: make([]byte, 0),
- subContainers: make([]*Container, 0),
+ code = append(code, byte(vm.PUSH0))
+ code = append(code, byte(vm.STOP))
+ container := &vm.Container{
+ Types: []*vm.FunctionMetadata{{Inputs: 0, Outputs: 0x80, MaxStackHeight: 1}},
+ Data: make([]byte, 0),
+ SubContainers: make([]*vm.Container, 0),
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
- _, err := validateCode(code, 0, container, &pragueInstructionSet, false)
+ _, err := vm.ValidateCode(code, 0, container, &vm.PragueInstructionSet, false)
if err != nil {
b.Fatal(err)
}
@@ -322,28 +323,28 @@ func BenchmarkRJUMPV(b *testing.B) {
// - or code to again call into 1024 code sections.
// We can't have all code sections calling each other, otherwise we would exceed 48KB.
func BenchmarkEOFValidation(b *testing.B) {
- var container Container
+ var container vm.Container
var code []byte
maxSections := 1024
for i := 0; i < maxSections; i++ {
- code = append(code, byte(CALLF))
+ code = append(code, byte(vm.CALLF))
code = binary.BigEndian.AppendUint16(code, uint16(i%(maxSections-1))+1)
}
// First container
- container.codeSections = append(container.codeSections, append(code, byte(STOP)))
- container.types = append(container.types, &functionMetadata{inputs: 0, outputs: 0x80, maxStackHeight: 0})
+ container.CodeSections = append(container.CodeSections, append(code, byte(vm.STOP)))
+ container.Types = append(container.Types, &vm.FunctionMetadata{Inputs: 0, Outputs: 0x80, MaxStackHeight: 0})
inner := []byte{
- byte(RETF),
+ byte(vm.RETF),
}
for i := 0; i < 1023; i++ {
- container.codeSections = append(container.codeSections, inner)
- container.types = append(container.types, &functionMetadata{inputs: 0, outputs: 0, maxStackHeight: 0})
+ container.CodeSections = append(container.CodeSections, inner)
+ container.Types = append(container.Types, &vm.FunctionMetadata{Inputs: 0, Outputs: 0, MaxStackHeight: 0})
}
for i := 0; i < 12; i++ {
- container.codeSections[i+1] = append(code, byte(RETF))
+ container.CodeSections[i+1] = append(code, byte(vm.RETF))
}
bin := container.MarshalBinary()
@@ -351,13 +352,13 @@ func BenchmarkEOFValidation(b *testing.B) {
b.Fatal("Exceeds 48Kb")
}
- var container2 Container
+ var container2 vm.Container
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := container2.UnmarshalBinary(bin, true); err != nil {
b.Fatal(err)
}
- if err := container2.ValidateCode(&pragueInstructionSet, false); err != nil {
+ if err := container2.ValidateCode(&vm.PragueInstructionSet, false); err != nil {
b.Fatal(err)
}
}
@@ -368,37 +369,37 @@ func BenchmarkEOFValidation(b *testing.B) {
// - contain calls to some other code sections.
// We can't have all code sections calling each other, otherwise we would exceed 48KB.
func BenchmarkEOFValidation2(b *testing.B) {
- var container Container
+ var container vm.Container
var code []byte
maxSections := 1024
for i := 0; i < maxSections; i++ {
- code = append(code, byte(CALLF))
+ code = append(code, byte(vm.CALLF))
code = binary.BigEndian.AppendUint16(code, uint16(i%(maxSections-1))+1)
}
- code = append(code, byte(STOP))
+ code = append(code, byte(vm.STOP))
// First container
- container.codeSections = append(container.codeSections, code)
- container.types = append(container.types, &functionMetadata{inputs: 0, outputs: 0x80, maxStackHeight: 0})
+ container.CodeSections = append(container.CodeSections, code)
+ container.Types = append(container.Types, &vm.FunctionMetadata{Inputs: 0, Outputs: 0x80, MaxStackHeight: 0})
inner := []byte{
- byte(CALLF), 0x03, 0xE8,
- byte(CALLF), 0x03, 0xE9,
- byte(CALLF), 0x03, 0xF0,
- byte(CALLF), 0x03, 0xF1,
- byte(CALLF), 0x03, 0xF2,
- byte(CALLF), 0x03, 0xF3,
- byte(CALLF), 0x03, 0xF4,
- byte(CALLF), 0x03, 0xF5,
- byte(CALLF), 0x03, 0xF6,
- byte(CALLF), 0x03, 0xF7,
- byte(CALLF), 0x03, 0xF8,
- byte(CALLF), 0x03, 0xF,
- byte(RETF),
+ byte(vm.CALLF), 0x03, 0xE8,
+ byte(vm.CALLF), 0x03, 0xE9,
+ byte(vm.CALLF), 0x03, 0xF0,
+ byte(vm.CALLF), 0x03, 0xF1,
+ byte(vm.CALLF), 0x03, 0xF2,
+ byte(vm.CALLF), 0x03, 0xF3,
+ byte(vm.CALLF), 0x03, 0xF4,
+ byte(vm.CALLF), 0x03, 0xF5,
+ byte(vm.CALLF), 0x03, 0xF6,
+ byte(vm.CALLF), 0x03, 0xF7,
+ byte(vm.CALLF), 0x03, 0xF8,
+ byte(vm.CALLF), 0x03, 0xF,
+ byte(vm.RETF),
}
for i := 0; i < 1023; i++ {
- container.codeSections = append(container.codeSections, inner)
- container.types = append(container.types, &functionMetadata{inputs: 0, outputs: 0, maxStackHeight: 0})
+ container.CodeSections = append(container.CodeSections, inner)
+ container.Types = append(container.Types, &vm.FunctionMetadata{Inputs: 0, Outputs: 0, MaxStackHeight: 0})
}
bin := container.MarshalBinary()
@@ -406,13 +407,13 @@ func BenchmarkEOFValidation2(b *testing.B) {
b.Fatal("Exceeds 48Kb")
}
- var container2 Container
+ var container2 vm.Container
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := container2.UnmarshalBinary(bin, true); err != nil {
b.Fatal(err)
}
- if err := container2.ValidateCode(&pragueInstructionSet, false); err != nil {
+ if err := container2.ValidateCode(&vm.PragueInstructionSet, false); err != nil {
b.Fatal(err)
}
}
@@ -424,11 +425,11 @@ func BenchmarkEOFValidation2(b *testing.B) {
// - contain calls to other code sections
// We can't have all code sections calling each other, otherwise we would exceed 48KB.
func BenchmarkEOFValidation3(b *testing.B) {
- var container Container
+ var container vm.Container
var code []byte
snippet := []byte{
- byte(PUSH0),
- byte(RJUMPV),
+ byte(vm.PUSH0),
+ byte(vm.RJUMPV),
0xff, // count
0x00, 0x00,
}
@@ -439,22 +440,22 @@ func BenchmarkEOFValidation3(b *testing.B) {
// First container, calls into all other containers
maxSections := 1024
for i := 0; i < maxSections; i++ {
- code = append(code, byte(CALLF))
+ code = append(code, byte(vm.CALLF))
code = binary.BigEndian.AppendUint16(code, uint16(i%(maxSections-1))+1)
}
- code = append(code, byte(STOP))
- container.codeSections = append(container.codeSections, code)
- container.types = append(container.types, &functionMetadata{inputs: 0, outputs: 0x80, maxStackHeight: 1})
+ code = append(code, byte(vm.STOP))
+ container.CodeSections = append(container.CodeSections, code)
+ container.Types = append(container.Types, &vm.FunctionMetadata{Inputs: 0, Outputs: 0x80, MaxStackHeight: 1})
// Other containers
for i := 0; i < 1023; i++ {
- container.codeSections = append(container.codeSections, []byte{byte(RJUMP), 0x00, 0x00, byte(RETF)})
- container.types = append(container.types, &functionMetadata{inputs: 0, outputs: 0, maxStackHeight: 0})
+ container.CodeSections = append(container.CodeSections, []byte{byte(vm.RJUMP), 0x00, 0x00, byte(vm.RETF)})
+ container.Types = append(container.Types, &vm.FunctionMetadata{Inputs: 0, Outputs: 0, MaxStackHeight: 0})
}
// Other containers
for i := 0; i < 68; i++ {
- container.codeSections[i+1] = append(snippet, byte(RETF))
- container.types[i+1] = &functionMetadata{inputs: 0, outputs: 0, maxStackHeight: 1}
+ container.CodeSections[i+1] = append(snippet, byte(vm.RETF))
+ container.Types[i+1] = &vm.FunctionMetadata{Inputs: 0, Outputs: 0, MaxStackHeight: 1}
}
bin := container.MarshalBinary()
if len(bin) > 48*1024 {
@@ -464,11 +465,11 @@ func BenchmarkEOFValidation3(b *testing.B) {
b.ReportMetric(float64(len(bin)), "bytes")
for i := 0; i < b.N; i++ {
for k := 0; k < 40; k++ {
- var container2 Container
+ var container2 vm.Container
if err := container2.UnmarshalBinary(bin, true); err != nil {
b.Fatal(err)
}
- if err := container2.ValidateCode(&pragueInstructionSet, false); err != nil {
+ if err := container2.ValidateCode(&vm.PragueInstructionSet, false); err != nil {
b.Fatal(err)
}
}
@@ -477,24 +478,24 @@ func BenchmarkEOFValidation3(b *testing.B) {
func BenchmarkRJUMPI_2(b *testing.B) {
code := []byte{
- byte(PUSH0),
- byte(RJUMPI), 0xFF, 0xFC,
+ byte(vm.PUSH0),
+ byte(vm.RJUMPI), 0xFF, 0xFC,
}
for i := 0; i < params.MaxCodeSize/4-1; i++ {
- code = append(code, byte(PUSH0))
+ code = append(code, byte(vm.PUSH0))
x := -4 * i
- code = append(code, byte(RJUMPI))
+ code = append(code, byte(vm.RJUMPI))
code = binary.BigEndian.AppendUint16(code, uint16(x))
}
- code = append(code, byte(STOP))
- container := &Container{
- types: []*functionMetadata{{inputs: 0, outputs: 0x80, maxStackHeight: 1}},
- data: make([]byte, 0),
- subContainers: make([]*Container, 0),
+ code = append(code, byte(vm.STOP))
+ container := &vm.Container{
+ Types: []*vm.FunctionMetadata{{Inputs: 0, Outputs: 0x80, MaxStackHeight: 1}},
+ Data: make([]byte, 0),
+ SubContainers: make([]*vm.Container, 0),
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
- _, err := validateCode(code, 0, container, &pragueInstructionSet, false)
+ _, err := vm.ValidateCode(code, 0, container, &vm.PragueInstructionSet, false)
if err != nil {
b.Fatal(err)
}
@@ -503,15 +504,15 @@ func BenchmarkRJUMPI_2(b *testing.B) {
func FuzzUnmarshalBinary(f *testing.F) {
f.Fuzz(func(_ *testing.T, input []byte) {
- var container Container
+ var container vm.Container
container.UnmarshalBinary(input, true)
})
}
func FuzzValidate(f *testing.F) {
f.Fuzz(func(_ *testing.T, code []byte, maxStack uint16) {
- var container Container
- container.types = append(container.types, &functionMetadata{inputs: 0, outputs: 0x80, maxStackHeight: maxStack})
- validateCode(code, 0, &container, &pragueInstructionSet, true)
+ var container vm.Container
+ container.Types = append(container.Types, &vm.FunctionMetadata{Inputs: 0, Outputs: 0x80, MaxStackHeight: maxStack})
+ vm.ValidateCode(code, 0, &container, &vm.PragueInstructionSet, true)
})
}
diff --git a/core/vm/errors.go b/core/vm/errors.go
index e33c9fcb853c..4de0d037093d 100644
--- a/core/vm/errors.go
+++ b/core/vm/errors.go
@@ -47,12 +47,12 @@ var (
// ErrStackUnderflow wraps an evm error when the items on the stack less
// than the minimal requirement.
type ErrStackUnderflow struct {
- stackLen int
- required int
+ StackLen int
+ Required int
}
func (e ErrStackUnderflow) Error() string {
- return fmt.Sprintf("stack underflow (%d <=> %d)", e.stackLen, e.required)
+ return fmt.Sprintf("stack underflow (%d <=> %d)", e.StackLen, e.Required)
}
func (e ErrStackUnderflow) Unwrap() error {
diff --git a/core/vm/evm.go b/core/vm/evm.go
index 442441e9aea8..76f3268d4c8a 100644
--- a/core/vm/evm.go
+++ b/core/vm/evm.go
@@ -22,7 +22,6 @@ import (
"sync/atomic"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
@@ -71,11 +70,11 @@ type BlockContext struct {
// All fields can change between transactions.
type TxContext struct {
// Message information
- Origin common.Address // Provides information for ORIGIN
- GasPrice *big.Int // Provides information for GASPRICE (and is used to zero the basefee if NoBaseFee is set)
- BlobHashes []common.Hash // Provides information for BLOBHASH
- BlobFeeCap *big.Int // Is used to zero the blobbasefee if NoBaseFee is set
- AccessEvents *state.AccessEvents // Capture all state accesses for this tx
+ Origin common.Address // Provides information for ORIGIN
+ GasPrice *big.Int // Provides information for GASPRICE (and is used to zero the basefee if NoBaseFee is set)
+ BlobHashes []common.Hash // Provides information for BLOBHASH
+ BlobFeeCap *big.Int // Is used to zero the blobbasefee if NoBaseFee is set
+ AccessEvents *AccessEvents // Capture all state accesses for this tx
}
// EVM is the Ethereum Virtual Machine base object and provides
@@ -133,6 +132,10 @@ func NewEVM(blockCtx BlockContext, statedb StateDB, chainConfig *params.ChainCon
return evm
}
+func (evm *EVM) GetInterpreter() *EVMInterpreter {
+ return evm.interpreter
+}
+
// SetPrecompiles sets the precompiled contracts for the EVM.
// This method is only used through RPC calls.
// It is not thread-safe.
@@ -144,7 +147,7 @@ func (evm *EVM) SetPrecompiles(precompiles PrecompiledContracts) {
// This is not threadsafe and should only be done very cautiously.
func (evm *EVM) SetTxContext(txCtx TxContext) {
if evm.chainRules.IsEIP4762 {
- txCtx.AccessEvents = state.NewAccessEvents(evm.StateDB.PointCache())
+ txCtx.AccessEvents = NewAccessEvents(evm.StateDB.PointCache())
}
evm.TxContext = txCtx
}
@@ -212,7 +215,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
evm.Context.Transfer(evm.StateDB, caller.Address(), addr, value)
if isPrecompile {
- ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer)
+ ret, gas, err = RunPrecompiledContract(p, evm, caller.Address(), caller.Address(), input, gas, value.ToBig(), evm.Config.Tracer, evm.interpreter.readOnly, false)
} else {
// Initialise a new contract and set the code that is to be used by the EVM.
// The contract is a scoped environment for this execution context only.
@@ -279,7 +282,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
// It is allowed to call precompiles, even via delegatecall
if p, isPrecompile := evm.precompile(addr); isPrecompile {
- ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer)
+ ret, gas, err = RunPrecompiledContract(p, evm, caller.Address(), caller.Address(), input, gas, value.ToBig(), evm.Config.Tracer, evm.interpreter.readOnly, true)
} else {
addrCopy := addr
// Initialise a new contract and set the code that is to be used by the EVM.
@@ -327,7 +330,10 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
// It is allowed to call precompiles, even via delegatecall
if p, isPrecompile := evm.precompile(addr); isPrecompile {
- ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer)
+ // NOTE: caller must, at all times be a contract. It should never happen
+ // that caller is something other than a Contract.
+ parent := caller.(*Contract)
+ ret, gas, err = RunPrecompiledContract(p, evm, parent.CallerAddress, caller.Address(), input, gas, nil, evm.Config.Tracer, evm.interpreter.readOnly, true)
} else {
addrCopy := addr
// Initialise a new contract and make initialise the delegate values
@@ -378,7 +384,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
evm.StateDB.AddBalance(addr, new(uint256.Int), tracing.BalanceChangeTouchAccount)
if p, isPrecompile := evm.precompile(addr); isPrecompile {
- ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer)
+ ret, gas, err = RunPrecompiledContract(p, evm, caller.Address(), caller.Address(), input, gas, nil, evm.Config.Tracer, true, false)
} else {
// At this point, we use a copy of address. If we don't, the go compiler will
// leak the 'contract' to the outer scope, and make allocation for 'contract'
@@ -596,6 +602,39 @@ func (evm *EVM) resolveCodeHash(addr common.Address) common.Hash {
return evm.StateDB.GetCodeHash(addr)
}
+func (evm *EVM) CreateWithAddress(caller ContractRef, code []byte, gas uint64, value *big.Int, address common.Address) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
+ return evm.create(caller, &codeAndHash{code: code}, gas, uint256.MustFromBig(value), address, CREATE)
+}
+
+func (evm *EVM) GetDeploymentCode(caller ContractRef, code []byte, gas uint64, value *big.Int, address common.Address) ([]byte, uint64, error) {
+ contract := NewContract(caller, AccountRef(address), uint256.MustFromBig(value), gas)
+ contract.SetCodeOptionalHash(&address, &codeAndHash{code: code})
+ ret, err := evm.interpreter.Run(contract, nil, false)
+ // Check whether the max code size has been exceeded, assign err if the case.
+ if err == nil && evm.chainRules.IsEIP158 && len(ret) > params.MaxCodeSize {
+ err = ErrMaxCodeSizeExceeded
+ }
+ // Reject code starting with 0xEF if EIP-3541 is enabled.
+ if err == nil && len(ret) >= 1 && ret[0] == 0xEF && evm.chainRules.IsLondon {
+ err = ErrInvalidCode
+ }
+ if err == nil {
+ createDataGas := uint64(len(ret)) * params.CreateDataGas
+ if !contract.UseGas(createDataGas, evm.Config.Tracer, tracing.GasChangeCallCodeStorage) {
+ err = ErrCodeStoreOutOfGas
+ }
+ }
+ // When an error was returned by the EVM or when setting the creation code
+ // above we revert to the snapshot and consume any gas remaining. Additionally,
+ // when we're in homestead this also counts for code storage gas errors.
+ if err != nil && (evm.chainRules.IsHomestead || err != ErrCodeStoreOutOfGas) {
+ if err != ErrExecutionReverted {
+ contract.UseGas(contract.Gas, evm.Config.Tracer, tracing.GasChangeCallFailedExecution)
+ }
+ }
+ return ret, contract.Gas, err
+}
+
// ChainConfig returns the environment's chain configuration
func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig }
diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go
index 55855727b527..c98318f42a79 100644
--- a/core/vm/gas_table.go
+++ b/core/vm/gas_table.go
@@ -25,9 +25,9 @@ import (
"github.com/ethereum/go-ethereum/params"
)
-// memoryGasCost calculates the quadratic gas for memory expansion. It does so
+// MemoryGasCost calculates the quadratic gas for memory expansion. It does so
// only for the memory region that is expanded, not the total memory.
-func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) {
+func MemoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) {
if newMemSize == 0 {
return 0, nil
}
@@ -39,7 +39,7 @@ func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) {
if newMemSize > 0x1FFFFFFFE0 {
return 0, ErrGasUintOverflow
}
- newMemSizeWords := toWordSize(newMemSize)
+ newMemSizeWords := ToWordSize(newMemSize)
newMemSize = newMemSizeWords * 32
if newMemSize > uint64(mem.Len()) {
@@ -67,7 +67,7 @@ func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) {
func memoryCopierGas(stackpos int) gasFunc {
return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
// Gas for expanding the memory
- gas, err := memoryGasCost(mem, memorySize)
+ gas, err := MemoryGasCost(mem, memorySize)
if err != nil {
return 0, err
}
@@ -77,7 +77,7 @@ func memoryCopierGas(stackpos int) gasFunc {
return 0, ErrGasUintOverflow
}
- if words, overflow = math.SafeMul(toWordSize(words), params.CopyGas); overflow {
+ if words, overflow = math.SafeMul(ToWordSize(words), params.CopyGas); overflow {
return 0, ErrGasUintOverflow
}
@@ -91,7 +91,7 @@ func memoryCopierGas(stackpos int) gasFunc {
var (
gasCallDataCopy = memoryCopierGas(2)
gasCodeCopy = memoryCopierGas(2)
- gasMcopy = memoryCopierGas(2)
+ GasMcopy = memoryCopierGas(2)
gasExtCodeCopy = memoryCopierGas(3)
gasReturnDataCopy = memoryCopierGas(2)
)
@@ -230,7 +230,7 @@ func makeGasLog(n uint64) gasFunc {
return 0, ErrGasUintOverflow
}
- gas, err := memoryGasCost(mem, memorySize)
+ gas, err := MemoryGasCost(mem, memorySize)
if err != nil {
return 0, err
}
@@ -254,7 +254,7 @@ func makeGasLog(n uint64) gasFunc {
}
func gasKeccak256(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- gas, err := memoryGasCost(mem, memorySize)
+ gas, err := MemoryGasCost(mem, memorySize)
if err != nil {
return 0, err
}
@@ -262,7 +262,7 @@ func gasKeccak256(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memor
if overflow {
return 0, ErrGasUintOverflow
}
- if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.Keccak256WordGas); overflow {
+ if wordGas, overflow = math.SafeMul(ToWordSize(wordGas), params.Keccak256WordGas); overflow {
return 0, ErrGasUintOverflow
}
if gas, overflow = math.SafeAdd(gas, wordGas); overflow {
@@ -275,7 +275,7 @@ func gasKeccak256(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memor
// static cost have a dynamic cost which is solely based on the memory
// expansion
func pureMemoryGascost(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- return memoryGasCost(mem, memorySize)
+ return MemoryGasCost(mem, memorySize)
}
var (
@@ -288,7 +288,7 @@ var (
)
func gasCreate2(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- gas, err := memoryGasCost(mem, memorySize)
+ gas, err := MemoryGasCost(mem, memorySize)
if err != nil {
return 0, err
}
@@ -296,7 +296,7 @@ func gasCreate2(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memoryS
if overflow {
return 0, ErrGasUintOverflow
}
- if wordGas, overflow = math.SafeMul(toWordSize(wordGas), params.Keccak256WordGas); overflow {
+ if wordGas, overflow = math.SafeMul(ToWordSize(wordGas), params.Keccak256WordGas); overflow {
return 0, ErrGasUintOverflow
}
if gas, overflow = math.SafeAdd(gas, wordGas); overflow {
@@ -306,7 +306,7 @@ func gasCreate2(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memoryS
}
func gasCreateEip3860(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- gas, err := memoryGasCost(mem, memorySize)
+ gas, err := MemoryGasCost(mem, memorySize)
if err != nil {
return 0, err
}
@@ -325,7 +325,7 @@ func gasCreateEip3860(evm *EVM, contract *Contract, stack *Stack, mem *Memory, m
return gas, nil
}
func gasCreate2Eip3860(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- gas, err := memoryGasCost(mem, memorySize)
+ gas, err := MemoryGasCost(mem, memorySize)
if err != nil {
return 0, err
}
@@ -345,7 +345,7 @@ func gasCreate2Eip3860(evm *EVM, contract *Contract, stack *Stack, mem *Memory,
}
func gasExpFrontier(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- expByteLen := uint64((stack.data[stack.len()-2].BitLen() + 7) / 8)
+ expByteLen := uint64((stack.data[stack.Len()-2].BitLen() + 7) / 8)
var (
gas = expByteLen * params.ExpByteFrontier // no overflow check required. Max is 256 * ExpByte gas
@@ -358,7 +358,7 @@ func gasExpFrontier(evm *EVM, contract *Contract, stack *Stack, mem *Memory, mem
}
func gasExpEIP158(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- expByteLen := uint64((stack.data[stack.len()-2].BitLen() + 7) / 8)
+ expByteLen := uint64((stack.data[stack.Len()-2].BitLen() + 7) / 8)
var (
gas = expByteLen * params.ExpByteEIP158 // no overflow check required. Max is 256 * ExpByte gas
@@ -386,7 +386,7 @@ func gasCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize
if transfersValue && !evm.chainRules.IsEIP4762 {
gas += params.CallValueTransferGas
}
- memoryGas, err := memoryGasCost(mem, memorySize)
+ memoryGas, err := MemoryGasCost(mem, memorySize)
if err != nil {
return 0, err
}
@@ -414,7 +414,7 @@ func gasCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize
}
func gasCallCode(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- memoryGas, err := memoryGasCost(mem, memorySize)
+ memoryGas, err := MemoryGasCost(mem, memorySize)
if err != nil {
return 0, err
}
@@ -449,7 +449,7 @@ func gasCallCode(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memory
}
func gasDelegateCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- gas, err := memoryGasCost(mem, memorySize)
+ gas, err := MemoryGasCost(mem, memorySize)
if err != nil {
return 0, err
}
@@ -465,7 +465,7 @@ func gasDelegateCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, me
}
func gasStaticCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- gas, err := memoryGasCost(mem, memorySize)
+ gas, err := MemoryGasCost(mem, memorySize)
if err != nil {
return 0, err
}
diff --git a/core/vm/gas_table_test.go b/core/vm/gas_table_test.go
index be8688526193..0d72f1ba12ac 100644
--- a/core/vm/gas_table_test.go
+++ b/core/vm/gas_table_test.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-package vm
+package vm_test
import (
"bytes"
@@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
"github.com/holiman/uint256"
)
@@ -42,9 +43,9 @@ func TestMemoryGasCost(t *testing.T) {
{0x1fffffffe1, 0, true},
}
for i, tt := range tests {
- v, err := memoryGasCost(&Memory{}, tt.size)
- if (err == ErrGasUintOverflow) != tt.overflow {
- t.Errorf("test %d: overflow mismatch: have %v, want %v", i, err == ErrGasUintOverflow, tt.overflow)
+ v, err := vm.MemoryGasCost(&vm.Memory{}, tt.size)
+ if (err == vm.ErrGasUintOverflow) != tt.overflow {
+ t.Errorf("test %d: overflow mismatch: have %v, want %v", i, err == vm.ErrGasUintOverflow, tt.overflow)
}
if v != tt.cost {
t.Errorf("test %d: gas cost mismatch: have %v, want %v", i, v, tt.cost)
@@ -77,7 +78,7 @@ var eip2200Tests = []struct {
{1, math.MaxUint64, "0x60016000556001600055", 1612, 0, nil}, // 1 -> 1 -> 1
{0, math.MaxUint64, "0x600160005560006000556001600055", 40818, 19200, nil}, // 0 -> 1 -> 0 -> 1
{1, math.MaxUint64, "0x600060005560016000556000600055", 10818, 19200, nil}, // 1 -> 0 -> 1 -> 0
- {1, 2306, "0x6001600055", 2306, 0, ErrOutOfGas}, // 1 -> 1 (2300 sentry + 2xPUSH)
+ {1, 2306, "0x6001600055", 2306, 0, vm.ErrOutOfGas}, // 1 -> 1 (2300 sentry + 2xPUSH)
{1, 2307, "0x6001600055", 806, 0, nil}, // 1 -> 1 (2301 sentry + 2xPUSH)
}
@@ -91,13 +92,13 @@ func TestEIP2200(t *testing.T) {
statedb.SetState(address, common.Hash{}, common.BytesToHash([]byte{tt.original}))
statedb.Finalise(true) // Push the state into the "original" slot
- vmctx := BlockContext{
- CanTransfer: func(StateDB, common.Address, *uint256.Int) bool { return true },
- Transfer: func(StateDB, common.Address, common.Address, *uint256.Int) {},
+ vmctx := vm.BlockContext{
+ CanTransfer: func(vm.StateDB, common.Address, *uint256.Int) bool { return true },
+ Transfer: func(vm.StateDB, common.Address, common.Address, *uint256.Int) {},
}
- evm := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}})
+ evm := vm.NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, vm.Config{ExtraEips: []int{2200}})
- _, gas, err := evm.Call(AccountRef(common.Address{}), address, nil, tt.gaspool, new(uint256.Int))
+ _, gas, err := evm.Call(vm.AccountRef(common.Address{}), address, nil, tt.gaspool, new(uint256.Int))
if !errors.Is(err, tt.failure) {
t.Errorf("test %d: failure mismatch: have %v, want %v", i, err, tt.failure)
}
@@ -141,19 +142,19 @@ func TestCreateGas(t *testing.T) {
statedb.CreateAccount(address)
statedb.SetCode(address, hexutil.MustDecode(tt.code))
statedb.Finalise(true)
- vmctx := BlockContext{
- CanTransfer: func(StateDB, common.Address, *uint256.Int) bool { return true },
- Transfer: func(StateDB, common.Address, common.Address, *uint256.Int) {},
+ vmctx := vm.BlockContext{
+ CanTransfer: func(vm.StateDB, common.Address, *uint256.Int) bool { return true },
+ Transfer: func(vm.StateDB, common.Address, common.Address, *uint256.Int) {},
BlockNumber: big.NewInt(0),
}
- config := Config{}
+ config := vm.Config{}
if tt.eip3860 {
config.ExtraEips = []int{3860}
}
- evm := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, config)
+ evm := vm.NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, config)
var startGas = uint64(testGas)
- ret, gas, err := evm.Call(AccountRef(common.Address{}), address, nil, startGas, new(uint256.Int))
+ ret, gas, err := evm.Call(vm.AccountRef(common.Address{}), address, nil, startGas, new(uint256.Int))
if err != nil {
return false
}
diff --git a/core/vm/instructions.go b/core/vm/instructions.go
index c9eea335070d..4f9e83a7fbd1 100644
--- a/core/vm/instructions.go
+++ b/core/vm/instructions.go
@@ -27,68 +27,68 @@ import (
"github.com/holiman/uint256"
)
-func opAdd(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- x, y := scope.Stack.pop(), scope.Stack.peek()
+func OpAdd(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
y.Add(&x, y)
return nil, nil
}
-func opSub(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- x, y := scope.Stack.pop(), scope.Stack.peek()
+func OpSub(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
y.Sub(&x, y)
return nil, nil
}
-func opMul(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- x, y := scope.Stack.pop(), scope.Stack.peek()
+func OpMul(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
y.Mul(&x, y)
return nil, nil
}
-func opDiv(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- x, y := scope.Stack.pop(), scope.Stack.peek()
+func OpDiv(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
y.Div(&x, y)
return nil, nil
}
-func opSdiv(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- x, y := scope.Stack.pop(), scope.Stack.peek()
+func OpSdiv(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
y.SDiv(&x, y)
return nil, nil
}
-func opMod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- x, y := scope.Stack.pop(), scope.Stack.peek()
+func OpMod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
y.Mod(&x, y)
return nil, nil
}
-func opSmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- x, y := scope.Stack.pop(), scope.Stack.peek()
+func OpSmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
y.SMod(&x, y)
return nil, nil
}
-func opExp(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- base, exponent := scope.Stack.pop(), scope.Stack.peek()
+func OpExp(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ base, exponent := scope.Stack.Pop(), scope.Stack.Peek()
exponent.Exp(&base, exponent)
return nil, nil
}
-func opSignExtend(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- back, num := scope.Stack.pop(), scope.Stack.peek()
+func OpSignExtend(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ back, num := scope.Stack.Pop(), scope.Stack.Peek()
num.ExtendSign(num, &back)
return nil, nil
}
func opNot(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- x := scope.Stack.peek()
+ x := scope.Stack.Peek()
x.Not(x)
return nil, nil
}
-func opLt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- x, y := scope.Stack.pop(), scope.Stack.peek()
+func OpLt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
if x.Lt(y) {
y.SetOne()
} else {
@@ -97,8 +97,8 @@ func opLt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte,
return nil, nil
}
-func opGt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- x, y := scope.Stack.pop(), scope.Stack.peek()
+func OpGt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
if x.Gt(y) {
y.SetOne()
} else {
@@ -107,8 +107,8 @@ func opGt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte,
return nil, nil
}
-func opSlt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- x, y := scope.Stack.pop(), scope.Stack.peek()
+func OpSlt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
if x.Slt(y) {
y.SetOne()
} else {
@@ -117,8 +117,8 @@ func opSlt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte
return nil, nil
}
-func opSgt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- x, y := scope.Stack.pop(), scope.Stack.peek()
+func OpSgt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
if x.Sgt(y) {
y.SetOne()
} else {
@@ -127,8 +127,8 @@ func opSgt(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte
return nil, nil
}
-func opEq(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- x, y := scope.Stack.pop(), scope.Stack.peek()
+func OpEq(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
if x.Eq(y) {
y.SetOne()
} else {
@@ -137,8 +137,8 @@ func opEq(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte,
return nil, nil
}
-func opIszero(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- x := scope.Stack.peek()
+func OpIszero(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x := scope.Stack.Peek()
if x.IsZero() {
x.SetOne()
} else {
@@ -147,48 +147,48 @@ func opIszero(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b
return nil, nil
}
-func opAnd(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- x, y := scope.Stack.pop(), scope.Stack.peek()
+func OpAnd(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
y.And(&x, y)
return nil, nil
}
-func opOr(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- x, y := scope.Stack.pop(), scope.Stack.peek()
+func OpOr(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
y.Or(&x, y)
return nil, nil
}
-func opXor(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- x, y := scope.Stack.pop(), scope.Stack.peek()
+func OpXor(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y := scope.Stack.Pop(), scope.Stack.Peek()
y.Xor(&x, y)
return nil, nil
}
-func opByte(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- th, val := scope.Stack.pop(), scope.Stack.peek()
+func OpByte(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ th, val := scope.Stack.Pop(), scope.Stack.Peek()
val.Byte(&th)
return nil, nil
}
-func opAddmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- x, y, z := scope.Stack.pop(), scope.Stack.pop(), scope.Stack.peek()
+func OpAddmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y, z := scope.Stack.Pop(), scope.Stack.Pop(), scope.Stack.Peek()
z.AddMod(&x, &y, z)
return nil, nil
}
-func opMulmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- x, y, z := scope.Stack.pop(), scope.Stack.pop(), scope.Stack.peek()
+func OpMulmod(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ x, y, z := scope.Stack.Pop(), scope.Stack.Pop(), scope.Stack.Peek()
z.MulMod(&x, &y, z)
return nil, nil
}
-// opSHL implements Shift Left
+// OpSHL implements Shift Left
// The SHL instruction (shift left) pops 2 values from the stack, first arg1 and then arg2,
// and pushes on the stack arg2 shifted to the left by arg1 number of bits.
-func opSHL(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+func OpSHL(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
// Note, second operand is left in the stack; accumulate result into it, and no need to push it afterwards
- shift, value := scope.Stack.pop(), scope.Stack.peek()
+ shift, value := scope.Stack.Pop(), scope.Stack.Peek()
if shift.LtUint64(256) {
value.Lsh(value, uint(shift.Uint64()))
} else {
@@ -197,12 +197,12 @@ func opSHL(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte
return nil, nil
}
-// opSHR implements Logical Shift Right
+// OpSHR implements Logical Shift Right
// The SHR instruction (logical shift right) pops 2 values from the stack, first arg1 and then arg2,
// and pushes on the stack arg2 shifted to the right by arg1 number of bits with zero fill.
-func opSHR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+func OpSHR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
// Note, second operand is left in the stack; accumulate result into it, and no need to push it afterwards
- shift, value := scope.Stack.pop(), scope.Stack.peek()
+ shift, value := scope.Stack.Pop(), scope.Stack.Peek()
if shift.LtUint64(256) {
value.Rsh(value, uint(shift.Uint64()))
} else {
@@ -211,11 +211,11 @@ func opSHR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte
return nil, nil
}
-// opSAR implements Arithmetic Shift Right
+// OpSAR implements Arithmetic Shift Right
// The SAR instruction (arithmetic shift right) pops 2 values from the stack, first arg1 and then arg2,
// and pushes on the stack arg2 shifted to the right by arg1 number of bits with sign extension.
-func opSAR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- shift, value := scope.Stack.pop(), scope.Stack.peek()
+func OpSAR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ shift, value := scope.Stack.Pop(), scope.Stack.Peek()
if shift.GtUint64(256) {
if value.Sign() >= 0 {
value.Clear()
@@ -230,8 +230,8 @@ func opSAR(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte
return nil, nil
}
-func opKeccak256(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- offset, size := scope.Stack.pop(), scope.Stack.peek()
+func OpKeccak256(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ offset, size := scope.Stack.Pop(), scope.Stack.Peek()
data := scope.Memory.GetPtr(offset.Uint64(), size.Uint64())
if interpreter.hasher == nil {
@@ -250,35 +250,35 @@ func opKeccak256(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) (
return nil, nil
}
-func opAddress(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- scope.Stack.push(new(uint256.Int).SetBytes(scope.Contract.Address().Bytes()))
+func OpAddress(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ scope.Stack.Push(new(uint256.Int).SetBytes(scope.Contract.Address().Bytes()))
return nil, nil
}
func opBalance(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- slot := scope.Stack.peek()
+ slot := scope.Stack.Peek()
address := common.Address(slot.Bytes20())
slot.Set(interpreter.evm.StateDB.GetBalance(address))
return nil, nil
}
-func opOrigin(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- scope.Stack.push(new(uint256.Int).SetBytes(interpreter.evm.Origin.Bytes()))
+func OpOrigin(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ scope.Stack.Push(new(uint256.Int).SetBytes(interpreter.evm.Origin.Bytes()))
return nil, nil
}
func opCaller(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- scope.Stack.push(new(uint256.Int).SetBytes(scope.Contract.Caller().Bytes()))
+ scope.Stack.Push(new(uint256.Int).SetBytes(scope.Contract.Caller().Bytes()))
return nil, nil
}
func opCallValue(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- scope.Stack.push(scope.Contract.value)
+ scope.Stack.Push(scope.Contract.value)
return nil, nil
}
func opCallDataLoad(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- x := scope.Stack.peek()
+ x := scope.Stack.Peek()
if offset, overflow := x.Uint64WithOverflow(); !overflow {
data := getData(scope.Contract.Input, offset, 32)
x.SetBytes(data)
@@ -289,15 +289,15 @@ func opCallDataLoad(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
}
func opCallDataSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- scope.Stack.push(new(uint256.Int).SetUint64(uint64(len(scope.Contract.Input))))
+ scope.Stack.Push(new(uint256.Int).SetUint64(uint64(len(scope.Contract.Input))))
return nil, nil
}
func opCallDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
var (
- memOffset = scope.Stack.pop()
- dataOffset = scope.Stack.pop()
- length = scope.Stack.pop()
+ memOffset = scope.Stack.Pop()
+ dataOffset = scope.Stack.Pop()
+ length = scope.Stack.Pop()
)
dataOffset64, overflow := dataOffset.Uint64WithOverflow()
if overflow {
@@ -312,15 +312,15 @@ func opCallDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
}
func opReturnDataSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- scope.Stack.push(new(uint256.Int).SetUint64(uint64(len(interpreter.returnData))))
+ scope.Stack.Push(new(uint256.Int).SetUint64(uint64(len(interpreter.returnData))))
return nil, nil
}
func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
var (
- memOffset = scope.Stack.pop()
- dataOffset = scope.Stack.pop()
- length = scope.Stack.pop()
+ memOffset = scope.Stack.Pop()
+ dataOffset = scope.Stack.Pop()
+ length = scope.Stack.Pop()
)
offset64, overflow := dataOffset.Uint64WithOverflow()
@@ -339,21 +339,21 @@ func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeConte
}
func opExtCodeSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- slot := scope.Stack.peek()
+ slot := scope.Stack.Peek()
slot.SetUint64(uint64(interpreter.evm.StateDB.GetCodeSize(slot.Bytes20())))
return nil, nil
}
func opCodeSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- scope.Stack.push(new(uint256.Int).SetUint64(uint64(len(scope.Contract.Code))))
+ scope.Stack.Push(new(uint256.Int).SetUint64(uint64(len(scope.Contract.Code))))
return nil, nil
}
func opCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
var (
- memOffset = scope.Stack.pop()
- codeOffset = scope.Stack.pop()
- length = scope.Stack.pop()
+ memOffset = scope.Stack.Pop()
+ codeOffset = scope.Stack.Pop()
+ length = scope.Stack.Pop()
)
uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow()
if overflow {
@@ -368,10 +368,10 @@ func opCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
var (
stack = scope.Stack
- a = stack.pop()
- memOffset = stack.pop()
- codeOffset = stack.pop()
- length = stack.pop()
+ a = stack.Pop()
+ memOffset = stack.Pop()
+ codeOffset = stack.Pop()
+ length = stack.Pop()
)
uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow()
if overflow {
@@ -412,7 +412,7 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
// 6. Caller tries to get the code hash for an account which is marked as deleted, this
// account should be regarded as a non-existent account and zero should be returned.
func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- slot := scope.Stack.peek()
+ slot := scope.Stack.Peek()
address := common.Address(slot.Bytes20())
if interpreter.evm.StateDB.Empty(address) {
slot.Clear()
@@ -424,12 +424,12 @@ func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
func opGasprice(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
v, _ := uint256.FromBig(interpreter.evm.GasPrice)
- scope.Stack.push(v)
+ scope.Stack.Push(v)
return nil, nil
}
func opBlockhash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- num := scope.Stack.peek()
+ num := scope.Stack.Peek()
num64, overflow := num.Uint64WithOverflow()
if overflow {
num.Clear()
@@ -459,64 +459,64 @@ func opBlockhash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) (
}
func opCoinbase(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- scope.Stack.push(new(uint256.Int).SetBytes(interpreter.evm.Context.Coinbase.Bytes()))
+ scope.Stack.Push(new(uint256.Int).SetBytes(interpreter.evm.Context.Coinbase.Bytes()))
return nil, nil
}
func opTimestamp(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- scope.Stack.push(new(uint256.Int).SetUint64(interpreter.evm.Context.Time))
+ scope.Stack.Push(new(uint256.Int).SetUint64(interpreter.evm.Context.Time))
return nil, nil
}
func opNumber(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
v, _ := uint256.FromBig(interpreter.evm.Context.BlockNumber)
- scope.Stack.push(v)
+ scope.Stack.Push(v)
return nil, nil
}
func opDifficulty(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
v, _ := uint256.FromBig(interpreter.evm.Context.Difficulty)
- scope.Stack.push(v)
+ scope.Stack.Push(v)
return nil, nil
}
-func opRandom(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+func OpRandom(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
v := new(uint256.Int).SetBytes(interpreter.evm.Context.Random.Bytes())
- scope.Stack.push(v)
+ scope.Stack.Push(v)
return nil, nil
}
func opGasLimit(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- scope.Stack.push(new(uint256.Int).SetUint64(interpreter.evm.Context.GasLimit))
+ scope.Stack.Push(new(uint256.Int).SetUint64(interpreter.evm.Context.GasLimit))
return nil, nil
}
func opPop(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- scope.Stack.pop()
+ scope.Stack.Pop()
return nil, nil
}
func opMload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- v := scope.Stack.peek()
+ v := scope.Stack.Peek()
offset := v.Uint64()
v.SetBytes(scope.Memory.GetPtr(offset, 32))
return nil, nil
}
-func opMstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- mStart, val := scope.Stack.pop(), scope.Stack.pop()
+func OpMstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ mStart, val := scope.Stack.Pop(), scope.Stack.Pop()
scope.Memory.Set32(mStart.Uint64(), &val)
return nil, nil
}
-func opMstore8(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- off, val := scope.Stack.pop(), scope.Stack.pop()
+func OpMstore8(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
+ off, val := scope.Stack.Pop(), scope.Stack.Pop()
scope.Memory.store[off.Uint64()] = byte(val.Uint64())
return nil, nil
}
func opSload(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- loc := scope.Stack.peek()
+ loc := scope.Stack.Peek()
hash := common.Hash(loc.Bytes32())
val := interpreter.evm.StateDB.GetState(scope.Contract.Address(), hash)
loc.SetBytes(val.Bytes())
@@ -527,8 +527,8 @@ func opSstore(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b
if interpreter.readOnly {
return nil, ErrWriteProtection
}
- loc := scope.Stack.pop()
- val := scope.Stack.pop()
+ loc := scope.Stack.Pop()
+ val := scope.Stack.Pop()
interpreter.evm.StateDB.SetState(scope.Contract.Address(), loc.Bytes32(), val.Bytes32())
return nil, nil
}
@@ -537,7 +537,7 @@ func opJump(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byt
if interpreter.evm.abort.Load() {
return nil, errStopToken
}
- pos := scope.Stack.pop()
+ pos := scope.Stack.Pop()
if !scope.Contract.validJumpdest(&pos) {
return nil, ErrInvalidJump
}
@@ -549,7 +549,7 @@ func opJumpi(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by
if interpreter.evm.abort.Load() {
return nil, errStopToken
}
- pos, cond := scope.Stack.pop(), scope.Stack.pop()
+ pos, cond := scope.Stack.Pop(), scope.Stack.Pop()
if !cond.IsZero() {
if !scope.Contract.validJumpdest(&pos) {
return nil, ErrInvalidJump
@@ -564,17 +564,17 @@ func opJumpdest(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
}
func opPc(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- scope.Stack.push(new(uint256.Int).SetUint64(*pc))
+ scope.Stack.Push(new(uint256.Int).SetUint64(*pc))
return nil, nil
}
func opMsize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- scope.Stack.push(new(uint256.Int).SetUint64(uint64(scope.Memory.Len())))
+ scope.Stack.Push(new(uint256.Int).SetUint64(uint64(scope.Memory.Len())))
return nil, nil
}
func opGas(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- scope.Stack.push(new(uint256.Int).SetUint64(scope.Contract.Gas))
+ scope.Stack.Push(new(uint256.Int).SetUint64(scope.Contract.Gas))
return nil, nil
}
@@ -663,8 +663,8 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b
return nil, ErrWriteProtection
}
var (
- value = scope.Stack.pop()
- offset, size = scope.Stack.pop(), scope.Stack.pop()
+ value = scope.Stack.Pop()
+ offset, size = scope.Stack.Pop(), scope.Stack.Pop()
input = scope.Memory.GetCopy(offset.Uint64(), size.Uint64())
gas = scope.Contract.Gas
)
@@ -689,7 +689,7 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b
} else {
stackvalue.SetBytes(addr.Bytes())
}
- scope.Stack.push(&stackvalue)
+ scope.Stack.Push(&stackvalue)
scope.Contract.RefundGas(returnGas, interpreter.evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
@@ -706,9 +706,9 @@ func opCreate2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]
return nil, ErrWriteProtection
}
var (
- endowment = scope.Stack.pop()
- offset, size = scope.Stack.pop(), scope.Stack.pop()
- salt = scope.Stack.pop()
+ endowment = scope.Stack.Pop()
+ offset, size = scope.Stack.Pop(), scope.Stack.Pop()
+ salt = scope.Stack.Pop()
input = scope.Memory.GetCopy(offset.Uint64(), size.Uint64())
gas = scope.Contract.Gas
)
@@ -726,7 +726,7 @@ func opCreate2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]
} else {
stackvalue.SetBytes(addr.Bytes())
}
- scope.Stack.push(&stackvalue)
+ scope.Stack.Push(&stackvalue)
scope.Contract.RefundGas(returnGas, interpreter.evm.Config.Tracer, tracing.GasChangeCallLeftOverRefunded)
if suberr == ErrExecutionReverted {
@@ -741,10 +741,10 @@ func opCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byt
stack := scope.Stack
// Pop gas. The actual gas in interpreter.evm.callGasTemp.
// We can use this as a temporary value
- temp := stack.pop()
+ temp := stack.Pop()
gas := interpreter.evm.callGasTemp
// Pop other call parameters.
- addr, value, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
+ addr, value, inOffset, inSize, retOffset, retSize := stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop()
toAddr := common.Address(addr.Bytes20())
// Get the arguments from the memory.
args := scope.Memory.GetPtr(inOffset.Uint64(), inSize.Uint64())
@@ -762,7 +762,7 @@ func opCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byt
} else {
temp.SetOne()
}
- stack.push(&temp)
+ stack.Push(&temp)
if err == nil || err == ErrExecutionReverted {
scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
}
@@ -777,10 +777,10 @@ func opCallCode(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
// Pop gas. The actual gas is in interpreter.evm.callGasTemp.
stack := scope.Stack
// We use it as a temporary value
- temp := stack.pop()
+ temp := stack.Pop()
gas := interpreter.evm.callGasTemp
// Pop other call parameters.
- addr, value, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
+ addr, value, inOffset, inSize, retOffset, retSize := stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop()
toAddr := common.Address(addr.Bytes20())
// Get arguments from the memory.
args := scope.Memory.GetPtr(inOffset.Uint64(), inSize.Uint64())
@@ -795,7 +795,7 @@ func opCallCode(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
} else {
temp.SetOne()
}
- stack.push(&temp)
+ stack.Push(&temp)
if err == nil || err == ErrExecutionReverted {
scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
}
@@ -810,10 +810,10 @@ func opDelegateCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
stack := scope.Stack
// Pop gas. The actual gas is in interpreter.evm.callGasTemp.
// We use it as a temporary value
- temp := stack.pop()
+ temp := stack.Pop()
gas := interpreter.evm.callGasTemp
// Pop other call parameters.
- addr, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
+ addr, inOffset, inSize, retOffset, retSize := stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop()
toAddr := common.Address(addr.Bytes20())
// Get arguments from the memory.
args := scope.Memory.GetPtr(inOffset.Uint64(), inSize.Uint64())
@@ -824,7 +824,7 @@ func opDelegateCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
} else {
temp.SetOne()
}
- stack.push(&temp)
+ stack.Push(&temp)
if err == nil || err == ErrExecutionReverted {
scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
}
@@ -839,10 +839,10 @@ func opStaticCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
// Pop gas. The actual gas is in interpreter.evm.callGasTemp.
stack := scope.Stack
// We use it as a temporary value
- temp := stack.pop()
+ temp := stack.Pop()
gas := interpreter.evm.callGasTemp
// Pop other call parameters.
- addr, inOffset, inSize, retOffset, retSize := stack.pop(), stack.pop(), stack.pop(), stack.pop(), stack.pop()
+ addr, inOffset, inSize, retOffset, retSize := stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop()
toAddr := common.Address(addr.Bytes20())
// Get arguments from the memory.
args := scope.Memory.GetPtr(inOffset.Uint64(), inSize.Uint64())
@@ -853,7 +853,7 @@ func opStaticCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
} else {
temp.SetOne()
}
- stack.push(&temp)
+ stack.Push(&temp)
if err == nil || err == ErrExecutionReverted {
scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
}
@@ -865,14 +865,14 @@ func opStaticCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
}
func opReturn(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- offset, size := scope.Stack.pop(), scope.Stack.pop()
+ offset, size := scope.Stack.Pop(), scope.Stack.Pop()
ret := scope.Memory.GetCopy(offset.Uint64(), size.Uint64())
return ret, errStopToken
}
func opRevert(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
- offset, size := scope.Stack.pop(), scope.Stack.pop()
+ offset, size := scope.Stack.Pop(), scope.Stack.Pop()
ret := scope.Memory.GetCopy(offset.Uint64(), size.Uint64())
interpreter.returnData = ret
@@ -891,7 +891,7 @@ func opSelfdestruct(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
if interpreter.readOnly {
return nil, ErrWriteProtection
}
- beneficiary := scope.Stack.pop()
+ beneficiary := scope.Stack.Pop()
balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address())
interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance, tracing.BalanceIncreaseSelfdestruct)
interpreter.evm.StateDB.SelfDestruct(scope.Contract.Address())
@@ -910,7 +910,7 @@ func opSelfdestruct6780(pc *uint64, interpreter *EVMInterpreter, scope *ScopeCon
if interpreter.readOnly {
return nil, ErrWriteProtection
}
- beneficiary := scope.Stack.pop()
+ beneficiary := scope.Stack.Pop()
balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address())
interpreter.evm.StateDB.SubBalance(scope.Contract.Address(), balance, tracing.BalanceDecreaseSelfdestruct)
interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance, tracing.BalanceIncreaseSelfdestruct)
@@ -929,16 +929,16 @@ func opSelfdestruct6780(pc *uint64, interpreter *EVMInterpreter, scope *ScopeCon
// following functions are used by the instruction jump table
// make log instruction function
-func makeLog(size int) executionFunc {
+func makeLog(size int) ExecutionFunc {
return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
if interpreter.readOnly {
return nil, ErrWriteProtection
}
topics := make([]common.Hash, size)
stack := scope.Stack
- mStart, mSize := stack.pop(), stack.pop()
+ mStart, mSize := stack.Pop(), stack.Pop()
for i := 0; i < size; i++ {
- addr := stack.pop()
+ addr := stack.Pop()
topics[i] = addr.Bytes32()
}
@@ -964,15 +964,15 @@ func opPush1(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by
)
*pc += 1
if *pc < codeLen {
- scope.Stack.push(integer.SetUint64(uint64(scope.Contract.Code[*pc])))
+ scope.Stack.Push(integer.SetUint64(uint64(scope.Contract.Code[*pc])))
} else {
- scope.Stack.push(integer.Clear())
+ scope.Stack.Push(integer.Clear())
}
return nil, nil
}
// make push instruction function
-func makePush(size uint64, pushByteSize int) executionFunc {
+func MakePush(size uint64, pushByteSize int) ExecutionFunc {
return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
var (
codeLen = len(scope.Contract.Code)
@@ -985,14 +985,14 @@ func makePush(size uint64, pushByteSize int) executionFunc {
if missing := pushByteSize - (end - start); missing > 0 {
a.Lsh(a, uint(8*missing))
}
- scope.Stack.push(a)
+ scope.Stack.Push(a)
*pc += size
return nil, nil
}
}
// make dup instruction function
-func makeDup(size int64) executionFunc {
+func makeDup(size int64) ExecutionFunc {
return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
scope.Stack.dup(int(size))
return nil, nil
diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go
index 08f2b2bfea1b..026eba0ee24d 100644
--- a/core/vm/instructions_test.go
+++ b/core/vm/instructions_test.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-package vm
+package vm_test
import (
"bytes"
@@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/holiman/uint256"
@@ -47,7 +48,7 @@ type twoOperandParams struct {
var alphabetSoup = "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
var commonParams []*twoOperandParams
-var twoOpMethods map[string]executionFunc
+var twoOpMethods map[string]vm.ExecutionFunc
type contractRef struct {
addr common.Address
@@ -77,35 +78,35 @@ func init() {
commonParams[i*len(params)+j] = &twoOperandParams{x, y}
}
}
- twoOpMethods = map[string]executionFunc{
- "add": opAdd,
- "sub": opSub,
- "mul": opMul,
- "div": opDiv,
- "sdiv": opSdiv,
- "mod": opMod,
- "smod": opSmod,
- "exp": opExp,
- "signext": opSignExtend,
- "lt": opLt,
- "gt": opGt,
- "slt": opSlt,
- "sgt": opSgt,
- "eq": opEq,
- "and": opAnd,
- "or": opOr,
- "xor": opXor,
- "byte": opByte,
- "shl": opSHL,
- "shr": opSHR,
- "sar": opSAR,
- }
-}
-
-func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFunc, name string) {
+ twoOpMethods = map[string]vm.ExecutionFunc{
+ "add": vm.OpAdd,
+ "sub": vm.OpSub,
+ "mul": vm.OpMul,
+ "div": vm.OpDiv,
+ "sdiv": vm.OpSdiv,
+ "mod": vm.OpMod,
+ "smod": vm.OpSmod,
+ "exp": vm.OpExp,
+ "signext": vm.OpSignExtend,
+ "lt": vm.OpLt,
+ "gt": vm.OpGt,
+ "slt": vm.OpSlt,
+ "sgt": vm.OpSgt,
+ "eq": vm.OpEq,
+ "and": vm.OpAnd,
+ "or": vm.OpOr,
+ "xor": vm.OpXor,
+ "byte": vm.OpByte,
+ "shl": vm.OpSHL,
+ "shr": vm.OpSHR,
+ "sar": vm.OpSAR,
+ }
+}
+
+func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn vm.ExecutionFunc, name string) {
var (
- evm = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
- stack = newstack()
+ evm = vm.NewEVM(vm.BlockContext{}, nil, params.TestChainConfig, vm.Config{})
+ stack = vm.Newstack()
pc = uint64(0)
)
@@ -113,13 +114,13 @@ func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFu
x := new(uint256.Int).SetBytes(common.Hex2Bytes(test.X))
y := new(uint256.Int).SetBytes(common.Hex2Bytes(test.Y))
expected := new(uint256.Int).SetBytes(common.Hex2Bytes(test.Expected))
- stack.push(x)
- stack.push(y)
- opFn(&pc, evm.interpreter, &ScopeContext{nil, stack, nil})
- if len(stack.data) != 1 {
- t.Errorf("Expected one item on stack after %v, got %d: ", name, len(stack.data))
+ stack.Push(x)
+ stack.Push(y)
+ opFn(&pc, evm.GetInterpreter(), &vm.ScopeContext{nil, stack, nil})
+ if len(stack.Data()) != 1 {
+ t.Errorf("Expected one item on stack after %v, got %d: ", name, len(stack.Data()))
}
- actual := stack.pop()
+ actual := stack.Pop()
if actual.Cmp(expected) != 0 {
t.Errorf("Testcase %v %d, %v(%x, %x): expected %x, got %x", name, i, name, x, y, expected, actual)
@@ -138,7 +139,7 @@ func TestByteOp(t *testing.T) {
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "20", "00"},
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "FFFFFFFFFFFFFFFF", "00"},
}
- testTwoOperandOp(t, tests, opByte, "byte")
+ testTwoOperandOp(t, tests, vm.OpByte, "byte")
}
func TestSHL(t *testing.T) {
@@ -155,7 +156,7 @@ func TestSHL(t *testing.T) {
{"0000000000000000000000000000000000000000000000000000000000000000", "01", "0000000000000000000000000000000000000000000000000000000000000000"},
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "01", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"},
}
- testTwoOperandOp(t, tests, opSHL, "shl")
+ testTwoOperandOp(t, tests, vm.OpSHL, "shl")
}
func TestSHR(t *testing.T) {
@@ -173,7 +174,7 @@ func TestSHR(t *testing.T) {
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", "0000000000000000000000000000000000000000000000000000000000000000"},
{"0000000000000000000000000000000000000000000000000000000000000000", "01", "0000000000000000000000000000000000000000000000000000000000000000"},
}
- testTwoOperandOp(t, tests, opSHR, "shr")
+ testTwoOperandOp(t, tests, vm.OpSHR, "shr")
}
func TestSAR(t *testing.T) {
@@ -197,13 +198,13 @@ func TestSAR(t *testing.T) {
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0100", "0000000000000000000000000000000000000000000000000000000000000000"},
}
- testTwoOperandOp(t, tests, opSAR, "sar")
+ testTwoOperandOp(t, tests, vm.OpSAR, "sar")
}
func TestAddMod(t *testing.T) {
var (
- evm = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
- stack = newstack()
+ evm = vm.NewEVM(vm.BlockContext{}, nil, params.TestChainConfig, vm.Config{})
+ stack = vm.Newstack()
pc = uint64(0)
)
tests := []struct {
@@ -226,11 +227,11 @@ func TestAddMod(t *testing.T) {
y := new(uint256.Int).SetBytes(common.Hex2Bytes(test.y))
z := new(uint256.Int).SetBytes(common.Hex2Bytes(test.z))
expected := new(uint256.Int).SetBytes(common.Hex2Bytes(test.expected))
- stack.push(z)
- stack.push(y)
- stack.push(x)
- opAddmod(&pc, evm.interpreter, &ScopeContext{nil, stack, nil})
- actual := stack.pop()
+ stack.Push(z)
+ stack.Push(y)
+ stack.Push(x)
+ vm.OpAddmod(&pc, evm.GetInterpreter(), &vm.ScopeContext{nil, stack, nil})
+ actual := stack.Pop()
if actual.Cmp(expected) != 0 {
t.Errorf("Testcase %d, expected %x, got %x", i, expected, actual)
}
@@ -243,20 +244,20 @@ func TestWriteExpectedValues(t *testing.T) {
t.Skip("Enable this test to create json test cases.")
// getResult is a convenience function to generate the expected values
- getResult := func(args []*twoOperandParams, opFn executionFunc) []TwoOperandTestcase {
+ getResult := func(args []*twoOperandParams, opFn vm.ExecutionFunc) []TwoOperandTestcase {
var (
- evm = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
- stack = newstack()
+ evm = vm.NewEVM(vm.BlockContext{}, nil, params.TestChainConfig, vm.Config{})
+ stack = vm.Newstack()
pc = uint64(0)
)
result := make([]TwoOperandTestcase, len(args))
for i, param := range args {
x := new(uint256.Int).SetBytes(common.Hex2Bytes(param.x))
y := new(uint256.Int).SetBytes(common.Hex2Bytes(param.y))
- stack.push(x)
- stack.push(y)
- opFn(&pc, evm.interpreter, &ScopeContext{nil, stack, nil})
- actual := stack.pop()
+ stack.Push(x)
+ stack.Push(y)
+ opFn(&pc, evm.GetInterpreter(), &vm.ScopeContext{nil, stack, nil})
+ actual := stack.Pop()
result[i] = TwoOperandTestcase{param.x, param.y, fmt.Sprintf("%064x", actual)}
}
return result
@@ -287,11 +288,11 @@ func TestJsonTestcases(t *testing.T) {
}
}
-func opBenchmark(bench *testing.B, op executionFunc, args ...string) {
+func opBenchmark(bench *testing.B, op vm.ExecutionFunc, args ...string) {
var (
- evm = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
- stack = newstack()
- scope = &ScopeContext{nil, stack, nil}
+ evm = vm.NewEVM(vm.BlockContext{}, nil, params.TestChainConfig, vm.Config{})
+ stack = vm.Newstack()
+ scope = &vm.ScopeContext{nil, stack, nil}
)
// convert args
intArgs := make([]*uint256.Int, len(args))
@@ -302,10 +303,10 @@ func opBenchmark(bench *testing.B, op executionFunc, args ...string) {
bench.ResetTimer()
for i := 0; i < bench.N; i++ {
for _, arg := range intArgs {
- stack.push(arg)
+ stack.Push(arg)
}
- op(&pc, evm.interpreter, scope)
- stack.pop()
+ op(&pc, evm.GetInterpreter(), scope)
+ stack.Pop()
}
bench.StopTimer()
@@ -321,169 +322,169 @@ func BenchmarkOpAdd64(b *testing.B) {
x := "ffffffff"
y := "fd37f3e2bba2c4f"
- opBenchmark(b, opAdd, x, y)
+ opBenchmark(b, vm.OpAdd, x, y)
}
func BenchmarkOpAdd128(b *testing.B) {
x := "ffffffffffffffff"
y := "f5470b43c6549b016288e9a65629687"
- opBenchmark(b, opAdd, x, y)
+ opBenchmark(b, vm.OpAdd, x, y)
}
func BenchmarkOpAdd256(b *testing.B) {
x := "0802431afcbce1fc194c9eaa417b2fb67dc75a95db0bc7ec6b1c8af11df6a1da9"
y := "a1f5aac137876480252e5dcac62c354ec0d42b76b0642b6181ed099849ea1d57"
- opBenchmark(b, opAdd, x, y)
+ opBenchmark(b, vm.OpAdd, x, y)
}
func BenchmarkOpSub64(b *testing.B) {
x := "51022b6317003a9d"
y := "a20456c62e00753a"
- opBenchmark(b, opSub, x, y)
+ opBenchmark(b, vm.OpSub, x, y)
}
func BenchmarkOpSub128(b *testing.B) {
x := "4dde30faaacdc14d00327aac314e915d"
y := "9bbc61f5559b829a0064f558629d22ba"
- opBenchmark(b, opSub, x, y)
+ opBenchmark(b, vm.OpSub, x, y)
}
func BenchmarkOpSub256(b *testing.B) {
x := "4bfcd8bb2ac462735b48a17580690283980aa2d679f091c64364594df113ea37"
y := "97f9b1765588c4e6b69142eb00d20507301545acf3e1238c86c8b29be227d46e"
- opBenchmark(b, opSub, x, y)
+ opBenchmark(b, vm.OpSub, x, y)
}
func BenchmarkOpMul(b *testing.B) {
x := alphabetSoup
y := alphabetSoup
- opBenchmark(b, opMul, x, y)
+ opBenchmark(b, vm.OpMul, x, y)
}
func BenchmarkOpDiv256(b *testing.B) {
x := "ff3f9014f20db29ae04af2c2d265de17"
y := "fe7fb0d1f59dfe9492ffbf73683fd1e870eec79504c60144cc7f5fc2bad1e611"
- opBenchmark(b, opDiv, x, y)
+ opBenchmark(b, vm.OpDiv, x, y)
}
func BenchmarkOpDiv128(b *testing.B) {
x := "fdedc7f10142ff97"
y := "fbdfda0e2ce356173d1993d5f70a2b11"
- opBenchmark(b, opDiv, x, y)
+ opBenchmark(b, vm.OpDiv, x, y)
}
func BenchmarkOpDiv64(b *testing.B) {
x := "fcb34eb3"
y := "f97180878e839129"
- opBenchmark(b, opDiv, x, y)
+ opBenchmark(b, vm.OpDiv, x, y)
}
func BenchmarkOpSdiv(b *testing.B) {
x := "ff3f9014f20db29ae04af2c2d265de17"
y := "fe7fb0d1f59dfe9492ffbf73683fd1e870eec79504c60144cc7f5fc2bad1e611"
- opBenchmark(b, opSdiv, x, y)
+ opBenchmark(b, vm.OpSdiv, x, y)
}
func BenchmarkOpMod(b *testing.B) {
x := alphabetSoup
y := alphabetSoup
- opBenchmark(b, opMod, x, y)
+ opBenchmark(b, vm.OpMod, x, y)
}
func BenchmarkOpSmod(b *testing.B) {
x := alphabetSoup
y := alphabetSoup
- opBenchmark(b, opSmod, x, y)
+ opBenchmark(b, vm.OpSmod, x, y)
}
func BenchmarkOpExp(b *testing.B) {
x := alphabetSoup
y := alphabetSoup
- opBenchmark(b, opExp, x, y)
+ opBenchmark(b, vm.OpExp, x, y)
}
func BenchmarkOpSignExtend(b *testing.B) {
x := alphabetSoup
y := alphabetSoup
- opBenchmark(b, opSignExtend, x, y)
+ opBenchmark(b, vm.OpSignExtend, x, y)
}
func BenchmarkOpLt(b *testing.B) {
x := alphabetSoup
y := alphabetSoup
- opBenchmark(b, opLt, x, y)
+ opBenchmark(b, vm.OpLt, x, y)
}
func BenchmarkOpGt(b *testing.B) {
x := alphabetSoup
y := alphabetSoup
- opBenchmark(b, opGt, x, y)
+ opBenchmark(b, vm.OpGt, x, y)
}
func BenchmarkOpSlt(b *testing.B) {
x := alphabetSoup
y := alphabetSoup
- opBenchmark(b, opSlt, x, y)
+ opBenchmark(b, vm.OpSlt, x, y)
}
func BenchmarkOpSgt(b *testing.B) {
x := alphabetSoup
y := alphabetSoup
- opBenchmark(b, opSgt, x, y)
+ opBenchmark(b, vm.OpSgt, x, y)
}
func BenchmarkOpEq(b *testing.B) {
x := alphabetSoup
y := alphabetSoup
- opBenchmark(b, opEq, x, y)
+ opBenchmark(b, vm.OpEq, x, y)
}
func BenchmarkOpEq2(b *testing.B) {
x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
y := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201fffffffe"
- opBenchmark(b, opEq, x, y)
+ opBenchmark(b, vm.OpEq, x, y)
}
func BenchmarkOpAnd(b *testing.B) {
x := alphabetSoup
y := alphabetSoup
- opBenchmark(b, opAnd, x, y)
+ opBenchmark(b, vm.OpAnd, x, y)
}
func BenchmarkOpOr(b *testing.B) {
x := alphabetSoup
y := alphabetSoup
- opBenchmark(b, opOr, x, y)
+ opBenchmark(b, vm.OpOr, x, y)
}
func BenchmarkOpXor(b *testing.B) {
x := alphabetSoup
y := alphabetSoup
- opBenchmark(b, opXor, x, y)
+ opBenchmark(b, vm.OpXor, x, y)
}
func BenchmarkOpByte(b *testing.B) {
x := alphabetSoup
y := alphabetSoup
- opBenchmark(b, opByte, x, y)
+ opBenchmark(b, vm.OpByte, x, y)
}
func BenchmarkOpAddmod(b *testing.B) {
@@ -491,7 +492,7 @@ func BenchmarkOpAddmod(b *testing.B) {
y := alphabetSoup
z := alphabetSoup
- opBenchmark(b, opAddmod, x, y, z)
+ opBenchmark(b, vm.OpAddmod, x, y, z)
}
func BenchmarkOpMulmod(b *testing.B) {
@@ -499,50 +500,50 @@ func BenchmarkOpMulmod(b *testing.B) {
y := alphabetSoup
z := alphabetSoup
- opBenchmark(b, opMulmod, x, y, z)
+ opBenchmark(b, vm.OpMulmod, x, y, z)
}
func BenchmarkOpSHL(b *testing.B) {
x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
y := "ff"
- opBenchmark(b, opSHL, x, y)
+ opBenchmark(b, vm.OpSHL, x, y)
}
func BenchmarkOpSHR(b *testing.B) {
x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
y := "ff"
- opBenchmark(b, opSHR, x, y)
+ opBenchmark(b, vm.OpSHR, x, y)
}
func BenchmarkOpSAR(b *testing.B) {
x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
y := "ff"
- opBenchmark(b, opSAR, x, y)
+ opBenchmark(b, vm.OpSAR, x, y)
}
func BenchmarkOpIsZero(b *testing.B) {
x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
- opBenchmark(b, opIszero, x)
+ opBenchmark(b, vm.OpIszero, x)
}
func TestOpMstore(t *testing.T) {
var (
- evm = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
- stack = newstack()
- mem = NewMemory()
+ evm = vm.NewEVM(vm.BlockContext{}, nil, params.TestChainConfig, vm.Config{})
+ stack = vm.Newstack()
+ mem = vm.NewMemory()
)
mem.Resize(64)
pc := uint64(0)
v := "abcdef00000000000000abba000000000deaf000000c0de00100000000133700"
- stack.push(new(uint256.Int).SetBytes(common.Hex2Bytes(v)))
- stack.push(new(uint256.Int))
- opMstore(&pc, evm.interpreter, &ScopeContext{mem, stack, nil})
+ stack.Push(new(uint256.Int).SetBytes(common.Hex2Bytes(v)))
+ stack.Push(new(uint256.Int))
+ vm.OpMstore(&pc, evm.GetInterpreter(), &vm.ScopeContext{mem, stack, nil})
if got := common.Bytes2Hex(mem.GetCopy(0, 32)); got != v {
t.Fatalf("Mstore fail, got %v, expected %v", got, v)
}
- stack.push(new(uint256.Int).SetUint64(0x1))
- stack.push(new(uint256.Int))
- opMstore(&pc, evm.interpreter, &ScopeContext{mem, stack, nil})
+ stack.Push(new(uint256.Int).SetUint64(0x1))
+ stack.Push(new(uint256.Int))
+ vm.OpMstore(&pc, evm.GetInterpreter(), &vm.ScopeContext{mem, stack, nil})
if common.Bytes2Hex(mem.GetCopy(0, 32)) != "0000000000000000000000000000000000000000000000000000000000000001" {
t.Fatalf("Mstore failed to overwrite previous value")
}
@@ -550,9 +551,9 @@ func TestOpMstore(t *testing.T) {
func BenchmarkOpMstore(bench *testing.B) {
var (
- evm = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
- stack = newstack()
- mem = NewMemory()
+ evm = vm.NewEVM(vm.BlockContext{}, nil, params.TestChainConfig, vm.Config{})
+ stack = vm.Newstack()
+ mem = vm.NewMemory()
)
mem.Resize(64)
pc := uint64(0)
@@ -561,23 +562,23 @@ func BenchmarkOpMstore(bench *testing.B) {
bench.ResetTimer()
for i := 0; i < bench.N; i++ {
- stack.push(value)
- stack.push(memStart)
- opMstore(&pc, evm.interpreter, &ScopeContext{mem, stack, nil})
+ stack.Push(value)
+ stack.Push(memStart)
+ vm.OpMstore(&pc, evm.GetInterpreter(), &vm.ScopeContext{mem, stack, nil})
}
}
func TestOpTstore(t *testing.T) {
var (
statedb, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
- evm = NewEVM(BlockContext{}, statedb, params.TestChainConfig, Config{})
- stack = newstack()
- mem = NewMemory()
+ evm = vm.NewEVM(vm.BlockContext{}, statedb, params.TestChainConfig, vm.Config{})
+ stack = vm.Newstack()
+ mem = vm.NewMemory()
caller = common.Address{}
to = common.Address{1}
contractRef = contractRef{caller}
- contract = NewContract(contractRef, AccountRef(to), new(uint256.Int), 0)
- scopeContext = ScopeContext{mem, stack, contract}
+ contract = vm.NewContract(contractRef, vm.AccountRef(to), new(uint256.Int), 0)
+ scopeContext = vm.ScopeContext{mem, stack, contract}
value = common.Hex2Bytes("abcdef00000000000000abba000000000deaf000000c0de00100000000133700")
)
@@ -587,22 +588,22 @@ func TestOpTstore(t *testing.T) {
pc := uint64(0)
// push the value to the stack
- stack.push(new(uint256.Int).SetBytes(value))
+ stack.Push(new(uint256.Int).SetBytes(value))
// push the location to the stack
- stack.push(new(uint256.Int))
- opTstore(&pc, evm.interpreter, &scopeContext)
+ stack.Push(new(uint256.Int))
+ vm.OpTstore(&pc, evm.GetInterpreter(), &scopeContext)
// there should be no elements on the stack after TSTORE
- if stack.len() != 0 {
+ if stack.Len() != 0 {
t.Fatal("stack wrong size")
}
// push the location to the stack
- stack.push(new(uint256.Int))
- opTload(&pc, evm.interpreter, &scopeContext)
+ stack.Push(new(uint256.Int))
+ vm.OpTload(&pc, evm.GetInterpreter(), &scopeContext)
// there should be one element on the stack after TLOAD
- if stack.len() != 1 {
+ if stack.Len() != 1 {
t.Fatal("stack wrong size")
}
- val := stack.peek()
+ val := stack.Peek()
if !bytes.Equal(val.Bytes(), value) {
t.Fatal("incorrect element read from transient storage")
}
@@ -610,9 +611,9 @@ func TestOpTstore(t *testing.T) {
func BenchmarkOpKeccak256(bench *testing.B) {
var (
- evm = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
- stack = newstack()
- mem = NewMemory()
+ evm = vm.NewEVM(vm.BlockContext{}, nil, params.TestChainConfig, vm.Config{})
+ stack = vm.Newstack()
+ mem = vm.NewMemory()
)
mem.Resize(32)
pc := uint64(0)
@@ -620,9 +621,9 @@ func BenchmarkOpKeccak256(bench *testing.B) {
bench.ResetTimer()
for i := 0; i < bench.N; i++ {
- stack.push(uint256.NewInt(32))
- stack.push(start)
- opKeccak256(&pc, evm.interpreter, &ScopeContext{mem, stack, nil})
+ stack.Push(uint256.NewInt(32))
+ stack.Push(start)
+ vm.OpKeccak256(&pc, evm.GetInterpreter(), &vm.ScopeContext{mem, stack, nil})
}
}
@@ -684,11 +685,11 @@ func TestCreate2Addresses(t *testing.T) {
codeHash := crypto.Keccak256(code)
address := crypto.CreateAddress2(origin, salt, codeHash)
/*
- stack := newstack()
+ stack := vm.Newstack()
// salt, but we don't need that for this test
- stack.push(big.NewInt(int64(len(code)))) //size
- stack.push(big.NewInt(0)) // memstart
- stack.push(big.NewInt(0)) // value
+ stack.Push(big.NewInt(int64(len(code)))) //size
+ stack.Push(big.NewInt(0)) // memstart
+ stack.Push(big.NewInt(0)) // value
gas, _ := gasCreate2(params.GasTable{}, nil, nil, stack, nil, 0)
fmt.Printf("Example %d\n* address `0x%x`\n* salt `0x%x`\n* init_code `0x%x`\n* gas (assuming no mem expansion): `%v`\n* result: `%s`\n\n", i,origin, salt, code, gas, address.String())
*/
@@ -712,15 +713,15 @@ func TestRandom(t *testing.T) {
{name: "hash(0x010203)", random: crypto.Keccak256Hash([]byte{0x01, 0x02, 0x03})},
} {
var (
- evm = NewEVM(BlockContext{Random: &tt.random}, nil, params.TestChainConfig, Config{})
- stack = newstack()
+ evm = vm.NewEVM(vm.BlockContext{Random: &tt.random}, nil, params.TestChainConfig, vm.Config{})
+ stack = vm.Newstack()
pc = uint64(0)
)
- opRandom(&pc, evm.interpreter, &ScopeContext{nil, stack, nil})
- if len(stack.data) != 1 {
- t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.data))
+ vm.OpRandom(&pc, evm.GetInterpreter(), &vm.ScopeContext{nil, stack, nil})
+ if len(stack.Data()) != 1 {
+ t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.Data()))
}
- actual := stack.pop()
+ actual := stack.Pop()
expected, overflow := uint256.FromBig(new(big.Int).SetBytes(tt.random.Bytes()))
if overflow {
t.Errorf("Testcase %v: invalid overflow", tt.name)
@@ -752,17 +753,17 @@ func TestBlobHash(t *testing.T) {
{name: "out-of-bounds (nil)", idx: 25, expect: zero, hashes: nil},
} {
var (
- evm = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
- stack = newstack()
+ evm = vm.NewEVM(vm.BlockContext{}, nil, params.TestChainConfig, vm.Config{})
+ stack = vm.Newstack()
pc = uint64(0)
)
- evm.SetTxContext(TxContext{BlobHashes: tt.hashes})
- stack.push(uint256.NewInt(tt.idx))
- opBlobHash(&pc, evm.interpreter, &ScopeContext{nil, stack, nil})
- if len(stack.data) != 1 {
- t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.data))
+ evm.SetTxContext(vm.TxContext{BlobHashes: tt.hashes})
+ stack.Push(uint256.NewInt(tt.idx))
+ vm.OpBlobHash(&pc, evm.GetInterpreter(), &vm.ScopeContext{nil, stack, nil})
+ if len(stack.Data()) != 1 {
+ t.Errorf("Expected one item on stack after %v, got %d: ", tt.name, len(stack.Data()))
}
- actual := stack.pop()
+ actual := stack.Pop()
expected, overflow := uint256.FromBig(new(big.Int).SetBytes(tt.expect.Bytes()))
if overflow {
t.Errorf("Testcase %v: invalid overflow", tt.name)
@@ -855,13 +856,13 @@ func TestOpMCopy(t *testing.T) {
},
} {
var (
- evm = NewEVM(BlockContext{}, nil, params.TestChainConfig, Config{})
- stack = newstack()
+ evm = vm.NewEVM(vm.BlockContext{}, nil, params.TestChainConfig, vm.Config{})
+ stack = vm.Newstack()
pc = uint64(0)
)
data := common.FromHex(strings.ReplaceAll(tc.pre, " ", ""))
// Set pre
- mem := NewMemory()
+ mem := vm.NewMemory()
mem.Resize(uint64(len(data)))
mem.Set(0, uint64(len(data)), data)
// Push stack args
@@ -869,38 +870,38 @@ func TestOpMCopy(t *testing.T) {
src, _ := uint256.FromHex(tc.src)
dst, _ := uint256.FromHex(tc.dst)
- stack.push(len)
- stack.push(src)
- stack.push(dst)
+ stack.Push(len)
+ stack.Push(src)
+ stack.Push(dst)
wantErr := (tc.wantGas == 0)
// Calc mem expansion
var memorySize uint64
- if memSize, overflow := memoryMcopy(stack); overflow {
+ if memSize, overflow := vm.MemoryMcopy(stack); overflow {
if wantErr {
continue
}
t.Errorf("overflow")
} else {
var overflow bool
- if memorySize, overflow = math.SafeMul(toWordSize(memSize), 32); overflow {
- t.Error(ErrGasUintOverflow)
+ if memorySize, overflow = math.SafeMul(vm.ToWordSize(memSize), 32); overflow {
+ t.Error(vm.ErrGasUintOverflow)
}
}
// and the dynamic cost
var haveGas uint64
- if dynamicCost, err := gasMcopy(evm, nil, stack, mem, memorySize); err != nil {
+ if dynamicCost, err := vm.GasMcopy(evm, nil, stack, mem, memorySize); err != nil {
t.Error(err)
} else {
- haveGas = GasFastestStep + dynamicCost
+ haveGas = vm.GasFastestStep + dynamicCost
}
// Expand mem
if memorySize > 0 {
mem.Resize(memorySize)
}
// Do the copy
- opMcopy(&pc, evm.interpreter, &ScopeContext{mem, stack, nil})
+ vm.OpMcopy(&pc, evm.GetInterpreter(), &vm.ScopeContext{mem, stack, nil})
want := common.FromHex(strings.ReplaceAll(tc.want, " ", ""))
- if have := mem.store; !bytes.Equal(want, have) {
+ if have := mem.Store(); !bytes.Equal(want, have) {
t.Errorf("case %d: \nwant: %#x\nhave: %#x\n", i, want, have)
}
wantGas := tc.wantGas
@@ -915,12 +916,12 @@ func TestOpMCopy(t *testing.T) {
func TestPush(t *testing.T) {
code := common.FromHex("0011223344556677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a19181716151413121")
- push32 := makePush(32, 32)
+ push32 := vm.MakePush(32, 32)
- scope := &ScopeContext{
+ scope := &vm.ScopeContext{
Memory: nil,
- Stack: newstack(),
- Contract: &Contract{
+ Stack: vm.Newstack(),
+ Contract: &vm.Contract{
Code: code,
},
}
@@ -975,7 +976,7 @@ func TestPush(t *testing.T) {
pc := new(uint64)
*pc = uint64(i)
push32(pc, nil, scope)
- res := scope.Stack.pop()
+ res := scope.Stack.Pop()
if have := res.Hex(); have != want {
t.Fatalf("case %d, have %v want %v", i, have, want)
}
diff --git a/core/vm/interface.go b/core/vm/interface.go
index 0d7862a66e11..c32f8c7b3463 100644
--- a/core/vm/interface.go
+++ b/core/vm/interface.go
@@ -20,7 +20,6 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/stateless"
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
@@ -99,10 +98,24 @@ type StateDB interface {
Witness() *stateless.Witness
- AccessEvents() *state.AccessEvents
+ AccessEvents() *AccessEvents
// Finalise must be invoked at the end of a transaction
Finalise(bool)
+
+ // new methods
+ Error() error
+ SetBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason)
+ SetStorage(common.Address, map[common.Hash]common.Hash)
+ Commit(block uint64, deleteEmptyObjects bool, noStorageWiping bool) (common.Hash, error)
+ SetTxContext(thash common.Hash, ti int)
+ Copy() StateDB
+ IntermediateRoot(deleteEmptyObjects bool) common.Hash
+ GetLogs(hash common.Hash, blockNumber uint64, blockHash common.Hash) []*types.Log
+ TxIndex() int
+ Preimages() map[common.Hash][]byte
+ Logs() []*types.Log
+ SetEVM(evm *EVM)
}
// CallContext provides a basic interface for the EVM calling conventions. The EVM
diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go
index a0038d1aa833..29cb8b00e924 100644
--- a/core/vm/interpreter.go
+++ b/core/vm/interpreter.go
@@ -110,7 +110,7 @@ func NewEVMInterpreter(evm *EVM) *EVMInterpreter {
// TODO replace with proper instruction set when fork is specified
table = &verkleInstructionSet
case evm.chainRules.IsPrague:
- table = &pragueInstructionSet
+ table = &PragueInstructionSet
case evm.chainRules.IsCancun:
table = &cancunInstructionSet
case evm.chainRules.IsShanghai:
@@ -139,7 +139,7 @@ func NewEVMInterpreter(evm *EVM) *EVMInterpreter {
var extraEips []int
if len(evm.Config.ExtraEips) > 0 {
// Deep-copy jumptable to prevent modification of opcodes in other tables
- table = copyJumpTable(table)
+ table = CopyJumpTable(table)
}
for _, eip := range evm.Config.ExtraEips {
if err := EnableEIP(eip, table); err != nil {
@@ -183,7 +183,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
var (
op OpCode // current opcode
mem = NewMemory() // bound memory
- stack = newstack() // local stack
+ stack = Newstack() // local stack
callContext = &ScopeContext{
Memory: mem,
Stack: stack,
@@ -246,8 +246,8 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
operation := in.table[op]
cost = operation.constantGas // For tracing
// Validate stack
- if sLen := stack.len(); sLen < operation.minStack {
- return nil, &ErrStackUnderflow{stackLen: sLen, required: operation.minStack}
+ if sLen := stack.Len(); sLen < operation.minStack {
+ return nil, &ErrStackUnderflow{StackLen: sLen, Required: operation.minStack}
} else if sLen > operation.maxStack {
return nil, &ErrStackOverflow{stackLen: sLen, limit: operation.maxStack}
}
@@ -272,7 +272,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
}
// memory is expanded in words of 32 bytes. Gas
// is also calculated in words.
- if memorySize, overflow = math.SafeMul(toWordSize(memSize), 32); overflow {
+ if memorySize, overflow = math.SafeMul(ToWordSize(memSize), 32); overflow {
return nil, ErrGasUintOverflow
}
}
diff --git a/core/vm/interpreter_test.go b/core/vm/interpreter_test.go
index cacad8f81339..358c5f34b6c1 100644
--- a/core/vm/interpreter_test.go
+++ b/core/vm/interpreter_test.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-package vm
+package vm_test
import (
"math"
@@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
"github.com/holiman/uint256"
)
@@ -37,8 +38,8 @@ var loopInterruptTests = []string{
func TestLoopInterrupt(t *testing.T) {
address := common.BytesToAddress([]byte("contract"))
- vmctx := BlockContext{
- Transfer: func(StateDB, common.Address, common.Address, *uint256.Int) {},
+ vmctx := vm.BlockContext{
+ Transfer: func(vm.StateDB, common.Address, common.Address, *uint256.Int) {},
}
for i, tt := range loopInterruptTests {
@@ -47,13 +48,13 @@ func TestLoopInterrupt(t *testing.T) {
statedb.SetCode(address, common.Hex2Bytes(tt))
statedb.Finalise(true)
- evm := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, Config{})
+ evm := vm.NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, vm.Config{})
errChannel := make(chan error)
timeout := make(chan bool)
- go func(evm *EVM) {
- _, _, err := evm.Call(AccountRef(common.Address{}), address, nil, math.MaxUint64, new(uint256.Int))
+ go func(evm *vm.EVM) {
+ _, _, err := evm.Call(vm.AccountRef(common.Address{}), address, nil, math.MaxUint64, new(uint256.Int))
errChannel <- err
}(evm)
diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go
index 6610fa7f9aba..64ca7df5581d 100644
--- a/core/vm/jump_table.go
+++ b/core/vm/jump_table.go
@@ -23,7 +23,7 @@ import (
)
type (
- executionFunc func(pc *uint64, interpreter *EVMInterpreter, callContext *ScopeContext) ([]byte, error)
+ ExecutionFunc func(pc *uint64, interpreter *EVMInterpreter, callContext *ScopeContext) ([]byte, error)
gasFunc func(*EVM, *Contract, *Stack, *Memory, uint64) (uint64, error) // last parameter is the requested memory size as a uint64
// memorySizeFunc returns the required size, and whether the operation overflowed a uint64
memorySizeFunc func(*Stack) (size uint64, overflow bool)
@@ -31,7 +31,7 @@ type (
type operation struct {
// execute is the operation function
- execute executionFunc
+ execute ExecutionFunc
constantGas uint64
dynamicGas gasFunc
// minStack tells how many stack items are required
@@ -47,6 +47,14 @@ type operation struct {
undefined bool
}
+func (o *operation) GetConstantGas() uint64 {
+ return o.constantGas
+}
+
+func (o *operation) SetConstantGas(cg uint64) {
+ o.constantGas = cg
+}
+
var (
frontierInstructionSet = newFrontierInstructionSet()
homesteadInstructionSet = newHomesteadInstructionSet()
@@ -57,12 +65,12 @@ var (
istanbulInstructionSet = newIstanbulInstructionSet()
berlinInstructionSet = newBerlinInstructionSet()
londonInstructionSet = newLondonInstructionSet()
- mergeInstructionSet = newMergeInstructionSet()
+ mergeInstructionSet = NewMergeInstructionSet()
shanghaiInstructionSet = newShanghaiInstructionSet()
cancunInstructionSet = newCancunInstructionSet()
verkleInstructionSet = newVerkleInstructionSet()
- pragueInstructionSet = newPragueInstructionSet()
- eofInstructionSet = newEOFInstructionSetForTesting()
+ PragueInstructionSet = newPragueInstructionSet()
+ EofInstructionSet = newEOFInstructionSetForTesting()
)
// JumpTable contains the EVM opcodes supported at a given fork.
@@ -119,17 +127,17 @@ func newCancunInstructionSet() JumpTable {
}
func newShanghaiInstructionSet() JumpTable {
- instructionSet := newMergeInstructionSet()
+ instructionSet := NewMergeInstructionSet()
enable3855(&instructionSet) // PUSH0 instruction
enable3860(&instructionSet) // Limit and meter initcode
return validate(instructionSet)
}
-func newMergeInstructionSet() JumpTable {
+func NewMergeInstructionSet() JumpTable {
instructionSet := newLondonInstructionSet()
instructionSet[PREVRANDAO] = &operation{
- execute: opRandom,
+ execute: OpRandom,
constantGas: GasQuickStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
@@ -171,19 +179,19 @@ func newIstanbulInstructionSet() JumpTable {
func newConstantinopleInstructionSet() JumpTable {
instructionSet := newByzantiumInstructionSet()
instructionSet[SHL] = &operation{
- execute: opSHL,
+ execute: OpSHL,
constantGas: GasFastestStep,
minStack: minStack(2, 1),
maxStack: maxStack(2, 1),
}
instructionSet[SHR] = &operation{
- execute: opSHR,
+ execute: OpSHR,
constantGas: GasFastestStep,
minStack: minStack(2, 1),
maxStack: maxStack(2, 1),
}
instructionSet[SAR] = &operation{
- execute: opSAR,
+ execute: OpSAR,
constantGas: GasFastestStep,
minStack: minStack(2, 1),
maxStack: maxStack(2, 1),
@@ -287,121 +295,121 @@ func newFrontierInstructionSet() JumpTable {
maxStack: maxStack(0, 0),
},
ADD: {
- execute: opAdd,
+ execute: OpAdd,
constantGas: GasFastestStep,
minStack: minStack(2, 1),
maxStack: maxStack(2, 1),
},
MUL: {
- execute: opMul,
+ execute: OpMul,
constantGas: GasFastStep,
minStack: minStack(2, 1),
maxStack: maxStack(2, 1),
},
SUB: {
- execute: opSub,
+ execute: OpSub,
constantGas: GasFastestStep,
minStack: minStack(2, 1),
maxStack: maxStack(2, 1),
},
DIV: {
- execute: opDiv,
+ execute: OpDiv,
constantGas: GasFastStep,
minStack: minStack(2, 1),
maxStack: maxStack(2, 1),
},
SDIV: {
- execute: opSdiv,
+ execute: OpSdiv,
constantGas: GasFastStep,
minStack: minStack(2, 1),
maxStack: maxStack(2, 1),
},
MOD: {
- execute: opMod,
+ execute: OpMod,
constantGas: GasFastStep,
minStack: minStack(2, 1),
maxStack: maxStack(2, 1),
},
SMOD: {
- execute: opSmod,
+ execute: OpSmod,
constantGas: GasFastStep,
minStack: minStack(2, 1),
maxStack: maxStack(2, 1),
},
ADDMOD: {
- execute: opAddmod,
+ execute: OpAddmod,
constantGas: GasMidStep,
minStack: minStack(3, 1),
maxStack: maxStack(3, 1),
},
MULMOD: {
- execute: opMulmod,
+ execute: OpMulmod,
constantGas: GasMidStep,
minStack: minStack(3, 1),
maxStack: maxStack(3, 1),
},
EXP: {
- execute: opExp,
+ execute: OpExp,
dynamicGas: gasExpFrontier,
minStack: minStack(2, 1),
maxStack: maxStack(2, 1),
},
SIGNEXTEND: {
- execute: opSignExtend,
+ execute: OpSignExtend,
constantGas: GasFastStep,
minStack: minStack(2, 1),
maxStack: maxStack(2, 1),
},
LT: {
- execute: opLt,
+ execute: OpLt,
constantGas: GasFastestStep,
minStack: minStack(2, 1),
maxStack: maxStack(2, 1),
},
GT: {
- execute: opGt,
+ execute: OpGt,
constantGas: GasFastestStep,
minStack: minStack(2, 1),
maxStack: maxStack(2, 1),
},
SLT: {
- execute: opSlt,
+ execute: OpSlt,
constantGas: GasFastestStep,
minStack: minStack(2, 1),
maxStack: maxStack(2, 1),
},
SGT: {
- execute: opSgt,
+ execute: OpSgt,
constantGas: GasFastestStep,
minStack: minStack(2, 1),
maxStack: maxStack(2, 1),
},
EQ: {
- execute: opEq,
+ execute: OpEq,
constantGas: GasFastestStep,
minStack: minStack(2, 1),
maxStack: maxStack(2, 1),
},
ISZERO: {
- execute: opIszero,
+ execute: OpIszero,
constantGas: GasFastestStep,
minStack: minStack(1, 1),
maxStack: maxStack(1, 1),
},
AND: {
- execute: opAnd,
+ execute: OpAnd,
constantGas: GasFastestStep,
minStack: minStack(2, 1),
maxStack: maxStack(2, 1),
},
XOR: {
- execute: opXor,
+ execute: OpXor,
constantGas: GasFastestStep,
minStack: minStack(2, 1),
maxStack: maxStack(2, 1),
},
OR: {
- execute: opOr,
+ execute: OpOr,
constantGas: GasFastestStep,
minStack: minStack(2, 1),
maxStack: maxStack(2, 1),
@@ -413,13 +421,13 @@ func newFrontierInstructionSet() JumpTable {
maxStack: maxStack(1, 1),
},
BYTE: {
- execute: opByte,
+ execute: OpByte,
constantGas: GasFastestStep,
minStack: minStack(2, 1),
maxStack: maxStack(2, 1),
},
KECCAK256: {
- execute: opKeccak256,
+ execute: OpKeccak256,
constantGas: params.Keccak256Gas,
dynamicGas: gasKeccak256,
minStack: minStack(2, 1),
@@ -427,7 +435,7 @@ func newFrontierInstructionSet() JumpTable {
memorySize: memoryKeccak256,
},
ADDRESS: {
- execute: opAddress,
+ execute: OpAddress,
constantGas: GasQuickStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
@@ -439,7 +447,7 @@ func newFrontierInstructionSet() JumpTable {
maxStack: maxStack(1, 1),
},
ORIGIN: {
- execute: opOrigin,
+ execute: OpOrigin,
constantGas: GasQuickStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
@@ -561,7 +569,7 @@ func newFrontierInstructionSet() JumpTable {
memorySize: memoryMLoad,
},
MSTORE: {
- execute: opMstore,
+ execute: OpMstore,
constantGas: GasFastestStep,
dynamicGas: gasMStore,
minStack: minStack(2, 0),
@@ -569,7 +577,7 @@ func newFrontierInstructionSet() JumpTable {
memorySize: memoryMStore,
},
MSTORE8: {
- execute: opMstore8,
+ execute: OpMstore8,
constantGas: GasFastestStep,
dynamicGas: gasMStore8,
memorySize: memoryMStore8,
@@ -631,187 +639,187 @@ func newFrontierInstructionSet() JumpTable {
maxStack: maxStack(0, 1),
},
PUSH2: {
- execute: makePush(2, 2),
+ execute: MakePush(2, 2),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH3: {
- execute: makePush(3, 3),
+ execute: MakePush(3, 3),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH4: {
- execute: makePush(4, 4),
+ execute: MakePush(4, 4),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH5: {
- execute: makePush(5, 5),
+ execute: MakePush(5, 5),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH6: {
- execute: makePush(6, 6),
+ execute: MakePush(6, 6),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH7: {
- execute: makePush(7, 7),
+ execute: MakePush(7, 7),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH8: {
- execute: makePush(8, 8),
+ execute: MakePush(8, 8),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH9: {
- execute: makePush(9, 9),
+ execute: MakePush(9, 9),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH10: {
- execute: makePush(10, 10),
+ execute: MakePush(10, 10),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH11: {
- execute: makePush(11, 11),
+ execute: MakePush(11, 11),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH12: {
- execute: makePush(12, 12),
+ execute: MakePush(12, 12),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH13: {
- execute: makePush(13, 13),
+ execute: MakePush(13, 13),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH14: {
- execute: makePush(14, 14),
+ execute: MakePush(14, 14),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH15: {
- execute: makePush(15, 15),
+ execute: MakePush(15, 15),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH16: {
- execute: makePush(16, 16),
+ execute: MakePush(16, 16),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH17: {
- execute: makePush(17, 17),
+ execute: MakePush(17, 17),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH18: {
- execute: makePush(18, 18),
+ execute: MakePush(18, 18),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH19: {
- execute: makePush(19, 19),
+ execute: MakePush(19, 19),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH20: {
- execute: makePush(20, 20),
+ execute: MakePush(20, 20),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH21: {
- execute: makePush(21, 21),
+ execute: MakePush(21, 21),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH22: {
- execute: makePush(22, 22),
+ execute: MakePush(22, 22),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH23: {
- execute: makePush(23, 23),
+ execute: MakePush(23, 23),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH24: {
- execute: makePush(24, 24),
+ execute: MakePush(24, 24),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH25: {
- execute: makePush(25, 25),
+ execute: MakePush(25, 25),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH26: {
- execute: makePush(26, 26),
+ execute: MakePush(26, 26),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH27: {
- execute: makePush(27, 27),
+ execute: MakePush(27, 27),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH28: {
- execute: makePush(28, 28),
+ execute: MakePush(28, 28),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH29: {
- execute: makePush(29, 29),
+ execute: MakePush(29, 29),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH30: {
- execute: makePush(30, 30),
+ execute: MakePush(30, 30),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH31: {
- execute: makePush(31, 31),
+ execute: MakePush(31, 31),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
},
PUSH32: {
- execute: makePush(32, 32),
+ execute: MakePush(32, 32),
constantGas: GasFastestStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
@@ -1097,7 +1105,7 @@ func newFrontierInstructionSet() JumpTable {
return validate(tbl)
}
-func copyJumpTable(source *JumpTable) *JumpTable {
+func CopyJumpTable(source *JumpTable) *JumpTable {
dest := *source
for i, op := range source {
if op != nil {
diff --git a/core/vm/jump_table_export.go b/core/vm/jump_table_export.go
index b8fa6049bb41..7794e5657f29 100644
--- a/core/vm/jump_table_export.go
+++ b/core/vm/jump_table_export.go
@@ -37,7 +37,7 @@ func LookupInstructionSet(rules params.Rules) (JumpTable, error) {
case rules.IsShanghai:
return newShanghaiInstructionSet(), nil
case rules.IsMerge:
- return newMergeInstructionSet(), nil
+ return NewMergeInstructionSet(), nil
case rules.IsLondon:
return newLondonInstructionSet(), nil
case rules.IsBerlin:
diff --git a/core/vm/jump_table_test.go b/core/vm/jump_table_test.go
index a4f9759ed2b7..9376f20b208a 100644
--- a/core/vm/jump_table_test.go
+++ b/core/vm/jump_table_test.go
@@ -14,22 +14,23 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-package vm
+package vm_test
import (
"testing"
+ "github.com/ethereum/go-ethereum/core/vm"
"github.com/stretchr/testify/require"
)
// TestJumpTableCopy tests that deep copy is necessary to prevent modify shared jump table
func TestJumpTableCopy(t *testing.T) {
- tbl := newMergeInstructionSet()
- require.Equal(t, uint64(0), tbl[SLOAD].constantGas)
+ tbl := vm.NewMergeInstructionSet()
+ require.Equal(t, uint64(0), tbl[vm.SLOAD].GetConstantGas())
// a deep copy won't modify the shared jump table
- deepCopy := copyJumpTable(&tbl)
- deepCopy[SLOAD].constantGas = 100
- require.Equal(t, uint64(100), deepCopy[SLOAD].constantGas)
- require.Equal(t, uint64(0), tbl[SLOAD].constantGas)
+ deepCopy := vm.CopyJumpTable(&tbl)
+ deepCopy[vm.SLOAD].SetConstantGas(100)
+ require.Equal(t, uint64(100), deepCopy[vm.SLOAD].GetConstantGas())
+ require.Equal(t, uint64(0), tbl[vm.SLOAD].GetConstantGas())
}
diff --git a/core/vm/memory.go b/core/vm/memory.go
index 5e11e83748fb..8fe575b9aa78 100644
--- a/core/vm/memory.go
+++ b/core/vm/memory.go
@@ -39,6 +39,10 @@ func NewMemory() *Memory {
return memoryPool.Get().(*Memory)
}
+func (m *Memory) Store() []byte {
+ return m.store
+}
+
// Free returns the memory to the pool.
func (m *Memory) Free() {
// To reduce peak allocation, return only smaller memory instances to the pool.
diff --git a/core/vm/memory_table.go b/core/vm/memory_table.go
index 28746042cf3b..33b3141faf2f 100644
--- a/core/vm/memory_table.go
+++ b/core/vm/memory_table.go
@@ -48,7 +48,7 @@ func memoryMStore(stack *Stack) (uint64, bool) {
return calcMemSize64WithUint(stack.Back(0), 32)
}
-func memoryMcopy(stack *Stack) (uint64, bool) {
+func MemoryMcopy(stack *Stack) (uint64, bool) {
mStart := stack.Back(0) // stack[0]: dest
if stack.Back(1).Gt(mStart) {
mStart = stack.Back(1) // stack[1]: source
diff --git a/core/vm/operations_acl.go b/core/vm/operations_acl.go
index ff3875868f56..ef2b0f1b5c04 100644
--- a/core/vm/operations_acl.go
+++ b/core/vm/operations_acl.go
@@ -34,7 +34,7 @@ func makeGasSStoreFunc(clearingRefund uint64) gasFunc {
}
// Gas sentry honoured, do the actual gas calculation based on the stored value
var (
- y, x = stack.Back(1), stack.peek()
+ y, x = stack.Back(1), stack.Peek()
slot = common.Hash(x.Bytes32())
current = evm.StateDB.GetState(contract.Address(), slot)
cost = uint64(0)
@@ -97,7 +97,7 @@ func makeGasSStoreFunc(clearingRefund uint64) gasFunc {
// charge 2100 gas and add the pair to accessed_storage_keys.
// If the pair is already in accessed_storage_keys, charge 100 gas.
func gasSLoadEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- loc := stack.peek()
+ loc := stack.Peek()
slot := common.Hash(loc.Bytes32())
// Check slot presence in the access list
if _, slotPresent := evm.StateDB.SlotInAccessList(contract.Address(), slot); !slotPresent {
@@ -120,7 +120,7 @@ func gasExtCodeCopyEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memo
if err != nil {
return 0, err
}
- addr := common.Address(stack.peek().Bytes20())
+ addr := common.Address(stack.Peek().Bytes20())
// Check slot presence in the access list
if !evm.StateDB.AddressInAccessList(addr) {
evm.StateDB.AddAddressToAccessList(addr)
@@ -142,7 +142,7 @@ func gasExtCodeCopyEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memo
// - extcodesize,
// - (ext) balance
func gasEip2929AccountCheck(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- addr := common.Address(stack.peek().Bytes20())
+ addr := common.Address(stack.Peek().Bytes20())
// Check slot presence in the access list
if !evm.StateDB.AddressInAccessList(addr) {
// If the caller cannot afford the cost, this change will be rolled back
@@ -225,7 +225,7 @@ func makeSelfdestructGasFn(refundsEnabled bool) gasFunc {
gasFunc := func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
var (
gas uint64
- address = common.Address(stack.peek().Bytes20())
+ address = common.Address(stack.Peek().Bytes20())
)
if !evm.StateDB.AddressInAccessList(address) {
// If the caller cannot afford the cost, this change will be rolled back
diff --git a/core/vm/operations_verkle.go b/core/vm/operations_verkle.go
index 751761a91159..9d4316538e52 100644
--- a/core/vm/operations_verkle.go
+++ b/core/vm/operations_verkle.go
@@ -25,7 +25,7 @@ import (
)
func gasSStore4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- gas := evm.AccessEvents.SlotGas(contract.Address(), stack.peek().Bytes32(), true)
+ gas := evm.AccessEvents.SlotGas(contract.Address(), stack.Peek().Bytes32(), true)
if gas == 0 {
gas = params.WarmStorageReadCostEIP2929
}
@@ -33,7 +33,7 @@ func gasSStore4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memo
}
func gasSLoad4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- gas := evm.AccessEvents.SlotGas(contract.Address(), stack.peek().Bytes32(), false)
+ gas := evm.AccessEvents.SlotGas(contract.Address(), stack.Peek().Bytes32(), false)
if gas == 0 {
gas = params.WarmStorageReadCostEIP2929
}
@@ -44,7 +44,7 @@ func gasBalance4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, mem
if contract.IsSystemCall {
return 0, nil
}
- address := stack.peek().Bytes20()
+ address := stack.Peek().Bytes20()
gas := evm.AccessEvents.BasicDataGas(address, false)
if gas == 0 {
gas = params.WarmStorageReadCostEIP2929
@@ -53,7 +53,7 @@ func gasBalance4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, mem
}
func gasExtCodeSize4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- address := stack.peek().Bytes20()
+ address := stack.Peek().Bytes20()
if _, isPrecompile := evm.precompile(address); isPrecompile {
return 0, nil
}
@@ -71,7 +71,7 @@ func gasExtCodeHash4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory,
if contract.IsSystemCall {
return 0, nil
}
- address := stack.peek().Bytes20()
+ address := stack.Peek().Bytes20()
if _, isPrecompile := evm.precompile(address); isPrecompile {
return 0, nil
}
@@ -110,7 +110,7 @@ var (
)
func gasSelfdestructEIP4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
- beneficiaryAddr := common.Address(stack.peek().Bytes20())
+ beneficiaryAddr := common.Address(stack.Peek().Bytes20())
if _, isPrecompile := evm.precompile(beneficiaryAddr); isPrecompile {
return 0, nil
}
@@ -161,7 +161,7 @@ func gasExtCodeCopyEIP4762(evm *EVM, contract *Contract, stack *Stack, mem *Memo
if contract.IsSystemCall {
return gas, nil
}
- addr := common.Address(stack.peek().Bytes20())
+ addr := common.Address(stack.Peek().Bytes20())
wgas := evm.AccessEvents.BasicDataGas(addr, false)
if wgas == 0 {
wgas = params.WarmStorageReadCostEIP2929
diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go
index 2243e14b65a9..ae815b54a270 100644
--- a/core/vm/runtime/runtime.go
+++ b/core/vm/runtime/runtime.go
@@ -49,12 +49,12 @@ type Config struct {
BlobFeeCap *big.Int
Random *common.Hash
- State *state.StateDB
+ State vm.StateDB
GetHashFn func(n uint64) common.Hash
}
// sets defaults on the config
-func setDefaults(cfg *Config) {
+func SetDefaults(cfg *Config) {
if cfg.ChainConfig == nil {
var (
shanghaiTime = uint64(0)
@@ -116,11 +116,11 @@ func setDefaults(cfg *Config) {
//
// Execute sets up an in-memory, temporary, environment for the execution of
// the given code. It makes sure that it's restored to its original state afterwards.
-func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
+func Execute(code, input []byte, cfg *Config) ([]byte, vm.StateDB, error) {
if cfg == nil {
cfg = new(Config)
}
- setDefaults(cfg)
+ SetDefaults(cfg)
if cfg.State == nil {
cfg.State, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
@@ -160,7 +160,7 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) {
if cfg == nil {
cfg = new(Config)
}
- setDefaults(cfg)
+ SetDefaults(cfg)
if cfg.State == nil {
cfg.State, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
@@ -196,7 +196,7 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) {
// Call, unlike Execute, requires a config and also requires the State field to
// be set.
func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, error) {
- setDefaults(cfg)
+ SetDefaults(cfg)
var (
vmenv = NewEnv(cfg)
diff --git a/core/vm/runtime/runtime_test.go b/core/vm/runtime/runtime_test.go
index bde230b6da12..5ccafa6248ec 100644
--- a/core/vm/runtime/runtime_test.go
+++ b/core/vm/runtime/runtime_test.go
@@ -45,7 +45,7 @@ import (
func TestDefaults(t *testing.T) {
cfg := new(Config)
- setDefaults(cfg)
+ SetDefaults(cfg)
if cfg.Difficulty == nil {
t.Error("expected difficulty to be non nil")
@@ -397,7 +397,7 @@ func TestBlockhash(t *testing.T) {
// state, this should not be used, since it does not reset the state between runs.
func benchmarkNonModifyingCode(gas uint64, code []byte, name string, tracerCode string, b *testing.B) {
cfg := new(Config)
- setDefaults(cfg)
+ SetDefaults(cfg)
cfg.State, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
cfg.GasLimit = gas
if len(tracerCode) > 0 {
diff --git a/core/vm/stack.go b/core/vm/stack.go
index 879dc9aa6d82..23d970a13cab 100644
--- a/core/vm/stack.go
+++ b/core/vm/stack.go
@@ -35,7 +35,7 @@ type Stack struct {
data []uint256.Int
}
-func newstack() *Stack {
+func Newstack() *Stack {
return stackPool.Get().(*Stack)
}
@@ -49,79 +49,79 @@ func (st *Stack) Data() []uint256.Int {
return st.data
}
-func (st *Stack) push(d *uint256.Int) {
+func (st *Stack) Push(d *uint256.Int) {
// NOTE push limit (1024) is checked in baseCheck
st.data = append(st.data, *d)
}
-func (st *Stack) pop() (ret uint256.Int) {
+func (st *Stack) Pop() (ret uint256.Int) {
ret = st.data[len(st.data)-1]
st.data = st.data[:len(st.data)-1]
return
}
-func (st *Stack) len() int {
+func (st *Stack) Len() int {
return len(st.data)
}
func (st *Stack) swap1() {
- st.data[st.len()-2], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-2]
+ st.data[st.Len()-2], st.data[st.Len()-1] = st.data[st.Len()-1], st.data[st.Len()-2]
}
func (st *Stack) swap2() {
- st.data[st.len()-3], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-3]
+ st.data[st.Len()-3], st.data[st.Len()-1] = st.data[st.Len()-1], st.data[st.Len()-3]
}
func (st *Stack) swap3() {
- st.data[st.len()-4], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-4]
+ st.data[st.Len()-4], st.data[st.Len()-1] = st.data[st.Len()-1], st.data[st.Len()-4]
}
func (st *Stack) swap4() {
- st.data[st.len()-5], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-5]
+ st.data[st.Len()-5], st.data[st.Len()-1] = st.data[st.Len()-1], st.data[st.Len()-5]
}
func (st *Stack) swap5() {
- st.data[st.len()-6], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-6]
+ st.data[st.Len()-6], st.data[st.Len()-1] = st.data[st.Len()-1], st.data[st.Len()-6]
}
func (st *Stack) swap6() {
- st.data[st.len()-7], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-7]
+ st.data[st.Len()-7], st.data[st.Len()-1] = st.data[st.Len()-1], st.data[st.Len()-7]
}
func (st *Stack) swap7() {
- st.data[st.len()-8], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-8]
+ st.data[st.Len()-8], st.data[st.Len()-1] = st.data[st.Len()-1], st.data[st.Len()-8]
}
func (st *Stack) swap8() {
- st.data[st.len()-9], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-9]
+ st.data[st.Len()-9], st.data[st.Len()-1] = st.data[st.Len()-1], st.data[st.Len()-9]
}
func (st *Stack) swap9() {
- st.data[st.len()-10], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-10]
+ st.data[st.Len()-10], st.data[st.Len()-1] = st.data[st.Len()-1], st.data[st.Len()-10]
}
func (st *Stack) swap10() {
- st.data[st.len()-11], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-11]
+ st.data[st.Len()-11], st.data[st.Len()-1] = st.data[st.Len()-1], st.data[st.Len()-11]
}
func (st *Stack) swap11() {
- st.data[st.len()-12], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-12]
+ st.data[st.Len()-12], st.data[st.Len()-1] = st.data[st.Len()-1], st.data[st.Len()-12]
}
func (st *Stack) swap12() {
- st.data[st.len()-13], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-13]
+ st.data[st.Len()-13], st.data[st.Len()-1] = st.data[st.Len()-1], st.data[st.Len()-13]
}
func (st *Stack) swap13() {
- st.data[st.len()-14], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-14]
+ st.data[st.Len()-14], st.data[st.Len()-1] = st.data[st.Len()-1], st.data[st.Len()-14]
}
func (st *Stack) swap14() {
- st.data[st.len()-15], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-15]
+ st.data[st.Len()-15], st.data[st.Len()-1] = st.data[st.Len()-1], st.data[st.Len()-15]
}
func (st *Stack) swap15() {
- st.data[st.len()-16], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-16]
+ st.data[st.Len()-16], st.data[st.Len()-1] = st.data[st.Len()-1], st.data[st.Len()-16]
}
func (st *Stack) swap16() {
- st.data[st.len()-17], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-17]
+ st.data[st.Len()-17], st.data[st.Len()-1] = st.data[st.Len()-1], st.data[st.Len()-17]
}
func (st *Stack) dup(n int) {
- st.push(&st.data[st.len()-n])
+ st.Push(&st.data[st.Len()-n])
}
-func (st *Stack) peek() *uint256.Int {
- return &st.data[st.len()-1]
+func (st *Stack) Peek() *uint256.Int {
+ return &st.data[st.Len()-1]
}
// Back returns the n'th item in stack
func (st *Stack) Back(n int) *uint256.Int {
- return &st.data[st.len()-n-1]
+ return &st.data[st.Len()-n-1]
}
diff --git a/eth/api_backend.go b/eth/api_backend.go
index 66621190ddcf..3ca9d5ce298b 100644
--- a/eth/api_backend.go
+++ b/eth/api_backend.go
@@ -30,7 +30,6 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/bloombits"
"github.com/ethereum/go-ethereum/core/rawdb"
- "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
@@ -182,11 +181,11 @@ func (b *EthAPIBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash r
return nil, errors.New("invalid arguments; neither block nor hash specified")
}
-func (b *EthAPIBackend) Pending() (*types.Block, types.Receipts, *state.StateDB) {
+func (b *EthAPIBackend) Pending() (*types.Block, types.Receipts, vm.StateDB) {
return b.eth.miner.Pending()
}
-func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) {
+func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (vm.StateDB, *types.Header, error) {
// Pending state is only known by the miner
if number == rpc.PendingBlockNumber {
block, _, state := b.eth.miner.Pending()
@@ -210,7 +209,7 @@ func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.B
return stateDb, header, nil
}
-func (b *EthAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) {
+func (b *EthAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (vm.StateDB, *types.Header, error) {
if blockNr, ok := blockNrOrHash.Number(); ok {
return b.StateAndHeaderByNumber(ctx, blockNr)
}
@@ -242,7 +241,7 @@ func (b *EthAPIBackend) GetLogs(ctx context.Context, hash common.Hash, number ui
return rawdb.ReadLogs(b.eth.chainDb, hash, number), nil
}
-func (b *EthAPIBackend) GetEVM(ctx context.Context, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM {
+func (b *EthAPIBackend) GetEVM(ctx context.Context, msg *core.Message, state vm.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM {
if vmConfig == nil {
vmConfig = b.eth.blockchain.GetVMConfig()
}
@@ -415,10 +414,10 @@ func (b *EthAPIBackend) CurrentHeader() *types.Header {
return b.eth.blockchain.CurrentHeader()
}
-func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, tracers.StateReleaseFunc, error) {
+func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base vm.StateDB, readOnly bool, preferDisk bool) (vm.StateDB, tracers.StateReleaseFunc, error) {
return b.eth.stateAtBlock(ctx, block, reexec, base, readOnly, preferDisk)
}
-func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) {
+func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, vm.StateDB, tracers.StateReleaseFunc, error) {
return b.eth.stateAtTransaction(ctx, block, txIndex, reexec)
}
diff --git a/eth/api_debug.go b/eth/api_debug.go
index d5e4dda1401c..eb9d04ef51bd 100644
--- a/eth/api_debug.go
+++ b/eth/api_debug.go
@@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/log"
@@ -229,13 +230,13 @@ func (api *DebugAPI) StorageRangeAt(ctx context.Context, blockNrOrHash rpc.Block
return storageRangeAt(statedb, block.Root(), contractAddress, keyStart, maxResult)
}
-func storageRangeAt(statedb *state.StateDB, root common.Hash, address common.Address, start []byte, maxResult int) (StorageRangeResult, error) {
+func storageRangeAt(statedb vm.StateDB, root common.Hash, address common.Address, start []byte, maxResult int) (StorageRangeResult, error) {
storageRoot := statedb.GetStorageRoot(address)
if storageRoot == types.EmptyRootHash || storageRoot == (common.Hash{}) {
return StorageRangeResult{}, nil // empty storage
}
id := trie.StorageTrieID(root, crypto.Keccak256Hash(address.Bytes()), storageRoot)
- tr, err := trie.NewStateTrie(id, statedb.Database().TrieDB())
+ tr, err := trie.NewStateTrie(id, statedb.(*state.StateDB).Database().TrieDB())
if err != nil {
return StorageRangeResult{}, err
}
diff --git a/eth/gasestimator/gasestimator.go b/eth/gasestimator/gasestimator.go
index a6c4718cf4a2..0b52d09d1d31 100644
--- a/eth/gasestimator/gasestimator.go
+++ b/eth/gasestimator/gasestimator.go
@@ -25,7 +25,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/internal/ethapi/override"
@@ -42,7 +41,7 @@ type Options struct {
Config *params.ChainConfig // Chain configuration for hard fork selection
Chain core.ChainContext // Chain context to access past block hashes
Header *types.Header // Header defining the block context to execute in
- State *state.StateDB // Pre-state on top of which to estimate the gas
+ State vm.StateDB // Pre-state on top of which to estimate the gas
BlockOverrides *override.BlockOverrides // Block overrides to apply during the estimation
ErrorRatio float64 // Allowed overestimation ratio for faster estimation termination
@@ -197,9 +196,16 @@ func Estimate(ctx context.Context, call *core.Message, opts *Options, gasCap uin
// returns true if the transaction fails for a reason that might be related to
// not enough gas. A non-nil error means execution failed due to reasons unrelated
// to the gas limit.
-func execute(ctx context.Context, call *core.Message, opts *Options, gasLimit uint64) (bool, *core.ExecutionResult, error) {
+func execute(ctx context.Context, call *core.Message, opts *Options, gasLimit uint64) (failed bool, execResult *core.ExecutionResult, err error) {
// Configure the call for this specific execution (and revert the change after)
defer func(gas uint64) { call.GasLimit = gas }(call.GasLimit)
+ defer func() {
+ if r := recover(); r != nil {
+ failed = true
+ execResult = nil
+ err = nil
+ }
+ }()
call.GasLimit = gasLimit
// Execute the call and separate execution faults caused by a lack of gas or
@@ -234,6 +240,7 @@ func run(ctx context.Context, call *core.Message, opts *Options) (*core.Executio
evmContext.BlobBaseFee = new(big.Int)
}
evm := vm.NewEVM(evmContext, dirtyState, opts.Config, vm.Config{NoBaseFee: true})
+ dirtyState.SetEVM(evm)
// Monitor the outer context and interrupt the EVM upon cancellation. To avoid
// a dangling goroutine until the outer estimation finishes, create an internal
diff --git a/eth/gasprice/gasprice.go b/eth/gasprice/gasprice.go
index 4fd3df742853..2bbceefad6de 100644
--- a/eth/gasprice/gasprice.go
+++ b/eth/gasprice/gasprice.go
@@ -25,8 +25,8 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/lru"
"github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
@@ -54,7 +54,7 @@ type OracleBackend interface {
HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error)
GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error)
- Pending() (*types.Block, types.Receipts, *state.StateDB)
+ Pending() (*types.Block, types.Receipts, vm.StateDB)
ChainConfig() *params.ChainConfig
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
}
diff --git a/eth/gasprice/gasprice_test.go b/eth/gasprice/gasprice_test.go
index 0a32c278cbf4..f785b5d01366 100644
--- a/eth/gasprice/gasprice_test.go
+++ b/eth/gasprice/gasprice_test.go
@@ -28,7 +28,6 @@ import (
"github.com/ethereum/go-ethereum/consensus/beacon"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
@@ -102,7 +101,7 @@ func (b *testBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.
return b.chain.GetReceiptsByHash(hash), nil
}
-func (b *testBackend) Pending() (*types.Block, types.Receipts, *state.StateDB) {
+func (b *testBackend) Pending() (*types.Block, types.Receipts, vm.StateDB) {
if b.pending {
block := b.chain.GetBlockByNumber(testHead + 1)
state, _ := b.chain.StateAt(block.Root())
diff --git a/eth/state_accessor.go b/eth/state_accessor.go
index 99ed28d96afc..45601517f52e 100644
--- a/eth/state_accessor.go
+++ b/eth/state_accessor.go
@@ -38,7 +38,7 @@ import (
// for releasing state.
var noopReleaser = tracers.StateReleaseFunc(func() {})
-func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (statedb *state.StateDB, release tracers.StateReleaseFunc, err error) {
+func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec uint64, base vm.StateDB, readOnly bool, preferDisk bool) (statedb vm.StateDB, release tracers.StateReleaseFunc, err error) {
var (
current *types.Block
database state.Database
@@ -76,7 +76,7 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u
}
}
// The optional base statedb is given, mark the start point as parent block
- statedb, database, tdb, report = base, base.Database(), base.Database().TrieDB(), false
+ statedb, database, tdb, report = base, base.(*state.StateDB).Database(), base.(*state.StateDB).Database().TrieDB(), false
current = eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1)
} else {
// Otherwise, try to reexec blocks until we find a state or reach our limit
@@ -210,7 +210,7 @@ func (eth *Ethereum) pathState(block *types.Block) (*state.StateDB, func(), erro
// - preferDisk: This arg can be used by the caller to signal that even though the 'base' is
// provided, it would be preferable to start from a fresh state, if we have it
// on disk.
-func (eth *Ethereum) stateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (statedb *state.StateDB, release tracers.StateReleaseFunc, err error) {
+func (eth *Ethereum) stateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base vm.StateDB, readOnly bool, preferDisk bool) (statedb vm.StateDB, release tracers.StateReleaseFunc, err error) {
if eth.blockchain.TrieDB().Scheme() == rawdb.HashScheme {
return eth.hashState(ctx, block, reexec, base, readOnly, preferDisk)
}
@@ -218,7 +218,7 @@ func (eth *Ethereum) stateAtBlock(ctx context.Context, block *types.Block, reexe
}
// stateAtTransaction returns the execution environment of a certain transaction.
-func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) {
+func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, vm.StateDB, tracers.StateReleaseFunc, error) {
// Short circuit if it's genesis block.
if block.NumberU64() == 0 {
return nil, vm.BlockContext{}, nil, nil, errors.New("no transaction in genesis")
diff --git a/eth/tracers/api.go b/eth/tracers/api.go
index d13aee555f46..134aad45fd68 100644
--- a/eth/tracers/api.go
+++ b/eth/tracers/api.go
@@ -25,6 +25,7 @@ import (
"math/big"
"os"
"runtime"
+ "strings"
"sync"
"time"
@@ -87,8 +88,8 @@ type Backend interface {
ChainConfig() *params.ChainConfig
Engine() consensus.Engine
ChainDb() ethdb.Database
- StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, StateReleaseFunc, error)
- StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, *state.StateDB, StateReleaseFunc, error)
+ StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base vm.StateDB, readOnly bool, preferDisk bool) (vm.StateDB, StateReleaseFunc, error)
+ StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, vm.StateDB, StateReleaseFunc, error)
}
// API is the collection of tracing APIs exposed over the private debugging endpoint.
@@ -176,8 +177,8 @@ type StdTraceConfig struct {
TxHash common.Hash
}
-// txTraceResult is the result of a single transaction trace.
-type txTraceResult struct {
+// TxTraceResult is the result of a single transaction trace.
+type TxTraceResult struct {
TxHash common.Hash `json:"txHash"` // transaction hash
Result interface{} `json:"result,omitempty"` // Trace results produced by the tracer
Error string `json:"error,omitempty"` // Trace failure produced by the tracer
@@ -186,10 +187,10 @@ type txTraceResult struct {
// blockTraceTask represents a single block trace task when an entire chain is
// being traced.
type blockTraceTask struct {
- statedb *state.StateDB // Intermediate state prepped for tracing
+ statedb vm.StateDB // Intermediate state prepped for tracing
block *types.Block // Block to trace the transactions from
release StateReleaseFunc // The function to release the held resource for this task
- results []*txTraceResult // Trace results produced by the task
+ results []*TxTraceResult // Trace results produced by the task
}
// blockTraceResult represents the results of tracing a single block when an entire
@@ -197,14 +198,14 @@ type blockTraceTask struct {
type blockTraceResult struct {
Block hexutil.Uint64 `json:"block"` // Block number corresponding to this trace
Hash common.Hash `json:"hash"` // Block hash corresponding to this trace
- Traces []*txTraceResult `json:"traces"` // Trace results produced by the task
+ Traces []*TxTraceResult `json:"traces"` // Trace results produced by the task
}
// txTraceTask represents a single transaction trace task when an entire block
// is being traced.
type txTraceTask struct {
- statedb *state.StateDB // Intermediate state prepped for tracing
- index int // Transaction offset in the block
+ statedb vm.StateDB // Intermediate state prepped for tracing
+ index int // Transaction offset in the block
}
// TraceChain returns the structured logs created during the execution of EVM
@@ -281,11 +282,11 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
}
res, err := api.traceTx(ctx, tx, msg, txctx, blockCtx, task.statedb, config)
if err != nil {
- task.results[i] = &txTraceResult{TxHash: tx.Hash(), Error: err.Error()}
+ task.results[i] = &TxTraceResult{TxHash: tx.Hash(), Error: err.Error()}
log.Warn("Tracing failed", "hash", tx.Hash(), "block", task.block.NumberU64(), "err", err)
break
}
- task.results[i] = &txTraceResult{TxHash: tx.Hash(), Result: res}
+ task.results[i] = &TxTraceResult{TxHash: tx.Hash(), Result: res}
}
// Tracing state is used up, queue it for de-referencing. Note the
// state is the parent state of trace block, use block.number-1 as
@@ -309,7 +310,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
number uint64
traced uint64
failed error
- statedb *state.StateDB
+ statedb vm.StateDB
release StateReleaseFunc
)
// Ensure everything is properly cleaned up on any exit path
@@ -369,7 +370,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
// if the relevant state is available in disk.
var preferDisk bool
if statedb != nil {
- s1, s2, s3 := statedb.Database().TrieDB().Size()
+ s1, s2, s3 := statedb.(*state.StateDB).Database().TrieDB().Size()
preferDisk = s1+s2+s3 > defaultTracechainMemLimit
}
statedb, release, err = api.backend.StateAtBlock(ctx, block, reexec, statedb, false, preferDisk)
@@ -397,7 +398,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
// Send the block over to the concurrent tracers (if not in the fast-forward phase)
txs := next.Transactions()
select {
- case taskCh <- &blockTraceTask{statedb: statedb.Copy(), block: next, release: release, results: make([]*txTraceResult, len(txs))}:
+ case taskCh <- &blockTraceTask{statedb: statedb.Copy(), block: next, release: release, results: make([]*TxTraceResult, len(txs))}:
case <-closed:
tracker.releaseState(number, release)
return
@@ -442,7 +443,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
// TraceBlockByNumber returns the structured logs created during the execution of
// EVM and returns them as a JSON object.
-func (api *API) TraceBlockByNumber(ctx context.Context, number rpc.BlockNumber, config *TraceConfig) ([]*txTraceResult, error) {
+func (api *API) TraceBlockByNumber(ctx context.Context, number rpc.BlockNumber, config *TraceConfig) ([]*TxTraceResult, error) {
block, err := api.blockByNumber(ctx, number)
if err != nil {
return nil, err
@@ -452,7 +453,7 @@ func (api *API) TraceBlockByNumber(ctx context.Context, number rpc.BlockNumber,
// TraceBlockByHash returns the structured logs created during the execution of
// EVM and returns them as a JSON object.
-func (api *API) TraceBlockByHash(ctx context.Context, hash common.Hash, config *TraceConfig) ([]*txTraceResult, error) {
+func (api *API) TraceBlockByHash(ctx context.Context, hash common.Hash, config *TraceConfig) ([]*TxTraceResult, error) {
block, err := api.blockByHash(ctx, hash)
if err != nil {
return nil, err
@@ -462,7 +463,7 @@ func (api *API) TraceBlockByHash(ctx context.Context, hash common.Hash, config *
// TraceBlock returns the structured logs created during the execution of EVM
// and returns them as a JSON object.
-func (api *API) TraceBlock(ctx context.Context, blob hexutil.Bytes, config *TraceConfig) ([]*txTraceResult, error) {
+func (api *API) TraceBlock(ctx context.Context, blob hexutil.Bytes, config *TraceConfig) ([]*TxTraceResult, error) {
block := new(types.Block)
if err := rlp.DecodeBytes(blob, block); err != nil {
return nil, fmt.Errorf("could not decode block: %v", err)
@@ -472,7 +473,7 @@ func (api *API) TraceBlock(ctx context.Context, blob hexutil.Bytes, config *Trac
// TraceBlockFromFile returns the structured logs created during the execution of
// EVM and returns them as a JSON object.
-func (api *API) TraceBlockFromFile(ctx context.Context, file string, config *TraceConfig) ([]*txTraceResult, error) {
+func (api *API) TraceBlockFromFile(ctx context.Context, file string, config *TraceConfig) ([]*TxTraceResult, error) {
blob, err := os.ReadFile(file)
if err != nil {
return nil, fmt.Errorf("could not read file: %v", err)
@@ -483,7 +484,7 @@ func (api *API) TraceBlockFromFile(ctx context.Context, file string, config *Tra
// TraceBadBlock returns the structured logs created during the execution of
// EVM against a block pulled from the pool of bad ones and returns them as a JSON
// object.
-func (api *API) TraceBadBlock(ctx context.Context, hash common.Hash, config *TraceConfig) ([]*txTraceResult, error) {
+func (api *API) TraceBadBlock(ctx context.Context, hash common.Hash, config *TraceConfig) ([]*TxTraceResult, error) {
block := rawdb.ReadBadBlock(api.backend.ChainDb(), hash)
if block == nil {
return nil, fmt.Errorf("bad block %#x not found", hash)
@@ -580,7 +581,7 @@ func (api *API) StandardTraceBadBlockToFile(ctx context.Context, hash common.Has
// traceBlock configures a new tracer according to the provided configuration, and
// executes all the transactions contained within. The return value will be one item
// per transaction, dependent on the requested tracer.
-func (api *API) traceBlock(ctx context.Context, block *types.Block, config *TraceConfig) ([]*txTraceResult, error) {
+func (api *API) traceBlock(ctx context.Context, block *types.Block, config *TraceConfig) ([]*TxTraceResult, error) {
if block.NumberU64() == 0 {
return nil, errors.New("genesis is not traceable")
}
@@ -621,7 +622,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
txs = block.Transactions()
blockHash = block.Hash()
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
- results = make([]*txTraceResult, len(txs))
+ results = make([]*TxTraceResult, len(txs))
)
for i, tx := range txs {
// Generate the next state snapshot fast without tracing
@@ -634,9 +635,10 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
}
res, err := api.traceTx(ctx, tx, msg, txctx, blockCtx, statedb, config)
if err != nil {
- return nil, err
+ results[i] = &TxTraceResult{TxHash: tx.Hash(), Error: err.Error()}
+ } else {
+ results[i] = &TxTraceResult{TxHash: tx.Hash(), Result: res}
}
- results[i] = &txTraceResult{TxHash: tx.Hash(), Result: res}
}
return results, nil
}
@@ -644,13 +646,13 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
// traceBlockParallel is for tracers that have a high overhead (read JS tracers). One thread
// runs along and executes txes without tracing enabled to generate their prestate.
// Worker threads take the tasks and the prestate and trace them.
-func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, statedb *state.StateDB, config *TraceConfig) ([]*txTraceResult, error) {
+func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, statedb vm.StateDB, config *TraceConfig) ([]*TxTraceResult, error) {
// Execute all the transaction contained within the block concurrently
var (
txs = block.Transactions()
blockHash = block.Hash()
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
- results = make([]*txTraceResult, len(txs))
+ results = make([]*TxTraceResult, len(txs))
pend sync.WaitGroup
)
threads := runtime.NumCPU()
@@ -678,10 +680,10 @@ func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, stat
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
res, err := api.traceTx(ctx, txs[task.index], msg, txctx, blockCtx, task.statedb, config)
if err != nil {
- results[task.index] = &txTraceResult{TxHash: txs[task.index].Hash(), Error: err.Error()}
+ results[task.index] = &TxTraceResult{TxHash: txs[task.index].Hash(), Error: err.Error()}
continue
}
- results[task.index] = &txTraceResult{TxHash: txs[task.index].Hash(), Result: res}
+ results[task.index] = &TxTraceResult{TxHash: txs[task.index].Hash(), Result: res}
}
}()
}
@@ -857,7 +859,13 @@ func containsTx(block *types.Block, hash common.Hash) bool {
// TraceTransaction returns the structured logs created during the execution of EVM
// and returns them as a JSON object.
-func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *TraceConfig) (interface{}, error) {
+func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *TraceConfig) (value interface{}, returnErr error) {
+ defer func() {
+ if r := recover(); r != nil {
+ value = nil
+ returnErr = fmt.Errorf("panic occurred: %v, could not trace tx: %s", r, hash.Hex())
+ }
+ }()
found, _, blockHash, blockNumber, index, err := api.backend.GetTransaction(ctx, hash)
if err != nil {
return nil, ethapi.NewTxIndexingError()
@@ -904,12 +912,18 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *
// after executing the specified block. However, if a transaction index is provided,
// the trace will be conducted on the state after executing the specified transaction
// within the specified block.
-func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, config *TraceCallConfig) (interface{}, error) {
+func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, config *TraceCallConfig) (value interface{}, returnErr error) {
+ defer func() {
+ if r := recover(); r != nil {
+ value = nil
+ returnErr = fmt.Errorf("panic occurred: %v, could not trace tx: %s", r, args.ToTransaction(types.LegacyTxType).Hash().Hex())
+ }
+ }()
// Try to retrieve the specified block
var (
err error
block *types.Block
- statedb *state.StateDB
+ statedb vm.StateDB
release StateReleaseFunc
)
if hash, ok := blockNrOrHash.Hash(); ok {
@@ -983,13 +997,19 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
// traceTx configures a new tracer according to the provided configuration, and
// executes the given message in the provided environment. The return value will
// be tracer dependent.
-func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *core.Message, txctx *Context, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig) (interface{}, error) {
+func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *core.Message, txctx *Context, vmctx vm.BlockContext, statedb vm.StateDB, config *TraceConfig) (value interface{}, returnErr error) {
var (
tracer *Tracer
err error
timeout = defaultTraceTimeout
usedGas uint64
)
+ defer func() {
+ if r := recover(); r != nil {
+ value = nil
+ returnErr = fmt.Errorf("panic occurred: %v, could not trace tx: %s", r, tx.Hash())
+ }
+ }()
if config == nil {
config = &TraceConfig{}
}
@@ -1031,6 +1051,10 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor
statedb.SetTxContext(txctx.TxHash, txctx.TxIndex)
_, err = core.ApplyTransactionWithEVM(message, new(core.GasPool).AddGas(message.GasLimit), statedb, vmctx.BlockNumber, txctx.BlockHash, tx, &usedGas, evm)
if err != nil {
+ // Due to how our mempool works, a transaction with insufficient funds can be included in a block. For tracing purposes, we should ignore this.
+ if strings.Contains(err.Error(), core.ErrInsufficientFunds.Error()) {
+ return json.RawMessage(`{}`), nil
+ }
return nil, fmt.Errorf("tracing failed: %w", err)
}
return tracer.GetResult()
diff --git a/eth/tracers/api_test.go b/eth/tracers/api_test.go
index 95e7739be06b..6ef268f065f7 100644
--- a/eth/tracers/api_test.go
+++ b/eth/tracers/api_test.go
@@ -36,7 +36,6 @@ import (
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
- "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
@@ -142,7 +141,7 @@ func (b *testBackend) teardown() {
b.chain.Stop()
}
-func (b *testBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, StateReleaseFunc, error) {
+func (b *testBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base vm.StateDB, readOnly bool, preferDisk bool) (vm.StateDB, StateReleaseFunc, error) {
statedb, err := b.chain.StateAt(block.Root())
if err != nil {
return nil, nil, errStateNotFound
@@ -158,7 +157,7 @@ func (b *testBackend) StateAtBlock(ctx context.Context, block *types.Block, reex
return statedb, release, nil
}
-func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, *state.StateDB, StateReleaseFunc, error) {
+func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, vm.StateDB, StateReleaseFunc, error) {
parent := b.chain.GetBlock(block.ParentHash(), block.NumberU64()-1)
if parent == nil {
return nil, vm.BlockContext{}, nil, nil, errBlockNotFound
@@ -548,6 +547,70 @@ func TestTraceTransaction(t *testing.T) {
}
}
+func TestTracePanicTransaction(t *testing.T) {
+ t.Parallel()
+ // Initialize test accounts
+ accounts := newAccounts(2)
+ genesis := &core.Genesis{
+ Config: params.TestChainConfig,
+ Alloc: types.GenesisAlloc{
+ accounts[0].addr: {Balance: big.NewInt(params.Ether)},
+ accounts[1].addr: {Balance: big.NewInt(params.Ether)},
+ },
+ }
+ target := common.Hash{}
+ signer := types.HomesteadSigner{}
+ backend := newTestBackend(t, 1, genesis, func(i int, b *core.BlockGen) {
+ // Transfer from account[0] to account[1]
+ tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
+ Nonce: uint64(i),
+ To: &accounts[1].addr,
+ Value: big.NewInt(1000),
+ Gas: params.TxGas,
+ GasPrice: b.BaseFee(),
+ Data: nil}),
+ signer, accounts[0].key)
+ b.AddTx(tx)
+ target = tx.Hash()
+ })
+ defer backend.chain.Stop()
+ // Create API with a backend that uses a panic-inducing StateDB
+ panicBackend := &panicBackend{backend}
+ api := NewAPI(panicBackend)
+ result, err := api.TraceTransaction(context.Background(), target, nil)
+ // Verify panic was caught and handled
+ if err == nil {
+ t.Fatal("Expected error from panic recovery, got nil")
+ }
+ if result != nil {
+ t.Errorf("Expected nil result after panic, got %v", result)
+ }
+}
+
+type panicBackend struct {
+ Backend
+}
+
+// StateAtTransaction overrides the backend's StateAtTransaction to use a panic-inducing StateDB
+func (b *panicBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, vm.StateDB, StateReleaseFunc, error) {
+ tx, vmctx, _, release, err := b.Backend.StateAtTransaction(ctx, block, txIndex, reexec)
+ if err != nil {
+ return nil, vm.BlockContext{}, nil, nil, err
+ }
+ // Return a StateDB that panics on ApplyTransactionWithEVM
+ return tx, vmctx, &panicStateDB{}, release, nil
+}
+
+// panicStateDB is a mock StateDB that panics during ApplyTransactionWithEVM
+type panicStateDB struct {
+ vm.StateDB
+}
+
+// ApplyTransactionWithEVM is overridden to panic
+func (s *panicStateDB) ApplyTransactionWithEVM(message *core.Message, config *params.ChainConfig, gasPool *core.GasPool, statedb vm.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) ([]byte, error) {
+ panic("intentional panic for testing")
+}
+
func TestTraceBlock(t *testing.T) {
t.Parallel()
diff --git a/export/ethapi.go b/export/ethapi.go
new file mode 100644
index 000000000000..ff8c052408c9
--- /dev/null
+++ b/export/ethapi.go
@@ -0,0 +1,19 @@
+package export
+
+import (
+ "github.com/ethereum/go-ethereum/internal/ethapi"
+ "github.com/ethereum/go-ethereum/internal/ethapi/override"
+)
+
+type RPCTransaction = ethapi.RPCTransaction
+type SignTransactionResult = ethapi.SignTransactionResult
+type TransactionArgs = ethapi.TransactionArgs
+type StateOverride = override.StateOverride
+type BlockOverrides = override.BlockOverrides
+
+var NewRPCTransaction = ethapi.NewRPCTransaction
+var AccessList = ethapi.AccessList
+var DoEstimateGas = ethapi.DoEstimateGas
+var DoEstimateGasAfterCalls = ethapi.DoEstimateGasAfterCalls
+var DoCall = ethapi.DoCall
+var NewRPCPendingTransaction = ethapi.NewRPCPendingTransaction
diff --git a/graphql/graphql.go b/graphql/graphql.go
index 7af1adbb4a8e..1e50f52d5ab6 100644
--- a/graphql/graphql.go
+++ b/graphql/graphql.go
@@ -31,8 +31,8 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
- "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/filters"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/rlp"
@@ -85,7 +85,7 @@ type Account struct {
}
// getState fetches the StateDB object for an account.
-func (a *Account) getState(ctx context.Context) (*state.StateDB, error) {
+func (a *Account) getState(ctx context.Context) (vm.StateDB, error) {
state, _, err := a.r.backend.StateAndHeaderByNumberOrHash(ctx, a.blockNrOrHash)
return state, err
}
diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go
index c0b37c516b09..d9800d81d7db 100644
--- a/internal/ethapi/api.go
+++ b/internal/ethapi/api.go
@@ -387,7 +387,7 @@ func (api *BlockChainAPI) GetProof(ctx context.Context, address common.Address,
var storageTrie state.Trie
if storageRoot != types.EmptyRootHash && storageRoot != (common.Hash{}) {
id := trie.StorageTrieID(header.Root, crypto.Keccak256Hash(address.Bytes()), storageRoot)
- st, err := trie.NewStateTrie(id, statedb.Database().TrieDB())
+ st, err := trie.NewStateTrie(id, statedb.(*state.StateDB).Database().TrieDB())
if err != nil {
return nil, err
}
@@ -418,7 +418,7 @@ func (api *BlockChainAPI) GetProof(ctx context.Context, address common.Address,
}
}
// Create the accountProof.
- tr, err := trie.NewStateTrie(trie.StateTrieID(header.Root), statedb.Database().TrieDB())
+ tr, err := trie.NewStateTrie(trie.StateTrieID(header.Root), statedb.(*state.StateDB).Database().TrieDB())
if err != nil {
return nil, err
}
@@ -657,7 +657,7 @@ func (context *ChainContext) Config() *params.ChainConfig {
return context.b.ChainConfig()
}
-func doCall(ctx context.Context, b Backend, args TransactionArgs, state *state.StateDB, header *types.Header, overrides *override.StateOverride, blockOverrides *override.BlockOverrides, timeout time.Duration, globalGasCap uint64) (*core.ExecutionResult, error) {
+func doCall(ctx context.Context, b Backend, args TransactionArgs, state vm.StateDB, header *types.Header, overrides *override.StateOverride, blockOverrides *override.BlockOverrides, timeout time.Duration, globalGasCap uint64) (*core.ExecutionResult, error) {
blockCtx := core.NewEVMBlockContext(header, NewChainContext(ctx, b), nil)
if blockOverrides != nil {
blockOverrides.Apply(&blockCtx)
@@ -688,7 +688,7 @@ func doCall(ctx context.Context, b Backend, args TransactionArgs, state *state.S
return applyMessage(ctx, b, args, state, header, timeout, gp, &blockCtx, &vm.Config{NoBaseFee: true}, precompiles, true)
}
-func applyMessage(ctx context.Context, b Backend, args TransactionArgs, state *state.StateDB, header *types.Header, timeout time.Duration, gp *core.GasPool, blockContext *vm.BlockContext, vmConfig *vm.Config, precompiles vm.PrecompiledContracts, skipChecks bool) (*core.ExecutionResult, error) {
+func applyMessage(ctx context.Context, b Backend, args TransactionArgs, state vm.StateDB, header *types.Header, timeout time.Duration, gp *core.GasPool, blockContext *vm.BlockContext, vmConfig *vm.Config, precompiles vm.PrecompiledContracts, skipChecks bool) (*core.ExecutionResult, error) {
// Get a new instance of the EVM.
if err := args.CallDefaults(gp.Gas(), blockContext.BaseFee, b.ChainConfig().ChainID); err != nil {
return nil, err
@@ -702,7 +702,7 @@ func applyMessage(ctx context.Context, b Backend, args TransactionArgs, state *s
if msg.BlobGasFeeCap != nil && msg.BlobGasFeeCap.BitLen() == 0 {
blockContext.BlobBaseFee = new(big.Int)
}
- evm := b.GetEVM(ctx, state, header, vmConfig, blockContext)
+ evm := b.GetEVM(ctx, msg, state, header, vmConfig, blockContext)
if precompiles != nil {
evm.SetPrecompiles(precompiles)
}
@@ -850,6 +850,44 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
return hexutil.Uint64(estimate), nil
}
+func DoEstimateGasAfterCalls(ctx context.Context, b Backend, args TransactionArgs, calls []TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *override.StateOverride, timeout time.Duration, gasCap uint64) (hexutil.Uint64, error) {
+ state, header, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
+ if state == nil || err != nil {
+ return 0, err
+ }
+ for _, call := range calls {
+ _, err = doCall(ctx, b, call, state, header, overrides, nil, timeout, gasCap)
+ if err != nil {
+ return 0, err
+ }
+ overrides = nil
+ }
+ // Construct the gas estimator option from the user input
+ opts := &gasestimator.Options{
+ Config: b.ChainConfig(),
+ Chain: NewChainContext(ctx, b),
+ Header: header,
+ State: state,
+ ErrorRatio: estimateGasErrorRatio,
+ }
+ if err := args.CallDefaults(gasCap, header.BaseFee, b.ChainConfig().ChainID); err != nil {
+ return 0, err
+ }
+ call := args.ToMessage(header.BaseFee, true, true)
+ if err != nil {
+ return 0, err
+ }
+ // Run the gas estimation andwrap any revertals into a custom return
+ estimate, revert, err := gasestimator.Estimate(ctx, call, opts, gasCap)
+ if err != nil {
+ if len(revert) > 0 {
+ return 0, newRevertError(revert)
+ }
+ return 0, err
+ }
+ return hexutil.Uint64(estimate), nil
+}
+
// EstimateGas returns the lowest possible gas limit that allows the transaction to run
// successfully at block `blockNrOrHash`, or the latest block if `blockNrOrHash` is unspecified. It
// returns error if the transaction would revert or if there are unexpected failures. The returned
@@ -918,7 +956,7 @@ func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool, config *param
}
if fullTx {
formatTx = func(idx int, tx *types.Transaction) interface{} {
- return newRPCTransactionFromBlockIndex(block, uint64(idx), config)
+ return NewRPCTransactionFromBlockIndex(block, uint64(idx), config)
}
}
txs := block.Transactions()
@@ -967,9 +1005,9 @@ type RPCTransaction struct {
YParity *hexutil.Uint64 `json:"yParity,omitempty"`
}
-// newRPCTransaction returns a transaction that will serialize to the RPC
+// NewRPCTransaction returns a transaction that will serialize to the RPC
// representation, with the given location metadata set (if available).
-func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber uint64, blockTime uint64, index uint64, baseFee *big.Int, config *params.ChainConfig) *RPCTransaction {
+func NewRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber uint64, blockTime uint64, index uint64, baseFee *big.Int, config *params.ChainConfig) *RPCTransaction {
signer := types.MakeSigner(config, new(big.Int).SetUint64(blockNumber), blockTime)
from, _ := types.Sender(signer, tx)
v, r, s := tx.RawSignatureValues()
@@ -1083,16 +1121,16 @@ func NewRPCPendingTransaction(tx *types.Transaction, current *types.Header, conf
blockNumber = current.Number.Uint64()
blockTime = current.Time
}
- return newRPCTransaction(tx, common.Hash{}, blockNumber, blockTime, 0, baseFee, config)
+ return NewRPCTransaction(tx, common.Hash{}, blockNumber, blockTime, 0, baseFee, config)
}
-// newRPCTransactionFromBlockIndex returns a transaction that will serialize to the RPC representation.
-func newRPCTransactionFromBlockIndex(b *types.Block, index uint64, config *params.ChainConfig) *RPCTransaction {
+// NewRPCTransactionFromBlockIndex returns a transaction that will serialize to the RPC representation.
+func NewRPCTransactionFromBlockIndex(b *types.Block, index uint64, config *params.ChainConfig) *RPCTransaction {
txs := b.Transactions()
if index >= uint64(len(txs)) {
return nil
}
- return newRPCTransaction(txs[index], b.Hash(), b.NumberU64(), b.Time(), index, b.BaseFee(), config)
+ return NewRPCTransaction(txs[index], b.Hash(), b.NumberU64(), b.Time(), index, b.BaseFee(), config)
}
// newRPCRawTransactionFromBlockIndex returns the bytes of a transaction given a block and a transaction index.
@@ -1187,7 +1225,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
// Apply the transaction with the access list tracer
tracer := logger.NewAccessListTracer(accessList, args.from(), to, precompiles)
config := vm.Config{Tracer: tracer.Hooks(), NoBaseFee: true}
- evm := b.GetEVM(ctx, statedb, header, &config, nil)
+ evm := b.GetEVM(ctx, msg, statedb, header, &config, nil)
// Lower the basefee to 0 to avoid breaking EVM
// invariants (basefee < feecap).
@@ -1244,7 +1282,7 @@ func (api *TransactionAPI) GetBlockTransactionCountByHash(ctx context.Context, b
// GetTransactionByBlockNumberAndIndex returns the transaction for the given block number and index.
func (api *TransactionAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) *RPCTransaction {
if block, _ := api.b.BlockByNumber(ctx, blockNr); block != nil {
- return newRPCTransactionFromBlockIndex(block, uint64(index), api.b.ChainConfig())
+ return NewRPCTransactionFromBlockIndex(block, uint64(index), api.b.ChainConfig())
}
return nil
}
@@ -1252,7 +1290,7 @@ func (api *TransactionAPI) GetTransactionByBlockNumberAndIndex(ctx context.Conte
// GetTransactionByBlockHashAndIndex returns the transaction for the given block hash and index.
func (api *TransactionAPI) GetTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) *RPCTransaction {
if block, _ := api.b.BlockByHash(ctx, blockHash); block != nil {
- return newRPCTransactionFromBlockIndex(block, uint64(index), api.b.ChainConfig())
+ return NewRPCTransactionFromBlockIndex(block, uint64(index), api.b.ChainConfig())
}
return nil
}
@@ -1310,7 +1348,7 @@ func (api *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common
if err != nil {
return nil, err
}
- return newRPCTransaction(tx, blockHash, blockNumber, header.Time, index, header.BaseFee, api.b.ChainConfig()), nil
+ return NewRPCTransaction(tx, blockHash, blockNumber, header.Time, index, header.BaseFee, api.b.ChainConfig()), nil
}
// GetRawTransactionByHash returns the bytes of the transaction for the given hash.
@@ -1464,7 +1502,7 @@ func (api *TransactionAPI) SendTransaction(ctx context.Context, args Transaction
}
// Set some sanity defaults and terminate on failure
- if err := args.setDefaults(ctx, api.b, false); err != nil {
+ if err := args.SetDefaults(ctx, api.b, false); err != nil {
return common.Hash{}, err
}
// Assemble the transaction and sign with the wallet
@@ -1484,7 +1522,7 @@ func (api *TransactionAPI) FillTransaction(ctx context.Context, args Transaction
args.blobSidecarAllowed = true
// Set some sanity defaults and terminate on failure
- if err := args.setDefaults(ctx, api.b, false); err != nil {
+ if err := args.SetDefaults(ctx, api.b, false); err != nil {
return nil, err
}
// Assemble the transaction and obtain rlp
@@ -1552,7 +1590,7 @@ func (api *TransactionAPI) SignTransaction(ctx context.Context, args Transaction
if args.Nonce == nil {
return nil, errors.New("nonce not specified")
}
- if err := args.setDefaults(ctx, api.b, false); err != nil {
+ if err := args.SetDefaults(ctx, api.b, false); err != nil {
return nil, err
}
// Before actually sign the transaction, ensure the transaction fee is reasonable.
@@ -1611,7 +1649,7 @@ func (api *TransactionAPI) Resend(ctx context.Context, sendArgs TransactionArgs,
if sendArgs.Nonce == nil {
return common.Hash{}, errors.New("missing transaction nonce in transaction spec")
}
- if err := sendArgs.setDefaults(ctx, api.b, false); err != nil {
+ if err := sendArgs.SetDefaults(ctx, api.b, false); err != nil {
return common.Hash{}, err
}
matchTx := sendArgs.ToTransaction(types.LegacyTxType)
diff --git a/internal/ethapi/api_test.go b/internal/ethapi/api_test.go
index f00022e3de4f..c19c49b5703d 100644
--- a/internal/ethapi/api_test.go
+++ b/internal/ethapi/api_test.go
@@ -47,7 +47,6 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/bloombits"
"github.com/ethereum/go-ethereum/core/rawdb"
- "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
@@ -83,7 +82,7 @@ func testTransactionMarshal(t *testing.T, tests []txData, config *params.ChainCo
}
// rpcTransaction
- rpcTx := newRPCTransaction(tx, common.Hash{}, 0, 0, 0, nil, config)
+ rpcTx := NewRPCTransaction(tx, common.Hash{}, 0, 0, 0, nil, config)
if data, err := json.Marshal(rpcTx); err != nil {
t.Fatalf("test %d: marshalling failed; %v", i, err)
} else if err = tx2.UnmarshalJSON(data); err != nil {
@@ -536,7 +535,7 @@ func (b testBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.
func (b testBackend) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) {
return b.chain.GetBlock(hash, uint64(number.Int64())).Body(), nil
}
-func (b testBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) {
+func (b testBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (vm.StateDB, *types.Header, error) {
if number == rpc.PendingBlockNumber {
panic("pending state not implemented")
}
@@ -550,13 +549,13 @@ func (b testBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.Bloc
stateDb, err := b.chain.StateAt(header.Root)
return stateDb, header, err
}
-func (b testBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) {
+func (b testBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (vm.StateDB, *types.Header, error) {
if blockNr, ok := blockNrOrHash.Number(); ok {
return b.StateAndHeaderByNumber(ctx, blockNr)
}
panic("only implemented for number")
}
-func (b testBackend) Pending() (*types.Block, types.Receipts, *state.StateDB) { panic("implement me") }
+func (b testBackend) Pending() (*types.Block, types.Receipts, vm.StateDB) { panic("implement me") }
func (b testBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
header, err := b.HeaderByHash(ctx, hash)
if header == nil || err != nil {
@@ -565,7 +564,7 @@ func (b testBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.R
receipts := rawdb.ReadReceipts(b.db, hash, header.Number.Uint64(), header.Time, b.chain.Config())
return receipts, nil
}
-func (b testBackend) GetEVM(ctx context.Context, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockContext *vm.BlockContext) *vm.EVM {
+func (b testBackend) GetEVM(ctx context.Context, msg *core.Message, state vm.StateDB, header *types.Header, vmConfig *vm.Config, blockContext *vm.BlockContext) *vm.EVM {
if vmConfig == nil {
vmConfig = b.chain.GetVMConfig()
}
diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go
index 3d8f7aa700b7..65666eda4166 100644
--- a/internal/ethapi/backend.go
+++ b/internal/ethapi/backend.go
@@ -28,7 +28,6 @@ import (
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/bloombits"
- "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
@@ -64,11 +63,11 @@ type Backend interface {
BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error)
BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error)
BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error)
- StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error)
- StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error)
- Pending() (*types.Block, types.Receipts, *state.StateDB)
+ StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (vm.StateDB, *types.Header, error)
+ StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (vm.StateDB, *types.Header, error)
+ Pending() (*types.Block, types.Receipts, vm.StateDB)
GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error)
- GetEVM(ctx context.Context, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM
+ GetEVM(ctx context.Context, msg *core.Message, state vm.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM
SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
diff --git a/internal/ethapi/override/override.go b/internal/ethapi/override/override.go
index f6a8a94ffdaf..93fb0d9bcced 100644
--- a/internal/ethapi/override/override.go
+++ b/internal/ethapi/override/override.go
@@ -22,7 +22,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
- "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
@@ -53,7 +52,7 @@ func (diff *StateOverride) has(address common.Address) bool {
}
// Apply overrides the fields of specified accounts into the given state.
-func (diff *StateOverride) Apply(statedb *state.StateDB, precompiles vm.PrecompiledContracts) error {
+func (diff *StateOverride) Apply(statedb vm.StateDB, precompiles vm.PrecompiledContracts) error {
if diff == nil {
return nil
}
diff --git a/internal/ethapi/override/override_test.go b/internal/ethapi/override/override_test.go
index 02a17c133170..21c9730602db 100644
--- a/internal/ethapi/override/override_test.go
+++ b/internal/ethapi/override/override_test.go
@@ -18,6 +18,7 @@ package override
import (
"maps"
+ "math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
@@ -33,7 +34,9 @@ type precompileContract struct{}
func (p *precompileContract) RequiredGas(input []byte) uint64 { return 0 }
-func (p *precompileContract) Run(input []byte) ([]byte, error) { return nil, nil }
+func (p *precompileContract) Run(_ *vm.EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) {
+ return nil, nil
+}
func TestStateOverrideMovePrecompile(t *testing.T) {
db := state.NewDatabase(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil), nil)
diff --git a/internal/ethapi/simulate.go b/internal/ethapi/simulate.go
index c461b1f0a1cb..6c65caf737b7 100644
--- a/internal/ethapi/simulate.go
+++ b/internal/ethapi/simulate.go
@@ -85,7 +85,7 @@ type simOpts struct {
// it is not safe for concurrent use.
type simulator struct {
b Backend
- state *state.StateDB
+ state vm.StateDB
base *types.Header
chainConfig *params.ChainConfig
gp *core.GasPool
diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go
index 7a7d63c535ac..30e45d15d0a8 100644
--- a/internal/ethapi/transaction_args.go
+++ b/internal/ethapi/transaction_args.go
@@ -94,8 +94,8 @@ func (args *TransactionArgs) data() []byte {
return nil
}
-// setDefaults fills in default values for unspecified tx fields.
-func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend, skipGasEstimation bool) error {
+// SetDefaults fills in default values for unspecified tx fields.
+func (args *TransactionArgs) SetDefaults(ctx context.Context, b Backend, skipGasEstimation bool) error {
if err := args.setBlobTxSidecar(ctx); err != nil {
return err
}
@@ -413,7 +413,7 @@ func (args *TransactionArgs) CallDefaults(globalGasCap uint64, baseFee *big.Int,
// ToMessage converts the transaction arguments to the Message type used by the
// core evm. This method is used in calls and traces that do not require a real
// live transaction.
-// Assumes that fields are not nil, i.e. setDefaults or CallDefaults has been called.
+// Assumes that fields are not nil, i.e. SetDefaults or CallDefaults has been called.
func (args *TransactionArgs) ToMessage(baseFee *big.Int, skipNonceCheck, skipEoACheck bool) *core.Message {
var (
gasPrice *big.Int
@@ -467,7 +467,7 @@ func (args *TransactionArgs) ToMessage(baseFee *big.Int, skipNonceCheck, skipEoA
}
// ToTransaction converts the arguments to a transaction.
-// This assumes that setDefaults has been called.
+// This assumes that SetDefaults has been called.
func (args *TransactionArgs) ToTransaction(defaultType int) *types.Transaction {
usedType := types.LegacyTxType
switch {
diff --git a/internal/ethapi/transaction_args_test.go b/internal/ethapi/transaction_args_test.go
index e017804861f7..03ef6b58e598 100644
--- a/internal/ethapi/transaction_args_test.go
+++ b/internal/ethapi/transaction_args_test.go
@@ -31,7 +31,6 @@ import (
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/bloombits"
- "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
@@ -357,20 +356,20 @@ func (b *backendMock) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc
func (b *backendMock) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) {
return nil, nil
}
-func (b *backendMock) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) {
+func (b *backendMock) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (vm.StateDB, *types.Header, error) {
return nil, nil, nil
}
-func (b *backendMock) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) {
+func (b *backendMock) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (vm.StateDB, *types.Header, error) {
return nil, nil, nil
}
-func (b *backendMock) Pending() (*types.Block, types.Receipts, *state.StateDB) { return nil, nil, nil }
+func (b *backendMock) Pending() (*types.Block, types.Receipts, vm.StateDB) { return nil, nil, nil }
func (b *backendMock) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
return nil, nil
}
func (b *backendMock) GetLogs(ctx context.Context, blockHash common.Hash, number uint64) ([][]*types.Log, error) {
return nil, nil
}
-func (b *backendMock) GetEVM(ctx context.Context, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM {
+func (b *backendMock) GetEVM(ctx context.Context, msg *core.Message, state vm.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM {
return nil
}
func (b *backendMock) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { return nil }
diff --git a/miner/miner.go b/miner/miner.go
index 595ef8081c8a..bf6666d5932d 100644
--- a/miner/miner.go
+++ b/miner/miner.go
@@ -96,7 +96,7 @@ func (miner *Miner) Pending() (*types.Block, types.Receipts, *state.StateDB) {
if pending == nil {
return nil, nil, nil
}
- return pending.block, pending.receipts, pending.stateDB.Copy()
+ return pending.block, pending.receipts, pending.stateDB.Copy().(*state.StateDB)
}
// SetExtra sets the content used to initialize the block extra field.
diff --git a/node/database.go b/node/database.go
index e3ccb9106678..f54bebf268b4 100644
--- a/node/database.go
+++ b/node/database.go
@@ -26,9 +26,9 @@ import (
"github.com/ethereum/go-ethereum/log"
)
-// openOptions contains the options to apply when opening a database.
+// OpenOptions contains the options to apply when opening a database.
// OBS: If AncientsDirectory is empty, it indicates that no freezer is to be used.
-type openOptions struct {
+type OpenOptions struct {
Type string // "leveldb" | "pebble"
Directory string // the datadir
AncientsDirectory string // the ancients-dir
@@ -38,12 +38,12 @@ type openOptions struct {
ReadOnly bool
}
-// openDatabase opens both a disk-based key-value database such as leveldb or pebble, but also
+// OpenDatabase opens both a disk-based key-value database such as leveldb or pebble, but also
// integrates it with a freezer database -- if the AncientDir option has been
// set on the provided OpenOptions.
// The passed o.AncientDir indicates the path of root ancient directory where
// the chain freezer can be opened.
-func openDatabase(o openOptions) (ethdb.Database, error) {
+func OpenDatabase(o OpenOptions) (ethdb.Database, error) {
kvdb, err := openKeyValueDatabase(o)
if err != nil {
return nil, err
@@ -65,7 +65,7 @@ func openDatabase(o openOptions) (ethdb.Database, error) {
// +----------------------------------------
// db is non-existent | pebble default | specified type
// db is existent | from db | specified type (if compatible)
-func openKeyValueDatabase(o openOptions) (ethdb.Database, error) {
+func openKeyValueDatabase(o OpenOptions) (ethdb.Database, error) {
// Reject any unsupported database type
if len(o.Type) != 0 && o.Type != rawdb.DBLeveldb && o.Type != rawdb.DBPebble {
return nil, fmt.Errorf("unknown db.engine %v", o.Type)
diff --git a/node/node.go b/node/node.go
index ec7382e72516..3df614e8e8bd 100644
--- a/node/node.go
+++ b/node/node.go
@@ -711,7 +711,7 @@ func (n *Node) OpenDatabase(name string, cache, handles int, namespace string, r
if n.config.DataDir == "" {
db = rawdb.NewMemoryDatabase()
} else {
- db, err = openDatabase(openOptions{
+ db, err = OpenDatabase(OpenOptions{
Type: n.config.DBEngine,
Directory: n.ResolvePath(name),
Namespace: namespace,
@@ -742,7 +742,7 @@ func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, ancient
if n.config.DataDir == "" {
db, err = rawdb.NewDatabaseWithFreezer(memorydb.New(), "", namespace, readonly)
} else {
- db, err = openDatabase(openOptions{
+ db, err = OpenDatabase(OpenOptions{
Type: n.config.DBEngine,
Directory: n.ResolvePath(name),
AncientsDirectory: n.ResolveAncient(name, ancient),
diff --git a/rpc/server.go b/rpc/server.go
index 42b59f8f6f7f..33564249820c 100644
--- a/rpc/server.go
+++ b/rpc/server.go
@@ -50,6 +50,7 @@ type Server struct {
mutex sync.Mutex
codecs map[ServerCodec]struct{}
+ denyList map[string]struct{}
run atomic.Bool
batchItemLimit int
batchResponseLimit int
@@ -62,6 +63,7 @@ func NewServer() *Server {
idgen: randomIDGenerator(),
codecs: make(map[ServerCodec]struct{}),
httpBodyLimit: defaultBodyLimit,
+ denyList: make(map[string]struct{}),
}
server.run.Store(true)
// Register the default service providing meta information about the RPC service such
@@ -97,6 +99,12 @@ func (s *Server) RegisterName(name string, receiver interface{}) error {
return s.services.registerName(name, receiver)
}
+// RegisterDenyList add given method name to the deny list so that RPC requests that matches
+// any of the methods in deny list will got rejected directly.
+func (s *Server) RegisterDenyList(methodName string) {
+ s.denyList[methodName] = struct{}{}
+}
+
// ServeCodec reads incoming requests from codec, calls the appropriate callback and writes
// the response back using the given codec. It will block until the codec is closed or the
// server is stopped. In either case the codec is closed.
@@ -159,6 +167,15 @@ func (s *Server) serveSingleRequest(ctx context.Context, codec ServerCodec) {
}
return
}
+ // check deny list
+ for _, req := range reqs {
+ method := req.Method
+ if _, found := s.denyList[method]; found {
+ resp := errorMessage(&methodNotFoundError{method: method})
+ codec.writeJSON(ctx, resp, true)
+ return
+ }
+ }
if batch {
h.handleBatch(reqs)
} else {
diff --git a/tests/block_test_util.go b/tests/block_test_util.go
index 77bf945e40e7..c7691b89e002 100644
--- a/tests/block_test_util.go
+++ b/tests/block_test_util.go
@@ -48,17 +48,17 @@ import (
// A BlockTest checks handling of entire blocks.
type BlockTest struct {
- json btJSON
+ Json BtJSON
}
// UnmarshalJSON implements json.Unmarshaler interface.
func (t *BlockTest) UnmarshalJSON(in []byte) error {
- return json.Unmarshal(in, &t.json)
+ return json.Unmarshal(in, &t.Json)
}
-type btJSON struct {
- Blocks []btBlock `json:"blocks"`
- Genesis btHeader `json:"genesisBlockHeader"`
+type BtJSON struct {
+ Blocks []BtBlock `json:"blocks"`
+ Genesis BtHeader `json:"genesisBlockHeader"`
Pre types.GenesisAlloc `json:"pre"`
Post types.GenesisAlloc `json:"postState"`
BestBlock common.UnprefixedHash `json:"lastblockhash"`
@@ -66,16 +66,16 @@ type btJSON struct {
SealEngine string `json:"sealEngine"`
}
-type btBlock struct {
- BlockHeader *btHeader
+type BtBlock struct {
+ BlockHeader *BtHeader
ExpectException string
Rlp string
- UncleHeaders []*btHeader
+ UncleHeaders []*BtHeader
}
//go:generate go run github.com/fjl/gencodec -type btHeader -field-override btHeaderMarshaling -out gen_btheader.go
-type btHeader struct {
+type BtHeader struct {
Bloom types.Bloom
Coinbase common.Address
MixHash common.Hash
@@ -99,7 +99,7 @@ type btHeader struct {
ParentBeaconBlockRoot *common.Hash
}
-type btHeaderMarshaling struct {
+type BtHeaderMarshaling struct {
ExtraData hexutil.Bytes
Number *math.HexOrDecimal256
Difficulty *math.HexOrDecimal256
@@ -112,9 +112,9 @@ type btHeaderMarshaling struct {
}
func (t *BlockTest) Run(snapshotter bool, scheme string, witness bool, tracer *tracing.Hooks, postCheck func(error, *core.BlockChain)) (result error) {
- config, ok := Forks[t.json.Network]
+ config, ok := Forks[t.Json.Network]
if !ok {
- return UnsupportedForkError{t.json.Network}
+ return UnsupportedForkError{t.Json.Network}
}
// import pre accounts & construct test genesis block & state root
var (
@@ -142,11 +142,11 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, witness bool, tracer *t
}
triedb.Close() // close the db to prevent memory leak
- if gblock.Hash() != t.json.Genesis.Hash {
- return fmt.Errorf("genesis block hash doesn't match test: computed=%x, test=%x", gblock.Hash().Bytes()[:6], t.json.Genesis.Hash[:6])
+ if gblock.Hash() != t.Json.Genesis.Hash {
+ return fmt.Errorf("genesis block hash doesn't match test: computed=%x, test=%x", gblock.Hash().Bytes()[:6], t.Json.Genesis.Hash[:6])
}
- if gblock.Root() != t.json.Genesis.StateRoot {
- return fmt.Errorf("genesis block state root does not match test: computed=%x, test=%x", gblock.Root().Bytes()[:6], t.json.Genesis.StateRoot[:6])
+ if gblock.Root() != t.Json.Genesis.StateRoot {
+ return fmt.Errorf("genesis block state root does not match test: computed=%x, test=%x", gblock.Root().Bytes()[:6], t.Json.Genesis.StateRoot[:6])
}
// Wrap the original engine within the beacon-engine
engine := beacon.New(ethash.NewFaker())
@@ -175,8 +175,8 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, witness bool, tracer *t
defer postCheck(result, chain)
}
cmlast := chain.CurrentBlock().Hash()
- if common.Hash(t.json.BestBlock) != cmlast {
- return fmt.Errorf("last block hash validation mismatch: want: %x, have: %x", t.json.BestBlock, cmlast)
+ if common.Hash(t.Json.BestBlock) != cmlast {
+ return fmt.Errorf("last block hash validation mismatch: want: %x, have: %x", t.Json.BestBlock, cmlast)
}
newDB, err := chain.State()
if err != nil {
@@ -197,19 +197,19 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, witness bool, tracer *t
func (t *BlockTest) genesis(config *params.ChainConfig) *core.Genesis {
return &core.Genesis{
Config: config,
- Nonce: t.json.Genesis.Nonce.Uint64(),
- Timestamp: t.json.Genesis.Timestamp,
- ParentHash: t.json.Genesis.ParentHash,
- ExtraData: t.json.Genesis.ExtraData,
- GasLimit: t.json.Genesis.GasLimit,
- GasUsed: t.json.Genesis.GasUsed,
- Difficulty: t.json.Genesis.Difficulty,
- Mixhash: t.json.Genesis.MixHash,
- Coinbase: t.json.Genesis.Coinbase,
- Alloc: t.json.Pre,
- BaseFee: t.json.Genesis.BaseFeePerGas,
- BlobGasUsed: t.json.Genesis.BlobGasUsed,
- ExcessBlobGas: t.json.Genesis.ExcessBlobGas,
+ Nonce: t.Json.Genesis.Nonce.Uint64(),
+ Timestamp: t.Json.Genesis.Timestamp,
+ ParentHash: t.Json.Genesis.ParentHash,
+ ExtraData: t.Json.Genesis.ExtraData,
+ GasLimit: t.Json.Genesis.GasLimit,
+ GasUsed: t.Json.Genesis.GasUsed,
+ Difficulty: t.Json.Genesis.Difficulty,
+ Mixhash: t.Json.Genesis.MixHash,
+ Coinbase: t.Json.Genesis.Coinbase,
+ Alloc: t.Json.Pre,
+ BaseFee: t.Json.Genesis.BaseFeePerGas,
+ BlobGasUsed: t.Json.Genesis.BlobGasUsed,
+ ExcessBlobGas: t.Json.Genesis.ExcessBlobGas,
}
}
@@ -226,11 +226,11 @@ See https://github.com/ethereum/tests/wiki/Blockchain-Tests-II
expected we are expected to ignore it and continue processing and then validate the
post state.
*/
-func (t *BlockTest) insertBlocks(blockchain *core.BlockChain) ([]btBlock, error) {
- validBlocks := make([]btBlock, 0)
+func (t *BlockTest) insertBlocks(blockchain *core.BlockChain) ([]BtBlock, error) {
+ validBlocks := make([]BtBlock, 0)
// insert the test blocks, which will execute all transactions
- for bi, b := range t.json.Blocks {
- cb, err := b.decode()
+ for bi, b := range t.Json.Blocks {
+ cb, err := b.Decode()
if err != nil {
if b.BlockHeader == nil {
log.Info("Block decoding failed", "index", bi, "err", err)
@@ -267,7 +267,7 @@ func (t *BlockTest) insertBlocks(blockchain *core.BlockChain) ([]btBlock, error)
return validBlocks, nil
}
-func validateHeader(h *btHeader, h2 *types.Header) error {
+func validateHeader(h *BtHeader, h2 *types.Header) error {
if h.Bloom != h2.Bloom {
return fmt.Errorf("bloom: want: %x have: %x", h.Bloom, h2.Bloom)
}
@@ -333,7 +333,7 @@ func validateHeader(h *btHeader, h2 *types.Header) error {
func (t *BlockTest) validatePostState(statedb *state.StateDB) error {
// validate post state accounts in test file against what we have in state db
- for addr, acct := range t.json.Post {
+ for addr, acct := range t.Json.Post {
// address is indirectly verified by the other fields, as it's the db key
code2 := statedb.GetCode(addr)
balance2 := statedb.GetBalance(addr).ToBig()
@@ -357,9 +357,9 @@ func (t *BlockTest) validatePostState(statedb *state.StateDB) error {
return nil
}
-func (t *BlockTest) validateImportedHeaders(cm *core.BlockChain, validBlocks []btBlock) error {
+func (t *BlockTest) validateImportedHeaders(cm *core.BlockChain, validBlocks []BtBlock) error {
// to get constant lookup when verifying block headers by hash (some tests have many blocks)
- bmap := make(map[common.Hash]btBlock, len(t.json.Blocks))
+ bmap := make(map[common.Hash]BtBlock, len(t.Json.Blocks))
for _, b := range validBlocks {
bmap[b.BlockHeader.Hash] = b
}
@@ -376,7 +376,7 @@ func (t *BlockTest) validateImportedHeaders(cm *core.BlockChain, validBlocks []b
return nil
}
-func (bb *btBlock) decode() (*types.Block, error) {
+func (bb *BtBlock) Decode() (*types.Block, error) {
data, err := hexutil.Decode(bb.Rlp)
if err != nil {
return nil, err
diff --git a/tests/fuzzers/bls12381/precompile_fuzzer.go b/tests/fuzzers/bls12381/precompile_fuzzer.go
index 33b2ca798874..b7cc19863d90 100644
--- a/tests/fuzzers/bls12381/precompile_fuzzer.go
+++ b/tests/fuzzers/bls12381/precompile_fuzzer.go
@@ -76,7 +76,7 @@ func fuzz(id byte, data []byte) int {
}
cpy := make([]byte, len(data))
copy(cpy, data)
- _, err := precompile.Run(cpy)
+ _, err := precompile.Run(nil, common.Address{}, common.Address{}, cpy, nil, false, false)
if !bytes.Equal(cpy, data) {
panic(fmt.Sprintf("input data modified, precompile %d: %x %x", id, data, cpy))
}
diff --git a/tests/gen_btheader.go b/tests/gen_btheader.go
index 80ad89e03bf5..5434cb7bfe02 100644
--- a/tests/gen_btheader.go
+++ b/tests/gen_btheader.go
@@ -12,10 +12,10 @@ import (
"github.com/ethereum/go-ethereum/core/types"
)
-var _ = (*btHeaderMarshaling)(nil)
+var _ = (*BtHeaderMarshaling)(nil)
// MarshalJSON marshals as JSON.
-func (b btHeader) MarshalJSON() ([]byte, error) {
+func (b BtHeader) MarshalJSON() ([]byte, error) {
type btHeader struct {
Bloom types.Bloom
Coinbase common.Address
@@ -65,7 +65,7 @@ func (b btHeader) MarshalJSON() ([]byte, error) {
}
// UnmarshalJSON unmarshals from JSON.
-func (b *btHeader) UnmarshalJSON(input []byte) error {
+func (b *BtHeader) UnmarshalJSON(input []byte) error {
type btHeader struct {
Bloom *types.Bloom
Coinbase *common.Address