Skip to content

Commit

Permalink
Merge pull request #4393 from filecoin-project/vectors/support-multip…
Browse files Browse the repository at this point in the history
…le-versions

conformance: support multiple protocol versions.
  • Loading branch information
magik6k authored Oct 15, 2020
2 parents 90d2a92 + 1fb9ed1 commit 955d7f9
Show file tree
Hide file tree
Showing 10 changed files with 130 additions and 40 deletions.
37 changes: 37 additions & 0 deletions cmd/tvx/codenames.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package main

import (
"github.com/filecoin-project/go-state-types/abi"

"github.com/filecoin-project/lotus/build"
)

// ProtocolCodenames is a table that summarises the protocol codenames that
// will be set on extracted vectors, depending on the original execution height.
//
// Implementers rely on these names to filter the vectors they can run through
// their implementations, based on their support level
var ProtocolCodenames = []struct {
firstEpoch abi.ChainEpoch
name string
}{
{0, "genesis"},
{build.UpgradeBreezeHeight + 1, "breeze"},
{build.UpgradeSmokeHeight + 1, "smoke"},
{build.UpgradeIgnitionHeight + 1, "ignition"},
{build.UpgradeRefuelHeight + 1, "refuel"},
{build.UpgradeActorsV2Height + 1, "actorsv2"},
{build.UpgradeTapeHeight + 1, "tape"},
{build.UpgradeLiftoffHeight + 1, "liftoff"},
}

// GetProtocolCodename gets the protocol codename associated with a height.
func GetProtocolCodename(height abi.ChainEpoch) string {
for i, v := range ProtocolCodenames {
if height < v.firstEpoch {
// found the cutoff, return previous.
return ProtocolCodenames[i-1].name
}
}
return ProtocolCodenames[len(ProtocolCodenames)-1].name
}
28 changes: 28 additions & 0 deletions cmd/tvx/codenames_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package main

import (
"math"
"testing"

"github.com/filecoin-project/go-state-types/abi"

"github.com/filecoin-project/lotus/build"
)

