vm.go 20.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// Copyright 2014 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with go-ethereum.  If not, see <http://www.gnu.org/licenses/>.

17
// Package vm implements the Ethereum Virtual Machine.
obscuren's avatar
obscuren committed
18
package vm
19

obscuren's avatar
obscuren committed
20 21 22
import (
	"fmt"
	"math/big"
23

obscuren's avatar
obscuren committed
24
	"github.com/ethereum/go-ethereum/common"
obscuren's avatar
obscuren committed
25
	"github.com/ethereum/go-ethereum/core/state"
obscuren's avatar
obscuren committed
26
	"github.com/ethereum/go-ethereum/crypto"
27
	"github.com/ethereum/go-ethereum/params"
obscuren's avatar
obscuren committed
28
)
obscuren's avatar
obscuren committed
29

30
// Vm implements VirtualMachine
31
type Vm struct {
obscuren's avatar
obscuren committed
32 33 34
	env Environment

	err error
35 36
	// For logging
	debug bool
obscuren's avatar
obscuren committed
37 38 39 40 41 42

	BreakPoints []int64
	Stepping    bool
	Fn          string

	Recoverable bool
obscuren's avatar
obscuren committed
43 44 45

	// Will be called before the vm returns
	After func(*Context, error)
obscuren's avatar
obscuren committed
46 47
}

48
// New returns a new Virtual Machine
obscuren's avatar
obscuren committed
49
func New(env Environment) *Vm {
50
	return &Vm{env: env, debug: Debug, Recoverable: true}
obscuren's avatar
obscuren committed
51 52
}

