func (self *BlockProcessor) ApplyTransactions(gp GasPool, statedb *state.StateDB, block *types.Block, txs types.Transactions, transientProcess bool) (types.Receipts, error) { var ( receipts types.Receipts totalUsedGas = big.NewInt(0) err error cumulativeSum = new(big.Int) header = block.Header() ) for i, tx := range txs { statedb.StartRecord(tx.Hash(), block.Hash(), i) receipt, txGas, err := self.ApplyTransaction(gp, statedb, header, tx, totalUsedGas, transientProcess) if err != nil { return nil, err } if err != nil { glog.V(logger.Core).Infoln("TX err:", err) } receipts = append(receipts, receipt) cumulativeSum.Add(cumulativeSum, new(big.Int).Mul(txGas, tx.GasPrice())) } if block.GasUsed().Cmp(totalUsedGas) != 0 { return nil, ValidationError(fmt.Sprintf("gas used error (%v / %v)", block.GasUsed(), totalUsedGas)) } if transientProcess { go self.eventMux.Post(PendingBlockEvent{block, statedb.Logs()}) } return receipts, err }
func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block *types.Block, transientProcess bool) (receipts types.Receipts, err error) { gp := statedb.GetOrNewStateObject(block.Coinbase()) gp.SetGasLimit(block.GasLimit()) // Process the transactions on to parent state receipts, err = sm.ApplyTransactions(gp, statedb, block, block.Transactions(), transientProcess) if err != nil { return nil, err } return receipts, nil }
func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, state.Logs, *big.Int, error) { var ( data = common.FromHex(tx["data"]) gas = common.Big(tx["gasLimit"]) price = common.Big(tx["gasPrice"]) value = common.Big(tx["value"]) nonce = common.Big(tx["nonce"]).Uint64() caddr = common.HexToAddress(env["currentCoinbase"]) ) var to *common.Address if len(tx["to"]) > 2 { t := common.HexToAddress(tx["to"]) to = &t } // Set pre compiled contracts vm.Precompiled = vm.PrecompiledContracts() snapshot := statedb.Copy() coinbase := statedb.GetOrNewStateObject(caddr) coinbase.SetGasLimit(common.Big(env["currentGasLimit"])) key, _ := hex.DecodeString(tx["secretKey"]) addr := crypto.PubkeyToAddress(crypto.ToECDSA(key).PublicKey) message := NewMessage(addr, to, data, value, gas, price, nonce) vmenv := NewEnvFromMap(statedb, env, tx) vmenv.origin = addr ret, _, err := core.ApplyMessage(vmenv, message, coinbase) if core.IsNonceErr(err) || core.IsInvalidTxErr(err) || state.IsGasLimitErr(err) { statedb.Set(snapshot) } statedb.SyncObjects() return ret, vmenv.state.Logs(), vmenv.Gas, err }
// AccumulateRewards credits the coinbase of the given block with the // mining reward. The total reward consists of the static block reward // and rewards for included uncles. The coinbase of each uncle block is // also rewarded. func AccumulateRewards(statedb *state.StateDB, header *types.Header, uncles []*types.Header) { reward := new(big.Int).Set(BlockReward) r := new(big.Int) for _, uncle := range uncles { r.Add(uncle.Number, big8) r.Sub(r, header.Number) r.Mul(r, BlockReward) r.Div(r, big8) statedb.AddBalance(uncle.Coinbase, r) r.Div(BlockReward, big32) reward.Add(reward, r) } statedb.AddBalance(header.Coinbase, reward) }
func (self *BlockProcessor) ApplyTransaction(gp GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, transientProcess bool) (*types.Receipt, *big.Int, error) { _, gas, err := ApplyMessage(NewEnv(statedb, self.bc, tx, header), tx, gp) if err != nil { return nil, nil, err } // Update the state with pending changes statedb.SyncIntermediate() usedGas.Add(usedGas, gas) receipt := types.NewReceipt(statedb.Root().Bytes(), usedGas) receipt.TxHash = tx.Hash() receipt.GasUsed = new(big.Int).Set(gas) if MessageCreatesContract(tx) { from, _ := tx.From() receipt.ContractAddress = crypto.CreateAddress(from, tx.Nonce()) } logs := statedb.GetLogs(tx.Hash()) receipt.SetLogs(logs) receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) glog.V(logger.Debug).Infoln(receipt) // Notify all subscribers if !transientProcess { go self.eventMux.Post(TxPostEvent{tx}) go self.eventMux.Post(logs) } return receipt, gas, err }
func makeHeader(parent *types.Block, state *state.StateDB) *types.Header { var time *big.Int if parent.Time() == nil { time = big.NewInt(10) } else { time = new(big.Int).Add(parent.Time(), big.NewInt(25)) // block time is fixed at 25 seconds } return &types.Header{ Root: state.Root(), ParentHash: parent.Hash(), Coinbase: parent.Coinbase(), Difficulty: CalcDifficulty(time.Uint64(), new(big.Int).Sub(time, big.NewInt(10)).Uint64(), parent.Number(), parent.Difficulty()), GasLimit: CalcGasLimit(parent), GasUsed: new(big.Int), Number: new(big.Int).Add(parent.Number(), common.Big1), Time: time, } }
func RunVm(state *state.StateDB, env, exec map[string]string) ([]byte, state.Logs, *big.Int, error) { var ( to = common.HexToAddress(exec["address"]) from = common.HexToAddress(exec["caller"]) data = common.FromHex(exec["data"]) gas = common.Big(exec["gas"]) price = common.Big(exec["gasPrice"]) value = common.Big(exec["value"]) ) // Reset the pre-compiled contracts for VM tests. vm.Precompiled = make(map[string]*vm.PrecompiledAccount) caller := state.GetOrNewStateObject(from) vmenv := NewEnvFromMap(state, env, exec) vmenv.vmTest = true vmenv.skipTransfer = true vmenv.initial = true ret, err := vmenv.Call(caller, to, data, gas, price, value) return ret, vmenv.state.Logs(), vmenv.Gas, err }
func (t *BlockTest) ValidatePostState(statedb *state.StateDB) error { for addrString, acct := range t.preAccounts { // XXX: is is worth it checking for errors here? addr, err := hex.DecodeString(addrString) if err != nil { return err } code, err := hex.DecodeString(strings.TrimPrefix(acct.Code, "0x")) if err != nil { return err } balance, ok := new(big.Int).SetString(acct.Balance, 0) if !ok { return err } nonce, err := strconv.ParseUint(prepInt(16, acct.Nonce), 16, 64) if err != nil { return err } // address is indirectly verified by the other fields, as it's the db key code2 := statedb.GetCode(common.BytesToAddress(addr)) balance2 := statedb.GetBalance(common.BytesToAddress(addr)) nonce2 := statedb.GetNonce(common.BytesToAddress(addr)) if !bytes.Equal(code2, code) { return fmt.Errorf("account code mismatch, addr, found, expected: ", addrString, hex.EncodeToString(code2), hex.EncodeToString(code)) } if balance2.Cmp(balance) != 0 { return fmt.Errorf("account balance mismatch, addr, found, expected: ", addrString, balance2, balance) } if nonce2 != nonce { return fmt.Errorf("account nonce mismatch, addr, found, expected: ", addrString, nonce2, nonce) } } return nil }
// jitCalculateGasAndSize 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. func jitCalculateGasAndSize(env Environment, context *Context, caller ContextRef, instr instruction, statedb *state.StateDB, mem *Memory, stack *stack) (*big.Int, *big.Int, error) { var ( gas = new(big.Int) newMemSize *big.Int = new(big.Int) ) err := jitBaseCheck(instr, stack, gas) if err != nil { return nil, nil, err } // stack Check, memory resize & gas phase switch op := instr.op; op { case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16: n := int(op - SWAP1 + 2) err := stack.require(n) if err != nil { return nil, nil, err } gas.Set(GasFastestStep) case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16: n := int(op - DUP1 + 1) err := stack.require(n) if err != nil { return nil, nil, err } gas.Set(GasFastestStep) case LOG0, LOG1, LOG2, LOG3, LOG4: n := int(op - LOG0) err := stack.require(n + 2) if err != nil { return nil, nil, err } mSize, mStart := stack.data[stack.len()-2], stack.data[stack.len()-1] add := new(big.Int) gas.Add(gas, params.LogGas) gas.Add(gas, add.Mul(big.NewInt(int64(n)), params.LogTopicGas)) gas.Add(gas, add.Mul(mSize, params.LogDataGas)) newMemSize = calcMemSize(mStart, mSize) case EXP: gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(len(stack.data[stack.len()-2].Bytes()))), params.ExpByteGas)) case SSTORE: err := stack.require(2) if err != nil { return nil, nil, err } var g *big.Int y, x := stack.data[stack.len()-2], stack.data[stack.len()-1] val := statedb.GetState(context.Address(), common.BigToHash(x)) // 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) if common.EmptyHash(val) && !common.EmptyHash(common.BigToHash(y)) { // 0 => non 0 g = params.SstoreSetGas } else if !common.EmptyHash(val) && common.EmptyHash(common.BigToHash(y)) { statedb.Refund(params.SstoreRefundGas) g = params.SstoreClearGas } else { // non 0 => non 0 (or 0 => 0) g = params.SstoreClearGas } gas.Set(g) case SUICIDE: if !statedb.IsDeleted(context.Address()) { statedb.Refund(params.SuicideRefundGas) } case MLOAD: newMemSize = calcMemSize(stack.peek(), u256(32)) case MSTORE8: newMemSize = calcMemSize(stack.peek(), u256(1)) case MSTORE: newMemSize = calcMemSize(stack.peek(), u256(32)) case RETURN: newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2]) case SHA3: newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2]) words := toWordSize(stack.data[stack.len()-2]) gas.Add(gas, words.Mul(words, params.Sha3WordGas)) case CALLDATACOPY: newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3]) words := toWordSize(stack.data[stack.len()-3]) gas.Add(gas, words.Mul(words, params.CopyGas)) case CODECOPY: newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3]) words := toWordSize(stack.data[stack.len()-3]) gas.Add(gas, words.Mul(words, params.CopyGas)) case EXTCODECOPY: newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-4]) words := toWordSize(stack.data[stack.len()-4]) gas.Add(gas, words.Mul(words, params.CopyGas)) case CREATE: newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-3]) case CALL, CALLCODE: gas.Add(gas, stack.data[stack.len()-1]) if op == CALL { if env.State().GetStateObject(common.BigToAddress(stack.data[stack.len()-2])) == nil { gas.Add(gas, params.CallNewAccountGas) } } if len(stack.data[stack.len()-3].Bytes()) > 0 { gas.Add(gas, params.CallValueTransferGas) } x := calcMemSize(stack.data[stack.len()-6], stack.data[stack.len()-7]) y := calcMemSize(stack.data[stack.len()-4], stack.data[stack.len()-5]) newMemSize = common.BigMax(x, y) } if newMemSize.Cmp(common.Big0) > 0 { newMemSizeWords := toWordSize(newMemSize) newMemSize.Mul(newMemSizeWords, u256(32)) if newMemSize.Cmp(u256(int64(mem.Len()))) > 0 { // be careful reusing variables here when changing. // The order has been optimised to reduce allocation oldSize := toWordSize(big.NewInt(int64(mem.Len()))) pow := new(big.Int).Exp(oldSize, common.Big2, Zero) linCoef := oldSize.Mul(oldSize, params.MemoryGas) quadCoef := new(big.Int).Div(pow, params.QuadCoeffDiv) oldTotalFee := new(big.Int).Add(linCoef, quadCoef) pow.Exp(newMemSizeWords, common.Big2, Zero) linCoef = linCoef.Mul(newMemSizeWords, params.MemoryGas) quadCoef = quadCoef.Div(pow, params.QuadCoeffDiv) newTotalFee := linCoef.Add(linCoef, quadCoef) fee := newTotalFee.Sub(newTotalFee, oldTotalFee) gas.Add(gas, fee) } } return newMemSize, gas, nil }