From f809e478f4e3fe7a309c3349ddbb1806976a4592 Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Fri, 7 Aug 2020 20:09:50 +0200 Subject: [PATCH] Don't spend eveything on message fees Signed-off-by: Jakub Sztandera --- api/api_full.go | 2 +- api/apistruct/struct.go | 8 ++++---- node/impl/full/gas.go | 30 ++++++++++++++++++++++++------ node/impl/full/mpool.go | 2 +- 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/api/api_full.go b/api/api_full.go index 515e57c0f..a8176559d 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -116,7 +116,7 @@ type FullNode interface { BeaconGetEntry(ctx context.Context, epoch abi.ChainEpoch) (*types.BeaconEntry, error) // GasEstimateFeeCap estimates gas fee cap - GasEstimateFeeCap(context.Context, int64, types.TipSetKey) (types.BigInt, error) + GasEstimateFeeCap(context.Context, *types.Message, int64, types.TipSetKey) (types.BigInt, error) // GasEstimateGasLimit estimates gas used by the message and returns it. // It fails if message fails to execute. diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index f53b91f2f..9b888335e 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -89,7 +89,7 @@ type FullNodeStruct struct { GasEsitmateGasPremium func(context.Context, uint64, address.Address, int64, types.TipSetKey) (types.BigInt, error) `perm:"read"` GasEstimateGasLimit func(context.Context, *types.Message, types.TipSetKey) (int64, error) `perm:"read"` - GasEstimateFeeCap func(context.Context, int64, types.TipSetKey) (types.BigInt, error) `perm:"read"` + GasEstimateFeeCap func(context.Context, *types.Message, int64, types.TipSetKey) (types.BigInt, error) `perm:"read"` SyncState func(context.Context) (*api.SyncState, error) `perm:"read"` SyncSubmitBlock func(ctx context.Context, blk *types.BlockMsg) error `perm:"write"` @@ -437,9 +437,9 @@ func (c *FullNodeStruct) GasEsitmateGasPremium(ctx context.Context, nblocksincl sender address.Address, gaslimit int64, tsk types.TipSetKey) (types.BigInt, error) { return c.Internal.GasEsitmateGasPremium(ctx, nblocksincl, sender, gaslimit, tsk) } -func (c *FullNodeStruct) GasEstimateFeeCap(ctx context.Context, maxqueueblks int64, - tsk types.TipSetKey) (types.BigInt, error) { - return c.Internal.GasEstimateFeeCap(ctx, maxqueueblks, tsk) +func (c *FullNodeStruct) GasEstimateFeeCap(ctx context.Context, msg *types.Message, + maxqueueblks int64, tsk types.TipSetKey) (types.BigInt, error) { + return c.Internal.GasEstimateFeeCap(ctx, msg, maxqueueblks, tsk) } func (c *FullNodeStruct) GasEstimateGasLimit(ctx context.Context, msg *types.Message, diff --git a/node/impl/full/gas.go b/node/impl/full/gas.go index 43df095c3..d4532884b 100644 --- a/node/impl/full/gas.go +++ b/node/impl/full/gas.go @@ -27,17 +27,35 @@ type GasAPI struct { } const MinGasPremium = 10e3 -const BaseFeeEstimNBlocks = 20 +const MaxSpendOnFeeDenom = 100 -func (a *GasAPI) GasEstimateFeeCap(ctx context.Context, maxqueueblks int64, +func (a *GasAPI) GasEstimateFeeCap(ctx context.Context, msg *types.Message, maxqueueblks int64, tsk types.TipSetKey) (types.BigInt, error) { ts := a.Chain.GetHeaviestTipSet() - parentBaseFee := ts.Blocks()[0].ParentBaseFee - increaseFactor := math.Pow(1+float64(1/build.BaseFeeMaxChangeDenom), BaseFeeEstimNBlocks) + var act types.Actor + err := a.Stmgr.WithParentState(ts, a.Stmgr.WithActor(msg.From, stmgr.GetActor(&act))) + if err != nil { + return types.NewInt(0), xerrors.Errorf("getting actor: %w", err) + } + + parentBaseFee := ts.Blocks()[0].ParentBaseFee + increaseFactor := math.Pow(1+float64(1/build.BaseFeeMaxChangeDenom), float64(maxqueueblks)) + + feeInFuture := types.BigMul(parentBaseFee, types.NewInt(uint64(increaseFactor*(1<<8)))) + feeInFuture = types.BigDiv(feeInFuture, types.NewInt(1<<8)) + + gasLimitBig := types.NewInt(uint64(msg.GasLimit)) + maxAccepted := types.BigDiv(act.Balance, types.NewInt(MaxSpendOnFeeDenom)) + expectedFee := types.BigMul(feeInFuture, gasLimitBig) + + out := feeInFuture + if types.BigCmp(expectedFee, maxAccepted) > 0 { + log.Warnf("Expected fee for message higher than tolerance: %s > %s, setting to tolerance", + types.FIL(expectedFee), types.FIL(maxAccepted)) + out = types.BigDiv(maxAccepted, gasLimitBig) + } - out := types.BigMul(parentBaseFee, types.NewInt(uint64(increaseFactor*(1<<8)))) - out = types.BigDiv(out, types.NewInt(1<<8)) return out, nil } diff --git a/node/impl/full/mpool.go b/node/impl/full/mpool.go index 01a8b9055..ac1bb58eb 100644 --- a/node/impl/full/mpool.go +++ b/node/impl/full/mpool.go @@ -129,7 +129,7 @@ func (a *MpoolAPI) MpoolPushMessage(ctx context.Context, msg *types.Message) (*t } if msg.GasFeeCap == types.EmptyInt || types.BigCmp(msg.GasFeeCap, types.NewInt(0)) == 0 { - feeCap, err := a.GasEstimateFeeCap(ctx, 20, types.EmptyTSK) + feeCap, err := a.GasEstimateFeeCap(ctx, msg, 20, types.EmptyTSK) if err != nil { return nil, xerrors.Errorf("estimating fee cap: %w", err) }