// returns the lowers possible price with which a tx was or could have been included func (self *GasPriceOracle) lowestPrice(block *types.Block) *big.Int { gasUsed := big.NewInt(0) receipts := core.GetBlockReceipts(self.eth.ChainDb(), block.Hash()) if len(receipts) > 0 { if cgu := receipts[len(receipts)-1].CumulativeGasUsed; cgu != nil { gasUsed = receipts[len(receipts)-1].CumulativeGasUsed } } if new(big.Int).Mul(gasUsed, big.NewInt(100)).Cmp(new(big.Int).Mul(block.GasLimit(), big.NewInt(int64(self.eth.GpoFullBlockRatio)))) < 0 { // block is not full, could have posted a tx with MinGasPrice return big.NewInt(0) } txs := block.Transactions() if len(txs) == 0 { return big.NewInt(0) } // block is full, find smallest gasPrice minPrice := txs[0].GasPrice() for i := 1; i < len(txs); i++ { price := txs[i].GasPrice() if price.Cmp(minPrice) < 0 { minPrice = price } } return minPrice }
// rpcOutputBlock converts the given block to the RPC output which depends on fullTx. If inclTx is true transactions are // returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain // transaction hashes. func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) { fields := map[string]interface{}{ "number": rpc.NewHexNumber(b.Number()), "hash": b.Hash(), "parentHash": b.ParentHash(), "nonce": b.Header().Nonce, "sha3Uncles": b.UncleHash(), "logsBloom": b.Bloom(), "stateRoot": b.Root(), "miner": b.Coinbase(), "difficulty": rpc.NewHexNumber(b.Difficulty()), "totalDifficulty": rpc.NewHexNumber(s.bc.GetTd(b.Hash())), "extraData": fmt.Sprintf("0x%x", b.Extra()), "size": rpc.NewHexNumber(b.Size().Int64()), "gasLimit": rpc.NewHexNumber(b.GasLimit()), "gasUsed": rpc.NewHexNumber(b.GasUsed()), "timestamp": rpc.NewHexNumber(b.Time()), "transactionsRoot": b.TxHash(), "receiptRoot": b.ReceiptHash(), } if inclTx { formatTx := func(tx *types.Transaction) (interface{}, error) { return tx.Hash(), nil } if fullTx { formatTx = func(tx *types.Transaction) (interface{}, error) { return newRPCTransaction(b, tx.Hash()) } } txs := b.Transactions() transactions := make([]interface{}, len(txs)) var err error for i, tx := range b.Transactions() { if transactions[i], err = formatTx(tx); err != nil { return nil, err } } fields["transactions"] = transactions } uncles := b.Uncles() uncleHashes := make([]common.Hash, len(uncles)) for i, uncle := range uncles { uncleHashes[i] = uncle.Hash() } fields["uncles"] = uncleHashes return fields, nil }
// CalcGasLimit computes the gas limit of the next block after parent. // The result may be modified by the caller. // This is miner strategy, not consensus protocol. func CalcGasLimit(parent *types.Block) *big.Int { // contrib = (parentGasUsed * 3 / 2) / 1024 contrib := new(big.Int).Mul(parent.GasUsed(), big.NewInt(3)) contrib = contrib.Div(contrib, big.NewInt(2)) contrib = contrib.Div(contrib, params.GasLimitBoundDivisor) // decay = parentGasLimit / 1024 -1 decay := new(big.Int).Div(parent.GasLimit(), params.GasLimitBoundDivisor) decay.Sub(decay, big.NewInt(1)) /* strategy: gasLimit of block-to-mine is set based on parent's gasUsed value. if parentGasUsed > parentGasLimit * (2/3) then we increase it, otherwise lower it (or leave it unchanged if it's right at that usage) the amount increased/decreased depends on how far away from parentGasLimit * (2/3) parentGasUsed is. */ gl := new(big.Int).Sub(parent.GasLimit(), decay) gl = gl.Add(gl, contrib) gl.Set(common.BigMax(gl, params.MinGasLimit)) // however, if we're now below the target (GenesisGasLimit) we increase the // limit as much as we can (parentGasLimit / 1024 -1) if gl.Cmp(params.GenesisGasLimit) < 0 { gl.Add(parent.GasLimit(), decay) gl.Set(common.BigMin(gl, params.GenesisGasLimit)) } return gl }
// Process processes the state changes according to the Ethereum rules by running // the transaction messages using the statedb and applying any rewards to both // the processor (coinbase) and any included uncles. // // Process returns the receipts and logs accumulated during the process and // returns the amount of gas that was used in the process. If any of the // transactions failed to execute due to insufficient gas it will return an error. func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB) (types.Receipts, vm.Logs, *big.Int, error) { var ( receipts types.Receipts totalUsedGas = big.NewInt(0) err error header = block.Header() allLogs vm.Logs gp = new(GasPool).AddGas(block.GasLimit()) ) for i, tx := range block.Transactions() { statedb.StartRecord(tx.Hash(), block.Hash(), i) receipt, logs, _, err := ApplyTransaction(p.bc, gp, statedb, header, tx, totalUsedGas) if err != nil { return nil, nil, totalUsedGas, err } receipts = append(receipts, receipt) allLogs = append(allLogs, logs...) } AccumulateRewards(statedb, header, block.Uncles()) return receipts, allLogs, totalUsedGas, err }