aboutsummaryrefslogtreecommitdiffstats
path: root/eth/gasprice/gasprice.go
diff options
context:
space:
mode:
authorNick Johnson <arachnid@notdot.net>2018-01-10 20:57:36 +0800
committerFelix Lange <fjl@users.noreply.github.com>2018-01-10 20:57:36 +0800
commitb06e20bc7c498adef658b58f10f5c729b46d84f9 (patch)
tree1c16872e929bd0af039ba791419ce2c1e6190a6c /eth/gasprice/gasprice.go
parent3a5a5599dd387e70da2df3240fa5553722851bb9 (diff)
downloaddexon-b06e20bc7c498adef658b58f10f5c729b46d84f9.tar
dexon-b06e20bc7c498adef658b58f10f5c729b46d84f9.tar.gz
dexon-b06e20bc7c498adef658b58f10f5c729b46d84f9.tar.bz2
dexon-b06e20bc7c498adef658b58f10f5c729b46d84f9.tar.lz
dexon-b06e20bc7c498adef658b58f10f5c729b46d84f9.tar.xz
dexon-b06e20bc7c498adef658b58f10f5c729b46d84f9.tar.zst
dexon-b06e20bc7c498adef658b58f10f5c729b46d84f9.zip
eth/gasprice: set default percentile to 60%, count blocks instead of transactions (#15828)
The first should address a long term issue where we recommend a gas price that is greater than that required for 50% of transactions in recent blocks, which can lead to gas price inflation as people take this figure and add a margin to it, resulting in a positive feedback loop.
Diffstat (limited to 'eth/gasprice/gasprice.go')
-rw-r--r--eth/gasprice/gasprice.go49
1 files changed, 32 insertions, 17 deletions
diff --git a/eth/gasprice/gasprice.go b/eth/gasprice/gasprice.go
index c662348e1..54325692c 100644
--- a/eth/gasprice/gasprice.go
+++ b/eth/gasprice/gasprice.go
@@ -23,6 +23,7 @@ import (
"sync"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
@@ -101,9 +102,9 @@ func (gpo *Oracle) SuggestPrice(ctx context.Context) (*big.Int, error) {
ch := make(chan getBlockPricesResult, gpo.checkBlocks)
sent := 0
exp := 0
- var txPrices []*big.Int
+ var blockPrices []*big.Int
for sent < gpo.checkBlocks && blockNum > 0 {
- go gpo.getBlockPrices(ctx, blockNum, ch)
+ go gpo.getBlockPrices(ctx, types.MakeSigner(gpo.backend.ChainConfig(), big.NewInt(int64(blockNum))), blockNum, ch)
sent++
exp++
blockNum--
@@ -115,8 +116,8 @@ func (gpo *Oracle) SuggestPrice(ctx context.Context) (*big.Int, error) {
return lastPrice, res.err
}
exp--
- if len(res.prices) > 0 {
- txPrices = append(txPrices, res.prices...)
+ if res.price != nil {
+ blockPrices = append(blockPrices, res.price)
continue
}
if maxEmpty > 0 {
@@ -124,16 +125,16 @@ func (gpo *Oracle) SuggestPrice(ctx context.Context) (*big.Int, error) {
continue
}
if blockNum > 0 && sent < gpo.maxBlocks {
- go gpo.getBlockPrices(ctx, blockNum, ch)
+ go gpo.getBlockPrices(ctx, types.MakeSigner(gpo.backend.ChainConfig(), big.NewInt(int64(blockNum))), blockNum, ch)
sent++
exp++
blockNum--
}
}
price := lastPrice
- if len(txPrices) > 0 {
- sort.Sort(bigIntArray(txPrices))
- price = txPrices[(len(txPrices)-1)*gpo.percentile/100]
+ if len(blockPrices) > 0 {
+ sort.Sort(bigIntArray(blockPrices))
+ price = blockPrices[(len(blockPrices)-1)*gpo.percentile/100]
}
if price.Cmp(maxPrice) > 0 {
price = new(big.Int).Set(maxPrice)
@@ -147,24 +148,38 @@ func (gpo *Oracle) SuggestPrice(ctx context.Context) (*big.Int, error) {
}
type getBlockPricesResult struct {
- prices []*big.Int
- err error
+ price *big.Int
+ err error
}
-// getLowestPrice calculates the lowest transaction gas price in a given block
+type transactionsByGasPrice []*types.Transaction
+
+func (t transactionsByGasPrice) Len() int { return len(t) }
+func (t transactionsByGasPrice) Swap(i, j int) { t[i], t[j] = t[j], t[i] }
+func (t transactionsByGasPrice) Less(i, j int) bool { return t[i].GasPrice().Cmp(t[j].GasPrice()) < 0 }
+
+// getBlockPrices calculates the lowest transaction gas price in a given block
// and sends it to the result channel. If the block is empty, price is nil.
-func (gpo *Oracle) getBlockPrices(ctx context.Context, blockNum uint64, ch chan getBlockPricesResult) {
+func (gpo *Oracle) getBlockPrices(ctx context.Context, signer types.Signer, blockNum uint64, ch chan getBlockPricesResult) {
block, err := gpo.backend.BlockByNumber(ctx, rpc.BlockNumber(blockNum))
if block == nil {
ch <- getBlockPricesResult{nil, err}
return
}
- txs := block.Transactions()
- prices := make([]*big.Int, len(txs))
- for i, tx := range txs {
- prices[i] = tx.GasPrice()
+
+ blockTxs := block.Transactions()
+ txs := make([]*types.Transaction, len(blockTxs))
+ copy(txs, blockTxs)
+ sort.Sort(transactionsByGasPrice(txs))
+
+ for _, tx := range txs {
+ sender, err := types.Sender(signer, tx)
+ if err == nil && sender != block.Coinbase() {
+ ch <- getBlockPricesResult{tx.GasPrice(), nil}
+ return
+ }
}
- ch <- getBlockPricesResult{prices, nil}
+ ch <- getBlockPricesResult{nil, nil}
}
type bigIntArray []*big.Int