53 54
// Run loops and evaluates the contract's code with the given input data
func (self *Vm) Run(context *Context, input []byte) (ret []byte, err error) {
obscuren's avatar
obscuren committed
55
	self.env.SetDepth(self.env.Depth() + 1)
obscuren's avatar
obscuren committed
56 57
	defer self.env.SetDepth(self.env.Depth() - 1)

58 59 60 61 62
	var (
		caller = context.caller
		code   = context.Code
		value  = context.value
		price  = context.Price
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87

		op       OpCode                  // current opcode
		codehash = crypto.Sha3Hash(code) // codehash is used when doing jump dest caching
		mem      = NewMemory()           // bound memory
		stack    = newstack()            // local stack
		statedb  = self.env.State()      // current state
		// For optimisation reason we're using uint64 as the program counter.
		// It's theoretically possible to go above 2^64. The YP defines the PC to be uint256. Pratically much less so feasible.
		pc = uint64(0) // program counter

		// jump evaluates and checks whether the given jump destination is a valid one
		// if valid move the `pc` otherwise return an error.
		jump = func(from uint64, to *big.Int) error {
			if !context.jumpdests.has(codehash, code, to) {
				nop := context.GetOp(to.Uint64())
				return fmt.Errorf("invalid jump destination (%v) %v", nop, to)
			}

			pc = to.Uint64()

			return nil
		}

		newMemSize *big.Int
		cost       *big.Int
88
	)
obscuren's avatar
obscuren committed
89

obscuren's avatar
obscuren committed
90
	// User defer pattern to check for an error and, based on the error being nil or not, use all gas and return.
obscuren's avatar
obscuren committed
91
	defer func() {
obscuren's avatar
obscuren committed
92 93 94 95
		if self.After != nil {
			self.After(context, err)
		}

obscuren's avatar
obscuren committed
96
		if err != nil {
97
			self.log(pc, op, context.Gas, cost, mem, stack, context, err)
98

obscuren's avatar
obscuren committed
99 100 101 102 103 104
			// In case of a VM exception (known exceptions) all gas consumed (panics NOT included).
			context.UseGas(context.Gas)

			ret = context.Return(nil)
		}
	}()
obscuren's avatar
obscuren committed
105

obscuren's avatar
obscuren committed
106 107
	if context.CodeAddr != nil {
		if p := Precompiled[context.CodeAddr.Str()]; p != nil {
108
			return self.RunPrecompiled(p, input, context)
obscuren's avatar
obscuren committed
109
		}
obscuren's avatar
obscuren committed
110 111
	}

112 113 114 115 116
	// Don't bother with the execution if there's no code.
	if len(code) == 0 {
		return context.Return(nil), nil
	}

obscuren's avatar
obscuren committed
117 118 119 120 121 122 123
	for {
		// The base for all big integer arithmetic
		base := new(big.Int)

		// Get the memory location of pc
		op = context.GetOp(pc)

124
		// calculate the new memory size and gas price for the current executing opcode
125
		newMemSize, cost, err = self.calculateGasAndSize(context, caller, op, statedb, mem, stack)
obscuren's avatar
obscuren committed
126 127 128
		if err != nil {
			return nil, err
		}
obscuren's avatar
obscuren committed
129

130 131
		// Use the calculated gas. When insufficient gas is present, use all gas and return an
		// Out Of Gas error
132
		if !context.UseGas(cost) {
obscuren's avatar
obscuren committed
133 134 135

			context.UseGas(context.Gas)

136
			return context.Return(nil), OutOfGasError
obscuren's avatar
obscuren committed
137
		}
138
		// Resize the memory calculated previously
obscuren's avatar
obscuren committed
139
		mem.Resize(newMemSize.Uint64())
140 141
		// Add a log message
		self.log(pc, op, context.Gas, cost, mem, stack, context, nil)
obscuren's avatar
obscuren committed
142 143 144

		switch op {
		case ADD:
obscuren's avatar
obscuren committed
145
			x, y := stack.pop(), stack.pop()
obscuren's avatar
obscuren committed
146

obscuren's avatar
obscuren committed
147
			base.Add(x, y)
obscuren's avatar
obscuren committed
148 149 150

			U256(base)

obscuren's avatar
obscuren committed
151 152
			// pop result back on the stack
			stack.push(base)
obscuren's avatar
obscuren committed
153
		case SUB:
obscuren's avatar
obscuren committed
154
			x, y := stack.pop(), stack.pop()
obscuren's avatar
obscuren committed
155

obscuren's avatar
obscuren committed
156
			base.Sub(x, y)
obscuren's avatar
obscuren committed
157 158 159

			U256(base)

obscuren's avatar
obscuren committed
160 161
			// pop result back on the stack
			stack.push(base)
obscuren's avatar
obscuren committed
162
		case MUL:
obscuren's avatar
obscuren committed
163
			x, y := stack.pop(), stack.pop()
obscuren's avatar
obscuren committed
164

obscuren's avatar
obscuren committed
165
			base.Mul(x, y)
obscuren's avatar
obscuren committed
166 167 168

			U256(base)

obscuren's avatar
obscuren committed
169 170
			// pop result back on the stack
			stack.push(base)
obscuren's avatar
obscuren committed
171
		case DIV:
obscuren's avatar
obscuren committed
172
			x, y := stack.pop(), stack.pop()
obscuren's avatar
obscuren committed
173

obscuren's avatar
obscuren committed
174
			if y.Cmp(common.Big0) != 0 {
obscuren's avatar
obscuren committed
175 176 177 178 179
				base.Div(x, y)
			}

			U256(base)

obscuren's avatar
obscuren committed
180 181
			// pop result back on the stack
			stack.push(base)
obscuren's avatar
obscuren committed
182
		case SDIV:
obscuren's avatar
obscuren committed
183
			x, y := S256(stack.pop()), S256(stack.pop())
obscuren's avatar
obscuren committed
184

obscuren's avatar
obscuren committed
185 186
			if y.Cmp(common.Big0) == 0 {
				base.Set(common.Big0)
obscuren's avatar
obscuren committed
187 188
			} else {
				n := new(big.Int)
obscuren's avatar
obscuren committed
189
				if new(big.Int).Mul(x, y).Cmp(common.Big0) < 0 {
obscuren's avatar
obscuren committed
190 191 192 193 194 195 196 197 198 199
					n.SetInt64(-1)
				} else {
					n.SetInt64(1)
				}

				base.Div(x.Abs(x), y.Abs(y)).Mul(base, n)

				U256(base)
			}

obscuren's avatar
obscuren committed
200
			stack.push(base)
obscuren's avatar
obscuren committed
201
		case MOD:
obscuren's avatar
obscuren committed
202
			x, y := stack.pop(), stack.pop()
obscuren's avatar
obscuren committed
203

obscuren's avatar
obscuren committed
204 205
			if y.Cmp(common.Big0) == 0 {
				base.Set(common.Big0)
obscuren's avatar
obscuren committed
206 207 208 209 210 211
			} else {
				base.Mod(x, y)
			}

			U256(base)

obscuren's avatar
obscuren committed
212
			stack.push(base)
obscuren's avatar
obscuren committed
213
		case SMOD:
obscuren's avatar
obscuren committed
214
			x, y := S256(stack.pop()), S256(stack.pop())
obscuren's avatar
obscuren committed
215

obscuren's avatar
obscuren committed
216 217
			if y.Cmp(common.Big0) == 0 {
				base.Set(common.Big0)
obscuren's avatar
obscuren committed
218 219
			} else {
				n := new(big.Int)
obscuren's avatar
obscuren committed
220
				if x.Cmp(common.Big0) < 0 {
obscuren's avatar
obscuren committed
221 222 223 224 225 226 227 228 229 230
					n.SetInt64(-1)
				} else {
					n.SetInt64(1)
				}

				base.Mod(x.Abs(x), y.Abs(y)).Mul(base, n)

				U256(base)
			}

obscuren's avatar
obscuren committed
231
			stack.push(base)
obscuren's avatar
obscuren committed
232 233

		case EXP:
obscuren's avatar
obscuren committed
234
			x, y := stack.pop(), stack.pop()
obscuren's avatar
obscuren committed
235

obscuren's avatar
obscuren committed
236
			base.Exp(x, y, Pow256)
obscuren's avatar
obscuren committed
237 238 239

			U256(base)

obscuren's avatar
obscuren committed
240
			stack.push(base)
obscuren's avatar
obscuren committed
241
		case SIGNEXTEND:
obscuren's avatar
obscuren committed
242 243 244
			back := stack.pop()
			if back.Cmp(big.NewInt(31)) < 0 {
				bit := uint(back.Uint64()*8 + 7)
obscuren's avatar
obscuren committed
245
				num := stack.pop()
obscuren's avatar
obscuren committed
246 247 248
				mask := new(big.Int).Lsh(common.Big1, bit)
				mask.Sub(mask, common.Big1)
				if common.BitTest(num, int(bit)) {
obscuren's avatar
obscuren committed
249 250 251 252 253 254 255
					num.Or(num, mask.Not(mask))
				} else {
					num.And(num, mask)
				}

				num = U256(num)

obscuren's avatar
obscuren committed
256
				stack.push(num)
obscuren's avatar
obscuren committed
257 258
			}
		case NOT:
obscuren's avatar
obscuren committed
259
			stack.push(U256(new(big.Int).Not(stack.pop())))
obscuren's avatar
obscuren committed
260
		case LT:
obscuren's avatar
obscuren committed
261
			x, y := stack.pop(), stack.pop()
262

obscuren's avatar
obscuren committed
263
			// x < y
obscuren's avatar
obscuren committed
264
			if x.Cmp(y) < 0 {
obscuren's avatar
obscuren committed
265
				stack.push(common.BigTrue)
obscuren's avatar
obscuren committed
266
			} else {
obscuren's avatar
obscuren committed
267
				stack.push(common.BigFalse)
obscuren's avatar
obscuren committed
268 269
			}
		case GT:
obscuren's avatar
obscuren committed
270
			x, y := stack.pop(), stack.pop()
obscuren's avatar
obscuren committed
271 272

			// x > y
obscuren's avatar
obscuren committed
273
			if x.Cmp(y) > 0 {
obscuren's avatar
obscuren committed
274
				stack.push(common.BigTrue)
obscuren's avatar
obscuren committed
275
			} else {
obscuren's avatar
obscuren committed
276
				stack.push(common.BigFalse)
obscuren's avatar
obscuren committed
277 278 279
			}

		case SLT:
obscuren's avatar
obscuren committed
280
			x, y := S256(stack.pop()), S256(stack.pop())
281

obscuren's avatar
obscuren committed
282
			// x < y
obscuren's avatar
obscuren committed
283
			if x.Cmp(S256(y)) < 0 {
obscuren's avatar
obscuren committed
284
				stack.push(common.BigTrue)
obscuren's avatar
obscuren committed
285
			} else {
obscuren's avatar
obscuren committed
286
				stack.push(common.BigFalse)
obscuren's avatar
obscuren committed
287 288
			}
		case SGT:
obscuren's avatar
obscuren committed
289
			x, y := S256(stack.pop()), S256(stack.pop())
obscuren's avatar
obscuren committed
290 291

			// x > y
obscuren's avatar
obscuren committed
292
			if x.Cmp(y) > 0 {
obscuren's avatar
obscuren committed
293
				stack.push(common.BigTrue)
obscuren's avatar
obscuren committed
294
			} else {
obscuren's avatar
obscuren committed
295
				stack.push(common.BigFalse)
obscuren's avatar
obscuren committed
296 297 298
			}

		case EQ:
obscuren's avatar
obscuren committed
299
			x, y := stack.pop(), stack.pop()
obscuren's avatar
obscuren committed
300 301 302

			// x == y
			if x.Cmp(y) == 0 {
obscuren's avatar
obscuren committed
303
				stack.push(common.BigTrue)
obscuren's avatar
obscuren committed
304
			} else {
obscuren's avatar
obscuren committed
305
				stack.push(common.BigFalse)
obscuren's avatar
obscuren committed
306 307
			}
		case ISZERO:
obscuren's avatar
obscuren committed
308
			x := stack.pop()
obscuren's avatar
obscuren committed
309 310
			if x.Cmp(common.BigFalse) > 0 {
				stack.push(common.BigFalse)
obscuren's avatar
obscuren committed
311
			} else {
obscuren's avatar
obscuren committed
312
				stack.push(common.BigTrue)
obscuren's avatar
obscuren committed
313 314 315
			}

		case AND:
obscuren's avatar
obscuren committed
316
			x, y := stack.pop(), stack.pop()
obscuren's avatar
obscuren committed
317

obscuren's avatar
obscuren committed
318
			stack.push(base.And(x, y))
obscuren's avatar
obscuren committed
319
		case OR:
obscuren's avatar
obscuren committed
320
			x, y := stack.pop(), stack.pop()
obscuren's avatar
obscuren committed
321

obscuren's avatar
obscuren committed
322
			stack.push(base.Or(x, y))
obscuren's avatar
obscuren committed
323
		case XOR:
obscuren's avatar
obscuren committed
324
			x, y := stack.pop(), stack.pop()
obscuren's avatar
obscuren committed
325

obscuren's avatar
obscuren committed
326
			stack.push(base.Xor(x, y))
obscuren's avatar
obscuren committed
327
		case BYTE:
obscuren's avatar
obscuren committed
328
			th, val := stack.pop(), stack.pop()
obscuren's avatar
obscuren committed
329 330

			if th.Cmp(big.NewInt(32)) < 0 {
obscuren's avatar
obscuren committed
331
				byt := big.NewInt(int64(common.LeftPadBytes(val.Bytes(), 32)[th.Int64()]))
obscuren's avatar
obscuren committed
332 333 334

				base.Set(byt)
			} else {
obscuren's avatar
obscuren committed
335
				base.Set(common.BigFalse)
obscuren's avatar
obscuren committed
336 337
			}

obscuren's avatar
obscuren committed
338
			stack.push(base)
obscuren's avatar
obscuren committed
339
		case ADDMOD:
obscuren's avatar
obscuren committed
340 341 342
			x := stack.pop()
			y := stack.pop()
			z := stack.pop()
obscuren's avatar
obscuren committed
343

obscuren's avatar
obscuren committed
344
			if z.Cmp(Zero) > 0 {
345
				add := new(big.Int).Add(x, y)
obscuren's avatar
obscuren committed
346 347
				base.Mod(add, z)

obscuren's avatar
obscuren committed
348
				base = U256(base)
obscuren's avatar
obscuren committed
349 350
			}

obscuren's avatar
obscuren committed
351
			stack.push(base)
obscuren's avatar
obscuren committed
352
		case MULMOD:
obscuren's avatar
obscuren committed
353 354 355
			x := stack.pop()
			y := stack.pop()
			z := stack.pop()
obscuren's avatar
obscuren committed
356

357 358
			if z.Cmp(Zero) > 0 {
				mul := new(big.Int).Mul(x, y)
obscuren's avatar
obscuren committed
359 360 361 362 363
				base.Mod(mul, z)

				U256(base)
			}

obscuren's avatar
obscuren committed
364
			stack.push(base)
obscuren's avatar
obscuren committed
365 366

		case SHA3:
367
			offset, size := stack.pop(), stack.pop()
obscuren's avatar
obscuren committed
368 369
			data := crypto.Sha3(mem.Get(offset.Int64(), size.Int64()))

obscuren's avatar
obscuren committed
370
			stack.push(common.BigD(data))
obscuren's avatar
obscuren committed
371 372

		case ADDRESS:
obscuren's avatar
obscuren committed
373
			stack.push(common.Bytes2Big(context.Address().Bytes()))
obscuren's avatar
obscuren committed
374 375

		case BALANCE:
obscuren's avatar
obscuren committed
376
			addr := common.BigToAddress(stack.pop())
377
			balance := statedb.GetBalance(addr)
obscuren's avatar
obscuren committed
378

obscuren's avatar
obscuren committed
379
			stack.push(balance)
obscuren's avatar
obscuren committed
380 381 382 383

		case ORIGIN:
			origin := self.env.Origin()

obscuren's avatar
obscuren committed
384
			stack.push(origin.Big())
obscuren's avatar
obscuren committed
385 386 387

		case CALLER:
			caller := context.caller.Address()
obscuren's avatar
obscuren committed
388
			stack.push(common.Bytes2Big(caller.Bytes()))
obscuren's avatar
obscuren committed
389 390

		case CALLVALUE:
obscuren's avatar
obscuren committed
391
			stack.push(value)
obscuren's avatar
obscuren committed
392 393

		case CALLDATALOAD:
394
			data := getData(input, stack.pop(), common.Big32)
obscuren's avatar
obscuren committed
395

obscuren's avatar
obscuren committed
396
			stack.push(common.Bytes2Big(data))
obscuren's avatar
obscuren committed
397
		case CALLDATASIZE:
398
			l := int64(len(input))
obscuren's avatar
obscuren committed
399
			stack.push(big.NewInt(l))
obscuren's avatar
obscuren committed
400 401 402

		case CALLDATACOPY:
			var (
obscuren's avatar
obscuren committed
403 404 405
				mOff = stack.pop()
				cOff = stack.pop()
				l    = stack.pop()
obscuren's avatar
obscuren committed
406
			)
407
			data := getData(input, cOff, l)
obscuren's avatar
obscuren committed
408

obscuren's avatar
obscuren committed
409
			mem.Set(mOff.Uint64(), l.Uint64(), data)
obscuren's avatar
obscuren committed
410 411 412 413

		case CODESIZE, EXTCODESIZE:
			var code []byte
			if op == EXTCODESIZE {
obscuren's avatar
obscuren committed
414
				addr := common.BigToAddress(stack.pop())
obscuren's avatar
obscuren committed
415 416 417 418 419 420 421

				code = statedb.GetCode(addr)
			} else {
				code = context.Code
			}

			l := big.NewInt(int64(len(code)))
obscuren's avatar
obscuren committed
422
			stack.push(l)
obscuren's avatar
obscuren committed
423 424 425 426

		case CODECOPY, EXTCODECOPY:
			var code []byte
			if op == EXTCODECOPY {
obscuren's avatar
obscuren committed
427 428
				addr := common.BigToAddress(stack.pop())
				code = statedb.GetCode(addr)
obscuren's avatar
obscuren committed
429 430 431
			} else {
				code = context.Code
			}
obscuren's avatar
obscuren committed
432

obscuren's avatar
obscuren committed
433
			var (
obscuren's avatar
obscuren committed
434 435 436
				mOff = stack.pop()
				cOff = stack.pop()
				l    = stack.pop()
obscuren's avatar
obscuren committed
437 438
			)

obscuren's avatar
obscuren committed
439
			codeCopy := getData(code, cOff, l)
obscuren's avatar
obscuren committed
440 441

			mem.Set(mOff.Uint64(), l.Uint64(), codeCopy)
obscuren's avatar
obscuren committed
442 443

		case GASPRICE:
obscuren's avatar
obscuren committed
444
			stack.push(context.Price)
obscuren's avatar
obscuren committed
445 446

		case BLOCKHASH:
obscuren's avatar
obscuren committed
447
			num := stack.pop()
obscuren's avatar
obscuren committed
448

obscuren's avatar
obscuren committed
449
			n := new(big.Int).Sub(self.env.BlockNumber(), common.Big257)
obscuren's avatar
obscuren committed
450
			if num.Cmp(n) > 0 && num.Cmp(self.env.BlockNumber()) < 0 {
obscuren's avatar
obscuren committed
451
				stack.push(self.env.GetHash(num.Uint64()).Big())
obscuren's avatar
obscuren committed
452
			} else {
obscuren's avatar
obscuren committed
453
				stack.push(common.Big0)
obscuren's avatar
obscuren committed
454 455 456 457 458
			}

		case COINBASE:
			coinbase := self.env.Coinbase()

obscuren's avatar
obscuren committed
459
			stack.push(coinbase.Big())
obscuren's avatar
obscuren committed
460 461 462 463

		case TIMESTAMP:
			time := self.env.Time()

464
			stack.push(new(big.Int).SetUint64(time))
obscuren's avatar
obscuren committed
465 466 467 468

		case NUMBER:
			number := self.env.BlockNumber()

obscuren's avatar
obscuren committed
469
			stack.push(U256(number))
obscuren's avatar
obscuren committed
470 471 472 473

		case DIFFICULTY:
			difficulty := self.env.Difficulty()

obscuren's avatar
obscuren committed
474
			stack.push(difficulty)
obscuren's avatar
obscuren committed
475 476 477

		case GASLIMIT:

obscuren's avatar
obscuren committed
478
			stack.push(self.env.GasLimit())
obscuren's avatar
obscuren committed
479 480

		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:
481 482
			size := uint64(op - PUSH1 + 1)
			byts := getData(code, new(big.Int).SetUint64(pc+1), new(big.Int).SetUint64(size))
obscuren's avatar
obscuren committed
483
			// push value to stack
obscuren's avatar
obscuren committed
484
			stack.push(common.Bytes2Big(byts))
485
			pc += size
obscuren's avatar
obscuren committed
486 487

		case POP:
obscuren's avatar
obscuren committed
488
			stack.pop()
obscuren's avatar
obscuren committed
489 490
		case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
			n := int(op - DUP1 + 1)
obscuren's avatar
obscuren committed
491
			stack.dup(n)
obscuren's avatar
obscuren committed
492 493 494

		case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
			n := int(op - SWAP1 + 2)
obscuren's avatar
obscuren committed
495
			stack.swap(n)
obscuren's avatar
obscuren committed
496 497 498

		case LOG0, LOG1, LOG2, LOG3, LOG4:
			n := int(op - LOG0)
obscuren's avatar
obscuren committed
499
			topics := make([]common.Hash, n)
obscuren's avatar
obscuren committed
500
			mStart, mSize := stack.pop(), stack.pop()
obscuren's avatar
obscuren committed
501
			for i := 0; i < n; i++ {
502
				topics[i] = common.BigToHash(stack.pop())
obscuren's avatar
obscuren committed
503 504 505
			}

			data := mem.Get(mStart.Int64(), mSize.Int64())
506
			log := state.NewLog(context.Address(), topics, data, self.env.BlockNumber().Uint64())
obscuren's avatar
obscuren committed
507 508 509
			self.env.AddLog(log)

		case MLOAD:
obscuren's avatar
obscuren committed
510
			offset := stack.pop()
obscuren's avatar
obscuren committed
511
			val := common.BigD(mem.Get(offset.Int64(), 32))
obscuren's avatar
obscuren committed
512
			stack.push(val)
obscuren's avatar
obscuren committed
513

514
		case MSTORE:
obscuren's avatar
obscuren committed
515 516
			// pop value of the stack
			mStart, val := stack.pop(), stack.pop()
obscuren's avatar
obscuren committed
517
			mem.Set(mStart.Uint64(), 32, common.BigToBytes(val, 256))
obscuren's avatar
obscuren committed
518 519

		case MSTORE8:
obscuren's avatar
obscuren committed
520
			off, val := stack.pop().Int64(), stack.pop().Int64()
obscuren's avatar
obscuren committed
521

obscuren's avatar
obscuren committed
522
			mem.store[off] = byte(val & 0xff)
obscuren's avatar
obscuren committed
523 524

		case SLOAD:
obscuren's avatar
obscuren committed
525
			loc := common.BigToHash(stack.pop())
526
			val := statedb.GetState(context.Address(), loc).Big()
obscuren's avatar
obscuren committed
527
			stack.push(val)
obscuren's avatar
obscuren committed
528 529

		case SSTORE:
obscuren's avatar
obscuren committed
530 531 532
			loc := common.BigToHash(stack.pop())
			val := stack.pop()

533
			statedb.SetState(context.Address(), loc, common.BigToHash(val))
obscuren's avatar
obscuren committed
534 535

		case JUMP:
obscuren's avatar
obscuren committed
536 537 538
			if err := jump(pc, stack.pop()); err != nil {
				return nil, err
			}
obscuren's avatar
obscuren committed
539 540 541

			continue
		case JUMPI:
obscuren's avatar
obscuren committed
542
			pos, cond := stack.pop(), stack.pop()
obscuren's avatar
obscuren committed
543

obscuren's avatar
obscuren committed
544
			if cond.Cmp(common.BigTrue) >= 0 {
obscuren's avatar
obscuren committed
545 546 547
				if err := jump(pc, pos); err != nil {
					return nil, err
				}
obscuren's avatar
obscuren committed
548 549 550 551 552 553

				continue
			}

		case JUMPDEST:
		case PC:
554
			stack.push(new(big.Int).SetUint64(pc))
obscuren's avatar
obscuren committed
555
		case MSIZE:
obscuren's avatar
obscuren committed
556
			stack.push(big.NewInt(int64(mem.Len())))
obscuren's avatar
obscuren committed
557
		case GAS:
obscuren's avatar
obscuren committed
558
			stack.push(context.Gas)
obscuren's avatar
obscuren committed
559

obscuren's avatar
obscuren committed
560 561 562
		case CREATE:

			var (
obscuren's avatar
obscuren committed
563 564
				value        = stack.pop()
				offset, size = stack.pop(), stack.pop()
obscuren's avatar
obscuren committed
565 566
				input        = mem.Get(offset.Int64(), size.Int64())
				gas          = new(big.Int).Set(context.Gas)
obscuren's avatar
obscuren committed
567
				addr         common.Address
obscuren's avatar
obscuren committed
568 569 570
			)

			context.UseGas(context.Gas)
obscuren's avatar
obscuren committed
571
			ret, suberr, ref := self.env.Create(context, input, gas, price, value)
obscuren's avatar
obscuren committed
572
			if suberr != nil {
obscuren's avatar
obscuren committed
573
				stack.push(common.BigFalse)
obscuren's avatar
obscuren committed
574 575 576 577

			} else {
				// gas < len(ret) * CreateDataGas == NO_CODE
				dataGas := big.NewInt(int64(len(ret)))
578
				dataGas.Mul(dataGas, params.CreateDataGas)
obscuren's avatar
obscuren committed
579 580 581 582 583
				if context.UseGas(dataGas) {
					ref.SetCode(ret)
				}
				addr = ref.Address()

obscuren's avatar
obscuren committed
584
				stack.push(addr.Big())
obscuren's avatar
obscuren committed
585 586 587 588

			}

		case CALL, CALLCODE:
obscuren's avatar
obscuren committed
589 590 591
			gas := stack.pop()
			// pop gas and value of the stack.
			addr, value := stack.pop(), stack.pop()
obscuren's avatar
obscuren committed
592
			value = U256(value)
obscuren's avatar
obscuren committed
593 594 595 596
			// pop input size and offset
			inOffset, inSize := stack.pop(), stack.pop()
			// pop return size and offset
			retOffset, retSize := stack.pop(), stack.pop()
obscuren's avatar
obscuren committed
597

obscuren's avatar
obscuren committed
598
			address := common.BigToAddress(addr)
599

obscuren's avatar
obscuren committed
600 601 602
			// Get the arguments from the memory
			args := mem.Get(inOffset.Int64(), inSize.Int64())

obscuren's avatar
obscuren committed
603
			if len(value.Bytes()) > 0 {
604
				gas.Add(gas, params.CallStipend)
obscuren's avatar
obscuren committed
605 606
			}

obscuren's avatar
obscuren committed
607 608 609 610 611
			var (
				ret []byte
				err error
			)
			if op == CALLCODE {
612
				ret, err = self.env.CallCode(context, address, args, gas, price, value)
obscuren's avatar
obscuren committed
613
			} else {
614
				ret, err = self.env.Call(context, address, args, gas, price, value)
obscuren's avatar
obscuren committed
615 616 617
			}

			if err != nil {
obscuren's avatar
obscuren committed
618
				stack.push(common.BigFalse)
obscuren's avatar
obscuren committed
619 620

			} else {
obscuren's avatar
obscuren committed
621
				stack.push(common.BigTrue)
obscuren's avatar
obscuren committed
622 623 624

				mem.Set(retOffset.Uint64(), retSize.Uint64(), ret)
			}
625

obscuren's avatar
obscuren committed
626
		case RETURN:
obscuren's avatar
obscuren committed
627
			offset, size := stack.pop(), stack.pop()
628
			ret := mem.GetPtr(offset.Int64(), size.Int64())
obscuren's avatar
obscuren committed
629 630 631

			return context.Return(ret), nil
		case SUICIDE:
obscuren's avatar
obscuren committed
632
			receiver := statedb.GetOrNewStateObject(common.BigToAddress(stack.pop()))
obscuren's avatar
obscuren committed
633 634
			balance := statedb.GetBalance(context.Address())

635
			receiver.AddBalance(balance)
636

obscuren's avatar
obscuren committed
637 638 639 640 641 642 643 644
			statedb.Delete(context.Address())

			fallthrough
		case STOP: // Stop the context

			return context.Return(nil), nil
		default:

obscuren's avatar
obscuren committed
645
			return nil, fmt.Errorf("Invalid opcode %x", op)
obscuren's avatar
obscuren committed
646 647
		}

648
		pc++
obscuren's avatar
obscuren committed
649 650

	}
651 652
}

