Skip to content

Commit

Permalink
feat(shed): lotus-shed miner locked-vested to find erroneously locked…
Browse files Browse the repository at this point in the history
  • Loading branch information
rvagg committed Jan 14, 2025
1 parent b83bf69 commit 09b9e6e
Showing 1 changed file with 88 additions and 0 deletions.
88 changes: 88 additions & 0 deletions cmd/lotus-shed/miner.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ import (
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/builtin"
"github.com/filecoin-project/go-state-types/builtin/v11/util/adt"
miner15 "github.com/filecoin-project/go-state-types/builtin/v15/miner"
miner8 "github.com/filecoin-project/go-state-types/builtin/v8/miner"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/manifest"
power7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/power"
"github.com/filecoin-project/specs-actors/v7/actors/runtime/proof"

Expand All @@ -36,6 +38,7 @@ import (
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types"
lcli "github.com/filecoin-project/lotus/cli"
)
Expand All @@ -50,6 +53,7 @@ var minerCmd = &cli.Command{
sendInvalidWindowPoStCmd,
generateAndSendConsensusFaultCmd,
sectorInfoCmd,
minerLockedVestedCmd,
},
}

Expand Down Expand Up @@ -688,3 +692,87 @@ var generateAndSendConsensusFaultCmd = &cli.Command{
return nil
},
}

// TODO: LoadVestingFunds isn't exposed on the miner wrappers in Lotus so we have to go decoding the
// miner state manually. This command will continue to work as long as the hard-coded go-state-types
// miner version matches the schema of the current miner actor. It will need to be updated if the
// miner actor schema changes; or we could expose LoadVestingFunds.
var minerLockedVestedCmd = &cli.Command{
Name: "locked-vested",
Usage: "Search through all miners for VestingFunds that are still locked even though the epoch has passed",
Action: func(cctx *cli.Context) error {
n, acloser, err := lcli.GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer acloser()
ctx := lcli.ReqContext(cctx)

bs := ReadOnlyAPIBlockstore{n}
adtStore := adt.WrapStore(ctx, ipldcbor.NewCborStore(&bs))

head, err := n.ChainHead(ctx)
if err != nil {
return err
}

tree, err := state.LoadStateTree(adtStore, head.ParentState())
if err != nil {
return err
}
nv, err := n.StateNetworkVersion(ctx, head.Key())
if err != nil {
return err
}
actorCodeCids, err := n.StateActorCodeCIDs(ctx, nv)
if err != nil {
return err
}
minerCode := actorCodeCids[manifest.MinerKey]

var totalCount int
var totalMiners int
var lockedCount int
var lockedFunds abi.TokenAmount = big.Zero()
fmt.Printf("Scanning actors (looking for v%d miners [%s] at epoch %d)", nv, minerCode, head.Height())
err = tree.ForEach(func(addr address.Address, act *types.Actor) error {
totalCount++
if totalCount%10000 == 0 {
fmt.Printf(".")
}
if act.Code == minerCode {
totalMiners++
m15 := miner15.State{}
if err := adtStore.Get(ctx, act.Head, &m15); err != nil {
return xerrors.Errorf("failed to load miner state (using miner15, try a newer version?): %w", err)
}
vf, err := m15.LoadVestingFunds(adtStore)
if err != nil {
return err
}
var locked bool
for _, f := range vf.Funds {
if f.Epoch < head.Height() {
lockedFunds = big.Add(lockedFunds, f.Amount)
locked = true
}
}
if locked {
lockedCount++
}
}
return nil
})
if err != nil {
return xerrors.Errorf("failed to loop over actors: %w", err)
}

fmt.Println()
fmt.Printf("Total actors: %d\n", totalCount)
fmt.Printf("Total miners: %d\n", totalMiners)
fmt.Printf("Miners with locked funds: %d\n", lockedCount)
fmt.Printf("Total locked funds: %s\n", types.FIL(lockedFunds))

return nil
},
}

0 comments on commit 09b9e6e

Please sign in to comment.