Skip to content

Commit 9996fa5

Browse files
committed
feat: ExpectedRewardForPower builtin utility function
And `lotus-shed miner expected-reward` CLI command Ref: #13137
1 parent 455f510 commit 9996fa5

File tree

4 files changed

+196
-1
lines changed

4 files changed

+196
-1
lines changed

chain/actors/builtin/miner/actor.go.template

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
gstbuiltin "github.com/filecoin-project/go-state-types/builtin"
1313
minertypes13 "github.com/filecoin-project/go-state-types/builtin/v13/miner"
1414
{{- range .versions}}
15-
{{- if (ge . 16)}}
15+
{{- if (ge . 13)}}
1616
minertypes{{.}} "github.com/filecoin-project/go-state-types/builtin/v{{.}}/miner"
1717
smoothing{{.}} "github.com/filecoin-project/go-state-types/builtin/v{{.}}/util/smoothing"
1818
{{- end -}}
@@ -403,4 +403,38 @@ func PledgePenaltyForTermination(
403403
default:
404404
return big.Zero(), xerrors.Errorf("unsupported network version: %d", nwVer)
405405
}
406+
}
407+
408+
func ExpectedRewardForPower(
409+
nwVer network.Version,
410+
rewardEstimate, networkQAPowerEstimate builtin.FilterEstimate,
411+
qaSectorPower abi.StoragePower,
412+
projectionDuration abi.ChainEpoch,
413+
) (abi.TokenAmount, error) {
414+
v, err := actorstypes.VersionForNetwork(nwVer)
415+
if err != nil {
416+
return big.Zero(), err
417+
}
418+
419+
switch v {
420+
{{- range .versions}}
421+
{{- if (ge . 13)}}
422+
case actorstypes.Version{{.}}:
423+
return minertypes{{.}}.ExpectedRewardForPower(
424+
smoothing{{.}}.FilterEstimate{
425+
PositionEstimate: rewardEstimate.PositionEstimate,
426+
VelocityEstimate: rewardEstimate.VelocityEstimate,
427+
},
428+
smoothing{{.}}.FilterEstimate{
429+
PositionEstimate: networkQAPowerEstimate.PositionEstimate,
430+
VelocityEstimate: networkQAPowerEstimate.VelocityEstimate,
431+
},
432+
qaSectorPower,
433+
projectionDuration,
434+
), nil
435+
{{- end}}
436+
{{- end}}
437+
default:
438+
return big.Zero(), xerrors.Errorf("unsupported network version: %d", nwVer)
439+
}
406440
}

chain/actors/builtin/miner/miner.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ import (
1111
"github.com/filecoin-project/go-state-types/big"
1212
gstbuiltin "github.com/filecoin-project/go-state-types/builtin"
1313
minertypes13 "github.com/filecoin-project/go-state-types/builtin/v13/miner"
14+
smoothing13 "github.com/filecoin-project/go-state-types/builtin/v13/util/smoothing"
15+
minertypes14 "github.com/filecoin-project/go-state-types/builtin/v14/miner"
16+
smoothing14 "github.com/filecoin-project/go-state-types/builtin/v14/util/smoothing"
17+
minertypes15 "github.com/filecoin-project/go-state-types/builtin/v15/miner"
18+
smoothing15 "github.com/filecoin-project/go-state-types/builtin/v15/util/smoothing"
1419
minertypes16 "github.com/filecoin-project/go-state-types/builtin/v16/miner"
1520
smoothing16 "github.com/filecoin-project/go-state-types/builtin/v16/util/smoothing"
1621
minertypes "github.com/filecoin-project/go-state-types/builtin/v9/miner"
@@ -479,3 +484,72 @@ func PledgePenaltyForTermination(
479484
return big.Zero(), xerrors.Errorf("unsupported network version: %d", nwVer)
480485
}
481486
}
487+
488+
func ExpectedRewardForPower(
489+
nwVer network.Version,
490+
rewardEstimate, networkQAPowerEstimate builtin.FilterEstimate,
491+
qaSectorPower abi.StoragePower,
492+
projectionDuration abi.ChainEpoch,
493+
) (abi.TokenAmount, error) {
494+
v, err := actorstypes.VersionForNetwork(nwVer)
495+
if err != nil {
496+
return big.Zero(), err
497+
}
498+
499+
switch v {
500+
case actorstypes.Version13:
501+
return minertypes13.ExpectedRewardForPower(
502+
smoothing13.FilterEstimate{
503+
PositionEstimate: rewardEstimate.PositionEstimate,
504+
VelocityEstimate: rewardEstimate.VelocityEstimate,
505+
},
506+
smoothing13.FilterEstimate{
507+
PositionEstimate: networkQAPowerEstimate.PositionEstimate,
508+
VelocityEstimate: networkQAPowerEstimate.VelocityEstimate,
509+
},
510+
qaSectorPower,
511+
projectionDuration,
512+
), nil
513+
case actorstypes.Version14:
514+
return minertypes14.ExpectedRewardForPower(
515+
smoothing14.FilterEstimate{
516+
PositionEstimate: rewardEstimate.PositionEstimate,
517+
VelocityEstimate: rewardEstimate.VelocityEstimate,
518+
},
519+
smoothing14.FilterEstimate{
520+
PositionEstimate: networkQAPowerEstimate.PositionEstimate,
521+
VelocityEstimate: networkQAPowerEstimate.VelocityEstimate,
522+
},
523+
qaSectorPower,
524+
projectionDuration,
525+
), nil
526+
case actorstypes.Version15:
527+
return minertypes15.ExpectedRewardForPower(
528+
smoothing15.FilterEstimate{
529+
PositionEstimate: rewardEstimate.PositionEstimate,
530+
VelocityEstimate: rewardEstimate.VelocityEstimate,
531+
},
532+
smoothing15.FilterEstimate{
533+
PositionEstimate: networkQAPowerEstimate.PositionEstimate,
534+
VelocityEstimate: networkQAPowerEstimate.VelocityEstimate,
535+
},
536+
qaSectorPower,
537+
projectionDuration,
538+
), nil
539+
case actorstypes.Version16:
540+
return minertypes16.ExpectedRewardForPower(
541+
smoothing16.FilterEstimate{
542+
PositionEstimate: rewardEstimate.PositionEstimate,
543+
VelocityEstimate: rewardEstimate.VelocityEstimate,
544+
},
545+
smoothing16.FilterEstimate{
546+
PositionEstimate: networkQAPowerEstimate.PositionEstimate,
547+
VelocityEstimate: networkQAPowerEstimate.VelocityEstimate,
548+
},
549+
qaSectorPower,
550+
projectionDuration,
551+
), nil
552+
default:
553+
return big.Zero(), xerrors.Errorf("unsupported network version: %d", nwVer)
554+
}
555+
}

cmd/lotus-shed/miner-fees.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
"fmt"
66
"sort"
7+
"strconv"
78