653 654
// calculateGasAndSize calculates the required given the opcode and stack items calculates the new memorysize for
// the operation. This does not reduce gas or resizes the memory.
655
func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCode, statedb *state.StateDB, mem *Memory, stack *stack) (*big.Int, *big.Int, error) {
obscuren's avatar
obscuren committed
656 657 658 659
	var (
		gas                 = new(big.Int)
		newMemSize *big.Int = new(big.Int)
	)
obscuren's avatar
obscuren committed
660 661 662 663
	err := baseCheck(op, stack, gas)
	if err != nil {
		return nil, nil, err
	}
obscuren's avatar
obscuren committed
664

obscuren's avatar
obscuren committed
665
	// stack Check, memory resize & gas phase
obscuren's avatar
obscuren committed
666 667 668
	switch op {
	case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
		n := int(op - SWAP1 + 2)
obscuren's avatar
obscuren committed
669 670 671 672
		err := stack.require(n)
		if err != nil {
			return nil, nil, err
		}
obscuren's avatar
obscuren committed
673
		gas.Set(GasFastestStep)
obscuren's avatar
obscuren committed
674 675
	case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
		n := int(op - DUP1 + 1)
obscuren's avatar
obscuren committed
676 677 678 679
		err := stack.require(n)
		if err != nil {
			return nil, nil, err
		}
obscuren's avatar
obscuren committed
680
		gas.Set(GasFastestStep)
obscuren's avatar
obscuren committed
681 682
	case LOG0, LOG1, LOG2, LOG3, LOG4:
		n := int(op - LOG0)
obscuren's avatar
obscuren committed
683 684 685 686
		err := stack.require(n + 2)
		if err != nil {
			return nil, nil, err
		}
obscuren's avatar
obscuren committed
687

obscuren's avatar
obscuren committed
688
		mSize, mStart := stack.data[stack.len()-2], stack.data[stack.len()-1]
obscuren's avatar
obscuren committed
689

690 691 692
		gas.Add(gas, params.LogGas)
		gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(n)), params.LogTopicGas))
		gas.Add(gas, new(big.Int).Mul(mSize, params.LogDataGas))
obscuren's avatar
obscuren committed
693 694 695

		newMemSize = calcMemSize(mStart, mSize)
	case EXP:
696
		gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(len(stack.data[stack.len()-2].Bytes()))), params.ExpByteGas))
obscuren's avatar
obscuren committed
697
	case SSTORE:
obscuren's avatar
obscuren committed
698 699 700 701
		err := stack.require(2)
		if err != nil {
			return nil, nil, err
		}
obscuren's avatar
obscuren committed
702

obscuren's avatar
obscuren committed
703
		var g *big.Int
obscuren's avatar
obscuren committed
704
		y, x := stack.data[stack.len()-2], stack.data[stack.len()-1]
obscuren's avatar
obscuren committed
705
		val := statedb.GetState(context.Address(), common.BigToHash(x))
obscuren's avatar
obscuren committed
706 707 708 709 710

		// This checks for 3 scenario's and calculates gas accordingly
		// 1. From a zero-value address to a non-zero value         (NEW VALUE)
		// 2. From a non-zero value address to a zero-value address (DELETE)
		// 3. From a nen-zero to a non-zero                         (CHANGE)
711
		if common.EmptyHash(val) && !common.EmptyHash(common.BigToHash(y)) {
obscuren's avatar
obscuren committed
712
			// 0 => non 0
713
			g = params.SstoreSetGas
714
		} else if !common.EmptyHash(val) && common.EmptyHash(common.BigToHash(y)) {
715
			statedb.Refund(params.SstoreRefundGas)
obscuren's avatar
obscuren committed
716

717
			g = params.SstoreClearGas
obscuren's avatar
obscuren committed
718 719
		} else {
			// non 0 => non 0 (or 0 => 0)
720
			g = params.SstoreClearGas
obscuren's avatar
obscuren committed
721
		}
