core/vm: added new behavior to legacy opcodes

This commit is contained in:
Marius van der Wijden 2024-09-26 13:40:50 +02:00
parent 8374793fec
commit 3012db54ee
1 changed files with 41 additions and 11 deletions

View File

@ -323,6 +323,18 @@ func opReturnDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeConte
length = scope.Stack.pop() length = scope.Stack.pop()
) )
if scope.Contract.IsEOF() {
dataOffset64, overflow := dataOffset.Uint64WithOverflow()
if overflow {
dataOffset64 = math.MaxUint64
}
// These values are checked for overflow during gas cost calculation
memOffset64 := memOffset.Uint64()
length64 := length.Uint64()
scope.Memory.Set(memOffset64, length64, getData(interpreter.returnData, dataOffset64, length64))
return nil, nil
}
offset64, overflow := dataOffset.Uint64WithOverflow() offset64, overflow := dataOffset.Uint64WithOverflow()
if overflow { if overflow {
return nil, ErrReturnDataOutOfBounds return nil, ErrReturnDataOutOfBounds
@ -344,12 +356,18 @@ func opExtCodeSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
if witness := interpreter.evm.StateDB.Witness(); witness != nil { if witness := interpreter.evm.StateDB.Witness(); witness != nil {
witness.AddCode(interpreter.evm.StateDB.GetCode(address)) witness.AddCode(interpreter.evm.StateDB.GetCode(address))
} }
slot.SetUint64(uint64(interpreter.evm.StateDB.GetCodeSize(slot.Bytes20()))) // TODO this should not need to pull up the whole code
code := interpreter.evm.StateDB.GetCode(slot.Bytes20())
if isEOFVersion1(code) {
slot.SetUint64(2)
} else {
slot.SetUint64(uint64(len(interpreter.evm.StateDB.GetCode(slot.Bytes20()))))
}
return nil, nil return nil, nil
} }
func opCodeSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { func opCodeSize(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
scope.Stack.push(new(uint256.Int).SetUint64(uint64(len(scope.Contract.Code)))) scope.Stack.push(new(uint256.Int).SetUint64(uint64(len(scope.Contract.CodeAt(scope.CodeSection)))))
return nil, nil return nil, nil
} }
@ -364,7 +382,7 @@ func opCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
uint64CodeOffset = math.MaxUint64 uint64CodeOffset = math.MaxUint64
} }
codeCopy := getData(scope.Contract.Code, uint64CodeOffset, length.Uint64()) codeCopy := getData(scope.Contract.CodeAt(scope.CodeSection), uint64CodeOffset, length.Uint64())
scope.Memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy) scope.Memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy)
return nil, nil return nil, nil
} }
@ -376,6 +394,7 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
memOffset = stack.pop() memOffset = stack.pop()
codeOffset = stack.pop() codeOffset = stack.pop()
length = stack.pop() length = stack.pop()
lengthU64 = length.Uint64()
) )
uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow() uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow()
if overflow { if overflow {
@ -386,8 +405,11 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
if witness := interpreter.evm.StateDB.Witness(); witness != nil { if witness := interpreter.evm.StateDB.Witness(); witness != nil {
witness.AddCode(code) witness.AddCode(code)
} }
codeCopy := getData(code, uint64CodeOffset, length.Uint64()) if isEOFVersion1(code) {
scope.Memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy) lengthU64 = 2
}
codeCopy := getData(code, uint64CodeOffset, lengthU64)
scope.Memory.Set(memOffset.Uint64(), lengthU64, codeCopy)
return nil, nil return nil, nil
} }
@ -423,9 +445,15 @@ func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
address := common.Address(slot.Bytes20()) address := common.Address(slot.Bytes20())
if interpreter.evm.StateDB.Empty(address) { if interpreter.evm.StateDB.Empty(address) {
slot.Clear() slot.Clear()
} else {
// TODO this should not need to pull up the whole code
code := interpreter.evm.StateDB.GetCode(address)
if HasEOFByte(code) {
slot.SetFromHex("0x9dbf3648db8210552e9c4f75c6a1c3057c0ca432043bd648be15fe7be05646f5")
} else { } else {
slot.SetBytes(interpreter.evm.StateDB.GetCodeHash(address).Bytes()) slot.SetBytes(interpreter.evm.StateDB.GetCodeHash(address).Bytes())
} }
}
return nil, nil return nil, nil
} }
@ -885,7 +913,7 @@ func opRevert(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b
} }
func opUndefined(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { func opUndefined(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
return nil, &ErrInvalidOpCode{opcode: OpCode(scope.Contract.Code[*pc])} return nil, &ErrInvalidOpCode{opcode: OpCode(scope.Contract.CodeAt(scope.CodeSection)[*pc])}
} }
func opStop(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { func opStop(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
@ -964,12 +992,13 @@ func makeLog(size int) executionFunc {
// opPush1 is a specialized version of pushN // opPush1 is a specialized version of pushN
func opPush1(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { func opPush1(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
var ( var (
codeLen = uint64(len(scope.Contract.Code)) code = scope.Contract.CodeAt(scope.CodeSection)
codeLen = uint64(len(code))
integer = new(uint256.Int) integer = new(uint256.Int)
) )
*pc += 1 *pc += 1
if *pc < codeLen { if *pc < codeLen {
scope.Stack.push(integer.SetUint64(uint64(scope.Contract.Code[*pc]))) scope.Stack.push(integer.SetUint64(uint64(code[*pc])))
} else { } else {
scope.Stack.push(integer.Clear()) scope.Stack.push(integer.Clear())
} }
@ -980,13 +1009,14 @@ func opPush1(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by
func makePush(size uint64, pushByteSize int) executionFunc { func makePush(size uint64, pushByteSize int) executionFunc {
return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
var ( var (
codeLen = len(scope.Contract.Code) code = scope.Contract.CodeAt(scope.CodeSection)
codeLen = len(code)
start = min(codeLen, int(*pc+1)) start = min(codeLen, int(*pc+1))
end = min(codeLen, start+pushByteSize) end = min(codeLen, start+pushByteSize)
) )
scope.Stack.push(new(uint256.Int).SetBytes( scope.Stack.push(new(uint256.Int).SetBytes(
common.RightPadBytes( common.RightPadBytes(
scope.Contract.Code[start:end], code[start:end],
pushByteSize, pushByteSize,
)), )),
) )