package mbt
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/tendermint/tendermint/light"
|
|
"github.com/tendermint/tendermint/types"
|
|
)
|
|
|
|
const jsonDir = "./json"
|
|
|
|
func TestVerify(t *testing.T) {
|
|
filenames := jsonFilenames(t)
|
|
|
|
for _, filename := range filenames {
|
|
filename := filename
|
|
t.Run(filename, func(t *testing.T) {
|
|
|
|
jsonBlob, err := os.ReadFile(filename)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
var tc testCase
|
|
err = json.Unmarshal(jsonBlob, &tc)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
t.Log(tc.Description)
|
|
|
|
var (
|
|
trustedSignedHeader = tc.Initial.SignedHeader
|
|
trustedNextVals = tc.Initial.NextValidatorSet
|
|
trustingPeriod = time.Duration(tc.Initial.TrustingPeriod) * time.Nanosecond
|
|
)
|
|
|
|
for _, input := range tc.Input {
|
|
var (
|
|
newSignedHeader = input.LightBlock.SignedHeader
|
|
newVals = input.LightBlock.ValidatorSet
|
|
)
|
|
|
|
err = light.Verify(
|
|
&trustedSignedHeader,
|
|
&trustedNextVals,
|
|
newSignedHeader,
|
|
newVals,
|
|
trustingPeriod,
|
|
input.Now,
|
|
1*time.Second,
|
|
light.DefaultTrustLevel,
|
|
)
|
|
|
|
t.Logf("%d -> %d", trustedSignedHeader.Height, newSignedHeader.Height)
|
|
|
|
switch input.Verdict {
|
|
case "SUCCESS":
|
|
require.NoError(t, err)
|
|
case "NOT_ENOUGH_TRUST":
|
|
require.IsType(t, light.ErrNewValSetCantBeTrusted{}, err)
|
|
case "INVALID":
|
|
switch err.(type) {
|
|
case light.ErrOldHeaderExpired:
|
|
case light.ErrInvalidHeader:
|
|
default:
|
|
t.Fatalf("expected either ErrInvalidHeader or ErrOldHeaderExpired, but got %v", err)
|
|
}
|
|
default:
|
|
t.Fatalf("unexpected verdict: %q", input.Verdict)
|
|
}
|
|
|
|
if err == nil { // advance
|
|
trustedSignedHeader = *newSignedHeader
|
|
trustedNextVals = *input.LightBlock.NextValidatorSet
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// jsonFilenames returns a list of files in jsonDir directory
|
|
func jsonFilenames(t *testing.T) []string {
|
|
matches, err := filepath.Glob(filepath.Join(jsonDir, "*.json"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return matches
|
|
}
|
|
|
|
type testCase struct {
|
|
Description string `json:"description"`
|
|
Initial initialData `json:"initial"`
|
|
Input []inputData `json:"input"`
|
|
}
|
|
|
|
type initialData struct {
|
|
SignedHeader types.SignedHeader `json:"signed_header"`
|
|
NextValidatorSet types.ValidatorSet `json:"next_validator_set"`
|
|
TrustingPeriod uint64 `json:"trusting_period,string"`
|
|
Now time.Time `json:"now"`
|
|
}
|
|
|
|
type inputData struct {
|
|
LightBlock lightBlockWithNextValidatorSet `json:"block"`
|
|
Now time.Time `json:"now"`
|
|
Verdict string `json:"verdict"`
|
|
}
|
|
|
|
// In tendermint-rs, NextValidatorSet is used to verify new blocks (opposite to
|
|
// Go tendermint).
|
|
type lightBlockWithNextValidatorSet struct {
|
|
*types.SignedHeader `json:"signed_header"`
|
|
ValidatorSet *types.ValidatorSet `json:"validator_set"`
|
|
NextValidatorSet *types.ValidatorSet `json:"next_validator_set"`
|
|
}
|