Minor improvements
* Moved gas and mem size to its own function
This commit is contained in:
parent
4b4e082102
commit
4547a05a68
@ -91,6 +91,12 @@ func (st *Stack) Get(amount *big.Int) []*big.Int {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (st *Stack) require(n int) {
|
||||
if st.Len() < n {
|
||||
panic(fmt.Sprintf("stack underflow (%d <=> %d)", st.Len(), n))
|
||||
}
|
||||
}
|
||||
|
||||
func (st *Stack) Print() {
|
||||
fmt.Println("### stack ###")
|
||||
if len(st.data) > 0 {
|
||||
|
325
vm/vm_debug.go
325
vm/vm_debug.go
@ -49,15 +49,11 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price *
|
||||
})
|
||||
closure := NewClosure(msg, caller, me, code, gas, price)
|
||||
|
||||
if p := Precompiled[string(me.Address())]; p != nil {
|
||||
return self.RunPrecompiled(p, callData, closure)
|
||||
}
|
||||
|
||||
if self.Recoverable {
|
||||
// Recover from any require exception
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
self.Endl()
|
||||
self.Printf(" %v", r).Endl()
|
||||
|
||||
closure.UseGas(closure.Gas)
|
||||
|
||||
@ -69,6 +65,10 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price *
|
||||
}()
|
||||
}
|
||||
|
||||
if p := Precompiled[string(me.Address())]; p != nil {
|
||||
return self.RunPrecompiled(p, callData, closure)
|
||||
}
|
||||
|
||||
var (
|
||||
op OpCode
|
||||
|
||||
@ -79,11 +79,6 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price *
|
||||
step = 0
|
||||
prevStep = 0
|
||||
statedb = self.env.State()
|
||||
require = func(m int) {
|
||||
if stack.Len() < m {
|
||||
panic(fmt.Sprintf("%04v (%v) stack err size = %d, required = %d", pc, op, stack.Len(), m))
|
||||
}
|
||||
}
|
||||
|
||||
jump = func(from uint64, to *big.Int) {
|
||||
p := to.Uint64()
|
||||
@ -124,160 +119,11 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price *
|
||||
// Get the memory location of pc
|
||||
op = closure.GetOp(pc)
|
||||
|
||||
gas := new(big.Int)
|
||||
addStepGasUsage := func(amount *big.Int) {
|
||||
if amount.Cmp(ethutil.Big0) >= 0 {
|
||||
gas.Add(gas, amount)
|
||||
}
|
||||
}
|
||||
self.Printf("(pc) %-3d -o- %-14s (m) %-4d (s) %-4d ", pc, op.String(), mem.Len(), stack.Len())
|
||||
|
||||
addStepGasUsage(GasStep)
|
||||
newMemSize, gas := self.calculateGasAndSize(closure, caller, op, statedb, mem, stack)
|
||||
|
||||
var newMemSize *big.Int = ethutil.Big0
|
||||
var additionalGas *big.Int = new(big.Int)
|
||||
// Stack Check, memory resize & gas phase
|
||||
switch op {
|
||||
// Stack checks only
|
||||
case ISZERO, CALLDATALOAD, POP, JUMP, NOT: // 1
|
||||
require(1)
|
||||
case JUMPI, ADD, SUB, DIV, SDIV, MOD, SMOD, LT, GT, SLT, SGT, EQ, AND, OR, XOR, BYTE, SIGNEXTEND: // 2
|
||||
require(2)
|
||||
case ADDMOD, MULMOD: // 3
|
||||
require(3)
|
||||
case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
|
||||
n := int(op - SWAP1 + 2)
|
||||
require(n)
|
||||
case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
|
||||
n := int(op - DUP1 + 1)
|
||||
require(n)
|
||||
case LOG0, LOG1, LOG2, LOG3, LOG4:
|
||||
n := int(op - LOG0)
|
||||
require(n + 2)
|
||||
|
||||
gas.Set(GasLog)
|
||||
addStepGasUsage(new(big.Int).Mul(big.NewInt(int64(n)), GasLog))
|
||||
|
||||
mSize, mStart := stack.Peekn()
|
||||
addStepGasUsage(mSize)
|
||||
|
||||
newMemSize = calcMemSize(mStart, mSize)
|
||||
case EXP:
|
||||
require(2)
|
||||
|
||||
gas.Set(big.NewInt(int64(len(stack.data[stack.Len()-2].Bytes()) + 1)))
|
||||
// Gas only
|
||||
case STOP:
|
||||
gas.Set(ethutil.Big0)
|
||||
case SUICIDE:
|
||||
require(1)
|
||||
|
||||
gas.Set(ethutil.Big0)
|
||||
case SLOAD:
|
||||
require(1)
|
||||
|
||||
gas.Set(GasSLoad)
|
||||
// Memory resize & Gas
|
||||
case SSTORE:
|
||||
require(2)
|
||||
|
||||
var mult *big.Int
|
||||
y, x := stack.Peekn()
|
||||
val := statedb.GetState(closure.Address(), x.Bytes())
|
||||
if len(val) == 0 && len(y.Bytes()) > 0 {
|
||||
// 0 => non 0
|
||||
mult = ethutil.Big3
|
||||
} else if len(val) > 0 && len(y.Bytes()) == 0 {
|
||||
statedb.Refund(caller.Address(), GasSStoreRefund)
|
||||
|
||||
mult = ethutil.Big0
|
||||
} else {
|
||||
// non 0 => non 0 (or 0 => 0)
|
||||
mult = ethutil.Big1
|
||||
}
|
||||
gas.Set(new(big.Int).Mul(mult, GasSStore))
|
||||
case BALANCE:
|
||||
require(1)
|
||||
gas.Set(GasBalance)
|
||||
case MSTORE:
|
||||
require(2)
|
||||
newMemSize = calcMemSize(stack.Peek(), u256(32))
|
||||
case MLOAD:
|
||||
require(1)
|
||||
|
||||
newMemSize = calcMemSize(stack.Peek(), u256(32))
|
||||
case MSTORE8:
|
||||
require(2)
|
||||
newMemSize = calcMemSize(stack.Peek(), u256(1))
|
||||
case RETURN:
|
||||
require(2)
|
||||
|
||||
newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-2])
|
||||
case SHA3:
|
||||
require(2)
|
||||
gas.Set(GasSha)
|
||||
newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-2])
|
||||
additionalGas.Set(stack.data[stack.Len()-2])
|
||||
case CALLDATACOPY:
|
||||
require(2)
|
||||
|
||||
newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-3])
|
||||
additionalGas.Set(stack.data[stack.Len()-3])
|
||||
case CODECOPY:
|
||||
require(3)
|
||||
|
||||
newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-3])
|
||||
additionalGas.Set(stack.data[stack.Len()-3])
|
||||
case EXTCODECOPY:
|
||||
require(4)
|
||||
|
||||
newMemSize = calcMemSize(stack.data[stack.Len()-2], stack.data[stack.Len()-4])
|
||||
additionalGas.Set(stack.data[stack.Len()-4])
|
||||
case CALL, CALLCODE:
|
||||
require(7)
|
||||
gas.Set(GasCall)
|
||||
addStepGasUsage(stack.data[stack.Len()-1])
|
||||
|
||||
x := calcMemSize(stack.data[stack.Len()-6], stack.data[stack.Len()-7])
|
||||
y := calcMemSize(stack.data[stack.Len()-4], stack.data[stack.Len()-5])
|
||||
|
||||
newMemSize = ethutil.BigMax(x, y)
|
||||
case CREATE:
|
||||
require(3)
|
||||
gas.Set(GasCreate)
|
||||
|
||||
newMemSize = calcMemSize(stack.data[stack.Len()-2], stack.data[stack.Len()-3])
|
||||
}
|
||||
|
||||
switch op {
|
||||
case CALLDATACOPY, CODECOPY, EXTCODECOPY:
|
||||
additionalGas.Add(additionalGas, u256(31))
|
||||
additionalGas.Div(additionalGas, u256(32))
|
||||
addStepGasUsage(additionalGas)
|
||||
case SHA3:
|
||||
additionalGas.Add(additionalGas, u256(31))
|
||||
additionalGas.Div(additionalGas, u256(32))
|
||||
additionalGas.Mul(additionalGas, GasSha3Byte)
|
||||
addStepGasUsage(additionalGas)
|
||||
}
|
||||
|
||||
if newMemSize.Cmp(ethutil.Big0) > 0 {
|
||||
newMemSize.Add(newMemSize, u256(31))
|
||||
newMemSize.Div(newMemSize, u256(32))
|
||||
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(GasMemory, memGasUsage)
|
||||
memGasUsage.Div(memGasUsage, u256(32))
|
||||
|
||||
addStepGasUsage(memGasUsage)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
self.Printf("(pc) %-3d -o- %-14s", pc, op.String())
|
||||
self.Printf(" (m) %-4d (s) %-4d (g) %-3v (%v)", mem.Len(), stack.Len(), gas, closure.Gas)
|
||||
self.Printf("(g) %-3v (%v)", gas, closure.Gas)
|
||||
|
||||
if !closure.UseGas(gas) {
|
||||
self.Endl()
|
||||
@ -939,6 +785,161 @@ func (self *DebugVm) Run(me, caller ClosureRef, code []byte, value, gas, price *
|
||||
}
|
||||
}
|
||||
|
||||
func (self *DebugVm) calculateGasAndSize(closure *Closure, caller ClosureRef, op OpCode, statedb *state.StateDB, mem *Memory, stack *Stack) (*big.Int, *big.Int) {
|
||||
gas := new(big.Int)
|
||||
addStepGasUsage := func(amount *big.Int) {
|
||||
if amount.Cmp(ethutil.Big0) >= 0 {
|
||||
gas.Add(gas, amount)
|
||||
}
|
||||
}
|
||||
|
||||
addStepGasUsage(GasStep)
|
||||
|
||||
var newMemSize *big.Int = ethutil.Big0
|
||||
var additionalGas *big.Int = new(big.Int)
|
||||
// Stack Check, memory resize & gas phase
|
||||
switch op {
|
||||
// Stack checks only
|
||||
case ISZERO, CALLDATALOAD, POP, JUMP, NOT: // 1
|
||||
stack.require(1)
|
||||
case JUMPI, ADD, SUB, DIV, SDIV, MOD, SMOD, LT, GT, SLT, SGT, EQ, AND, OR, XOR, BYTE, SIGNEXTEND: // 2
|
||||
stack.require(2)
|
||||
case ADDMOD, MULMOD: // 3
|
||||
stack.require(3)
|
||||
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)
|
||||
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)
|
||||
case LOG0, LOG1, LOG2, LOG3, LOG4:
|
||||
n := int(op - LOG0)
|
||||
stack.require(n + 2)
|
||||
|
||||
gas.Set(GasLog)
|
||||
addStepGasUsage(new(big.Int).Mul(big.NewInt(int64(n)), GasLog))
|
||||
|
||||
mSize, mStart := stack.Peekn()
|
||||
addStepGasUsage(mSize)
|
||||
|
||||
newMemSize = calcMemSize(mStart, mSize)
|
||||
case EXP:
|
||||
stack.require(2)
|
||||
|
||||
gas.Set(big.NewInt(int64(len(stack.data[stack.Len()-2].Bytes()) + 1)))
|
||||
// Gas only
|
||||
case STOP:
|
||||
gas.Set(ethutil.Big0)
|
||||
case SUICIDE:
|
||||
stack.require(1)
|
||||
|
||||
gas.Set(ethutil.Big0)
|
||||
case SLOAD:
|
||||
stack.require(1)
|
||||
|
||||
gas.Set(GasSLoad)
|
||||
// Memory resize & Gas
|
||||
case SSTORE:
|
||||
stack.require(2)
|
||||
|
||||
var mult *big.Int
|
||||
y, x := stack.Peekn()
|
||||
val := statedb.GetState(closure.Address(), x.Bytes())
|
||||
if len(val) == 0 && len(y.Bytes()) > 0 {
|
||||
// 0 => non 0
|
||||
mult = ethutil.Big3
|
||||
} else if len(val) > 0 && len(y.Bytes()) == 0 {
|
||||
statedb.Refund(caller.Address(), GasSStoreRefund)
|
||||
|
||||
mult = ethutil.Big0
|
||||
} else {
|
||||
// non 0 => non 0 (or 0 => 0)
|
||||
mult = ethutil.Big1
|
||||
}
|
||||
gas.Set(new(big.Int).Mul(mult, GasSStore))
|
||||
case BALANCE:
|
||||
stack.require(1)
|
||||
gas.Set(GasBalance)
|
||||
case MSTORE:
|
||||
stack.require(2)
|
||||
newMemSize = calcMemSize(stack.Peek(), u256(32))
|
||||
case MLOAD:
|
||||
stack.require(1)
|
||||
|
||||
newMemSize = calcMemSize(stack.Peek(), u256(32))
|
||||
case MSTORE8:
|
||||
stack.require(2)
|
||||
newMemSize = calcMemSize(stack.Peek(), u256(1))
|
||||
case RETURN:
|
||||
stack.require(2)
|
||||
|
||||
newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-2])
|
||||
case SHA3:
|
||||
stack.require(2)
|
||||
gas.Set(GasSha)
|
||||
newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-2])
|
||||
additionalGas.Set(stack.data[stack.Len()-2])
|
||||
case CALLDATACOPY:
|
||||
stack.require(2)
|
||||
|
||||
newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-3])
|
||||
additionalGas.Set(stack.data[stack.Len()-3])
|
||||
case CODECOPY:
|
||||
stack.require(3)
|
||||
|
||||
newMemSize = calcMemSize(stack.Peek(), stack.data[stack.Len()-3])
|
||||
additionalGas.Set(stack.data[stack.Len()-3])
|
||||
case EXTCODECOPY:
|
||||
stack.require(4)
|
||||
|
||||
newMemSize = calcMemSize(stack.data[stack.Len()-2], stack.data[stack.Len()-4])
|
||||
additionalGas.Set(stack.data[stack.Len()-4])
|
||||
case CALL, CALLCODE:
|
||||
stack.require(7)
|
||||
gas.Set(GasCall)
|
||||
addStepGasUsage(stack.data[stack.Len()-1])
|
||||
|
||||
x := calcMemSize(stack.data[stack.Len()-6], stack.data[stack.Len()-7])
|
||||
y := calcMemSize(stack.data[stack.Len()-4], stack.data[stack.Len()-5])
|
||||
|
||||
newMemSize = ethutil.BigMax(x, y)
|
||||
case CREATE:
|
||||
stack.require(3)
|
||||
gas.Set(GasCreate)
|
||||
|
||||
newMemSize = calcMemSize(stack.data[stack.Len()-2], stack.data[stack.Len()-3])
|
||||
}
|
||||
|
||||
switch op {
|
||||
case CALLDATACOPY, CODECOPY, EXTCODECOPY:
|
||||
additionalGas.Add(additionalGas, u256(31))
|
||||
additionalGas.Div(additionalGas, u256(32))
|
||||
addStepGasUsage(additionalGas)
|
||||
case SHA3:
|
||||
additionalGas.Add(additionalGas, u256(31))
|
||||
additionalGas.Div(additionalGas, u256(32))
|
||||
additionalGas.Mul(additionalGas, GasSha3Byte)
|
||||
addStepGasUsage(additionalGas)
|
||||
}
|
||||
|
||||
if newMemSize.Cmp(ethutil.Big0) > 0 {
|
||||
newMemSize.Add(newMemSize, u256(31))
|
||||
newMemSize.Div(newMemSize, u256(32))
|
||||
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(GasMemory, memGasUsage)
|
||||
memGasUsage.Div(memGasUsage, u256(32))
|
||||
|
||||
addStepGasUsage(memGasUsage)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return newMemSize, gas
|
||||
}
|
||||
|
||||
func (self *DebugVm) RunPrecompiled(p *PrecompiledAccount, callData []byte, closure *Closure) (ret []byte, err error) {
|
||||
gas := p.Gas(len(callData))
|
||||
if closure.UseGas(gas) {
|
||||
|
Loading…
Reference in New Issue
Block a user