mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
core/vm: remove function call for stack validation from evm runloop
This commit is contained in:
parent
f9aa1cd21f
commit
4caa9dec46
3 changed files with 778 additions and 641 deletions
|
|
@ -118,22 +118,6 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter {
|
|||
}
|
||||
}
|
||||
|
||||
func (in *EVMInterpreter) enforceRestrictions(op OpCode, operation operation, stack *Stack) error {
|
||||
if in.evm.chainRules.IsByzantium {
|
||||
if in.readOnly {
|
||||
// If the interpreter is operating in readonly mode, make sure no
|
||||
// state-modifying operation is performed. The 3rd stack item
|
||||
// for a call operation is the value. Transferring value from one
|
||||
// account to the others means the state is modified and should also
|
||||
// return with an error.
|
||||
if operation.writes || (op == CALL && stack.Back(2).BitLen() > 0) {
|
||||
return errWriteProtection
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run loops and evaluates the contract's code with the given input data and returns
|
||||
// the return byte-slice and an error if one occurred.
|
||||
//
|
||||
|
|
@ -217,12 +201,24 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
|||
if !operation.valid {
|
||||
return nil, fmt.Errorf("invalid opcode 0x%x", int(op))
|
||||
}
|
||||
if err = operation.validateStack(stack); err != nil {
|
||||
return nil, err
|
||||
// Validate stack
|
||||
if sLen := stack.len(); sLen < operation.minStack{
|
||||
return nil, fmt.Errorf("stack underflow (%d <=> %d)", sLen, operation.minStack)
|
||||
}else{
|
||||
if sLen > operation.maxStack{
|
||||
return nil, fmt.Errorf("stack limit reached %d (%d)", sLen, operation.maxStack)
|
||||
}
|
||||
}
|
||||
// If the operation is valid, enforce and write restrictions
|
||||
if err = in.enforceRestrictions(op, operation, stack); err != nil {
|
||||
return nil, err
|
||||
if in.readOnly && in.evm.chainRules.IsByzantium {
|
||||
// If the interpreter is operating in readonly mode, make sure no
|
||||
// state-modifying operation is performed. The 3rd stack item
|
||||
// for a call operation is the value. Transferring value from one
|
||||
// account to the others means the state is modified and should also
|
||||
// return with an error.
|
||||
if operation.writes || (op == CALL && stack.Back(2).BitLen() > 0) {
|
||||
return nil, errWriteProtection
|
||||
}
|
||||
}
|
||||
|
||||
var memorySize uint64
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -17,28 +17,26 @@
|
|||
package vm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
func makeStackFunc(pop, push int) stackValidationFunc {
|
||||
return func(stack *Stack) error {
|
||||
if err := stack.require(pop); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if stack.len()+push-pop > int(params.StackLimit) {
|
||||
return fmt.Errorf("stack limit reached %d (%d)", stack.len(), params.StackLimit)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func minSwapStack(n int) int {
|
||||
return minStack(n, n)
|
||||
}
|
||||
func maxSwapStack(n int) int {
|
||||
return maxStack(n, n)
|
||||
}
|
||||
|
||||
func makeDupStackFunc(n int) stackValidationFunc {
|
||||
return makeStackFunc(n, n+1)
|
||||
func minDupStack(n int) int {
|
||||
return minStack(n, n+1)
|
||||
}
|
||||
func maxDupStack(n int) int {
|
||||
return maxStack(n, n+1)
|
||||
}
|
||||
|
||||
func makeSwapStackFunc(n int) stackValidationFunc {
|
||||
return makeStackFunc(n, n)
|
||||
func maxStack(pop, push int) int {
|
||||
return int(params.StackLimit) + pop - push
|
||||
}
|
||||
func minStack(pops, push int) int {
|
||||
return pops
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue