Skip to content

Commit 29a3d42

Browse files
authored
feat: ExpectedRewardForPower builtin utility function (#13138)
And `lotus-shed miner expected-reward` CLI command Ref: #13137
1 parent 22a1eaa commit 29a3d42

File tree

5 files changed

+193
-1
lines changed

5 files changed

+193
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
- chore: increase the F3 GMessage buffer size to 1024 ([filecoin-project/lotus#13126](https://github.com/filecoin-project/lotus/pull/13126))
1515
- feat(f3): integrate cached MapReduce from go-hamt-ipld, which improves performance of F3 power table calculation by 6-10x ([filecoin-project/lotus#13134](https://github.com/filecoin-project/lotus/pull/13134))
1616
- fix(spcli): send SettleDealPayments msg to f05 for `lotus-miner actor settle-deal` ([filecoin-project/lotus#13142](https://github.com/filecoin-project/lotus/pull/13142))
17+
- feat: ExpectedRewardForPower builtin utility function and `lotus-shed miner expected-reward` CLI command ([filecoin-project/lotus#13138](https://github.com/filecoin-project/lotus/pull/13138))
1718

1819
# Node v1.33.0 / 2025-05-08
1920
The Lotus v1.33.0 release introduces experimental v2 APIs with F3 awareness, featuring a new TipSet selection mechanism that significantly enhances how applications interact with the Filecoin blockchain. This release candidate also adds F3-aware Ethereum APIs via the /v2 endpoint. All of the /v2 APIs implement intelligent fallback mechanisms between F3 and Expected Consensus and are exposed through the Lotus Gateway.

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: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"github.com/filecoin-project/lotus/chain/actors/builtin"
2222
minertypes "github.com/filecoin-project/lotus/chain/actors/builtin/miner"
2323
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
24+
"github.com/filecoin-project/lotus/chain/actors/builtin/reward"
2425
"github.com/filecoin-project/lotus/chain/types"
2526
lcli "github.com/filecoin-project/lotus/cli"
2627
"github.com/filecoin-project/lotus/lib/must"
@@ -607,3 +608,84 @@ var minerFeesInspect = &cli.Command{
607608
return nil
608609
},
609610
}
611+
612+
var minerExpectedRewardCmd = &cli.Command{
613+
Name: "expected-reward",
614+
Usage: "Calculate the expected block reward for a miner over a specified projection period " +
615+
"(e.g. lotus-shed miner expected-reward --tipset @head --projection-period 1025280 --qapower 69793218560)",
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.Int64Flag{
623+
Name: "projection-period",
624+
Usage: "number of epochs to project reward for",
625+
Value: builtin.EpochsInDay,
626+
},
627+
&cli.Int64Flag{
628+
Name: "qapower",
629+
Usage: "Quality Adjusted Power in bytes",
630+
Value: 32 * 1024 * 1024 * 1024, // 32 GiB
631+
},
632+
},
633+
Action: func(cctx *cli.Context) error {
634+
api, closer, err := lcli.GetFullNodeAPIV1(cctx)
635+
if err != nil {
636+
return err
637+
}
638+
defer closer()
639+
640+
ctx := lcli.ReqContext(cctx)
641+
bstore := blockstore.NewAPIBlockstore(api)
642+
adtStore := adt.WrapStore(ctx, cbor.NewCborStore(bstore))
643+
644+
ts, err := lcli.LoadTipSet(ctx, cctx, api)
645+
if err != nil {
646+
return err
647+
}
648+
649+
projectionPeriod := abi.ChainEpoch(cctx.Int64("projection-period"))
650+
qapower := abi.NewStoragePower(cctx.Int64("qapower"))
651+
652+
// Get the reward value for the current tipset from the reward actor
653+
var rewardSmoothed builtin.FilterEstimate
654+
if act, err := api.StateGetActor(ctx, reward.Address, ts.Key()); err != nil {
655+
return xerrors.Errorf("loading reward actor: %w", err)
656+
} else if s, err := reward.Load(adtStore, act); err != nil {
657+
return xerrors.Errorf("loading reward actor state: %w", err)
658+
} else if rewardSmoothed, err = s.ThisEpochRewardSmoothed(); err != nil {
659+
return xerrors.Errorf("failed to determine smoothed reward: %w", err)
660+
}
661+
662+
// Get the network power value for the current tipset from the power actor
663+
var powerSmoothed builtin.FilterEstimate
664+
if act, err := api.StateGetActor(ctx, power.Address, ts.Key()); err != nil {
665+
return xerrors.Errorf("loading power actor: %w", err)
666+
} else if s, err := power.Load(adtStore, act); err != nil {
667+
return xerrors.Errorf("loading power actor state: %w", err)
668+
} else if powerSmoothed, err = s.TotalPowerSmoothed(); err != nil {
669+
return xerrors.Errorf("failed to determine total power: %w", err)
670+
}
671+
672+
nv, err := api.StateNetworkVersion(ctx, ts.Key())
673+
if err != nil {
674+
return xerrors.Errorf("getting network version: %w", err)
675+
}
676+
677+
rew, err := minertypes.ExpectedRewardForPower(nv, rewardSmoothed, powerSmoothed, qapower, projectionPeriod)
678+
if err != nil {
679+
return xerrors.Errorf("calculating expected reward: %w", err)
680+
}
681+
_, _ = fmt.Fprintf(
682+
cctx.App.Writer,
683+
"Expected reward for %s bytes of QA power @ epoch %d for %d epochs: %s attoFIL\n",
684+
qapower,
685+
ts.Height(),
686+
projectionPeriod,
687+
rew,
688+
)
689+
return nil
690+
},
691+
}

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)