obscuren's avatar
obscuren committed
722
		gas.Set(g)
723 724
	case SUICIDE:
		if !statedb.IsDeleted(context.Address()) {
725
			statedb.Refund(params.SuicideRefundGas)
726
		}
obscuren's avatar
obscuren committed
727
	case MLOAD:
obscuren's avatar
obscuren committed
728
		newMemSize = calcMemSize(stack.peek(), u256(32))
obscuren's avatar
obscuren committed
729
	case MSTORE8:
obscuren's avatar
obscuren committed
730
		newMemSize = calcMemSize(stack.peek(), u256(1))
obscuren's avatar
obscuren committed
731
	case MSTORE:
obscuren's avatar
obscuren committed
732
		newMemSize = calcMemSize(stack.peek(), u256(32))
obscuren's avatar
obscuren committed
733
	case RETURN:
obscuren's avatar
obscuren committed
734
		newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2])
obscuren's avatar
obscuren committed
735
	case SHA3:
obscuren's avatar
obscuren committed
736
		newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2])
obscuren's avatar
obscuren committed
737

obscuren's avatar
obscuren committed
738
		words := toWordSize(stack.data[stack.len()-2])
739
		gas.Add(gas, words.Mul(words, params.Sha3WordGas))
obscuren's avatar
obscuren committed
740
	case CALLDATACOPY:
