Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(shed): check command for FIP-0081 pledge calculation #12713

Merged
merged 1 commit into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
342 changes: 341 additions & 1 deletion cmd/lotus-shed/balances.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,14 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"

miner14 "github.com/filecoin-project/go-state-types/builtin/v14/miner"
smoothing14 "github.com/filecoin-project/go-state-types/builtin/v14/util/smoothing"
miner15 "github.com/filecoin-project/go-state-types/builtin/v15/miner"
smoothing15 "github.com/filecoin-project/go-state-types/builtin/v15/util/smoothing"
gststore "github.com/filecoin-project/go-state-types/store"

"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/blockstore"
"github.com/filecoin-project/lotus/build/buildconstants"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
Expand Down Expand Up @@ -69,6 +76,7 @@ var auditsCmd = &cli.Command{
chainBalanceSanityCheckCmd,
chainBalanceStateCmd,
chainPledgeCmd,
chainFip0081PledgeCmd,
fillBalancesCmd,
duplicatedMessagesCmd,
},
Expand Down Expand Up @@ -941,3 +949,335 @@ var fillBalancesCmd = &cli.Command{
return nil
},
}

var chainFip0081PledgeCmd = &cli.Command{
Name: "fip0081-pledge",
Description: "Calculate sector pledge values comparing current to pre-FIP-0081",
ArgsUsage: "[epoch number]",
Action: func(cctx *cli.Context) error {

ctx := lcli.ReqContext(cctx)

api, acloser, err := lcli.GetFullNodeAPIV1(cctx)
if err != nil {
return err
}
defer acloser()

var ts *types.TipSet
if cctx.Args().Present() {
epoch, err := strconv.ParseInt(cctx.Args().First(), 10, 64)
if err != nil {
return xerrors.Errorf("parsing epoch arg: %w", err)
}
ts, err = api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(epoch), types.EmptyTSK)
if err != nil {
return err
}
} else {
ts, err = api.ChainHead(ctx)
if err != nil {
return err
}
}

cases := []struct {
sectorSize abi.SectorSize
verifiedSize uint64
duration abi.ChainEpoch
rvagg marked this conversation as resolved.
Show resolved Hide resolved
}{
{
sectorSize: 2 << 10,
verifiedSize: 2 << 10,
duration: builtin.EpochsInYear,
},
{
sectorSize: 2 << 10,
verifiedSize: (2 << 10) / 2,
duration: builtin.EpochsInYear,
},
{
sectorSize: 2 << 10,
verifiedSize: 0,
duration: builtin.EpochsInYear,
},
{
sectorSize: 2 << 10,
verifiedSize: 2 << 10,
duration: 3 * builtin.EpochsInYear,
},
{
sectorSize: 2 << 10,
verifiedSize: (2 << 10) / 2,
duration: 3 * builtin.EpochsInYear,
},
{
sectorSize: 2 << 10,
verifiedSize: 0,
duration: 3 * builtin.EpochsInYear,
},
{
sectorSize: 32 << 30,
verifiedSize: 32 << 30,
duration: builtin.EpochsInYear,
},
{
sectorSize: 32 << 30,
verifiedSize: (32 << 30) / 2,
duration: builtin.EpochsInYear,
},
{
sectorSize: 32 << 30,
verifiedSize: 0,
duration: builtin.EpochsInYear,
},
{
sectorSize: 32 << 30,
verifiedSize: 32 << 30,
duration: 3 * builtin.EpochsInYear,
},
{
sectorSize: 32 << 30,
verifiedSize: (32 << 30) / 2,
duration: 3 * builtin.EpochsInYear,
},
{
sectorSize: 32 << 30,
verifiedSize: 0,
duration: 3 * builtin.EpochsInYear,
},
{
sectorSize: 64 << 30,
verifiedSize: 64 << 30,
duration: builtin.EpochsInYear,
},
{
sectorSize: 64 << 30,
verifiedSize: (64 << 30) / 2,
duration: builtin.EpochsInYear,
},
{
sectorSize: 64 << 30,
verifiedSize: 0,
duration: builtin.EpochsInYear,
},
{
sectorSize: 64 << 30,
verifiedSize: 64 << 30,
duration: 3 * builtin.EpochsInYear,
},
{
sectorSize: 64 << 30,
verifiedSize: (64 << 30) / 2,
duration: 3 * builtin.EpochsInYear,
},
{
sectorSize: 64 << 30,
verifiedSize: 0,
duration: 3 * builtin.EpochsInYear,
},
}

fmt.Printf("\033[3mCalculating at epoch %d\033[0m\n", ts.Height())
fmt.Printf(" \033[1mSector Size\033[0m | \033[1mVerified %%\033[0m | \033[1mDuration\033[0m | \033[1mActual\033[0m | \033[1mPre-FIP-0081\033[0m | \033[1mDifference\033[0m\n")
fmt.Println(strings.Repeat("-", 119))

for _, c := range cases {
pledge, err := api.StateMinerInitialPledgeForSector(ctx, c.duration, c.sectorSize, c.verifiedSize, ts.Key())
if err != nil {
return err
}
newPledge, err := postFip0081StateMinerInitialPledgeForSector(ctx, api, c.duration, c.sectorSize, c.verifiedSize, ts)
if err != nil {
return err
}
if !pledge.Equals(newPledge) {
return xerrors.Errorf("failed to sanity check StateMinerInitialPledgeForSector calculation!")
}
oldPledge, err := preFip0081StateMinerInitialPledgeForSector(ctx, api, c.duration, c.sectorSize, c.verifiedSize, ts)
if err != nil {
return err
}

fmt.Printf(" %-11s | % 4.f%% | %0.f year(s) | %-24s | %-24s | %s\n",
c.sectorSize.ShortString(),
float64(c.verifiedSize)/float64(c.sectorSize)*100,
float64(c.duration)/builtin.EpochsInYear,
types.FIL(pledge).String(),
types.FIL(oldPledge).String(),
types.FIL(types.BigSub(pledge, oldPledge)).String(),
)
}
fmt.Println(strings.Repeat("-", 119))

return nil
},
}

