mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 21:31:37 +00:00
core/vm: move interpreter.ReadOnly check into the opcode implementations (#23970)
* core/vm: Move interpreter.ReadOnly check into the opcode implementations Also remove the same check from the interpreter inner loop. * core/vm: Remove obsolete operation.writes flag * core/vm: Capture fault states in logger Co-authored-by: Martin Holst Swende <martin@swende.se> * core/vm: Remove panic added for testing Co-authored-by: Martin Holst Swende <martin@swende.se>
This commit is contained in:
parent
002be52ae9
commit
bfbb678309
4 changed files with 19 additions and 23 deletions
|
|
@ -514,6 +514,9 @@ func opSload(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]b
|
|||
}
|
||||
|
||||
func opSstore(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
|
||||
if interpreter.readOnly {
|
||||
return nil, ErrWriteProtection
|
||||
}
|
||||
loc := callContext.stack.pop()
|
||||
val := callContext.stack.pop()
|
||||
interpreter.evm.StateDB.SetState(callContext.contract.Address(),
|
||||
|
|
@ -561,6 +564,9 @@ func opGas(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byt
|
|||
}
|
||||
|
||||
func opCreate(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
|
||||
if interpreter.readOnly {
|
||||
return nil, ErrWriteProtection
|
||||
}
|
||||
var (
|
||||
value = callContext.stack.pop()
|
||||
offset, size = callContext.stack.pop(), callContext.stack.pop()
|
||||
|
|
@ -598,6 +604,9 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]
|
|||
}
|
||||
|
||||
func opCreate2(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
|
||||
if interpreter.readOnly {
|
||||
return nil, ErrWriteProtection
|
||||
}
|
||||
var (
|
||||
endowment = callContext.stack.pop()
|
||||
offset, size = callContext.stack.pop(), callContext.stack.pop()
|
||||
|
|
@ -642,6 +651,9 @@ func opCall(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]by
|
|||
// Get the arguments from the memory.
|
||||
args := callContext.memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64()))
|
||||
|
||||
if interpreter.readOnly && !value.IsZero() {
|
||||
return nil, ErrWriteProtection
|
||||
}
|
||||
if !value.IsZero() {
|
||||
gas += params.CallStipend
|
||||
}
|
||||
|
|
@ -772,6 +784,9 @@ func opStop(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]by
|
|||
}
|
||||
|
||||
func opSuicide(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
|
||||
if interpreter.readOnly {
|
||||
return nil, ErrWriteProtection
|
||||
}
|
||||
beneficiary := callContext.stack.pop()
|
||||
balance := interpreter.evm.StateDB.GetBalance(callContext.contract.Address())
|
||||
interpreter.evm.StateDB.AddBalance(common.Address(beneficiary.Bytes20()), balance)
|
||||
|
|
@ -784,6 +799,9 @@ func opSuicide(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([
|
|||
// make log instruction function
|
||||
func makeLog(size int) executionFunc {
|
||||
return func(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
|
||||
if interpreter.readOnly {
|
||||
return nil, ErrWriteProtection
|
||||
}
|
||||
topics := make([]common.Hash, size)
|
||||
stack := callContext.stack
|
||||
mStart, mSize := stack.pop(), stack.pop()
|
||||
|
|
|
|||
|
|
@ -216,17 +216,6 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
|||
} else if sLen > operation.maxStack {
|
||||
return nil, &ErrStackOverflow{stackLen: sLen, limit: operation.maxStack}
|
||||
}
|
||||
// If the operation is valid, enforce write restrictions
|
||||
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).Sign() != 0) {
|
||||
return nil, ErrWriteProtection
|
||||
}
|
||||
}
|
||||
// Static portion of gas
|
||||
cost = operation.constantGas // For tracing
|
||||
if !contract.UseGas(operation.constantGas) {
|
||||
|
|
|
|||
|
|
@ -40,8 +40,6 @@ type operation struct {
|
|||
|
||||
// memorySize returns the memory size required for the operation
|
||||
memorySize memorySizeFunc
|
||||
|
||||
writes bool // determines whether this a state modifying operation
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
@ -104,7 +102,6 @@ func newConstantinopleInstructionSet() JumpTable {
|
|||
minStack: minStack(4, 1),
|
||||
maxStack: maxStack(4, 1),
|
||||
memorySize: memoryCreate2,
|
||||
writes: true,
|
||||
}
|
||||
return instructionSet
|
||||
}
|
||||
|
|
@ -492,7 +489,6 @@ func newFrontierInstructionSet() JumpTable {
|
|||
dynamicGas: gasSStore,
|
||||
minStack: minStack(2, 0),
|
||||
maxStack: maxStack(2, 0),
|
||||
writes: true,
|
||||
},
|
||||
JUMP: {
|
||||
execute: opJump,
|
||||
|
|
@ -920,7 +916,6 @@ func newFrontierInstructionSet() JumpTable {
|
|||
minStack: minStack(2, 0),
|
||||
maxStack: maxStack(2, 0),
|
||||
memorySize: memoryLog,
|
||||
writes: true,
|
||||
},
|
||||
LOG1: {
|
||||
execute: makeLog(1),
|
||||
|
|
@ -928,7 +923,6 @@ func newFrontierInstructionSet() JumpTable {
|
|||
minStack: minStack(3, 0),
|
||||
maxStack: maxStack(3, 0),
|
||||
memorySize: memoryLog,
|
||||
writes: true,
|
||||
},
|
||||
LOG2: {
|
||||
execute: makeLog(2),
|
||||
|
|
@ -936,7 +930,6 @@ func newFrontierInstructionSet() JumpTable {
|
|||
minStack: minStack(4, 0),
|
||||
maxStack: maxStack(4, 0),
|
||||
memorySize: memoryLog,
|
||||
writes: true,
|
||||
},
|
||||
LOG3: {
|
||||
execute: makeLog(3),
|
||||
|
|
@ -944,7 +937,6 @@ func newFrontierInstructionSet() JumpTable {
|
|||
minStack: minStack(5, 0),
|
||||
maxStack: maxStack(5, 0),
|
||||
memorySize: memoryLog,
|
||||
writes: true,
|
||||
},
|
||||
LOG4: {
|
||||
execute: makeLog(4),
|
||||
|
|
@ -952,7 +944,6 @@ func newFrontierInstructionSet() JumpTable {
|
|||
minStack: minStack(6, 0),
|
||||
maxStack: maxStack(6, 0),
|
||||
memorySize: memoryLog,
|
||||
writes: true,
|
||||
},
|
||||
CREATE: {
|
||||
execute: opCreate,
|
||||
|
|
@ -961,7 +952,6 @@ func newFrontierInstructionSet() JumpTable {
|
|||
minStack: minStack(3, 1),
|
||||
maxStack: maxStack(3, 1),
|
||||
memorySize: memoryCreate,
|
||||
writes: true,
|
||||
},
|
||||
CALL: {
|
||||
execute: opCall,
|
||||
|
|
@ -991,7 +981,6 @@ func newFrontierInstructionSet() JumpTable {
|
|||
dynamicGas: gasSelfdestruct,
|
||||
minStack: minStack(1, 0),
|
||||
maxStack: maxStack(1, 0),
|
||||
writes: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint
|
|||
|
||||
// CaptureFault outputs state information on the logger.
|
||||
func (l *JSONLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, memory *Memory, stack *Stack, contract *Contract, depth int, err error) error {
|
||||
return nil
|
||||
return l.CaptureState(env, pc, op, gas, cost, memory, stack, contract, depth, err)
|
||||
}
|
||||
|
||||
// CaptureEnd is triggered at end of execution.
|
||||
|
|
|
|||
Loading…
Reference in a new issue