Merge pull request #9521 from filecoin-project/gstuart/invariance-test

feat: shed: Add invariance tests for v9
This commit is contained in:
Geoff Stuart 2022-11-02 12:28:54 +00:00 committed by GitHub
commit c1e1d00d0e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 153 additions and 9 deletions

View File

@ -0,0 +1,142 @@
package main
import (
"context"
"fmt"
"io"
"strconv"
"time"
"github.com/ipfs/go-cid"
"github.com/urfave/cli/v2"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/abi"
actorstypes "github.com/filecoin-project/go-state-types/actors"
"github.com/filecoin-project/go-state-types/builtin"
v8 "github.com/filecoin-project/go-state-types/builtin/v8"
v9 "github.com/filecoin-project/go-state-types/builtin/v9"
"github.com/filecoin-project/lotus/blockstore"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/consensus/filcns"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
lcli "github.com/filecoin-project/lotus/cli"
"github.com/filecoin-project/lotus/node/repo"
"github.com/filecoin-project/lotus/storage/sealer/ffiwrapper"
)
var invariantsCmd = &cli.Command{
Name: "check-invariants",
Description: "Check state invariants",
ArgsUsage: "[StateRootCid, height]",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "repo",
Value: "~/.lotus",
},
},
Action: func(cctx *cli.Context) error {
ctx := context.TODO()
if cctx.NArg() != 2 {
return lcli.IncorrectNumArgs(cctx)
}
stateRootCid, err := cid.Decode(cctx.Args().Get(0))
if err != nil {
return fmt.Errorf("failed to parse state root cid: %w", err)
}
epoch, err := strconv.ParseInt(cctx.Args().Get(1), 10, 64)
if err != nil {
return fmt.Errorf("failed to parse epoch: %w", err)
}
fsrepo, err := repo.NewFS(cctx.String("repo"))
if err != nil {
return err
}
lkrepo, err := fsrepo.Lock(repo.FullNode)
if err != nil {
return err
}
defer lkrepo.Close() //nolint:errcheck
bs, err := lkrepo.Blockstore(ctx, repo.UniversalBlockstore)
if err != nil {
return fmt.Errorf("failed to open blockstore: %w", err)
}
defer func() {
if c, ok := bs.(io.Closer); ok {
if err := c.Close(); err != nil {
log.Warnf("failed to close blockstore: %s", err)
}
}
}()
mds, err := lkrepo.Datastore(context.Background(), "/metadata")
if err != nil {
return err
}
cs := store.NewChainStore(bs, bs, mds, filcns.Weight, nil)
defer cs.Close() //nolint:errcheck
sm, err := stmgr.NewStateManager(cs, filcns.NewTipSetExecutor(), vm.Syscalls(ffiwrapper.ProofVerifier), filcns.DefaultUpgradeSchedule(), nil)
if err != nil {
return err
}
nv := sm.GetNetworkVersion(ctx, abi.ChainEpoch(epoch))
fmt.Println("Network Version ", nv)
av, err := actorstypes.VersionForNetwork(nv)
fmt.Println("Actors Version ", av)
actorCodeCids, err := actors.GetActorCodeIDs(av)
if err != nil {
return err
}
actorStore := store.ActorStore(ctx, blockstore.NewTieredBstore(bs, blockstore.NewMemorySync()))
// Load the state root.
var stateRoot types.StateRoot
if err := actorStore.Get(ctx, stateRootCid, &stateRoot); err != nil {
return xerrors.Errorf("failed to decode state root: %w", err)
}
actorTree, err := builtin.LoadTree(actorStore, stateRoot.Actors)
startTime := time.Now()
var messages *builtin.MessageAccumulator
switch av {
case actorstypes.Version8:
messages, err = v8.CheckStateInvariants(actorTree, abi.ChainEpoch(epoch), actorCodeCids)
if err != nil {
return xerrors.Errorf("checking state invariants: %w", err)
}
case actorstypes.Version9:
messages, err = v9.CheckStateInvariants(actorTree, abi.ChainEpoch(epoch), actorCodeCids)
if err != nil {
return xerrors.Errorf("checking state invariants: %w", err)
}
}
fmt.Println("completed, took ", time.Since(startTime))
for _, message := range messages.Messages() {
fmt.Println("got the following error: ", message)
}
return nil
},
}

View File

@ -73,6 +73,7 @@ func main() {
migrationsCmd,
diffCmd,
itestdCmd,
invariantsCmd,
}
app := &cli.App{

View File

@ -170,14 +170,15 @@ var migrationsCmd = &cli.Command{
newCid2)
}
fmt.Println("new cid", newCid2)
fmt.Println("migration height ", blk.Height-1)
fmt.Println("new cid ", newCid2)
fmt.Println("completed premigration 1, took ", preMigration1Time)
fmt.Println("completed premigration 2, took ", preMigration2Time)
fmt.Println("completed round actual (with cache), took ", cachedMigrationTime)
fmt.Println("completed round actual (without cache), took ", uncachedMigrationTime)
if cctx.Bool("check-invariants") {
err = checkMigrationInvariants(ctx, blk.ParentStateRoot, newCid1, bs, blk.Height-1)
err = checkMigrationInvariants(ctx, blk.ParentStateRoot, newCid2, bs, blk.Height-1)
if err != nil {
return err
}
@ -187,16 +188,16 @@ var migrationsCmd = &cli.Command{
},
}
func checkMigrationInvariants(ctx context.Context, v8StateRoot cid.Cid, v9StateRoot cid.Cid, bs blockstore.Blockstore, epoch abi.ChainEpoch) error {
func checkMigrationInvariants(ctx context.Context, v8StateRootCid cid.Cid, v9StateRootCid cid.Cid, bs blockstore.Blockstore, epoch abi.ChainEpoch) error {
actorStore := store.ActorStore(ctx, bs)
startTime := time.Now()
stateTreeV8, err := state.LoadStateTree(actorStore, v8StateRoot)
stateTreeV8, err := state.LoadStateTree(actorStore, v8StateRootCid)
if err != nil {
return err
}
stateTreeV9, err := state.LoadStateTree(actorStore, v9StateRoot)
stateTreeV9, err := state.LoadStateTree(actorStore, v9StateRootCid)
if err != nil {
return err
}
@ -217,8 +218,8 @@ func checkMigrationInvariants(ctx context.Context, v8StateRoot cid.Cid, v9StateR
}
// Load the state root.
var stateRoot types.StateRoot
if err := actorStore.Get(ctx, v9StateRoot, &stateRoot); err != nil {
var v9stateRoot types.StateRoot
if err := actorStore.Get(ctx, v9StateRootCid, &v9stateRoot); err != nil {
return xerrors.Errorf("failed to decode state root: %w", err)
}
@ -227,8 +228,8 @@ func checkMigrationInvariants(ctx context.Context, v8StateRoot cid.Cid, v9StateR
return err
}
actorTree, err := builtin.LoadTree(actorStore, stateRoot.Actors)
messages, err := v9.CheckStateInvariants(actorTree, epoch, actorCodeCids)
v9actorTree, err := builtin.LoadTree(actorStore, v9stateRoot.Actors)
messages, err := v9.CheckStateInvariants(v9actorTree, epoch, actorCodeCids)
if err != nil {
return xerrors.Errorf("checking state invariants: %w", err)
}