// from itests/migration_test.go

// preFip0081StateMinerInitialPledgeForSector is the same calculation as StateMinerInitialPledgeForSector
// but uses miner14's version of the calculation without the FIP-0081 changes.
func preFip0081StateMinerInitialPledgeForSector(
ctx context.Context,
client api.FullNode,
sectorDuration abi.ChainEpoch,
sectorSize abi.SectorSize,
verifiedSize uint64,
ts *types.TipSet,
) (types.BigInt, error) {
bs := blockstore.NewAPIBlockstore(client)
ctxStore := gststore.WrapBlockStore(ctx, bs)

circSupply, err := client.StateVMCirculatingSupplyInternal(ctx, ts.Key())
if err != nil {
return types.NewInt(0), err
}

powerActor, err := client.StateGetActor(ctx, power.Address, ts.Key())
if err != nil {
return types.NewInt(0), err
}

powerState, err := power.Load(ctxStore, powerActor)
if err != nil {
return types.NewInt(0), err
}

rewardActor, err := client.StateGetActor(ctx, reward.Address, ts.Key())
if err != nil {
return types.NewInt(0), err
}

rewardState, err := reward.Load(ctxStore, rewardActor)
if err != nil {
return types.NewInt(0), err
}

networkQAPower, err := powerState.TotalPowerSmoothed()
if err != nil {
return types.NewInt(0), err
}

verifiedWeight := big.Mul(big.NewIntUnsigned(verifiedSize), big.NewInt(int64(sectorDuration)))
sectorWeight := builtin.QAPowerForWeight(sectorSize, sectorDuration, verifiedWeight)

thisEpochBaselinePower, err := rewardState.(interface {
ThisEpochBaselinePower() (abi.StoragePower, error)
}).ThisEpochBaselinePower()
if err != nil {
return types.NewInt(0), err
}
thisEpochRewardSmoothed, err := rewardState.(interface {
ThisEpochRewardSmoothed() (builtin.FilterEstimate, error)
}).ThisEpochRewardSmoothed()
if err != nil {
return types.NewInt(0), err
}

rewardEstimate := smoothing14.FilterEstimate{
PositionEstimate: thisEpochRewardSmoothed.PositionEstimate,
VelocityEstimate: thisEpochRewardSmoothed.VelocityEstimate,
}
networkQAPowerEstimate := smoothing14.FilterEstimate{
PositionEstimate: networkQAPower.PositionEstimate,
VelocityEstimate: networkQAPower.VelocityEstimate,
}

initialPledge := miner14.InitialPledgeForPower(
sectorWeight,
thisEpochBaselinePower,
rewardEstimate,
networkQAPowerEstimate,
circSupply.FilCirculating,
)

var initialPledgeNum = types.NewInt(110)
var initialPledgeDen = types.NewInt(100)

return types.BigDiv(types.BigMul(initialPledge, initialPledgeNum), initialPledgeDen), nil
}