obscuren's avatar
obscuren committed
741
		newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3])
obscuren's avatar
obscuren committed
742

obscuren's avatar
obscuren committed
743
		words := toWordSize(stack.data[stack.len()-3])
744
		gas.Add(gas, words.Mul(words, params.CopyGas))
obscuren's avatar
obscuren committed
745
	case CODECOPY:
obscuren's avatar
obscuren committed
746
		newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3])
obscuren's avatar
obscuren committed
747

obscuren's avatar
obscuren committed
748
		words := toWordSize(stack.data[stack.len()-3])
749
		gas.Add(gas, words.Mul(words, params.CopyGas))
obscuren's avatar
obscuren committed
750
	case EXTCODECOPY:
obscuren's avatar
obscuren committed
751
		newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-4])
obscuren's avatar
obscuren committed
752

obscuren's avatar
obscuren committed
753
		words := toWordSize(stack.data[stack.len()-4])
754
		gas.Add(gas, words.Mul(words, params.CopyGas))
obscuren's avatar
obscuren committed
755

obscuren's avatar
obscuren committed
756
	case CREATE:
obscuren's avatar
obscuren committed
757
		newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-3])
obscuren's avatar
obscuren committed
758
	case CALL, CALLCODE:
obscuren's avatar
obscuren committed
759
		gas.Add(gas, stack.data[stack.len()-1])
