This commit is contained in:
obscuren 2015-03-03 11:11:11 +01:00
parent fe7ab662f0
commit c1ef19bef9
4 changed files with 53 additions and 16 deletions

View File

@ -28,6 +28,8 @@ type Env struct {
gasLimit *big.Int gasLimit *big.Int
logs state.Logs logs state.Logs
vmTest bool
} }
func NewEnv(state *state.StateDB) *Env { 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) { 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) exe := self.vm(addr, data, gas, price, value)
ret, err := exe.Call(addr, caller) ret, err := exe.Call(addr, caller)
self.Gas = exe.Gas self.Gas = exe.Gas
return ret, err return ret, err
} }
func (self *Env) CallCode(caller vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { 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) exe := self.vm(caller.Address(), data, gas, price, value)
return exe.Call(addr, caller) return exe.Call(addr, caller)
} }
func (self *Env) Create(caller vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) { 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) 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) { 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) caller := state.GetOrNewStateObject(from)
vmenv := NewEnvFromMap(state, env, exec) vmenv := NewEnvFromMap(state, env, exec)
vmenv.vmTest = true
vmenv.skipTransfer = true vmenv.skipTransfer = true
vmenv.initial = true vmenv.initial = true
ret, err := vmenv.Call(caller, to, data, gas, price, value) ret, err := vmenv.Call(caller, to, data, gas, price, value)

View File

@ -79,12 +79,10 @@ func RunVmTest(p string, t *testing.T) {
helper.CreateFileTests(t, p, &tests) helper.CreateFileTests(t, p, &tests)
for name, test := range tests { for name, test := range tests {
/* helper.Logger.SetLogLevel(4)
helper.Logger.SetLogLevel(4) if name != "env1" {
if name != "log1_nonEmptyMem_logMemSize1_logMemStart31" { continue
continue }
}
*/
db, _ := ethdb.NewMemDatabase() db, _ := ethdb.NewMemDatabase()
statedb := state.New(nil, db) statedb := state.New(nil, db)
for addr, account := range test.Pre { for addr, account := range test.Pre {

View File

@ -43,7 +43,7 @@ var (
GasStorageMod = big.NewInt(5000) GasStorageMod = big.NewInt(5000)
GasLogBase = big.NewInt(2000) GasLogBase = big.NewInt(2000)
GasLogTopic = big.NewInt(2000) GasLogTopic = big.NewInt(2000)
GasLogData = big.NewInt(8) GasLogByte = big.NewInt(8)
GasCreate = big.NewInt(32000) GasCreate = big.NewInt(32000)
GasCreateByte = big.NewInt(300) GasCreateByte = big.NewInt(300)
GasCall = big.NewInt(40) GasCall = big.NewInt(40)
@ -57,11 +57,13 @@ var (
RefundSuicide = big.NewInt(24000) RefundSuicide = big.NewInt(24000)
GasMemWord = big.NewInt(3) GasMemWord = big.NewInt(3)
GasQuadCoeffWord = big.NewInt(1) GasQuadCoeffDenom = big.NewInt(512)
GasContractByte = big.NewInt(200) GasContractByte = big.NewInt(200)
GasTransaction = big.NewInt(21000) GasTransaction = big.NewInt(21000)
GasTxDataNonzeroByte = big.NewInt(37) GasTxDataNonzeroByte = big.NewInt(37)
GasTxZeroByte = big.NewInt(2) GasTxZeroByte = big.NewInt(2)
GasExp = big.NewInt(10)
GasExpByte = big.NewInt(10)
GasSha3Base = big.NewInt(30) GasSha3Base = big.NewInt(30)
GasSha3Word = big.NewInt(6) GasSha3Word = big.NewInt(6)

View File

@ -812,6 +812,7 @@ var _baseCheck = map[OpCode]req{
COINBASE: {0, GasQuickStep}, COINBASE: {0, GasQuickStep},
TIMESTAMP: {0, GasQuickStep}, TIMESTAMP: {0, GasQuickStep},
NUMBER: {0, GasQuickStep}, NUMBER: {0, GasQuickStep},
CALLDATASIZE: {0, GasQuickStep},
DIFFICULTY: {0, GasQuickStep}, DIFFICULTY: {0, GasQuickStep},
GASLIMIT: {0, GasQuickStep}, GASLIMIT: {0, GasQuickStep},
POP: {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: case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
n := int(op - SWAP1 + 2) n := int(op - SWAP1 + 2)
stack.require(n) stack.require(n)
gas.Set(GasFastestStep)
case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16: case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
n := int(op - DUP1 + 1) n := int(op - DUP1 + 1)
stack.require(n) stack.require(n)
gas.Set(GasFastestStep)
case LOG0, LOG1, LOG2, LOG3, LOG4: case LOG0, LOG1, LOG2, LOG3, LOG4:
n := int(op - LOG0) n := int(op - LOG0)
stack.require(n + 2) 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, GasLogBase)
gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(n)), GasLogTopic)) 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) newMemSize = calcMemSize(mStart, mSize)
case EXP: 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: case SSTORE:
stack.require(2) stack.require(2)
@ -935,7 +938,7 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
gas.Add(gas, GasCallNewAccount) 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) gas.Add(gas, GasCallValueTransfer)
} }
} }
@ -953,11 +956,24 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
newMemSize.Mul(newMemSize, u256(32)) newMemSize.Mul(newMemSize, u256(32))
if newMemSize.Cmp(u256(int64(mem.Len()))) > 0 { if newMemSize.Cmp(u256(int64(mem.Len()))) > 0 {
memGasUsage := new(big.Int).Sub(newMemSize, u256(int64(mem.Len()))) //memGasUsage := new(big.Int).Sub(newMemSize, u256(int64(mem.Len())))
memGasUsage.Mul(GasMemWord, memGasUsage) //memGasUsage.Mul(GasMemWord, memGasUsage)
memGasUsage.Div(memGasUsage, u256(32)) //memGasUsage.Div(memGasUsage, u256(32))
gas.Add(gas, memGasUsage) //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))
} }
} }