// postFip0081StateMinerInitialPledgeForSector should be the same calculation as StateMinerInitialPledgeForSector,
// it's here for sanity checking.
func postFip0081StateMinerInitialPledgeForSector(
rvagg marked this conversation as resolved.
Show resolved Hide resolved
ctx context.Context,
client api.FullNode,
sectorDuration abi.ChainEpoch,
sectorSize abi.SectorSize,
verifiedSize uint64,
ts *types.TipSet,
) (types.BigInt, error) {
bs := blockstore.NewAPIBlockstore(client)
ctxStore := gststore.WrapBlockStore(ctx, bs)

circSupply, err := client.StateVMCirculatingSupplyInternal(ctx, ts.Key())
if err != nil {
return types.NewInt(0), err
}

powerActor, err := client.StateGetActor(ctx, power.Address, ts.Key())
if err != nil {
return types.NewInt(0), err
}

powerState, err := power.Load(ctxStore, powerActor)
if err != nil {
return types.NewInt(0), err
}

rewardActor, err := client.StateGetActor(ctx, reward.Address, ts.Key())
if err != nil {
return types.NewInt(0), err
}

rewardState, err := reward.Load(ctxStore, rewardActor)
if err != nil {
return types.NewInt(0), err
}

networkQAPower, err := powerState.TotalPowerSmoothed()
if err != nil {
return types.NewInt(0), err
}

verifiedWeight := big.Mul(big.NewIntUnsigned(verifiedSize), big.NewInt(int64(sectorDuration)))
sectorWeight := builtin.QAPowerForWeight(sectorSize, sectorDuration, verifiedWeight)

thisEpochBaselinePower, err := rewardState.(interface {
ThisEpochBaselinePower() (abi.StoragePower, error)
}).ThisEpochBaselinePower()
if err != nil {
return types.NewInt(0), err
}
thisEpochRewardSmoothed, err := rewardState.(interface {
ThisEpochRewardSmoothed() (builtin.FilterEstimate, error)
}).ThisEpochRewardSmoothed()
if err != nil {
return types.NewInt(0), err
}

rewardEstimate := smoothing15.FilterEstimate{
PositionEstimate: thisEpochRewardSmoothed.PositionEstimate,
VelocityEstimate: thisEpochRewardSmoothed.VelocityEstimate,
}
networkQAPowerEstimate := smoothing15.FilterEstimate{
PositionEstimate: networkQAPower.PositionEstimate,
VelocityEstimate: networkQAPower.VelocityEstimate,
}

initialPledge := miner15.InitialPledgeForPower(
sectorWeight,
thisEpochBaselinePower,
rewardEstimate,
networkQAPowerEstimate,
circSupply.FilCirculating,
int64(ts.Height())-powerState.RampStartEpoch(),
powerState.RampDurationEpochs(),
)

var initialPledgeNum = types.NewInt(110)
var initialPledgeDen = types.NewInt(100)

return types.BigDiv(types.BigMul(initialPledge, initialPledgeNum), initialPledgeDen), nil
}
5 changes: 2 additions & 3 deletions itests/migration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1140,14 +1140,13 @@ func preFip0081StateMinerInitialPledgeForSector(ctx context.Context, t *testing.
VelocityEstimate: networkQAPower.VelocityEstimate,
}

initialPledge, err := miner14.InitialPledgeForPower(
initialPledge := miner14.InitialPledgeForPower(
sectorWeight,
thisEpochBaselinePower,
rewardEstimate,
networkQAPowerEstimate,
circSupply.FilCirculating,
), nil
req.NoError(err)
)

var initialPledgeNum = types.NewInt(110)
var initialPledgeDen = types.NewInt(100)
Expand Down
Loading