gas oracle work
This commit is contained in:
+82
-29
@@ -18,6 +18,7 @@ package gasprice
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"math/big"
|
||||
"sort"
|
||||
"sync"
|
||||
@@ -33,6 +34,9 @@ var (
|
||||
maxPrice = big.NewInt(500 * params.GWei)
|
||||
maxPremium = big.NewInt(500 * params.GWei)
|
||||
maxFeeCap = big.NewInt(1000 * params.GWei)
|
||||
|
||||
errEIP1559IsFinalized = errors.New("past EIP1559 finalization, GasPrice cannot be set")
|
||||
errEIP1559IsNotActivated = errors.New("before EIP1559 activation, GasPremium and FeeCap cannot be set")
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
@@ -92,6 +96,9 @@ func (gpo *Oracle) SuggestPrice(ctx context.Context) (*big.Int, error) {
|
||||
gpo.cacheLock.RUnlock()
|
||||
|
||||
head, _ := gpo.backend.HeaderByNumber(ctx, rpc.LatestBlockNumber)
|
||||
if gpo.backend.ChainConfig().IsEIP1559Finalized(head.Number) {
|
||||
return nil, errEIP1559IsFinalized
|
||||
}
|
||||
headHash := head.Hash()
|
||||
if headHash == lastHead {
|
||||
return lastPrice, nil
|
||||
@@ -166,6 +173,9 @@ func (gpo *Oracle) SuggestPremium(ctx context.Context) (*big.Int, error) {
|
||||
gpo.cacheLock.RUnlock()
|
||||
|
||||
head, _ := gpo.backend.HeaderByNumber(ctx, rpc.LatestBlockNumber)
|
||||
if !gpo.backend.ChainConfig().IsEIP1559(head.Number) {
|
||||
return nil, errEIP1559IsNotActivated
|
||||
}
|
||||
headHash := head.Hash()
|
||||
if headHash == lastHead {
|
||||
return lastPremium, nil
|
||||
@@ -240,6 +250,9 @@ func (gpo *Oracle) SuggestCap(ctx context.Context) (*big.Int, error) {
|
||||
gpo.cacheLock.RUnlock()
|
||||
|
||||
head, _ := gpo.backend.HeaderByNumber(ctx, rpc.LatestBlockNumber)
|
||||
if !gpo.backend.ChainConfig().IsEIP1559(head.Number) {
|
||||
return nil, errEIP1559IsNotActivated
|
||||
}
|
||||
headHash := head.Hash()
|
||||
if headHash == lastHead {
|
||||
return lastCap, nil
|
||||
@@ -321,34 +334,52 @@ type getBlockCapsResult struct {
|
||||
err error
|
||||
}
|
||||
|
||||
type transactionsByGasPrice []*types.Transaction
|
||||
type transactionsByGasPrice struct {
|
||||
txs []*types.Transaction
|
||||
baseFee *big.Int
|
||||
}
|
||||
|
||||
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 {
|
||||
iPrice := t[i].GasPrice()
|
||||
jPrice := t[j].GasPrice()
|
||||
func (t *transactionsByGasPrice) Len() int { return len(t.txs) }
|
||||
func (t *transactionsByGasPrice) Swap(i, j int) { t.txs[i], t.txs[j] = t.txs[j], t.txs[i] }
|
||||
func (t *transactionsByGasPrice) Less(i, j int) bool {
|
||||
iPrice := t.txs[i].GasPrice()
|
||||
jPrice := t.txs[j].GasPrice()
|
||||
if iPrice == nil {
|
||||
iPrice = big.NewInt(0)
|
||||
iPrice = new(big.Int).Add(t.baseFee, t.txs[i].GasPremium())
|
||||
if iPrice.Cmp(t.txs[i].FeeCap()) > 0 {
|
||||
iPrice.Set(t.txs[i].FeeCap())
|
||||
}
|
||||
}
|
||||
if jPrice == nil {
|
||||
jPrice = big.NewInt(0)
|
||||
jPrice = new(big.Int).Add(t.baseFee, t.txs[j].GasPremium())
|
||||
if jPrice.Cmp(t.txs[j].FeeCap()) > 0 {
|
||||
jPrice.Set(t.txs[j].FeeCap())
|
||||
}
|
||||
}
|
||||
return iPrice.Cmp(jPrice) < 0
|
||||
}
|
||||
|
||||
type transactionsByGasPremium []*types.Transaction
|
||||
type transactionsByGasPremium struct {
|
||||
txs []*types.Transaction
|
||||
baseFee *big.Int
|
||||
}
|
||||
|
||||
func (t transactionsByGasPremium) Len() int { return len(t) }
|
||||
func (t transactionsByGasPremium) Swap(i, j int) { t[i], t[j] = t[j], t[i] }
|
||||
func (t transactionsByGasPremium) Less(i, j int) bool {
|
||||
iPremium := t[i].GasPremium()
|
||||
jPremium := t[j].GasPremium()
|
||||
func (t *transactionsByGasPremium) Len() int { return len(t.txs) }
|
||||
func (t *transactionsByGasPremium) Swap(i, j int) { t.txs[i], t.txs[j] = t.txs[j], t.txs[i] }
|
||||
func (t *transactionsByGasPremium) Less(i, j int) bool {
|
||||
iPremium := t.txs[i].GasPremium()
|
||||
jPremium := t.txs[j].GasPremium()
|
||||
if iPremium == nil {
|
||||
iPremium = big.NewInt(0)
|
||||
iPremium = new(big.Int).Sub(t.txs[i].GasPrice(), t.baseFee)
|
||||
if iPremium.Cmp(common.Big0) < 0 {
|
||||
iPremium.Set(common.Big0)
|
||||
}
|
||||
}
|
||||
if jPremium == nil {
|
||||
jPremium = big.NewInt(0)
|
||||
jPremium = new(big.Int).Sub(t.txs[j].GasPrice(), t.baseFee)
|
||||
if jPremium.Cmp(common.Big0) < 0 {
|
||||
jPremium.Set(common.Big0)
|
||||
}
|
||||
}
|
||||
return iPremium.Cmp(jPremium) < 0
|
||||
}
|
||||
@@ -361,10 +392,10 @@ func (t transactionsByFeeCap) Less(i, j int) bool {
|
||||
iCap := t[i].FeeCap()
|
||||
jCap := t[j].FeeCap()
|
||||
if iCap == nil {
|
||||
iCap = big.NewInt(0)
|
||||
iCap = t[i].GasPrice()
|
||||
}
|
||||
if jCap == nil {
|
||||
jCap = big.NewInt(0)
|
||||
jCap = t[j].GasPrice()
|
||||
}
|
||||
return iCap.Cmp(jCap) < 0
|
||||
}
|
||||
@@ -379,14 +410,23 @@ func (gpo *Oracle) getBlockPrices(ctx context.Context, signer types.Signer, bloc
|
||||
}
|
||||
|
||||
blockTxs := block.Transactions()
|
||||
txs := make([]*types.Transaction, len(blockTxs))
|
||||
copy(txs, blockTxs)
|
||||
sort.Sort(transactionsByGasPrice(txs))
|
||||
txs := new(transactionsByGasPrice)
|
||||
txs.txs = make([]*types.Transaction, len(blockTxs))
|
||||
copy(txs.txs, blockTxs)
|
||||
txs.baseFee = block.BaseFee()
|
||||
sort.Sort(txs)
|
||||
|
||||
for _, tx := range txs {
|
||||
for _, tx := range txs.txs {
|
||||
sender, err := types.Sender(signer, tx)
|
||||
if err == nil && sender != block.Coinbase() {
|
||||
ch <- getBlockPricesResult{tx.GasPrice(), nil}
|
||||
price := tx.GasPrice()
|
||||
if price == nil {
|
||||
price = new(big.Int).Add(block.BaseFee(), tx.GasPremium())
|
||||
if price.Cmp(tx.FeeCap()) > 0 {
|
||||
price.Set(tx.FeeCap())
|
||||
}
|
||||
}
|
||||
ch <- getBlockPricesResult{price, nil}
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -403,14 +443,23 @@ func (gpo *Oracle) getBlockPremiums(ctx context.Context, signer types.Signer, bl
|
||||
}
|
||||
|
||||
blockTxs := block.Transactions()
|
||||
txs := make([]*types.Transaction, len(blockTxs))
|
||||
copy(txs, blockTxs)
|
||||
sort.Sort(transactionsByGasPremium(txs))
|
||||
txs := new(transactionsByGasPremium)
|
||||
txs.txs = make([]*types.Transaction, len(blockTxs))
|
||||
copy(txs.txs, blockTxs)
|
||||
txs.baseFee = block.BaseFee()
|
||||
sort.Sort(txs)
|
||||
|
||||
for _, tx := range txs {
|
||||
for _, tx := range txs.txs {
|
||||
sender, err := types.Sender(signer, tx)
|
||||
if err == nil && sender != block.Coinbase() {
|
||||
ch <- getBlockPremiumsResult{tx.GasPremium(), nil}
|
||||
premium := tx.GasPremium()
|
||||
if premium == nil {
|
||||
premium = new(big.Int).Sub(tx.GasPrice(), block.BaseFee())
|
||||
if premium.Cmp(common.Big0) < 0 {
|
||||
premium.Set(common.Big0)
|
||||
}
|
||||
}
|
||||
ch <- getBlockPremiumsResult{premium, nil}
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -434,7 +483,11 @@ func (gpo *Oracle) getBlockCaps(ctx context.Context, signer types.Signer, blockN
|
||||
for _, tx := range txs {
|
||||
sender, err := types.Sender(signer, tx)
|
||||
if err == nil && sender != block.Coinbase() {
|
||||
ch <- getBlockCapsResult{tx.FeeCap(), nil}
|
||||
cap := tx.FeeCap()
|
||||
if cap == nil {
|
||||
cap = tx.GasPrice()
|
||||
}
|
||||
ch <- getBlockCapsResult{cap, nil}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,8 +395,8 @@ func (s *PrivateAccountAPI) SignTransaction(ctx context.Context, args SendTxArgs
|
||||
if args.Gas == nil {
|
||||
return nil, fmt.Errorf("gas not specified")
|
||||
}
|
||||
if args.GasPrice == nil {
|
||||
return nil, fmt.Errorf("gasPrice not specified")
|
||||
if args.GasPrice == nil && (args.GasPremium == nil || args.FeeCap == nil) {
|
||||
return nil, fmt.Errorf("gasPrice or gasPremium+feeCap not specified")
|
||||
}
|
||||
if args.Nonce == nil {
|
||||
return nil, fmt.Errorf("nonce not specified")
|
||||
|
||||
@@ -20,6 +20,7 @@ package les
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||
@@ -161,6 +162,20 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
|
||||
if gpoParams.DefaultGasPrice == nil {
|
||||
gpoParams.DefaultGasPrice = config.Miner.GasPrice
|
||||
}
|
||||
if gpoParams.DefaultFeeCap == nil {
|
||||
gpoParams.DefaultFeeCap = config.Miner.GasPrice
|
||||
}
|
||||
if gpoParams.DefaultGasPremium == nil {
|
||||
baseFee := leth.blockchain.CurrentHeader().BaseFee
|
||||
if baseFee == nil {
|
||||
baseFee = new(big.Int).SetUint64(params.EIP1559InitialBaseFee)
|
||||
}
|
||||
gasPremium := new(big.Int).Sub(config.Miner.GasPrice, baseFee)
|
||||
if gasPremium.Cmp(big.NewInt(0)) < 0 {
|
||||
gasPremium = big.NewInt(0)
|
||||
}
|
||||
gpoParams.DefaultGasPremium = gasPremium
|
||||
}
|
||||
leth.ApiBackend.gpo = gasprice.NewOracle(leth.ApiBackend, gpoParams)
|
||||
|
||||
leth.handler = newClientHandler(config.UltraLightServers, config.UltraLightFraction, checkpoint, leth)
|
||||
|
||||
Reference in New Issue
Block a user