aboutsummaryrefslogtreecommitdiffstats
path: root/core/vm/vm.go
diff options
context:
space:
mode:
Diffstat (limited to 'core/vm/vm.go')
-rw-r--r--core/vm/vm.go31
1 files changed, 14 insertions, 17 deletions
diff --git a/core/vm/vm.go b/core/vm/vm.go
index 0c6bbcd42..320135ff2 100644
--- a/core/vm/vm.go
+++ b/core/vm/vm.go
@@ -35,6 +35,9 @@ type Vm struct {
// New returns a new Vm
func New(env Environment) *Vm {
+ // init the jump table. Also prepares the homestead changes
+ jumpTable.init(env.BlockNumber())
+
return &Vm{env: env}
}
@@ -43,16 +46,6 @@ func (self *Vm) Run(contract *Contract, input []byte) (ret []byte, err error) {
self.env.SetDepth(self.env.Depth() + 1)
defer self.env.SetDepth(self.env.Depth() - 1)
- // User defer pattern to check for an error and, based on the error being nil or not, use all gas and return.
- defer func() {
- if err != nil {
- // In case of a VM exception (known exceptions) all gas consumed (panics NOT included).
- contract.UseGas(contract.Gas)
-
- ret = contract.Return(nil)
- }
- }()
-
if contract.CodeAddr != nil {
if p := Precompiled[contract.CodeAddr.Str()]; p != nil {
return self.RunPrecompiled(p, input, contract)
@@ -61,7 +54,7 @@ func (self *Vm) Run(contract *Contract, input []byte) (ret []byte, err error) {
// Don't bother with the execution if there's no code.
if len(contract.Code) == 0 {
- return contract.Return(nil), nil
+ return nil, nil
}
var (
@@ -160,7 +153,6 @@ func (self *Vm) Run(contract *Contract, input []byte) (ret []byte, err error) {
// Get the memory location of pc
op = contract.GetOp(pc)
-
// calculate the new memory size and gas price for the current executing opcode
newMemSize, cost, err = calculateGasAndSize(self.env, contract, caller, op, statedb, mem, stack)
if err != nil {
@@ -177,7 +169,6 @@ func (self *Vm) Run(contract *Contract, input []byte) (ret []byte, err error) {
mem.Resize(newMemSize.Uint64())
// Add a log message
self.log(pc, op, contract.Gas, cost, mem, stack, contract, nil)
-
if opPtr := jumpTable[op]; opPtr.valid {
if opPtr.fn != nil {
opPtr.fn(instruction{}, &pc, self.env, contract, mem, stack)
@@ -205,13 +196,13 @@ func (self *Vm) Run(contract *Contract, input []byte) (ret []byte, err error) {
offset, size := stack.pop(), stack.pop()
ret := mem.GetPtr(offset.Int64(), size.Int64())
- return contract.Return(ret), nil
+ return ret, nil
case SUICIDE:
opSuicide(instruction{}, nil, self.env, contract, mem, stack)
fallthrough
case STOP: // Stop the contract
- return contract.Return(nil), nil
+ return nil, nil
}
}
} else {
@@ -332,7 +323,6 @@ func calculateGasAndSize(env Environment, contract *Contract, caller ContractRef
gas.Add(gas, stack.data[stack.len()-1])
if op == CALL {
- //if env.Db().GetStateObject(common.BigToAddress(stack.data[stack.len()-2])) == nil {
if !env.Db().Exist(common.BigToAddress(stack.data[stack.len()-2])) {
gas.Add(gas, params.CallNewAccountGas)
}
@@ -346,6 +336,13 @@ func calculateGasAndSize(env Environment, contract *Contract, caller ContractRef
y := calcMemSize(stack.data[stack.len()-4], stack.data[stack.len()-5])
newMemSize = common.BigMax(x, y)
+ case DELEGATECALL:
+ gas.Add(gas, stack.data[stack.len()-1])
+
+ x := calcMemSize(stack.data[stack.len()-5], stack.data[stack.len()-6])
+ y := calcMemSize(stack.data[stack.len()-3], stack.data[stack.len()-4])
+
+ newMemSize = common.BigMax(x, y)
}
quadMemGas(mem, newMemSize, gas)
@@ -358,7 +355,7 @@ func (self *Vm) RunPrecompiled(p *PrecompiledAccount, input []byte, contract *Co
if contract.UseGas(gas) {
ret = p.Call(input)
- return contract.Return(ret), nil
+ return ret, nil
} else {
return nil, OutOfGasError
}