Improve gas price estimator

This commit is contained in:
Łukasz Magiera
2020-08-01 09:40:11 +02:00
parent 4e9343c487
commit e5ca4b22d5
4 changed files with 108 additions and 7 deletions
+71 -5
View File
@@ -2,6 +2,8 @@ package full
import (
"context"
"github.com/filecoin-project/specs-actors/actors/abi/big"
"sort"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/build"
@@ -17,7 +19,7 @@ import (
type GasAPI struct {
fx.In
Stmgr *stmgr.StateManager
Cs *store.ChainStore
Chain *store.ChainStore
Mpool *messagepool.MessagePool
}
@@ -26,11 +28,75 @@ const MinGasPrice = 1
func (a *GasAPI) GasEstimateGasPrice(ctx context.Context, nblocksincl uint64,
sender address.Address, gaslimit int64, tsk types.TipSetKey) (types.BigInt, error) {
// TODO: something smarter obviously
if nblocksincl == 0 {
nblocksincl = 1
}
type gasMeta struct {
price big.Int
used int64
}
var prices []gasMeta
var gasUsed int64
var blocks int
ts := a.Chain.GetHeaviestTipSet()
for i := uint64(0); i < nblocksincl * 2; i++ {
if len(ts.Parents().Cids()) == 0 {
break // genesis
}
pts, err := a.Chain.LoadTipSet(ts.Parents())
if err != nil {
return types.BigInt{}, err
}
blocks += len(pts.Blocks())
msgs, err := a.Chain.MessagesForTipset(pts)
if err != nil {
return types.BigInt{}, xerrors.Errorf("loading messages: %w", err)
}
for i, msg := range msgs {
r, err := a.Chain.GetParentReceipt(ts.MinTicketBlock(), i)
if err != nil {
return types.BigInt{}, xerrors.Errorf("getting receipt: %w", err)
}
prices = append(prices, gasMeta{
price: msg.VMMessage().GasPrice,
used: r.GasUsed,
})
gasUsed += r.GasUsed
}
ts = pts
}
sort.Slice(prices, func(i, j int) bool {
// sort desc by price
return prices[i].price.GreaterThan(prices[j].price)
})
// todo: account for how full blocks are
at := gasUsed / 2
for _, price := range prices {
at -= price.used
if at > 0 {
continue
}
return price.price, nil
}
switch nblocksincl {
case 0:
return types.NewInt(MinGasPrice + 2), nil
case 1:
return types.NewInt(MinGasPrice + 2), nil
case 2:
return types.NewInt(MinGasPrice + 1), nil
default:
return types.NewInt(MinGasPrice), nil
@@ -43,7 +109,7 @@ func (a *GasAPI) GasEstimateGasLimit(ctx context.Context, msgIn *types.Message,
msg.GasLimit = build.BlockGasLimit
msg.GasPrice = types.NewInt(1)
currTs := a.Cs.GetHeaviestTipSet()
currTs := a.Chain.GetHeaviestTipSet()
fromA, err := a.Stmgr.ResolveToKeyAddress(ctx, msgIn.From, currTs)
if err != nil {
return -1, xerrors.Errorf("getting key address: %w", err)
+2 -2
View File
@@ -87,7 +87,7 @@ func (a *MpoolAPI) MpoolPush(ctx context.Context, smsg *types.SignedMessage) (ci
return a.Mpool.Push(smsg)
}
// GasMargin sets by how much should gas limit be increased over test execution
// GasMargin sets by how much should gas used be increased over test execution
var GasMargin = 1.5
func (a *MpoolAPI) MpoolPushMessage(ctx context.Context, msg *types.Message) (*types.SignedMessage, error) {
@@ -97,7 +97,7 @@ func (a *MpoolAPI) MpoolPushMessage(ctx context.Context, msg *types.Message) (*t
if msg.GasLimit == 0 {
gasLimit, err := a.GasEstimateGasLimit(ctx, msg, types.TipSetKey{})
if err != nil {
return nil, xerrors.Errorf("estimating gas limit: %w", err)
return nil, xerrors.Errorf("estimating gas used: %w", err)
}
msg.GasLimit = int64(float64(gasLimit) * GasMargin)
}