89
cbor "github.com/ipfs/go-ipld-cbor"
910
"github.com/urfave/cli/v2"
@@ -21,6 +22,7 @@ import (
2122
"github.com/filecoin-project/lotus/chain/actors/builtin"
2223
minertypes "github.com/filecoin-project/lotus/chain/actors/builtin/miner"
2324
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
25+
"github.com/filecoin-project/lotus/chain/actors/builtin/reward"
2426
"github.com/filecoin-project/lotus/chain/types"
2527
lcli "github.com/filecoin-project/lotus/cli"
2628
"github.com/filecoin-project/lotus/lib/must"
@@ -607,3 +609,87 @@ var minerFeesInspect = &cli.Command{
607609
return nil
608610
},
609611
}
612+
613+
var minerExpectedRewardCmd = &cli.Command{
614+
Name: "expected-reward",
615+
Usage: " [--tipset <tipset>] [qapower]",
616+
Flags: []cli.Flag{
617+
&cli.StringFlag{
618+
Name: "tipset",
619+
Usage: "tipset or height (@X or @head for latest)",
620+
Value: "@head",
621+
},
622+
&cli.IntFlag{
623+
Name: "projection-period",
624+
Usage: "number of epochs to project reward for",
625+
Value: builtin.EpochsInDay,
626+
},
627+
},
628+
Action: func(cctx *cli.Context) error {
629+
api, closer, err := lcli.GetFullNodeAPIV1(cctx)
630+
if err != nil {
631+
return err
632+
}
633+
defer closer()
634+
635+
ctx := lcli.ReqContext(cctx)
636+
bstore := blockstore.NewAPIBlockstore(api)
637+
adtStore := adt.WrapStore(ctx, cbor.NewCborStore(bstore))
638+
639+
ts, err := lcli.LoadTipSet(ctx, cctx, api)
640+
if err != nil {
641+
return err
642+
}
643+
644+
if cctx.Args().Len() != 1 {
645+
return xerrors.Errorf("must provide qapower")
646+
}
647+
648+
projectionPeriod := abi.ChainEpoch(cctx.Int64("projection-period"))
649+
650+
powerInt, err := strconv.ParseUint(cctx.Args().Get(0), 10, 64)
651+
if err != nil {
652+
return xerrors.Errorf("parsing qapower: %w", err)
653+
}
654+
qapower := abi.NewStoragePower(int64(powerInt))
655+
656+
// Get the reward value for the current tipset from the reward actor
657+
var rewardSmoothed builtin.FilterEstimate
658+
if act, err := api.StateGetActor(ctx, reward.Address, ts.Key()); err != nil {
659+
return xerrors.Errorf("loading reward actor: %w", err)
660+
} else if s, err := reward.Load(adtStore, act); err != nil {
661+
return xerrors.Errorf("loading reward actor state: %w", err)
662+
} else if rewardSmoothed, err = s.ThisEpochRewardSmoothed(); err != nil {
663+
return xerrors.Errorf("failed to determine smoothed reward: %w", err)
664+
}
665+
666+
// Get the network power value for the current tipset from the power actor
667+
var powerSmoothed builtin.FilterEstimate
668+
if act, err := api.StateGetActor(ctx, power.Address, ts.Key()); err != nil {
669+
return xerrors.Errorf("loading power actor: %w", err)
670+
} else if s, err := power.Load(adtStore, act); err != nil {
671+
return xerrors.Errorf("loading power actor state: %w", err)
672+
} else if powerSmoothed, err = s.TotalPowerSmoothed(); err != nil {
673+
return xerrors.Errorf("failed to determine total power: %w", err)
674+
}
675+
676+
nv, err := api.StateNetworkVersion(ctx, ts.Key())
677+
if err != nil {
678+
return xerrors.Errorf("getting network version: %w", err)
679+
}
680+
681+
rew, err := minertypes.ExpectedRewardForPower(nv, rewardSmoothed, powerSmoothed, qapower, projectionPeriod)
682+
if err != nil {
683+
return xerrors.Errorf("calculating expected reward: %w", err)
684+
}
685+
_, _ = fmt.Fprintf(
686+
cctx.App.Writer,
687+
"Expected reward for %s bytes of QA power @ epoch %d for %d epochs: %s attoFIL\n",
688+
qapower,
689+
ts.Height(),
690+
projectionPeriod,
691+
rew,
692+
)
693+
return nil
694+
},
695+
}

cmd/lotus-shed/miner.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ var minerCmd = &cli.Command{
6060
minerFeesCmd,
6161
minerFeesInspect,
6262
minerListBalancesCmd,
63+
minerExpectedRewardCmd,
6364
},
6465
}
6566

0 commit comments

Comments
 (0)