Browse Source

lite2: return height as 2nd return param in TrustedValidatorSet (#4479)

Closes #4473
pull/4485/head
Anton Kaliaev 4 years ago
committed by GitHub
parent
commit
b5f6bfa4f9
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 103 additions and 17 deletions
  1. +1
    -1
      docs/architecture/adr-046-light-client-implementation.md
  2. +11
    -6
      lite2/client.go
  3. +91
    -10
      lite2/client_test.go

+ 1
- 1
docs/architecture/adr-046-light-client-implementation.md View File

@ -28,7 +28,7 @@ type Client interface {
// get trusted headers & validators
TrustedHeader(height int64) (*types.SignedHeader, error)
TrustedValidatorSet(height int64) (*types.ValidatorSet, error)
TrustedValidatorSet(height int64) (valSet *types.ValidatorSet, heightUsed int64, err error)
LastTrustedHeight() (int64, error)
FirstTrustedHeight() (int64, error)


+ 11
- 6
lite2/client.go View File

@ -433,7 +433,8 @@ func (c *Client) TrustedHeader(height int64) (*types.SignedHeader, error) {
}
// TrustedValidatorSet returns a trusted validator set at the given height (0 -
// latest).
// latest). The second return parameter is the height used (useful if 0 was
// passed; otherwise can be ignored).
//
// height must be >= 0.
//
@ -448,18 +449,22 @@ func (c *Client) TrustedHeader(height int64) (*types.SignedHeader, error) {
// - header signed by that validator set has not been verified yet
//
// Safe for concurrent use by multiple goroutines.
func (c *Client) TrustedValidatorSet(height int64) (*types.ValidatorSet, error) {
height, err := c.compareWithLatestHeight(height)
func (c *Client) TrustedValidatorSet(height int64) (valSet *types.ValidatorSet, heightUsed int64, err error) {
heightUsed, err = c.compareWithLatestHeight(height)
if err != nil {
return nil, err
return nil, heightUsed, err
}
valSet, err = c.trustedStore.ValidatorSet(heightUsed)
if err != nil {
return nil, heightUsed, err
}
return c.trustedStore.ValidatorSet(height)
return valSet, heightUsed, err
}
func (c *Client) compareWithLatestHeight(height int64) (int64, error) {
latestHeight, err := c.LastTrustedHeight()
if err != nil {
return 0, err
return 0, errors.Wrap(err, "can't get last trusted height")
}
if latestHeight == -1 {
return 0, errors.New("no headers exist")


+ 91
- 10
lite2/client_test.go View File

@ -47,7 +47,9 @@ var (
}
headerSet = map[int64]*types.SignedHeader{
1: h1,
// interim header (3/3 signed)
2: h2,
// last header (3/3 signed)
3: h3,
}
fullNode = mockp.New(
@ -71,14 +73,7 @@ func TestClient_SequentialVerification(t *testing.T) {
}{
{
"good",
map[int64]*types.SignedHeader{
// trusted header
1: h1,
// interim header (3/3 signed)
2: h2,
// last header (3/3 signed)
3: h3,
},
headerSet,
valSet,
false,
false,
@ -322,10 +317,14 @@ func TestClient_Cleanup(t *testing.T) {
err = c.Cleanup()
require.NoError(t, err)
// Check no headers exist after Cleanup.
// Check no headers/valsets exist after Cleanup.
h, err := c.TrustedHeader(1)
assert.Error(t, err)
assert.Nil(t, h)
valSet, _, err := c.TrustedValidatorSet(1)
assert.Error(t, err)
assert.Nil(t, valSet)
}
// trustedHeader.Height == options.Height
@ -350,6 +349,13 @@ func TestClientRestoresTrustedHeaderAfterStartup1(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, h)
assert.Equal(t, h.Hash(), h1.Hash())
valSet, _, err := c.TrustedValidatorSet(1)
assert.NoError(t, err)
assert.NotNil(t, valSet)
if assert.NotNil(t, valSet) {
assert.Equal(t, h.ValidatorsHash.Bytes(), valSet.Hash())
}
}
// 2. options.Hash != trustedHeader.Hash
@ -390,6 +396,13 @@ func TestClientRestoresTrustedHeaderAfterStartup1(t *testing.T) {
if assert.NotNil(t, h) {
assert.Equal(t, h.Hash(), header1.Hash())
}
valSet, _, err := c.TrustedValidatorSet(1)
assert.NoError(t, err)
assert.NotNil(t, valSet)
if assert.NotNil(t, valSet) {
assert.Equal(t, h.ValidatorsHash.Bytes(), valSet.Hash())
}
}
}
@ -423,6 +436,13 @@ func TestClientRestoresTrustedHeaderAfterStartup2(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, h)
assert.Equal(t, h.Hash(), h1.Hash())
valSet, _, err := c.TrustedValidatorSet(1)
assert.NoError(t, err)
assert.NotNil(t, valSet)
if assert.NotNil(t, valSet) {
assert.Equal(t, h.ValidatorsHash.Bytes(), valSet.Hash())
}
}
// 2. options.Hash != trustedHeader.Hash
@ -469,6 +489,10 @@ func TestClientRestoresTrustedHeaderAfterStartup2(t *testing.T) {
h, err := c.TrustedHeader(1)
assert.Error(t, err)
assert.Nil(t, h)
valSet, _, err := c.TrustedValidatorSet(1)
assert.Error(t, err)
assert.Nil(t, valSet)
}
}
@ -504,10 +528,21 @@ func TestClientRestoresTrustedHeaderAfterStartup3(t *testing.T) {
assert.NotNil(t, h)
assert.Equal(t, h.Hash(), h1.Hash())
valSet, _, err := c.TrustedValidatorSet(1)
assert.NoError(t, err)
assert.NotNil(t, valSet)
if assert.NotNil(t, valSet) {
assert.Equal(t, h.ValidatorsHash.Bytes(), valSet.Hash())
}
// Check we no longer have 2nd header (+header2+).
h, err = c.TrustedHeader(2)
assert.Error(t, err)
assert.Nil(t, h)
valSet, _, err = c.TrustedValidatorSet(2)
assert.Error(t, err)
assert.Nil(t, valSet)
}
// 2. options.Hash != trustedHeader.Hash
@ -557,10 +592,21 @@ func TestClientRestoresTrustedHeaderAfterStartup3(t *testing.T) {
assert.NotNil(t, h)
assert.Equal(t, h.Hash(), header1.Hash())
valSet, _, err := c.TrustedValidatorSet(1)
assert.NoError(t, err)
assert.NotNil(t, valSet)
if assert.NotNil(t, valSet) {
assert.Equal(t, h.ValidatorsHash.Bytes(), valSet.Hash())
}
// Check we no longer have invalid 2nd header (+header2+).
h, err = c.TrustedHeader(2)
assert.Error(t, err)
assert.Nil(t, h)
valSet, _, err = c.TrustedValidatorSet(2)
assert.Error(t, err)
assert.Nil(t, valSet)
}
}
@ -586,6 +632,12 @@ func TestClient_Update(t *testing.T) {
assert.NoError(t, err)
require.NotNil(t, h)
assert.EqualValues(t, 3, h.Height)
valSet, _, err := c.TrustedValidatorSet(3)
assert.NoError(t, err)
if assert.NotNil(t, valSet) {
assert.Equal(t, h.ValidatorsHash.Bytes(), valSet.Hash())
}
}
func TestClient_Concurrency(t *testing.T) {
@ -627,7 +679,7 @@ func TestClient_Concurrency(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, h)
vals, err := c.TrustedValidatorSet(2)
vals, _, err := c.TrustedValidatorSet(2)
assert.NoError(t, err)
assert.NotNil(t, vals)
}()
@ -784,6 +836,13 @@ func TestClient_NewClientFromTrustedStore(t *testing.T) {
h, err := c.TrustedHeader(1)
assert.NoError(t, err)
assert.EqualValues(t, 1, h.Height)
valSet, _, err := c.TrustedValidatorSet(1)
assert.NoError(t, err)
assert.NotNil(t, valSet)
if assert.NotNil(t, valSet) {
assert.Equal(t, h.ValidatorsHash.Bytes(), valSet.Hash())
}
}
func TestNewClientErrorsIfAllWitnessesUnavailable(t *testing.T) {
@ -857,3 +916,25 @@ func TestClientRemovesWitnessIfItSendsUsIncorrectHeader(t *testing.T) {
assert.Error(t, err)
assert.EqualValues(t, 0, len(c.Witnesses()))
}
func TestClientTrustedValidatorSet(t *testing.T) {
c, err := NewClient(
chainID,
trustOptions,
fullNode,
[]provider.Provider{fullNode},
dbs.New(dbm.NewMemDB(), chainID),
UpdatePeriod(0),
Logger(log.TestingLogger()),
)
require.NoError(t, err)
_, err = c.VerifyHeaderAtHeight(2, bTime.Add(2*time.Hour).Add(1*time.Second))
require.NoError(t, err)
valSet, height, err := c.TrustedValidatorSet(0)
assert.NoError(t, err)
assert.NotNil(t, valSet)
assert.EqualValues(t, 2, height)
}

Loading…
Cancel
Save