Ejemplo n.º 1
0
// CalcDifficulty is the difficulty adjustment algorithm. It returns
// the difficulty that a new block should have when created at time
// given the parent block's time and difficulty.
func CalcDifficulty(time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
	if params.IsHomestead(new(big.Int).Add(parentNumber, common.Big1)) {
		return calcDifficultyHomestead(time, parentTime, parentNumber, parentDiff)
	} else {
		return calcDifficultyFrontier(time, parentTime, parentNumber, parentDiff)
	}
}
Ejemplo n.º 2
0
func (jt vmJumpTable) init(blockNumber *big.Int) {
	// when initialising a new VM execution we must first check the homestead
	// changes.
	if params.IsHomestead(blockNumber) {
		jumpTable[DELEGATECALL] = jumpPtr{opDelegateCall, true}
	} else {
		jumpTable[DELEGATECALL] = jumpPtr{nil, false}
	}
}
Ejemplo n.º 3
0
func (self *StateTransition) transitionDb() (ret []byte, usedGas *big.Int, err error) {
	if err = self.preCheck(); err != nil {
		return
	}
	msg := self.msg
	sender, _ := self.from() // err checked in preCheck

	homestead := params.IsHomestead(self.env.BlockNumber())
	contractCreation := MessageCreatesContract(msg)
	// Pay intrinsic gas
	if err = self.useGas(IntrinsicGas(self.data, contractCreation, homestead)); err != nil {
		return nil, nil, InvalidTxError(err)
	}

	vmenv := self.env
	//var addr common.Address
	if contractCreation {
		ret, _, err = vmenv.Create(sender, self.data, self.gas, self.gasPrice, self.value)
		if homestead && err == vm.CodeStoreOutOfGasError {
			self.gas = Big0
		}

		if err != nil {
			ret = nil
			glog.V(logger.Core).Infoln("VM create err:", err)
		}
	} else {
		// Increment the nonce for the next transaction
		self.state.SetNonce(sender.Address(), self.state.GetNonce(sender.Address())+1)
		ret, err = vmenv.Call(sender, self.to().Address(), self.data, self.gas, self.gasPrice, self.value)
		if err != nil {
			glog.V(logger.Core).Infoln("VM call err:", err)
		}
	}

	if err != nil && IsValueTransferErr(err) {
		return nil, nil, InvalidTxError(err)
	}

	// We aren't interested in errors here. Errors returned by the VM are non-consensus errors and therefor shouldn't bubble up
	if err != nil {
		err = nil
	}

	if vm.Debug {
		vm.StdErrFormat(vmenv.StructLogs())
	}

	self.refundGas()
	self.state.AddBalance(self.env.Coinbase(), new(big.Int).Mul(self.gasUsed(), self.gasPrice))

	return ret, self.gasUsed(), err
}
Ejemplo n.º 4
0
func (self *StateTransition) from() (vm.Account, error) {
	var (
		f   common.Address
		err error
	)
	if params.IsHomestead(self.env.BlockNumber()) {
		f, err = self.msg.From()
	} else {
		f, err = self.msg.FromFrontier()
	}
	if err != nil {
		return nil, err
	}
	if !self.state.Exist(f) {
		return self.state.CreateAccount(f), nil
	}
	return self.state.GetAccount(f), nil
}
Ejemplo n.º 5
0
func opCreate(instr instruction, pc *uint64, env Environment, contract *Contract, memory *Memory, stack *stack) {
	var (
		value        = stack.pop()
		offset, size = stack.pop(), stack.pop()
		input        = memory.Get(offset.Int64(), size.Int64())
		gas          = new(big.Int).Set(contract.Gas)
	)
	contract.UseGas(contract.Gas)
	_, addr, suberr := env.Create(contract, input, gas, contract.Price, value)
	// Push item on the stack based on the returned error. If the ruleset is
	// homestead we must check for CodeStoreOutOfGasError (homestead only
	// rule) and treat as an error, if the ruleset is frontier we must
	// ignore this error and pretend the operation was successful.
	if params.IsHomestead(env.BlockNumber()) && suberr == CodeStoreOutOfGasError {
		stack.push(new(big.Int))
	} else if suberr != nil && suberr != CodeStoreOutOfGasError {
		stack.push(new(big.Int))
	} else {
		stack.push(addr.Big())
	}
}
Ejemplo n.º 6
0
func runProgram(program *Program, pcstart uint64, mem *Memory, stack *stack, env Environment, contract *Contract, input []byte) ([]byte, error) {
	contract.Input = input

	var (
		pc         uint64 = program.mapping[pcstart]
		instrCount        = 0
	)

	if glog.V(logger.Debug) {
		glog.Infof("running JIT program %x\n", program.Id[:4])
		tstart := time.Now()
		defer func() {
			glog.Infof("JIT program %x done. time: %v instrc: %v\n", program.Id[:4], time.Since(tstart), instrCount)
		}()
	}

	homestead := params.IsHomestead(env.BlockNumber())
	for pc < uint64(len(program.instructions)) {
		instrCount++

		instr := program.instructions[pc]
		if instr.Op() == DELEGATECALL && !homestead {
			return nil, fmt.Errorf("Invalid opcode 0x%x", instr.Op())
		}

		ret, err := instr.do(program, &pc, env, contract, mem, stack)
		if err != nil {
			return nil, err
		}

		if instr.halts() {
			return ret, nil
		}
	}

	contract.Input = nil

	return nil, nil
}
Ejemplo n.º 7
0
func (pool *TxPool) eventLoop() {
	// Track chain events. When a chain events occurs (new chain canon block)
	// we need to know the new state. The new state will help us determine
	// the nonces in the managed state
	for ev := range pool.events.Chan() {
		switch ev := ev.Data.(type) {
		case ChainHeadEvent:
			pool.mu.Lock()
			if ev.Block != nil && params.IsHomestead(ev.Block.Number()) {
				pool.homestead = true
			}

			pool.resetState()
			pool.mu.Unlock()
		case GasPriceChanged:
			pool.mu.Lock()
			pool.minGasPrice = ev.Price
			pool.mu.Unlock()
		case RemovedTransactionEvent:
			pool.AddTransactions(ev.Txs)
		}
	}
}
Ejemplo n.º 8
0
func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.Address, input, code []byte, gas, gasPrice, value *big.Int) (ret []byte, addr common.Address, err error) {
	evm := vm.NewVm(env)
	// Depth check execution. Fail if we're trying to execute above the
	// limit.
	if env.Depth() > int(params.CallCreateDepth.Int64()) {
		caller.ReturnGas(gas, gasPrice)

		return nil, common.Address{}, vm.DepthError
	}

	if !env.CanTransfer(caller.Address(), value) {
		caller.ReturnGas(gas, gasPrice)

		return nil, common.Address{}, ValueTransferErr("insufficient funds to transfer value. Req %v, has %v", value, env.Db().GetBalance(caller.Address()))
	}

	var createAccount bool
	if address == nil {
		// Create a new account on the state
		nonce := env.Db().GetNonce(caller.Address())
		env.Db().SetNonce(caller.Address(), nonce+1)
		addr = crypto.CreateAddress(caller.Address(), nonce)
		address = &addr
		createAccount = true
	}

	snapshotPreTransfer := env.MakeSnapshot()
	var (
		from = env.Db().GetAccount(caller.Address())
		to   vm.Account
	)
	if createAccount {
		to = env.Db().CreateAccount(*address)
	} else {
		if !env.Db().Exist(*address) {
			to = env.Db().CreateAccount(*address)
		} else {
			to = env.Db().GetAccount(*address)
		}
	}
	env.Transfer(from, to, value)

	// initialise a new contract and set the code that is to be used by the
	// EVM. The contract is a scoped environment for this execution context
	// only.
	contract := vm.NewContract(caller, to, value, gas, gasPrice)
	contract.SetCallCode(codeAddr, code)
	defer contract.Finalise()

	ret, err = evm.Run(contract, input)
	// if the contract creation ran successfully and no errors were returned
	// calculate the gas required to store the code. If the code could not
	// be stored due to not enough gas set an error and let it be handled
	// by the error checking condition below.
	if err == nil && createAccount {
		dataGas := big.NewInt(int64(len(ret)))
		dataGas.Mul(dataGas, params.CreateDataGas)
		if contract.UseGas(dataGas) {
			env.Db().SetCode(*address, ret)
		} else {
			err = vm.CodeStoreOutOfGasError
		}
	}

	// When an error was returned by the EVM or when setting the creation code
	// above we revert to the snapshot and consume any gas remaining. Additionally
	// when we're in homestead this also counts for code storage gas errors.
	if err != nil && (params.IsHomestead(env.BlockNumber()) || err != vm.CodeStoreOutOfGasError) {
		contract.UseGas(contract.Gas)

		env.SetSnapshot(snapshotPreTransfer)
	}

	return ret, addr, err
}
Ejemplo n.º 9
0
func verifyTxFields(txTest TransactionTest, decodedTx *types.Transaction) (err error) {
	defer func() {
		if recovered := recover(); recovered != nil {
			buf := make([]byte, 64<<10)
			buf = buf[:runtime.Stack(buf, false)]
			err = fmt.Errorf("%v\n%s", recovered, buf)
		}
	}()

	var (
		decodedSender common.Address
	)

	if params.IsHomestead(common.String2Big(txTest.Blocknumber)) {
		decodedSender, err = decodedTx.From()
	} else {
		decodedSender, err = decodedTx.FromFrontier()
	}
	if err != nil {
		return err
	}

	expectedSender := mustConvertAddress(txTest.Sender)
	if expectedSender != decodedSender {
		return fmt.Errorf("Sender mismatch: %v %v", expectedSender, decodedSender)
	}

	expectedData := mustConvertBytes(txTest.Transaction.Data)
	if !bytes.Equal(expectedData, decodedTx.Data()) {
		return fmt.Errorf("Tx input data mismatch: %#v %#v", expectedData, decodedTx.Data())
	}

	expectedGasLimit := mustConvertBigInt(txTest.Transaction.GasLimit, 16)
	if expectedGasLimit.Cmp(decodedTx.Gas()) != 0 {
		return fmt.Errorf("GasLimit mismatch: %v %v", expectedGasLimit, decodedTx.Gas())
	}

	expectedGasPrice := mustConvertBigInt(txTest.Transaction.GasPrice, 16)
	if expectedGasPrice.Cmp(decodedTx.GasPrice()) != 0 {
		return fmt.Errorf("GasPrice mismatch: %v %v", expectedGasPrice, decodedTx.GasPrice())
	}

	expectedNonce := mustConvertUint(txTest.Transaction.Nonce, 16)
	if expectedNonce != decodedTx.Nonce() {
		return fmt.Errorf("Nonce mismatch: %v %v", expectedNonce, decodedTx.Nonce())
	}

	v, r, s := decodedTx.SignatureValues()
	expectedR := mustConvertBigInt(txTest.Transaction.R, 16)
	if r.Cmp(expectedR) != 0 {
		return fmt.Errorf("R mismatch: %v %v", expectedR, r)
	}
	expectedS := mustConvertBigInt(txTest.Transaction.S, 16)
	if s.Cmp(expectedS) != 0 {
		return fmt.Errorf("S mismatch: %v %v", expectedS, s)
	}
	expectedV := mustConvertUint(txTest.Transaction.V, 16)
	if uint64(v) != expectedV {
		return fmt.Errorf("V mismatch: %v %v", expectedV, v)
	}

	expectedTo := mustConvertAddress(txTest.Transaction.To)
	if decodedTx.To() == nil {
		if expectedTo != common.BytesToAddress([]byte{}) { // "empty" or "zero" address
			return fmt.Errorf("To mismatch when recipient is nil (contract creation): %v", expectedTo)
		}
	} else {
		if expectedTo != *decodedTx.To() {
			return fmt.Errorf("To mismatch: %v %v", expectedTo, *decodedTx.To())
		}
	}

	expectedValue := mustConvertBigInt(txTest.Transaction.Value, 16)
	if expectedValue.Cmp(decodedTx.Value()) != 0 {
		return fmt.Errorf("Value mismatch: %v %v", expectedValue, decodedTx.Value())
	}

	return nil
}