obscuren's avatar
obscuren committed
760 761

		if op == CALL {
obscuren's avatar
obscuren committed
762
			if self.env.State().GetStateObject(common.BigToAddress(stack.data[stack.len()-2])) == nil {
763
				gas.Add(gas, params.CallNewAccountGas)
obscuren's avatar
obscuren committed
764
			}
obscuren's avatar
obscuren committed
765
		}
obscuren's avatar
obscuren committed
766

obscuren's avatar
obscuren committed
767
		if len(stack.data[stack.len()-3].Bytes()) > 0 {
768
			gas.Add(gas, params.CallValueTransferGas)
obscuren's avatar
obscuren committed
769
		}
obscuren's avatar
obscuren committed
770

obscuren's avatar
obscuren committed
771 772
		x := calcMemSize(stack.data[stack.len()-6], stack.data[stack.len()-7])
		y := calcMemSize(stack.data[stack.len()-4], stack.data[stack.len()-5])
obscuren's avatar
obscuren committed
773

obscuren's avatar
obscuren committed
774
		newMemSize = common.BigMax(x, y)
obscuren's avatar
obscuren committed
775 776
	}

obscuren's avatar
obscuren committed
777
	if newMemSize.Cmp(common.Big0) > 0 {
obscuren's avatar
obscuren committed
778 779
		newMemSizeWords := toWordSize(newMemSize)
		newMemSize.Mul(newMemSizeWords, u256(32))
obscuren's avatar
obscuren committed
780 781

		if newMemSize.Cmp(u256(int64(mem.Len()))) > 0 {
obscuren's avatar
obscuren committed
782
			oldSize := toWordSize(big.NewInt(int64(mem.Len())))
obscuren's avatar
obscuren committed
783
			pow := new(big.Int).Exp(oldSize, common.Big2, Zero)
784 785
			linCoef := new(big.Int).Mul(oldSize, params.MemoryGas)
			quadCoef := new(big.Int).Div(pow, params.QuadCoeffDiv)
obscuren's avatar
obscuren committed
786 787
			oldTotalFee := new(big.Int).Add(linCoef, quadCoef)

obscuren's avatar
obscuren committed
788
			pow.Exp(newMemSizeWords, common.Big2, Zero)
789 790
			linCoef = new(big.Int).Mul(newMemSizeWords, params.MemoryGas)
			quadCoef = new(big.Int).Div(pow, params.QuadCoeffDiv)
obscuren's avatar
obscuren committed
791 792
			newTotalFee := new(big.Int).Add(linCoef, quadCoef)

793 794
			fee := new(big.Int).Sub(newTotalFee, oldTotalFee)
			gas.Add(gas, fee)
obscuren's avatar
obscuren committed
795
		}
796
	}
