lite2: store current validator set (#4472)

Before we were storing trustedHeader (height=1) and trustedNextVals
(height=2).

After this change, we will be storing trustedHeader (height=1) and
trustedVals (height=1). This a) simplifies the code b) fixes #4399
inconsistent pairing issue c) gives a relayer access to the current
validator set #4470.

The only downside is more jumps during bisection. If validator set
changes between trustedHeader and the next header (by 2/3 or more), the
light client will be forced to download the next header and check that
2/3+ signed the transition. But we don't expect validator set change too
much and too often, so it's an acceptable compromise.

Closes #4470 and #4399
This commit is contained in:
Anton Kaliaev
2020-02-26 10:20:51 +01:00
committed by GitHub
parent 25d92d05f8
commit c4f7256766
8 changed files with 119 additions and 153 deletions
+9 -8
View File
@@ -31,9 +31,9 @@ func New(db dbm.DB, prefix string) store.Store {
return &dbs{db: db, prefix: prefix, cdc: cdc}
}
// SaveSignedHeaderAndNextValidatorSet persists SignedHeader and ValidatorSet
// to the db.
func (s *dbs) SaveSignedHeaderAndNextValidatorSet(sh *types.SignedHeader, valSet *types.ValidatorSet) error {
// SaveSignedHeaderAndValidatorSet persists SignedHeader and ValidatorSet to
// the db.
func (s *dbs) SaveSignedHeaderAndValidatorSet(sh *types.SignedHeader, valSet *types.ValidatorSet) error {
if sh.Height <= 0 {
panic("negative or zero height")
}
@@ -42,6 +42,7 @@ func (s *dbs) SaveSignedHeaderAndNextValidatorSet(sh *types.SignedHeader, valSet
if err != nil {
return errors.Wrap(err, "marshalling header")
}
valSetBz, err := s.cdc.MarshalBinaryLengthPrefixed(valSet)
if err != nil {
return errors.Wrap(err, "marshalling validator set")
@@ -49,22 +50,22 @@ func (s *dbs) SaveSignedHeaderAndNextValidatorSet(sh *types.SignedHeader, valSet
b := s.db.NewBatch()
b.Set(s.shKey(sh.Height), shBz)
b.Set(s.vsKey(sh.Height+1), valSetBz)
b.Set(s.vsKey(sh.Height), valSetBz)
err = b.WriteSync()
b.Close()
return err
}
// DeleteSignedHeaderAndNextValidatorSet deletes SignedHeader and ValidatorSet
// from the db.
func (s *dbs) DeleteSignedHeaderAndNextValidatorSet(height int64) error {
// DeleteSignedHeaderAndValidatorSet deletes SignedHeader and ValidatorSet from
// the db.
func (s *dbs) DeleteSignedHeaderAndValidatorSet(height int64) error {
if height <= 0 {
panic("negative or zero height")
}
b := s.db.NewBatch()
b.Delete(s.shKey(height))
b.Delete(s.vsKey(height + 1))
b.Delete(s.vsKey(height))
err := b.WriteSync()
b.Close()
return err
+9 -9
View File
@@ -24,7 +24,7 @@ func TestLast_FirstSignedHeaderHeight(t *testing.T) {
assert.EqualValues(t, -1, height)
// 1 key
err = dbStore.SaveSignedHeaderAndNextValidatorSet(
err = dbStore.SaveSignedHeaderAndValidatorSet(
&types.SignedHeader{Header: &types.Header{Height: 1}}, &types.ValidatorSet{})
require.NoError(t, err)
@@ -37,20 +37,20 @@ func TestLast_FirstSignedHeaderHeight(t *testing.T) {
assert.EqualValues(t, 1, height)
}
func Test_SaveSignedHeaderAndNextValidatorSet(t *testing.T) {
dbStore := New(dbm.NewMemDB(), "Test_SaveSignedHeaderAndNextValidatorSet")
func Test_SaveSignedHeaderAndValidatorSet(t *testing.T) {
dbStore := New(dbm.NewMemDB(), "Test_SaveSignedHeaderAndValidatorSet")
// Empty store
h, err := dbStore.SignedHeader(1)
require.Error(t, err)
assert.Nil(t, h)
valSet, err := dbStore.ValidatorSet(2)
valSet, err := dbStore.ValidatorSet(1)
require.Error(t, err)
assert.Nil(t, valSet)
// 1 key
err = dbStore.SaveSignedHeaderAndNextValidatorSet(
err = dbStore.SaveSignedHeaderAndValidatorSet(
&types.SignedHeader{Header: &types.Header{Height: 1}}, &types.ValidatorSet{})
require.NoError(t, err)
@@ -58,19 +58,19 @@ func Test_SaveSignedHeaderAndNextValidatorSet(t *testing.T) {
require.NoError(t, err)
assert.NotNil(t, h)
valSet, err = dbStore.ValidatorSet(2)
valSet, err = dbStore.ValidatorSet(1)
require.NoError(t, err)
assert.NotNil(t, valSet)
// Empty store
err = dbStore.DeleteSignedHeaderAndNextValidatorSet(1)
err = dbStore.DeleteSignedHeaderAndValidatorSet(1)
require.NoError(t, err)
h, err = dbStore.SignedHeader(1)
require.Error(t, err)
assert.Nil(t, h)
valSet, err = dbStore.ValidatorSet(2)
valSet, err = dbStore.ValidatorSet(1)
require.Error(t, err)
assert.Nil(t, valSet)
}
@@ -83,7 +83,7 @@ func Test_SignedHeaderAfter(t *testing.T) {
dbStore.SignedHeaderAfter(100)
})
err := dbStore.SaveSignedHeaderAndNextValidatorSet(
err := dbStore.SaveSignedHeaderAndValidatorSet(
&types.SignedHeader{Header: &types.Header{Height: 2}}, &types.ValidatorSet{})
require.NoError(t, err)
+1
View File
@@ -6,6 +6,7 @@ var (
// ErrSignedHeaderNotFound is returned when a store does not have the
// requested header.
ErrSignedHeaderNotFound = errors.New("signed header not found")
// ErrValidatorSetNotFound is returned when a store does not have the
// requested validator set.
ErrValidatorSetNotFound = errors.New("validator set not found")
+6 -6
View File
@@ -4,17 +4,17 @@ import "github.com/tendermint/tendermint/types"
// Store is anything that can persistenly store headers.
type Store interface {
// SaveSignedHeaderAndNextValidatorSet saves a SignedHeader (h: sh.Height)
// and a ValidatorSet (h: sh.Height+1).
// SaveSignedHeaderAndValidatorSet saves a SignedHeader (h: sh.Height) and a
// ValidatorSet (h: sh.Height).
//
// height must be > 0.
SaveSignedHeaderAndNextValidatorSet(sh *types.SignedHeader, valSet *types.ValidatorSet) error
SaveSignedHeaderAndValidatorSet(sh *types.SignedHeader, valSet *types.ValidatorSet) error
// DeleteSignedHeaderAndNextValidatorSet deletes SignedHeader (h: height) and
// ValidatorSet (h: height+1).
// DeleteSignedHeaderAndValidatorSet deletes SignedHeader (h: height) and
// ValidatorSet (h: height).
//
// height must be > 0.
DeleteSignedHeaderAndNextValidatorSet(height int64) error
DeleteSignedHeaderAndValidatorSet(height int64) error
// SignedHeader returns the SignedHeader that corresponds to the given
// height.