mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 13:46:43 +00:00
core/vm: interpreter loop generator PoC
This commit is contained in:
parent
f17df6db91
commit
ae63a92d08
8 changed files with 705 additions and 302 deletions
|
|
@ -18,7 +18,7 @@ package vm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
stdmath "math"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
|
@ -352,7 +352,7 @@ func opExtCodeCopyEIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeC
|
||||||
)
|
)
|
||||||
uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow()
|
uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow()
|
||||||
if overflow {
|
if overflow {
|
||||||
uint64CodeOffset = math.MaxUint64
|
uint64CodeOffset = stdmath.MaxUint64
|
||||||
}
|
}
|
||||||
addr := common.Address(a.Bytes20())
|
addr := common.Address(a.Bytes20())
|
||||||
code := interpreter.evm.StateDB.GetCode(addr)
|
code := interpreter.evm.StateDB.GetCode(addr)
|
||||||
|
|
|
||||||
|
|
@ -64,8 +64,7 @@ func memoryGasCost(mem *Memory, newMemSize uint64) (uint64, error) {
|
||||||
// MCOPY (stack position 2)
|
// MCOPY (stack position 2)
|
||||||
// EXTCODECOPY (stack position 3)
|
// EXTCODECOPY (stack position 3)
|
||||||
// RETURNDATACOPY (stack position 2)
|
// RETURNDATACOPY (stack position 2)
|
||||||
func memoryCopierGas(stackpos int) gasFunc {
|
func memoryCopierGas(stackpos int, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
|
||||||
// Gas for expanding the memory
|
// Gas for expanding the memory
|
||||||
gas, err := memoryGasCost(mem, memorySize)
|
gas, err := memoryGasCost(mem, memorySize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -86,15 +85,22 @@ func memoryCopierGas(stackpos int) gasFunc {
|
||||||
}
|
}
|
||||||
return gas, nil
|
return gas, nil
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
func gasCallDataCopy(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
gasCallDataCopy = memoryCopierGas(2)
|
return memoryCopierGas(2, evm, contract, stack, mem, memorySize)
|
||||||
gasCodeCopy = memoryCopierGas(2)
|
}
|
||||||
gasMcopy = memoryCopierGas(2)
|
func gasCodeCopy(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
gasExtCodeCopy = memoryCopierGas(3)
|
return memoryCopierGas(2, evm, contract, stack, mem, memorySize)
|
||||||
gasReturnDataCopy = memoryCopierGas(2)
|
}
|
||||||
)
|
func gasMcopy(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
|
return memoryCopierGas(2, evm, contract, stack, mem, memorySize)
|
||||||
|
}
|
||||||
|
func gasExtCodeCopy(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
|
return memoryCopierGas(3, evm, contract, stack, mem, memorySize)
|
||||||
|
}
|
||||||
|
func gasReturnDataCopy(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
|
return memoryCopierGas(2, evm, contract, stack, mem, memorySize)
|
||||||
|
}
|
||||||
|
|
||||||
func gasSStore(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
func gasSStore(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
var (
|
var (
|
||||||
|
|
@ -221,8 +227,7 @@ func gasSStoreEIP2200(evm *EVM, contract *Contract, stack *Stack, mem *Memory, m
|
||||||
return params.SloadGasEIP2200, nil // dirty update (2.2)
|
return params.SloadGasEIP2200, nil // dirty update (2.2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeGasLog(n uint64) gasFunc {
|
func makeGasLog(n uint64, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
|
||||||
requestedSize, overflow := stack.Back(1).Uint64WithOverflow()
|
requestedSize, overflow := stack.Back(1).Uint64WithOverflow()
|
||||||
if overflow {
|
if overflow {
|
||||||
return 0, ErrGasUintOverflow
|
return 0, ErrGasUintOverflow
|
||||||
|
|
@ -249,6 +254,21 @@ func makeGasLog(n uint64) gasFunc {
|
||||||
}
|
}
|
||||||
return gas, nil
|
return gas, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func gasLog0(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
|
return makeGasLog(0, evm, contract, stack, mem, memorySize)
|
||||||
|
}
|
||||||
|
func gasLog1(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
|
return makeGasLog(1, evm, contract, stack, mem, memorySize)
|
||||||
|
}
|
||||||
|
func gasLog2(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
|
return makeGasLog(2, evm, contract, stack, mem, memorySize)
|
||||||
|
}
|
||||||
|
func gasLog3(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
|
return makeGasLog(3, evm, contract, stack, mem, memorySize)
|
||||||
|
}
|
||||||
|
func gasLog4(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
|
return makeGasLog(4, evm, contract, stack, mem, memorySize)
|
||||||
}
|
}
|
||||||
|
|
||||||
func gasKeccak256(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
func gasKeccak256(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
|
|
|
||||||
217
core/vm/generator.go
Normal file
217
core/vm/generator.go
Normal file
|
|
@ -0,0 +1,217 @@
|
||||||
|
package vm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go/ast"
|
||||||
|
"go/parser"
|
||||||
|
"go/token"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var fSet = token.NewFileSet()
|
||||||
|
|
||||||
|
type opFuncNames struct {
|
||||||
|
memory string
|
||||||
|
gas string
|
||||||
|
execution string
|
||||||
|
}
|
||||||
|
|
||||||
|
func functionName(f any) string {
|
||||||
|
fValue := reflect.ValueOf(f)
|
||||||
|
if fValue.IsNil() {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
rFunc := runtime.FuncForPC(fValue.Pointer())
|
||||||
|
if rFunc == nil {
|
||||||
|
panic(fmt.Sprint(f, "is not a function"))
|
||||||
|
}
|
||||||
|
ident := rFunc.Name()
|
||||||
|
arr := strings.Split(ident, ".")
|
||||||
|
return arr[len(arr)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func collectFuncNames(jt JumpTable) [256]opFuncNames {
|
||||||
|
var funcNames [256]opFuncNames
|
||||||
|
for opCode, entry := range jt {
|
||||||
|
funcNames[opCode] = opFuncNames{
|
||||||
|
memory: functionName(entry.memorySize),
|
||||||
|
gas: functionName(entry.dynamicGas),
|
||||||
|
execution: functionName(entry.execute),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return funcNames
|
||||||
|
}
|
||||||
|
|
||||||
|
type funcDef struct {
|
||||||
|
decl *ast.FuncDecl
|
||||||
|
source string
|
||||||
|
}
|
||||||
|
|
||||||
|
type opFuncDefs struct {
|
||||||
|
memory funcDef
|
||||||
|
gas funcDef
|
||||||
|
execution funcDef
|
||||||
|
}
|
||||||
|
|
||||||
|
func definitionTargets(name string, funcNames *[256]opFuncNames, funcDefs *[256]opFuncDefs) []*funcDef {
|
||||||
|
targets := []*funcDef{}
|
||||||
|
for op := range funcNames {
|
||||||
|
if funcNames[op].memory == name {
|
||||||
|
targets = append(targets, &funcDefs[op].memory)
|
||||||
|
}
|
||||||
|
if funcNames[op].gas == name {
|
||||||
|
targets = append(targets, &funcDefs[op].gas)
|
||||||
|
}
|
||||||
|
if funcNames[op].execution == name {
|
||||||
|
targets = append(targets, &funcDefs[op].execution)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return targets
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractBody(funcDef string) string {
|
||||||
|
start := strings.Index(funcDef, "{")
|
||||||
|
end := strings.LastIndex(funcDef, "}")
|
||||||
|
return funcDef[start : end+1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func collectFuncDefinitions(funcNames [256]opFuncNames) [256]opFuncDefs {
|
||||||
|
pkgs, err := parser.ParseDir(fSet, ".", nil, 0)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprint("failed to parse vm package", err))
|
||||||
|
}
|
||||||
|
vmPkg := pkgs["vm"]
|
||||||
|
if vmPkg == nil {
|
||||||
|
panic(fmt.Sprint("vm package not found"))
|
||||||
|
}
|
||||||
|
|
||||||
|
var defs [256]opFuncDefs
|
||||||
|
for _, astFile := range vmPkg.Files {
|
||||||
|
f, err := os.Open(fSet.File(astFile.FileStart).Name())
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprint("failed to open file package", astFile.Name.Name, err))
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, decl := range astFile.Decls {
|
||||||
|
if fDecl, isFunc := decl.(*ast.FuncDecl); isFunc {
|
||||||
|
defTargets := definitionTargets(fDecl.Name.Name, &funcNames, &defs)
|
||||||
|
if len(defTargets) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
declPos := fSet.Position(fDecl.Pos())
|
||||||
|
declEndPos := fSet.Position(fDecl.End())
|
||||||
|
declSize := declEndPos.Offset - declPos.Offset
|
||||||
|
|
||||||
|
def := make([]byte, declSize)
|
||||||
|
_, err := f.ReadAt(def, int64(declPos.Offset))
|
||||||
|
if err != nil && err != io.EOF {
|
||||||
|
panic(fmt.Sprint("failed to read function def", fDecl.Name.Name, err))
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, defTarget := range defTargets {
|
||||||
|
(*defTarget) = funcDef{
|
||||||
|
source: string(def),
|
||||||
|
decl: fDecl,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return defs
|
||||||
|
}
|
||||||
|
|
||||||
|
func outputMemoryCalc(w io.Writer, op *funcDef) {
|
||||||
|
fmt.Fprintf(w, `
|
||||||
|
_memorySize, _overflow := func (stack *Stack) (uint64, bool) %s(callContext.Stack)
|
||||||
|
if _overflow {
|
||||||
|
return nil, ErrGasUintOverflow
|
||||||
|
}
|
||||||
|
`, extractBody(op.source))
|
||||||
|
}
|
||||||
|
|
||||||
|
func outputDynamicGas(w io.Writer, op *funcDef, hasDynamicMemory bool) {
|
||||||
|
dynamicMemory := "0"
|
||||||
|
if hasDynamicMemory {
|
||||||
|
dynamicMemory = "_memorySize"
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, `
|
||||||
|
_dynamicGas, _gasErr := func (evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) %s(interpreter.evm, callContext.Contract, callContext.Stack, callContext.Memory, %s)
|
||||||
|
if _gasErr != nil {
|
||||||
|
return nil, ErrOutOfGas
|
||||||
|
}
|
||||||
|
if !callContext.Contract.UseGas(_dynamicGas, nil, tracing.GasChangeIgnored) {
|
||||||
|
return nil, ErrOutOfGas
|
||||||
|
}
|
||||||
|
|
||||||
|
`, extractBody(op.source), dynamicMemory)
|
||||||
|
if hasDynamicMemory {
|
||||||
|
fmt.Fprintf(w, "callContext.Memory.Resize(_memorySize)\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func outputExecution(w io.Writer, op *funcDef) {
|
||||||
|
fmt.Fprintf(w, `
|
||||||
|
_, _executionErr := func (pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) %s(&pc, interpreter, callContext)
|
||||||
|
if _executionErr != nil {
|
||||||
|
return nil, _executionErr
|
||||||
|
}
|
||||||
|
`, extractBody(op.source))
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenerateRun() {
|
||||||
|
set := newLondonInstructionSet()
|
||||||
|
funcNames := collectFuncNames(set)
|
||||||
|
funcDefinitions := collectFuncDefinitions(funcNames)
|
||||||
|
|
||||||
|
output, _ := os.Create("out.go")
|
||||||
|
|
||||||
|
fmt.Fprintln(output, `package vm
|
||||||
|
func Run(interpreter *EVMInterpreter, callContext *ScopeContext) ([]byte, error) {
|
||||||
|
|
||||||
|
var pc uint64
|
||||||
|
for {
|
||||||
|
op := callContext.Contract.GetOp(pc)
|
||||||
|
switch op {
|
||||||
|
`)
|
||||||
|
for opCode := range funcDefinitions {
|
||||||
|
fmt.Fprintf(output, `case %d:
|
||||||
|
if !callContext.Contract.UseGas(%d, nil, tracing.GasChangeIgnored) {
|
||||||
|
return nil, ErrOutOfGas
|
||||||
|
}
|
||||||
|
|
||||||
|
if sLen := callContext.Stack.len(); sLen < %d {
|
||||||
|
return nil, &ErrStackUnderflow{stackLen: sLen, required: %d}
|
||||||
|
} else if sLen > %d {
|
||||||
|
return nil, &ErrStackOverflow{stackLen: sLen, limit: %d}
|
||||||
|
}
|
||||||
|
`, opCode, set[opCode].constantGas, set[opCode].minStack, set[opCode].minStack, set[opCode].maxStack, set[opCode].maxStack)
|
||||||
|
if funcDefinitions[opCode].memory.decl != nil {
|
||||||
|
outputMemoryCalc(output, &funcDefinitions[opCode].memory)
|
||||||
|
} else if len(funcNames[opCode].memory) > 0 {
|
||||||
|
panic(fmt.Sprint("failed to get memory handler definition for ", opCodeToString[opCode]))
|
||||||
|
}
|
||||||
|
|
||||||
|
if funcDefinitions[opCode].gas.decl != nil {
|
||||||
|
outputDynamicGas(output, &funcDefinitions[opCode].gas, funcDefinitions[opCode].memory.decl != nil)
|
||||||
|
} else if len(funcNames[opCode].gas) > 0 {
|
||||||
|
panic(fmt.Sprint("failed to get gas handler definition for ", opCodeToString[opCode]))
|
||||||
|
}
|
||||||
|
|
||||||
|
if funcDefinitions[opCode].execution.decl != nil {
|
||||||
|
outputExecution(output, &funcDefinitions[opCode].execution)
|
||||||
|
} else if len(funcNames[opCode].execution) > 0 {
|
||||||
|
panic(fmt.Sprint("failed to get exec handler definition for ", opCodeToString[opCode]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Fprintln(output, `}
|
||||||
|
pc++
|
||||||
|
}}`)
|
||||||
|
output.Close()
|
||||||
|
}
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
package vm
|
package vm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
stdmath "math"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
|
|
@ -296,7 +296,7 @@ func opCallDataCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
|
||||||
)
|
)
|
||||||
dataOffset64, overflow := dataOffset.Uint64WithOverflow()
|
dataOffset64, overflow := dataOffset.Uint64WithOverflow()
|
||||||
if overflow {
|
if overflow {
|
||||||
dataOffset64 = math.MaxUint64
|
dataOffset64 = stdmath.MaxUint64
|
||||||
}
|
}
|
||||||
// These values are checked for overflow during gas cost calculation
|
// These values are checked for overflow during gas cost calculation
|
||||||
memOffset64 := memOffset.Uint64()
|
memOffset64 := memOffset.Uint64()
|
||||||
|
|
@ -352,7 +352,7 @@ func opCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
|
||||||
)
|
)
|
||||||
uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow()
|
uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow()
|
||||||
if overflow {
|
if overflow {
|
||||||
uint64CodeOffset = math.MaxUint64
|
uint64CodeOffset = stdmath.MaxUint64
|
||||||
}
|
}
|
||||||
|
|
||||||
codeCopy := getData(scope.Contract.Code, uint64CodeOffset, length.Uint64())
|
codeCopy := getData(scope.Contract.Code, uint64CodeOffset, length.Uint64())
|
||||||
|
|
@ -370,7 +370,7 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
|
||||||
)
|
)
|
||||||
uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow()
|
uint64CodeOffset, overflow := codeOffset.Uint64WithOverflow()
|
||||||
if overflow {
|
if overflow {
|
||||||
uint64CodeOffset = math.MaxUint64
|
uint64CodeOffset = stdmath.MaxUint64
|
||||||
}
|
}
|
||||||
addr := common.Address(a.Bytes20())
|
addr := common.Address(a.Bytes20())
|
||||||
code := interpreter.evm.StateDB.GetCode(addr)
|
code := interpreter.evm.StateDB.GetCode(addr)
|
||||||
|
|
@ -924,8 +924,7 @@ func opSelfdestruct6780(pc *uint64, interpreter *EVMInterpreter, scope *ScopeCon
|
||||||
// following functions are used by the instruction jump table
|
// following functions are used by the instruction jump table
|
||||||
|
|
||||||
// make log instruction function
|
// make log instruction function
|
||||||
func makeLog(size int) executionFunc {
|
func doLog(size int, pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
|
||||||
if interpreter.readOnly {
|
if interpreter.readOnly {
|
||||||
return nil, ErrWriteProtection
|
return nil, ErrWriteProtection
|
||||||
}
|
}
|
||||||
|
|
@ -949,6 +948,21 @@ func makeLog(size int) executionFunc {
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func opLog0(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doLog(0, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opLog1(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doLog(1, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opLog2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doLog(2, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opLog3(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doLog(3, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opLog4(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doLog(4, pc, interpreter, scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
// opPush1 is a specialized version of pushN
|
// opPush1 is a specialized version of pushN
|
||||||
|
|
@ -983,10 +997,9 @@ func opPush2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// make push instruction function
|
func doPush(size uint64, pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
func makePush(size uint64, pushByteSize int) executionFunc {
|
|
||||||
return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
|
||||||
var (
|
var (
|
||||||
|
pushByteSize = int(size)
|
||||||
codeLen = len(scope.Contract.Code)
|
codeLen = len(scope.Contract.Code)
|
||||||
start = min(codeLen, int(*pc+1))
|
start = min(codeLen, int(*pc+1))
|
||||||
end = min(codeLen, start+pushByteSize)
|
end = min(codeLen, start+pushByteSize)
|
||||||
|
|
@ -1001,12 +1014,159 @@ func makePush(size uint64, pushByteSize int) executionFunc {
|
||||||
*pc += size
|
*pc += size
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func opPush3(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(3, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush4(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(4, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush5(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(5, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush6(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(6, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush7(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(7, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush8(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(8, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush9(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(9, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush10(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(10, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush11(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(11, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush12(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(12, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush13(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(13, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush14(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(14, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush15(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(15, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush16(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(16, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush17(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(17, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush18(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(18, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush19(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(19, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush20(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(20, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush21(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(21, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush22(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(22, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush23(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(23, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush24(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(24, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush25(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(25, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush26(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(26, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush27(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(27, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush28(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(28, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush29(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(29, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush30(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(30, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush31(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(31, pc, interpreter, scope)
|
||||||
|
}
|
||||||
|
func opPush32(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
return doPush(32, pc, interpreter, scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
// make dup instruction function
|
func opDup1(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
func makeDup(size int64) executionFunc {
|
scope.Stack.dup(1)
|
||||||
return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
|
||||||
scope.Stack.dup(int(size))
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
func opDup2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.dup(2)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func opDup3(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.dup(3)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func opDup4(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.dup(4)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func opDup5(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.dup(5)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func opDup6(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.dup(6)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func opDup7(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.dup(7)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func opDup8(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.dup(8)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func opDup9(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.dup(9)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func opDup10(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.dup(10)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func opDup11(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.dup(11)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func opDup12(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.dup(12)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func opDup13(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.dup(13)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func opDup14(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.dup(14)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func opDup15(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.dup(15)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func opDup16(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.dup(16)
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -906,7 +906,7 @@ func TestOpMCopy(t *testing.T) {
|
||||||
func TestPush(t *testing.T) {
|
func TestPush(t *testing.T) {
|
||||||
code := common.FromHex("0011223344556677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a19181716151413121")
|
code := common.FromHex("0011223344556677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a19181716151413121")
|
||||||
|
|
||||||
push32 := makePush(32, 32)
|
push32 := opPush32
|
||||||
|
|
||||||
scope := &ScopeContext{
|
scope := &ScopeContext{
|
||||||
Memory: nil,
|
Memory: nil,
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,6 @@ func BenchmarkInterpreter(b *testing.B) {
|
||||||
)
|
)
|
||||||
stack.push(uint256.NewInt(123))
|
stack.push(uint256.NewInt(123))
|
||||||
stack.push(uint256.NewInt(123))
|
stack.push(uint256.NewInt(123))
|
||||||
gasSStoreEIP3529 = makeGasSStoreFunc(params.SstoreClearsScheduleRefundEIP3529)
|
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
gasSStoreEIP3529(evm, contract, stack, mem, 1234)
|
gasSStoreEIP3529(evm, contract, stack, mem, 1234)
|
||||||
|
|
|
||||||
|
|
@ -633,277 +633,277 @@ func newFrontierInstructionSet() JumpTable {
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH3: {
|
PUSH3: {
|
||||||
execute: makePush(3, 3),
|
execute: opPush3,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH4: {
|
PUSH4: {
|
||||||
execute: makePush(4, 4),
|
execute: opPush4,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH5: {
|
PUSH5: {
|
||||||
execute: makePush(5, 5),
|
execute: opPush5,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH6: {
|
PUSH6: {
|
||||||
execute: makePush(6, 6),
|
execute: opPush6,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH7: {
|
PUSH7: {
|
||||||
execute: makePush(7, 7),
|
execute: opPush7,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH8: {
|
PUSH8: {
|
||||||
execute: makePush(8, 8),
|
execute: opPush8,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH9: {
|
PUSH9: {
|
||||||
execute: makePush(9, 9),
|
execute: opPush9,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH10: {
|
PUSH10: {
|
||||||
execute: makePush(10, 10),
|
execute: opPush10,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH11: {
|
PUSH11: {
|
||||||
execute: makePush(11, 11),
|
execute: opPush11,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH12: {
|
PUSH12: {
|
||||||
execute: makePush(12, 12),
|
execute: opPush12,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH13: {
|
PUSH13: {
|
||||||
execute: makePush(13, 13),
|
execute: opPush13,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH14: {
|
PUSH14: {
|
||||||
execute: makePush(14, 14),
|
execute: opPush14,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH15: {
|
PUSH15: {
|
||||||
execute: makePush(15, 15),
|
execute: opPush15,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH16: {
|
PUSH16: {
|
||||||
execute: makePush(16, 16),
|
execute: opPush16,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH17: {
|
PUSH17: {
|
||||||
execute: makePush(17, 17),
|
execute: opPush17,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH18: {
|
PUSH18: {
|
||||||
execute: makePush(18, 18),
|
execute: opPush18,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH19: {
|
PUSH19: {
|
||||||
execute: makePush(19, 19),
|
execute: opPush19,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH20: {
|
PUSH20: {
|
||||||
execute: makePush(20, 20),
|
execute: opPush20,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH21: {
|
PUSH21: {
|
||||||
execute: makePush(21, 21),
|
execute: opPush21,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH22: {
|
PUSH22: {
|
||||||
execute: makePush(22, 22),
|
execute: opPush22,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH23: {
|
PUSH23: {
|
||||||
execute: makePush(23, 23),
|
execute: opPush23,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH24: {
|
PUSH24: {
|
||||||
execute: makePush(24, 24),
|
execute: opPush24,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH25: {
|
PUSH25: {
|
||||||
execute: makePush(25, 25),
|
execute: opPush25,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH26: {
|
PUSH26: {
|
||||||
execute: makePush(26, 26),
|
execute: opPush26,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH27: {
|
PUSH27: {
|
||||||
execute: makePush(27, 27),
|
execute: opPush27,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH28: {
|
PUSH28: {
|
||||||
execute: makePush(28, 28),
|
execute: opPush28,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH29: {
|
PUSH29: {
|
||||||
execute: makePush(29, 29),
|
execute: opPush29,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH30: {
|
PUSH30: {
|
||||||
execute: makePush(30, 30),
|
execute: opPush30,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH31: {
|
PUSH31: {
|
||||||
execute: makePush(31, 31),
|
execute: opPush31,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
PUSH32: {
|
PUSH32: {
|
||||||
execute: makePush(32, 32),
|
execute: opPush32,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minStack(0, 1),
|
minStack: minStack(0, 1),
|
||||||
maxStack: maxStack(0, 1),
|
maxStack: maxStack(0, 1),
|
||||||
},
|
},
|
||||||
DUP1: {
|
DUP1: {
|
||||||
execute: makeDup(1),
|
execute: opDup1,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minDupStack(1),
|
minStack: minDupStack(1),
|
||||||
maxStack: maxDupStack(1),
|
maxStack: maxDupStack(1),
|
||||||
},
|
},
|
||||||
DUP2: {
|
DUP2: {
|
||||||
execute: makeDup(2),
|
execute: opDup2,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minDupStack(2),
|
minStack: minDupStack(2),
|
||||||
maxStack: maxDupStack(2),
|
maxStack: maxDupStack(2),
|
||||||
},
|
},
|
||||||
DUP3: {
|
DUP3: {
|
||||||
execute: makeDup(3),
|
execute: opDup3,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minDupStack(3),
|
minStack: minDupStack(3),
|
||||||
maxStack: maxDupStack(3),
|
maxStack: maxDupStack(3),
|
||||||
},
|
},
|
||||||
DUP4: {
|
DUP4: {
|
||||||
execute: makeDup(4),
|
execute: opDup4,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minDupStack(4),
|
minStack: minDupStack(4),
|
||||||
maxStack: maxDupStack(4),
|
maxStack: maxDupStack(4),
|
||||||
},
|
},
|
||||||
DUP5: {
|
DUP5: {
|
||||||
execute: makeDup(5),
|
execute: opDup5,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minDupStack(5),
|
minStack: minDupStack(5),
|
||||||
maxStack: maxDupStack(5),
|
maxStack: maxDupStack(5),
|
||||||
},
|
},
|
||||||
DUP6: {
|
DUP6: {
|
||||||
execute: makeDup(6),
|
execute: opDup6,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minDupStack(6),
|
minStack: minDupStack(6),
|
||||||
maxStack: maxDupStack(6),
|
maxStack: maxDupStack(6),
|
||||||
},
|
},
|
||||||
DUP7: {
|
DUP7: {
|
||||||
execute: makeDup(7),
|
execute: opDup7,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minDupStack(7),
|
minStack: minDupStack(7),
|
||||||
maxStack: maxDupStack(7),
|
maxStack: maxDupStack(7),
|
||||||
},
|
},
|
||||||
DUP8: {
|
DUP8: {
|
||||||
execute: makeDup(8),
|
execute: opDup8,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minDupStack(8),
|
minStack: minDupStack(8),
|
||||||
maxStack: maxDupStack(8),
|
maxStack: maxDupStack(8),
|
||||||
},
|
},
|
||||||
DUP9: {
|
DUP9: {
|
||||||
execute: makeDup(9),
|
execute: opDup9,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minDupStack(9),
|
minStack: minDupStack(9),
|
||||||
maxStack: maxDupStack(9),
|
maxStack: maxDupStack(9),
|
||||||
},
|
},
|
||||||
DUP10: {
|
DUP10: {
|
||||||
execute: makeDup(10),
|
execute: opDup10,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minDupStack(10),
|
minStack: minDupStack(10),
|
||||||
maxStack: maxDupStack(10),
|
maxStack: maxDupStack(10),
|
||||||
},
|
},
|
||||||
DUP11: {
|
DUP11: {
|
||||||
execute: makeDup(11),
|
execute: opDup11,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minDupStack(11),
|
minStack: minDupStack(11),
|
||||||
maxStack: maxDupStack(11),
|
maxStack: maxDupStack(11),
|
||||||
},
|
},
|
||||||
DUP12: {
|
DUP12: {
|
||||||
execute: makeDup(12),
|
execute: opDup12,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minDupStack(12),
|
minStack: minDupStack(12),
|
||||||
maxStack: maxDupStack(12),
|
maxStack: maxDupStack(12),
|
||||||
},
|
},
|
||||||
DUP13: {
|
DUP13: {
|
||||||
execute: makeDup(13),
|
execute: opDup13,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minDupStack(13),
|
minStack: minDupStack(13),
|
||||||
maxStack: maxDupStack(13),
|
maxStack: maxDupStack(13),
|
||||||
},
|
},
|
||||||
DUP14: {
|
DUP14: {
|
||||||
execute: makeDup(14),
|
execute: opDup14,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minDupStack(14),
|
minStack: minDupStack(14),
|
||||||
maxStack: maxDupStack(14),
|
maxStack: maxDupStack(14),
|
||||||
},
|
},
|
||||||
DUP15: {
|
DUP15: {
|
||||||
execute: makeDup(15),
|
execute: opDup15,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minDupStack(15),
|
minStack: minDupStack(15),
|
||||||
maxStack: maxDupStack(15),
|
maxStack: maxDupStack(15),
|
||||||
},
|
},
|
||||||
DUP16: {
|
DUP16: {
|
||||||
execute: makeDup(16),
|
execute: opDup16,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minDupStack(16),
|
minStack: minDupStack(16),
|
||||||
maxStack: maxDupStack(16),
|
maxStack: maxDupStack(16),
|
||||||
|
|
@ -1005,36 +1005,36 @@ func newFrontierInstructionSet() JumpTable {
|
||||||
maxStack: maxSwapStack(17),
|
maxStack: maxSwapStack(17),
|
||||||
},
|
},
|
||||||
LOG0: {
|
LOG0: {
|
||||||
execute: makeLog(0),
|
execute: opLog0,
|
||||||
dynamicGas: makeGasLog(0),
|
dynamicGas: gasLog0,
|
||||||
minStack: minStack(2, 0),
|
minStack: minStack(2, 0),
|
||||||
maxStack: maxStack(2, 0),
|
maxStack: maxStack(2, 0),
|
||||||
memorySize: memoryLog,
|
memorySize: memoryLog,
|
||||||
},
|
},
|
||||||
LOG1: {
|
LOG1: {
|
||||||
execute: makeLog(1),
|
execute: opLog1,
|
||||||
dynamicGas: makeGasLog(1),
|
dynamicGas: gasLog1,
|
||||||
minStack: minStack(3, 0),
|
minStack: minStack(3, 0),
|
||||||
maxStack: maxStack(3, 0),
|
maxStack: maxStack(3, 0),
|
||||||
memorySize: memoryLog,
|
memorySize: memoryLog,
|
||||||
},
|
},
|
||||||
LOG2: {
|
LOG2: {
|
||||||
execute: makeLog(2),
|
execute: opLog2,
|
||||||
dynamicGas: makeGasLog(2),
|
dynamicGas: gasLog2,
|
||||||
minStack: minStack(4, 0),
|
minStack: minStack(4, 0),
|
||||||
maxStack: maxStack(4, 0),
|
maxStack: maxStack(4, 0),
|
||||||
memorySize: memoryLog,
|
memorySize: memoryLog,
|
||||||
},
|
},
|
||||||
LOG3: {
|
LOG3: {
|
||||||
execute: makeLog(3),
|
execute: opLog3,
|
||||||
dynamicGas: makeGasLog(3),
|
dynamicGas: gasLog3,
|
||||||
minStack: minStack(5, 0),
|
minStack: minStack(5, 0),
|
||||||
maxStack: maxStack(5, 0),
|
maxStack: maxStack(5, 0),
|
||||||
memorySize: memoryLog,
|
memorySize: memoryLog,
|
||||||
},
|
},
|
||||||
LOG4: {
|
LOG4: {
|
||||||
execute: makeLog(4),
|
execute: opLog4,
|
||||||
dynamicGas: makeGasLog(4),
|
dynamicGas: gasLog4,
|
||||||
minStack: minStack(6, 0),
|
minStack: minStack(6, 0),
|
||||||
maxStack: maxStack(6, 0),
|
maxStack: maxStack(6, 0),
|
||||||
memorySize: memoryLog,
|
memorySize: memoryLog,
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeGasSStoreFunc(clearingRefund uint64) gasFunc {
|
func gasSStoreFuncEIP(clearingRefund uint64, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
|
||||||
// If we fail the minimum gas availability invariant, fail (0)
|
// If we fail the minimum gas availability invariant, fail (0)
|
||||||
if contract.Gas <= params.SstoreSentryGasEIP2200 {
|
if contract.Gas <= params.SstoreSentryGasEIP2200 {
|
||||||
return 0, errors.New("not enough gas for reentrancy sentry")
|
return 0, errors.New("not enough gas for reentrancy sentry")
|
||||||
|
|
@ -88,7 +87,6 @@ func makeGasSStoreFunc(clearingRefund uint64) gasFunc {
|
||||||
//return params.SloadGasEIP2200, nil // dirty update (2.2)
|
//return params.SloadGasEIP2200, nil // dirty update (2.2)
|
||||||
return cost + params.WarmStorageReadCostEIP2929, nil // dirty update (2.2)
|
return cost + params.WarmStorageReadCostEIP2929, nil // dirty update (2.2)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// gasSLoadEIP2929 calculates dynamic gas for SLOAD according to EIP-2929
|
// gasSLoadEIP2929 calculates dynamic gas for SLOAD according to EIP-2929
|
||||||
// For SLOAD, if the (address, storage_key) pair (where address is the address of the contract
|
// For SLOAD, if the (address, storage_key) pair (where address is the address of the contract
|
||||||
|
|
@ -152,8 +150,7 @@ func gasEip2929AccountCheck(evm *EVM, contract *Contract, stack *Stack, mem *Mem
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeCallVariantGasCallEIP2929(oldCalculator gasFunc, addressPosition int) gasFunc {
|
func makeCallVariantGasCallEIP2929(oldCalculator gasFunc, addressPosition int, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
return func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
|
||||||
addr := common.Address(stack.Back(addressPosition).Bytes20())
|
addr := common.Address(stack.Back(addressPosition).Bytes20())
|
||||||
// Check slot presence in the access list
|
// Check slot presence in the access list
|
||||||
warmAccess := evm.StateDB.AddressInAccessList(addr)
|
warmAccess := evm.StateDB.AddressInAccessList(addr)
|
||||||
|
|
@ -189,16 +186,25 @@ func makeCallVariantGasCallEIP2929(oldCalculator gasFunc, addressPosition int) g
|
||||||
}
|
}
|
||||||
return gas, nil
|
return gas, nil
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
func gasCallEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
gasCallEIP2929 = makeCallVariantGasCallEIP2929(gasCall, 1)
|
return makeCallVariantGasCallEIP2929(gasCall, 1, evm, contract, stack, mem, memorySize)
|
||||||
gasDelegateCallEIP2929 = makeCallVariantGasCallEIP2929(gasDelegateCall, 1)
|
}
|
||||||
gasStaticCallEIP2929 = makeCallVariantGasCallEIP2929(gasStaticCall, 1)
|
func gasDelegateCallEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
gasCallCodeEIP2929 = makeCallVariantGasCallEIP2929(gasCallCode, 1)
|
return makeCallVariantGasCallEIP2929(gasDelegateCall, 1, evm, contract, stack, mem, memorySize)
|
||||||
gasSelfdestructEIP2929 = makeSelfdestructGasFn(true)
|
}
|
||||||
// gasSelfdestructEIP3529 implements the changes in EIP-3529 (no refunds)
|
func gasStaticCallEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
gasSelfdestructEIP3529 = makeSelfdestructGasFn(false)
|
return makeCallVariantGasCallEIP2929(gasStaticCall, 1, evm, contract, stack, mem, memorySize)
|
||||||
|
}
|
||||||
|
func gasCallCodeEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
|
return makeCallVariantGasCallEIP2929(gasCallCode, 1, evm, contract, stack, mem, memorySize)
|
||||||
|
}
|
||||||
|
func gasSelfdestructEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
|
return makeSelfdestructGasFn(true, evm, contract, stack, mem, memorySize)
|
||||||
|
}
|
||||||
|
func gasSelfdestructEIP3529(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
|
return makeSelfdestructGasFn(false, evm, contract, stack, mem, memorySize)
|
||||||
|
}
|
||||||
|
|
||||||
// gasSStoreEIP2929 implements gas cost for SSTORE according to EIP-2929
|
// gasSStoreEIP2929 implements gas cost for SSTORE according to EIP-2929
|
||||||
//
|
//
|
||||||
|
|
@ -212,16 +218,19 @@ var (
|
||||||
//
|
//
|
||||||
// The other parameters defined in EIP 2200 are unchanged.
|
// The other parameters defined in EIP 2200 are unchanged.
|
||||||
// see gasSStoreEIP2200(...) in core/vm/gas_table.go for more info about how EIP 2200 is specified
|
// see gasSStoreEIP2200(...) in core/vm/gas_table.go for more info about how EIP 2200 is specified
|
||||||
gasSStoreEIP2929 = makeGasSStoreFunc(params.SstoreClearsScheduleRefundEIP2200)
|
func gasSStoreEIP2929(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
|
return gasSStoreFuncEIP(params.SstoreClearsScheduleRefundEIP2200, evm, contract, stack, mem, memorySize)
|
||||||
|
}
|
||||||
|
|
||||||
// gasSStoreEIP3529 implements gas cost for SSTORE according to EIP-3529
|
// gasSStoreEIP3529 implements gas cost for SSTORE according to EIP-3529
|
||||||
// Replace `SSTORE_CLEARS_SCHEDULE` with `SSTORE_RESET_GAS + ACCESS_LIST_STORAGE_KEY_COST` (4,800)
|
// Replace `SSTORE_CLEARS_SCHEDULE` with `SSTORE_RESET_GAS + ACCESS_LIST_STORAGE_KEY_COST` (4,800)
|
||||||
gasSStoreEIP3529 = makeGasSStoreFunc(params.SstoreClearsScheduleRefundEIP3529)
|
func gasSStoreEIP3529(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
)
|
return gasSStoreFuncEIP(params.SstoreClearsScheduleRefundEIP3529, evm, contract, stack, mem, memorySize)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// makeSelfdestructGasFn can create the selfdestruct dynamic gas function for EIP-2929 and EIP-3529
|
// makeSelfdestructGasFn can create the selfdestruct dynamic gas function for EIP-2929 and EIP-3529
|
||||||
func makeSelfdestructGasFn(refundsEnabled bool) gasFunc {
|
func makeSelfdestructGasFn(refundsEnabled bool, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
gasFunc := func(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
|
||||||
var (
|
var (
|
||||||
gas uint64
|
gas uint64
|
||||||
address = common.Address(stack.peek().Bytes20())
|
address = common.Address(stack.peek().Bytes20())
|
||||||
|
|
@ -240,8 +249,6 @@ func makeSelfdestructGasFn(refundsEnabled bool) gasFunc {
|
||||||
}
|
}
|
||||||
return gas, nil
|
return gas, nil
|
||||||
}
|
}
|
||||||
return gasFunc
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
gasCallEIP7702 = makeCallVariantGasCallEIP7702(gasCall)
|
gasCallEIP7702 = makeCallVariantGasCallEIP7702(gasCall)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue