浏览代码

Minor improvements

* Moved gas and mem size to its own function
obscuren 11 年之前
父节点
当前提交
4547a05a68
共有 2 个文件被更改,包括 169 次插入162 次删除
  1. 6 0
      vm/stack.go
  2. 163 162
      vm/vm_debug.go

+ 6 - 0
vm/stack.go

@@ -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 {

+ 163 - 162
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)
-			}
-		}
-
-		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
-			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 (m) %-4d (s) %-4d ", pc, op.String(), mem.Len(), stack.Len())
 
-			}
-
-		}
+		newMemSize, gas := self.calculateGasAndSize(closure, caller, op, statedb, mem, stack)
 
-		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) {