Retrieve Epoch from ChainID (#7280)
* add functions to parse epoch from height * remove 0 epoch hardcoding * fix tendermint tests * fix tests * start update docs * progress * better parsing of chainID * fix update and misbehaviour logic and add tests * update docs * docfix * Apply suggestions from code review Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> * Update x/ibc/07-tendermint/types/misbehaviour_handle_test.go * change self checks to use epochs * address rest of reviews * rename epoch number to version in docs * wrap up rest of TODOs * Update x/ibc/02-client/genesis.go * add self validate test * Apply suggestions from code review Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> * fix godoc Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com>
This commit is contained in:
parent
5dc434fbca
commit
984c2d4179
|
@ -115,7 +115,6 @@ func QueryConsensusStateABCI(
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: retrieve epoch-number from chain-id
|
|
||||||
return types.NewQueryConsensusStateResponse(clientID, anyConsensusState, proofBz, proofHeight), nil
|
return types.NewQueryConsensusStateResponse(clientID, anyConsensusState, proofBz, proofHeight), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,10 +45,9 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, gs types.GenesisState) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// client id is always "localhost"
|
// client id is always "localhost"
|
||||||
// Hardcode 0 as epoch number for now
|
epoch := types.ParseChainID(ctx.ChainID())
|
||||||
// TODO: Retrieve epoch from chain-id
|
|
||||||
clientState := localhosttypes.NewClientState(
|
clientState := localhosttypes.NewClientState(
|
||||||
ctx.ChainID(), types.NewHeight(0, uint64(ctx.BlockHeight())),
|
ctx.ChainID(), types.NewHeight(epoch, uint64(ctx.BlockHeight())),
|
||||||
)
|
)
|
||||||
|
|
||||||
_, err := k.CreateClient(ctx, exported.ClientTypeLocalHost, clientState, nil)
|
_, err := k.CreateClient(ctx, exported.ClientTypeLocalHost, clientState, nil)
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
tmtypes "github.com/tendermint/tendermint/types"
|
tmtypes "github.com/tendermint/tendermint/types"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
|
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
|
||||||
|
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
|
||||||
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
|
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
|
||||||
localhosttypes "github.com/cosmos/cosmos-sdk/x/ibc/09-localhost/types"
|
localhosttypes "github.com/cosmos/cosmos-sdk/x/ibc/09-localhost/types"
|
||||||
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
|
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
|
||||||
|
@ -60,11 +61,17 @@ func (suite *KeeperTestSuite) TestCreateClient() {
|
||||||
func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
|
func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
|
||||||
// Must create header creation functions since suite.header gets recreated on each test case
|
// Must create header creation functions since suite.header gets recreated on each test case
|
||||||
createFutureUpdateFn := func(s *KeeperTestSuite) *ibctmtypes.Header {
|
createFutureUpdateFn := func(s *KeeperTestSuite) *ibctmtypes.Header {
|
||||||
return ibctmtypes.CreateTestHeader(testChainID, int64(suite.header.GetHeight().GetEpochHeight()+3), int64(suite.header.GetHeight().GetEpochHeight()), suite.header.Header.Time.Add(time.Hour),
|
heightPlus3 := clienttypes.NewHeight(suite.header.GetHeight().GetEpochNumber(), suite.header.GetHeight().GetEpochHeight()+3)
|
||||||
|
height := suite.header.GetHeight().(clienttypes.Height)
|
||||||
|
|
||||||
|
return ibctmtypes.CreateTestHeader(testChainID, heightPlus3, height, suite.header.Header.Time.Add(time.Hour),
|
||||||
suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal})
|
suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal})
|
||||||
}
|
}
|
||||||
createPastUpdateFn := func(s *KeeperTestSuite) *ibctmtypes.Header {
|
createPastUpdateFn := func(s *KeeperTestSuite) *ibctmtypes.Header {
|
||||||
return ibctmtypes.CreateTestHeader(testChainID, int64(suite.header.GetHeight().GetEpochHeight()-2), int64(suite.header.GetHeight().GetEpochHeight())-4, suite.header.Header.Time,
|
heightMinus2 := clienttypes.NewHeight(suite.header.GetHeight().GetEpochNumber(), suite.header.GetHeight().GetEpochHeight()-2)
|
||||||
|
heightMinus4 := clienttypes.NewHeight(suite.header.GetHeight().GetEpochNumber(), suite.header.GetHeight().GetEpochHeight()-4)
|
||||||
|
|
||||||
|
return ibctmtypes.CreateTestHeader(testChainID, heightMinus2, heightMinus4, suite.header.Header.Time,
|
||||||
suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal})
|
suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal})
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
|
@ -270,6 +277,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
||||||
altTime := suite.ctx.BlockTime().Add(time.Minute)
|
altTime := suite.ctx.BlockTime().Add(time.Minute)
|
||||||
|
|
||||||
heightPlus3 := types.NewHeight(0, height+3)
|
heightPlus3 := types.NewHeight(0, height+3)
|
||||||
|
heightPlus5 := types.NewHeight(0, height+5)
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
|
@ -280,8 +288,8 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
||||||
{
|
{
|
||||||
"trusting period misbehavior should pass",
|
"trusting period misbehavior should pass",
|
||||||
&ibctmtypes.Misbehaviour{
|
&ibctmtypes.Misbehaviour{
|
||||||
Header1: ibctmtypes.CreateTestHeader(testChainID, height, height, altTime, bothValSet, bothValSet, bothSigners),
|
Header1: ibctmtypes.CreateTestHeader(testChainID, testClientHeight, testClientHeight, altTime, bothValSet, bothValSet, bothSigners),
|
||||||
Header2: ibctmtypes.CreateTestHeader(testChainID, height, height, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners),
|
Header2: ibctmtypes.CreateTestHeader(testChainID, testClientHeight, testClientHeight, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners),
|
||||||
ChainId: testChainID,
|
ChainId: testChainID,
|
||||||
ClientId: testClientID,
|
ClientId: testClientID,
|
||||||
},
|
},
|
||||||
|
@ -297,8 +305,8 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
||||||
{
|
{
|
||||||
"misbehavior at later height should pass",
|
"misbehavior at later height should pass",
|
||||||
&ibctmtypes.Misbehaviour{
|
&ibctmtypes.Misbehaviour{
|
||||||
Header1: ibctmtypes.CreateTestHeader(testChainID, height+5, height, altTime, bothValSet, valSet, bothSigners),
|
Header1: ibctmtypes.CreateTestHeader(testChainID, heightPlus5, testClientHeight, altTime, bothValSet, valSet, bothSigners),
|
||||||
Header2: ibctmtypes.CreateTestHeader(testChainID, height+5, height, suite.ctx.BlockTime(), bothValSet, valSet, bothSigners),
|
Header2: ibctmtypes.CreateTestHeader(testChainID, heightPlus5, testClientHeight, suite.ctx.BlockTime(), bothValSet, valSet, bothSigners),
|
||||||
ChainId: testChainID,
|
ChainId: testChainID,
|
||||||
ClientId: testClientID,
|
ClientId: testClientID,
|
||||||
},
|
},
|
||||||
|
@ -324,8 +332,8 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
||||||
{
|
{
|
||||||
"misbehavior at later height with different trusted heights should pass",
|
"misbehavior at later height with different trusted heights should pass",
|
||||||
&ibctmtypes.Misbehaviour{
|
&ibctmtypes.Misbehaviour{
|
||||||
Header1: ibctmtypes.CreateTestHeader(testChainID, height+5, height, altTime, bothValSet, valSet, bothSigners),
|
Header1: ibctmtypes.CreateTestHeader(testChainID, heightPlus5, testClientHeight, altTime, bothValSet, valSet, bothSigners),
|
||||||
Header2: ibctmtypes.CreateTestHeader(testChainID, height+5, height+3, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners),
|
Header2: ibctmtypes.CreateTestHeader(testChainID, heightPlus5, heightPlus3, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners),
|
||||||
ChainId: testChainID,
|
ChainId: testChainID,
|
||||||
ClientId: testClientID,
|
ClientId: testClientID,
|
||||||
},
|
},
|
||||||
|
@ -351,8 +359,8 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
||||||
{
|
{
|
||||||
"trusted ConsensusState1 not found",
|
"trusted ConsensusState1 not found",
|
||||||
&ibctmtypes.Misbehaviour{
|
&ibctmtypes.Misbehaviour{
|
||||||
Header1: ibctmtypes.CreateTestHeader(testChainID, height+5, height+3, altTime, bothValSet, bothValSet, bothSigners),
|
Header1: ibctmtypes.CreateTestHeader(testChainID, heightPlus5, heightPlus3, altTime, bothValSet, bothValSet, bothSigners),
|
||||||
Header2: ibctmtypes.CreateTestHeader(testChainID, height+5, height, suite.ctx.BlockTime(), bothValSet, valSet, bothSigners),
|
Header2: ibctmtypes.CreateTestHeader(testChainID, heightPlus5, testClientHeight, suite.ctx.BlockTime(), bothValSet, valSet, bothSigners),
|
||||||
ChainId: testChainID,
|
ChainId: testChainID,
|
||||||
ClientId: testClientID,
|
ClientId: testClientID,
|
||||||
},
|
},
|
||||||
|
@ -368,8 +376,8 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
||||||
{
|
{
|
||||||
"trusted ConsensusState2 not found",
|
"trusted ConsensusState2 not found",
|
||||||
&ibctmtypes.Misbehaviour{
|
&ibctmtypes.Misbehaviour{
|
||||||
Header1: ibctmtypes.CreateTestHeader(testChainID, height+5, height, altTime, bothValSet, valSet, bothSigners),
|
Header1: ibctmtypes.CreateTestHeader(testChainID, heightPlus5, testClientHeight, altTime, bothValSet, valSet, bothSigners),
|
||||||
Header2: ibctmtypes.CreateTestHeader(testChainID, height+5, height+3, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners),
|
Header2: ibctmtypes.CreateTestHeader(testChainID, heightPlus5, heightPlus3, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners),
|
||||||
ChainId: testChainID,
|
ChainId: testChainID,
|
||||||
ClientId: testClientID,
|
ClientId: testClientID,
|
||||||
},
|
},
|
||||||
|
@ -391,8 +399,8 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
||||||
{
|
{
|
||||||
"client already frozen at earlier height",
|
"client already frozen at earlier height",
|
||||||
&ibctmtypes.Misbehaviour{
|
&ibctmtypes.Misbehaviour{
|
||||||
Header1: ibctmtypes.CreateTestHeader(testChainID, height, height, altTime, bothValSet, bothValSet, bothSigners),
|
Header1: ibctmtypes.CreateTestHeader(testChainID, testClientHeight, testClientHeight, altTime, bothValSet, bothValSet, bothSigners),
|
||||||
Header2: ibctmtypes.CreateTestHeader(testChainID, height, height, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners),
|
Header2: ibctmtypes.CreateTestHeader(testChainID, testClientHeight, testClientHeight, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners),
|
||||||
ChainId: testChainID,
|
ChainId: testChainID,
|
||||||
ClientId: testClientID,
|
ClientId: testClientID,
|
||||||
},
|
},
|
||||||
|
@ -411,8 +419,8 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
||||||
{
|
{
|
||||||
"misbehaviour check failed",
|
"misbehaviour check failed",
|
||||||
&ibctmtypes.Misbehaviour{
|
&ibctmtypes.Misbehaviour{
|
||||||
Header1: ibctmtypes.CreateTestHeader(testChainID, height, height, altTime, bothValSet, bothValSet, bothSigners),
|
Header1: ibctmtypes.CreateTestHeader(testChainID, testClientHeight, testClientHeight, altTime, bothValSet, bothValSet, bothSigners),
|
||||||
Header2: ibctmtypes.CreateTestHeader(testChainID, height, height, suite.ctx.BlockTime(), altValSet, bothValSet, altSigners),
|
Header2: ibctmtypes.CreateTestHeader(testChainID, testClientHeight, testClientHeight, suite.ctx.BlockTime(), altValSet, bothValSet, altSigners),
|
||||||
ChainId: testChainID,
|
ChainId: testChainID,
|
||||||
ClientId: testClientID,
|
ClientId: testClientID,
|
||||||
},
|
},
|
||||||
|
|
|
@ -189,14 +189,15 @@ func (k Keeper) GetClientConsensusStateLTE(ctx sdk.Context, clientID string, max
|
||||||
|
|
||||||
// GetSelfConsensusState introspects the (self) past historical info at a given height
|
// GetSelfConsensusState introspects the (self) past historical info at a given height
|
||||||
// and returns the expected consensus state at that height.
|
// and returns the expected consensus state at that height.
|
||||||
// TODO: Replace height with *clienttypes.Height once interfaces change
|
// For now, can only retrieve self consensus states for the current epoch
|
||||||
func (k Keeper) GetSelfConsensusState(ctx sdk.Context, height exported.Height) (exported.ConsensusState, bool) {
|
func (k Keeper) GetSelfConsensusState(ctx sdk.Context, height exported.Height) (exported.ConsensusState, bool) {
|
||||||
// TODO: check self chain-id against epoch number
|
|
||||||
selfHeight, ok := height.(types.Height)
|
selfHeight, ok := height.(types.Height)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
if selfHeight.EpochNumber != 0 {
|
// check that height epoch matches chainID epoch
|
||||||
|
epoch := types.ParseChainID(ctx.ChainID())
|
||||||
|
if epoch != height.GetEpochNumber() {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
histInfo, found := k.stakingKeeper.GetHistoricalInfo(ctx, int64(selfHeight.EpochHeight))
|
histInfo, found := k.stakingKeeper.GetHistoricalInfo(ctx, int64(selfHeight.EpochHeight))
|
||||||
|
@ -214,6 +215,7 @@ func (k Keeper) GetSelfConsensusState(ctx sdk.Context, height exported.Height) (
|
||||||
|
|
||||||
// ValidateSelfClient validates the client parameters for a client of the running chain
|
// ValidateSelfClient validates the client parameters for a client of the running chain
|
||||||
// This function is only used to validate the client state the counterparty stores for this chain
|
// This function is only used to validate the client state the counterparty stores for this chain
|
||||||
|
// Client must be in same epoch as the executing chain
|
||||||
func (k Keeper) ValidateSelfClient(ctx sdk.Context, clientState exported.ClientState) error {
|
func (k Keeper) ValidateSelfClient(ctx sdk.Context, clientState exported.ClientState) error {
|
||||||
tmClient, ok := clientState.(*ibctmtypes.ClientState)
|
tmClient, ok := clientState.(*ibctmtypes.ClientState)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -230,9 +232,15 @@ func (k Keeper) ValidateSelfClient(ctx sdk.Context, clientState exported.ClientS
|
||||||
ctx.ChainID(), tmClient.ChainId)
|
ctx.ChainID(), tmClient.ChainId)
|
||||||
}
|
}
|
||||||
|
|
||||||
// For now, assume epoch number is zero
|
epoch := types.ParseChainID(ctx.ChainID())
|
||||||
// TODO: Retrieve epoch number from chain-id
|
|
||||||
selfHeight := types.NewHeight(0, uint64(ctx.BlockHeight()))
|
// client must be in the same epoch as executing chain
|
||||||
|
if tmClient.LatestHeight.EpochNumber != epoch {
|
||||||
|
return sdkerrors.Wrapf(types.ErrInvalidClient, "client is not in the same epoch as the chain. expected epoch: %d, got: %d",
|
||||||
|
tmClient.LatestHeight.EpochNumber, epoch)
|
||||||
|
}
|
||||||
|
|
||||||
|
selfHeight := types.NewHeight(epoch, uint64(ctx.BlockHeight()))
|
||||||
if tmClient.LatestHeight.GT(selfHeight) {
|
if tmClient.LatestHeight.GT(selfHeight) {
|
||||||
return sdkerrors.Wrapf(types.ErrInvalidClient, "client has LatestHeight %d greater than chain height %d",
|
return sdkerrors.Wrapf(types.ErrInvalidClient, "client has LatestHeight %d greater than chain height %d",
|
||||||
tmClient.LatestHeight, ctx.BlockHeight())
|
tmClient.LatestHeight, ctx.BlockHeight())
|
||||||
|
|
|
@ -26,7 +26,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
testChainID = "gaiahub"
|
testChainID = "gaiahub-0"
|
||||||
|
testChainIDEpoch1 = "gaiahub-1"
|
||||||
|
|
||||||
testClientID = "gaiachain"
|
testClientID = "gaiachain"
|
||||||
testClientID2 = "ethbridge"
|
testClientID2 = "ethbridge"
|
||||||
|
@ -40,6 +41,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
var testClientHeight = types.NewHeight(0, 5)
|
var testClientHeight = types.NewHeight(0, 5)
|
||||||
|
var testClientHeightEpoch1 = types.NewHeight(1, 5)
|
||||||
|
|
||||||
type KeeperTestSuite struct {
|
type KeeperTestSuite struct {
|
||||||
suite.Suite
|
suite.Suite
|
||||||
|
@ -83,10 +85,12 @@ func (suite *KeeperTestSuite) SetupTest() {
|
||||||
pubKey, err := suite.privVal.GetPubKey()
|
pubKey, err := suite.privVal.GetPubKey()
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
testClientHeightMinus1 := types.NewHeight(0, height-1)
|
||||||
|
|
||||||
validator := tmtypes.NewValidator(pubKey, 1)
|
validator := tmtypes.NewValidator(pubKey, 1)
|
||||||
suite.valSet = tmtypes.NewValidatorSet([]*tmtypes.Validator{validator})
|
suite.valSet = tmtypes.NewValidatorSet([]*tmtypes.Validator{validator})
|
||||||
suite.valSetHash = suite.valSet.Hash()
|
suite.valSetHash = suite.valSet.Hash()
|
||||||
suite.header = ibctmtypes.CreateTestHeader(testChainID, height, height-1, now2, suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal})
|
suite.header = ibctmtypes.CreateTestHeader(testChainID, testClientHeight, testClientHeightMinus1, now2, suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal})
|
||||||
suite.consensusState = ibctmtypes.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot([]byte("hash")), suite.valSetHash)
|
suite.consensusState = ibctmtypes.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot([]byte("hash")), suite.valSetHash)
|
||||||
|
|
||||||
var validators stakingtypes.Validators
|
var validators stakingtypes.Validators
|
||||||
|
@ -170,6 +174,11 @@ func (suite *KeeperTestSuite) TestValidateSelfClient() {
|
||||||
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.NewHeight(0, testClientHeight.EpochHeight+10), commitmenttypes.GetSDKSpecs(), false, false),
|
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.NewHeight(0, testClientHeight.EpochHeight+10), commitmenttypes.GetSDKSpecs(), false, false),
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"invalid client epoch",
|
||||||
|
ibctmtypes.NewClientState(testChainIDEpoch1, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeightEpoch1, commitmenttypes.GetSDKSpecs(), false, false),
|
||||||
|
false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"invalid proof specs",
|
"invalid proof specs",
|
||||||
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, nil, false, false),
|
ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, nil, false, false),
|
||||||
|
@ -291,7 +300,9 @@ func (suite KeeperTestSuite) TestConsensusStateHelpers() {
|
||||||
|
|
||||||
nextState := ibctmtypes.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot([]byte("next")), suite.valSetHash)
|
nextState := ibctmtypes.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot([]byte("next")), suite.valSetHash)
|
||||||
|
|
||||||
header := ibctmtypes.CreateTestHeader(testClientID, height+5, height, suite.header.Header.Time.Add(time.Minute),
|
testClientHeightPlus5 := types.NewHeight(0, height+5)
|
||||||
|
|
||||||
|
header := ibctmtypes.CreateTestHeader(testClientID, testClientHeightPlus5, testClientHeight, suite.header.Header.Time.Add(time.Minute),
|
||||||
suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal})
|
suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal})
|
||||||
|
|
||||||
// mock update functionality
|
// mock update functionality
|
||||||
|
|
|
@ -53,7 +53,8 @@ func TestValidateGenesis(t *testing.T) {
|
||||||
val := tmtypes.NewValidator(pubKey, 10)
|
val := tmtypes.NewValidator(pubKey, 10)
|
||||||
valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{val})
|
valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{val})
|
||||||
|
|
||||||
header := ibctmtypes.CreateTestHeader(chainID, height, height-1, now, valSet, valSet, []tmtypes.PrivValidator{privVal})
|
heightMinus1 := types.NewHeight(0, height-1)
|
||||||
|
header := ibctmtypes.CreateTestHeader(chainID, clientHeight, heightMinus1, now, valSet, valSet, []tmtypes.PrivValidator{privVal})
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
|
|
|
@ -2,6 +2,7 @@ package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -12,6 +13,11 @@ import (
|
||||||
|
|
||||||
var _ exported.Height = (*Height)(nil)
|
var _ exported.Height = (*Height)(nil)
|
||||||
|
|
||||||
|
// IsEpochFormat checks if a chainID is in the format required for parsing epochs
|
||||||
|
// The chainID must be in the form: `{chainID}-{version}
|
||||||
|
// 24-host may enforce stricter checks on chainID
|
||||||
|
var IsEpochFormat = regexp.MustCompile(`^.+[^-]-{1}[1-9][0-9]*$`).MatchString
|
||||||
|
|
||||||
// ZeroHeight is a helper function which returns an uninitialized height.
|
// ZeroHeight is a helper function which returns an uninitialized height.
|
||||||
func ZeroHeight() Height {
|
func ZeroHeight() Height {
|
||||||
return Height{}
|
return Height{}
|
||||||
|
@ -35,7 +41,7 @@ func (h Height) GetEpochHeight() uint64 {
|
||||||
return h.EpochHeight
|
return h.EpochHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compare implements a method to compare two heights. When comparing two heights a, b
|
// Compare implements a method to compare two heights. When comparing two heights a, b
|
||||||
// we can call a.Compare(b) which will return
|
// we can call a.Compare(b) which will return
|
||||||
// -1 if a < b
|
// -1 if a < b
|
||||||
// 0 if a = b
|
// 0 if a = b
|
||||||
|
@ -143,8 +149,42 @@ func ParseHeight(heightStr string) (Height, error) {
|
||||||
return NewHeight(epochNumber, epochHeight), nil
|
return NewHeight(epochNumber, epochHeight), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSelfHeight is a utility function that returns self height given context
|
// SetEpochNumber takes a chainID in valid epoch format and swaps the epoch number
|
||||||
// TODO: Retrieve epoch-number from chain-id
|
// in the chainID with the given epoch number.
|
||||||
func GetSelfHeight(ctx sdk.Context) Height {
|
func SetEpochNumber(chainID string, epoch uint64) (string, error) {
|
||||||
return NewHeight(0, uint64(ctx.BlockHeight()))
|
if !IsEpochFormat(chainID) {
|
||||||
|
return "", sdkerrors.Wrapf(
|
||||||
|
sdkerrors.ErrInvalidChainID, "chainID is not in epoch format: %s", chainID,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
splitStr := strings.Split(chainID, "-")
|
||||||
|
// swap out epoch number with given epoch
|
||||||
|
splitStr[len(splitStr)-1] = strconv.Itoa(int(epoch))
|
||||||
|
return strings.Join(splitStr, "-"), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseChainID is a utility function that returns an epoch number from the given ChainID.
|
||||||
|
// ParseChainID attempts to parse a chain id in the format: `{chainID}-{version}`
|
||||||
|
// and return the epochnumber as a uint64.
|
||||||
|
// If the chainID is not in the expected format, a default epoch value of 0 is returned.
|
||||||
|
func ParseChainID(chainID string) uint64 {
|
||||||
|
if !IsEpochFormat(chainID) {
|
||||||
|
// chainID is not in epoch format, return 0 as default
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
splitStr := strings.Split(chainID, "-")
|
||||||
|
epoch, err := strconv.ParseUint(splitStr[len(splitStr)-1], 10, 64)
|
||||||
|
// sanity check: error should always be nil since regex only allows numbers in last element
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("regex allowed non-number value as last split element for chainID: %s", chainID))
|
||||||
|
}
|
||||||
|
return epoch
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSelfHeight is a utility function that returns self height given context
|
||||||
|
// Epoch number is retrieved from ctx.ChainID()
|
||||||
|
func GetSelfHeight(ctx sdk.Context) Height {
|
||||||
|
epoch := ParseChainID(ctx.ChainID())
|
||||||
|
return NewHeight(epoch, uint64(ctx.BlockHeight()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,3 +93,56 @@ func (suite *TypesTestSuite) TestMustParseHeight() {
|
||||||
types.MustParseHeight("0-0")
|
types.MustParseHeight("0-0")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseChainID(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
chainID string
|
||||||
|
epoch uint64
|
||||||
|
formatted bool
|
||||||
|
}{
|
||||||
|
{"gaiamainnet-3", 3, true},
|
||||||
|
{"gaia-mainnet-40", 40, true},
|
||||||
|
{"gaiamainnet-3-39", 39, true},
|
||||||
|
{"gaiamainnet--", 0, false},
|
||||||
|
{"gaiamainnet-03", 0, false},
|
||||||
|
{"gaiamainnet--4", 0, false},
|
||||||
|
{"gaiamainnet-3.4", 0, false},
|
||||||
|
{"gaiamainnet", 0, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tc := range cases {
|
||||||
|
require.Equal(t, tc.formatted, types.IsEpochFormat(tc.chainID), "case %d does not match expected format", i)
|
||||||
|
|
||||||
|
epoch := types.ParseChainID(tc.chainID)
|
||||||
|
require.Equal(t, tc.epoch, epoch, "case %d returns incorrect epoch", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetEpochNumber(t *testing.T) {
|
||||||
|
// Test SetEpochNumber
|
||||||
|
chainID, err := types.SetEpochNumber("gaiamainnet", 3)
|
||||||
|
require.Error(t, err, "invalid epoch format passed SetEpochNumber")
|
||||||
|
require.Equal(t, "", chainID, "invalid epoch format returned non-empty string on SetEpochNumber")
|
||||||
|
chainID = "gaiamainnet-3"
|
||||||
|
|
||||||
|
chainID, err = types.SetEpochNumber(chainID, 4)
|
||||||
|
require.NoError(t, err, "valid epoch format failed SetEpochNumber")
|
||||||
|
require.Equal(t, "gaiamainnet-4", chainID, "valid epoch format returned incorrect string on SetEpochNumber")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *TypesTestSuite) TestSelfHeight() {
|
||||||
|
ctx := suite.chainA.GetContext()
|
||||||
|
|
||||||
|
// Test default epoch
|
||||||
|
ctx = ctx.WithChainID("gaiamainnet")
|
||||||
|
ctx = ctx.WithBlockHeight(10)
|
||||||
|
height := types.GetSelfHeight(ctx)
|
||||||
|
suite.Require().Equal(types.NewHeight(0, 10), height, "default self height failed")
|
||||||
|
|
||||||
|
// Test successful epoch format
|
||||||
|
ctx = ctx.WithChainID("gaiamainnet-3")
|
||||||
|
ctx = ctx.WithBlockHeight(18)
|
||||||
|
height = types.GetSelfHeight(ctx)
|
||||||
|
suite.Require().Equal(types.NewHeight(3, 18), height, "valid self height failed")
|
||||||
|
}
|
||||||
|
|
|
@ -354,8 +354,10 @@ func (suite *TypesTestSuite) TestMarshalMsgSubmitMisbehaviour() {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tendermint client", func() {
|
"tendermint client", func() {
|
||||||
header1 := ibctmtypes.CreateTestHeader(suite.chainA.ChainID, suite.chainA.CurrentHeader.Height, suite.chainA.CurrentHeader.Height-1, suite.chainA.CurrentHeader.Time, suite.chainA.Vals, suite.chainA.Vals, suite.chainA.Signers)
|
height := types.NewHeight(0, uint64(suite.chainA.CurrentHeader.Height))
|
||||||
header2 := ibctmtypes.CreateTestHeader(suite.chainA.ChainID, suite.chainA.CurrentHeader.Height, suite.chainA.CurrentHeader.Height-1, suite.chainA.CurrentHeader.Time.Add(time.Minute), suite.chainA.Vals, suite.chainA.Vals, suite.chainA.Signers)
|
heightMinus1 := types.NewHeight(0, uint64(suite.chainA.CurrentHeader.Height)-1)
|
||||||
|
header1 := ibctmtypes.CreateTestHeader(suite.chainA.ChainID, height, heightMinus1, suite.chainA.CurrentHeader.Time, suite.chainA.Vals, suite.chainA.Vals, suite.chainA.Signers)
|
||||||
|
header2 := ibctmtypes.CreateTestHeader(suite.chainA.ChainID, height, heightMinus1, suite.chainA.CurrentHeader.Time.Add(time.Minute), suite.chainA.Vals, suite.chainA.Vals, suite.chainA.Signers)
|
||||||
|
|
||||||
misbehaviour := ibctmtypes.NewMisbehaviour("tendermint", suite.chainA.ChainID, header1, header2)
|
misbehaviour := ibctmtypes.NewMisbehaviour("tendermint", suite.chainA.ChainID, header1, header2)
|
||||||
msg, err = types.NewMsgSubmitMisbehaviour("tendermint", misbehaviour, suite.chainA.SenderAccount.GetAddress())
|
msg, err = types.NewMsgSubmitMisbehaviour("tendermint", misbehaviour, suite.chainA.SenderAccount.GetAddress())
|
||||||
|
@ -410,8 +412,10 @@ func (suite *TypesTestSuite) TestMsgSubmitMisbehaviour_ValidateBasic() {
|
||||||
{
|
{
|
||||||
"valid - tendermint misbehaviour",
|
"valid - tendermint misbehaviour",
|
||||||
func() {
|
func() {
|
||||||
header1 := ibctmtypes.CreateTestHeader(suite.chainA.ChainID, suite.chainA.CurrentHeader.Height, suite.chainA.CurrentHeader.Height-1, suite.chainA.CurrentHeader.Time, suite.chainA.Vals, suite.chainA.Vals, suite.chainA.Signers)
|
height := types.NewHeight(0, uint64(suite.chainA.CurrentHeader.Height))
|
||||||
header2 := ibctmtypes.CreateTestHeader(suite.chainA.ChainID, suite.chainA.CurrentHeader.Height, suite.chainA.CurrentHeader.Height-1, suite.chainA.CurrentHeader.Time.Add(time.Minute), suite.chainA.Vals, suite.chainA.Vals, suite.chainA.Signers)
|
heightMinus1 := types.NewHeight(0, uint64(suite.chainA.CurrentHeader.Height)-1)
|
||||||
|
header1 := ibctmtypes.CreateTestHeader(suite.chainA.ChainID, height, heightMinus1, suite.chainA.CurrentHeader.Time, suite.chainA.Vals, suite.chainA.Vals, suite.chainA.Signers)
|
||||||
|
header2 := ibctmtypes.CreateTestHeader(suite.chainA.ChainID, height, heightMinus1, suite.chainA.CurrentHeader.Time.Add(time.Minute), suite.chainA.Vals, suite.chainA.Vals, suite.chainA.Signers)
|
||||||
|
|
||||||
misbehaviour := ibctmtypes.NewMisbehaviour("tendermint", suite.chainA.ChainID, header1, header2)
|
misbehaviour := ibctmtypes.NewMisbehaviour("tendermint", suite.chainA.ChainID, header1, header2)
|
||||||
msg, err = types.NewMsgSubmitMisbehaviour("tendermint", misbehaviour, suite.chainA.SenderAccount.GetAddress())
|
msg, err = types.NewMsgSubmitMisbehaviour("tendermint", misbehaviour, suite.chainA.SenderAccount.GetAddress())
|
||||||
|
|
|
@ -51,7 +51,6 @@ func queryPacketCommitmentABCI(
|
||||||
return nil, sdkerrors.Wrapf(types.ErrPacketCommitmentNotFound, "portID (%s), channelID (%s), sequence (%d)", portID, channelID, sequence)
|
return nil, sdkerrors.Wrapf(types.ErrPacketCommitmentNotFound, "portID (%s), channelID (%s), sequence (%d)", portID, channelID, sequence)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: retrieve epoch number from chain-id
|
|
||||||
return types.NewQueryPacketCommitmentResponse(portID, channelID, sequence, value, proofBz, proofHeight), nil
|
return types.NewQueryPacketCommitmentResponse(portID, channelID, sequence, value, proofBz, proofHeight), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,6 +229,5 @@ func queryNextSequenceRecvABCI(clientCtx client.Context, portID, channelID strin
|
||||||
|
|
||||||
sequence := binary.BigEndian.Uint64(value)
|
sequence := binary.BigEndian.Uint64(value)
|
||||||
|
|
||||||
// TODO: retrieve epoch number from chain-id
|
|
||||||
return types.NewQueryNextSequenceReceiveResponse(portID, channelID, sequence, proofBz, proofHeight), nil
|
return types.NewQueryNextSequenceReceiveResponse(portID, channelID, sequence, proofBz, proofHeight), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,16 +30,12 @@ func (h Header) ConsensusState() *ConsensusState {
|
||||||
|
|
||||||
// GetHeight returns the current height. It returns 0 if the tendermint
|
// GetHeight returns the current height. It returns 0 if the tendermint
|
||||||
// header is nil.
|
// header is nil.
|
||||||
//
|
|
||||||
// TODO: return clienttypes.Height once interface changes
|
|
||||||
func (h Header) GetHeight() exported.Height {
|
func (h Header) GetHeight() exported.Height {
|
||||||
if h.Header == nil {
|
if h.Header == nil {
|
||||||
return clienttypes.ZeroHeight()
|
return clienttypes.ZeroHeight()
|
||||||
}
|
}
|
||||||
|
epoch := clienttypes.ParseChainID(h.Header.ChainID)
|
||||||
// Enforce clienttypes.Height to use 0 epoch number
|
return clienttypes.NewHeight(epoch, uint64(h.Header.Height))
|
||||||
// TODO: Retrieve epoch number from chain-id
|
|
||||||
return clienttypes.NewHeight(0, uint64(h.Header.Height))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTime returns the current block timestamp. It returns a zero time if
|
// GetTime returns the current block timestamp. It returns a zero time if
|
||||||
|
|
|
@ -62,7 +62,7 @@ func (cs ClientState) CheckMisbehaviourAndUpdateState(
|
||||||
infractionHeight := tmMisbehaviour.GetHeight().GetEpochHeight()
|
infractionHeight := tmMisbehaviour.GetHeight().GetEpochHeight()
|
||||||
ageBlocks = int64(cs.LatestHeight.EpochHeight - infractionHeight)
|
ageBlocks = int64(cs.LatestHeight.EpochHeight - infractionHeight)
|
||||||
} else {
|
} else {
|
||||||
// if the misbehaviour is from a previous epoch, then the epoch-height
|
// if the misbehaviour is from a different epoch, then the epoch-height
|
||||||
// of misbehaviour has no correlation with the current epoch-height
|
// of misbehaviour has no correlation with the current epoch-height
|
||||||
// so we disable the block check by setting ageBlocks to 0 and only
|
// so we disable the block check by setting ageBlocks to 0 and only
|
||||||
// rely on the time expiry check with ageDuration
|
// rely on the time expiry check with ageDuration
|
||||||
|
@ -136,15 +136,22 @@ func checkMisbehaviourHeader(
|
||||||
if currentTimestamp.Sub(consState.Timestamp) >= clientState.UnbondingPeriod {
|
if currentTimestamp.Sub(consState.Timestamp) >= clientState.UnbondingPeriod {
|
||||||
return sdkerrors.Wrapf(
|
return sdkerrors.Wrapf(
|
||||||
ErrUnbondingPeriodExpired,
|
ErrUnbondingPeriodExpired,
|
||||||
"current timestamp minus the latest consensus state timestamp is greater than or equal to the unbonding period (%s >= %s)",
|
"current timestamp minus the latest consensus state timestamp is greater than or equal to the unbonding period (%d >= %d)",
|
||||||
currentTimestamp.Sub(consState.Timestamp), clientState.UnbondingPeriod,
|
currentTimestamp.Sub(consState.Timestamp), clientState.UnbondingPeriod,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chainID := clientState.GetChainID()
|
||||||
|
// If chainID is in epoch format, then set epoch number of chainID with the epoch number
|
||||||
|
// of the misbehaviour header
|
||||||
|
if clienttypes.IsEpochFormat(chainID) {
|
||||||
|
chainID, _ = clienttypes.SetEpochNumber(chainID, header.GetHeight().GetEpochNumber())
|
||||||
|
}
|
||||||
|
|
||||||
// - ValidatorSet must have 2/3 similarity with trusted FromValidatorSet
|
// - ValidatorSet must have 2/3 similarity with trusted FromValidatorSet
|
||||||
// - ValidatorSets on both headers are valid given the last trusted ValidatorSet
|
// - ValidatorSets on both headers are valid given the last trusted ValidatorSet
|
||||||
if err := tmTrustedValset.VerifyCommitLightTrusting(
|
if err := tmTrustedValset.VerifyCommitLightTrusting(
|
||||||
clientState.GetChainID(), tmCommit, clientState.TrustLevel.ToTendermint(),
|
chainID, tmCommit, clientState.TrustLevel.ToTendermint(),
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return sdkerrors.Wrapf(clienttypes.ErrInvalidMisbehaviour, "validator set in header has too much change from trusted validator set: %v", err)
|
return sdkerrors.Wrapf(clienttypes.ErrInvalidMisbehaviour, "validator set in header has too much change from trusted validator set: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,8 +58,8 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
||||||
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
||||||
height,
|
height,
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: types.CreateTestHeader(chainID, epochHeight, epochHeight, suite.now, bothValSet, bothValSet, bothSigners),
|
Header1: types.CreateTestHeader(chainID, height, height, suite.now, bothValSet, bothValSet, bothSigners),
|
||||||
Header2: types.CreateTestHeader(chainID, epochHeight, epochHeight, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
|
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: chainID,
|
ClientId: chainID,
|
||||||
},
|
},
|
||||||
|
@ -74,8 +74,88 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
||||||
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
||||||
heightMinus1,
|
heightMinus1,
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: types.CreateTestHeader(chainID, epochHeight, epochHeight-1, suite.now, bothValSet, bothValSet, bothSigners),
|
Header1: types.CreateTestHeader(chainID, height, heightMinus1, suite.now, bothValSet, bothValSet, bothSigners),
|
||||||
Header2: types.CreateTestHeader(chainID, epochHeight, epochHeight-1, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
|
Header2: types.CreateTestHeader(chainID, height, heightMinus1, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
|
||||||
|
ChainId: chainID,
|
||||||
|
ClientId: chainID,
|
||||||
|
},
|
||||||
|
suite.now,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"valid misbehaviour with different trusted heights",
|
||||||
|
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
|
||||||
|
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
||||||
|
heightMinus1,
|
||||||
|
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash),
|
||||||
|
heightMinus3,
|
||||||
|
&types.Misbehaviour{
|
||||||
|
Header1: types.CreateTestHeader(chainID, height, heightMinus1, suite.now, bothValSet, bothValSet, bothSigners),
|
||||||
|
Header2: types.CreateTestHeader(chainID, height, heightMinus3, suite.now.Add(time.Minute), bothValSet, suite.valSet, bothSigners),
|
||||||
|
ChainId: chainID,
|
||||||
|
ClientId: chainID,
|
||||||
|
},
|
||||||
|
suite.now,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"valid misbehaviour at a previous epoch",
|
||||||
|
types.NewClientState(chainIDEpoch1, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clienttypes.NewHeight(1, 1), commitmenttypes.GetSDKSpecs(), false, false),
|
||||||
|
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
||||||
|
heightMinus1,
|
||||||
|
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash),
|
||||||
|
heightMinus3,
|
||||||
|
&types.Misbehaviour{
|
||||||
|
Header1: types.CreateTestHeader(chainIDEpoch0, height, heightMinus1, suite.now, bothValSet, bothValSet, bothSigners),
|
||||||
|
Header2: types.CreateTestHeader(chainIDEpoch0, height, heightMinus3, suite.now.Add(time.Minute), bothValSet, suite.valSet, bothSigners),
|
||||||
|
ChainId: chainIDEpoch0,
|
||||||
|
ClientId: chainID,
|
||||||
|
},
|
||||||
|
suite.now,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"valid misbehaviour at a future epoch",
|
||||||
|
types.NewClientState(chainIDEpoch0, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
|
||||||
|
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
||||||
|
heightMinus1,
|
||||||
|
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash),
|
||||||
|
heightMinus3,
|
||||||
|
&types.Misbehaviour{
|
||||||
|
Header1: types.CreateTestHeader(chainIDEpoch0, clienttypes.NewHeight(1, 3), heightMinus1, suite.now, bothValSet, bothValSet, bothSigners),
|
||||||
|
Header2: types.CreateTestHeader(chainIDEpoch0, clienttypes.NewHeight(1, 3), heightMinus3, suite.now.Add(time.Minute), bothValSet, suite.valSet, bothSigners),
|
||||||
|
ChainId: chainIDEpoch0,
|
||||||
|
ClientId: chainID,
|
||||||
|
},
|
||||||
|
suite.now,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"valid misbehaviour with trusted heights at a previous epoch",
|
||||||
|
types.NewClientState(chainIDEpoch1, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clienttypes.NewHeight(1, 1), commitmenttypes.GetSDKSpecs(), false, false),
|
||||||
|
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
||||||
|
heightMinus1,
|
||||||
|
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash),
|
||||||
|
heightMinus3,
|
||||||
|
&types.Misbehaviour{
|
||||||
|
Header1: types.CreateTestHeader(chainIDEpoch1, clienttypes.NewHeight(1, 1), heightMinus1, suite.now, bothValSet, bothValSet, bothSigners),
|
||||||
|
Header2: types.CreateTestHeader(chainIDEpoch1, clienttypes.NewHeight(1, 1), heightMinus3, suite.now.Add(time.Minute), bothValSet, suite.valSet, bothSigners),
|
||||||
|
ChainId: chainIDEpoch1,
|
||||||
|
ClientId: chainID,
|
||||||
|
},
|
||||||
|
suite.now,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"consensus state's valset hash different from misbehaviour should still pass",
|
||||||
|
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
|
||||||
|
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash),
|
||||||
|
height,
|
||||||
|
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash),
|
||||||
|
height,
|
||||||
|
&types.Misbehaviour{
|
||||||
|
Header1: types.CreateTestHeader(chainID, height, height, suite.now, bothValSet, suite.valSet, bothSigners),
|
||||||
|
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), bothValSet, suite.valSet, bothSigners),
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: chainID,
|
ClientId: chainID,
|
||||||
},
|
},
|
||||||
|
@ -90,46 +170,14 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
||||||
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
||||||
height,
|
height,
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: types.CreateTestHeader("ethermint", int64(height.EpochHeight), int64(height.EpochHeight), suite.now, bothValSet, bothValSet, bothSigners),
|
Header1: types.CreateTestHeader("ethermint", height, height, suite.now, bothValSet, bothValSet, bothSigners),
|
||||||
Header2: types.CreateTestHeader("ethermint", int64(height.EpochHeight), int64(height.EpochHeight), suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
|
Header2: types.CreateTestHeader("ethermint", height, height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
|
||||||
ChainId: "ethermint",
|
ChainId: "ethermint",
|
||||||
ClientId: chainID,
|
ClientId: chainID,
|
||||||
},
|
},
|
||||||
suite.now,
|
suite.now,
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"valid misbehavior misbehaviour with different trusted heights",
|
|
||||||
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
|
|
||||||
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
|
||||||
heightMinus1,
|
|
||||||
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash),
|
|
||||||
heightMinus3,
|
|
||||||
&types.Misbehaviour{
|
|
||||||
Header1: types.CreateTestHeader(chainID, epochHeight, epochHeight-1, suite.now, bothValSet, bothValSet, bothSigners),
|
|
||||||
Header2: types.CreateTestHeader(chainID, epochHeight, epochHeight-3, suite.now.Add(time.Minute), bothValSet, suite.valSet, bothSigners),
|
|
||||||
ChainId: chainID,
|
|
||||||
ClientId: chainID,
|
|
||||||
},
|
|
||||||
suite.now,
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"consensus state's valset hash different from misbehaviour should still pass",
|
|
||||||
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
|
|
||||||
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash),
|
|
||||||
height,
|
|
||||||
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash),
|
|
||||||
height,
|
|
||||||
&types.Misbehaviour{
|
|
||||||
Header1: types.CreateTestHeader(chainID, epochHeight, epochHeight, suite.now, bothValSet, suite.valSet, bothSigners),
|
|
||||||
Header2: types.CreateTestHeader(chainID, epochHeight, epochHeight, suite.now.Add(time.Minute), bothValSet, suite.valSet, bothSigners),
|
|
||||||
ChainId: chainID,
|
|
||||||
ClientId: chainID,
|
|
||||||
},
|
|
||||||
suite.now,
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"invalid misbehavior misbehaviour with trusted height different from trusted consensus state",
|
"invalid misbehavior misbehaviour with trusted height different from trusted consensus state",
|
||||||
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
|
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false),
|
||||||
|
@ -138,8 +186,8 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
||||||
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash),
|
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash),
|
||||||
heightMinus3,
|
heightMinus3,
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: types.CreateTestHeader(chainID, epochHeight, epochHeight-1, suite.now, bothValSet, bothValSet, bothSigners),
|
Header1: types.CreateTestHeader(chainID, height, heightMinus1, suite.now, bothValSet, bothValSet, bothSigners),
|
||||||
Header2: types.CreateTestHeader(chainID, epochHeight, epochHeight, suite.now.Add(time.Minute), bothValSet, suite.valSet, bothSigners),
|
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), bothValSet, suite.valSet, bothSigners),
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: chainID,
|
ClientId: chainID,
|
||||||
},
|
},
|
||||||
|
@ -154,8 +202,8 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
||||||
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash),
|
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash),
|
||||||
heightMinus3,
|
heightMinus3,
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: types.CreateTestHeader(chainID, epochHeight, epochHeight-1, suite.now, bothValSet, bothValSet, bothSigners),
|
Header1: types.CreateTestHeader(chainID, height, heightMinus1, suite.now, bothValSet, bothValSet, bothSigners),
|
||||||
Header2: types.CreateTestHeader(chainID, epochHeight, epochHeight-3, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
|
Header2: types.CreateTestHeader(chainID, height, heightMinus3, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: chainID,
|
ClientId: chainID,
|
||||||
},
|
},
|
||||||
|
@ -170,8 +218,8 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
||||||
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
||||||
height,
|
height,
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: types.CreateTestHeader(chainID, epochHeight, epochHeight, suite.now, bothValSet, bothValSet, bothSigners),
|
Header1: types.CreateTestHeader(chainID, height, height, suite.now, bothValSet, bothValSet, bothSigners),
|
||||||
Header2: types.CreateTestHeader(chainID, epochHeight, epochHeight, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
|
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: chainID,
|
ClientId: chainID,
|
||||||
},
|
},
|
||||||
|
@ -186,8 +234,8 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
||||||
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
||||||
height,
|
height,
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: types.CreateTestHeader(chainID, epochHeight, epochHeight-1, suite.now, bothValSet, bothValSet, bothSigners),
|
Header1: types.CreateTestHeader(chainID, height, heightMinus1, suite.now, bothValSet, bothValSet, bothSigners),
|
||||||
Header2: types.CreateTestHeader(chainID, epochHeight, epochHeight, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
|
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: chainID,
|
ClientId: chainID,
|
||||||
},
|
},
|
||||||
|
@ -213,8 +261,8 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
||||||
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
||||||
height,
|
height,
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: types.CreateTestHeader(chainID, epochHeight, epochHeight, suite.now, bothValSet, bothValSet, bothSigners),
|
Header1: types.CreateTestHeader(chainID, height, height, suite.now, bothValSet, bothValSet, bothSigners),
|
||||||
Header2: types.CreateTestHeader(chainID, epochHeight, epochHeight, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
|
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: chainID,
|
ClientId: chainID,
|
||||||
},
|
},
|
||||||
|
@ -229,8 +277,8 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
||||||
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
||||||
height,
|
height,
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: types.CreateTestHeader(chainID, epochHeight, epochHeight, suite.now, bothValSet, bothValSet, bothSigners),
|
Header1: types.CreateTestHeader(chainID, height, height, suite.now, bothValSet, bothValSet, bothSigners),
|
||||||
Header2: types.CreateTestHeader(chainID, epochHeight, epochHeight, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
|
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: chainID,
|
ClientId: chainID,
|
||||||
},
|
},
|
||||||
|
@ -245,8 +293,8 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
||||||
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
||||||
height,
|
height,
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: types.CreateTestHeader(chainID, epochHeight, epochHeight-1, suite.now, bothValSet, bothValSet, bothSigners),
|
Header1: types.CreateTestHeader(chainID, height, heightMinus1, suite.now, bothValSet, bothValSet, bothSigners),
|
||||||
Header2: types.CreateTestHeader(chainID, epochHeight, epochHeight-1, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
|
Header2: types.CreateTestHeader(chainID, height, heightMinus1, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: chainID,
|
ClientId: chainID,
|
||||||
},
|
},
|
||||||
|
@ -261,8 +309,8 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
||||||
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
||||||
height,
|
height,
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: types.CreateTestHeader(chainID, epochHeight, epochHeight-1, suite.now, bothValSet, bothValSet, bothSigners),
|
Header1: types.CreateTestHeader(chainID, height, heightMinus1, suite.now, bothValSet, bothValSet, bothSigners),
|
||||||
Header2: types.CreateTestHeader(chainID, epochHeight, epochHeight, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
|
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: chainID,
|
ClientId: chainID,
|
||||||
},
|
},
|
||||||
|
@ -277,8 +325,8 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
||||||
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
||||||
height,
|
height,
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: types.CreateTestHeader(chainID, epochHeight, epochHeight, suite.now, bothValSet, suite.valSet, bothSigners),
|
Header1: types.CreateTestHeader(chainID, height, height, suite.now, bothValSet, suite.valSet, bothSigners),
|
||||||
Header2: types.CreateTestHeader(chainID, epochHeight, epochHeight, suite.now.Add(time.Minute), bothValSet, suite.valSet, bothSigners),
|
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), bothValSet, suite.valSet, bothSigners),
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: chainID,
|
ClientId: chainID,
|
||||||
},
|
},
|
||||||
|
@ -293,8 +341,8 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
||||||
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
||||||
height,
|
height,
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: types.CreateTestHeader(chainID, epochHeight, epochHeight, suite.now, altValSet, bothValSet, altSigners),
|
Header1: types.CreateTestHeader(chainID, height, height, suite.now, altValSet, bothValSet, altSigners),
|
||||||
Header2: types.CreateTestHeader(chainID, epochHeight, epochHeight, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
|
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: chainID,
|
ClientId: chainID,
|
||||||
},
|
},
|
||||||
|
@ -309,8 +357,8 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
||||||
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
||||||
height,
|
height,
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: types.CreateTestHeader(chainID, epochHeight, epochHeight, suite.now, bothValSet, bothValSet, bothSigners),
|
Header1: types.CreateTestHeader(chainID, height, height, suite.now, bothValSet, bothValSet, bothSigners),
|
||||||
Header2: types.CreateTestHeader(chainID, epochHeight, epochHeight, suite.now.Add(time.Minute), altValSet, bothValSet, altSigners),
|
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), altValSet, bothValSet, altSigners),
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: chainID,
|
ClientId: chainID,
|
||||||
},
|
},
|
||||||
|
@ -325,8 +373,8 @@ func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
|
||||||
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash),
|
||||||
height,
|
height,
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: types.CreateTestHeader(chainID, epochHeight, epochHeight, suite.now, altValSet, bothValSet, altSigners),
|
Header1: types.CreateTestHeader(chainID, height, height, suite.now, altValSet, bothValSet, altSigners),
|
||||||
Header2: types.CreateTestHeader(chainID, epochHeight, epochHeight, suite.now.Add(time.Minute), altValSet, bothValSet, altSigners),
|
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), altValSet, bothValSet, altSigners),
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: chainID,
|
ClientId: chainID,
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||||
tmtypes "github.com/tendermint/tendermint/types"
|
tmtypes "github.com/tendermint/tendermint/types"
|
||||||
|
|
||||||
|
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
|
"github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/ibc/exported"
|
"github.com/cosmos/cosmos-sdk/x/ibc/exported"
|
||||||
ibctestingmock "github.com/cosmos/cosmos-sdk/x/ibc/testing/mock"
|
ibctestingmock "github.com/cosmos/cosmos-sdk/x/ibc/testing/mock"
|
||||||
|
@ -14,11 +15,11 @@ import (
|
||||||
|
|
||||||
func (suite *TendermintTestSuite) TestMisbehaviour() {
|
func (suite *TendermintTestSuite) TestMisbehaviour() {
|
||||||
signers := []tmtypes.PrivValidator{suite.privVal}
|
signers := []tmtypes.PrivValidator{suite.privVal}
|
||||||
epochHeight := int64(height.EpochHeight)
|
heightMinus1 := clienttypes.NewHeight(0, height.EpochHeight-1)
|
||||||
|
|
||||||
misbehaviour := &types.Misbehaviour{
|
misbehaviour := &types.Misbehaviour{
|
||||||
Header1: suite.header,
|
Header1: suite.header,
|
||||||
Header2: types.CreateTestHeader(chainID, epochHeight, epochHeight-1, suite.now, suite.valSet, suite.valSet, signers),
|
Header2: types.CreateTestHeader(chainID, height, heightMinus1, suite.now, suite.valSet, suite.valSet, signers),
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: clientID,
|
ClientId: clientID,
|
||||||
}
|
}
|
||||||
|
@ -50,6 +51,8 @@ func (suite *TendermintTestSuite) TestMisbehaviourValidateBasic() {
|
||||||
|
|
||||||
altSigners := []tmtypes.PrivValidator{altPrivVal}
|
altSigners := []tmtypes.PrivValidator{altPrivVal}
|
||||||
|
|
||||||
|
heightMinus1 := clienttypes.NewHeight(0, height.EpochHeight-1)
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
misbehaviour *types.Misbehaviour
|
misbehaviour *types.Misbehaviour
|
||||||
|
@ -60,7 +63,7 @@ func (suite *TendermintTestSuite) TestMisbehaviourValidateBasic() {
|
||||||
"valid misbehaviour",
|
"valid misbehaviour",
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: suite.header,
|
Header1: suite.header,
|
||||||
Header2: types.CreateTestHeader(chainID, epochHeight, epochHeight-1, suite.now.Add(time.Minute), suite.valSet, suite.valSet, signers),
|
Header2: types.CreateTestHeader(chainID, height, heightMinus1, suite.now.Add(time.Minute), suite.valSet, suite.valSet, signers),
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: clientID,
|
ClientId: clientID,
|
||||||
},
|
},
|
||||||
|
@ -83,7 +86,7 @@ func (suite *TendermintTestSuite) TestMisbehaviourValidateBasic() {
|
||||||
"valid misbehaviour with different trusted headers",
|
"valid misbehaviour with different trusted headers",
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: suite.header,
|
Header1: suite.header,
|
||||||
Header2: types.CreateTestHeader(chainID, epochHeight, epochHeight-3, suite.now.Add(time.Minute), suite.valSet, bothValSet, signers),
|
Header2: types.CreateTestHeader(chainID, height, clienttypes.NewHeight(0, height.EpochHeight-3), suite.now.Add(time.Minute), suite.valSet, bothValSet, signers),
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: clientID,
|
ClientId: clientID,
|
||||||
},
|
},
|
||||||
|
@ -93,7 +96,7 @@ func (suite *TendermintTestSuite) TestMisbehaviourValidateBasic() {
|
||||||
{
|
{
|
||||||
"trusted height is 0 in Header1",
|
"trusted height is 0 in Header1",
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: types.CreateTestHeader(chainID, epochHeight, 0, suite.now.Add(time.Minute), suite.valSet, suite.valSet, signers),
|
Header1: types.CreateTestHeader(chainID, height, clienttypes.ZeroHeight(), suite.now.Add(time.Minute), suite.valSet, suite.valSet, signers),
|
||||||
Header2: suite.header,
|
Header2: suite.header,
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: clientID,
|
ClientId: clientID,
|
||||||
|
@ -105,7 +108,7 @@ func (suite *TendermintTestSuite) TestMisbehaviourValidateBasic() {
|
||||||
"trusted height is 0 in Header2",
|
"trusted height is 0 in Header2",
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: suite.header,
|
Header1: suite.header,
|
||||||
Header2: types.CreateTestHeader(chainID, epochHeight, 0, suite.now.Add(time.Minute), suite.valSet, suite.valSet, signers),
|
Header2: types.CreateTestHeader(chainID, height, clienttypes.ZeroHeight(), suite.now.Add(time.Minute), suite.valSet, suite.valSet, signers),
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: clientID,
|
ClientId: clientID,
|
||||||
},
|
},
|
||||||
|
@ -115,7 +118,7 @@ func (suite *TendermintTestSuite) TestMisbehaviourValidateBasic() {
|
||||||
{
|
{
|
||||||
"trusted valset is nil in Header1",
|
"trusted valset is nil in Header1",
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: types.CreateTestHeader(chainID, epochHeight, epochHeight-1, suite.now.Add(time.Minute), suite.valSet, nil, signers),
|
Header1: types.CreateTestHeader(chainID, height, heightMinus1, suite.now.Add(time.Minute), suite.valSet, nil, signers),
|
||||||
Header2: suite.header,
|
Header2: suite.header,
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: clientID,
|
ClientId: clientID,
|
||||||
|
@ -127,7 +130,7 @@ func (suite *TendermintTestSuite) TestMisbehaviourValidateBasic() {
|
||||||
"trusted valset is nil in Header2",
|
"trusted valset is nil in Header2",
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: suite.header,
|
Header1: suite.header,
|
||||||
Header2: types.CreateTestHeader(chainID, epochHeight, epochHeight-1, suite.now.Add(time.Minute), suite.valSet, nil, signers),
|
Header2: types.CreateTestHeader(chainID, height, heightMinus1, suite.now.Add(time.Minute), suite.valSet, nil, signers),
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: clientID,
|
ClientId: clientID,
|
||||||
},
|
},
|
||||||
|
@ -138,7 +141,7 @@ func (suite *TendermintTestSuite) TestMisbehaviourValidateBasic() {
|
||||||
"invalid client ID ",
|
"invalid client ID ",
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: suite.header,
|
Header1: suite.header,
|
||||||
Header2: types.CreateTestHeader(chainID, epochHeight, epochHeight-1, suite.now, suite.valSet, suite.valSet, signers),
|
Header2: types.CreateTestHeader(chainID, height, heightMinus1, suite.now, suite.valSet, suite.valSet, signers),
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: "GAIA",
|
ClientId: "GAIA",
|
||||||
},
|
},
|
||||||
|
@ -149,7 +152,7 @@ func (suite *TendermintTestSuite) TestMisbehaviourValidateBasic() {
|
||||||
"wrong chainID on header1",
|
"wrong chainID on header1",
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: suite.header,
|
Header1: suite.header,
|
||||||
Header2: types.CreateTestHeader("ethermint", epochHeight, epochHeight-1, suite.now, suite.valSet, suite.valSet, signers),
|
Header2: types.CreateTestHeader("ethermint", height, heightMinus1, suite.now, suite.valSet, suite.valSet, signers),
|
||||||
ChainId: "ethermint",
|
ChainId: "ethermint",
|
||||||
ClientId: clientID,
|
ClientId: clientID,
|
||||||
},
|
},
|
||||||
|
@ -160,7 +163,7 @@ func (suite *TendermintTestSuite) TestMisbehaviourValidateBasic() {
|
||||||
"wrong chainID on header2",
|
"wrong chainID on header2",
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: suite.header,
|
Header1: suite.header,
|
||||||
Header2: types.CreateTestHeader("ethermint", epochHeight, epochHeight-1, suite.now, suite.valSet, suite.valSet, signers),
|
Header2: types.CreateTestHeader("ethermint", height, heightMinus1, suite.now, suite.valSet, suite.valSet, signers),
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: clientID,
|
ClientId: clientID,
|
||||||
},
|
},
|
||||||
|
@ -171,7 +174,7 @@ func (suite *TendermintTestSuite) TestMisbehaviourValidateBasic() {
|
||||||
"wrong chainID in misbehaviour",
|
"wrong chainID in misbehaviour",
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: suite.header,
|
Header1: suite.header,
|
||||||
Header2: types.CreateTestHeader(chainID, int64(height.EpochHeight), int64(height.EpochHeight-1), suite.now.Add(time.Minute), suite.valSet, suite.valSet, signers),
|
Header2: types.CreateTestHeader(chainID, height, heightMinus1, suite.now.Add(time.Minute), suite.valSet, suite.valSet, signers),
|
||||||
ChainId: "ethermint",
|
ChainId: "ethermint",
|
||||||
ClientId: clientID,
|
ClientId: clientID,
|
||||||
},
|
},
|
||||||
|
@ -182,7 +185,7 @@ func (suite *TendermintTestSuite) TestMisbehaviourValidateBasic() {
|
||||||
"mismatched heights",
|
"mismatched heights",
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: suite.header,
|
Header1: suite.header,
|
||||||
Header2: types.CreateTestHeader(chainID, 6, 4, suite.now, suite.valSet, suite.valSet, signers),
|
Header2: types.CreateTestHeader(chainID, clienttypes.NewHeight(0, 6), clienttypes.NewHeight(0, 4), suite.now, suite.valSet, suite.valSet, signers),
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: clientID,
|
ClientId: clientID,
|
||||||
},
|
},
|
||||||
|
@ -203,7 +206,7 @@ func (suite *TendermintTestSuite) TestMisbehaviourValidateBasic() {
|
||||||
{
|
{
|
||||||
"header 1 doesn't have 2/3 majority",
|
"header 1 doesn't have 2/3 majority",
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: types.CreateTestHeader(chainID, epochHeight, epochHeight-1, suite.now, bothValSet, suite.valSet, bothSigners),
|
Header1: types.CreateTestHeader(chainID, height, heightMinus1, suite.now, bothValSet, suite.valSet, bothSigners),
|
||||||
Header2: suite.header,
|
Header2: suite.header,
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: clientID,
|
ClientId: clientID,
|
||||||
|
@ -226,7 +229,7 @@ func (suite *TendermintTestSuite) TestMisbehaviourValidateBasic() {
|
||||||
"header 2 doesn't have 2/3 majority",
|
"header 2 doesn't have 2/3 majority",
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: suite.header,
|
Header1: suite.header,
|
||||||
Header2: types.CreateTestHeader(chainID, epochHeight, epochHeight-1, suite.now, bothValSet, suite.valSet, bothSigners),
|
Header2: types.CreateTestHeader(chainID, height, heightMinus1, suite.now, bothValSet, suite.valSet, bothSigners),
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: clientID,
|
ClientId: clientID,
|
||||||
},
|
},
|
||||||
|
@ -248,7 +251,7 @@ func (suite *TendermintTestSuite) TestMisbehaviourValidateBasic() {
|
||||||
"validators sign off on wrong commit",
|
"validators sign off on wrong commit",
|
||||||
&types.Misbehaviour{
|
&types.Misbehaviour{
|
||||||
Header1: suite.header,
|
Header1: suite.header,
|
||||||
Header2: types.CreateTestHeader(chainID, epochHeight, epochHeight-1, suite.now, bothValSet, suite.valSet, bothSigners),
|
Header2: types.CreateTestHeader(chainID, height, heightMinus1, suite.now, bothValSet, suite.valSet, bothSigners),
|
||||||
ChainId: chainID,
|
ChainId: chainID,
|
||||||
ClientId: clientID,
|
ClientId: clientID,
|
||||||
},
|
},
|
||||||
|
|
|
@ -20,6 +20,8 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
chainID = "gaia"
|
chainID = "gaia"
|
||||||
|
chainIDEpoch0 = "gaia-epoch-0"
|
||||||
|
chainIDEpoch1 = "gaia-epoch-1"
|
||||||
clientID = "gaiamainnet"
|
clientID = "gaiamainnet"
|
||||||
trustingPeriod time.Duration = time.Hour * 24 * 7 * 2
|
trustingPeriod time.Duration = time.Hour * 24 * 7 * 2
|
||||||
ubdPeriod time.Duration = time.Hour * 24 * 7 * 3
|
ubdPeriod time.Duration = time.Hour * 24 * 7 * 3
|
||||||
|
@ -72,12 +74,12 @@ func (suite *TendermintTestSuite) SetupTest() {
|
||||||
pubKey, err := suite.privVal.GetPubKey()
|
pubKey, err := suite.privVal.GetPubKey()
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
epochHeight := int64(height.EpochHeight)
|
heightMinus1 := clienttypes.NewHeight(0, height.EpochHeight-1)
|
||||||
|
|
||||||
val := tmtypes.NewValidator(pubKey, 10)
|
val := tmtypes.NewValidator(pubKey, 10)
|
||||||
suite.valSet = tmtypes.NewValidatorSet([]*tmtypes.Validator{val})
|
suite.valSet = tmtypes.NewValidatorSet([]*tmtypes.Validator{val})
|
||||||
suite.valsHash = suite.valSet.Hash()
|
suite.valsHash = suite.valSet.Hash()
|
||||||
suite.header = ibctmtypes.CreateTestHeader(chainID, epochHeight, epochHeight-1, suite.now, suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal})
|
suite.header = ibctmtypes.CreateTestHeader(chainID, height, heightMinus1, suite.now, suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal})
|
||||||
suite.ctx = app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1, Time: suite.now})
|
suite.ctx = app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1, Time: suite.now})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,16 +24,17 @@ func MakeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) tmtypes.Bl
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateTestHeader creates a mock header for testing only.
|
// CreateTestHeader creates a mock header for testing only.
|
||||||
func CreateTestHeader(chainID string, height, trustedHeight int64, timestamp time.Time, tmValSet, tmTrustedVals *tmtypes.ValidatorSet, signers []tmtypes.PrivValidator) *Header {
|
func CreateTestHeader(chainID string, height, trustedHeight clienttypes.Height, timestamp time.Time, tmValSet, tmTrustedVals *tmtypes.ValidatorSet, signers []tmtypes.PrivValidator) *Header {
|
||||||
var (
|
var (
|
||||||
valSet *tmproto.ValidatorSet
|
valSet *tmproto.ValidatorSet
|
||||||
trustedVals *tmproto.ValidatorSet
|
trustedVals *tmproto.ValidatorSet
|
||||||
)
|
)
|
||||||
vsetHash := tmValSet.Hash()
|
vsetHash := tmValSet.Hash()
|
||||||
|
blockHeight := int64(height.EpochHeight)
|
||||||
tmHeader := tmtypes.Header{
|
tmHeader := tmtypes.Header{
|
||||||
Version: version.Consensus{Block: 2, App: 2},
|
Version: version.Consensus{Block: 2, App: 2},
|
||||||
ChainID: chainID,
|
ChainID: chainID,
|
||||||
Height: height,
|
Height: blockHeight,
|
||||||
Time: timestamp,
|
Time: timestamp,
|
||||||
LastBlockID: MakeBlockID(make([]byte, tmhash.Size), 10_000, make([]byte, tmhash.Size)),
|
LastBlockID: MakeBlockID(make([]byte, tmhash.Size), 10_000, make([]byte, tmhash.Size)),
|
||||||
LastCommitHash: tmhash.Sum([]byte("last_commit_hash")),
|
LastCommitHash: tmhash.Sum([]byte("last_commit_hash")),
|
||||||
|
@ -49,8 +50,8 @@ func CreateTestHeader(chainID string, height, trustedHeight int64, timestamp tim
|
||||||
|
|
||||||
hhash := tmHeader.Hash()
|
hhash := tmHeader.Hash()
|
||||||
blockID := MakeBlockID(hhash, 3, tmhash.Sum([]byte("part_set")))
|
blockID := MakeBlockID(hhash, 3, tmhash.Sum([]byte("part_set")))
|
||||||
voteSet := tmtypes.NewVoteSet(chainID, height, 1, tmproto.PrecommitType, tmValSet)
|
voteSet := tmtypes.NewVoteSet(chainID, blockHeight, 1, tmproto.PrecommitType, tmValSet)
|
||||||
commit, err := tmtypes.MakeCommit(blockID, height, 1, voteSet, signers, timestamp)
|
commit, err := tmtypes.MakeCommit(blockID, blockHeight, 1, voteSet, signers, timestamp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -77,7 +78,7 @@ func CreateTestHeader(chainID string, height, trustedHeight int64, timestamp tim
|
||||||
return &Header{
|
return &Header{
|
||||||
SignedHeader: &signedHeader,
|
SignedHeader: &signedHeader,
|
||||||
ValidatorSet: valSet,
|
ValidatorSet: valSet,
|
||||||
TrustedHeight: clienttypes.NewHeight(0, uint64(trustedHeight)),
|
TrustedHeight: trustedHeight,
|
||||||
TrustedValidators: trustedVals,
|
TrustedValidators: trustedVals,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,8 @@ import (
|
||||||
// It returns an error if:
|
// It returns an error if:
|
||||||
// - the client or header provided are not parseable to tendermint types
|
// - the client or header provided are not parseable to tendermint types
|
||||||
// - the header is invalid
|
// - the header is invalid
|
||||||
// - header height is less than or equal to the consensus state height
|
// - header height is less than or equal to the trusted header height
|
||||||
|
// - header epoch is not equal to trusted header epoch
|
||||||
// - header valset commit verification fails
|
// - header valset commit verification fails
|
||||||
// - header timestamp is past the trusting period in relation to the consensus state
|
// - 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
|
// - header timestamp is less than or equal to the consensus state timestamp
|
||||||
|
@ -32,6 +33,8 @@ import (
|
||||||
// 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 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
|
// 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
|
// the new latest height
|
||||||
|
// UpdateClient must only be used to update within a single epoch, thus header epoch number and trusted height's epoch
|
||||||
|
// number must be the same. To update to a new epoch, use a separate upgrade path
|
||||||
// Tendermint client validity checking uses the bisection algorithm described
|
// 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).
|
// in the [Tendermint spec](https://github.com/tendermint/spec/blob/master/spec/consensus/light-client.md).
|
||||||
func (cs ClientState) CheckHeaderAndUpdateState(
|
func (cs ClientState) CheckHeaderAndUpdateState(
|
||||||
|
@ -91,6 +94,16 @@ func checkValidity(
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateClient only accepts updates with a header at the same epoch
|
||||||
|
// as the trusted consensus state
|
||||||
|
if header.GetHeight().GetEpochNumber() != header.TrustedHeight.EpochNumber {
|
||||||
|
return sdkerrors.Wrapf(
|
||||||
|
ErrInvalidHeaderHeight,
|
||||||
|
"header height epoch %d does not match trusted header epoch %d",
|
||||||
|
header.GetHeight().GetEpochNumber(), header.TrustedHeight.EpochNumber,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
tmTrustedValidators, err := tmtypes.ValidatorSetFromProto(header.TrustedValidators)
|
tmTrustedValidators, err := tmtypes.ValidatorSetFromProto(header.TrustedValidators)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sdkerrors.Wrap(err, "trusted validator set in not tendermint validator set type")
|
return sdkerrors.Wrap(err, "trusted validator set in not tendermint validator set type")
|
||||||
|
@ -110,7 +123,7 @@ func checkValidity(
|
||||||
if header.GetHeight().LTE(header.TrustedHeight) {
|
if header.GetHeight().LTE(header.TrustedHeight) {
|
||||||
return sdkerrors.Wrapf(
|
return sdkerrors.Wrapf(
|
||||||
clienttypes.ErrInvalidHeader,
|
clienttypes.ErrInvalidHeader,
|
||||||
"header height ≤ consensus state height (%d ≤ %d)", header.GetHeight(), header.TrustedHeight,
|
"header height ≤ consensus state height (%s ≤ %s)", header.GetHeight(), header.TrustedHeight,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,13 +138,24 @@ func checkValidity(
|
||||||
Header: &trustedHeader,
|
Header: &trustedHeader,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chainID := clientState.GetChainID()
|
||||||
|
// If chainID is in epoch format, then set epoch number of chainID with the epoch number
|
||||||
|
// of the header we are verifying
|
||||||
|
// This is useful if the update is at a previous epoch rather than an update to the latest epoch
|
||||||
|
// of the client.
|
||||||
|
// The chainID must be set correctly for the previous epoch before attempting verification.
|
||||||
|
// Updates for previous epochs are not supported if the chainID is not in epoch format.
|
||||||
|
if clienttypes.IsEpochFormat(chainID) {
|
||||||
|
chainID, _ = clienttypes.SetEpochNumber(chainID, header.GetHeight().GetEpochNumber())
|
||||||
|
}
|
||||||
|
|
||||||
// Verify next header with the passed-in trustedVals
|
// Verify next header with the passed-in trustedVals
|
||||||
// - asserts trusting period not passed
|
// - asserts trusting period not passed
|
||||||
// - assert header timestamp is not past the trusting period
|
// - assert header timestamp is not past the trusting period
|
||||||
// - assert header timestamp is past latest stored consensus state timestamp
|
// - assert header timestamp is past latest stored consensus state timestamp
|
||||||
// - assert that a TrustLevel proportion of TrustedValidators signed new Commit
|
// - assert that a TrustLevel proportion of TrustedValidators signed new Commit
|
||||||
err = light.Verify(
|
err = light.Verify(
|
||||||
clientState.GetChainID(), &signedHeader,
|
chainID, &signedHeader,
|
||||||
tmTrustedValidators, tmSignedHeader, tmValidatorSet,
|
tmTrustedValidators, tmSignedHeader, tmValidatorSet,
|
||||||
clientState.TrustingPeriod, currentTimestamp, clientState.MaxClockDrift, clientState.TrustLevel.ToTendermint(),
|
clientState.TrustingPeriod, currentTimestamp, clientState.MaxClockDrift, clientState.TrustLevel.ToTendermint(),
|
||||||
)
|
)
|
||||||
|
|
|
@ -26,6 +26,10 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
epochHeight := int64(height.EpochHeight)
|
epochHeight := int64(height.EpochHeight)
|
||||||
|
|
||||||
|
// create modified heights to use for test-cases
|
||||||
|
heightPlus1 := clienttypes.NewHeight(height.EpochNumber, height.EpochHeight+1)
|
||||||
|
heightMinus1 := clienttypes.NewHeight(height.EpochNumber, height.EpochHeight-1)
|
||||||
heightMinus3 := clienttypes.NewHeight(height.EpochNumber, height.EpochHeight-3)
|
heightMinus3 := clienttypes.NewHeight(height.EpochNumber, height.EpochHeight-3)
|
||||||
heightPlus5 := clienttypes.NewHeight(height.EpochNumber, height.EpochHeight+5)
|
heightPlus5 := clienttypes.NewHeight(height.EpochNumber, height.EpochHeight+5)
|
||||||
|
|
||||||
|
@ -54,7 +58,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
|
||||||
setup: func() {
|
setup: func() {
|
||||||
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
||||||
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
||||||
newHeader = types.CreateTestHeader(chainID, epochHeight+1, epochHeight, suite.headerTime, suite.valSet, suite.valSet, signers)
|
newHeader = types.CreateTestHeader(chainID, heightPlus1, height, suite.headerTime, suite.valSet, suite.valSet, signers)
|
||||||
currentTime = suite.now
|
currentTime = suite.now
|
||||||
},
|
},
|
||||||
expPass: true,
|
expPass: true,
|
||||||
|
@ -64,7 +68,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
|
||||||
setup: func() {
|
setup: func() {
|
||||||
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
||||||
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
||||||
newHeader = types.CreateTestHeader(chainID, epochHeight+5, epochHeight, suite.headerTime, bothValSet, suite.valSet, bothSigners)
|
newHeader = types.CreateTestHeader(chainID, heightPlus5, height, suite.headerTime, bothValSet, suite.valSet, bothSigners)
|
||||||
currentTime = suite.now
|
currentTime = suite.now
|
||||||
},
|
},
|
||||||
expPass: true,
|
expPass: true,
|
||||||
|
@ -74,7 +78,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
|
||||||
setup: func() {
|
setup: func() {
|
||||||
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
||||||
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), bothValSet.Hash())
|
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), bothValSet.Hash())
|
||||||
newHeader = types.CreateTestHeader(chainID, epochHeight+1, epochHeight, suite.headerTime, bothValSet, bothValSet, bothSigners)
|
newHeader = types.CreateTestHeader(chainID, heightPlus1, height, suite.headerTime, bothValSet, bothValSet, bothSigners)
|
||||||
currentTime = suite.now
|
currentTime = suite.now
|
||||||
},
|
},
|
||||||
expPass: true,
|
expPass: true,
|
||||||
|
@ -85,7 +89,17 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
|
||||||
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
||||||
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
||||||
consStateHeight = heightMinus3
|
consStateHeight = heightMinus3
|
||||||
newHeader = types.CreateTestHeader(chainID, epochHeight-1, epochHeight-3, suite.headerTime, bothValSet, suite.valSet, bothSigners)
|
newHeader = types.CreateTestHeader(chainID, heightMinus1, heightMinus3, suite.headerTime, bothValSet, suite.valSet, bothSigners)
|
||||||
|
currentTime = suite.now
|
||||||
|
},
|
||||||
|
expPass: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "successful update for a previous epoch",
|
||||||
|
setup: func() {
|
||||||
|
clientState = types.NewClientState(chainIDEpoch1, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
||||||
|
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
||||||
|
newHeader = types.CreateTestHeader(chainIDEpoch0, height, heightMinus3, suite.headerTime, bothValSet, suite.valSet, bothSigners)
|
||||||
currentTime = suite.now
|
currentTime = suite.now
|
||||||
},
|
},
|
||||||
expPass: true,
|
expPass: true,
|
||||||
|
@ -95,7 +109,27 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
|
||||||
setup: func() {
|
setup: func() {
|
||||||
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
||||||
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
||||||
newHeader = types.CreateTestHeader("ethermint", int64(height.EpochHeight+1), int64(height.EpochHeight), suite.headerTime, suite.valSet, suite.valSet, signers)
|
newHeader = types.CreateTestHeader("ethermint", heightPlus1, height, suite.headerTime, suite.valSet, suite.valSet, signers)
|
||||||
|
currentTime = suite.now
|
||||||
|
},
|
||||||
|
expPass: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "unsuccessful update to a future epoch",
|
||||||
|
setup: func() {
|
||||||
|
clientState = types.NewClientState(chainIDEpoch0, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
||||||
|
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
||||||
|
newHeader = types.CreateTestHeader(chainIDEpoch1, clienttypes.NewHeight(1, 1), height, suite.headerTime, suite.valSet, suite.valSet, signers)
|
||||||
|
currentTime = suite.now
|
||||||
|
},
|
||||||
|
expPass: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "unsuccessful update: header height epoch and trusted height epoch mismatch",
|
||||||
|
setup: func() {
|
||||||
|
clientState = types.NewClientState(chainIDEpoch1, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clienttypes.NewHeight(1, 1), commitmenttypes.GetSDKSpecs(), false, false)
|
||||||
|
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
||||||
|
newHeader = types.CreateTestHeader(chainIDEpoch1, clienttypes.NewHeight(1, 3), height, suite.headerTime, suite.valSet, suite.valSet, signers)
|
||||||
currentTime = suite.now
|
currentTime = suite.now
|
||||||
},
|
},
|
||||||
expPass: false,
|
expPass: false,
|
||||||
|
@ -105,7 +139,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
|
||||||
setup: func() {
|
setup: func() {
|
||||||
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
||||||
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
||||||
newHeader = types.CreateTestHeader(chainID, epochHeight+1, epochHeight, suite.headerTime, bothValSet, suite.valSet, bothSigners)
|
newHeader = types.CreateTestHeader(chainID, heightPlus1, height, suite.headerTime, bothValSet, suite.valSet, bothSigners)
|
||||||
currentTime = suite.now
|
currentTime = suite.now
|
||||||
},
|
},
|
||||||
expPass: false,
|
expPass: false,
|
||||||
|
@ -115,7 +149,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
|
||||||
setup: func() {
|
setup: func() {
|
||||||
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
||||||
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), bothValSet.Hash())
|
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), bothValSet.Hash())
|
||||||
newHeader = types.CreateTestHeader(chainID, epochHeight+1, epochHeight, suite.headerTime, suite.valSet, bothValSet, signers)
|
newHeader = types.CreateTestHeader(chainID, heightPlus1, height, suite.headerTime, suite.valSet, bothValSet, signers)
|
||||||
currentTime = suite.now
|
currentTime = suite.now
|
||||||
},
|
},
|
||||||
expPass: false,
|
expPass: false,
|
||||||
|
@ -125,7 +159,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
|
||||||
setup: func() {
|
setup: func() {
|
||||||
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
||||||
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
||||||
newHeader = types.CreateTestHeader(chainID, epochHeight+5, epochHeight, suite.headerTime, altValSet, suite.valSet, altSigners)
|
newHeader = types.CreateTestHeader(chainID, heightPlus5, height, suite.headerTime, altValSet, suite.valSet, altSigners)
|
||||||
currentTime = suite.now
|
currentTime = suite.now
|
||||||
},
|
},
|
||||||
expPass: false,
|
expPass: false,
|
||||||
|
@ -135,7 +169,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
|
||||||
setup: func() {
|
setup: func() {
|
||||||
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
||||||
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
||||||
newHeader = types.CreateTestHeader(chainID, epochHeight+5, epochHeight, suite.headerTime, bothValSet, bothValSet, bothSigners)
|
newHeader = types.CreateTestHeader(chainID, heightPlus5, height, suite.headerTime, bothValSet, bothValSet, bothSigners)
|
||||||
currentTime = suite.now
|
currentTime = suite.now
|
||||||
},
|
},
|
||||||
expPass: false,
|
expPass: false,
|
||||||
|
@ -145,7 +179,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
|
||||||
setup: func() {
|
setup: func() {
|
||||||
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
||||||
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
||||||
newHeader = types.CreateTestHeader(chainID, epochHeight+1, epochHeight, suite.headerTime, suite.valSet, suite.valSet, signers)
|
newHeader = types.CreateTestHeader(chainID, heightPlus1, height, suite.headerTime, suite.valSet, suite.valSet, signers)
|
||||||
// make current time pass trusting period from last timestamp on clientstate
|
// make current time pass trusting period from last timestamp on clientstate
|
||||||
currentTime = suite.now.Add(trustingPeriod)
|
currentTime = suite.now.Add(trustingPeriod)
|
||||||
},
|
},
|
||||||
|
@ -156,7 +190,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
|
||||||
setup: func() {
|
setup: func() {
|
||||||
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
||||||
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
||||||
newHeader = types.CreateTestHeader(chainID, epochHeight+1, epochHeight, suite.now.Add(time.Minute), suite.valSet, suite.valSet, signers)
|
newHeader = types.CreateTestHeader(chainID, heightPlus1, height, suite.now.Add(time.Minute), suite.valSet, suite.valSet, signers)
|
||||||
currentTime = suite.now
|
currentTime = suite.now
|
||||||
},
|
},
|
||||||
expPass: false,
|
expPass: false,
|
||||||
|
@ -166,7 +200,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
|
||||||
setup: func() {
|
setup: func() {
|
||||||
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
||||||
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
||||||
newHeader = types.CreateTestHeader(chainID, epochHeight+1, epochHeight, suite.clientTime, suite.valSet, suite.valSet, signers)
|
newHeader = types.CreateTestHeader(chainID, heightPlus1, height, suite.clientTime, suite.valSet, suite.valSet, signers)
|
||||||
currentTime = suite.now
|
currentTime = suite.now
|
||||||
},
|
},
|
||||||
expPass: false,
|
expPass: false,
|
||||||
|
@ -176,7 +210,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
|
||||||
setup: func() {
|
setup: func() {
|
||||||
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), false, false)
|
||||||
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
||||||
newHeader = types.CreateTestHeader(chainID, epochHeight+1, epochHeight, suite.headerTime, suite.valSet, suite.valSet, signers)
|
newHeader = types.CreateTestHeader(chainID, heightPlus1, height, suite.headerTime, suite.valSet, suite.valSet, signers)
|
||||||
// cause new header to fail validatebasic by changing commit height to mismatch header height
|
// cause new header to fail validatebasic by changing commit height to mismatch header height
|
||||||
newHeader.SignedHeader.Commit.Height = epochHeight - 1
|
newHeader.SignedHeader.Commit.Height = epochHeight - 1
|
||||||
currentTime = suite.now
|
currentTime = suite.now
|
||||||
|
@ -189,7 +223,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
|
||||||
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, heightPlus5, commitmenttypes.GetSDKSpecs(), false, false)
|
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, heightPlus5, commitmenttypes.GetSDKSpecs(), false, false)
|
||||||
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash)
|
||||||
// Make new header at height less than latest client state
|
// Make new header at height less than latest client state
|
||||||
newHeader = types.CreateTestHeader(chainID, epochHeight-1, epochHeight, suite.headerTime, suite.valSet, suite.valSet, signers)
|
newHeader = types.CreateTestHeader(chainID, heightMinus1, height, suite.headerTime, suite.valSet, suite.valSet, signers)
|
||||||
currentTime = suite.now
|
currentTime = suite.now
|
||||||
},
|
},
|
||||||
expPass: false,
|
expPass: false,
|
||||||
|
|
|
@ -75,9 +75,8 @@ func (cs *ClientState) CheckHeaderAndUpdateState(
|
||||||
) (exported.ClientState, exported.ConsensusState, error) {
|
) (exported.ClientState, exported.ConsensusState, error) {
|
||||||
// use the chain ID from context since the localhost client is from the running chain (i.e self).
|
// use the chain ID from context since the localhost client is from the running chain (i.e self).
|
||||||
cs.ChainId = ctx.ChainID()
|
cs.ChainId = ctx.ChainID()
|
||||||
// Hardcode 0 for epoch number for now
|
epoch := clienttypes.ParseChainID(cs.ChainId)
|
||||||
// TODO: Retrieve epoch number from chain-id
|
cs.Height = clienttypes.NewHeight(epoch, uint64(ctx.BlockHeight()))
|
||||||
cs.Height = clienttypes.NewHeight(0, uint64(ctx.BlockHeight()))
|
|
||||||
return cs, nil, nil
|
return cs, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,6 @@ func QueryTendermintProof(clientCtx client.Context, key []byte) ([]byte, []byte,
|
||||||
return nil, nil, clienttypes.Height{}, err
|
return nil, nil, clienttypes.Height{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: retrieve epoch number from chain-id
|
epoch := clienttypes.ParseChainID(clientCtx.ChainID)
|
||||||
return res.Value, proofBz, clienttypes.NewHeight(0, uint64(res.Height)+1), nil
|
return res.Value, proofBz, clienttypes.NewHeight(epoch, uint64(res.Height)+1), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,9 @@ func (suite *IBCTestSuite) SetupTest() {
|
||||||
val := tmtypes.NewValidator(pubKey, 10)
|
val := tmtypes.NewValidator(pubKey, 10)
|
||||||
valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{val})
|
valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{val})
|
||||||
|
|
||||||
suite.header = ibctmtypes.CreateTestHeader(chainID, height, height-1, now, valSet, valSet, []tmtypes.PrivValidator{privVal})
|
clientHeightMinus1 := clienttypes.NewHeight(0, height-1)
|
||||||
|
|
||||||
|
suite.header = ibctmtypes.CreateTestHeader(chainID, clientHeight, clientHeightMinus1, now, valSet, valSet, []tmtypes.PrivValidator{privVal})
|
||||||
|
|
||||||
suite.ctx = suite.app.BaseApp.NewContext(isCheckTx, tmproto.Header{})
|
suite.ctx = suite.app.BaseApp.NewContext(isCheckTx, tmproto.Header{})
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,13 @@ given by the chain's chainID, and the epoch height given by the Tendermint block
|
||||||
and resets its block-height, it is responsible for updating its chain-id to increment the epoch number.
|
and resets its block-height, it is responsible for updating its chain-id to increment the epoch number.
|
||||||
IBC Tendermint clients then verifies the epoch number against their `ChainId` and treat the `EpochHeight` as the Tendermint block-height.
|
IBC Tendermint clients then verifies the epoch number against their `ChainId` and treat the `EpochHeight` as the Tendermint block-height.
|
||||||
|
|
||||||
TODO: Explain how to structure chain-id to make epoch-number parsable
|
Tendermint chains wishing to use epochs to maintain persistent IBC connections even across height-resetting upgrades must format their chain-ids
|
||||||
|
in the following manner: `{chainID}-{version}`. On any height-resetting upgrade, the chainID **MUST** be updated with a higher epoch number
|
||||||
|
than the previous value.
|
||||||
|
|
||||||
|
Ex:
|
||||||
|
Before upgrade ChainID: `gaiamainnet-3`
|
||||||
|
After upgrade ChainID: `gaiamainnet-4`
|
||||||
|
|
||||||
Clients that do not require epochs, such as the solo-machine client, simply hardcode `0` into the epoch number whenever they
|
Clients that do not require epochs, such as the solo-machine client, simply hardcode `0` into the epoch number whenever they
|
||||||
need to return an IBC height when implementing IBC interfaces and use the `EpochHeight` exclusively.
|
need to return an IBC height when implementing IBC interfaces and use the `EpochHeight` exclusively.
|
||||||
|
|
|
@ -181,10 +181,12 @@ func (chain *TestChain) QueryProof(key []byte) ([]byte, clienttypes.Height) {
|
||||||
proof, err := chain.App.AppCodec().MarshalBinaryBare(&merkleProof)
|
proof, err := chain.App.AppCodec().MarshalBinaryBare(&merkleProof)
|
||||||
require.NoError(chain.t, err)
|
require.NoError(chain.t, err)
|
||||||
|
|
||||||
|
epoch := clienttypes.ParseChainID(chain.ChainID)
|
||||||
|
|
||||||
// proof height + 1 is returned as the proof created corresponds to the height the proof
|
// proof height + 1 is returned as the proof created corresponds to the height the proof
|
||||||
// was created in the IAVL tree. Tendermint and subsequently the clients that rely on it
|
// was created in the IAVL tree. Tendermint and subsequently the clients that rely on it
|
||||||
// have heights 1 above the IAVL tree. Thus we return proof height + 1
|
// have heights 1 above the IAVL tree. Thus we return proof height + 1
|
||||||
return proof, clienttypes.NewHeight(0, uint64(res.Height)+1)
|
return proof, clienttypes.NewHeight(epoch, uint64(res.Height)+1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryClientStateProof performs and abci query for a client state
|
// QueryClientStateProof performs and abci query for a client state
|
||||||
|
|
Loading…
Reference in New Issue