feat: add RPC for GasEstimateMessageGas
This commit is contained in:
parent
767611247c
commit
b32d25c562
@ -13,6 +13,7 @@ type GatewayAPI interface {
|
|||||||
ChainHead(ctx context.Context) (*types.TipSet, error)
|
ChainHead(ctx context.Context) (*types.TipSet, error)
|
||||||
ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
|
ChainGetTipSet(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
|
||||||
ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
|
ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
|
||||||
|
GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
|
||||||
MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
|
MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
|
||||||
StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
StateAccountKey(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
||||||
StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
|
StateGetActor(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
|
||||||
|
@ -368,6 +368,7 @@ type GatewayStruct struct {
|
|||||||
ChainGetTipSet func(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
|
ChainGetTipSet func(ctx context.Context, tsk types.TipSetKey) (*types.TipSet, error)
|
||||||
ChainGetTipSetByHeight func(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
|
ChainGetTipSetByHeight func(ctx context.Context, h abi.ChainEpoch, tsk types.TipSetKey) (*types.TipSet, error)
|
||||||
ChainHead func(ctx context.Context) (*types.TipSet, error)
|
ChainHead func(ctx context.Context) (*types.TipSet, error)
|
||||||
|
GasEstimateMessageGas func(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
|
||||||
MpoolPush func(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
|
MpoolPush func(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error)
|
||||||
StateAccountKey func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
StateAccountKey func(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error)
|
||||||
StateGetActor func(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
|
StateGetActor func(ctx context.Context, actor address.Address, ts types.TipSetKey) (*types.Actor, error)
|
||||||
@ -1403,6 +1404,10 @@ func (g GatewayStruct) ChainGetTipSetByHeight(ctx context.Context, h abi.ChainEp
|
|||||||
return g.Internal.ChainGetTipSetByHeight(ctx, h, tsk)
|
return g.Internal.ChainGetTipSetByHeight(ctx, h, tsk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g GatewayStruct) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) {
|
||||||
|
return g.Internal.GasEstimateMessageGas(ctx, msg, spec, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
func (g GatewayStruct) MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) {
|
func (g GatewayStruct) MpoolPush(ctx context.Context, sm *types.SignedMessage) (cid.Cid, error) {
|
||||||
return g.Internal.MpoolPush(ctx, sm)
|
return g.Internal.MpoolPush(ctx, sm)
|
||||||
}
|
}
|
||||||
|
@ -111,6 +111,14 @@ func (a *GatewayAPI) StateAccountKey(ctx context.Context, addr address.Address,
|
|||||||
return a.api.StateAccountKey(ctx, addr, tsk)
|
return a.api.StateAccountKey(ctx, addr, tsk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *GatewayAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error) {
|
||||||
|
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.api.GasEstimateMessageGas(ctx, msg, spec, tsk)
|
||||||
|
}
|
||||||
|
|
||||||
func (a *GatewayAPI) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) {
|
func (a *GatewayAPI) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) {
|
||||||
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
if err := a.checkTipsetKey(ctx, tsk); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -133,5 +141,6 @@ func (a *GatewayAPI) StateWaitMsg(ctx context.Context, msg cid.Cid, confidence u
|
|||||||
|
|
||||||
var _ api.GatewayAPI = (*GatewayAPI)(nil)
|
var _ api.GatewayAPI = (*GatewayAPI)(nil)
|
||||||
var _ full.ChainModuleAPI = (*GatewayAPI)(nil)
|
var _ full.ChainModuleAPI = (*GatewayAPI)(nil)
|
||||||
|
var _ full.GasModuleAPI = (*GatewayAPI)(nil)
|
||||||
var _ full.MpoolModuleAPI = (*GatewayAPI)(nil)
|
var _ full.MpoolModuleAPI = (*GatewayAPI)(nil)
|
||||||
var _ full.StateModuleAPI = (*GatewayAPI)(nil)
|
var _ full.StateModuleAPI = (*GatewayAPI)(nil)
|
||||||
|
@ -259,6 +259,7 @@ var DaemonCmd = &cli.Command{
|
|||||||
liteMode = node.Options(
|
liteMode = node.Options(
|
||||||
node.Override(new(api.GatewayAPI), gapi),
|
node.Override(new(api.GatewayAPI), gapi),
|
||||||
node.Override(new(full.ChainModuleAPI), node.From(new(api.GatewayAPI))),
|
node.Override(new(full.ChainModuleAPI), node.From(new(api.GatewayAPI))),
|
||||||
|
node.Override(new(full.GasModuleAPI), node.From(new(api.GatewayAPI))),
|
||||||
node.Override(new(full.MpoolModuleAPI), node.From(new(api.GatewayAPI))),
|
node.Override(new(full.MpoolModuleAPI), node.From(new(api.GatewayAPI))),
|
||||||
node.Override(new(full.StateModuleAPI), node.From(new(api.GatewayAPI))),
|
node.Override(new(full.StateModuleAPI), node.From(new(api.GatewayAPI))),
|
||||||
node.Override(new(stmgr.StateManagerAPI), modules.NewRPCStateManager),
|
node.Override(new(stmgr.StateManagerAPI), modules.NewRPCStateManager),
|
||||||
|
@ -267,8 +267,9 @@ func Online() Option {
|
|||||||
Override(new(*messagesigner.MessageSigner), messagesigner.NewMessageSigner),
|
Override(new(*messagesigner.MessageSigner), messagesigner.NewMessageSigner),
|
||||||
|
|
||||||
Override(new(full.ChainModuleAPI), From(new(full.ChainModule))),
|
Override(new(full.ChainModuleAPI), From(new(full.ChainModule))),
|
||||||
Override(new(full.StateModuleAPI), From(new(full.StateModule))),
|
Override(new(full.GasModuleAPI), From(new(full.GasModule))),
|
||||||
Override(new(full.MpoolModuleAPI), From(new(full.MpoolModule))),
|
Override(new(full.MpoolModuleAPI), From(new(full.MpoolModule))),
|
||||||
|
Override(new(full.StateModuleAPI), From(new(full.StateModule))),
|
||||||
Override(new(stmgr.StateManagerAPI), From(new(*stmgr.StateManager))),
|
Override(new(stmgr.StateManagerAPI), From(new(*stmgr.StateManager))),
|
||||||
|
|
||||||
Override(new(dtypes.ChainGCLocker), blockstore.NewGCLocker),
|
Override(new(dtypes.ChainGCLocker), blockstore.NewGCLocker),
|
||||||
|
@ -26,8 +26,27 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type GasModuleAPI interface {
|
||||||
|
GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, tsk types.TipSetKey) (*types.Message, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GasModule provides a default implementation of GasModuleAPI.
|
||||||
|
// It can be swapped out with another implementation through Dependency
|
||||||
|
// Injection (for example with a thin RPC client).
|
||||||
|
type GasModule struct {
|
||||||
|
fx.In
|
||||||
|
Stmgr *stmgr.StateManager
|
||||||
|
Chain *store.ChainStore
|
||||||
|
Mpool *messagepool.MessagePool
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ GasModuleAPI = (*GasModule)(nil)
|
||||||
|
|
||||||
type GasAPI struct {
|
type GasAPI struct {
|
||||||
fx.In
|
fx.In
|
||||||
|
|
||||||
|
GasModuleAPI
|
||||||
|
|
||||||
Stmgr *stmgr.StateManager
|
Stmgr *stmgr.StateManager
|
||||||
Chain *store.ChainStore
|
Chain *store.ChainStore
|
||||||
Mpool *messagepool.MessagePool
|
Mpool *messagepool.MessagePool
|
||||||
@ -36,9 +55,24 @@ type GasAPI struct {
|
|||||||
const MinGasPremium = 100e3
|
const MinGasPremium = 100e3
|
||||||
const MaxSpendOnFeeDenom = 100
|
const MaxSpendOnFeeDenom = 100
|
||||||
|
|
||||||
func (a *GasAPI) GasEstimateFeeCap(ctx context.Context, msg *types.Message, maxqueueblks int64,
|
func (a *GasAPI) GasEstimateFeeCap(
|
||||||
tsk types.TipSetKey) (types.BigInt, error) {
|
ctx context.Context,
|
||||||
ts := a.Chain.GetHeaviestTipSet()
|
msg *types.Message,
|
||||||
|
maxqueueblks int64,
|
||||||
|
tsk types.TipSetKey,
|
||||||
|
) (types.BigInt, error) {
|
||||||
|
return gasEstimateFeeCap(a.Chain, msg, maxqueueblks)
|
||||||
|
}
|
||||||
|
func (m *GasModule) GasEstimateFeeCap(
|
||||||
|
ctx context.Context,
|
||||||
|
msg *types.Message,
|
||||||
|
maxqueueblks int64,
|
||||||
|
tsk types.TipSetKey,
|
||||||
|
) (types.BigInt, error) {
|
||||||
|
return gasEstimateFeeCap(m.Chain, msg, maxqueueblks)
|
||||||
|
}
|
||||||
|
func gasEstimateFeeCap(cstore *store.ChainStore, msg *types.Message, maxqueueblks int64) (types.BigInt, error) {
|
||||||
|
ts := cstore.GetHeaviestTipSet()
|
||||||
|
|
||||||
parentBaseFee := ts.Blocks()[0].ParentBaseFee
|
parentBaseFee := ts.Blocks()[0].ParentBaseFee
|
||||||
increaseFactor := math.Pow(1.+1./float64(build.BaseFeeMaxChangeDenom), float64(maxqueueblks))
|
increaseFactor := math.Pow(1.+1./float64(build.BaseFeeMaxChangeDenom), float64(maxqueueblks))
|
||||||
@ -82,9 +116,25 @@ func medianGasPremium(prices []gasMeta, blocks int) abi.TokenAmount {
|
|||||||
return premium
|
return premium
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *GasAPI) GasEstimateGasPremium(ctx context.Context, nblocksincl uint64,
|
func (a *GasAPI) GasEstimateGasPremium(
|
||||||
sender address.Address, gaslimit int64, _ types.TipSetKey) (types.BigInt, error) {
|
ctx context.Context,
|
||||||
|
nblocksincl uint64,
|
||||||
|
sender address.Address,
|
||||||
|
gaslimit int64,
|
||||||
|
_ types.TipSetKey,
|
||||||
|
) (types.BigInt, error) {
|
||||||
|
return gasEstimateGasPremium(a.Chain, nblocksincl)
|
||||||
|
}
|
||||||
|
func (m *GasModule) GasEstimateGasPremium(
|
||||||
|
ctx context.Context,
|
||||||
|
nblocksincl uint64,
|
||||||
|
sender address.Address,
|
||||||
|
gaslimit int64,
|
||||||
|
_ types.TipSetKey,
|
||||||
|
) (types.BigInt, error) {
|
||||||
|
return gasEstimateGasPremium(m.Chain, nblocksincl)
|
||||||
|
}
|
||||||
|
func gasEstimateGasPremium(cstore *store.ChainStore, nblocksincl uint64) (types.BigInt, error) {
|
||||||
if nblocksincl == 0 {
|
if nblocksincl == 0 {
|
||||||
nblocksincl = 1
|
nblocksincl = 1
|
||||||
}
|
}
|
||||||
@ -92,20 +142,20 @@ func (a *GasAPI) GasEstimateGasPremium(ctx context.Context, nblocksincl uint64,
|
|||||||
var prices []gasMeta
|
var prices []gasMeta
|
||||||
var blocks int
|
var blocks int
|
||||||
|
|
||||||
ts := a.Chain.GetHeaviestTipSet()
|
ts := cstore.GetHeaviestTipSet()
|
||||||
for i := uint64(0); i < nblocksincl*2; i++ {
|
for i := uint64(0); i < nblocksincl*2; i++ {
|
||||||
if ts.Height() == 0 {
|
if ts.Height() == 0 {
|
||||||
break // genesis
|
break // genesis
|
||||||
}
|
}
|
||||||
|
|
||||||
pts, err := a.Chain.LoadTipSet(ts.Parents())
|
pts, err := cstore.LoadTipSet(ts.Parents())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.BigInt{}, err
|
return types.BigInt{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
blocks += len(pts.Blocks())
|
blocks += len(pts.Blocks())
|
||||||
|
|
||||||
msgs, err := a.Chain.MessagesForTipset(pts)
|
msgs, err := cstore.MessagesForTipset(pts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.BigInt{}, xerrors.Errorf("loading messages: %w", err)
|
return types.BigInt{}, xerrors.Errorf("loading messages: %w", err)
|
||||||
}
|
}
|
||||||
@ -142,19 +192,30 @@ func (a *GasAPI) GasEstimateGasPremium(ctx context.Context, nblocksincl uint64,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *GasAPI) GasEstimateGasLimit(ctx context.Context, msgIn *types.Message, _ types.TipSetKey) (int64, error) {
|
func (a *GasAPI) GasEstimateGasLimit(ctx context.Context, msgIn *types.Message, _ types.TipSetKey) (int64, error) {
|
||||||
|
return gasEstimateGasLimit(ctx, a.Chain, a.Stmgr, a.Mpool, msgIn)
|
||||||
|
}
|
||||||
|
func (m *GasModule) GasEstimateGasLimit(ctx context.Context, msgIn *types.Message, _ types.TipSetKey) (int64, error) {
|
||||||
|
return gasEstimateGasLimit(ctx, m.Chain, m.Stmgr, m.Mpool, msgIn)
|
||||||
|
}
|
||||||
|
func gasEstimateGasLimit(
|
||||||
|
ctx context.Context,
|
||||||
|
cstore *store.ChainStore,
|
||||||
|
smgr *stmgr.StateManager,
|
||||||
|
mpool *messagepool.MessagePool,
|
||||||
|
msgIn *types.Message,
|
||||||
|
) (int64, error) {
|
||||||
msg := *msgIn
|
msg := *msgIn
|
||||||
msg.GasLimit = build.BlockGasLimit
|
msg.GasLimit = build.BlockGasLimit
|
||||||
msg.GasFeeCap = types.NewInt(uint64(build.MinimumBaseFee) + 1)
|
msg.GasFeeCap = types.NewInt(uint64(build.MinimumBaseFee) + 1)
|
||||||
msg.GasPremium = types.NewInt(1)
|
msg.GasPremium = types.NewInt(1)
|
||||||
|
|
||||||
currTs := a.Chain.GetHeaviestTipSet()
|
currTs := cstore.GetHeaviestTipSet()
|
||||||
fromA, err := a.Stmgr.ResolveToKeyAddress(ctx, msgIn.From, currTs)
|
fromA, err := smgr.ResolveToKeyAddress(ctx, msgIn.From, currTs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, xerrors.Errorf("getting key address: %w", err)
|
return -1, xerrors.Errorf("getting key address: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pending, ts := a.Mpool.PendingFor(fromA)
|
pending, ts := mpool.PendingFor(fromA)
|
||||||
priorMsgs := make([]types.ChainMsg, 0, len(pending))
|
priorMsgs := make([]types.ChainMsg, 0, len(pending))
|
||||||
for _, m := range pending {
|
for _, m := range pending {
|
||||||
priorMsgs = append(priorMsgs, m)
|
priorMsgs = append(priorMsgs, m)
|
||||||
@ -163,11 +224,11 @@ func (a *GasAPI) GasEstimateGasLimit(ctx context.Context, msgIn *types.Message,
|
|||||||
// Try calling until we find a height with no migration.
|
// Try calling until we find a height with no migration.
|
||||||
var res *api.InvocResult
|
var res *api.InvocResult
|
||||||
for {
|
for {
|
||||||
res, err = a.Stmgr.CallWithGas(ctx, &msg, priorMsgs, ts)
|
res, err = smgr.CallWithGas(ctx, &msg, priorMsgs, ts)
|
||||||
if err != stmgr.ErrExpensiveFork {
|
if err != stmgr.ErrExpensiveFork {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
ts, err = a.Chain.GetTipSetFromKey(ts.Parents())
|
ts, err = cstore.GetTipSetFromKey(ts.Parents())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, xerrors.Errorf("getting parent tipset: %w", err)
|
return -1, xerrors.Errorf("getting parent tipset: %w", err)
|
||||||
}
|
}
|
||||||
@ -180,7 +241,7 @@ func (a *GasAPI) GasEstimateGasLimit(ctx context.Context, msgIn *types.Message,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Special case for PaymentChannel collect, which is deleting actor
|
// Special case for PaymentChannel collect, which is deleting actor
|
||||||
st, err := a.Stmgr.ParentState(ts)
|
st, err := smgr.ParentState(ts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = err
|
_ = err
|
||||||
// somewhat ignore it as it can happen and we just want to detect
|
// somewhat ignore it as it can happen and we just want to detect
|
||||||
@ -206,17 +267,17 @@ func (a *GasAPI) GasEstimateGasLimit(ctx context.Context, msgIn *types.Message,
|
|||||||
return res.MsgRct.GasUsed + 76e3, nil
|
return res.MsgRct.GasUsed + 76e3, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *GasAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, _ types.TipSetKey) (*types.Message, error) {
|
func (m *GasModule) GasEstimateMessageGas(ctx context.Context, msg *types.Message, spec *api.MessageSendSpec, _ types.TipSetKey) (*types.Message, error) {
|
||||||
if msg.GasLimit == 0 {
|
if msg.GasLimit == 0 {
|
||||||
gasLimit, err := a.GasEstimateGasLimit(ctx, msg, types.TipSetKey{})
|
gasLimit, err := m.GasEstimateGasLimit(ctx, msg, types.TipSetKey{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("estimating gas used: %w", err)
|
return nil, xerrors.Errorf("estimating gas used: %w", err)
|
||||||
}
|
}
|
||||||
msg.GasLimit = int64(float64(gasLimit) * a.Mpool.GetConfig().GasLimitOverestimation)
|
msg.GasLimit = int64(float64(gasLimit) * m.Mpool.GetConfig().GasLimitOverestimation)
|
||||||
}
|
}
|
||||||
|
|
||||||
if msg.GasPremium == types.EmptyInt || types.BigCmp(msg.GasPremium, types.NewInt(0)) == 0 {
|
if msg.GasPremium == types.EmptyInt || types.BigCmp(msg.GasPremium, types.NewInt(0)) == 0 {
|
||||||
gasPremium, err := a.GasEstimateGasPremium(ctx, 2, msg.From, msg.GasLimit, types.TipSetKey{})
|
gasPremium, err := m.GasEstimateGasPremium(ctx, 2, msg.From, msg.GasLimit, types.TipSetKey{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("estimating gas price: %w", err)
|
return nil, xerrors.Errorf("estimating gas price: %w", err)
|
||||||
}
|
}
|
||||||
@ -224,7 +285,7 @@ func (a *GasAPI) GasEstimateMessageGas(ctx context.Context, msg *types.Message,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if msg.GasFeeCap == types.EmptyInt || types.BigCmp(msg.GasFeeCap, types.NewInt(0)) == 0 {
|
if msg.GasFeeCap == types.EmptyInt || types.BigCmp(msg.GasFeeCap, types.NewInt(0)) == 0 {
|
||||||
feeCap, err := a.GasEstimateFeeCap(ctx, msg, 20, types.EmptyTSK)
|
feeCap, err := m.GasEstimateFeeCap(ctx, msg, 20, types.EmptyTSK)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("estimating fee cap: %w", err)
|
return nil, xerrors.Errorf("estimating fee cap: %w", err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user