core/vm: remove function call for stack validation from evm runloop

This commit is contained in:
Martin Holst Swende 2019-03-03 20:47:30 +01:00
parent f9aa1cd21f
commit 4caa9dec46
No known key found for this signature in database
GPG key ID: 683B438C05A5DDF0
3 changed files with 778 additions and 641 deletions

View file

@ -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 // 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. // 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 { if !operation.valid {
return nil, fmt.Errorf("invalid opcode 0x%x", int(op)) return nil, fmt.Errorf("invalid opcode 0x%x", int(op))
} }
if err = operation.validateStack(stack); err != nil { // Validate stack
return nil, err 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 the operation is valid, enforce and write restrictions
if err = in.enforceRestrictions(op, operation, stack); err != nil { if in.readOnly && in.evm.chainRules.IsByzantium {
return nil, err // 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 var memorySize uint64

File diff suppressed because it is too large Load diff

View file

@ -17,28 +17,26 @@
package vm package vm
import ( import (
"fmt"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
) )
func makeStackFunc(pop, push int) stackValidationFunc { func minSwapStack(n int) int {
return func(stack *Stack) error { return minStack(n, n)
if err := stack.require(pop); err != nil { }
return err func maxSwapStack(n int) int {
return maxStack(n, n)
} }
if stack.len()+push-pop > int(params.StackLimit) { func minDupStack(n int) int {
return fmt.Errorf("stack limit reached %d (%d)", stack.len(), params.StackLimit) return minStack(n, n+1)
}
return nil
} }
func maxDupStack(n int) int {
return maxStack(n, n+1)
} }
func makeDupStackFunc(n int) stackValidationFunc { func maxStack(pop, push int) int {
return makeStackFunc(n, n+1) return int(params.StackLimit) + pop - push
} }
func minStack(pops, push int) int {
func makeSwapStackFunc(n int) stackValidationFunc { return pops
return makeStackFunc(n, n)
} }