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

tvx: a test vector extraction and execution tool #4064

Merged
merged 20 commits into from
Sep 30, 2020
Merged

tvx: a test vector extraction and execution tool #4064

merged 20 commits into from
Sep 30, 2020

Conversation

raulk
Copy link
Member

@raulk raulk commented Sep 27, 2020

This PR contributes tvx, a test vector extraction and execution tool.

The tvx binary supports two subcommands.

tvx extract --cid <message id>

Extracts a message-class test vector from a live chain/network, using the JSON-RPC API pointed at by the API info env variable (FULLNODE_API_INFO=token:multiaddr), or the --api flag.

It does the following:

  1. Locates the message on chain (if the message is old, Lotus takes ages, so if you're testing this, use a recent message; Lotus needs better indexing).
  2. Retrieves the inclusion and execution tipsets.
  3. Finds any precursor messages in the same block (messages sent by the same actor with a lower nonce). If there are such messages, we can't take the previous tipset's state as the base state; instead we need to cherry-pick apply precursor messages first.
  4. Applies the message on top of the base state, turning on blockstore tracing. This records the CIDs that were effectively accessed during the execution of the transaction.
  5. Prunes the state tree encoded in the test vector's CAR by only retaining the effectively accessed CIDs and ignoring any others.
    • This deliberately causes dangling links, but it is non harmful.
    • If the actor code changed in a way that it started accessing more CIDs, the gas costs would change, which would invalidate the test vector anyway.
    • So trimming down the state tree this way is a pretty safe bet.
    • If it does break, we can always regenerate from chain history.
  6. Writes out the test vector to a file (if -o <file> was specified), or to stdout.

tvx uses a special "proxying" blockstore, which fetches objects from a remote node via JSON-RPC ChainReadObj.

Try:

$ env FULLNODE_API_INFO="token:multiaddr" tvx extract --cid bafy2bzaced3gxdknd5zuxcglnyec3hwe4tom3nmunt5neaglybxurclgkkr6e -o vector.json

(^^ depending on when you run this, it can be extremely slow to locate the message, due to Lotus' lack of indices; substitute the CID with a fresher one).

tvx exec --file <path>

Executes a single vector against Lotus. It's super fast, so if you don't believe it, mangle the vector (e.g. change the postcondition state root, the gas cost in the receipt, the exit code, etc.) and notice how it fails.

Try:

$ tvx exec --file vector.json

These tools were incubated in the Oni repo (https://github.com/filecoin-project/oni/), and heavily refactored before submitting here. Thanks @willscott and @nonsense for past contributions!

@raulk raulk changed the title move conformance tvx tool to lotus. tvx: a test vector extraction and execution tool Sep 27, 2020
@raulk raulk marked this pull request as draft September 27, 2020 19:32
cmd/tvx/main.go Outdated Show resolved Hide resolved
}

// loadInitActor loads the init actor state from a given tipset.
func (sg *StateSurgeon) loadInitActor(st *state.StateTree) (*types.Actor, init_.State, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will this need to be interface'd to support versioning?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe, but honestly I don't think we'll end up using the accessed-actors ever. I just don't want to throw it away too quickly in case it comes in handy, but it's very inefficient and ultimately useless.

cmd/tvx/stores.go Show resolved Hide resolved
@raulk raulk marked this pull request as ready for review September 27, 2020 20:12
cmd/tvx/main.go Outdated
}
}

func makeAPIClient() (api.FullNode, jsonrpc.ClientCloser, error) {
Copy link
Contributor

@magik6k magik6k Sep 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should just use the methods from cli/:

  • Add a global repo flag to cli.App above:
			&cli.StringFlag{
				Name:    "repo",
				EnvVars: []string{"LOTUS_PATH"},
				Hidden:  true,
				Value:   "~/.lotus",
			},
  • In any commands which need the API:
lcli "github.com/filecoin-project/lotus/cli"
...
		api, closer, err := lcli.GetFullNodeAPI(cctx)
		if err != nil {
			return err
		}

		defer closer()
		ctx := lcli.ReqContext(cctx)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can add this, which can be useful if you're running the binary from the same machine as the client, that is not my case, for example ;-)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caught up with @magik6k 1:1. I've dropped the --api flag (now only an env var), and added the --repo flag and env variable binding. We now use the lotus CLI lib, and the usage docs on the command document how the API endpoint is resolved.

@raulk
Copy link
Member Author

raulk commented Sep 28, 2020

@magik6k this is ready to merge. The test failure looks like an unrelated, flaky test!

@Kubuxu
Copy link
Contributor

Kubuxu commented Sep 28, 2020

Any concrete reason for placing it in separate command instead of lotus-shed?

@raulk
Copy link
Member Author

raulk commented Sep 28, 2020

@Kubuxu no concrete reason other than lotus-shed appearing to be a miscellaneous/catch-all/utilities location. This binary doesn't seem to fall in that category. It will become a pretty important tool in our testing workflow going forward, and will also be used by other implementers. Also, I want to be the code owner of this, and no other lotus-shed gadget ;-)

// ChainReadObj RPC.
func NewProxyingStores(ctx context.Context, api api.FullNode) *Stores {
ds := dssync.MutexWrap(ds.NewMapDatastore())
ds = dssync.MutexWrap(ds)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is twice as race safe.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to be super extra sure :D Thanks for catching this!

Comment on lines +14 to +23
builtin.InitActorCodeID: builtin.MethodsInit,
builtin.CronActorCodeID: builtin.MethodsCron,
builtin.AccountActorCodeID: builtin.MethodsAccount,
builtin.StoragePowerActorCodeID: builtin.MethodsPower,
builtin.StorageMinerActorCodeID: builtin.MethodsMiner,
builtin.StorageMarketActorCodeID: builtin.MethodsMarket,
builtin.PaymentChannelActorCodeID: builtin.MethodsPaych,
builtin.MultisigActorCodeID: builtin.MethodsMultisig,
builtin.RewardActorCodeID: builtin.MethodsReward,
builtin.VerifiedRegistryActorCodeID: builtin.MethodsVerifiedRegistry,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With #3936 there are multiple code CIDs depending on actor version.

Ideally we would deduplicate this with the registry in chain/vm/invoker.go

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think there's anything I can do right now. When that PR lands, we can enhance the invoker so that it can be introspected from the outside and return metadata about the actors/methods it knows about. For that to be usable here, we'd need to record the method name too (probably just the name of the actor function).

"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/lib/blockstore"

"github.com/filecoin-project/specs-actors/actors/util/adt"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should use chain/actors/adt to handle network upgrades correctly

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved.

@magik6k magik6k merged commit 5bffea6 into master Sep 30, 2020
@magik6k magik6k deleted the tvx branch September 30, 2020 15:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants