diff --git a/tests/helper/vm.go b/tests/helper/vm.go index f1c1ffdfc..a1a1a98ca 100644 --- a/tests/helper/vm.go +++ b/tests/helper/vm.go @@ -28,6 +28,8 @@ type Env struct { gasLimit *big.Int logs state.Logs + + vmTest bool } func NewEnv(state *state.StateDB) *Env { @@ -92,20 +94,38 @@ func (self *Env) vm(addr, data []byte, gas, price, value *big.Int) *core.Executi } func (self *Env) Call(caller vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { + if self.vmTest && self.depth > 0 { + caller.ReturnGas(gas, price) + + return nil, nil + } exe := self.vm(addr, data, gas, price, value) ret, err := exe.Call(addr, caller) self.Gas = exe.Gas return ret, err + } func (self *Env) CallCode(caller vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { + if self.vmTest && self.depth > 0 { + caller.ReturnGas(gas, price) + } exe := self.vm(caller.Address(), data, gas, price, value) return exe.Call(addr, caller) } func (self *Env) Create(caller vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) { exe := self.vm(addr, data, gas, price, value) - return exe.Create(caller) + if self.vmTest { + caller.ReturnGas(gas, price) + + nonce := self.state.GetNonce(caller.Address()) + obj := self.state.GetOrNewStateObject(crypto.CreateAddress(caller.Address(), nonce)) + + return nil, nil, obj + } else { + return exe.Create(caller) + } } func RunVm(state *state.StateDB, env, exec map[string]string) ([]byte, state.Logs, *big.Int, error) { @@ -123,6 +143,7 @@ func RunVm(state *state.StateDB, env, exec map[string]string) ([]byte, state.Log caller := state.GetOrNewStateObject(from) vmenv := NewEnvFromMap(state, env, exec) + vmenv.vmTest = true vmenv.skipTransfer = true vmenv.initial = true ret, err := vmenv.Call(caller, to, data, gas, price, value) diff --git a/tests/vm/gh_test.go b/tests/vm/gh_test.go index a23076b74..f8c42f09c 100644 --- a/tests/vm/gh_test.go +++ b/tests/vm/gh_test.go @@ -79,12 +79,10 @@ func RunVmTest(p string, t *testing.T) { helper.CreateFileTests(t, p, &tests) for name, test := range tests { - /* - helper.Logger.SetLogLevel(4) - if name != "log1_nonEmptyMem_logMemSize1_logMemStart31" { - continue - } - */ + helper.Logger.SetLogLevel(4) + if name != "env1" { + continue + } db, _ := ethdb.NewMemDatabase() statedb := state.New(nil, db) for addr, account := range test.Pre { diff --git a/vm/common.go b/vm/common.go index bc1353009..1202966fd 100644 --- a/vm/common.go +++ b/vm/common.go @@ -43,7 +43,7 @@ var ( GasStorageMod = big.NewInt(5000) GasLogBase = big.NewInt(2000) GasLogTopic = big.NewInt(2000) - GasLogData = big.NewInt(8) + GasLogByte = big.NewInt(8) GasCreate = big.NewInt(32000) GasCreateByte = big.NewInt(300) GasCall = big.NewInt(40) @@ -57,11 +57,13 @@ var ( RefundSuicide = big.NewInt(24000) GasMemWord = big.NewInt(3) - GasQuadCoeffWord = big.NewInt(1) + GasQuadCoeffDenom = big.NewInt(512) GasContractByte = big.NewInt(200) GasTransaction = big.NewInt(21000) GasTxDataNonzeroByte = big.NewInt(37) GasTxZeroByte = big.NewInt(2) + GasExp = big.NewInt(10) + GasExpByte = big.NewInt(10) GasSha3Base = big.NewInt(30) GasSha3Word = big.NewInt(6) diff --git a/vm/vm.go b/vm/vm.go index e3b7df329..9f8d5e8df 100644 --- a/vm/vm.go +++ b/vm/vm.go @@ -812,6 +812,7 @@ var _baseCheck = map[OpCode]req{ COINBASE: {0, GasQuickStep}, TIMESTAMP: {0, GasQuickStep}, NUMBER: {0, GasQuickStep}, + CALLDATASIZE: {0, GasQuickStep}, DIFFICULTY: {0, GasQuickStep}, GASLIMIT: {0, GasQuickStep}, POP: {0, GasQuickStep}, @@ -862,9 +863,11 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16: n := int(op - SWAP1 + 2) stack.require(n) + gas.Set(GasFastestStep) case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16: n := int(op - DUP1 + 1) stack.require(n) + gas.Set(GasFastestStep) case LOG0, LOG1, LOG2, LOG3, LOG4: n := int(op - LOG0) stack.require(n + 2) @@ -873,11 +876,11 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo gas.Add(gas, GasLogBase) gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(n)), GasLogTopic)) - gas.Add(gas, new(big.Int).Mul(mSize, GasLogData)) + gas.Add(gas, new(big.Int).Mul(mSize, GasLogByte)) newMemSize = calcMemSize(mStart, mSize) case EXP: - gas.Add(gas, big.NewInt(int64(len(stack.data[stack.Len()-2].Bytes())+1))) + gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(len(stack.data[stack.Len()-2].Bytes()))), GasExpByte)) case SSTORE: stack.require(2) @@ -935,7 +938,7 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo gas.Add(gas, GasCallNewAccount) } - if len(stack.data[stack.Len()].Bytes()) > 0 { + if len(stack.data[stack.Len()-1].Bytes()) > 0 { gas.Add(gas, GasCallValueTransfer) } } @@ -953,11 +956,24 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo newMemSize.Mul(newMemSize, u256(32)) if newMemSize.Cmp(u256(int64(mem.Len()))) > 0 { - memGasUsage := new(big.Int).Sub(newMemSize, u256(int64(mem.Len()))) - memGasUsage.Mul(GasMemWord, memGasUsage) - memGasUsage.Div(memGasUsage, u256(32)) - - gas.Add(gas, memGasUsage) + //memGasUsage := new(big.Int).Sub(newMemSize, u256(int64(mem.Len()))) + //memGasUsage.Mul(GasMemWord, memGasUsage) + //memGasUsage.Div(memGasUsage, u256(32)) + + //Old: full_memory_gas_cost = W + floor(W*W / 1024), W = words in memory + oldSize := toWordSize(big.NewInt(int64(mem.Len()))) + linCoef := new(big.Int).Mul(oldSize, GasMemWord) + pow := new(big.Int) + pow.Exp(oldSize, ethutil.Big2, Zero) + quadCoef := new(big.Int).Div(pow, GasQuadCoeffDenom) + oldTotalFee := new(big.Int).Add(linCoef, quadCoef) + + linCoef = new(big.Int).Mul(newMemSize, GasMemWord) + pow.Exp(newMemSize, ethutil.Big2, Zero) + quadCoef = new(big.Int).Div(pow, GasQuadCoeffDenom) + newTotalFee := new(big.Int).Add(linCoef, quadCoef) + + gas.Add(gas, new(big.Int).Sub(newTotalFee, oldTotalFee)) } }