tvx exec: flag to fallback to API blockstore.

This commit is contained in:
Raúl Kripalani 2020-12-15 17:44:56 +00:00
parent 3fa51f08e1
commit 2af1283c65
3 changed files with 44 additions and 8 deletions

View File

@ -17,6 +17,7 @@ import (
var execFlags struct { var execFlags struct {
file string file string
fallbackBlockstore bool
} }
var execCmd = &cli.Command{ var execCmd = &cli.Command{
@ -30,10 +31,23 @@ var execCmd = &cli.Command{
TakesFile: true, TakesFile: true,
Destination: &execFlags.file, Destination: &execFlags.file,
}, },
&cli.BoolFlag{
Name: "fallback-blockstore",
Usage: "sets the full node API as a fallback blockstore; use this if you're transplanting vectors and get block not found errors",
Destination: &execFlags.fallbackBlockstore,
},
}, },
} }
func runExecLotus(_ *cli.Context) error { func runExecLotus(c *cli.Context) error {
if execFlags.fallbackBlockstore {
if err := initialize(c); err != nil {
return fmt.Errorf("fallback blockstore was enabled, but could not resolve lotus API endpoint: %w", err)
}
defer destroy(c) //nolint:errcheck
conformance.FallbackBlockstoreGetter = FullAPI
}
if file := execFlags.file; file != "" { if file := execFlags.file; file != "" {
// we have a single test vector supplied as a file. // we have a single test vector supplied as a file.
file, err := os.Open(file) file, err := os.Open(file)

View File

@ -102,7 +102,7 @@ func initialize(c *cli.Context) error {
// Make the API client. // Make the API client.
var err error var err error
if FullAPI, Closer, err = lcli.GetFullNodeAPI(c); err != nil { if FullAPI, Closer, err = lcli.GetFullNodeAPI(c); err != nil {
err = fmt.Errorf("failed to locate Lotus node; ") err = fmt.Errorf("failed to locate Lotus node; err: %w", err)
} }
return err return err
} }

View File

@ -14,6 +14,7 @@ import (
"github.com/fatih/color" "github.com/fatih/color"
"github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/go-state-types/exitcode"
blocks "github.com/ipfs/go-block-format"
"github.com/ipfs/go-blockservice" "github.com/ipfs/go-blockservice"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
ds "github.com/ipfs/go-datastore" ds "github.com/ipfs/go-datastore"
@ -29,6 +30,14 @@ import (
"github.com/filecoin-project/lotus/lib/blockstore" "github.com/filecoin-project/lotus/lib/blockstore"
) )
// FallbackBlockstoreGetter is a fallback blockstore to use for resolving CIDs
// unknown to the test vector. This is rarely used, usually only needed
// when transplanting vectors across versions. This is an interface tighter
// than ChainModuleAPI. It can be backed by a FullAPI client.
var FallbackBlockstoreGetter interface {
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
}
// ExecuteMessageVector executes a message-class test vector. // ExecuteMessageVector executes a message-class test vector.
func ExecuteMessageVector(r Reporter, vector *schema.TestVector, variant *schema.Variant) { func ExecuteMessageVector(r Reporter, vector *schema.TestVector, variant *schema.Variant) {
var ( var (
@ -38,7 +47,7 @@ func ExecuteMessageVector(r Reporter, vector *schema.TestVector, variant *schema
) )
// Load the CAR into a new temporary Blockstore. // Load the CAR into a new temporary Blockstore.
bs, err := LoadVectorCAR(vector.CAR) bs, err := LoadBlockstore(vector.CAR)
if err != nil { if err != nil {
r.Fatalf("failed to load the vector CAR: %w", err) r.Fatalf("failed to load the vector CAR: %w", err)
} }
@ -95,7 +104,7 @@ func ExecuteTipsetVector(r Reporter, vector *schema.TestVector, variant *schema.
) )
// Load the vector CAR into a new temporary Blockstore. // Load the vector CAR into a new temporary Blockstore.
bs, err := LoadVectorCAR(vector.CAR) bs, err := LoadBlockstore(vector.CAR)
if err != nil { if err != nil {
r.Fatalf("failed to load the vector CAR: %w", err) r.Fatalf("failed to load the vector CAR: %w", err)
} }
@ -117,7 +126,7 @@ func ExecuteTipsetVector(r Reporter, vector *schema.TestVector, variant *schema.
Rand: NewReplayingRand(r, vector.Randomness), Rand: NewReplayingRand(r, vector.Randomness),
}) })
if err != nil { if err != nil {
r.Fatalf("failed to apply tipset %d message: %s", i, err) r.Fatalf("failed to apply tipset %d: %s", i, err)
} }
for j, v := range ret.AppliedResults { for j, v := range ret.AppliedResults {
@ -254,8 +263,8 @@ func writeStateToTempCAR(bs blockstore.Blockstore, roots ...cid.Cid) (string, er
return tmp.Name(), nil return tmp.Name(), nil
} }
func LoadVectorCAR(vectorCAR schema.Base64EncodedBytes) (blockstore.Blockstore, error) { func LoadBlockstore(vectorCAR schema.Base64EncodedBytes) (blockstore.Blockstore, error) {
bs := blockstore.NewTemporary() bs := blockstore.Blockstore(blockstore.NewTemporary())
// Read the base64-encoded CAR from the vector, and inflate the gzip. // Read the base64-encoded CAR from the vector, and inflate the gzip.
buf := bytes.NewReader(vectorCAR) buf := bytes.NewReader(vectorCAR)
@ -270,5 +279,18 @@ func LoadVectorCAR(vectorCAR schema.Base64EncodedBytes) (blockstore.Blockstore,
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to load state tree car from test vector: %s", err) return nil, fmt.Errorf("failed to load state tree car from test vector: %s", err)
} }
if FallbackBlockstoreGetter != nil {
fbs := &blockstore.FallbackStore{Blockstore: bs}
fbs.SetFallback(func(ctx context.Context, c cid.Cid) (blocks.Block, error) {
b, err := FallbackBlockstoreGetter.ChainReadObj(ctx, c)
if err != nil {
return nil, err
}
return blocks.NewBlockWithCid(b, c)
})
bs = fbs
}
return bs, nil return bs, nil
} }