// 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) } }
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} } }
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 }
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 }
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()) } }
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 }
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) } } }
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 }
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 }