Remove Last Header from ClientState (#6873)
* implement features, fix tendermint tests * allow test headers to pass in custom nextvalidatorset * allow updates to previous heights and test * remove unnecessary testing feature * fix client tests * fix ibc tests, and updating consensus state * fix ibc-transfer tests * appease linter * Apply suggestions from code review Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> * add chainID test case * fix expPass value * Apply suggestions from code review Co-authored-by: colin axner <25233464+colin-axner@users.noreply.github.com> Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> * address rest of @colin-axner review * fix bug and errors * Apply suggestions from code review Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> * address rest of @colin-axner review * implement updating before frozen height Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Co-authored-by: colin axner <25233464+colin-axner@users.noreply.github.com>
This commit is contained in:
parent
0daf3c3271
commit
9b61e0947e
|
@ -136,7 +136,12 @@ func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, genAccs
|
|||
|
||||
// commit genesis changes
|
||||
app.Commit()
|
||||
app.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{Height: app.LastBlockHeight() + 1, AppHash: app.LastCommitID().Hash}})
|
||||
app.BeginBlock(abci.RequestBeginBlock{Header: abci.Header{
|
||||
Height: app.LastBlockHeight() + 1,
|
||||
AppHash: app.LastCommitID().Hash,
|
||||
ValidatorsHash: valSet.Hash(),
|
||||
NextValidatorsHash: valSet.Hash(),
|
||||
}})
|
||||
|
||||
return app
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ type ClientState interface {
|
|||
ClientType() ClientType
|
||||
GetLatestHeight() uint64
|
||||
IsFrozen() bool
|
||||
GetFrozenHeight() uint64
|
||||
Validate() error
|
||||
GetProofSpecs() []*ics23.ProofSpec
|
||||
|
||||
|
|
|
@ -58,8 +58,8 @@ func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.H
|
|||
return nil, sdkerrors.Wrapf(types.ErrClientNotFound, "cannot update client with ID %s", clientID)
|
||||
}
|
||||
|
||||
// addition to spec: prevent update if the client is frozen
|
||||
if clientState.IsFrozen() {
|
||||
// prevent update if the client is frozen before or at header height
|
||||
if clientState.IsFrozen() && clientState.GetFrozenHeight() <= header.GetHeight() {
|
||||
return nil, sdkerrors.Wrapf(types.ErrClientFrozen, "cannot update client with ID %s", clientID)
|
||||
}
|
||||
|
||||
|
@ -71,9 +71,16 @@ func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.H
|
|||
|
||||
switch clientType {
|
||||
case exported.Tendermint:
|
||||
trustedConsState, found := k.GetClientConsensusStateLTE(ctx, clientID, header.GetHeight())
|
||||
if !found {
|
||||
return nil, sdkerrors.Wrapf(types.ErrConsensusStateNotFound, "could not find consensus state less than header height: %d to verify header against", header.GetHeight())
|
||||
}
|
||||
clientState, consensusState, err = tendermint.CheckValidityAndUpdateState(
|
||||
clientState, header, ctx.BlockTime(),
|
||||
clientState, trustedConsState, header, ctx.BlockTime(),
|
||||
)
|
||||
if err != nil {
|
||||
err = sdkerrors.Wrapf(err, "failed to update client using trusted consensus state height %d", trustedConsState.GetHeight())
|
||||
}
|
||||
case exported.Localhost:
|
||||
// override client state and update the block height
|
||||
clientState = localhosttypes.NewClientState(
|
||||
|
|
|
@ -38,12 +38,12 @@ func (suite *KeeperTestSuite) TestCreateClient() {
|
|||
i := i
|
||||
if tc.expPanic {
|
||||
suite.Require().Panics(func() {
|
||||
clientState, err := ibctmtypes.Initialize(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
|
||||
clientState, err := ibctmtypes.Initialize(testChainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
|
||||
suite.Require().NoError(err, "err on client state initialization")
|
||||
suite.keeper.CreateClient(suite.ctx, tc.clientID, clientState, suite.consensusState)
|
||||
}, "Msg %d didn't panic: %s", i, tc.msg)
|
||||
} else {
|
||||
clientState, err := ibctmtypes.Initialize(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
|
||||
clientState, err := ibctmtypes.Initialize(testChainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err, "errored on initialization")
|
||||
suite.Require().NotNil(clientState, "valid test case %d failed: %s", i, tc.msg)
|
||||
|
@ -64,15 +64,19 @@ func (suite *KeeperTestSuite) TestCreateClient() {
|
|||
|
||||
func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
|
||||
// Must create header creation functions since suite.header gets recreated on each test case
|
||||
createValidUpdateFn := func(s *KeeperTestSuite) ibctmtypes.Header {
|
||||
return ibctmtypes.CreateTestHeader(testClientID, suite.header.Height+1, suite.header.Time.Add(time.Minute),
|
||||
createFutureUpdateFn := func(s *KeeperTestSuite) ibctmtypes.Header {
|
||||
return ibctmtypes.CreateTestHeader(testChainID, suite.header.Height+1, suite.header.Time.Add(time.Minute),
|
||||
suite.valSet, []tmtypes.PrivValidator{suite.privVal})
|
||||
}
|
||||
createInvalidUpdateFn := func(s *KeeperTestSuite) ibctmtypes.Header {
|
||||
return ibctmtypes.CreateTestHeader(testClientID, suite.header.Height-3, suite.header.Time.Add(time.Minute),
|
||||
createPastUpdateFn := func(s *KeeperTestSuite) ibctmtypes.Header {
|
||||
return ibctmtypes.CreateTestHeader(testChainID, suite.header.Height-3, suite.header.Time,
|
||||
suite.valSet, []tmtypes.PrivValidator{suite.privVal})
|
||||
}
|
||||
var updateHeader ibctmtypes.Header
|
||||
var (
|
||||
updateHeader ibctmtypes.Header
|
||||
clientState ibctmtypes.ClientState
|
||||
err error
|
||||
)
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
|
@ -80,41 +84,95 @@ func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
|
|||
expPass bool
|
||||
}{
|
||||
{"valid update", func() error {
|
||||
clientState, err := ibctmtypes.Initialize(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
|
||||
clientState, err = ibctmtypes.Initialize(testChainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = suite.keeper.CreateClient(suite.ctx, testClientID, clientState, suite.consensusState)
|
||||
updateHeader = createValidUpdateFn(suite)
|
||||
updateHeader = createFutureUpdateFn(suite)
|
||||
return err
|
||||
}, true},
|
||||
{"valid past update", func() error {
|
||||
clientState, err = ibctmtypes.Initialize(testChainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = suite.keeper.CreateClient(suite.ctx, testClientID, clientState, suite.consensusState)
|
||||
|
||||
// store previous consensus state
|
||||
prevConsState := ibctmtypes.ConsensusState{
|
||||
Height: 1,
|
||||
Timestamp: suite.past,
|
||||
NextValidatorsHash: suite.valSet.Hash(),
|
||||
ValidatorSet: suite.valSet,
|
||||
}
|
||||
suite.keeper.SetClientConsensusState(suite.ctx, testClientID, 1, prevConsState)
|
||||
|
||||
// updateHeader will fill in consensus state between prevConsState and suite.consState
|
||||
// clientState should not be updated
|
||||
updateHeader = createPastUpdateFn(suite)
|
||||
return nil
|
||||
}, true},
|
||||
{"client type not found", func() error {
|
||||
updateHeader = createValidUpdateFn(suite)
|
||||
updateHeader = createFutureUpdateFn(suite)
|
||||
|
||||
return nil
|
||||
}, false},
|
||||
{"client type and header type mismatch", func() error {
|
||||
suite.keeper.SetClientType(suite.ctx, testClientID, invalidClientType)
|
||||
updateHeader = createValidUpdateFn(suite)
|
||||
updateHeader = createFutureUpdateFn(suite)
|
||||
|
||||
return nil
|
||||
}, false},
|
||||
{"client state not found", func() error {
|
||||
suite.keeper.SetClientType(suite.ctx, testClientID, exported.Tendermint)
|
||||
updateHeader = createValidUpdateFn(suite)
|
||||
updateHeader = createFutureUpdateFn(suite)
|
||||
|
||||
return nil
|
||||
}, false},
|
||||
{"frozen client", func() error {
|
||||
clientState := ibctmtypes.ClientState{FrozenHeight: 1, LastHeader: suite.header}
|
||||
{"consensus state not found", func() error {
|
||||
clientState, err = ibctmtypes.Initialize(testChainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
suite.keeper.SetClientState(suite.ctx, testClientID, clientState)
|
||||
suite.keeper.SetClientType(suite.ctx, testClientID, exported.Tendermint)
|
||||
updateHeader = createValidUpdateFn(suite)
|
||||
updateHeader = createFutureUpdateFn(suite)
|
||||
|
||||
return nil
|
||||
}, false},
|
||||
{"frozen client before update", func() error {
|
||||
clientState = ibctmtypes.ClientState{FrozenHeight: 1, LatestHeight: testClientHeight}
|
||||
suite.keeper.SetClientState(suite.ctx, testClientID, clientState)
|
||||
suite.keeper.SetClientType(suite.ctx, testClientID, exported.Tendermint)
|
||||
updateHeader = createFutureUpdateFn(suite)
|
||||
|
||||
return nil
|
||||
}, false},
|
||||
{"valid past update before client was frozen", func() error {
|
||||
clientState, err = ibctmtypes.Initialize(testChainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
clientState.FrozenHeight = testClientHeight - 1
|
||||
_, err = suite.keeper.CreateClient(suite.ctx, testClientID, clientState, suite.consensusState)
|
||||
|
||||
// store previous consensus state
|
||||
prevConsState := ibctmtypes.ConsensusState{
|
||||
Height: 1,
|
||||
Timestamp: suite.past,
|
||||
NextValidatorsHash: suite.valSet.Hash(),
|
||||
ValidatorSet: suite.valSet,
|
||||
}
|
||||
suite.keeper.SetClientConsensusState(suite.ctx, testClientID, 1, prevConsState)
|
||||
|
||||
// updateHeader will fill in consensus state between prevConsState and suite.consState
|
||||
// clientState should not be updated
|
||||
updateHeader = createPastUpdateFn(suite)
|
||||
return nil
|
||||
}, true},
|
||||
{"invalid header", func() error {
|
||||
clientState, err := ibctmtypes.Initialize(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
|
||||
clientState, err = ibctmtypes.Initialize(testChainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -122,7 +180,7 @@ func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
updateHeader = createInvalidUpdateFn(suite)
|
||||
updateHeader = createPastUpdateFn(suite)
|
||||
|
||||
return nil
|
||||
}, false},
|
||||
|
@ -145,13 +203,14 @@ func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
|
|||
suite.Require().NoError(err, err)
|
||||
|
||||
expConsensusState := ibctmtypes.ConsensusState{
|
||||
Height: updateHeader.GetHeight(),
|
||||
Timestamp: updateHeader.Time,
|
||||
Root: commitmenttypes.NewMerkleRoot(updateHeader.AppHash),
|
||||
ValidatorSet: updateHeader.ValidatorSet,
|
||||
Height: updateHeader.GetHeight(),
|
||||
Timestamp: updateHeader.Time,
|
||||
Root: commitmenttypes.NewMerkleRoot(updateHeader.AppHash),
|
||||
NextValidatorsHash: updateHeader.NextValidatorsHash,
|
||||
ValidatorSet: updateHeader.ValidatorSet,
|
||||
}
|
||||
|
||||
clientState, found := suite.keeper.GetClientState(suite.ctx, testClientID)
|
||||
newClientState, found := suite.keeper.GetClientState(suite.ctx, testClientID)
|
||||
suite.Require().True(found, "valid test case %d failed: %s", i, tc.name)
|
||||
|
||||
consensusState, found := suite.keeper.GetClientConsensusState(suite.ctx, testClientID, updateHeader.GetHeight())
|
||||
|
@ -161,16 +220,20 @@ func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
|
|||
// recalculate cached totalVotingPower field for equality check
|
||||
tmConsState.ValidatorSet.TotalVotingPower()
|
||||
|
||||
tmClientState, ok := updatedClientState.(ibctmtypes.ClientState)
|
||||
suite.Require().True(ok, "client state is not a tendermint client state")
|
||||
// check returned client state is same as client state in store
|
||||
suite.Require().Equal(updatedClientState, newClientState, "updatedClient state not persisted correctly")
|
||||
|
||||
// recalculate cached totalVotingPower field for equality check
|
||||
tmClientState.LastHeader.ValidatorSet.TotalVotingPower()
|
||||
// Determine if clientState should be updated or not
|
||||
if uint64(updateHeader.Height) > clientState.GetLatestHeight() {
|
||||
// Header Height is greater than clientState latest Height, clientState should be updated with header.Height
|
||||
suite.Require().Equal(uint64(updateHeader.Height), updatedClientState.GetLatestHeight(), "clientstate height did not update")
|
||||
} else {
|
||||
// Update will add past consensus state, clientState should not be updated at all
|
||||
suite.Require().Equal(clientState.GetLatestHeight(), updatedClientState.GetLatestHeight(), "client state height updated for past header")
|
||||
}
|
||||
|
||||
suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
|
||||
suite.Require().Equal(updateHeader.GetHeight(), clientState.GetLatestHeight(), "client state height not updated correctly on case %s", tc.name)
|
||||
suite.Require().Equal(expConsensusState, consensusState, "consensus state should have been updated on case %s", tc.name)
|
||||
suite.Require().Equal(updatedClientState, tmClientState, "client states don't match")
|
||||
} else {
|
||||
suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
|
||||
}
|
||||
|
@ -228,7 +291,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
|||
},
|
||||
func() error {
|
||||
suite.consensusState.ValidatorSet = bothValSet
|
||||
clientState, err := ibctmtypes.Initialize(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
|
||||
clientState, err := ibctmtypes.Initialize(testChainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -248,7 +311,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
|||
},
|
||||
func() error {
|
||||
suite.consensusState.ValidatorSet = bothValSet
|
||||
clientState, err := ibctmtypes.Initialize(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
|
||||
clientState, err := ibctmtypes.Initialize(testChainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -273,7 +336,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
|||
ClientID: testClientID,
|
||||
},
|
||||
func() error {
|
||||
clientState := ibctmtypes.ClientState{FrozenHeight: 1, LastHeader: suite.header}
|
||||
clientState := ibctmtypes.ClientState{FrozenHeight: 1, LatestHeight: testClientHeight}
|
||||
suite.keeper.SetClientState(suite.ctx, testClientID, clientState)
|
||||
return nil
|
||||
},
|
||||
|
@ -288,7 +351,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
|||
ClientID: testClientID,
|
||||
},
|
||||
func() error {
|
||||
clientState := ibctmtypes.ClientState{FrozenHeight: 1, LastHeader: suite.header}
|
||||
clientState := ibctmtypes.ClientState{FrozenHeight: 1, LatestHeight: testClientHeight}
|
||||
suite.keeper.SetClientState(suite.ctx, testClientID, clientState)
|
||||
return nil
|
||||
},
|
||||
|
@ -303,7 +366,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
|||
ClientID: testClientID,
|
||||
},
|
||||
func() error {
|
||||
clientState, err := ibctmtypes.Initialize(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
|
||||
clientState, err := ibctmtypes.Initialize(testChainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -211,10 +211,11 @@ func (k Keeper) GetSelfConsensusState(ctx sdk.Context, height uint64) (exported.
|
|||
valSet := stakingtypes.Validators(histInfo.Valset)
|
||||
|
||||
consensusState := ibctmtypes.ConsensusState{
|
||||
Height: height,
|
||||
Timestamp: histInfo.Header.Time,
|
||||
Root: commitmenttypes.NewMerkleRoot(histInfo.Header.AppHash),
|
||||
ValidatorSet: tmtypes.NewValidatorSet(valSet.ToTmValidators()),
|
||||
Height: height,
|
||||
Timestamp: histInfo.Header.Time,
|
||||
Root: commitmenttypes.NewMerkleRoot(histInfo.Header.AppHash),
|
||||
NextValidatorsHash: histInfo.Header.NextValidatorsHash,
|
||||
ValidatorSet: tmtypes.NewValidatorSet(valSet.ToTmValidators()),
|
||||
}
|
||||
return consensusState, true
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
testChainID = "gaiahub"
|
||||
|
||||
testClientID = "gaiachain"
|
||||
testClientID2 = "ethbridge"
|
||||
testClientID3 = "ethermint"
|
||||
|
@ -45,11 +47,13 @@ type KeeperTestSuite struct {
|
|||
valSet *tmtypes.ValidatorSet
|
||||
privVal tmtypes.PrivValidator
|
||||
now time.Time
|
||||
past time.Time
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) SetupTest() {
|
||||
isCheckTx := false
|
||||
suite.now = time.Date(2020, 1, 2, 0, 0, 0, 0, time.UTC)
|
||||
suite.past = time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
now2 := suite.now.Add(time.Hour)
|
||||
app := simapp.Setup(isCheckTx)
|
||||
|
||||
|
@ -63,12 +67,13 @@ func (suite *KeeperTestSuite) SetupTest() {
|
|||
|
||||
validator := tmtypes.NewValidator(pubKey, 1)
|
||||
suite.valSet = tmtypes.NewValidatorSet([]*tmtypes.Validator{validator})
|
||||
suite.header = ibctmtypes.CreateTestHeader(testClientID, testClientHeight, now2, suite.valSet, []tmtypes.PrivValidator{suite.privVal})
|
||||
suite.header = ibctmtypes.CreateTestHeader(testChainID, testClientHeight, now2, suite.valSet, []tmtypes.PrivValidator{suite.privVal})
|
||||
suite.consensusState = ibctmtypes.ConsensusState{
|
||||
Height: testClientHeight,
|
||||
Timestamp: suite.now,
|
||||
Root: commitmenttypes.NewMerkleRoot([]byte("hash")),
|
||||
ValidatorSet: suite.valSet,
|
||||
Height: testClientHeight,
|
||||
Timestamp: suite.now,
|
||||
Root: commitmenttypes.NewMerkleRoot([]byte("hash")),
|
||||
NextValidatorsHash: suite.valSet.Hash(),
|
||||
ValidatorSet: suite.valSet,
|
||||
}
|
||||
|
||||
var validators stakingtypes.Validators
|
||||
|
@ -90,7 +95,7 @@ func TestKeeperTestSuite(t *testing.T) {
|
|||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestSetClientState() {
|
||||
clientState := ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}, commitmenttypes.GetSDKSpecs())
|
||||
clientState := ibctmtypes.NewClientState(testChainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, 0, commitmenttypes.GetSDKSpecs())
|
||||
suite.keeper.SetClientState(suite.ctx, testClientID, clientState)
|
||||
|
||||
retrievedState, found := suite.keeper.GetClientState(suite.ctx, testClientID)
|
||||
|
@ -124,9 +129,9 @@ func (suite KeeperTestSuite) TestGetAllClients() {
|
|||
testClientID2, testClientID3, testClientID,
|
||||
}
|
||||
expClients := []exported.ClientState{
|
||||
ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.NewClientState(testChainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, 0, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.NewClientState(testChainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, 0, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.NewClientState(testChainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, 0, commitmenttypes.GetSDKSpecs()),
|
||||
}
|
||||
|
||||
for i := range expClients {
|
||||
|
@ -148,9 +153,9 @@ func (suite KeeperTestSuite) TestGetAllGenesisClients() {
|
|||
testClientID2, testClientID3, testClientID,
|
||||
}
|
||||
expClients := []exported.ClientState{
|
||||
ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.NewClientState(testChainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, 0, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.NewClientState(testChainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, 0, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.NewClientState(testChainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, 0, commitmenttypes.GetSDKSpecs()),
|
||||
}
|
||||
|
||||
expGenClients := make([]types.GenesisClientState, len(expClients))
|
||||
|
@ -198,7 +203,7 @@ func (suite KeeperTestSuite) TestGetConsensusState() {
|
|||
|
||||
func (suite KeeperTestSuite) TestConsensusStateHelpers() {
|
||||
// initial setup
|
||||
clientState, err := ibctmtypes.Initialize(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
|
||||
clientState, err := ibctmtypes.Initialize(testChainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs())
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.keeper.SetClientState(suite.ctx, testClientID, clientState)
|
||||
|
@ -214,7 +219,7 @@ func (suite KeeperTestSuite) TestConsensusStateHelpers() {
|
|||
header := ibctmtypes.CreateTestHeader(testClientID, testClientHeight+5, suite.header.Time.Add(time.Minute), suite.valSet, []tmtypes.PrivValidator{suite.privVal})
|
||||
|
||||
// mock update functionality
|
||||
clientState.LastHeader = header
|
||||
clientState.LatestHeight = uint64(header.Height)
|
||||
suite.keeper.SetClientConsensusState(suite.ctx, testClientID, testClientHeight+5, nextState)
|
||||
suite.keeper.SetClientState(suite.ctx, testClientID, clientState)
|
||||
|
||||
|
@ -238,10 +243,10 @@ func (suite KeeperTestSuite) TestGetAllConsensusStates() {
|
|||
testClientID,
|
||||
[]exported.ConsensusState{
|
||||
ibctmtypes.NewConsensusState(
|
||||
suite.consensusState.Timestamp, commitmenttypes.NewMerkleRoot([]byte("hash")), suite.consensusState.GetHeight(), &tmtypes.ValidatorSet{},
|
||||
suite.consensusState.Timestamp, commitmenttypes.NewMerkleRoot([]byte("hash")), suite.consensusState.GetHeight(), nil, &tmtypes.ValidatorSet{},
|
||||
),
|
||||
ibctmtypes.NewConsensusState(
|
||||
suite.consensusState.Timestamp.Add(time.Minute), commitmenttypes.NewMerkleRoot([]byte("app_hash")), suite.consensusState.GetHeight()+1, &tmtypes.ValidatorSet{},
|
||||
suite.consensusState.Timestamp.Add(time.Minute), commitmenttypes.NewMerkleRoot([]byte("app_hash")), suite.consensusState.GetHeight()+1, nil, &tmtypes.ValidatorSet{},
|
||||
),
|
||||
},
|
||||
),
|
||||
|
@ -249,7 +254,7 @@ func (suite KeeperTestSuite) TestGetAllConsensusStates() {
|
|||
testClientID2,
|
||||
[]exported.ConsensusState{
|
||||
ibctmtypes.NewConsensusState(
|
||||
suite.consensusState.Timestamp.Add(2*time.Minute), commitmenttypes.NewMerkleRoot([]byte("app_hash_2")), suite.consensusState.GetHeight()+2, &tmtypes.ValidatorSet{},
|
||||
suite.consensusState.Timestamp.Add(2*time.Minute), commitmenttypes.NewMerkleRoot([]byte("app_hash_2")), suite.consensusState.GetHeight()+2, nil, &tmtypes.ValidatorSet{},
|
||||
),
|
||||
},
|
||||
),
|
||||
|
|
|
@ -17,8 +17,11 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
chainID = "chainID"
|
||||
clientID = "ethbridge"
|
||||
|
||||
height = 10
|
||||
|
||||
trustingPeriod time.Duration = time.Hour * 24 * 7 * 2
|
||||
ubdPeriod time.Duration = time.Hour * 24 * 7 * 3
|
||||
maxClockDrift time.Duration = time.Second * 10
|
||||
|
@ -34,7 +37,7 @@ func TestValidateGenesis(t *testing.T) {
|
|||
val := tmtypes.NewValidator(pubKey, 10)
|
||||
valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{val})
|
||||
|
||||
header := ibctmtypes.CreateTestHeader("chainID", 10, now, valSet, []tmtypes.PrivValidator{privVal})
|
||||
header := ibctmtypes.CreateTestHeader(chainID, height, now, valSet, []tmtypes.PrivValidator{privVal})
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
|
@ -51,7 +54,7 @@ func TestValidateGenesis(t *testing.T) {
|
|||
genState: types.NewGenesisState(
|
||||
[]types.GenesisClientState{
|
||||
types.NewGenesisClientState(
|
||||
clientID, ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, header, commitmenttypes.GetSDKSpecs()),
|
||||
clientID, ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
),
|
||||
types.NewGenesisClientState(
|
||||
exported.ClientTypeLocalHost, localhosttypes.NewClientState("chainID", 10),
|
||||
|
@ -62,7 +65,7 @@ func TestValidateGenesis(t *testing.T) {
|
|||
clientID,
|
||||
[]exported.ConsensusState{
|
||||
ibctmtypes.NewConsensusState(
|
||||
header.Time, commitmenttypes.NewMerkleRoot(header.AppHash), header.GetHeight(), header.ValidatorSet,
|
||||
header.Time, commitmenttypes.NewMerkleRoot(header.AppHash), header.GetHeight(), header.ValidatorSet.Hash(), header.ValidatorSet,
|
||||
),
|
||||
},
|
||||
},
|
||||
|
@ -76,7 +79,7 @@ func TestValidateGenesis(t *testing.T) {
|
|||
genState: types.NewGenesisState(
|
||||
[]types.GenesisClientState{
|
||||
types.NewGenesisClientState(
|
||||
"/~@$*", ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, header, commitmenttypes.GetSDKSpecs()),
|
||||
"/~@$*", ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
),
|
||||
types.NewGenesisClientState(
|
||||
exported.ClientTypeLocalHost, localhosttypes.NewClientState("chainID", 10),
|
||||
|
@ -87,7 +90,7 @@ func TestValidateGenesis(t *testing.T) {
|
|||
clientID,
|
||||
[]exported.ConsensusState{
|
||||
ibctmtypes.NewConsensusState(
|
||||
header.Time, commitmenttypes.NewMerkleRoot(header.AppHash), header.GetHeight(), header.ValidatorSet,
|
||||
header.Time, commitmenttypes.NewMerkleRoot(header.AppHash), header.GetHeight(), header.ValidatorSet.Hash(), header.ValidatorSet,
|
||||
),
|
||||
},
|
||||
},
|
||||
|
@ -102,7 +105,7 @@ func TestValidateGenesis(t *testing.T) {
|
|||
genState: types.NewGenesisState(
|
||||
[]types.GenesisClientState{
|
||||
types.NewGenesisClientState(
|
||||
clientID, ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, header, commitmenttypes.GetSDKSpecs()),
|
||||
clientID, ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
),
|
||||
types.NewGenesisClientState(exported.ClientTypeLocalHost, localhosttypes.NewClientState("chaindID", 0)),
|
||||
},
|
||||
|
@ -116,7 +119,7 @@ func TestValidateGenesis(t *testing.T) {
|
|||
genState: types.NewGenesisState(
|
||||
[]types.GenesisClientState{
|
||||
types.NewGenesisClientState(
|
||||
clientID, ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, header, commitmenttypes.GetSDKSpecs()),
|
||||
clientID, ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
),
|
||||
types.NewGenesisClientState(
|
||||
exported.ClientTypeLocalHost, localhosttypes.NewClientState("chaindID", 10),
|
||||
|
@ -127,7 +130,7 @@ func TestValidateGenesis(t *testing.T) {
|
|||
"CLIENTID2",
|
||||
[]exported.ConsensusState{
|
||||
ibctmtypes.NewConsensusState(
|
||||
header.Time, commitmenttypes.NewMerkleRoot(header.AppHash), 0, header.ValidatorSet,
|
||||
header.Time, commitmenttypes.NewMerkleRoot(header.AppHash), 0, header.ValidatorSet.Hash(), header.ValidatorSet,
|
||||
),
|
||||
},
|
||||
},
|
||||
|
@ -141,7 +144,7 @@ func TestValidateGenesis(t *testing.T) {
|
|||
genState: types.NewGenesisState(
|
||||
[]types.GenesisClientState{
|
||||
types.NewGenesisClientState(
|
||||
clientID, ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, header, commitmenttypes.GetSDKSpecs()),
|
||||
clientID, ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
),
|
||||
types.NewGenesisClientState(
|
||||
exported.ClientTypeLocalHost, localhosttypes.NewClientState("chaindID", 10),
|
||||
|
@ -152,7 +155,7 @@ func TestValidateGenesis(t *testing.T) {
|
|||
clientID,
|
||||
[]exported.ConsensusState{
|
||||
ibctmtypes.NewConsensusState(
|
||||
header.Time, commitmenttypes.NewMerkleRoot(header.AppHash), 0, header.ValidatorSet,
|
||||
header.Time, commitmenttypes.NewMerkleRoot(header.AppHash), 0, header.ValidatorSet.Hash(), header.ValidatorSet,
|
||||
),
|
||||
},
|
||||
),
|
||||
|
|
|
@ -54,7 +54,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() {
|
|||
}{
|
||||
{
|
||||
"valid misbehavior evidence",
|
||||
ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet},
|
||||
ibctmtypes.Evidence{
|
||||
Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothSigners),
|
||||
|
@ -69,7 +69,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() {
|
|||
},
|
||||
{
|
||||
"valid misbehavior at height greater than last consensusState",
|
||||
ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.ConsensusState{Timestamp: suite.now, Height: height - 1, Root: commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet},
|
||||
ibctmtypes.Evidence{
|
||||
Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothSigners),
|
||||
|
@ -84,7 +84,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() {
|
|||
},
|
||||
{
|
||||
"consensus state's valset hash different from evidence should still pass",
|
||||
ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.ConsensusState{Timestamp: suite.now, Height: height - 1, Root: commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: suite.valSet},
|
||||
ibctmtypes.Evidence{
|
||||
Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothSigners),
|
||||
|
@ -129,7 +129,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() {
|
|||
},
|
||||
{
|
||||
"invalid tendermint consensus state",
|
||||
ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
nil,
|
||||
ibctmtypes.Evidence{
|
||||
Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, altValSet, altSigners),
|
||||
|
@ -144,7 +144,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() {
|
|||
},
|
||||
{
|
||||
"invalid tendermint misbehaviour evidence",
|
||||
ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet},
|
||||
nil,
|
||||
simapp.DefaultConsensusParams,
|
||||
|
@ -154,7 +154,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() {
|
|||
},
|
||||
{
|
||||
"rejected misbehaviour due to expired age",
|
||||
ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet},
|
||||
ibctmtypes.Evidence{
|
||||
Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothSigners),
|
||||
|
@ -169,7 +169,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() {
|
|||
},
|
||||
{
|
||||
"provided height ≠ header height",
|
||||
ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet},
|
||||
ibctmtypes.Evidence{
|
||||
Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothSigners),
|
||||
|
@ -184,7 +184,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() {
|
|||
},
|
||||
{
|
||||
"unbonding period expired",
|
||||
ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.ConsensusState{Timestamp: time.Time{}, Root: commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet},
|
||||
ibctmtypes.Evidence{
|
||||
Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothSigners),
|
||||
|
@ -199,7 +199,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() {
|
|||
},
|
||||
{
|
||||
"first valset has too much change",
|
||||
ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet},
|
||||
ibctmtypes.Evidence{
|
||||
Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, altValSet, altSigners),
|
||||
|
@ -214,7 +214,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() {
|
|||
},
|
||||
{
|
||||
"second valset has too much change",
|
||||
ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet},
|
||||
ibctmtypes.Evidence{
|
||||
Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, bothValSet, bothSigners),
|
||||
|
@ -229,7 +229,7 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviour() {
|
|||
},
|
||||
{
|
||||
"both valsets have too much change",
|
||||
ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
ibctmtypes.ConsensusState{Timestamp: suite.now, Root: commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), ValidatorSet: bothValSet},
|
||||
ibctmtypes.Evidence{
|
||||
Header1: ibctmtypes.CreateTestHeader(chainID, height, suite.now, altValSet, altSigners),
|
||||
|
|
|
@ -26,6 +26,7 @@ type TendermintTestSuite struct {
|
|||
suite.Suite
|
||||
|
||||
cdc *codec.Codec
|
||||
signers []tmtypes.PrivValidator
|
||||
privVal tmtypes.PrivValidator
|
||||
valSet *tmtypes.ValidatorSet
|
||||
header ibctmtypes.Header
|
||||
|
@ -47,15 +48,18 @@ func (suite *TendermintTestSuite) SetupTest() {
|
|||
// Header time is intended to be time for any new header used for updates
|
||||
suite.headerTime = time.Date(2020, 1, 2, 0, 0, 0, 0, time.UTC)
|
||||
suite.privVal = tmtypes.NewMockPV()
|
||||
suite.signers = []tmtypes.PrivValidator{suite.privVal}
|
||||
|
||||
pubKey, err := suite.privVal.GetPubKey()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
val := tmtypes.NewValidator(pubKey, 10)
|
||||
suite.valSet = tmtypes.NewValidatorSet([]*tmtypes.Validator{val})
|
||||
|
||||
// Suite header is intended to be header passed in for initial ClientState
|
||||
// Thus it should have same height and time as ClientState
|
||||
suite.header = ibctmtypes.CreateTestHeader(chainID, height, suite.clientTime, suite.valSet, []tmtypes.PrivValidator{suite.privVal})
|
||||
// Note: default header has the same validator set suite.valSet as next validators set
|
||||
suite.header = ibctmtypes.CreateTestHeader(chainID, height, suite.clientTime, suite.valSet, suite.signers)
|
||||
}
|
||||
|
||||
func TestTendermintTestSuite(t *testing.T) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
ics23 "github.com/confio/ics23/go"
|
||||
|
@ -26,6 +27,8 @@ var _ clientexported.ClientState = ClientState{}
|
|||
// ClientState from Tendermint tracks the current validator set, latest height,
|
||||
// and a possible frozen height.
|
||||
type ClientState struct {
|
||||
ChainID string `json:"chain_id" yaml:"chain_id"`
|
||||
|
||||
TrustLevel tmmath.Fraction `json:"trust_level" yaml:"trust_level"`
|
||||
|
||||
// Duration of the period since the LastestTimestamp during which the
|
||||
|
@ -42,8 +45,8 @@ type ClientState struct {
|
|||
// Block height when the client was frozen due to a misbehaviour
|
||||
FrozenHeight uint64 `json:"frozen_height" yaml:"frozen_height"`
|
||||
|
||||
// Last Header that was stored by client
|
||||
LastHeader Header `json:"last_header" yaml:"last_header"`
|
||||
// Latest height the client was updated up to
|
||||
LatestHeight uint64 `json:"latest_height" yaml:"latest_height"`
|
||||
|
||||
ProofSpecs []*ics23.ProofSpec `json:"proof_specs" yaml:"proof_specs"`
|
||||
}
|
||||
|
@ -51,47 +54,48 @@ type ClientState struct {
|
|||
// InitializeFromMsg creates a tendermint client state from a CreateClientMsg
|
||||
func InitializeFromMsg(msg *MsgCreateClient) (ClientState, error) {
|
||||
return Initialize(
|
||||
msg.Header.ChainID,
|
||||
msg.TrustLevel,
|
||||
msg.TrustingPeriod, msg.UnbondingPeriod, msg.MaxClockDrift,
|
||||
msg.Header, msg.ProofSpecs,
|
||||
uint64(msg.Header.Height), msg.ProofSpecs,
|
||||
)
|
||||
}
|
||||
|
||||
// Initialize creates a client state and validates its contents, checking that
|
||||
// the provided consensus state is from the same client type.
|
||||
func Initialize(
|
||||
chainID string,
|
||||
trustLevel tmmath.Fraction,
|
||||
trustingPeriod, ubdPeriod, maxClockDrift time.Duration,
|
||||
header Header, specs []*ics23.ProofSpec,
|
||||
latestHeight uint64, specs []*ics23.ProofSpec,
|
||||
) (ClientState, error) {
|
||||
clientState := NewClientState(trustLevel, trustingPeriod, ubdPeriod, maxClockDrift, header, specs)
|
||||
clientState := NewClientState(chainID, trustLevel, trustingPeriod, ubdPeriod, maxClockDrift, latestHeight, specs)
|
||||
|
||||
return clientState, nil
|
||||
}
|
||||
|
||||
// NewClientState creates a new ClientState instance
|
||||
func NewClientState(
|
||||
chainID string,
|
||||
trustLevel tmmath.Fraction,
|
||||
trustingPeriod, ubdPeriod, maxClockDrift time.Duration,
|
||||
header Header, specs []*ics23.ProofSpec,
|
||||
latestHeight uint64, specs []*ics23.ProofSpec,
|
||||
) ClientState {
|
||||
return ClientState{
|
||||
ChainID: chainID,
|
||||
TrustLevel: trustLevel,
|
||||
TrustingPeriod: trustingPeriod,
|
||||
UnbondingPeriod: ubdPeriod,
|
||||
MaxClockDrift: maxClockDrift,
|
||||
LastHeader: header,
|
||||
LatestHeight: latestHeight,
|
||||
FrozenHeight: 0,
|
||||
ProofSpecs: specs,
|
||||
}
|
||||
}
|
||||
|
||||
// GetChainID returns the chain-id from the last header
|
||||
// GetChainID returns the chain-id
|
||||
func (cs ClientState) GetChainID() string {
|
||||
if cs.LastHeader.SignedHeader.Header == nil {
|
||||
return ""
|
||||
}
|
||||
return cs.LastHeader.SignedHeader.Header.ChainID
|
||||
return cs.ChainID
|
||||
}
|
||||
|
||||
// ClientType is tendermint.
|
||||
|
@ -101,12 +105,7 @@ func (cs ClientState) ClientType() clientexported.ClientType {
|
|||
|
||||
// GetLatestHeight returns latest block height.
|
||||
func (cs ClientState) GetLatestHeight() uint64 {
|
||||
return uint64(cs.LastHeader.Height)
|
||||
}
|
||||
|
||||
// GetLatestTimestamp returns latest block time.
|
||||
func (cs ClientState) GetLatestTimestamp() time.Time {
|
||||
return cs.LastHeader.Time
|
||||
return cs.LatestHeight
|
||||
}
|
||||
|
||||
// IsFrozen returns true if the frozen height has been set.
|
||||
|
@ -114,8 +113,17 @@ func (cs ClientState) IsFrozen() bool {
|
|||
return cs.FrozenHeight != 0
|
||||
}
|
||||
|
||||
// FrozenHeight returns the height at which client is frozen
|
||||
// NOTE: FrozenHeight is 0 if client is unfrozen
|
||||
func (cs ClientState) GetFrozenHeight() uint64 {
|
||||
return cs.FrozenHeight
|
||||
}
|
||||
|
||||
// Validate performs a basic validation of the client state fields.
|
||||
func (cs ClientState) Validate() error {
|
||||
if strings.TrimSpace(cs.ChainID) == "" {
|
||||
return sdkerrors.Wrap(ErrInvalidChainID, "chain id cannot be empty string")
|
||||
}
|
||||
if err := lite.ValidateTrustLevel(cs.TrustLevel); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -128,6 +136,9 @@ func (cs ClientState) Validate() error {
|
|||
if cs.MaxClockDrift == 0 {
|
||||
return sdkerrors.Wrap(ErrInvalidMaxClockDrift, "max clock drift cannot be zero")
|
||||
}
|
||||
if cs.LatestHeight == 0 {
|
||||
return sdkerrors.Wrap(ErrInvalidHeaderHeight, "tendermint height cannot be zero")
|
||||
}
|
||||
if cs.TrustingPeriod >= cs.UnbondingPeriod {
|
||||
return sdkerrors.Wrapf(
|
||||
ErrInvalidTrustingPeriod,
|
||||
|
@ -144,7 +155,7 @@ func (cs ClientState) Validate() error {
|
|||
}
|
||||
}
|
||||
|
||||
return cs.LastHeader.ValidateBasic(cs.GetChainID())
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetProofSpecs returns the format the client expects for proof verification
|
||||
|
|
|
@ -28,47 +28,52 @@ func (suite *TendermintTestSuite) TestValidate() {
|
|||
}{
|
||||
{
|
||||
name: "valid client",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
expPass: true,
|
||||
},
|
||||
{
|
||||
name: "invalid chainID",
|
||||
clientState: ibctmtypes.NewClientState(" ", lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "invalid trust level",
|
||||
clientState: ibctmtypes.NewClientState(tmmath.Fraction{Numerator: 0, Denominator: 1}, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, tmmath.Fraction{Numerator: 0, Denominator: 1}, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "invalid trusting period",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, 0, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, 0, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "invalid unbonding period",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, 0, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, 0, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "invalid max clock drift",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, 0, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, 0, height, commitmenttypes.GetSDKSpecs()),
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "invalid header",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, ibctmtypes.Header{}, commitmenttypes.GetSDKSpecs()),
|
||||
name: "invalid height",
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, 0, commitmenttypes.GetSDKSpecs()),
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "trusting period not less than unbonding period",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "proof specs is nil",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, suite.header, nil),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, height, nil),
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "proof specs contains nil",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, suite.header, []*ics23.ProofSpec{ics23.TendermintSpec, nil}),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, height, []*ics23.ProofSpec{ics23.TendermintSpec, nil}),
|
||||
expPass: false,
|
||||
},
|
||||
}
|
||||
|
@ -95,7 +100,7 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
|
|||
// FIXME: uncomment
|
||||
// {
|
||||
// name: "successful verification",
|
||||
// clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
// clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
// consensusState: ibctmtypes.ConsensusState{
|
||||
// Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
// },
|
||||
|
@ -104,7 +109,7 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
|
|||
// },
|
||||
{
|
||||
name: "ApplyPrefix failed",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
},
|
||||
|
@ -113,7 +118,7 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
|
|||
},
|
||||
{
|
||||
name: "latest client height < height",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
},
|
||||
|
@ -122,7 +127,7 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
|
|||
},
|
||||
{
|
||||
name: "client is frozen",
|
||||
clientState: ibctmtypes.ClientState{LastHeader: suite.header, FrozenHeight: height - 1},
|
||||
clientState: ibctmtypes.ClientState{LatestHeight: height, FrozenHeight: height - 1},
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
},
|
||||
|
@ -131,7 +136,7 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
|
|||
},
|
||||
{
|
||||
name: "proof verification failed",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
ValidatorSet: suite.valSet,
|
||||
|
@ -173,7 +178,7 @@ func (suite *TendermintTestSuite) TestVerifyConnectionState() {
|
|||
// FIXME: uncomment
|
||||
// {
|
||||
// name: "successful verification",
|
||||
// clientState: ibctmtypes.NewClientState(chainID, chainID, height, commitmenttypes.GetSDKSpecs()),
|
||||
// clientState: ibctmtypes.NewClientState(chainID, chainID, chainID, height, commitmenttypes.GetSDKSpecs()),
|
||||
// connection: conn,
|
||||
// consensusState: ibctmtypes.ConsensusState{
|
||||
// Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
|
@ -183,7 +188,7 @@ func (suite *TendermintTestSuite) TestVerifyConnectionState() {
|
|||
// },
|
||||
{
|
||||
name: "ApplyPrefix failed",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
connection: conn,
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
|
@ -193,7 +198,7 @@ func (suite *TendermintTestSuite) TestVerifyConnectionState() {
|
|||
},
|
||||
{
|
||||
name: "latest client height < height",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
connection: conn,
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
|
@ -203,7 +208,7 @@ func (suite *TendermintTestSuite) TestVerifyConnectionState() {
|
|||
},
|
||||
{
|
||||
name: "client is frozen",
|
||||
clientState: ibctmtypes.ClientState{LastHeader: suite.header, FrozenHeight: height - 1},
|
||||
clientState: ibctmtypes.ClientState{LatestHeight: height, FrozenHeight: height - 1},
|
||||
connection: conn,
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
|
@ -213,7 +218,7 @@ func (suite *TendermintTestSuite) TestVerifyConnectionState() {
|
|||
},
|
||||
{
|
||||
name: "proof verification failed",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
connection: conn,
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
|
@ -266,7 +271,7 @@ func (suite *TendermintTestSuite) TestVerifyChannelState() {
|
|||
// },
|
||||
{
|
||||
name: "ApplyPrefix failed",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
channel: ch,
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
|
@ -276,7 +281,7 @@ func (suite *TendermintTestSuite) TestVerifyChannelState() {
|
|||
},
|
||||
{
|
||||
name: "latest client height < height",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
channel: ch,
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
|
@ -286,7 +291,7 @@ func (suite *TendermintTestSuite) TestVerifyChannelState() {
|
|||
},
|
||||
{
|
||||
name: "client is frozen",
|
||||
clientState: ibctmtypes.ClientState{LastHeader: suite.header, FrozenHeight: height - 1},
|
||||
clientState: ibctmtypes.ClientState{LatestHeight: height, FrozenHeight: height - 1},
|
||||
channel: ch,
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
|
@ -296,7 +301,7 @@ func (suite *TendermintTestSuite) TestVerifyChannelState() {
|
|||
},
|
||||
{
|
||||
name: "proof verification failed",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
channel: ch,
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
|
@ -346,7 +351,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketCommitment() {
|
|||
// },
|
||||
{
|
||||
name: "ApplyPrefix failed",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
commitment: []byte{},
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
|
@ -356,7 +361,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketCommitment() {
|
|||
},
|
||||
{
|
||||
name: "latest client height < height",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
commitment: []byte{},
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
|
@ -366,7 +371,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketCommitment() {
|
|||
},
|
||||
{
|
||||
name: "client is frozen",
|
||||
clientState: ibctmtypes.ClientState{LastHeader: suite.header, FrozenHeight: height - 1},
|
||||
clientState: ibctmtypes.ClientState{LatestHeight: height, FrozenHeight: height - 1},
|
||||
commitment: []byte{},
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
|
@ -376,7 +381,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketCommitment() {
|
|||
},
|
||||
{
|
||||
name: "proof verification failed",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
commitment: []byte{},
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
|
@ -416,7 +421,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgement() {
|
|||
// FIXME: uncomment
|
||||
// {
|
||||
// name: "successful verification",
|
||||
// clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
// clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
// connection: conn,
|
||||
// consensusState: ibctmtypes.ConsensusState{
|
||||
// Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
|
@ -426,7 +431,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgement() {
|
|||
// },
|
||||
{
|
||||
name: "ApplyPrefix failed",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
ack: []byte{},
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
|
@ -436,7 +441,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgement() {
|
|||
},
|
||||
{
|
||||
name: "latest client height < height",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
ack: []byte{},
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
|
@ -446,7 +451,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgement() {
|
|||
},
|
||||
{
|
||||
name: "client is frozen",
|
||||
clientState: ibctmtypes.ClientState{LastHeader: suite.header, FrozenHeight: height - 1},
|
||||
clientState: ibctmtypes.ClientState{LatestHeight: height, FrozenHeight: height - 1},
|
||||
ack: []byte{},
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
|
@ -456,7 +461,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgement() {
|
|||
},
|
||||
{
|
||||
name: "proof verification failed",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
ack: []byte{},
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
|
@ -505,7 +510,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgementAbsence() {
|
|||
// },
|
||||
{
|
||||
name: "ApplyPrefix failed",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
},
|
||||
|
@ -514,7 +519,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgementAbsence() {
|
|||
},
|
||||
{
|
||||
name: "latest client height < height",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
},
|
||||
|
@ -523,7 +528,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgementAbsence() {
|
|||
},
|
||||
{
|
||||
name: "client is frozen",
|
||||
clientState: ibctmtypes.ClientState{LastHeader: suite.header, FrozenHeight: height - 1},
|
||||
clientState: ibctmtypes.ClientState{LatestHeight: height, FrozenHeight: height - 1},
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
},
|
||||
|
@ -532,7 +537,7 @@ func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgementAbsence() {
|
|||
},
|
||||
{
|
||||
name: "proof verification failed",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
ValidatorSet: suite.valSet,
|
||||
|
@ -580,7 +585,7 @@ func (suite *TendermintTestSuite) TestVerifyNextSeqRecv() {
|
|||
// },
|
||||
{
|
||||
name: "ApplyPrefix failed",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
},
|
||||
|
@ -589,7 +594,7 @@ func (suite *TendermintTestSuite) TestVerifyNextSeqRecv() {
|
|||
},
|
||||
{
|
||||
name: "latest client height < height",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
},
|
||||
|
@ -598,7 +603,7 @@ func (suite *TendermintTestSuite) TestVerifyNextSeqRecv() {
|
|||
},
|
||||
{
|
||||
name: "client is frozen",
|
||||
clientState: ibctmtypes.ClientState{LastHeader: suite.header, FrozenHeight: height - 1},
|
||||
clientState: ibctmtypes.ClientState{LatestHeight: height, FrozenHeight: height - 1},
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
},
|
||||
|
@ -607,7 +612,7 @@ func (suite *TendermintTestSuite) TestVerifyNextSeqRecv() {
|
|||
},
|
||||
{
|
||||
name: "proof verification failed",
|
||||
clientState: ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientState: ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
consensusState: ibctmtypes.ConsensusState{
|
||||
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
|
||||
ValidatorSet: suite.valSet,
|
||||
|
|
|
@ -3,6 +3,7 @@ package types
|
|||
import (
|
||||
"time"
|
||||
|
||||
tmbytes "github.com/tendermint/tendermint/libs/bytes"
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
|
@ -13,22 +14,24 @@ import (
|
|||
|
||||
// ConsensusState defines a Tendermint consensus state
|
||||
type ConsensusState struct {
|
||||
Timestamp time.Time `json:"timestamp" yaml:"timestamp"`
|
||||
Root commitmentexported.Root `json:"root" yaml:"root"`
|
||||
Height uint64 `json:"height" yaml:"height"`
|
||||
ValidatorSet *tmtypes.ValidatorSet `json:"validator_set" yaml:"validator_set"`
|
||||
Timestamp time.Time `json:"timestamp" yaml:"timestamp"`
|
||||
Root commitmentexported.Root `json:"root" yaml:"root"`
|
||||
Height uint64 `json:"height" yaml:"height"`
|
||||
NextValidatorsHash tmbytes.HexBytes `json:"next_validators_hash"` // validators hash for the next block
|
||||
ValidatorSet *tmtypes.ValidatorSet `json:"validator_set" yaml:"validator_set"`
|
||||
}
|
||||
|
||||
// NewConsensusState creates a new ConsensusState instance.
|
||||
func NewConsensusState(
|
||||
timestamp time.Time, root commitmentexported.Root, height uint64,
|
||||
valset *tmtypes.ValidatorSet,
|
||||
nextValsHash tmbytes.HexBytes, valset *tmtypes.ValidatorSet,
|
||||
) ConsensusState {
|
||||
return ConsensusState{
|
||||
Timestamp: timestamp,
|
||||
Root: root,
|
||||
Height: height,
|
||||
ValidatorSet: valset,
|
||||
Timestamp: timestamp,
|
||||
Root: root,
|
||||
Height: height,
|
||||
NextValidatorsHash: nextValsHash,
|
||||
ValidatorSet: valset,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,6 +63,9 @@ func (cs ConsensusState) ValidateBasic() error {
|
|||
if cs.ValidatorSet == nil {
|
||||
return sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "validator set cannot be nil")
|
||||
}
|
||||
if err := tmtypes.ValidateHash(cs.NextValidatorsHash); err != nil {
|
||||
return sdkerrors.Wrap(err, "next validators hash is invalid")
|
||||
}
|
||||
if cs.Height == 0 {
|
||||
return sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "height cannot be 0")
|
||||
}
|
||||
|
|
|
@ -10,11 +10,13 @@ const (
|
|||
|
||||
// IBC tendermint client sentinel errors
|
||||
var (
|
||||
ErrInvalidTrustingPeriod = sdkerrors.Register(SubModuleName, 2, "invalid trusting period")
|
||||
ErrInvalidUnbondingPeriod = sdkerrors.Register(SubModuleName, 3, "invalid unbonding period")
|
||||
ErrInvalidHeader = sdkerrors.Register(SubModuleName, 4, "invalid header")
|
||||
ErrInvalidMaxClockDrift = sdkerrors.Register(SubModuleName, 5, "invalid max clock drift")
|
||||
ErrTrustingPeriodExpired = sdkerrors.Register(SubModuleName, 6, "time since latest trusted state has passed the trusting period")
|
||||
ErrUnbondingPeriodExpired = sdkerrors.Register(SubModuleName, 7, "time since latest trusted state has passed the unbonding period")
|
||||
ErrInvalidProofSpecs = sdkerrors.Register(SubModuleName, 8, "invalid proof specs")
|
||||
ErrInvalidChainID = sdkerrors.Register(SubModuleName, 2, "invalid chain-id")
|
||||
ErrInvalidTrustingPeriod = sdkerrors.Register(SubModuleName, 3, "invalid trusting period")
|
||||
ErrInvalidUnbondingPeriod = sdkerrors.Register(SubModuleName, 4, "invalid unbonding period")
|
||||
ErrInvalidHeaderHeight = sdkerrors.Register(SubModuleName, 5, "invalid header height")
|
||||
ErrInvalidHeader = sdkerrors.Register(SubModuleName, 6, "invalid header")
|
||||
ErrInvalidMaxClockDrift = sdkerrors.Register(SubModuleName, 7, "invalid max clock drift")
|
||||
ErrTrustingPeriodExpired = sdkerrors.Register(SubModuleName, 8, "time since latest trusted state has passed the trusting period")
|
||||
ErrUnbondingPeriodExpired = sdkerrors.Register(SubModuleName, 9, "time since latest trusted state has passed the unbonding period")
|
||||
ErrInvalidProofSpecs = sdkerrors.Register(SubModuleName, 10, "invalid proof specs")
|
||||
)
|
||||
|
|
|
@ -142,10 +142,11 @@ func (msg MsgCreateClient) GetConsensusState() clientexported.ConsensusState {
|
|||
// Construct initial consensus state from provided Header
|
||||
root := commitmenttypes.NewMerkleRoot(msg.Header.AppHash)
|
||||
return ConsensusState{
|
||||
Timestamp: msg.Header.Time,
|
||||
Root: root,
|
||||
Height: uint64(msg.Header.Height),
|
||||
ValidatorSet: msg.Header.ValidatorSet,
|
||||
Timestamp: msg.Header.Time,
|
||||
Root: root,
|
||||
Height: uint64(msg.Header.Height),
|
||||
NextValidatorsHash: msg.Header.NextValidatorsHash,
|
||||
ValidatorSet: msg.Header.ValidatorSet,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"time"
|
||||
|
||||
lite "github.com/tendermint/tendermint/lite2"
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
|
||||
|
@ -12,18 +13,28 @@ import (
|
|||
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
|
||||
)
|
||||
|
||||
// CheckValidityAndUpdateState checks if the provided header is valid and updates
|
||||
// the consensus state if appropriate. It returns an error if:
|
||||
// CheckValidityAndUpdateState checks if the provided header is valid, and if valid it will:
|
||||
// create the consensus state for the header.Height
|
||||
// and update the client state if the header height is greater than the latest client state height
|
||||
// It returns an error if:
|
||||
// - the client or header provided are not parseable to tendermint types
|
||||
// - the header is invalid
|
||||
// - header height is lower than the latest client height
|
||||
// - header height is less than or equal to the consensus state height
|
||||
// - header valset commit verification fails
|
||||
// - header timestamp is past the trusting period in relation to the consensus state
|
||||
// - header timestamp is less than or equal to the consensus state timestamp
|
||||
//
|
||||
// UpdateClient may be used to either create a consensus state for:
|
||||
// - a future height greater than the latest client state height
|
||||
// - a past height that was skipped during bisection
|
||||
// If we are updating to a past height, a consensus state is created for that height to be persisted in client store
|
||||
// If we are updating to a future height, the consensus state is created and the client state is updated to reflect
|
||||
// the new latest height
|
||||
// Tendermint client validity checking uses the bisection algorithm described
|
||||
// in the [Tendermint spec](https://github.com/tendermint/spec/blob/master/spec/consensus/light-client.md).
|
||||
func CheckValidityAndUpdateState(
|
||||
clientState clientexported.ClientState, header clientexported.Header,
|
||||
currentTimestamp time.Time,
|
||||
clientState clientexported.ClientState, consState clientexported.ConsensusState,
|
||||
header clientexported.Header, currentTimestamp time.Time,
|
||||
) (clientexported.ClientState, clientexported.ConsensusState, error) {
|
||||
tmClientState, ok := clientState.(types.ClientState)
|
||||
if !ok {
|
||||
|
@ -32,6 +43,13 @@ func CheckValidityAndUpdateState(
|
|||
)
|
||||
}
|
||||
|
||||
tmConsState, ok := consState.(types.ConsensusState)
|
||||
if !ok {
|
||||
return nil, nil, sdkerrors.Wrapf(
|
||||
clienttypes.ErrInvalidConsensus, "expected type %T, got %T", types.ConsensusState{}, consState,
|
||||
)
|
||||
}
|
||||
|
||||
tmHeader, ok := header.(types.Header)
|
||||
if !ok {
|
||||
return nil, nil, sdkerrors.Wrapf(
|
||||
|
@ -39,7 +57,7 @@ func CheckValidityAndUpdateState(
|
|||
)
|
||||
}
|
||||
|
||||
if err := checkValidity(tmClientState, tmHeader, currentTimestamp); err != nil {
|
||||
if err := checkValidity(tmClientState, tmConsState, tmHeader, currentTimestamp); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
|
@ -48,49 +66,58 @@ func CheckValidityAndUpdateState(
|
|||
}
|
||||
|
||||
// checkValidity checks if the Tendermint header is valid.
|
||||
//
|
||||
// CONTRACT: assumes header.Height > consensusState.Height
|
||||
func checkValidity(
|
||||
clientState types.ClientState, header types.Header, currentTimestamp time.Time,
|
||||
clientState types.ClientState, consState types.ConsensusState, header types.Header, currentTimestamp time.Time,
|
||||
) error {
|
||||
// assert trusting period has not yet passed
|
||||
if currentTimestamp.Sub(clientState.GetLatestTimestamp()) >= clientState.TrustingPeriod {
|
||||
if currentTimestamp.Sub(consState.Timestamp) >= clientState.TrustingPeriod {
|
||||
return sdkerrors.Wrapf(
|
||||
types.ErrTrustingPeriodExpired,
|
||||
"current timestamp minus the latest trusted client state timestamp is greater than or equal to the trusting period (%s >= %s)",
|
||||
currentTimestamp.Sub(clientState.GetLatestTimestamp()), clientState.TrustingPeriod,
|
||||
"current timestamp minus the consensus state timestamp is greater than or equal to the trusting period (%s >= %s)",
|
||||
currentTimestamp.Sub(consState.Timestamp), clientState.TrustingPeriod,
|
||||
)
|
||||
}
|
||||
|
||||
// assert header timestamp is not past the trusting period
|
||||
if header.Time.Sub(clientState.GetLatestTimestamp()) >= clientState.TrustingPeriod {
|
||||
if header.Time.Sub(consState.Timestamp) >= clientState.TrustingPeriod {
|
||||
return sdkerrors.Wrap(
|
||||
clienttypes.ErrInvalidHeader,
|
||||
"header blocktime is outside trusting period from last client timestamp",
|
||||
"header timestamp is beyond trusting period in relation to the consensus state timestamp",
|
||||
)
|
||||
}
|
||||
|
||||
// assert header timestamp is past latest clientstate timestamp
|
||||
if header.Time.Unix() <= clientState.GetLatestTimestamp().Unix() {
|
||||
// assert header timestamp is past latest stored consensus state timestamp
|
||||
if header.Time.Unix() <= consState.Timestamp.Unix() {
|
||||
return sdkerrors.Wrapf(
|
||||
clienttypes.ErrInvalidHeader,
|
||||
"header blocktime ≤ latest client state block time (%s ≤ %s)",
|
||||
header.Time.UTC(), clientState.GetLatestTimestamp().UTC(),
|
||||
"header timestamp ≤ consensus state timestamp (%s ≤ %s)",
|
||||
header.Time.UTC(), consState.Timestamp.UTC(),
|
||||
)
|
||||
}
|
||||
|
||||
// assert header height is newer than any we know
|
||||
if header.GetHeight() <= clientState.GetLatestHeight() {
|
||||
// assert header height is newer than consensus state
|
||||
if header.GetHeight() <= consState.Height {
|
||||
return sdkerrors.Wrapf(
|
||||
clienttypes.ErrInvalidHeader,
|
||||
"header height ≤ latest client state height (%d ≤ %d)", header.GetHeight(), clientState.GetLatestHeight(),
|
||||
"header height ≤ consensus state height (%d ≤ %d)", header.GetHeight(), consState.Height,
|
||||
)
|
||||
}
|
||||
|
||||
// Construct a trusted header using the fields in consensus state
|
||||
// Only Height, Time, and NextValidatorsHash are necessary for verification
|
||||
trustedHeader := tmtypes.Header{
|
||||
Height: int64(consState.Height),
|
||||
Time: consState.Timestamp,
|
||||
NextValidatorsHash: consState.NextValidatorsHash,
|
||||
}
|
||||
signedHeader := tmtypes.SignedHeader{
|
||||
Header: &trustedHeader,
|
||||
}
|
||||
|
||||
// Verify next header with the last header's validatorset as trusted validatorset
|
||||
err := lite.Verify(
|
||||
clientState.GetChainID(), &clientState.LastHeader.SignedHeader,
|
||||
clientState.LastHeader.ValidatorSet, &header.SignedHeader, header.ValidatorSet,
|
||||
clientState.GetChainID(), &signedHeader,
|
||||
consState.ValidatorSet, &header.SignedHeader, header.ValidatorSet,
|
||||
clientState.TrustingPeriod, currentTimestamp, clientState.MaxClockDrift, clientState.TrustLevel,
|
||||
)
|
||||
if err != nil {
|
||||
|
@ -101,12 +128,15 @@ func checkValidity(
|
|||
|
||||
// update the consensus state from a new header
|
||||
func update(clientState types.ClientState, header types.Header) (types.ClientState, types.ConsensusState) {
|
||||
clientState.LastHeader = header
|
||||
if uint64(header.Height) > clientState.LatestHeight {
|
||||
clientState.LatestHeight = uint64(header.Height)
|
||||
}
|
||||
consensusState := types.ConsensusState{
|
||||
Height: uint64(header.Height),
|
||||
Timestamp: header.Time,
|
||||
Root: commitmenttypes.NewMerkleRoot(header.AppHash),
|
||||
ValidatorSet: header.ValidatorSet,
|
||||
Height: uint64(header.Height),
|
||||
Timestamp: header.Time,
|
||||
Root: commitmenttypes.NewMerkleRoot(header.AppHash),
|
||||
NextValidatorsHash: header.NextValidatorsHash,
|
||||
ValidatorSet: header.ValidatorSet,
|
||||
}
|
||||
|
||||
return clientState, consensusState
|
||||
|
|
|
@ -14,9 +14,10 @@ import (
|
|||
|
||||
func (suite *TendermintTestSuite) TestCheckValidity() {
|
||||
var (
|
||||
clientState ibctmtypes.ClientState
|
||||
newHeader ibctmtypes.Header
|
||||
currentTime time.Time
|
||||
clientState ibctmtypes.ClientState
|
||||
consensusState ibctmtypes.ConsensusState
|
||||
newHeader ibctmtypes.Header
|
||||
currentTime time.Time
|
||||
)
|
||||
|
||||
// Setup different validators and signers for testing different types of updates
|
||||
|
@ -54,7 +55,8 @@ func (suite *TendermintTestSuite) TestCheckValidity() {
|
|||
{
|
||||
name: "successful update with next height and same validator set",
|
||||
setup: func() {
|
||||
clientState = ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
|
||||
clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
|
||||
consensusState = ibctmtypes.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.AppHash), height, suite.valSet.Hash(), suite.valSet)
|
||||
newHeader = ibctmtypes.CreateTestHeader(chainID, height+1, suite.headerTime, suite.valSet, signers)
|
||||
currentTime = suite.now
|
||||
},
|
||||
|
@ -63,25 +65,58 @@ func (suite *TendermintTestSuite) TestCheckValidity() {
|
|||
{
|
||||
name: "successful update with future height and different validator set",
|
||||
setup: func() {
|
||||
clientState = ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
|
||||
clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
|
||||
consensusState = ibctmtypes.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.AppHash), height, suite.valSet.Hash(), suite.valSet)
|
||||
newHeader = ibctmtypes.CreateTestHeader(chainID, height+5, suite.headerTime, bothValSet, bothSigners)
|
||||
currentTime = suite.now
|
||||
},
|
||||
expPass: true,
|
||||
},
|
||||
{
|
||||
name: "successful update with next height and different validator set",
|
||||
setup: func() {
|
||||
clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
|
||||
consensusState = ibctmtypes.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.AppHash), height, bothValSet.Hash(), suite.valSet)
|
||||
newHeader = ibctmtypes.CreateTestHeader(chainID, height+1, suite.headerTime, bothValSet, bothSigners)
|
||||
currentTime = suite.now
|
||||
},
|
||||
expPass: true,
|
||||
},
|
||||
{
|
||||
name: "successful update for a previous height",
|
||||
setup: func() {
|
||||
clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
|
||||
consensusState = ibctmtypes.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.AppHash), height-3, bothValSet.Hash(), suite.valSet)
|
||||
newHeader = ibctmtypes.CreateTestHeader(chainID, height-1, suite.headerTime, bothValSet, bothSigners)
|
||||
currentTime = suite.now
|
||||
},
|
||||
expPass: true,
|
||||
},
|
||||
{
|
||||
name: "unsuccessful update with next height: update header mismatches nextValSetHash",
|
||||
setup: func() {
|
||||
clientState = ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
|
||||
clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
|
||||
consensusState = ibctmtypes.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.AppHash), height, suite.valSet.Hash(), suite.valSet)
|
||||
newHeader = ibctmtypes.CreateTestHeader(chainID, height+1, suite.headerTime, bothValSet, bothSigners)
|
||||
currentTime = suite.now
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "unsuccessful update with next height: update header mismatches different nextValSetHash",
|
||||
setup: func() {
|
||||
clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
|
||||
consensusState = ibctmtypes.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.AppHash), height, bothValSet.Hash(), suite.valSet)
|
||||
newHeader = ibctmtypes.CreateTestHeader(chainID, height+1, suite.headerTime, suite.valSet, signers)
|
||||
currentTime = suite.now
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "unsuccessful update with future height: too much change in validator set",
|
||||
setup: func() {
|
||||
clientState = ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
|
||||
clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
|
||||
consensusState = ibctmtypes.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.AppHash), height, suite.valSet.Hash(), suite.valSet)
|
||||
newHeader = ibctmtypes.CreateTestHeader(chainID, height+5, suite.headerTime, altValSet, altSigners)
|
||||
currentTime = suite.now
|
||||
},
|
||||
|
@ -90,17 +125,19 @@ func (suite *TendermintTestSuite) TestCheckValidity() {
|
|||
{
|
||||
name: "unsuccessful update: trusting period has passed since last client timestamp",
|
||||
setup: func() {
|
||||
clientState = ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
|
||||
clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
|
||||
consensusState = ibctmtypes.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.AppHash), height, suite.valSet.Hash(), suite.valSet)
|
||||
newHeader = ibctmtypes.CreateTestHeader(chainID, height+1, suite.headerTime, suite.valSet, signers)
|
||||
// make current time pass trusting period from last timestamp on clientstate
|
||||
currentTime = suite.now.Add(ubdPeriod)
|
||||
currentTime = suite.now.Add(trustingPeriod)
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "unsuccessful update: header timestamp is past current timestamp",
|
||||
setup: func() {
|
||||
clientState = ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
|
||||
clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
|
||||
consensusState = ibctmtypes.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.AppHash), height, suite.valSet.Hash(), suite.valSet)
|
||||
newHeader = ibctmtypes.CreateTestHeader(chainID, height+1, suite.now.Add(time.Minute), suite.valSet, signers)
|
||||
currentTime = suite.now
|
||||
},
|
||||
|
@ -109,7 +146,8 @@ func (suite *TendermintTestSuite) TestCheckValidity() {
|
|||
{
|
||||
name: "unsuccessful update: header timestamp is not past last client timestamp",
|
||||
setup: func() {
|
||||
clientState = ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
|
||||
clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
|
||||
consensusState = ibctmtypes.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.AppHash), height, suite.valSet.Hash(), suite.valSet)
|
||||
newHeader = ibctmtypes.CreateTestHeader(chainID, height+1, suite.clientTime, suite.valSet, signers)
|
||||
currentTime = suite.now
|
||||
},
|
||||
|
@ -118,7 +156,8 @@ func (suite *TendermintTestSuite) TestCheckValidity() {
|
|||
{
|
||||
name: "header basic validation failed",
|
||||
setup: func() {
|
||||
clientState = ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
|
||||
clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
|
||||
consensusState = ibctmtypes.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.AppHash), height, suite.valSet.Hash(), suite.valSet)
|
||||
newHeader = ibctmtypes.CreateTestHeader(chainID, height+1, suite.headerTime, suite.valSet, signers)
|
||||
// cause new header to fail validatebasic by changing commit height to mismatch header height
|
||||
newHeader.SignedHeader.Commit.Height = height - 1
|
||||
|
@ -127,14 +166,14 @@ func (suite *TendermintTestSuite) TestCheckValidity() {
|
|||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "header height < latest client height",
|
||||
name: "header height < consensus height",
|
||||
setup: func() {
|
||||
clientState = ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs())
|
||||
clientState = ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height+5, commitmenttypes.GetSDKSpecs())
|
||||
consensusState = ibctmtypes.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.AppHash), height, suite.valSet.Hash(), suite.valSet)
|
||||
// Make new header at height less than latest client state
|
||||
newHeader = ibctmtypes.CreateTestHeader(chainID, height-1, suite.headerTime, suite.valSet, signers)
|
||||
currentTime = suite.now
|
||||
},
|
||||
|
||||
expPass: false,
|
||||
},
|
||||
}
|
||||
|
@ -145,21 +184,31 @@ func (suite *TendermintTestSuite) TestCheckValidity() {
|
|||
tc.setup()
|
||||
|
||||
expectedConsensus := ibctmtypes.ConsensusState{
|
||||
Height: uint64(newHeader.Height),
|
||||
Timestamp: newHeader.Time,
|
||||
Root: commitmenttypes.NewMerkleRoot(newHeader.AppHash),
|
||||
ValidatorSet: newHeader.ValidatorSet,
|
||||
Height: uint64(newHeader.Height),
|
||||
Timestamp: newHeader.Time,
|
||||
Root: commitmenttypes.NewMerkleRoot(newHeader.AppHash),
|
||||
NextValidatorsHash: newHeader.NextValidatorsHash,
|
||||
ValidatorSet: newHeader.ValidatorSet,
|
||||
}
|
||||
|
||||
clientState, consensusState, err := tendermint.CheckValidityAndUpdateState(clientState, newHeader, currentTime)
|
||||
newClientState, consensusState, err := tendermint.CheckValidityAndUpdateState(clientState, consensusState, newHeader, currentTime)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
|
||||
suite.Require().Equal(newHeader.GetHeight(), clientState.GetLatestHeight(), "valid test case %d failed: %s", i, tc.name)
|
||||
|
||||
// Determine if clientState should be updated or not
|
||||
if uint64(newHeader.Height) > clientState.LatestHeight {
|
||||
// Header Height is greater than clientState latest Height, clientState should be updated with header.Height
|
||||
suite.Require().Equal(uint64(newHeader.Height), newClientState.GetLatestHeight(), "clientstate height did not update")
|
||||
} else {
|
||||
// Update will add past consensus state, clientState should not be updated at all
|
||||
suite.Require().Equal(clientState.LatestHeight, newClientState.GetLatestHeight(), "client state height updated for past header")
|
||||
}
|
||||
|
||||
suite.Require().Equal(expectedConsensus, consensusState, "valid test case %d failed: %s", i, tc.name)
|
||||
} else {
|
||||
suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
|
||||
suite.Require().Nil(clientState, "invalid test case %d passed: %s", i, tc.name)
|
||||
suite.Require().Nil(newClientState, "invalid test case %d passed: %s", i, tc.name)
|
||||
suite.Require().Nil(consensusState, "invalid test case %d passed: %s", i, tc.name)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,6 +51,11 @@ func (cs ClientState) IsFrozen() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// GetFrozenHeight returns 0.
|
||||
func (cs ClientState) GetFrozenHeight() uint64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Validate performs a basic validation of the client state fields.
|
||||
func (cs ClientState) Validate() error {
|
||||
if strings.TrimSpace(cs.ChainID) == "" {
|
||||
|
|
|
@ -32,7 +32,7 @@ func (suite *IBCTestSuite) TestValidateGenesis() {
|
|||
ClientGenesis: clienttypes.NewGenesisState(
|
||||
[]clienttypes.GenesisClientState{
|
||||
clienttypes.NewGenesisClientState(
|
||||
clientID, ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientID, ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
),
|
||||
clienttypes.NewGenesisClientState(
|
||||
exported.ClientTypeLocalHost, localhosttypes.NewClientState("chaindID", 10),
|
||||
|
@ -43,7 +43,7 @@ func (suite *IBCTestSuite) TestValidateGenesis() {
|
|||
clientID,
|
||||
[]exported.ConsensusState{
|
||||
ibctmtypes.NewConsensusState(
|
||||
suite.header.Time, commitmenttypes.NewMerkleRoot(suite.header.AppHash), suite.header.GetHeight(), suite.header.ValidatorSet,
|
||||
suite.header.Time, commitmenttypes.NewMerkleRoot(suite.header.AppHash), suite.header.GetHeight(), suite.header.ValidatorSet.Hash(), suite.header.ValidatorSet,
|
||||
),
|
||||
},
|
||||
),
|
||||
|
@ -92,7 +92,7 @@ func (suite *IBCTestSuite) TestValidateGenesis() {
|
|||
ClientGenesis: clienttypes.NewGenesisState(
|
||||
[]clienttypes.GenesisClientState{
|
||||
clienttypes.NewGenesisClientState(
|
||||
clientID, ibctmtypes.NewClientState(lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, suite.header, commitmenttypes.GetSDKSpecs()),
|
||||
clientID, ibctmtypes.NewClientState(chainID, lite.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
|
||||
),
|
||||
clienttypes.NewGenesisClientState(
|
||||
exported.ClientTypeLocalHost, localhosttypes.NewClientState("(chaindID)", 0),
|
||||
|
|
|
@ -17,6 +17,8 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
chainID = "chainID"
|
||||
|
||||
connectionID = "connectionidone"
|
||||
clientID = "clientidone"
|
||||
connectionID2 = "connectionidtwo"
|
||||
|
@ -31,6 +33,8 @@ const (
|
|||
channelOrder = channeltypes.ORDERED
|
||||
channelVersion = "1.0"
|
||||
|
||||
height = 10
|
||||
|
||||
trustingPeriod time.Duration = time.Hour * 24 * 7 * 2
|
||||
ubdPeriod time.Duration = time.Hour * 24 * 7 * 3
|
||||
maxClockDrift time.Duration = time.Second * 10
|
||||
|
@ -58,7 +62,7 @@ func (suite *IBCTestSuite) SetupTest() {
|
|||
val := tmtypes.NewValidator(pubKey, 10)
|
||||
valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{val})
|
||||
|
||||
suite.header = ibctmtypes.CreateTestHeader("chainID", 10, now, valSet, []tmtypes.PrivValidator{privVal})
|
||||
suite.header = ibctmtypes.CreateTestHeader(chainID, height, now, valSet, []tmtypes.PrivValidator{privVal})
|
||||
|
||||
suite.cdc = suite.app.Codec()
|
||||
suite.ctx = suite.app.BaseApp.NewContext(isCheckTx, abci.Header{})
|
||||
|
|
|
@ -202,7 +202,9 @@ func (chain *TestChain) NextBlock() {
|
|||
AppHash: chain.App.LastCommitID().Hash,
|
||||
// NOTE: the time is increased by the coordinator to maintain time synchrony amongst
|
||||
// chains.
|
||||
Time: chain.CurrentHeader.Time,
|
||||
Time: chain.CurrentHeader.Time,
|
||||
ValidatorsHash: chain.Vals.Hash(),
|
||||
NextValidatorsHash: chain.Vals.Hash(),
|
||||
}
|
||||
|
||||
chain.App.BeginBlock(abci.RequestBeginBlock{Header: chain.CurrentHeader})
|
||||
|
|
Loading…
Reference in New Issue