obscuren's avatar
obscuren committed
797

obscuren's avatar
obscuren committed
798
	return newMemSize, gas, nil
obscuren's avatar
obscuren committed
799 800
}

801 802 803
// RunPrecompile runs and evaluate the output of a precompiled contract defined in contracts.go
func (self *Vm) RunPrecompiled(p *PrecompiledAccount, input []byte, context *Context) (ret []byte, err error) {
	gas := p.Gas(len(input))
obscuren's avatar
obscuren committed
804
	if context.UseGas(gas) {
805
		ret = p.Call(input)
obscuren's avatar
obscuren committed
806 807 808

		return context.Return(ret), nil
	} else {
809
		return nil, OutOfGasError
obscuren's avatar
obscuren committed
810
	}
811 812
}

813 814
// log emits a log event to the environment for each opcode encountered. This is not to be confused with the
// LOG* opcode.
815
func (self *Vm) log(pc uint64, op OpCode, gas, cost *big.Int, memory *Memory, stack *stack, context *Context, err error) {
816 817 818 819 820
	if Debug {
		mem := make([]byte, len(memory.Data()))
		copy(mem, memory.Data())
		stck := make([]*big.Int, len(stack.Data()))
		copy(stck, stack.Data())
821 822 823 824 825 826 827

		object := context.self.(*state.StateObject)
		storage := make(map[common.Hash][]byte)
		object.EachStorage(func(k, v []byte) {
			storage[common.BytesToHash(k)] = v
		})

828
		self.env.AddStructLog(StructLog{pc, op, new(big.Int).Set(gas), cost, mem, stck, storage, err})
obscuren's avatar
obscuren committed
829
	}
obscuren's avatar
obscuren committed
830
}
831

832
// Environment returns the current workable state of the VM
obscuren's avatar
obscuren committed
833 834 835
func (self *Vm) Env() Environment {
	return self.env
}