core/vm: EIP-2315, JUMPSUB for the EVM (#20619)

* core/vm: implement EIP 2315, subroutines for the EVM

* core/vm: eip 2315 - lintfix + check jump dest validity + check ret stack size constraints

  logger: markdown-friendly traces, validate jumpdest, more testcase, correct opcodes

* core/vm: update subroutines acc to eip: disallow walk-into

* core/vm/eips: gas cost changes for subroutines

* core/vm: update opcodes for EIP-2315

* core/vm: define RETURNSUB as a 'jumping' operation + review concerns

Co-authored-by: Martin Holst Swende <martin@swende.se>
This commit is contained in:
Greg Colvin
2020-06-02 04:30:16 -06:00
committed by GitHub
parent a35382de94
commit cd57d5cd38
15 changed files with 529 additions and 52 deletions

View File

@ -664,6 +664,39 @@ func opJumpdest(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) (
return nil, nil
}
func opBeginSub(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
return nil, ErrInvalidSubroutineEntry
}
func opJumpSub(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
if len(callContext.rstack.data) >= 1023 {
return nil, ErrReturnStackExceeded
}
pos := callContext.stack.pop()
if !pos.IsUint64() {
return nil, ErrInvalidJump
}
posU64 := pos.Uint64()
if !callContext.contract.validJumpSubdest(posU64) {
return nil, ErrInvalidJump
}
callContext.rstack.push(*pc)
*pc = posU64 + 1
interpreter.intPool.put(pos)
return nil, nil
}
func opReturnSub(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
if len(callContext.rstack.data) == 0 {
return nil, ErrInvalidRetsub
}
// Other than the check that the return stack is not empty, there is no
// need to validate the pc from 'returns', since we only ever push valid
//values onto it via jumpsub.
*pc = callContext.rstack.pop() + 1
return nil, nil
}
func opPc(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
callContext.stack.push(interpreter.intPool.get().SetUint64(*pc))
return nil, nil