github.com/theQRL/go-zond@v0.2.1/core/vm/zvm.go (about)

     1  // Copyright 2014 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package vm
    18  
    19  import (
    20  	"math/big"
    21  	"sync/atomic"
    22  
    23  	"github.com/holiman/uint256"
    24  	"github.com/theQRL/go-zond/common"
    25  	"github.com/theQRL/go-zond/core/types"
    26  	"github.com/theQRL/go-zond/crypto"
    27  	"github.com/theQRL/go-zond/params"
    28  )
    29  
    30  type (
    31  	// CanTransferFunc is the signature of a transfer guard function
    32  	CanTransferFunc func(StateDB, common.Address, *big.Int) bool
    33  	// TransferFunc is the signature of a transfer function
    34  	TransferFunc func(StateDB, common.Address, common.Address, *big.Int)
    35  	// GetHashFunc returns the n'th block hash in the blockchain
    36  	// and is used by the BLOCKHASH ZVM op code.
    37  	GetHashFunc func(uint64) common.Hash
    38  )
    39  
    40  func (zvm *ZVM) precompile(addr common.Address) (PrecompiledContract, bool) {
    41  	precompiles := PrecompiledContractsBerlin
    42  	p, ok := precompiles[addr]
    43  	return p, ok
    44  }
    45  
    46  // BlockContext provides the ZVM with auxiliary information. Once provided
    47  // it shouldn't be modified.
    48  type BlockContext struct {
    49  	// CanTransfer returns whether the account contains
    50  	// sufficient ether to transfer the value
    51  	CanTransfer CanTransferFunc
    52  	// Transfer transfers ether from one account to the other
    53  	Transfer TransferFunc
    54  	// GetHash returns the hash corresponding to n
    55  	GetHash GetHashFunc
    56  
    57  	// Block information
    58  	Coinbase    common.Address // Provides information for COINBASE
    59  	GasLimit    uint64         // Provides information for GASLIMIT
    60  	BlockNumber *big.Int       // Provides information for NUMBER
    61  	Time        uint64         // Provides information for TIME
    62  	BaseFee     *big.Int       // Provides information for BASEFEE
    63  	Random      *common.Hash   // Provides information for PREVRANDAO
    64  }
    65  
    66  // TxContext provides the ZVM with information about a transaction.
    67  // All fields can change between transactions.
    68  type TxContext struct {
    69  	// Message information
    70  	Origin   common.Address // Provides information for ORIGIN
    71  	GasPrice *big.Int       // Provides information for GASPRICE
    72  }
    73  
    74  // ZVM is the Zond Virtual Machine base object and provides
    75  // the necessary tools to run a contract on the given state with
    76  // the provided context. It should be noted that any error
    77  // generated through any of the calls should be considered a
    78  // revert-state-and-consume-all-gas operation, no checks on
    79  // specific errors should ever be performed. The interpreter makes
    80  // sure that any errors generated are to be considered faulty code.
    81  //
    82  // The ZVM should never be reused and is not thread safe.
    83  type ZVM struct {
    84  	// Context provides auxiliary blockchain related information
    85  	Context BlockContext
    86  	TxContext
    87  	// StateDB gives access to the underlying state
    88  	StateDB StateDB
    89  	// Depth is the current call stack
    90  	depth int
    91  
    92  	// chainConfig contains information about the current chain
    93  	chainConfig *params.ChainConfig
    94  	// chain rules contains the chain rules for the current epoch
    95  	chainRules params.Rules
    96  	// virtual machine configuration options used to initialise the
    97  	// zvm.
    98  	Config Config
    99  	// global (to this context) zond virtual machine
   100  	// used throughout the execution of the tx.
   101  	interpreter *ZVMInterpreter
   102  	// abort is used to abort the ZVM calling operations
   103  	abort atomic.Bool
   104  	// callGasTemp holds the gas available for the current call. This is needed because the
   105  	// available gas is calculated in gasCall* according to the 63/64 rule and later
   106  	// applied in opCall*.
   107  	callGasTemp uint64
   108  }
   109  
   110  // NewZVM returns a new ZVM. The returned ZVM is not thread safe and should
   111  // only ever be used *once*.
   112  func NewZVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config) *ZVM {
   113  	zvm := &ZVM{
   114  		Context:     blockCtx,
   115  		TxContext:   txCtx,
   116  		StateDB:     statedb,
   117  		Config:      config,
   118  		chainConfig: chainConfig,
   119  		chainRules:  chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Time),
   120  	}
   121  	zvm.interpreter = NewZVMInterpreter(zvm)
   122  	return zvm
   123  }
   124  
   125  // Reset resets the ZVM with a new transaction context.Reset
   126  // This is not threadsafe and should only be done very cautiously.
   127  func (zvm *ZVM) Reset(txCtx TxContext, statedb StateDB) {
   128  	zvm.TxContext = txCtx
   129  	zvm.StateDB = statedb
   130  }
   131  
   132  // Cancel cancels any running ZVM operation. This may be called concurrently and
   133  // it's safe to be called multiple times.
   134  func (zvm *ZVM) Cancel() {
   135  	zvm.abort.Store(true)
   136  }
   137  
   138  // Cancelled returns true if Cancel has been called
   139  func (zvm *ZVM) Cancelled() bool {
   140  	return zvm.abort.Load()
   141  }
   142  
   143  // Interpreter returns the current interpreter
   144  func (zvm *ZVM) Interpreter() *ZVMInterpreter {
   145  	return zvm.interpreter
   146  }
   147  
   148  // SetBlockContext updates the block context of the ZVM.
   149  func (zvm *ZVM) SetBlockContext(blockCtx BlockContext) {
   150  	zvm.Context = blockCtx
   151  	num := blockCtx.BlockNumber
   152  	timestamp := blockCtx.Time
   153  	zvm.chainRules = zvm.chainConfig.Rules(num, timestamp)
   154  }
   155  
   156  // Call executes the contract associated with the addr with the given input as
   157  // parameters. It also handles any necessary value transfer required and takes
   158  // the necessary steps to create accounts and reverses the state in case of an
   159  // execution error or failed value transfer.
   160  func (zvm *ZVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
   161  	// Fail if we're trying to execute above the call depth limit
   162  	if zvm.depth > int(params.CallCreateDepth) {
   163  		return nil, gas, ErrDepth
   164  	}
   165  	// Fail if we're trying to transfer more than the available balance
   166  	if value.Sign() != 0 && !zvm.Context.CanTransfer(zvm.StateDB, caller.Address(), value) {
   167  		return nil, gas, ErrInsufficientBalance
   168  	}
   169  	snapshot := zvm.StateDB.Snapshot()
   170  	p, isPrecompile := zvm.precompile(addr)
   171  	debug := zvm.Config.Tracer != nil
   172  
   173  	if !zvm.StateDB.Exist(addr) {
   174  		if !isPrecompile && value.Sign() == 0 {
   175  			// Calling a non existing account, don't do anything, but ping the tracer
   176  			if debug {
   177  				if zvm.depth == 0 {
   178  					zvm.Config.Tracer.CaptureStart(zvm, caller.Address(), addr, false, input, gas, value)
   179  					zvm.Config.Tracer.CaptureEnd(ret, 0, nil)
   180  				} else {
   181  					zvm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value)
   182  					zvm.Config.Tracer.CaptureExit(ret, 0, nil)
   183  				}
   184  			}
   185  			return nil, gas, nil
   186  		}
   187  		zvm.StateDB.CreateAccount(addr)
   188  	}
   189  	zvm.Context.Transfer(zvm.StateDB, caller.Address(), addr, value)
   190  
   191  	// Capture the tracer start/end events in debug mode
   192  	if debug {
   193  		if zvm.depth == 0 {
   194  			zvm.Config.Tracer.CaptureStart(zvm, caller.Address(), addr, false, input, gas, value)
   195  			defer func(startGas uint64) { // Lazy evaluation of the parameters
   196  				zvm.Config.Tracer.CaptureEnd(ret, startGas-gas, err)
   197  			}(gas)
   198  		} else {
   199  			// Handle tracer events for entering and exiting a call frame
   200  			zvm.Config.Tracer.CaptureEnter(CALL, caller.Address(), addr, input, gas, value)
   201  			defer func(startGas uint64) {
   202  				zvm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
   203  			}(gas)
   204  		}
   205  	}
   206  
   207  	if isPrecompile {
   208  		ret, gas, err = RunPrecompiledContract(p, input, gas)
   209  	} else {
   210  		// Initialise a new contract and set the code that is to be used by the ZVM.
   211  		// The contract is a scoped environment for this execution context only.
   212  		code := zvm.StateDB.GetCode(addr)
   213  		if len(code) == 0 {
   214  			ret, err = nil, nil // gas is unchanged
   215  		} else {
   216  			addrCopy := addr
   217  			// If the account has no code, we can abort here
   218  			// The depth-check is already done, and precompiles handled above
   219  			contract := NewContract(caller, AccountRef(addrCopy), value, gas)
   220  			contract.SetCallCode(&addrCopy, zvm.StateDB.GetCodeHash(addrCopy), code)
   221  			ret, err = zvm.interpreter.Run(contract, input, false)
   222  			gas = contract.Gas
   223  		}
   224  	}
   225  	// When an error was returned by the ZVM or when setting the creation code
   226  	// above we revert to the snapshot and consume any gas remaining. Additionally
   227  	// when we're in homestead this also counts for code storage gas errors.
   228  	if err != nil {
   229  		zvm.StateDB.RevertToSnapshot(snapshot)
   230  		if err != ErrExecutionReverted {
   231  			gas = 0
   232  		}
   233  		// TODO: consider clearing up unused snapshots:
   234  		//} else {
   235  		//	zvm.StateDB.DiscardSnapshot(snapshot)
   236  	}
   237  	return ret, gas, err
   238  }
   239  
   240  // DelegateCall executes the contract associated with the addr with the given input
   241  // as parameters. It reverses the state in case of an execution error.
   242  //
   243  // DelegateCall differs from CallCode in the sense that it executes the given address'
   244  // code with the caller as context and the caller is set to the caller of the caller.
   245  func (zvm *ZVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
   246  	// Fail if we're trying to execute above the call depth limit
   247  	if zvm.depth > int(params.CallCreateDepth) {
   248  		return nil, gas, ErrDepth
   249  	}
   250  	var snapshot = zvm.StateDB.Snapshot()
   251  
   252  	// Invoke tracer hooks that signal entering/exiting a call frame
   253  	if zvm.Config.Tracer != nil {
   254  		// NOTE: caller must, at all times be a contract. It should never happen
   255  		// that caller is something other than a Contract.
   256  		parent := caller.(*Contract)
   257  		// DELEGATECALL inherits value from parent call
   258  		zvm.Config.Tracer.CaptureEnter(DELEGATECALL, caller.Address(), addr, input, gas, parent.value)
   259  		defer func(startGas uint64) {
   260  			zvm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
   261  		}(gas)
   262  	}
   263  
   264  	// It is allowed to call precompiles, even via delegatecall
   265  	if p, isPrecompile := zvm.precompile(addr); isPrecompile {
   266  		ret, gas, err = RunPrecompiledContract(p, input, gas)
   267  	} else {
   268  		addrCopy := addr
   269  		// Initialise a new contract and make initialise the delegate values
   270  		contract := NewContract(caller, AccountRef(caller.Address()), nil, gas).AsDelegate()
   271  		contract.SetCallCode(&addrCopy, zvm.StateDB.GetCodeHash(addrCopy), zvm.StateDB.GetCode(addrCopy))
   272  		ret, err = zvm.interpreter.Run(contract, input, false)
   273  		gas = contract.Gas
   274  	}
   275  	if err != nil {
   276  		zvm.StateDB.RevertToSnapshot(snapshot)
   277  		if err != ErrExecutionReverted {
   278  			gas = 0
   279  		}
   280  	}
   281  	return ret, gas, err
   282  }
   283  
   284  // StaticCall executes the contract associated with the addr with the given input
   285  // as parameters while disallowing any modifications to the state during the call.
   286  // Opcodes that attempt to perform such modifications will result in exceptions
   287  // instead of performing the modifications.
   288  func (zvm *ZVM) StaticCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
   289  	// Fail if we're trying to execute above the call depth limit
   290  	if zvm.depth > int(params.CallCreateDepth) {
   291  		return nil, gas, ErrDepth
   292  	}
   293  	// We take a snapshot here. This is a bit counter-intuitive, and could probably be skipped.
   294  	// However, even a staticcall is considered a 'touch'. On mainnet, static calls were introduced
   295  	// after all empty accounts were deleted, so this is not required. However, if we omit this,
   296  	// then certain tests start failing; stRevertTest/RevertPrecompiledTouchExactOOG.json.
   297  	// We could change this, but for now it's left for legacy reasons
   298  	var snapshot = zvm.StateDB.Snapshot()
   299  
   300  	// We do an AddBalance of zero here, just in order to trigger a touch.
   301  	// This doesn't matter on Mainnet, where all empties are gone at the time of Byzantium,
   302  	// but is the correct thing to do and matters on other networks, in tests, and potential
   303  	// future scenarios
   304  	zvm.StateDB.AddBalance(addr, big0)
   305  
   306  	// Invoke tracer hooks that signal entering/exiting a call frame
   307  	if zvm.Config.Tracer != nil {
   308  		zvm.Config.Tracer.CaptureEnter(STATICCALL, caller.Address(), addr, input, gas, nil)
   309  		defer func(startGas uint64) {
   310  			zvm.Config.Tracer.CaptureExit(ret, startGas-gas, err)
   311  		}(gas)
   312  	}
   313  
   314  	if p, isPrecompile := zvm.precompile(addr); isPrecompile {
   315  		ret, gas, err = RunPrecompiledContract(p, input, gas)
   316  	} else {
   317  		// At this point, we use a copy of address. If we don't, the go compiler will
   318  		// leak the 'contract' to the outer scope, and make allocation for 'contract'
   319  		// even if the actual execution ends on RunPrecompiled above.
   320  		addrCopy := addr
   321  		// Initialise a new contract and set the code that is to be used by the ZVM.
   322  		// The contract is a scoped environment for this execution context only.
   323  		contract := NewContract(caller, AccountRef(addrCopy), new(big.Int), gas)
   324  		contract.SetCallCode(&addrCopy, zvm.StateDB.GetCodeHash(addrCopy), zvm.StateDB.GetCode(addrCopy))
   325  		// When an error was returned by the ZVM or when setting the creation code
   326  		// above we revert to the snapshot and consume any gas remaining. Additionally
   327  		// when we're in Homestead this also counts for code storage gas errors.
   328  		ret, err = zvm.interpreter.Run(contract, input, true)
   329  		gas = contract.Gas
   330  	}
   331  	if err != nil {
   332  		zvm.StateDB.RevertToSnapshot(snapshot)
   333  		if err != ErrExecutionReverted {
   334  			gas = 0
   335  		}
   336  	}
   337  	return ret, gas, err
   338  }
   339  
   340  type codeAndHash struct {
   341  	code []byte
   342  	hash common.Hash
   343  }
   344  
   345  func (c *codeAndHash) Hash() common.Hash {
   346  	if c.hash == (common.Hash{}) {
   347  		c.hash = crypto.Keccak256Hash(c.code)
   348  	}
   349  	return c.hash
   350  }
   351  
   352  // create creates a new contract using code as deployment code.
   353  func (zvm *ZVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *big.Int, address common.Address, typ OpCode) ([]byte, common.Address, uint64, error) {
   354  	// Depth check execution. Fail if we're trying to execute above the
   355  	// limit.
   356  	if zvm.depth > int(params.CallCreateDepth) {
   357  		return nil, common.Address{}, gas, ErrDepth
   358  	}
   359  	if !zvm.Context.CanTransfer(zvm.StateDB, caller.Address(), value) {
   360  		return nil, common.Address{}, gas, ErrInsufficientBalance
   361  	}
   362  	nonce := zvm.StateDB.GetNonce(caller.Address())
   363  	if nonce+1 < nonce {
   364  		return nil, common.Address{}, gas, ErrNonceUintOverflow
   365  	}
   366  	zvm.StateDB.SetNonce(caller.Address(), nonce+1)
   367  	// We add this to the access list _before_ taking a snapshot. Even if the creation fails,
   368  	// the access-list change should not be rolled back
   369  	zvm.StateDB.AddAddressToAccessList(address)
   370  	// Ensure there's no existing contract already at the designated address
   371  	contractHash := zvm.StateDB.GetCodeHash(address)
   372  	if zvm.StateDB.GetNonce(address) != 0 || (contractHash != (common.Hash{}) && contractHash != types.EmptyCodeHash) {
   373  		return nil, common.Address{}, 0, ErrContractAddressCollision
   374  	}
   375  	// Create a new account on the state
   376  	snapshot := zvm.StateDB.Snapshot()
   377  	zvm.StateDB.CreateAccount(address)
   378  	zvm.StateDB.SetNonce(address, 1)
   379  	zvm.Context.Transfer(zvm.StateDB, caller.Address(), address, value)
   380  
   381  	// Initialise a new contract and set the code that is to be used by the ZVM.
   382  	// The contract is a scoped environment for this execution context only.
   383  	contract := NewContract(caller, AccountRef(address), value, gas)
   384  	contract.SetCodeOptionalHash(&address, codeAndHash)
   385  
   386  	if zvm.Config.Tracer != nil {
   387  		if zvm.depth == 0 {
   388  			zvm.Config.Tracer.CaptureStart(zvm, caller.Address(), address, true, codeAndHash.code, gas, value)
   389  		} else {
   390  			zvm.Config.Tracer.CaptureEnter(typ, caller.Address(), address, codeAndHash.code, gas, value)
   391  		}
   392  	}
   393  
   394  	ret, err := zvm.interpreter.Run(contract, nil, false)
   395  
   396  	// Check whether the max code size has been exceeded, assign err if the case.
   397  	if err == nil && len(ret) > params.MaxCodeSize {
   398  		err = ErrMaxCodeSizeExceeded
   399  	}
   400  
   401  	// Reject code starting with 0xEF if EIP-3541 is enabled.
   402  	if err == nil && len(ret) >= 1 && ret[0] == 0xEF {
   403  		err = ErrInvalidCode
   404  	}
   405  
   406  	// if the contract creation ran successfully and no errors were returned
   407  	// calculate the gas required to store the code. If the code could not
   408  	// be stored due to not enough gas set an error and let it be handled
   409  	// by the error checking condition below.
   410  	if err == nil {
   411  		createDataGas := uint64(len(ret)) * params.CreateDataGas
   412  		if contract.UseGas(createDataGas) {
   413  			zvm.StateDB.SetCode(address, ret)
   414  		} else {
   415  			err = ErrCodeStoreOutOfGas
   416  		}
   417  	}
   418  
   419  	// When an error was returned by the ZVM or when setting the creation code
   420  	// above we revert to the snapshot and consume any gas remaining. Additionally
   421  	// when we're in homestead this also counts for code storage gas errors.
   422  	if err != nil && (err != ErrCodeStoreOutOfGas) {
   423  		zvm.StateDB.RevertToSnapshot(snapshot)
   424  		if err != ErrExecutionReverted {
   425  			contract.UseGas(contract.Gas)
   426  		}
   427  	}
   428  
   429  	if zvm.Config.Tracer != nil {
   430  		if zvm.depth == 0 {
   431  			zvm.Config.Tracer.CaptureEnd(ret, gas-contract.Gas, err)
   432  		} else {
   433  			zvm.Config.Tracer.CaptureExit(ret, gas-contract.Gas, err)
   434  		}
   435  	}
   436  	return ret, address, contract.Gas, err
   437  }
   438  
   439  // Create creates a new contract using code as deployment code.
   440  func (zvm *ZVM) Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
   441  	contractAddr = crypto.CreateAddress(caller.Address(), zvm.StateDB.GetNonce(caller.Address()))
   442  	return zvm.create(caller, &codeAndHash{code: code}, gas, value, contractAddr, CREATE)
   443  }
   444  
   445  // Create2 creates a new contract using code as deployment code.
   446  //
   447  // The different between Create2 with Create is Create2 uses keccak256(0xff ++ msg.sender ++ salt ++ keccak256(init_code))[12:]
   448  // instead of the usual sender-and-nonce-hash as the address where the contract is initialized at.
   449  func (zvm *ZVM) Create2(caller ContractRef, code []byte, gas uint64, endowment *big.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
   450  	codeAndHash := &codeAndHash{code: code}
   451  	contractAddr = crypto.CreateAddress2(caller.Address(), salt.Bytes32(), codeAndHash.Hash().Bytes())
   452  	return zvm.create(caller, codeAndHash, gas, endowment, contractAddr, CREATE2)
   453  }
   454  
   455  // ChainConfig returns the environment's chain configuration
   456  func (zvm *ZVM) ChainConfig() *params.ChainConfig { return zvm.chainConfig }