2020-09-27 19:10:05 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2020-10-23 12:30:04 +00:00
|
|
|
"fmt"
|
2020-09-27 19:10:05 +00:00
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
"sort"
|
|
|
|
|
|
|
|
"github.com/urfave/cli/v2"
|
2020-10-21 09:58:07 +00:00
|
|
|
|
2022-06-14 15:00:51 +00:00
|
|
|
"github.com/filecoin-project/go-jsonrpc"
|
|
|
|
|
2023-09-21 15:37:02 +00:00
|
|
|
"github.com/filecoin-project/lotus/api/v1api"
|
2020-10-21 09:58:07 +00:00
|
|
|
lcli "github.com/filecoin-project/lotus/cli"
|
2020-09-27 19:10:05 +00:00
|
|
|
)
|
|
|
|
|
2020-10-21 09:58:07 +00:00
|
|
|
// FullAPI is a JSON-RPC client targeting a full node. It's initialized in a
|
|
|
|
// cli.BeforeFunc.
|
2023-09-21 15:37:02 +00:00
|
|
|
var FullAPI v1api.FullNode
|
2020-10-21 09:58:07 +00:00
|
|
|
|
|
|
|
// Closer is the closer for the JSON-RPC client, which must be called on
|
|
|
|
// cli.AfterFunc.
|
|
|
|
var Closer jsonrpc.ClientCloser
|
|
|
|
|
2020-09-28 11:35:01 +00:00
|
|
|
// DefaultLotusRepoPath is where the fallback path where to look for a Lotus
|
|
|
|
// client repo. It is expanded with mitchellh/go-homedir, so it'll work with all
|
|
|
|
// OSes despite the Unix twiddle notation.
|
|
|
|
const DefaultLotusRepoPath = "~/.lotus"
|
|
|
|
|
|
|
|
var repoFlag = cli.StringFlag{
|
|
|
|
Name: "repo",
|
|
|
|
EnvVars: []string{"LOTUS_PATH"},
|
|
|
|
Value: DefaultLotusRepoPath,
|
|
|
|
TakesFile: true,
|
|
|
|
}
|
|
|
|
|
2020-09-27 19:10:05 +00:00
|
|
|
func main() {
|
|
|
|
app := &cli.App{
|
|
|
|
Name: "tvx",
|
2020-10-21 09:58:07 +00:00
|
|
|
Description: `tvx is a tool for extracting and executing test vectors. It has four subcommands.
|
2020-09-27 19:10:05 +00:00
|
|
|
|
|
|
|
tvx extract extracts a test vector from a live network. It requires access to
|
2020-09-28 11:27:42 +00:00
|
|
|
a Filecoin client that exposes the standard JSON-RPC API endpoint. Only
|
|
|
|
message class test vectors are supported at this time.
|
2020-09-27 19:10:05 +00:00
|
|
|
|
|
|
|
tvx exec executes test vectors against Lotus. Either you can supply one in a
|
2020-09-28 11:27:42 +00:00
|
|
|
file, or many as an ndjson stdin stream.
|
|
|
|
|
2020-09-28 16:02:56 +00:00
|
|
|
tvx extract-many performs a batch extraction of many messages, supplied in a
|
|
|
|
CSV file. Refer to the help of that subcommand for more info.
|
|
|
|
|
2020-10-21 09:58:07 +00:00
|
|
|
tvx simulate takes a raw message and simulates it on top of the supplied
|
|
|
|
epoch, reporting the result on stderr and writing a test vector on stdout
|
|
|
|
or into the specified file.
|
|
|
|
|
2020-09-28 11:27:42 +00:00
|
|
|
SETTING THE JSON-RPC API ENDPOINT
|
|
|
|
|
2020-09-28 11:35:01 +00:00
|
|
|
You can set the JSON-RPC API endpoint through one of the following methods.
|
2020-09-28 11:27:42 +00:00
|
|
|
|
|
|
|
1. Directly set the API endpoint on the FULLNODE_API_INFO env variable.
|
|
|
|
The format is [token]:multiaddr, where token is optional for commands not
|
|
|
|
accessing privileged operations.
|
|
|
|
|
|
|
|
2. If you're running tvx against a local Lotus client, you can set the REPO
|
|
|
|
env variable to have the API endpoint and token extracted from the repo.
|
2020-09-28 11:35:01 +00:00
|
|
|
Alternatively, you can pass the --repo CLI flag.
|
2020-09-28 11:27:42 +00:00
|
|
|
|
|
|
|
3. Rely on the default fallback, which inspects ~/.lotus and extracts the
|
|
|
|
API endpoint string if the location is a Lotus repo.
|
|
|
|
|
2020-09-28 11:35:01 +00:00
|
|
|
tvx will apply these methods in the same order of precedence they're listed.
|
2020-09-28 11:27:42 +00:00
|
|
|
`,
|
2020-09-27 19:10:05 +00:00
|
|
|
Usage: "tvx is a tool for extracting and executing test vectors",
|
|
|
|
Commands: []*cli.Command{
|
|
|
|
extractCmd,
|
|
|
|
execCmd,
|
2020-09-28 16:02:56 +00:00
|
|
|
extractManyCmd,
|
2020-10-21 09:58:07 +00:00
|
|
|
simulateCmd,
|
2020-09-27 19:10:05 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
sort.Sort(cli.CommandsByName(app.Commands))
|
|
|
|
for _, c := range app.Commands {
|
|
|
|
sort.Sort(cli.FlagsByName(c.Flags))
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := app.Run(os.Args); err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
2020-10-21 09:58:07 +00:00
|
|
|
|
|
|
|
func initialize(c *cli.Context) error {
|
|
|
|
// LOTUS_DISABLE_VM_BUF disables what's called "VM state tree buffering",
|
|
|
|
// which stashes write operations in a BufferedBlockstore
|
|
|
|
// (https://github.com/filecoin-project/lotus/blob/b7a4dbb07fd8332b4492313a617e3458f8003b2a/lib/bufbstore/buf_bstore.go#L21)
|
|
|
|
// such that they're not written until the VM is actually flushed.
|
|
|
|
//
|
|
|
|
// For some reason, the standard behaviour was not working for me (raulk),
|
|
|
|
// and disabling it (such that the state transformations are written immediately
|
|
|
|
// to the blockstore) worked.
|
|
|
|
_ = os.Setenv("LOTUS_DISABLE_VM_BUF", "iknowitsabadidea")
|
|
|
|
|
|
|
|
// Make the API client.
|
|
|
|
var err error
|
2023-09-21 15:37:02 +00:00
|
|
|
if FullAPI, Closer, err = lcli.GetFullNodeAPIV1(c); err != nil {
|
2020-12-15 17:44:56 +00:00
|
|
|
err = fmt.Errorf("failed to locate Lotus node; err: %w", err)
|
2020-10-23 12:30:04 +00:00
|
|
|
}
|
2020-10-21 09:58:07 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func destroy(_ *cli.Context) error {
|
|
|
|
if Closer != nil {
|
|
|
|
Closer()
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2020-12-16 21:40:37 +00:00
|
|
|
|
|
|
|
func ensureDir(path string) error {
|
|
|
|
switch fi, err := os.Stat(path); {
|
|
|
|
case os.IsNotExist(err):
|
|
|
|
if err := os.MkdirAll(path, 0755); err != nil {
|
|
|
|
return fmt.Errorf("failed to create directory %s: %w", path, err)
|
|
|
|
}
|
|
|
|
case err == nil:
|
|
|
|
if !fi.IsDir() {
|
|
|
|
return fmt.Errorf("path %s is not a directory: %w", path, err)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return fmt.Errorf("failed to stat directory %s: %w", path, err)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|