@ -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 tx Prices [ ] * big . Int
var block Prices [ ] * 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 {
tx Prices = append ( tx Prices, res . prices ... )
if res . price != nil {
block Prices = append ( block Prices, 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 ( tx Prices) > 0 {
sort . Sort ( bigIntArray ( tx Prices) )
price = tx Prices[ ( len ( tx Prices) - 1 ) * gpo . percentile / 100 ]
if len ( block Prices) > 0 {
sort . Sort ( bigIntArray ( block Prices) )
price = block Prices[ ( len ( block Prices) - 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