From 1871a7c3d0e31fed37047b6c1cda572cfa58d262 Mon Sep 17 00:00:00 2001 From: Adrian Brink Date: Thu, 26 Oct 2017 11:10:14 +0200 Subject: [PATCH] Rename certifier to light (#784) and add godocs The certifier package is renamed to light. This is more descriptive especially in the wider blockchain context. Moreover we are building light-clients using the light package. This also adds godocs to all exported functions. Furthermore it introduces some extra error handling. I've added one TODO where I would like someone else's opinion on how to handle the error. --- {certifiers => light}/client/main_test.go | 0 {certifiers => light}/client/provider.go | 39 +++++------ {certifiers => light}/client/provider_test.go | 8 +-- {certifiers => light}/commit.go | 9 ++- {certifiers => light}/doc.go | 4 +- {certifiers => light}/dynamic.go | 16 +++-- {certifiers => light}/dynamic_test.go | 18 +++--- {certifiers => light}/errors/errors.go | 10 ++- {certifiers => light}/errors/errors_test.go | 0 {certifiers => light}/files/commit.go | 22 ++++--- {certifiers => light}/files/commit_test.go | 4 +- {certifiers => light}/files/provider.go | 23 ++++--- {certifiers => light}/files/provider_test.go | 20 +++--- certifiers/helper.go => light/helpers.go | 24 +++---- {certifiers => light}/inquirer.go | 33 +++++++--- {certifiers => light}/inquirer_test.go | 44 ++++++------- {certifiers => light}/memprovider.go | 15 +++-- {certifiers => light}/performance_test.go | 34 +++++----- {certifiers => light}/provider.go | 64 ++++++------------- {certifiers => light}/provider_test.go | 57 +++++++++++------ {certifiers => light}/static.go | 11 +++- {certifiers => light}/static_test.go | 14 ++-- 22 files changed, 258 insertions(+), 211 deletions(-) rename {certifiers => light}/client/main_test.go (100%) rename {certifiers => light}/client/provider.go (73%) rename {certifiers => light}/client/provider_test.go (86%) rename {certifiers => light}/commit.go (89%) rename {certifiers => light}/doc.go (98%) rename {certifiers => light}/dynamic.go (79%) rename {certifiers => light}/dynamic_test.go (91%) rename {certifiers => light}/errors/errors.go (85%) rename {certifiers => light}/errors/errors_test.go (100%) rename {certifiers => light}/files/commit.go (66%) rename {certifiers => light}/files/commit_test.go (94%) rename {certifiers => light}/files/provider.go (79%) rename {certifiers => light}/files/provider_test.go (79%) rename certifiers/helper.go => light/helpers.go (91%) rename {certifiers => light}/inquirer.go (69%) rename {certifiers => light}/inquirer_test.go (78%) rename {certifiers => light}/memprovider.go (73%) rename {certifiers => light}/performance_test.go (74%) rename {certifiers => light}/provider.go (56%) rename {certifiers => light}/provider_test.go (64%) rename {certifiers => light}/static.go (79%) rename {certifiers => light}/static_test.go (81%) diff --git a/certifiers/client/main_test.go b/light/client/main_test.go similarity index 100% rename from certifiers/client/main_test.go rename to light/client/main_test.go diff --git a/certifiers/client/provider.go b/light/client/provider.go similarity index 73% rename from certifiers/client/provider.go rename to light/client/provider.go index 0c0add6a1..e1274c477 100644 --- a/certifiers/client/provider.go +++ b/light/client/provider.go @@ -12,10 +12,11 @@ import ( ctypes "github.com/tendermint/tendermint/rpc/core/types" "github.com/tendermint/tendermint/types" - "github.com/tendermint/tendermint/certifiers" - certerr "github.com/tendermint/tendermint/certifiers/errors" + "github.com/tendermint/tendermint/light" + lightErr "github.com/tendermint/tendermint/light/errors" ) +// SignStatusClient combines a SignClient and StatusClient. type SignStatusClient interface { rpcclient.SignClient rpcclient.StatusClient @@ -28,13 +29,13 @@ type provider struct { // NewProvider can wrap any rpcclient to expose it as // a read-only provider. -func NewProvider(node SignStatusClient) certifiers.Provider { +func NewProvider(node SignStatusClient) light.Provider { return &provider{node: node} } -// NewProvider can connects to a tendermint json-rpc endpoint +// NewHTTPProvider can connects to a tendermint json-rpc endpoint // at the given url, and uses that as a read-only provider. -func NewHTTPProvider(remote string) certifiers.Provider { +func NewHTTPProvider(remote string) light.Provider { return &provider{ node: rpcclient.NewHTTP(remote, "/websocket"), } @@ -46,13 +47,13 @@ func (p *provider) StatusClient() rpcclient.StatusClient { } // StoreCommit is a noop, as clients can only read from the chain... -func (p *provider) StoreCommit(_ certifiers.FullCommit) error { return nil } +func (p *provider) StoreCommit(_ light.FullCommit) error { return nil } // GetHash gets the most recent validator and sees if it matches // // TODO: improve when the rpc interface supports more functionality -func (p *provider) GetByHash(hash []byte) (certifiers.FullCommit, error) { - var fc certifiers.FullCommit +func (p *provider) GetByHash(hash []byte) (light.FullCommit, error) { + var fc light.FullCommit vals, err := p.node.Validators(nil) // if we get no validators, or a different height, return an error if err != nil { @@ -61,13 +62,13 @@ func (p *provider) GetByHash(hash []byte) (certifiers.FullCommit, error) { p.updateHeight(vals.BlockHeight) vhash := types.NewValidatorSet(vals.Validators).Hash() if !bytes.Equal(hash, vhash) { - return fc, certerr.ErrCommitNotFound() + return fc, lightErr.ErrCommitNotFound() } return p.seedFromVals(vals) } // GetByHeight gets the validator set by height -func (p *provider) GetByHeight(h int) (fc certifiers.FullCommit, err error) { +func (p *provider) GetByHeight(h int) (fc light.FullCommit, err error) { commit, err := p.node.Commit(&h) if err != nil { return fc, err @@ -75,7 +76,8 @@ func (p *provider) GetByHeight(h int) (fc certifiers.FullCommit, err error) { return p.seedFromCommit(commit) } -func (p *provider) LatestCommit() (fc certifiers.FullCommit, err error) { +// LatestCommit returns the newest commit stored. +func (p *provider) LatestCommit() (fc light.FullCommit, err error) { commit, err := p.GetLatestCommit() if err != nil { return fc, err @@ -94,24 +96,25 @@ func (p *provider) GetLatestCommit() (*ctypes.ResultCommit, error) { return p.node.Commit(&status.LatestBlockHeight) } -func CommitFromResult(result *ctypes.ResultCommit) certifiers.Commit { - return (certifiers.Commit)(result.SignedHeader) +// CommitFromResult ... +func CommitFromResult(result *ctypes.ResultCommit) light.Commit { + return (light.Commit)(result.SignedHeader) } -func (p *provider) seedFromVals(vals *ctypes.ResultValidators) (certifiers.FullCommit, error) { +func (p *provider) seedFromVals(vals *ctypes.ResultValidators) (light.FullCommit, error) { // now get the commits and build a full commit commit, err := p.node.Commit(&vals.BlockHeight) if err != nil { - return certifiers.FullCommit{}, err + return light.FullCommit{}, err } - fc := certifiers.NewFullCommit( + fc := light.NewFullCommit( CommitFromResult(commit), types.NewValidatorSet(vals.Validators), ) return fc, nil } -func (p *provider) seedFromCommit(commit *ctypes.ResultCommit) (fc certifiers.FullCommit, err error) { +func (p *provider) seedFromCommit(commit *ctypes.ResultCommit) (fc light.FullCommit, err error) { fc.Commit = CommitFromResult(commit) // now get the proper validators @@ -123,7 +126,7 @@ func (p *provider) seedFromCommit(commit *ctypes.ResultCommit) (fc certifiers.Fu // make sure they match the commit (as we cannot enforce height) vset := types.NewValidatorSet(vals.Validators) if !bytes.Equal(vset.Hash(), commit.Header.ValidatorsHash) { - return fc, certerr.ErrValidatorsChanged() + return fc, lightErr.ErrValidatorsChanged() } p.updateHeight(commit.Header.Height) diff --git a/certifiers/client/provider_test.go b/light/client/provider_test.go similarity index 86% rename from certifiers/client/provider_test.go rename to light/client/provider_test.go index 82955c22f..ed4fd7e17 100644 --- a/certifiers/client/provider_test.go +++ b/light/client/provider_test.go @@ -6,8 +6,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/tendermint/tendermint/certifiers" - certerr "github.com/tendermint/tendermint/certifiers/errors" + "github.com/tendermint/tendermint/light" + lightErr "github.com/tendermint/tendermint/light/errors" rpcclient "github.com/tendermint/tendermint/rpc/client" rpctest "github.com/tendermint/tendermint/rpc/test" ) @@ -35,7 +35,7 @@ func TestProvider(t *testing.T) { // let's check this is valid somehow assert.Nil(seed.ValidateBasic(chainID)) - cert := certifiers.NewStatic(chainID, seed.Validators) + cert := light.NewStatic(chainID, seed.Validators) // historical queries now work :) lower := sh - 5 @@ -53,7 +53,7 @@ func TestProvider(t *testing.T) { // get by hash fails without match seed, err = p.GetByHash([]byte("foobar")) assert.NotNil(err) - assert.True(certerr.IsCommitNotFoundErr(err)) + assert.True(lightErr.IsCommitNotFoundErr(err)) // storing the seed silently ignored err = p.StoreCommit(seed) diff --git a/certifiers/commit.go b/light/commit.go similarity index 89% rename from certifiers/commit.go rename to light/commit.go index 464a48ba2..c5472dbb9 100644 --- a/certifiers/commit.go +++ b/light/commit.go @@ -1,4 +1,4 @@ -package certifiers +package light import ( "bytes" @@ -7,7 +7,7 @@ import ( "github.com/tendermint/tendermint/types" - certerr "github.com/tendermint/tendermint/certifiers/errors" + lightErr "github.com/tendermint/tendermint/light/errors" ) // Certifier checks the votes to make sure the block really is signed properly. @@ -33,6 +33,7 @@ type FullCommit struct { Validators *types.ValidatorSet `json:"validator_set"` } +// NewFullCommit returns a new FullCommit. func NewFullCommit(commit Commit, vals *types.ValidatorSet) FullCommit { return FullCommit{ Commit: commit, @@ -40,6 +41,7 @@ func NewFullCommit(commit Commit, vals *types.ValidatorSet) FullCommit { } } +// Height returns the of the header. func (c Commit) Height() int { if c.Header == nil { return 0 @@ -47,6 +49,7 @@ func (c Commit) Height() int { return c.Header.Height } +// ValidatorsHash returns the hash of the validator set. func (c Commit) ValidatorsHash() []byte { if c.Header == nil { return nil @@ -75,7 +78,7 @@ func (c Commit) ValidateBasic(chainID string) error { // make sure the header and commit match (height and hash) if c.Commit.Height() != c.Header.Height { - return certerr.ErrHeightMismatch(c.Commit.Height(), c.Header.Height) + return lightErr.ErrHeightMismatch(c.Commit.Height(), c.Header.Height) } hhash := c.Header.Hash() chash := c.Commit.BlockID.Hash diff --git a/certifiers/doc.go b/light/doc.go similarity index 98% rename from certifiers/doc.go rename to light/doc.go index 7566405bd..1bde5ee46 100644 --- a/certifiers/doc.go +++ b/light/doc.go @@ -1,5 +1,5 @@ /* -Package certifiers allows you to securely validate headers +Package light allows you to securely validate headers without a full node. This library pulls together all the crypto and algorithms, @@ -130,4 +130,4 @@ to manually verify the new validator set hash using off-chain means (the same as getting the initial hash). */ -package certifiers +package light diff --git a/certifiers/dynamic.go b/light/dynamic.go similarity index 79% rename from certifiers/dynamic.go rename to light/dynamic.go index b40177949..cf856c63a 100644 --- a/certifiers/dynamic.go +++ b/light/dynamic.go @@ -1,9 +1,9 @@ -package certifiers +package light import ( "github.com/tendermint/tendermint/types" - certerr "github.com/tendermint/tendermint/certifiers/errors" + lightErr "github.com/tendermint/tendermint/light/errors" ) var _ Certifier = &Dynamic{} @@ -22,6 +22,7 @@ type Dynamic struct { lastHeight int } +// NewDynamic returns a new dynamic certifier. func NewDynamic(chainID string, vals *types.ValidatorSet, height int) *Dynamic { return &Dynamic{ cert: NewStatic(chainID, vals), @@ -29,23 +30,28 @@ func NewDynamic(chainID string, vals *types.ValidatorSet, height int) *Dynamic { } } +// ChainID returns the chain id of this certifier. func (c *Dynamic) ChainID() string { return c.cert.ChainID() } +// Validators returns the validators of this certifier. func (c *Dynamic) Validators() *types.ValidatorSet { return c.cert.vSet } +// Hash returns the hash of this certifier. func (c *Dynamic) Hash() []byte { return c.cert.Hash() } +// LastHeight returns the last height of this certifier. func (c *Dynamic) LastHeight() int { return c.lastHeight } -// Certify handles this with +// Certify will verify whether the commit is valid and will update the height if it is or return an +// error if it is not. func (c *Dynamic) Certify(check Commit) error { err := c.cert.Certify(check) if err == nil { @@ -63,7 +69,7 @@ func (c *Dynamic) Update(fc FullCommit) error { // ignore all checkpoints in the past -> only to the future h := fc.Height() if h <= c.lastHeight { - return certerr.ErrPastTime() + return lightErr.ErrPastTime() } // first, verify if the input is self-consistent.... @@ -79,7 +85,7 @@ func (c *Dynamic) Update(fc FullCommit) error { err = c.Validators().VerifyCommitAny(fc.Validators, c.ChainID(), commit.BlockID, h, commit) if err != nil { - return certerr.ErrTooMuchChange() + return lightErr.ErrTooMuchChange() } // looks good, we can update diff --git a/certifiers/dynamic_test.go b/light/dynamic_test.go similarity index 91% rename from certifiers/dynamic_test.go rename to light/dynamic_test.go index 2c921099f..3212b9c8d 100644 --- a/certifiers/dynamic_test.go +++ b/light/dynamic_test.go @@ -1,4 +1,4 @@ -package certifiers_test +package light_test import ( "testing" @@ -8,8 +8,8 @@ import ( "github.com/tendermint/tendermint/types" - "github.com/tendermint/tendermint/certifiers" - "github.com/tendermint/tendermint/certifiers/errors" + "github.com/tendermint/tendermint/light" + "github.com/tendermint/tendermint/light/errors" ) // TestDynamicCert just makes sure it still works like StaticCert @@ -18,15 +18,15 @@ func TestDynamicCert(t *testing.T) { assert := assert.New(t) // require := require.New(t) - keys := certifiers.GenValKeys(4) + keys := light.GenValKeys(4) // 20, 30, 40, 50 - the first 3 don't have 2/3, the last 3 do! vals := keys.ToValidators(20, 10) // and a certifier based on our known set chainID := "test-dyno" - cert := certifiers.NewDynamic(chainID, vals, 0) + cert := light.NewDynamic(chainID, vals, 0) cases := []struct { - keys certifiers.ValKeys + keys light.ValKeys vals *types.ValidatorSet height int first, last int // who actually signs @@ -65,9 +65,9 @@ func TestDynamicUpdate(t *testing.T) { assert, require := assert.New(t), require.New(t) chainID := "test-dyno-up" - keys := certifiers.GenValKeys(5) + keys := light.GenValKeys(5) vals := keys.ToValidators(20, 0) - cert := certifiers.NewDynamic(chainID, vals, 40) + cert := light.NewDynamic(chainID, vals, 40) // one valid block to give us a sense of time h := 100 @@ -81,7 +81,7 @@ func TestDynamicUpdate(t *testing.T) { // we try to update with some blocks cases := []struct { - keys certifiers.ValKeys + keys light.ValKeys vals *types.ValidatorSet height int first, last int // who actually signs diff --git a/certifiers/errors/errors.go b/light/errors/errors.go similarity index 85% rename from certifiers/errors/errors.go rename to light/errors/errors.go index c716c8fc0..96c075394 100644 --- a/certifiers/errors/errors.go +++ b/light/errors/errors.go @@ -19,34 +19,39 @@ func IsCommitNotFoundErr(err error) bool { return err != nil && (errors.Cause(err) == errCommitNotFound) } +// ErrCommitNotFound indicates that a the requested commit was not found. func ErrCommitNotFound() error { return errors.WithStack(errCommitNotFound) } // IsValidatorsChangedErr checks whether an error is due -// to a differing validator set +// to a differing validator set. func IsValidatorsChangedErr(err error) bool { return err != nil && (errors.Cause(err) == errValidatorsChanged) } +// ErrValidatorsChanged indicates that the validator set was changed between two commits. func ErrValidatorsChanged() error { return errors.WithStack(errValidatorsChanged) } // IsTooMuchChangeErr checks whether an error is due to too much change -// between these validators sets +// between these validators sets. func IsTooMuchChangeErr(err error) bool { return err != nil && (errors.Cause(err) == errTooMuchChange) } +// ErrTooMuchChange indicates that the underlying validator set was changed by >1/3. func ErrTooMuchChange() error { return errors.WithStack(errTooMuchChange) } +// IsPastTimeErr ... func IsPastTimeErr(err error) bool { return err != nil && (errors.Cause(err) == errPastTime) } +// ErrPastTime ... func ErrPastTime() error { return errors.WithStack(errPastTime) } @@ -57,6 +62,7 @@ func IsNoPathFoundErr(err error) bool { return err != nil && (errors.Cause(err) == errNoPathFound) } +// ErrNoPathFound ... func ErrNoPathFound() error { return errors.WithStack(errNoPathFound) } diff --git a/certifiers/errors/errors_test.go b/light/errors/errors_test.go similarity index 100% rename from certifiers/errors/errors_test.go rename to light/errors/errors_test.go diff --git a/certifiers/files/commit.go b/light/files/commit.go similarity index 66% rename from certifiers/files/commit.go rename to light/files/commit.go index 18994f0fc..1a3709304 100644 --- a/certifiers/files/commit.go +++ b/light/files/commit.go @@ -8,8 +8,8 @@ import ( wire "github.com/tendermint/go-wire" - "github.com/tendermint/tendermint/certifiers" - certerr "github.com/tendermint/tendermint/certifiers/errors" + "github.com/tendermint/tendermint/light" + lightErr "github.com/tendermint/tendermint/light/errors" ) const ( @@ -20,7 +20,7 @@ const ( ) // SaveFullCommit exports the seed in binary / go-wire style -func SaveFullCommit(fc certifiers.FullCommit, path string) error { +func SaveFullCommit(fc light.FullCommit, path string) error { f, err := os.Create(path) if err != nil { return errors.WithStack(err) @@ -33,7 +33,7 @@ func SaveFullCommit(fc certifiers.FullCommit, path string) error { } // SaveFullCommitJSON exports the seed in a json format -func SaveFullCommitJSON(fc certifiers.FullCommit, path string) error { +func SaveFullCommitJSON(fc light.FullCommit, path string) error { f, err := os.Create(path) if err != nil { return errors.WithStack(err) @@ -44,12 +44,13 @@ func SaveFullCommitJSON(fc certifiers.FullCommit, path string) error { return errors.WithStack(err) } -func LoadFullCommit(path string) (certifiers.FullCommit, error) { - var fc certifiers.FullCommit +// LoadFullCommit loads the full commit from the file system. +func LoadFullCommit(path string) (light.FullCommit, error) { + var fc light.FullCommit f, err := os.Open(path) if err != nil { if os.IsNotExist(err) { - return fc, certerr.ErrCommitNotFound() + return fc, lightErr.ErrCommitNotFound() } return fc, errors.WithStack(err) } @@ -60,12 +61,13 @@ func LoadFullCommit(path string) (certifiers.FullCommit, error) { return fc, errors.WithStack(err) } -func LoadFullCommitJSON(path string) (certifiers.FullCommit, error) { - var fc certifiers.FullCommit +// LoadFullCommitJSON loads the commit from the file system in JSON format. +func LoadFullCommitJSON(path string) (light.FullCommit, error) { + var fc light.FullCommit f, err := os.Open(path) if err != nil { if os.IsNotExist(err) { - return fc, certerr.ErrCommitNotFound() + return fc, lightErr.ErrCommitNotFound() } return fc, errors.WithStack(err) } diff --git a/certifiers/files/commit_test.go b/light/files/commit_test.go similarity index 94% rename from certifiers/files/commit_test.go rename to light/files/commit_test.go index 934ab7b66..100ee58fd 100644 --- a/certifiers/files/commit_test.go +++ b/light/files/commit_test.go @@ -10,7 +10,7 @@ import ( cmn "github.com/tendermint/tmlibs/common" - "github.com/tendermint/tendermint/certifiers" + "github.com/tendermint/tendermint/light" ) func tmpFile() string { @@ -27,7 +27,7 @@ func TestSerializeFullCommits(t *testing.T) { h := 25 // build a fc - keys := certifiers.GenValKeys(5) + keys := light.GenValKeys(5) vals := keys.ToValidators(10, 0) fc := keys.GenFullCommit(chainID, h, nil, vals, appHash, 0, 5) diff --git a/certifiers/files/provider.go b/light/files/provider.go similarity index 79% rename from certifiers/files/provider.go rename to light/files/provider.go index 9dcfb1691..48a3d6554 100644 --- a/certifiers/files/provider.go +++ b/light/files/provider.go @@ -24,10 +24,11 @@ import ( "github.com/pkg/errors" - "github.com/tendermint/tendermint/certifiers" - certerr "github.com/tendermint/tendermint/certifiers/errors" + "github.com/tendermint/tendermint/light" + lightErr "github.com/tendermint/tendermint/light/errors" ) +// nolint const ( Ext = ".tsd" ValDir = "validators" @@ -43,7 +44,7 @@ type provider struct { // NewProvider creates the parent dir and subdirs // for validators and checkpoints as needed -func NewProvider(dir string) certifiers.Provider { +func NewProvider(dir string) light.Provider { valDir := filepath.Join(dir, ValDir) checkDir := filepath.Join(dir, CheckDir) for _, d := range []string{valDir, checkDir} { @@ -64,7 +65,8 @@ func (p *provider) encodeHeight(h int) string { return fmt.Sprintf("%012d%s", h, Ext) } -func (p *provider) StoreCommit(fc certifiers.FullCommit) error { +// StoreCommit saves a full commit after it has been verified. +func (p *provider) StoreCommit(fc light.FullCommit) error { // make sure the fc is self-consistent before saving err := fc.ValidateBasic(fc.Commit.Header.ChainID) if err != nil { @@ -85,11 +87,12 @@ func (p *provider) StoreCommit(fc certifiers.FullCommit) error { return nil } -func (p *provider) GetByHeight(h int) (certifiers.FullCommit, error) { +// GetByHeight returns the closest commit with height <= h. +func (p *provider) GetByHeight(h int) (light.FullCommit, error) { // first we look for exact match, then search... path := filepath.Join(p.checkDir, p.encodeHeight(h)) fc, err := LoadFullCommit(path) - if certerr.IsCommitNotFoundErr(err) { + if lightErr.IsCommitNotFoundErr(err) { path, err = p.searchForHeight(h) if err == nil { fc, err = LoadFullCommit(path) @@ -98,7 +101,8 @@ func (p *provider) GetByHeight(h int) (certifiers.FullCommit, error) { return fc, err } -func (p *provider) LatestCommit() (fc certifiers.FullCommit, err error) { +// LatestCommit returns the newest commit stored. +func (p *provider) LatestCommit() (fc light.FullCommit, err error) { // Note to future: please update by 2077 to avoid rollover return p.GetByHeight(math.MaxInt32 - 1) } @@ -121,14 +125,15 @@ func (p *provider) searchForHeight(h int) (string, error) { sort.Strings(files) i := sort.SearchStrings(files, desired) if i == 0 { - return "", certerr.ErrCommitNotFound() + return "", lightErr.ErrCommitNotFound() } found := files[i-1] path := filepath.Join(p.checkDir, found) return path, errors.WithStack(err) } -func (p *provider) GetByHash(hash []byte) (certifiers.FullCommit, error) { +// GetByHash returns a commit exactly matching this validator hash. +func (p *provider) GetByHash(hash []byte) (light.FullCommit, error) { path := filepath.Join(p.valDir, p.encodeHash(hash)) return LoadFullCommit(path) } diff --git a/certifiers/files/provider_test.go b/light/files/provider_test.go similarity index 79% rename from certifiers/files/provider_test.go rename to light/files/provider_test.go index 05e8f59d2..7bbfab73e 100644 --- a/certifiers/files/provider_test.go +++ b/light/files/provider_test.go @@ -10,12 +10,12 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/tendermint/tendermint/certifiers" - certerr "github.com/tendermint/tendermint/certifiers/errors" - "github.com/tendermint/tendermint/certifiers/files" + "github.com/tendermint/tendermint/light" + lightErr "github.com/tendermint/tendermint/light/errors" + "github.com/tendermint/tendermint/light/files" ) -func checkEqual(stored, loaded certifiers.FullCommit, chainID string) error { +func checkEqual(stored, loaded light.FullCommit, chainID string) error { err := loaded.ValidateBasic(chainID) if err != nil { return err @@ -36,28 +36,28 @@ func TestFileProvider(t *testing.T) { chainID := "test-files" appHash := []byte("some-data") - keys := certifiers.GenValKeys(5) + keys := light.GenValKeys(5) count := 10 // make a bunch of seeds... - seeds := make([]certifiers.FullCommit, count) + seeds := make([]light.FullCommit, count) for i := 0; i < count; i++ { // two seeds for each validator, to check how we handle dups // (10, 0), (10, 1), (10, 1), (10, 2), (10, 2), ... vals := keys.ToValidators(10, int64(count/2)) h := 20 + 10*i check := keys.GenCommit(chainID, h, nil, vals, appHash, 0, 5) - seeds[i] = certifiers.NewFullCommit(check, vals) + seeds[i] = light.NewFullCommit(check, vals) } // check provider is empty seed, err := p.GetByHeight(20) require.NotNil(err) - assert.True(certerr.IsCommitNotFoundErr(err)) + assert.True(lightErr.IsCommitNotFoundErr(err)) seed, err = p.GetByHash(seeds[3].ValidatorsHash()) require.NotNil(err) - assert.True(certerr.IsCommitNotFoundErr(err)) + assert.True(lightErr.IsCommitNotFoundErr(err)) // now add them all to the provider for _, s := range seeds { @@ -92,5 +92,5 @@ func TestFileProvider(t *testing.T) { // and proper error for too low _, err = p.GetByHeight(5) assert.NotNil(err) - assert.True(certerr.IsCommitNotFoundErr(err)) + assert.True(lightErr.IsCommitNotFoundErr(err)) } diff --git a/certifiers/helper.go b/light/helpers.go similarity index 91% rename from certifiers/helper.go rename to light/helpers.go index 6f2daa63b..c1627375f 100644 --- a/certifiers/helper.go +++ b/light/helpers.go @@ -1,4 +1,4 @@ -package certifiers +package light import ( "time" @@ -12,14 +12,14 @@ import ( // // It lets us simulate signing with many keys, either ed25519 or secp256k1. // The main use case is to create a set, and call GenCommit -// to get propely signed header for testing. +// to get properly signed header for testing. // // You can set different weights of validators each time you call // ToValidators, and can optionally extend the validator set later // with Extend or ExtendSecp type ValKeys []crypto.PrivKey -// GenValKeys produces an array of private keys to generate commits +// GenValKeys produces an array of private keys to generate commits. func GenValKeys(n int) ValKeys { res := make(ValKeys, n) for i := range res { @@ -28,7 +28,7 @@ func GenValKeys(n int) ValKeys { return res } -// Change replaces the key at index i +// Change replaces the key at index i. func (v ValKeys) Change(i int) ValKeys { res := make(ValKeys, len(v)) copy(res, v) @@ -36,13 +36,13 @@ func (v ValKeys) Change(i int) ValKeys { return res } -// Extend adds n more keys (to remove, just take a slice) +// Extend adds n more keys (to remove, just take a slice). func (v ValKeys) Extend(n int) ValKeys { extra := GenValKeys(n) return append(v, extra...) } -// GenSecpValKeys produces an array of secp256k1 private keys to generate commits +// GenSecpValKeys produces an array of secp256k1 private keys to generate commits. func GenSecpValKeys(n int) ValKeys { res := make(ValKeys, n) for i := range res { @@ -51,7 +51,7 @@ func GenSecpValKeys(n int) ValKeys { return res } -// ExtendSecp adds n more secp256k1 keys (to remove, just take a slice) +// ExtendSecp adds n more secp256k1 keys (to remove, just take a slice). func (v ValKeys) ExtendSecp(n int) ValKeys { extra := GenSecpValKeys(n) return append(v, extra...) @@ -60,7 +60,7 @@ func (v ValKeys) ExtendSecp(n int) ValKeys { // ToValidators produces a list of validators from the set of keys // The first key has weight `init` and it increases by `inc` every step // so we can have all the same weight, or a simple linear distribution -// (should be enough for testing) +// (should be enough for testing). func (v ValKeys) ToValidators(init, inc int64) *types.ValidatorSet { res := make([]*types.Validator, len(v)) for i, k := range v { @@ -69,7 +69,7 @@ func (v ValKeys) ToValidators(init, inc int64) *types.ValidatorSet { return types.NewValidatorSet(res) } -// signHeader properly signs the header with all keys from first to last exclusive +// signHeader properly signs the header with all keys from first to last exclusive. func (v ValKeys) signHeader(header *types.Header, first, last int) *types.Commit { votes := make([]*types.Vote, len(v)) @@ -106,6 +106,8 @@ func makeVote(header *types.Header, vals *types.ValidatorSet, key crypto.PrivKey return vote } +// Silences warning that vals can also be merkle.Hashable +// nolint: interfacer func genHeader(chainID string, height int, txs types.Txs, vals *types.ValidatorSet, appHash []byte) *types.Header { @@ -122,7 +124,7 @@ func genHeader(chainID string, height int, txs types.Txs, } } -// GenCommit calls genHeader and signHeader and combines them into a Commit +// GenCommit calls genHeader and signHeader and combines them into a Commit. func (v ValKeys) GenCommit(chainID string, height int, txs types.Txs, vals *types.ValidatorSet, appHash []byte, first, last int) Commit { @@ -134,7 +136,7 @@ func (v ValKeys) GenCommit(chainID string, height int, txs types.Txs, return check } -// GenFullCommit calls genHeader and signHeader and combines them into a Commit +// GenFullCommit calls genHeader and signHeader and combines them into a Commit. func (v ValKeys) GenFullCommit(chainID string, height int, txs types.Txs, vals *types.ValidatorSet, appHash []byte, first, last int) FullCommit { diff --git a/certifiers/inquirer.go b/light/inquirer.go similarity index 69% rename from certifiers/inquirer.go rename to light/inquirer.go index 460b622ab..586dc899c 100644 --- a/certifiers/inquirer.go +++ b/light/inquirer.go @@ -1,11 +1,15 @@ -package certifiers +package light import ( "github.com/tendermint/tendermint/types" - certerr "github.com/tendermint/tendermint/certifiers/errors" + lightErr "github.com/tendermint/tendermint/light/errors" ) +// Inquiring wraps a dynamic certifier and implements an auto-update strategy. If a call to Certify +// fails due to a change it validator set, Inquiring will try and find a previous FullCommit which +// it can use to safely update the validator set. It uses a source provider to obtain the needed +// FullCommits. It stores properly validated data on the local system. type Inquiring struct { cert *Dynamic // These are only properly validated data, from local system @@ -14,8 +18,14 @@ type Inquiring struct { Source Provider } +// NewInquiring returns a new Inquiring object. It uses the trusted provider to store validated +// data and the source provider to obtain missing FullCommits. +// +// Example: The trusted provider should a CacheProvider, MemProvider or files.Provider. The source +// provider should be a client.HTTPProvider. func NewInquiring(chainID string, fc FullCommit, trusted Provider, source Provider) *Inquiring { // store the data in trusted + // TODO: StoredCommit() can return an error and we need to handle this. trusted.StoreCommit(fc) return &Inquiring{ @@ -25,14 +35,17 @@ func NewInquiring(chainID string, fc FullCommit, trusted Provider, source Provid } } +// ChainID returns the chain id. func (c *Inquiring) ChainID() string { return c.cert.ChainID() } +// Validators returns the validator set. func (c *Inquiring) Validators() *types.ValidatorSet { return c.cert.cert.vSet } +// LastHeight returns the last height. func (c *Inquiring) LastHeight() int { return c.cert.lastHeight } @@ -50,7 +63,7 @@ func (c *Inquiring) Certify(commit Commit) error { } err = c.cert.Certify(commit) - if !certerr.IsValidatorsChangedErr(err) { + if !lightErr.IsValidatorsChangedErr(err) { return err } err = c.updateToHash(commit.Header.ValidatorsHash) @@ -64,11 +77,11 @@ func (c *Inquiring) Certify(commit Commit) error { } // store the new checkpoint - c.trusted.StoreCommit( - NewFullCommit(commit, c.Validators())) - return nil + return c.trusted.StoreCommit(NewFullCommit(commit, c.Validators())) } +// Update will verify if this is a valid change and update +// the certifying validator set if safe to do so. func (c *Inquiring) Update(fc FullCommit) error { err := c.useClosestTrust(fc.Height()) if err != nil { @@ -77,7 +90,7 @@ func (c *Inquiring) Update(fc FullCommit) error { err = c.cert.Update(fc) if err == nil { - c.trusted.StoreCommit(fc) + err = c.trusted.StoreCommit(fc) } return err } @@ -106,7 +119,7 @@ func (c *Inquiring) updateToHash(vhash []byte) error { } err = c.cert.Update(fc) // handle IsTooMuchChangeErr by using divide and conquer - if certerr.IsTooMuchChangeErr(err) { + if lightErr.IsTooMuchChangeErr(err) { err = c.updateToHeight(fc.Height()) } return err @@ -121,12 +134,12 @@ func (c *Inquiring) updateToHeight(h int) error { } start, end := c.LastHeight(), fc.Height() if end <= start { - return certerr.ErrNoPathFound() + return lightErr.ErrNoPathFound() } err = c.Update(fc) // we can handle IsTooMuchChangeErr specially - if !certerr.IsTooMuchChangeErr(err) { + if !lightErr.IsTooMuchChangeErr(err) { return err } diff --git a/certifiers/inquirer_test.go b/light/inquirer_test.go similarity index 78% rename from certifiers/inquirer_test.go rename to light/inquirer_test.go index 2a0ee5551..6024e42d1 100644 --- a/certifiers/inquirer_test.go +++ b/light/inquirer_test.go @@ -1,4 +1,5 @@ -package certifiers_test +// nolint: vetshadow +package light_test import ( "fmt" @@ -7,34 +8,33 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/tendermint/tendermint/certifiers" + "github.com/tendermint/tendermint/light" ) func TestInquirerValidPath(t *testing.T) { assert, require := assert.New(t), require.New(t) - trust := certifiers.NewMemStoreProvider() - source := certifiers.NewMemStoreProvider() + trust := light.NewMemStoreProvider() + source := light.NewMemStoreProvider() // set up the validators to generate test blocks var vote int64 = 10 - keys := certifiers.GenValKeys(5) - vals := keys.ToValidators(vote, 0) + keys := light.GenValKeys(5) // construct a bunch of commits, each with one more height than the last chainID := "inquiry-test" count := 50 - commits := make([]certifiers.FullCommit, count) + commits := make([]light.FullCommit, count) for i := 0; i < count; i++ { // extend the keys by 1 each time keys = keys.Extend(1) - vals = keys.ToValidators(vote, 0) + vals := keys.ToValidators(vote, 0) h := 20 + 10*i appHash := []byte(fmt.Sprintf("h=%d", h)) commits[i] = keys.GenFullCommit(chainID, h, nil, vals, appHash, 0, len(keys)) } // initialize a certifier with the initial state - cert := certifiers.NewInquiring(chainID, commits[0], trust, source) + cert := light.NewInquiring(chainID, commits[0], trust, source) // this should fail validation.... commit := commits[count-1].Commit @@ -60,29 +60,28 @@ func TestInquirerValidPath(t *testing.T) { func TestInquirerMinimalPath(t *testing.T) { assert, require := assert.New(t), require.New(t) - trust := certifiers.NewMemStoreProvider() - source := certifiers.NewMemStoreProvider() + trust := light.NewMemStoreProvider() + source := light.NewMemStoreProvider() // set up the validators to generate test blocks var vote int64 = 10 - keys := certifiers.GenValKeys(5) - vals := keys.ToValidators(vote, 0) + keys := light.GenValKeys(5) // construct a bunch of commits, each with one more height than the last chainID := "minimal-path" count := 12 - commits := make([]certifiers.FullCommit, count) + commits := make([]light.FullCommit, count) for i := 0; i < count; i++ { // extend the validators, so we are just below 2/3 keys = keys.Extend(len(keys)/2 - 1) - vals = keys.ToValidators(vote, 0) + vals := keys.ToValidators(vote, 0) h := 5 + 10*i appHash := []byte(fmt.Sprintf("h=%d", h)) commits[i] = keys.GenFullCommit(chainID, h, nil, vals, appHash, 0, len(keys)) } // initialize a certifier with the initial state - cert := certifiers.NewInquiring(chainID, commits[0], trust, source) + cert := light.NewInquiring(chainID, commits[0], trust, source) // this should fail validation.... commit := commits[count-1].Commit @@ -108,29 +107,28 @@ func TestInquirerMinimalPath(t *testing.T) { func TestInquirerVerifyHistorical(t *testing.T) { assert, require := assert.New(t), require.New(t) - trust := certifiers.NewMemStoreProvider() - source := certifiers.NewMemStoreProvider() + trust := light.NewMemStoreProvider() + source := light.NewMemStoreProvider() // set up the validators to generate test blocks var vote int64 = 10 - keys := certifiers.GenValKeys(5) - vals := keys.ToValidators(vote, 0) + keys := light.GenValKeys(5) // construct a bunch of commits, each with one more height than the last chainID := "inquiry-test" count := 10 - commits := make([]certifiers.FullCommit, count) + commits := make([]light.FullCommit, count) for i := 0; i < count; i++ { // extend the keys by 1 each time keys = keys.Extend(1) - vals = keys.ToValidators(vote, 0) + vals := keys.ToValidators(vote, 0) h := 20 + 10*i appHash := []byte(fmt.Sprintf("h=%d", h)) commits[i] = keys.GenFullCommit(chainID, h, nil, vals, appHash, 0, len(keys)) } // initialize a certifier with the initial state - cert := certifiers.NewInquiring(chainID, commits[0], trust, source) + cert := light.NewInquiring(chainID, commits[0], trust, source) // store a few commits as trust for _, i := range []int{2, 5} { diff --git a/certifiers/memprovider.go b/light/memprovider.go similarity index 73% rename from certifiers/memprovider.go rename to light/memprovider.go index cdad75e49..d1c58db19 100644 --- a/certifiers/memprovider.go +++ b/light/memprovider.go @@ -1,10 +1,10 @@ -package certifiers +package light import ( "encoding/hex" "sort" - certerr "github.com/tendermint/tendermint/certifiers/errors" + lightErr "github.com/tendermint/tendermint/light/errors" ) type memStoreProvider struct { @@ -23,6 +23,7 @@ func (s fullCommits) Less(i, j int) bool { return s[i].Height() < s[j].Height() } +// NewMemStoreProvider returns a new in-memory provider. func NewMemStoreProvider() Provider { return &memStoreProvider{ byHeight: fullCommits{}, @@ -34,6 +35,7 @@ func (m *memStoreProvider) encodeHash(hash []byte) string { return hex.EncodeToString(hash) } +// StoreCommit stores a FullCommit after verifying it. func (m *memStoreProvider) StoreCommit(fc FullCommit) error { // make sure the fc is self-consistent before saving err := fc.ValidateBasic(fc.Commit.Header.ChainID) @@ -49,6 +51,7 @@ func (m *memStoreProvider) StoreCommit(fc FullCommit) error { return nil } +// GetByHeight returns the FullCommit for height h or an error if the commit is not found. func (m *memStoreProvider) GetByHeight(h int) (FullCommit, error) { // search from highest to lowest for i := len(m.byHeight) - 1; i >= 0; i-- { @@ -57,22 +60,24 @@ func (m *memStoreProvider) GetByHeight(h int) (FullCommit, error) { return fc, nil } } - return FullCommit{}, certerr.ErrCommitNotFound() + return FullCommit{}, lightErr.ErrCommitNotFound() } +// GetByHash returns the FullCommit for the hash or an error if the commit is not found. func (m *memStoreProvider) GetByHash(hash []byte) (FullCommit, error) { var err error fc, ok := m.byHash[m.encodeHash(hash)] if !ok { - err = certerr.ErrCommitNotFound() + err = lightErr.ErrCommitNotFound() } return fc, err } +// LatestCommit returns the latest FullCommit or an error if no commits exist. func (m *memStoreProvider) LatestCommit() (FullCommit, error) { l := len(m.byHeight) if l == 0 { - return FullCommit{}, certerr.ErrCommitNotFound() + return FullCommit{}, lightErr.ErrCommitNotFound() } return m.byHeight[l-1], nil } diff --git a/certifiers/performance_test.go b/light/performance_test.go similarity index 74% rename from certifiers/performance_test.go rename to light/performance_test.go index 2a6c6ced8..6d4fb4cd2 100644 --- a/certifiers/performance_test.go +++ b/light/performance_test.go @@ -1,33 +1,33 @@ -package certifiers_test +package light_test import ( "fmt" "testing" - "github.com/tendermint/tendermint/certifiers" + "github.com/tendermint/tendermint/light" ) func BenchmarkGenCommit20(b *testing.B) { - keys := certifiers.GenValKeys(20) + keys := light.GenValKeys(20) benchmarkGenCommit(b, keys) } func BenchmarkGenCommit100(b *testing.B) { - keys := certifiers.GenValKeys(100) + keys := light.GenValKeys(100) benchmarkGenCommit(b, keys) } func BenchmarkGenCommitSec20(b *testing.B) { - keys := certifiers.GenSecpValKeys(20) + keys := light.GenSecpValKeys(20) benchmarkGenCommit(b, keys) } func BenchmarkGenCommitSec100(b *testing.B) { - keys := certifiers.GenSecpValKeys(100) + keys := light.GenSecpValKeys(100) benchmarkGenCommit(b, keys) } -func benchmarkGenCommit(b *testing.B, keys certifiers.ValKeys) { +func benchmarkGenCommit(b *testing.B, keys light.ValKeys) { chainID := fmt.Sprintf("bench-%d", len(keys)) vals := keys.ToValidators(20, 10) for i := 0; i < b.N; i++ { @@ -39,7 +39,7 @@ func benchmarkGenCommit(b *testing.B, keys certifiers.ValKeys) { // this benchmarks generating one key func BenchmarkGenValKeys(b *testing.B) { - keys := certifiers.GenValKeys(20) + keys := light.GenValKeys(20) for i := 0; i < b.N; i++ { keys = keys.Extend(1) } @@ -47,7 +47,7 @@ func BenchmarkGenValKeys(b *testing.B) { // this benchmarks generating one key func BenchmarkGenSecpValKeys(b *testing.B) { - keys := certifiers.GenSecpValKeys(20) + keys := light.GenSecpValKeys(20) for i := 0; i < b.N; i++ { keys = keys.Extend(1) } @@ -63,7 +63,7 @@ func BenchmarkToValidators100(b *testing.B) { // this benchmarks constructing the validator set (.PubKey() * nodes) func benchmarkToValidators(b *testing.B, nodes int) { - keys := certifiers.GenValKeys(nodes) + keys := light.GenValKeys(nodes) for i := 1; i <= b.N; i++ { keys.ToValidators(int64(2*i), int64(i)) } @@ -75,36 +75,36 @@ func BenchmarkToValidatorsSec100(b *testing.B) { // this benchmarks constructing the validator set (.PubKey() * nodes) func benchmarkToValidatorsSec(b *testing.B, nodes int) { - keys := certifiers.GenSecpValKeys(nodes) + keys := light.GenSecpValKeys(nodes) for i := 1; i <= b.N; i++ { keys.ToValidators(int64(2*i), int64(i)) } } func BenchmarkCertifyCommit20(b *testing.B) { - keys := certifiers.GenValKeys(20) + keys := light.GenValKeys(20) benchmarkCertifyCommit(b, keys) } func BenchmarkCertifyCommit100(b *testing.B) { - keys := certifiers.GenValKeys(100) + keys := light.GenValKeys(100) benchmarkCertifyCommit(b, keys) } func BenchmarkCertifyCommitSec20(b *testing.B) { - keys := certifiers.GenSecpValKeys(20) + keys := light.GenSecpValKeys(20) benchmarkCertifyCommit(b, keys) } func BenchmarkCertifyCommitSec100(b *testing.B) { - keys := certifiers.GenSecpValKeys(100) + keys := light.GenSecpValKeys(100) benchmarkCertifyCommit(b, keys) } -func benchmarkCertifyCommit(b *testing.B, keys certifiers.ValKeys) { +func benchmarkCertifyCommit(b *testing.B, keys light.ValKeys) { chainID := "bench-certify" vals := keys.ToValidators(20, 10) - cert := certifiers.NewStatic(chainID, vals) + cert := light.NewStatic(chainID, vals) check := keys.GenCommit(chainID, 123, nil, vals, []byte("foo"), 0, len(keys)) for i := 0; i < b.N; i++ { err := cert.Certify(check) diff --git a/certifiers/provider.go b/light/provider.go similarity index 56% rename from certifiers/provider.go rename to light/provider.go index 64b4212d8..fa7f1d70e 100644 --- a/certifiers/provider.go +++ b/light/provider.go @@ -1,22 +1,18 @@ -package certifiers +package light -import ( - certerr "github.com/tendermint/tendermint/certifiers/errors" -) - -// Provider is used to get more validators by other means +// Provider is used to get more validators by other means. // -// Examples: MemProvider, files.Provider, client.Provider.... +// Examples: MemProvider, files.Provider, client.Provider, CacheProvider.... type Provider interface { // StoreCommit saves a FullCommit after we have verified it, // so we can query for it later. Important for updating our - // store of trusted commits + // store of trusted commits. StoreCommit(fc FullCommit) error - // GetByHeight returns the closest commit with height <= h + // GetByHeight returns the closest commit with height <= h. GetByHeight(h int) (FullCommit, error) - // GetByHash returns a commit exactly matching this validator hash + // GetByHash returns a commit exactly matching this validator hash. GetByHash(hash []byte) (FullCommit, error) - // LatestCommit returns the newest commit stored + // LatestCommit returns the newest commit stored. LatestCommit() (FullCommit, error) } @@ -28,6 +24,7 @@ type cacheProvider struct { Providers []Provider } +// NewCacheProvider returns a new provider which wraps multiple other providers. func NewCacheProvider(providers ...Provider) Provider { return cacheProvider{ Providers: providers, @@ -47,19 +44,17 @@ func (c cacheProvider) StoreCommit(fc FullCommit) (err error) { return err } -/* -GetByHeight should return the closest possible match from all providers. - -The Cache is usually organized in order from cheapest call (memory) -to most expensive calls (disk/network). However, since GetByHeight returns -a FullCommit at h' <= h, if the memory has a seed at h-10, but the network would -give us the exact match, a naive "stop at first non-error" would hide -the actual desired results. - -Thus, we query each provider in order until we find an exact match -or we finished querying them all. If at least one returned a non-error, -then this returns the best match (minimum h-h'). -*/ +// GetByHeight should return the closest possible match from all providers. +// +// The Cache is usually organized in order from cheapest call (memory) +// to most expensive calls (disk/network). However, since GetByHeight returns +// a FullCommit at h' <= h, if the memory has a seed at h-10, but the network would +// give us the exact match, a naive "stop at first non-error" would hide +// the actual desired results. +// +// Thus, we query each provider in order until we find an exact match +// or we finished querying them all. If at least one returned a non-error, +// then this returns the best match (minimum h-h'). func (c cacheProvider) GetByHeight(h int) (fc FullCommit, err error) { for _, p := range c.Providers { var tfc FullCommit @@ -80,6 +75,7 @@ func (c cacheProvider) GetByHeight(h int) (fc FullCommit, err error) { return fc, err } +// GetByHash returns the FullCommit for the hash or an error if the commit is not found. func (c cacheProvider) GetByHash(hash []byte) (fc FullCommit, err error) { for _, p := range c.Providers { fc, err = p.GetByHash(hash) @@ -90,6 +86,7 @@ func (c cacheProvider) GetByHash(hash []byte) (fc FullCommit, err error) { return fc, err } +// LatestCommit returns the latest FullCommit or an error if no commit exists. func (c cacheProvider) LatestCommit() (fc FullCommit, err error) { for _, p := range c.Providers { var tfc FullCommit @@ -104,22 +101,3 @@ func (c cacheProvider) LatestCommit() (fc FullCommit, err error) { } return fc, err } - -// missingProvider doens't store anything, always a miss -// Designed as a mock for testing -type missingProvider struct{} - -func NewMissingProvider() Provider { - return missingProvider{} -} - -func (missingProvider) StoreCommit(_ FullCommit) error { return nil } -func (missingProvider) GetByHeight(_ int) (FullCommit, error) { - return FullCommit{}, certerr.ErrCommitNotFound() -} -func (missingProvider) GetByHash(_ []byte) (FullCommit, error) { - return FullCommit{}, certerr.ErrCommitNotFound() -} -func (missingProvider) LatestCommit() (FullCommit, error) { - return FullCommit{}, certerr.ErrCommitNotFound() -} diff --git a/certifiers/provider_test.go b/light/provider_test.go similarity index 64% rename from certifiers/provider_test.go rename to light/provider_test.go index c1e9ae514..d9c1df670 100644 --- a/certifiers/provider_test.go +++ b/light/provider_test.go @@ -1,4 +1,5 @@ -package certifiers_test +// nolint: vetshadow +package light_test import ( "testing" @@ -6,32 +7,52 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/tendermint/tendermint/certifiers" - "github.com/tendermint/tendermint/certifiers/errors" + light "github.com/tendermint/tendermint/light" + lightErr "github.com/tendermint/tendermint/light/errors" ) +// missingProvider doens't store anything, always a miss +// Designed as a mock for testing +type missingProvider struct{} + +// NewMissingProvider returns a provider which does not store anything and always misses. +func NewMissingProvider() light.Provider { + return missingProvider{} +} + +func (missingProvider) StoreCommit(_ light.FullCommit) error { return nil } +func (missingProvider) GetByHeight(_ int) (light.FullCommit, error) { + return light.FullCommit{}, lightErr.ErrCommitNotFound() +} +func (missingProvider) GetByHash(_ []byte) (light.FullCommit, error) { + return light.FullCommit{}, lightErr.ErrCommitNotFound() +} +func (missingProvider) LatestCommit() (light.FullCommit, error) { + return light.FullCommit{}, lightErr.ErrCommitNotFound() +} + func TestMemProvider(t *testing.T) { - p := certifiers.NewMemStoreProvider() + p := light.NewMemStoreProvider() checkProvider(t, p, "test-mem", "empty") } func TestCacheProvider(t *testing.T) { - p := certifiers.NewCacheProvider( - certifiers.NewMissingProvider(), - certifiers.NewMemStoreProvider(), - certifiers.NewMissingProvider(), + p := light.NewCacheProvider( + NewMissingProvider(), + light.NewMemStoreProvider(), + NewMissingProvider(), ) checkProvider(t, p, "test-cache", "kjfhekfhkewhgit") } -func checkProvider(t *testing.T, p certifiers.Provider, chainID, app string) { +func checkProvider(t *testing.T, p light.Provider, chainID, app string) { assert, require := assert.New(t), require.New(t) appHash := []byte(app) - keys := certifiers.GenValKeys(5) + keys := light.GenValKeys(5) count := 10 // make a bunch of commits... - commits := make([]certifiers.FullCommit, count) + commits := make([]light.FullCommit, count) for i := 0; i < count; i++ { // two commits for each validator, to check how we handle dups // (10, 0), (10, 1), (10, 1), (10, 2), (10, 2), ... @@ -43,11 +64,11 @@ func checkProvider(t *testing.T, p certifiers.Provider, chainID, app string) { // check provider is empty fc, err := p.GetByHeight(20) require.NotNil(err) - assert.True(errors.IsCommitNotFoundErr(err)) + assert.True(lightErr.IsCommitNotFoundErr(err)) fc, err = p.GetByHash(commits[3].ValidatorsHash()) require.NotNil(err) - assert.True(errors.IsCommitNotFoundErr(err)) + assert.True(lightErr.IsCommitNotFoundErr(err)) // now add them all to the provider for _, s := range commits { @@ -80,7 +101,7 @@ func checkProvider(t *testing.T, p certifiers.Provider, chainID, app string) { } // this will make a get height, and if it is good, set the data as well -func checkGetHeight(t *testing.T, p certifiers.Provider, ask, expect int) { +func checkGetHeight(t *testing.T, p light.Provider, ask, expect int) { fc, err := p.GetByHeight(ask) require.Nil(t, err, "%+v", err) if assert.Equal(t, expect, fc.Height()) { @@ -95,13 +116,13 @@ func TestCacheGetsBestHeight(t *testing.T) { // we will write data to the second level of the cache (p2), // and see what gets cached, stored in - p := certifiers.NewMemStoreProvider() - p2 := certifiers.NewMemStoreProvider() - cp := certifiers.NewCacheProvider(p, p2) + p := light.NewMemStoreProvider() + p2 := light.NewMemStoreProvider() + cp := light.NewCacheProvider(p, p2) chainID := "cache-best-height" appHash := []byte("01234567") - keys := certifiers.GenValKeys(5) + keys := light.GenValKeys(5) count := 10 // set a bunch of commits diff --git a/certifiers/static.go b/light/static.go similarity index 79% rename from certifiers/static.go rename to light/static.go index 787aecb3f..f2482186d 100644 --- a/certifiers/static.go +++ b/light/static.go @@ -1,4 +1,4 @@ -package certifiers +package light import ( "bytes" @@ -7,7 +7,7 @@ import ( "github.com/tendermint/tendermint/types" - certerr "github.com/tendermint/tendermint/certifiers/errors" + lightErr "github.com/tendermint/tendermint/light/errors" ) var _ Certifier = &Static{} @@ -25,6 +25,7 @@ type Static struct { vhash []byte } +// NewStatic returns a new certifier with a static validator set. func NewStatic(chainID string, vals *types.ValidatorSet) *Static { return &Static{ chainID: chainID, @@ -32,14 +33,17 @@ func NewStatic(chainID string, vals *types.ValidatorSet) *Static { } } +// ChainID returns the chain id. func (c *Static) ChainID() string { return c.chainID } +// Validators returns the validator set. func (c *Static) Validators() *types.ValidatorSet { return c.vSet } +// Hash returns the hash of the validator set. func (c *Static) Hash() []byte { if len(c.vhash) == 0 { c.vhash = c.vSet.Hash() @@ -47,6 +51,7 @@ func (c *Static) Hash() []byte { return c.vhash } +// Certify makes sure that the commit is valid. func (c *Static) Certify(commit Commit) error { // do basic sanity checks err := commit.ValidateBasic(c.chainID) @@ -56,7 +61,7 @@ func (c *Static) Certify(commit Commit) error { // make sure it has the same validator set we have (static means static) if !bytes.Equal(c.Hash(), commit.Header.ValidatorsHash) { - return certerr.ErrValidatorsChanged() + return lightErr.ErrValidatorsChanged() } // then make sure we have the proper signatures for this diff --git a/certifiers/static_test.go b/light/static_test.go similarity index 81% rename from certifiers/static_test.go rename to light/static_test.go index f1f40c6c9..fbfa5c8fd 100644 --- a/certifiers/static_test.go +++ b/light/static_test.go @@ -1,4 +1,4 @@ -package certifiers_test +package light_test import ( "testing" @@ -7,8 +7,8 @@ import ( "github.com/tendermint/tendermint/types" - "github.com/tendermint/tendermint/certifiers" - errors "github.com/tendermint/tendermint/certifiers/errors" + "github.com/tendermint/tendermint/light" + lightErr "github.com/tendermint/tendermint/light/errors" ) func TestStaticCert(t *testing.T) { @@ -16,15 +16,15 @@ func TestStaticCert(t *testing.T) { assert := assert.New(t) // require := require.New(t) - keys := certifiers.GenValKeys(4) + keys := light.GenValKeys(4) // 20, 30, 40, 50 - the first 3 don't have 2/3, the last 3 do! vals := keys.ToValidators(20, 10) // and a certifier based on our known set chainID := "test-static" - cert := certifiers.NewStatic(chainID, vals) + cert := light.NewStatic(chainID, vals) cases := []struct { - keys certifiers.ValKeys + keys light.ValKeys vals *types.ValidatorSet height int first, last int // who actually signs @@ -51,7 +51,7 @@ func TestStaticCert(t *testing.T) { } else { assert.NotNil(err) if tc.changed { - assert.True(errors.IsValidatorsChangedErr(err), "%+v", err) + assert.True(lightErr.IsValidatorsChangedErr(err), "%+v", err) } } }