mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-25 02:31:46 +00:00
Refactor "lite" to handle delayed validator set changes.
Also, fix consensus liveness issue.
This commit is contained in:
@ -1,98 +1,88 @@
|
||||
// nolint: vetshadow
|
||||
package lite_test
|
||||
package lite
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/tendermint/tendermint/lite"
|
||||
liteErr "github.com/tendermint/tendermint/lite/errors"
|
||||
lerr "github.com/tendermint/tendermint/lite/errors"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
dbm "github.com/tendermint/tmlibs/db"
|
||||
)
|
||||
|
||||
// missingProvider doesn't store anything, always a miss
|
||||
// Designed as a mock for testing
|
||||
// missingProvider doesn'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() lite.Provider {
|
||||
func NewMissingProvider() PersistentProvider {
|
||||
return missingProvider{}
|
||||
}
|
||||
|
||||
func (missingProvider) StoreCommit(lite.FullCommit) error { return nil }
|
||||
func (missingProvider) GetByHeight(int64) (lite.FullCommit, error) {
|
||||
return lite.FullCommit{}, liteErr.ErrCommitNotFound()
|
||||
func (missingProvider) SaveFullCommit(FullCommit) error { return nil }
|
||||
func (missingProvider) LatestFullCommit(chainID string, minHeight, maxHeight int64) (FullCommit, error) {
|
||||
return FullCommit{}, lerr.ErrCommitNotFound()
|
||||
}
|
||||
func (missingProvider) GetByHash([]byte) (lite.FullCommit, error) {
|
||||
return lite.FullCommit{}, liteErr.ErrCommitNotFound()
|
||||
}
|
||||
func (missingProvider) LatestCommit() (lite.FullCommit, error) {
|
||||
return lite.FullCommit{}, liteErr.ErrCommitNotFound()
|
||||
func (missingProvider) ValidatorSet(chainID string, height int64) (*types.ValidatorSet, error) {
|
||||
return nil, errors.New("missing validator set")
|
||||
}
|
||||
|
||||
func TestMemProvider(t *testing.T) {
|
||||
p := lite.NewMemStoreProvider()
|
||||
p := NewDBProvider(dbm.NewMemDB())
|
||||
checkProvider(t, p, "test-mem", "empty")
|
||||
}
|
||||
|
||||
func TestCacheProvider(t *testing.T) {
|
||||
p := lite.NewCacheProvider(
|
||||
func TestMultiProvider(t *testing.T) {
|
||||
p := NewMultiProvider(
|
||||
NewMissingProvider(),
|
||||
lite.NewMemStoreProvider(),
|
||||
NewDBProvider(dbm.NewMemDB()),
|
||||
NewMissingProvider(),
|
||||
)
|
||||
checkProvider(t, p, "test-cache", "kjfhekfhkewhgit")
|
||||
}
|
||||
|
||||
func checkProvider(t *testing.T, p lite.Provider, chainID, app string) {
|
||||
func checkProvider(t *testing.T, p PersistentProvider, chainID, app string) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
appHash := []byte(app)
|
||||
keys := lite.GenValKeys(5)
|
||||
keys := genPrivKeys(5)
|
||||
count := 10
|
||||
|
||||
// make a bunch of commits...
|
||||
commits := make([]lite.FullCommit, count)
|
||||
// Make a bunch of full commits.
|
||||
fcz := make([]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), ...
|
||||
vals := keys.ToValidators(10, int64(count/2))
|
||||
h := int64(20 + 10*i)
|
||||
commits[i] = keys.GenFullCommit(chainID, h, nil, vals, appHash, []byte("params"), []byte("results"), 0, 5)
|
||||
fcz[i] = keys.GenFullCommit(chainID, h, nil, vals, vals, appHash, []byte("params"), []byte("results"), 0, 5)
|
||||
}
|
||||
|
||||
// check provider is empty
|
||||
fc, err := p.GetByHeight(20)
|
||||
// Check that provider is initially empty.
|
||||
fc, err := p.LatestFullCommit(chainID, 1, 1<<63-1)
|
||||
require.NotNil(err)
|
||||
assert.True(liteErr.IsCommitNotFoundErr(err))
|
||||
assert.True(lerr.IsErrCommitNotFound(err))
|
||||
|
||||
fc, err = p.GetByHash(commits[3].ValidatorsHash())
|
||||
require.NotNil(err)
|
||||
assert.True(liteErr.IsCommitNotFoundErr(err))
|
||||
|
||||
// now add them all to the provider
|
||||
for _, s := range commits {
|
||||
err = p.StoreCommit(s)
|
||||
// Save all full commits to the provider.
|
||||
for _, fc := range fcz {
|
||||
err = p.SaveFullCommit(fc)
|
||||
require.Nil(err)
|
||||
// and make sure we can get it back
|
||||
s2, err := p.GetByHash(s.ValidatorsHash())
|
||||
// Make sure we can get it back.
|
||||
fc2, err := p.LatestFullCommit(chainID, fc.Height(), fc.Height())
|
||||
assert.Nil(err)
|
||||
assert.Equal(s, s2)
|
||||
// by height as well
|
||||
s2, err = p.GetByHeight(s.Height())
|
||||
assert.Nil(err)
|
||||
assert.Equal(s, s2)
|
||||
assert.Equal(fc.SignedHeader, fc2.SignedHeader)
|
||||
assert.Equal(fc.Validators, fc2.Validators)
|
||||
assert.Equal(fc.NextValidators, fc2.NextValidators)
|
||||
}
|
||||
|
||||
// make sure we get the last hash if we overstep
|
||||
fc, err = p.GetByHeight(5000)
|
||||
// Make sure we get the last hash if we overstep.
|
||||
fc, err = p.LatestFullCommit(chainID, 1, 5000)
|
||||
if assert.Nil(err) {
|
||||
assert.Equal(commits[count-1].Height(), fc.Height())
|
||||
assert.Equal(commits[count-1], fc)
|
||||
assert.Equal(fcz[count-1].Height(), fc.Height())
|
||||
assert.Equal(fcz[count-1], fc)
|
||||
}
|
||||
|
||||
// and middle ones as well
|
||||
fc, err = p.GetByHeight(47)
|
||||
// ... and middle ones as well.
|
||||
fc, err = p.LatestFullCommit(chainID, 1, 47)
|
||||
if assert.Nil(err) {
|
||||
// we only step by 10, so 40 must be the one below this
|
||||
assert.EqualValues(40, fc.Height())
|
||||
@ -100,50 +90,49 @@ func checkProvider(t *testing.T, p lite.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 lite.Provider, ask, expect int64) {
|
||||
fc, err := p.GetByHeight(ask)
|
||||
require.Nil(t, err, "GetByHeight")
|
||||
// This will make a get height, and if it is good, set the data as well.
|
||||
func checkLatestFullCommit(t *testing.T, p PersistentProvider, chainID string, ask, expect int64) {
|
||||
fc, err := p.LatestFullCommit(chainID, 1, ask)
|
||||
require.Nil(t, err)
|
||||
if assert.Equal(t, expect, fc.Height()) {
|
||||
err = p.StoreCommit(fc)
|
||||
require.Nil(t, err, "StoreCommit")
|
||||
err = p.SaveFullCommit(fc)
|
||||
require.Nil(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCacheGetsBestHeight(t *testing.T) {
|
||||
// assert, require := assert.New(t), require.New(t)
|
||||
func TestMultiLatestFullCommit(t *testing.T) {
|
||||
require := require.New(t)
|
||||
|
||||
// we will write data to the second level of the cache (p2),
|
||||
// and see what gets cached, stored in
|
||||
p := lite.NewMemStoreProvider()
|
||||
p2 := lite.NewMemStoreProvider()
|
||||
cp := lite.NewCacheProvider(p, p2)
|
||||
// We will write data to the second level of the cache (p2), and see what
|
||||
// gets cached/stored in.
|
||||
p := NewDBProvider(dbm.NewMemDB())
|
||||
p2 := NewDBProvider(dbm.NewMemDB())
|
||||
cp := NewMultiProvider(p, p2)
|
||||
|
||||
chainID := "cache-best-height"
|
||||
appHash := []byte("01234567")
|
||||
keys := lite.GenValKeys(5)
|
||||
keys := genPrivKeys(5)
|
||||
count := 10
|
||||
|
||||
// set a bunch of commits
|
||||
// Set a bunch of full commits.
|
||||
for i := 0; i < count; i++ {
|
||||
vals := keys.ToValidators(10, int64(count/2))
|
||||
h := int64(10 * (i + 1))
|
||||
fc := keys.GenFullCommit(chainID, h, nil, vals, appHash, []byte("params"), []byte("results"), 0, 5)
|
||||
err := p2.StoreCommit(fc)
|
||||
fc := keys.GenFullCommit(chainID, h, nil, vals, vals, appHash, []byte("params"), []byte("results"), 0, 5)
|
||||
err := p2.SaveFullCommit(fc)
|
||||
require.NoError(err)
|
||||
}
|
||||
|
||||
// let's get a few heights from the cache and set them proper
|
||||
checkGetHeight(t, cp, 57, 50)
|
||||
checkGetHeight(t, cp, 33, 30)
|
||||
// Get a few heights from the cache and set them proper.
|
||||
checkLatestFullCommit(t, cp, chainID, 57, 50)
|
||||
checkLatestFullCommit(t, cp, chainID, 33, 30)
|
||||
|
||||
// make sure they are set in p as well (but nothing else)
|
||||
checkGetHeight(t, p, 44, 30)
|
||||
checkGetHeight(t, p, 50, 50)
|
||||
checkGetHeight(t, p, 99, 50)
|
||||
checkLatestFullCommit(t, p, chainID, 44, 30)
|
||||
checkLatestFullCommit(t, p, chainID, 50, 50)
|
||||
checkLatestFullCommit(t, p, chainID, 99, 50)
|
||||
|
||||
// now, query the cache for a higher value
|
||||
checkGetHeight(t, p2, 99, 90)
|
||||
checkGetHeight(t, cp, 99, 90)
|
||||
checkLatestFullCommit(t, p2, chainID, 99, 90)
|
||||
checkLatestFullCommit(t, cp, chainID, 99, 90)
|
||||
}
|
||||
|
Reference in New Issue
Block a user