func TestProtocolCodenames(t *testing.T) {
if height := abi.ChainEpoch(100); GetProtocolCodename(height) != "genesis" {
t.Fatal("expected genesis codename")
}

if height := abi.ChainEpoch(build.UpgradeBreezeHeight + 1); GetProtocolCodename(height) != "breeze" {
t.Fatal("expected breeze codename")
}

if height := build.UpgradeActorsV2Height + 1; GetProtocolCodename(height) != "actorsv2" {
t.Fatal("expected actorsv2 codename")
}

if height := abi.ChainEpoch(math.MaxInt64); GetProtocolCodename(height) != ProtocolCodenames[len(ProtocolCodenames)-1].name {
t.Fatal("expected last codename")
}
}
30 changes: 17 additions & 13 deletions cmd/tvx/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,20 +72,24 @@ func runExecLotus(_ *cli.Context) error {

func executeTestVector(tv schema.TestVector) error {
log.Println("executing test vector:", tv.Meta.ID)
r := new(conformance.LogReporter)
switch class := tv.Class; class {
case "message":
conformance.ExecuteMessageVector(r, &tv)
case "tipset":
conformance.ExecuteTipsetVector(r, &tv)
default:
return fmt.Errorf("test vector class %s not supported", class)
}

if r.Failed() {
log.Println(color.HiRedString("❌ test vector failed"))
} else {
log.Println(color.GreenString("✅ test vector succeeded"))
for _, v := range tv.Pre.Variants {
r := new(conformance.LogReporter)

switch class, v := tv.Class, v; class {
case "message":
conformance.ExecuteMessageVector(r, &tv, &v)
case "tipset":
conformance.ExecuteTipsetVector(r, &tv, &v)
default:
return fmt.Errorf("test vector class %s not supported", class)
}

if r.Failed() {
log.Println(color.HiRedString("❌ test vector failed for variant %s", v.ID))
} else {
log.Println(color.GreenString("✅ test vector succeeded for variant %s", v.ID))
}
}

return nil
Expand Down
14 changes: 13 additions & 1 deletion cmd/tvx/extract.go
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,13 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error {
return err
}

nv, err := fapi.StateNetworkVersion(ctx, execTs.Key())
if err != nil {
return err
}

codename := GetProtocolCodename(execTs.Height())

// Write out the test vector.
vector := schema.TestVector{
Class: schema.ClassMessage,
Expand All @@ -363,10 +370,15 @@ func doExtract(ctx context.Context, fapi api.FullNode, opts extractOpts) error {
{Source: fmt.Sprintf("execution_tipset:%s", execTs.Key().String())},
{Source: "github.com/filecoin-project/lotus", Version: version.String()}},
},
Selector: schema.Selector{
schema.SelectorMinProtocolVersion: codename,
},
Randomness: recordingRand.Recorded(),
CAR: out.Bytes(),
Pre: &schema.Preconditions{
Epoch: int64(execTs.Height()),
Variants: []schema.Variant{
{ID: codename, Epoch: int64(execTs.Height()), NetworkVersion: uint(nv)},
},
CircSupply: circSupply.Int,
BaseFee: basefee.Int,
StateTree: &schema.StateTree{
Expand Down
22 changes: 15 additions & 7 deletions conformance/corpus_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ import (
"github.com/filecoin-project/test-vectors/schema"
)

var invokees = map[schema.Class]func(Reporter, *schema.TestVector, *schema.Variant){
schema.ClassMessage: ExecuteMessageVector,
schema.ClassTipset: ExecuteTipsetVector,
}

const (
// EnvSkipConformance, if 1, skips the conformance test suite.
EnvSkipConformance = "SKIP_CONFORMANCE"
Expand Down Expand Up @@ -120,13 +125,16 @@ func TestConformance(t *testing.T) {
}

// dispatch the execution depending on the vector class.
switch vector.Class {
case "message":
ExecuteMessageVector(t, &vector)
case "tipset":
ExecuteTipsetVector(t, &vector)
default:
t.Fatalf("test vector class not supported: %s", vector.Class)
invokee, ok := invokees[vector.Class]
if !ok {
t.Fatalf("unsupported test vector class: %s", vector.Class)
}

for _, variant := range vector.Pre.Variants {
variant := variant
t.Run(variant.ID, func(t *testing.T) {
invokee(t, &vector, &variant)
})
}
})
}
Expand Down
5 changes: 2 additions & 3 deletions conformance/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ type ExecuteTipsetResult struct {
// This method returns the the receipts root, the poststate root, and the VM
// message results. The latter _include_ implicit messages, such as cron ticks
// and reward withdrawal per miner.
func (d *Driver) ExecuteTipset(bs blockstore.Blockstore, ds ds.Batching, preroot cid.Cid, parentEpoch abi.ChainEpoch, tipset *schema.Tipset) (*ExecuteTipsetResult, error) {
func (d *Driver) ExecuteTipset(bs blockstore.Blockstore, ds ds.Batching, preroot cid.Cid, parentEpoch abi.ChainEpoch, tipset *schema.Tipset, execEpoch abi.ChainEpoch) (*ExecuteTipsetResult, error) {
var (
syscalls = vm.Syscalls(ffiwrapper.ProofVerifier)
vmRand = NewFixedRand()
Expand Down Expand Up @@ -121,11 +121,10 @@ func (d *Driver) ExecuteTipset(bs blockstore.Blockstore, ds ds.Batching, preroot
messages []*types.Message
results []*vm.ApplyRet

epoch = abi.ChainEpoch(tipset.Epoch)
basefee = abi.NewTokenAmount(tipset.BaseFee.Int64())
)

postcid, receiptsroot, err := sm.ApplyBlocks(context.Background(), parentEpoch, preroot, blocks, epoch, vmRand, func(_ cid.Cid, msg *types.Message, ret *vm.ApplyRet) error {
postcid, receiptsroot, err := sm.ApplyBlocks(context.Background(), parentEpoch, preroot, blocks, execEpoch, vmRand, func(_ cid.Cid, msg *types.Message, ret *vm.ApplyRet) error {
messages = append(messages, msg)
results = append(results, ret)
return nil
Expand Down
26 changes: 14 additions & 12 deletions conformance/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ import (
)

// ExecuteMessageVector executes a message-class test vector.
func ExecuteMessageVector(r Reporter, vector *schema.TestVector) {
func ExecuteMessageVector(r Reporter, vector *schema.TestVector, variant *schema.Variant) {
var (
ctx = context.Background()
epoch = vector.Pre.Epoch
root = vector.Pre.StateTree.RootCID
ctx = context.Background()
baseEpoch = variant.Epoch
root = vector.Pre.StateTree.RootCID
)

// Load the CAR into a new temporary Blockstore.
Expand All @@ -53,16 +53,16 @@ func ExecuteMessageVector(r Reporter, vector *schema.TestVector) {
r.Fatalf("failed to deserialize message: %s", err)
}

// add an epoch if one's set.
if m.Epoch != nil {
epoch = *m.Epoch
// add the epoch offset if one is set.
if m.EpochOffset != nil {
baseEpoch += *m.EpochOffset
}

// Execute the message.
var ret *vm.ApplyRet
ret, root, err = driver.ExecuteMessage(bs, ExecuteMessageParams{
Preroot: root,
Epoch: abi.ChainEpoch(epoch),
Epoch: abi.ChainEpoch(baseEpoch),
Message: msg,
BaseFee: BaseFeeOrDefault(vector.Pre.BaseFee),
CircSupply: CircSupplyOrDefault(vector.Pre.CircSupply),
Expand All @@ -86,10 +86,10 @@ func ExecuteMessageVector(r Reporter, vector *schema.TestVector) {
}

// ExecuteTipsetVector executes a tipset-class test vector.
func ExecuteTipsetVector(r Reporter, vector *schema.TestVector) {
func ExecuteTipsetVector(r Reporter, vector *schema.TestVector, variant *schema.Variant) {
var (
ctx = context.Background()
prevEpoch = vector.Pre.Epoch
baseEpoch = abi.ChainEpoch(variant.Epoch)
root = vector.Pre.StateTree.RootCID
tmpds = ds.NewMapDatastore()
)
Expand All @@ -105,9 +105,11 @@ func ExecuteTipsetVector(r Reporter, vector *schema.TestVector) {

// Apply every tipset.
var receiptsIdx int
var prevEpoch = baseEpoch
for i, ts := range vector.ApplyTipsets {
ts := ts // capture
ret, err := driver.ExecuteTipset(bs, tmpds, root, abi.ChainEpoch(prevEpoch), &ts)
execEpoch := baseEpoch + abi.ChainEpoch(ts.EpochOffset)
ret, err := driver.ExecuteTipset(bs, tmpds, root, prevEpoch, &ts, execEpoch)
if err != nil {
r.Fatalf("failed to apply tipset %d message: %s", i, err)
}
Expand All @@ -122,7 +124,7 @@ func ExecuteTipsetVector(r Reporter, vector *schema.TestVector) {
r.Errorf("post receipts root doesn't match; expected: %s, was: %s", expected, actual)
}

prevEpoch = ts.Epoch
prevEpoch = execEpoch
root = ret.PostStateRoot
}

Expand Down
2 changes: 1 addition & 1 deletion extern/test-vectors
Submodule test-vectors updated 1328 files
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ require (
github.com/filecoin-project/specs-actors v0.9.12
github.com/filecoin-project/specs-actors/v2 v2.1.0
github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796
github.com/filecoin-project/test-vectors/schema v0.0.4
github.com/filecoin-project/test-vectors/schema v0.0.5
github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1
github.com/go-kit/kit v0.10.0
github.com/go-ole/go-ole v1.2.4 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -282,8 +282,8 @@ github.com/filecoin-project/specs-actors/v2 v2.1.0 h1:ocEuGz8DG2cUWw32c/tvF8D6xT
github.com/filecoin-project/specs-actors/v2 v2.1.0/go.mod h1:E7fAX4CZkDVQvDNRCxfq+hc3nx56KcCKyuZf0hlQJ20=
github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796 h1:dJsTPWpG2pcTeojO2pyn0c6l+x/3MZYCBgo/9d11JEk=
github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g=
github.com/filecoin-project/test-vectors/schema v0.0.4 h1:QTRd0gb/NP4ZOTM7Dib5U3xE1/ToGDKnYLfxkC3t/m8=
github.com/filecoin-project/test-vectors/schema v0.0.4/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E=
github.com/filecoin-project/test-vectors/schema v0.0.5 h1:w3zHQhzM4pYxJDl21avXjOKBLF8egrvwUwjpT8TquDg=
github.com/filecoin-project/test-vectors/schema v0.0.5/go.mod h1:iQ9QXLpYWL3m7warwvK1JC/pTri8mnfEmKygNDqqY6E=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6 h1:u/UEqS66A5ckRmS4yNpjmVH56sVtS/RfclBAYocb4as=
github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6/go.mod h1:1i71OnUq3iUe1ma7Lr6yG6/rjvM3emb6yoL7xLFzcVQ=
Expand Down

0 comments on commit 955d7f9

Please sign in to comment.