github.com/jeffallen/go-ethereum@v1.1.4-0.20150910155051-571d3236c49c/core/vm/instructions.go (about)

     1  // Copyright 2014 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package vm
    18  
    19  import (
    20  	"math/big"
    21  
    22  	"github.com/ethereum/go-ethereum/common"
    23  	"github.com/ethereum/go-ethereum/core/state"
    24  	"github.com/ethereum/go-ethereum/crypto"
    25  	"github.com/ethereum/go-ethereum/params"
    26  )
    27  
    28  type instrFn func(instr instruction, env Environment, context *Context, memory *Memory, stack *stack)
    29  type instrExFn func(instr instruction, ret *big.Int, env Environment, context *Context, memory *Memory, stack *stack)
    30  
    31  type instruction struct {
    32  	op     OpCode
    33  	pc     uint64
    34  	fn     instrFn
    35  	specFn instrExFn
    36  	data   *big.Int
    37  
    38  	gas   *big.Int
    39  	spop  int
    40  	spush int
    41  }
    42  
    43  func opStaticJump(instr instruction, ret *big.Int, env Environment, context *Context, memory *Memory, stack *stack) {
    44  	ret.Set(instr.data)
    45  }
    46  
    47  func opAdd(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
    48  	x, y := stack.pop(), stack.pop()
    49  	stack.push(U256(x.Add(x, y)))
    50  }
    51  
    52  func opSub(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
    53  	x, y := stack.pop(), stack.pop()
    54  	stack.push(U256(x.Sub(x, y)))
    55  }
    56  
    57  func opMul(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
    58  	x, y := stack.pop(), stack.pop()
    59  	stack.push(U256(x.Mul(x, y)))
    60  }
    61  
    62  func opDiv(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
    63  	x, y := stack.pop(), stack.pop()
    64  	if y.Cmp(common.Big0) != 0 {
    65  		stack.push(U256(x.Div(x, y)))
    66  	} else {
    67  		stack.push(new(big.Int))
    68  	}
    69  }
    70  
    71  func opSdiv(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
    72  	x, y := S256(stack.pop()), S256(stack.pop())
    73  	if y.Cmp(common.Big0) == 0 {
    74  		stack.push(new(big.Int))
    75  		return
    76  	} else {
    77  		n := new(big.Int)
    78  		if new(big.Int).Mul(x, y).Cmp(common.Big0) < 0 {
    79  			n.SetInt64(-1)
    80  		} else {
    81  			n.SetInt64(1)
    82  		}
    83  
    84  		res := x.Div(x.Abs(x), y.Abs(y))
    85  		res.Mul(res, n)
    86  
    87  		stack.push(U256(res))
    88  	}
    89  }
    90  
    91  func opMod(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
    92  	x, y := stack.pop(), stack.pop()
    93  	if y.Cmp(common.Big0) == 0 {
    94  		stack.push(new(big.Int))
    95  	} else {
    96  		stack.push(U256(x.Mod(x, y)))
    97  	}
    98  }
    99  
   100  func opSmod(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   101  	x, y := S256(stack.pop()), S256(stack.pop())
   102  
   103  	if y.Cmp(common.Big0) == 0 {
   104  		stack.push(new(big.Int))
   105  	} else {
   106  		n := new(big.Int)
   107  		if x.Cmp(common.Big0) < 0 {
   108  			n.SetInt64(-1)
   109  		} else {
   110  			n.SetInt64(1)
   111  		}
   112  
   113  		res := x.Mod(x.Abs(x), y.Abs(y))
   114  		res.Mul(res, n)
   115  
   116  		stack.push(U256(res))
   117  	}
   118  }
   119  
   120  func opExp(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   121  	x, y := stack.pop(), stack.pop()
   122  	stack.push(U256(x.Exp(x, y, Pow256)))
   123  }
   124  
   125  func opSignExtend(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   126  	back := stack.pop()
   127  	if back.Cmp(big.NewInt(31)) < 0 {
   128  		bit := uint(back.Uint64()*8 + 7)
   129  		num := stack.pop()
   130  		mask := back.Lsh(common.Big1, bit)
   131  		mask.Sub(mask, common.Big1)
   132  		if common.BitTest(num, int(bit)) {
   133  			num.Or(num, mask.Not(mask))
   134  		} else {
   135  			num.And(num, mask)
   136  		}
   137  
   138  		stack.push(U256(num))
   139  	}
   140  }
   141  
   142  func opNot(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   143  	x := stack.pop()
   144  	stack.push(U256(x.Not(x)))
   145  }
   146  
   147  func opLt(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   148  	x, y := stack.pop(), stack.pop()
   149  	if x.Cmp(y) < 0 {
   150  		stack.push(big.NewInt(1))
   151  	} else {
   152  		stack.push(new(big.Int))
   153  	}
   154  }
   155  
   156  func opGt(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   157  	x, y := stack.pop(), stack.pop()
   158  	if x.Cmp(y) > 0 {
   159  		stack.push(big.NewInt(1))
   160  	} else {
   161  		stack.push(new(big.Int))
   162  	}
   163  }
   164  
   165  func opSlt(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   166  	x, y := S256(stack.pop()), S256(stack.pop())
   167  	if x.Cmp(S256(y)) < 0 {
   168  		stack.push(big.NewInt(1))
   169  	} else {
   170  		stack.push(new(big.Int))
   171  	}
   172  }
   173  
   174  func opSgt(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   175  	x, y := S256(stack.pop()), S256(stack.pop())
   176  	if x.Cmp(y) > 0 {
   177  		stack.push(big.NewInt(1))
   178  	} else {
   179  		stack.push(new(big.Int))
   180  	}
   181  }
   182  
   183  func opEq(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   184  	x, y := stack.pop(), stack.pop()
   185  	if x.Cmp(y) == 0 {
   186  		stack.push(big.NewInt(1))
   187  	} else {
   188  		stack.push(new(big.Int))
   189  	}
   190  }
   191  
   192  func opIszero(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   193  	x := stack.pop()
   194  	if x.Cmp(common.Big0) > 0 {
   195  		stack.push(new(big.Int))
   196  	} else {
   197  		stack.push(big.NewInt(1))
   198  	}
   199  }
   200  
   201  func opAnd(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   202  	x, y := stack.pop(), stack.pop()
   203  	stack.push(x.And(x, y))
   204  }
   205  func opOr(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   206  	x, y := stack.pop(), stack.pop()
   207  	stack.push(x.Or(x, y))
   208  }
   209  func opXor(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   210  	x, y := stack.pop(), stack.pop()
   211  	stack.push(x.Xor(x, y))
   212  }
   213  func opByte(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   214  	th, val := stack.pop(), stack.pop()
   215  	if th.Cmp(big.NewInt(32)) < 0 {
   216  		byte := big.NewInt(int64(common.LeftPadBytes(val.Bytes(), 32)[th.Int64()]))
   217  		stack.push(byte)
   218  	} else {
   219  		stack.push(new(big.Int))
   220  	}
   221  }
   222  func opAddmod(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   223  	x, y, z := stack.pop(), stack.pop(), stack.pop()
   224  	if z.Cmp(Zero) > 0 {
   225  		add := x.Add(x, y)
   226  		add.Mod(add, z)
   227  		stack.push(U256(add))
   228  	} else {
   229  		stack.push(new(big.Int))
   230  	}
   231  }
   232  func opMulmod(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   233  	x, y, z := stack.pop(), stack.pop(), stack.pop()
   234  	if z.Cmp(Zero) > 0 {
   235  		mul := x.Mul(x, y)
   236  		mul.Mod(mul, z)
   237  		stack.push(U256(mul))
   238  	} else {
   239  		stack.push(new(big.Int))
   240  	}
   241  }
   242  
   243  func opSha3(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   244  	offset, size := stack.pop(), stack.pop()
   245  	hash := crypto.Sha3(memory.Get(offset.Int64(), size.Int64()))
   246  
   247  	stack.push(common.BytesToBig(hash))
   248  }
   249  
   250  func opAddress(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   251  	stack.push(common.Bytes2Big(context.Address().Bytes()))
   252  }
   253  
   254  func opBalance(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   255  	addr := common.BigToAddress(stack.pop())
   256  	balance := env.State().GetBalance(addr)
   257  
   258  	stack.push(new(big.Int).Set(balance))
   259  }
   260  
   261  func opOrigin(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   262  	stack.push(env.Origin().Big())
   263  }
   264  
   265  func opCaller(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   266  	stack.push(common.Bytes2Big(context.caller.Address().Bytes()))
   267  }
   268  
   269  func opCallValue(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   270  	stack.push(new(big.Int).Set(context.value))
   271  }
   272  
   273  func opCalldataLoad(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   274  	stack.push(common.Bytes2Big(getData(context.Input, stack.pop(), common.Big32)))
   275  }
   276  
   277  func opCalldataSize(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   278  	stack.push(big.NewInt(int64(len(context.Input))))
   279  }
   280  
   281  func opCalldataCopy(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   282  	var (
   283  		mOff = stack.pop()
   284  		cOff = stack.pop()
   285  		l    = stack.pop()
   286  	)
   287  	memory.Set(mOff.Uint64(), l.Uint64(), getData(context.Input, cOff, l))
   288  }
   289  
   290  func opExtCodeSize(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   291  	addr := common.BigToAddress(stack.pop())
   292  	l := big.NewInt(int64(len(env.State().GetCode(addr))))
   293  	stack.push(l)
   294  }
   295  
   296  func opCodeSize(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   297  	l := big.NewInt(int64(len(context.Code)))
   298  	stack.push(l)
   299  }
   300  
   301  func opCodeCopy(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   302  	var (
   303  		mOff = stack.pop()
   304  		cOff = stack.pop()
   305  		l    = stack.pop()
   306  	)
   307  	codeCopy := getData(context.Code, cOff, l)
   308  
   309  	memory.Set(mOff.Uint64(), l.Uint64(), codeCopy)
   310  }
   311  
   312  func opExtCodeCopy(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   313  	var (
   314  		addr = common.BigToAddress(stack.pop())
   315  		mOff = stack.pop()
   316  		cOff = stack.pop()
   317  		l    = stack.pop()
   318  	)
   319  	codeCopy := getData(env.State().GetCode(addr), cOff, l)
   320  
   321  	memory.Set(mOff.Uint64(), l.Uint64(), codeCopy)
   322  }
   323  
   324  func opGasprice(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   325  	stack.push(new(big.Int).Set(context.Price))
   326  }
   327  
   328  func opBlockhash(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   329  	num := stack.pop()
   330  
   331  	n := new(big.Int).Sub(env.BlockNumber(), common.Big257)
   332  	if num.Cmp(n) > 0 && num.Cmp(env.BlockNumber()) < 0 {
   333  		stack.push(env.GetHash(num.Uint64()).Big())
   334  	} else {
   335  		stack.push(new(big.Int))
   336  	}
   337  }
   338  
   339  func opCoinbase(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   340  	stack.push(env.Coinbase().Big())
   341  }
   342  
   343  func opTimestamp(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   344  	stack.push(U256(new(big.Int).Set(env.Time())))
   345  }
   346  
   347  func opNumber(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   348  	stack.push(U256(new(big.Int).Set(env.BlockNumber())))
   349  }
   350  
   351  func opDifficulty(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   352  	stack.push(U256(new(big.Int).Set(env.Difficulty())))
   353  }
   354  
   355  func opGasLimit(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   356  	stack.push(U256(new(big.Int).Set(env.GasLimit())))
   357  }
   358  
   359  func opPop(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   360  	stack.pop()
   361  }
   362  
   363  func opPush(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   364  	stack.push(new(big.Int).Set(instr.data))
   365  }
   366  
   367  func opDup(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   368  	stack.dup(int(instr.data.Int64()))
   369  }
   370  
   371  func opSwap(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   372  	stack.swap(int(instr.data.Int64()))
   373  }
   374  
   375  func opLog(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   376  	n := int(instr.data.Int64())
   377  	topics := make([]common.Hash, n)
   378  	mStart, mSize := stack.pop(), stack.pop()
   379  	for i := 0; i < n; i++ {
   380  		topics[i] = common.BigToHash(stack.pop())
   381  	}
   382  
   383  	d := memory.Get(mStart.Int64(), mSize.Int64())
   384  	log := state.NewLog(context.Address(), topics, d, env.BlockNumber().Uint64())
   385  	env.AddLog(log)
   386  }
   387  
   388  func opMload(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   389  	offset := stack.pop()
   390  	val := common.BigD(memory.Get(offset.Int64(), 32))
   391  	stack.push(val)
   392  }
   393  
   394  func opMstore(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   395  	// pop value of the stack
   396  	mStart, val := stack.pop(), stack.pop()
   397  	memory.Set(mStart.Uint64(), 32, common.BigToBytes(val, 256))
   398  }
   399  
   400  func opMstore8(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   401  	off, val := stack.pop().Int64(), stack.pop().Int64()
   402  	memory.store[off] = byte(val & 0xff)
   403  }
   404  
   405  func opSload(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   406  	loc := common.BigToHash(stack.pop())
   407  	val := env.State().GetState(context.Address(), loc).Big()
   408  	stack.push(val)
   409  }
   410  
   411  func opSstore(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   412  	loc := common.BigToHash(stack.pop())
   413  	val := stack.pop()
   414  
   415  	env.State().SetState(context.Address(), loc, common.BigToHash(val))
   416  }
   417  
   418  func opJump(instr instruction, env Environment, context *Context, memory *Memory, stack *stack)     {}
   419  func opJumpi(instr instruction, env Environment, context *Context, memory *Memory, stack *stack)    {}
   420  func opJumpdest(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {}
   421  
   422  func opPc(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   423  	stack.push(new(big.Int).Set(instr.data))
   424  }
   425  
   426  func opMsize(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   427  	stack.push(big.NewInt(int64(memory.Len())))
   428  }
   429  
   430  func opGas(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   431  	stack.push(new(big.Int).Set(context.Gas))
   432  }
   433  
   434  func opCreate(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   435  	var (
   436  		value        = stack.pop()
   437  		offset, size = stack.pop(), stack.pop()
   438  		input        = memory.Get(offset.Int64(), size.Int64())
   439  		gas          = new(big.Int).Set(context.Gas)
   440  		addr         common.Address
   441  	)
   442  
   443  	context.UseGas(context.Gas)
   444  	ret, suberr, ref := env.Create(context, input, gas, context.Price, value)
   445  	if suberr != nil {
   446  		stack.push(new(big.Int))
   447  
   448  	} else {
   449  		// gas < len(ret) * Createinstr.dataGas == NO_CODE
   450  		dataGas := big.NewInt(int64(len(ret)))
   451  		dataGas.Mul(dataGas, params.CreateDataGas)
   452  		if context.UseGas(dataGas) {
   453  			ref.SetCode(ret)
   454  		}
   455  		addr = ref.Address()
   456  
   457  		stack.push(addr.Big())
   458  
   459  	}
   460  }
   461  
   462  func opCall(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   463  	gas := stack.pop()
   464  	// pop gas and value of the stack.
   465  	addr, value := stack.pop(), stack.pop()
   466  	value = U256(value)
   467  	// pop input size and offset
   468  	inOffset, inSize := stack.pop(), stack.pop()
   469  	// pop return size and offset
   470  	retOffset, retSize := stack.pop(), stack.pop()
   471  
   472  	address := common.BigToAddress(addr)
   473  
   474  	// Get the arguments from the memory
   475  	args := memory.Get(inOffset.Int64(), inSize.Int64())
   476  
   477  	if len(value.Bytes()) > 0 {
   478  		gas.Add(gas, params.CallStipend)
   479  	}
   480  
   481  	ret, err := env.Call(context, address, args, gas, context.Price, value)
   482  
   483  	if err != nil {
   484  		stack.push(new(big.Int))
   485  
   486  	} else {
   487  		stack.push(big.NewInt(1))
   488  
   489  		memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
   490  	}
   491  }
   492  
   493  func opCallCode(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   494  	gas := stack.pop()
   495  	// pop gas and value of the stack.
   496  	addr, value := stack.pop(), stack.pop()
   497  	value = U256(value)
   498  	// pop input size and offset
   499  	inOffset, inSize := stack.pop(), stack.pop()
   500  	// pop return size and offset
   501  	retOffset, retSize := stack.pop(), stack.pop()
   502  
   503  	address := common.BigToAddress(addr)
   504  
   505  	// Get the arguments from the memory
   506  	args := memory.Get(inOffset.Int64(), inSize.Int64())
   507  
   508  	if len(value.Bytes()) > 0 {
   509  		gas.Add(gas, params.CallStipend)
   510  	}
   511  
   512  	ret, err := env.CallCode(context, address, args, gas, context.Price, value)
   513  
   514  	if err != nil {
   515  		stack.push(new(big.Int))
   516  
   517  	} else {
   518  		stack.push(big.NewInt(1))
   519  
   520  		memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
   521  	}
   522  }
   523  
   524  func opReturn(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {}
   525  func opStop(instr instruction, env Environment, context *Context, memory *Memory, stack *stack)   {}
   526  
   527  func opSuicide(instr instruction, env Environment, context *Context, memory *Memory, stack *stack) {
   528  	receiver := env.State().GetOrNewStateObject(common.BigToAddress(stack.pop()))
   529  	balance := env.State().GetBalance(context.Address())
   530  
   531  	receiver.AddBalance(balance)
   532  
   533  	env.State().Delete(context.Address())
   534  }