Pārlūkot izejas kodu

Cleanup VM.

* CALLDATA use getData
* removed old context get range value
* removed casting big => int for some cases
* pc now big int #457
obscuren 10 gadi atpakaļ
vecāks
revīzija
368ebe63a9
4 mainītis faili ar 45 papildinājumiem un 56 dzēšanām
  1. 20 4
      core/vm/analysis.go
  2. 1 0
      core/vm/common.go
  3. 4 16
      core/vm/context.go
  4. 20 36
      core/vm/vm.go

+ 20 - 4
core/vm/analysis.go

@@ -1,9 +1,25 @@
 package vm
 
-import "gopkg.in/fatih/set.v0"
+import (
+	"math/big"
 
-func analyseJumpDests(code []byte) (dests *set.Set) {
-	dests = set.New()
+	"gopkg.in/fatih/set.v0"
+)
+
+type destinations struct {
+	set *set.Set
+}
+
+func (d *destinations) Has(dest *big.Int) bool {
+	return d.set.Has(string(dest.Bytes()))
+}
+
+func (d *destinations) Add(dest *big.Int) {
+	d.set.Add(string(dest.Bytes()))
+}
+
+func analyseJumpDests(code []byte) (dests *destinations) {
+	dests = &destinations{set.New()}
 
 	for pc := uint64(0); pc < uint64(len(code)); pc++ {
 		var op OpCode = OpCode(code[pc])
@@ -13,7 +29,7 @@ func analyseJumpDests(code []byte) (dests *set.Set) {
 
 			pc += a
 		case JUMPDEST:
-			dests.Add(pc)
+			dests.Add(big.NewInt(int64(pc)))
 		}
 	}
 	return

+ 1 - 0
core/vm/common.go

@@ -33,6 +33,7 @@ var (
 	S256 = common.S256
 
 	Zero = common.Big0
+	One  = common.Big1
 
 	max = big.NewInt(math.MaxInt64)
 )

+ 4 - 16
core/vm/context.go

@@ -1,7 +1,6 @@
 package vm
 
 import (
-	"math"
 	"math/big"
 
 	"github.com/ethereum/go-ethereum/common"
@@ -41,29 +40,18 @@ func NewContext(caller ContextRef, object ContextRef, value, gas, price *big.Int
 	return c
 }
 
-func (c *Context) GetOp(n uint64) OpCode {
+func (c *Context) GetOp(n *big.Int) OpCode {
 	return OpCode(c.GetByte(n))
 }
 
-func (c *Context) GetByte(n uint64) byte {
-	if n < uint64(len(c.Code)) {
-		return c.Code[n]
+func (c *Context) GetByte(n *big.Int) byte {
+	if n.Cmp(big.NewInt(int64(len(c.Code)))) < 0 {
+		return c.Code[n.Int64()]
 	}
 
 	return 0
 }
 
-func (c *Context) GetBytes(x, y int) []byte {
-	return c.GetRangeValue(uint64(x), uint64(y))
-}
-
-func (c *Context) GetRangeValue(x, size uint64) []byte {
-	x = uint64(math.Min(float64(x), float64(len(c.Code))))
-	y := uint64(math.Min(float64(x+size), float64(len(c.Code))))
-
-	return common.RightPadBytes(c.Code[x:y], int(size))
-}
-
 func (c *Context) Return(ret []byte) []byte {
 	// Return the remaining gas to the caller
 	c.caller.ReturnGas(c.Gas, c.Price)

+ 20 - 36
core/vm/vm.go

@@ -72,23 +72,20 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
 	var (
 		op OpCode
 
-		destinations        = analyseJumpDests(context.Code)
-		mem                 = NewMemory()
-		stack               = newStack()
-		pc           uint64 = 0
-		step                = 0
-		statedb             = self.env.State()
-
-		jump = func(from uint64, to *big.Int) error {
-			p := to.Uint64()
-
-			nop := context.GetOp(p)
-			if !destinations.Has(p) {
-				return fmt.Errorf("invalid jump destination (%v) %v", nop, p)
+		destinations = analyseJumpDests(context.Code)
+		mem          = NewMemory()
+		stack        = newStack()
+		pc           = new(big.Int)
+		statedb      = self.env.State()
+
+		jump = func(from *big.Int, to *big.Int) error {
+			nop := context.GetOp(to)
+			if !destinations.Has(to) {
+				return fmt.Errorf("invalid jump destination (%v) %v", nop, to)
 			}
 
 			self.Printf(" ~> %v", to)
-			pc = to.Uint64()
+			pc = to
 
 			self.Endl()
 
@@ -105,7 +102,6 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
 		// The base for all big integer arithmetic
 		base := new(big.Int)
 
-		step++
 		// Get the memory location of pc
 		op = context.GetOp(pc)
 
@@ -428,22 +424,11 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
 
 			self.Printf(" => %v", value)
 		case CALLDATALOAD:
-			var (
-				offset  = stack.pop()
-				data    = make([]byte, 32)
-				lenData = big.NewInt(int64(len(callData)))
-			)
-
-			if lenData.Cmp(offset) >= 0 {
-				length := new(big.Int).Add(offset, common.Big32)
-				length = common.BigMin(length, lenData)
-
-				copy(data, callData[offset.Int64():length.Int64()])
-			}
+			data := getData(callData, stack.pop(), common.Big32)
 
 			self.Printf(" => 0x%x", data)
 
-			stack.push(common.BigD(data))
+			stack.push(common.Bytes2Big(data))
 		case CALLDATASIZE:
 			l := int64(len(callData))
 			stack.push(big.NewInt(l))
@@ -542,13 +527,11 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
 
 			// 0x50 range
 		case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32:
-			a := uint64(op - PUSH1 + 1)
-			byts := context.GetRangeValue(pc+1, a)
+			a := big.NewInt(int64(op - PUSH1 + 1))
+			byts := getData(code, new(big.Int).Add(pc, big.NewInt(1)), a)
 			// push value to stack
-			stack.push(common.BigD(byts))
-			pc += a
-
-			step += int(op) - int(PUSH1) + 1
+			stack.push(common.Bytes2Big(byts))
+			pc.Add(pc, a)
 
 			self.Printf(" => 0x%x", byts)
 		case POP:
@@ -628,7 +611,8 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
 
 		case JUMPDEST:
 		case PC:
-			stack.push(big.NewInt(int64(pc)))
+			//stack.push(big.NewInt(int64(pc)))
+			stack.push(pc)
 		case MSIZE:
 			stack.push(big.NewInt(int64(mem.Len())))
 		case GAS:
@@ -734,7 +718,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
 			return nil, fmt.Errorf("Invalid opcode %x", op)
 		}
 
-		pc++
+		pc.Add(pc, One)
 
 		self.Endl()
 	}