core/vm: apply suggestions, make ReturnStack an object

This commit is contained in:
Marius van der Wijden 2024-09-04 16:27:13 +02:00
parent 6549a87202
commit ddb9907a7a
2 changed files with 29 additions and 23 deletions

View file

@ -789,20 +789,20 @@ func opRjumpi(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b
// opRjumpv implements the RJUMPV opcode
func opRjumpv(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
var (
code = scope.Contract.CodeAt(scope.CodeSection)
count = uint64(code[*pc+1]) + 1
idx = scope.Stack.pop()
code = scope.Contract.CodeAt(scope.CodeSection)
maxIndex = uint64(code[*pc+1]) + 1
idx = scope.Stack.pop()
)
if idx, overflow := idx.Uint64WithOverflow(); overflow || idx >= count {
if idx, overflow := idx.Uint64WithOverflow(); overflow || idx >= maxIndex {
// Index out-of-bounds, don't branch, just skip over immediate
// argument.
*pc += 1 + count*2
*pc += 1 + maxIndex*2
return nil, nil
}
offset := parseInt16(code[*pc+2+2*idx.Uint64():])
// move pc past op and count byte (2), move past count number of 16bit offsets (count*2), add relative offset, subtract 1 to
// account for interpreter loop.
*pc = uint64(int64(*pc+2+count*2) + int64(offset) - 1)
*pc = uint64(int64(*pc+2+maxIndex*2) + int64(offset) - 1)
return nil, nil
}
@ -816,7 +816,7 @@ func opCallf(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by
if scope.Stack.len()+int(typ.MaxStackHeight)-int(typ.Input) > 1024 {
return nil, fmt.Errorf("stack overflow")
}
if len(scope.ReturnStack) > 1024 {
if scope.ReturnStack.Len() > 1024 {
return nil, fmt.Errorf("return stack overflow")
}
retCtx := &ReturnContext{
@ -826,23 +826,18 @@ func opCallf(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by
}
scope.ReturnStack = append(scope.ReturnStack, retCtx)
scope.CodeSection = uint64(idx)
*pc = 0
*pc -= 1 // hacks xD (interpreter loop)
*pc = uint64(math.MaxUint64)
return nil, nil
}
// opRetf implements the RETF opcode
func opRetf(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
var (
last = len(scope.ReturnStack) - 1
retCtx = scope.ReturnStack[last]
)
scope.ReturnStack = scope.ReturnStack[:last]
retCtx := scope.ReturnStack.Pop()
scope.CodeSection = retCtx.Section
*pc = retCtx.Pc - 1
// If returning from top frame, exit cleanly.
if len(scope.ReturnStack) == 0 {
if scope.ReturnStack.Len() == 0 {
return nil, errStopToken
}
return nil, nil
@ -858,8 +853,7 @@ func opJumpf(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by
return nil, fmt.Errorf("stack overflow")
}
scope.CodeSection = uint64(idx)
*pc = 0
*pc -= 1 // hacks xD (interpreter loop)
*pc = uint64(math.MaxUint64)
return nil, nil
}
@ -947,11 +941,7 @@ func opReturnContract(pc *uint64, interpreter *EVMInterpreter, scope *ScopeConte
}
c.DataSize = len(c.Data)
// Restore context
var (
last = len(scope.ReturnStack) - 1
retCtx = scope.ReturnStack[last]
)
scope.ReturnStack = scope.ReturnStack[:last]
retCtx := scope.ReturnStack.Pop()
scope.CodeSection = retCtx.Section
*pc = retCtx.Pc - 1 // account for interpreter loop
return c.MarshalBinary(), errStopToken

View file

@ -44,10 +44,26 @@ type ScopeContext struct {
Contract *Contract
CodeSection uint64
ReturnStack []*ReturnContext
ReturnStack ReturnStack
InitCodeMode bool
}
type ReturnStack []*ReturnContext
// Pop removes an element from the return stack
// Panics if the return stack is empty, which should
// never happen, since EOF code is verified for that.
func (ctx *ReturnStack) Pop() *ReturnContext {
item := (*ctx)[ctx.Len()-1]
*ctx = (*ctx)[:ctx.Len()-1]
return item
}
// Len returns the length of the return stack
func (ctx *ReturnStack) Len() int {
return len(*ctx)
}
type ReturnContext struct {
Section uint64
Pc uint64