Migrate IBC tendermint header to proto (#7120)

* gen header proto file

* fix tm type to proto conversion issues

* fix tendermint type tests

* fix remaining tests

* fix lint

* Update x/ibc/07-tendermint/types/header.go

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Update x/ibc/07-tendermint/types/header.go

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* apply @fedekunze review suggestions

* fix build

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
This commit is contained in:
colin axnér 2020-08-20 17:46:11 +02:00 committed by GitHub
parent 3368dae5f5
commit be0cc63808
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 759 additions and 202 deletions

View File

@ -371,6 +371,7 @@ proto-update-deps:
@curl -sSL $(TM_URL)/types/types.proto > $(TM_TYPES)/types.proto
@curl -sSL $(TM_URL)/types/evidence.proto > $(TM_TYPES)/evidence.proto
@curl -sSL $(TM_URL)/types/params.proto > $(TM_TYPES)/params.proto
@curl -sSL $(TM_URL)/types/validator.proto > $(TM_TYPES)/validator.proto
@mkdir -p $(TM_CRYPTO_TYPES)
@curl -sSL $(TM_URL)/crypto/proof.proto > $(TM_CRYPTO_TYPES)/proof.proto

View File

@ -3,6 +3,8 @@ package ibc.tendermint;
option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types";
import "tendermint/types/validator.proto";
import "tendermint/types/types.proto";
import "confio/proofs.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";
@ -14,7 +16,7 @@ import "gogoproto/gogo.proto";
message ClientState {
option (gogoproto.goproto_getters) = false;
string chain_id = 1;
string chain_id = 1;
Fraction trust_level = 2 [
(gogoproto.nullable) = false,
(gogoproto.moretags) = "yaml:\"trust_level\""
@ -22,21 +24,21 @@ message ClientState {
// duration of the period since the LastestTimestamp during which the
// submitted headers are valid for upgrade
google.protobuf.Duration trusting_period = 3 [
(gogoproto.nullable) = false,
(gogoproto.nullable) = false,
(gogoproto.stdduration) = true,
(gogoproto.moretags) = "yaml:\"trusting_period\""
(gogoproto.moretags) = "yaml:\"trusting_period\""
];
// duration of the staking unbonding period
google.protobuf.Duration unbonding_period = 4 [
(gogoproto.nullable) = false,
(gogoproto.nullable) = false,
(gogoproto.stdduration) = true,
(gogoproto.moretags) = "yaml:\"unbonding_period\""
(gogoproto.moretags) = "yaml:\"unbonding_period\""
];
// defines how much new (untrusted) header's Time can drift into the future.
google.protobuf.Duration max_clock_drift = 5 [
(gogoproto.nullable) = false,
(gogoproto.nullable) = false,
(gogoproto.stdduration) = true,
(gogoproto.moretags) = "yaml:\"max_clock_drift\""
(gogoproto.moretags) = "yaml:\"max_clock_drift\""
];
// Block height when the client was frozen due to a misbehaviour
uint64 frozen_height = 6 [(gogoproto.moretags) = "yaml:\"frozen_height\""];
@ -58,15 +60,42 @@ message ConsensusState {
// commitment root (i.e app hash)
ibc.commitment.MerkleRoot root = 2 [(gogoproto.nullable) = false];
// height at which the consensus state was stored.
uint64 height = 3;
bytes next_validators_hash = 4 [
(gogoproto.casttype) = "github.com/tendermint/tendermint/libs/bytes.HexBytes",
uint64 height = 3;
bytes next_validators_hash = 4 [
(gogoproto.casttype) =
"github.com/tendermint/tendermint/libs/bytes.HexBytes",
(gogoproto.moretags) = "yaml:\"next_validators_hash\""
];
}
// Header defines the Tendermint client consensus Header.
// It encapsulates all the information necessary to update from a trusted
// Tendermint ConsensusState. The inclusion of TrustedHeight and
// TrustedValidators allows this update to process correctly, so long as the
// ConsensusState for the TrustedHeight exists, this removes race conditions
// among relayers The SignedHeader and ValidatorSet are the new untrusted update
// fields for the client. The TrustedHeight is the height of a stored
// ConsensusState on the client that will be used to verify the new untrusted
// header. The Trusted ConsensusState must be within the unbonding period of
// current time in order to correctly verify, and the TrustedValidators must
// hash to TrustedConsensusState.NextValidatorsHash since that is the last
// trusted validator set at the TrustedHeight.
message Header {
.tendermint.types.SignedHeader signed_header = 1 [
(gogoproto.embed) = true,
(gogoproto.nullable) = false,
(gogoproto.moretags) = "yaml:\"signed_header\""
];
.tendermint.types.ValidatorSet validator_set = 2
[(gogoproto.moretags) = "yaml:\"validator_set\""];
uint64 trusted_height = 3 [(gogoproto.moretags) = "yaml:\"trusted_height\""];
.tendermint.types.ValidatorSet trusted_validators = 4
[(gogoproto.moretags) = "yaml:\"trusted_validators\""];
}
// Fraction defines the protobuf message type for tmmath.Fraction
message Fraction {
int64 numerator = 1;
int64 numerator = 1;
int64 denominator = 2;
}

View File

@ -0,0 +1,25 @@
syntax = "proto3";
package tendermint.types;
option go_package = "github.com/tendermint/tendermint/proto/tendermint/types";
import "gogoproto/gogo.proto";
import "tendermint/crypto/keys.proto";
message ValidatorSet {
repeated Validator validators = 1;
Validator proposer = 2;
int64 total_voting_power = 3;
}
message Validator {
bytes address = 1;
tendermint.crypto.PublicKey pub_key = 2 [(gogoproto.nullable) = false];
int64 voting_power = 3;
int64 proposer_priority = 4;
}
message SimpleValidator {
tendermint.crypto.PublicKey pub_key = 1;
int64 voting_power = 2;
}

View File

@ -148,9 +148,15 @@ func QueryTendermintHeader(clientCtx client.Context) (ibctmtypes.Header, int64,
return ibctmtypes.Header{}, 0, err
}
protoCommit := commit.SignedHeader.ToProto()
protoValset, err := tmtypes.NewValidatorSet(validators.Validators).ToProto()
if err != nil {
return ibctmtypes.Header{}, 0, err
}
header := ibctmtypes.Header{
SignedHeader: commit.SignedHeader,
ValidatorSet: tmtypes.NewValidatorSet(validators.Validators),
SignedHeader: *protoCommit,
ValidatorSet: protoValset,
}
return header, height, nil

View File

@ -57,11 +57,11 @@ func (suite *KeeperTestSuite) TestCreateClient() {
func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
// Must create header creation functions since suite.header gets recreated on each test case
createFutureUpdateFn := func(s *KeeperTestSuite) ibctmtypes.Header {
return ibctmtypes.CreateTestHeader(testChainID, suite.header.Height+3, suite.header.Height, suite.header.Time.Add(time.Hour),
return ibctmtypes.CreateTestHeader(testChainID, int64(suite.header.GetHeight()+3), int64(suite.header.GetHeight()), suite.header.Header.Time.Add(time.Hour),
suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal})
}
createPastUpdateFn := func(s *KeeperTestSuite) ibctmtypes.Header {
return ibctmtypes.CreateTestHeader(testChainID, suite.header.Height-2, suite.header.Height-4, suite.header.Time,
return ibctmtypes.CreateTestHeader(testChainID, int64(suite.header.GetHeight()-2), int64(suite.header.GetHeight())-4, suite.header.Header.Time,
suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal})
}
var (
@ -189,7 +189,7 @@ func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
err := tc.malleate()
suite.Require().NoError(err)
suite.ctx = suite.ctx.WithBlockTime(updateHeader.Time.Add(time.Minute))
suite.ctx = suite.ctx.WithBlockTime(updateHeader.Header.Time.Add(time.Minute))
updatedClientState, err := suite.keeper.UpdateClient(suite.ctx, testClientID, updateHeader)
@ -198,9 +198,9 @@ func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
expConsensusState := &ibctmtypes.ConsensusState{
Height: updateHeader.GetHeight(),
Timestamp: updateHeader.Time,
Root: commitmenttypes.NewMerkleRoot(updateHeader.AppHash),
NextValidatorsHash: updateHeader.NextValidatorsHash,
Timestamp: updateHeader.GetTime(),
Root: commitmenttypes.NewMerkleRoot(updateHeader.Header.GetAppHash()),
NextValidatorsHash: updateHeader.Header.NextValidatorsHash,
}
newClientState, found := suite.keeper.GetClientState(suite.ctx, testClientID)
@ -212,9 +212,9 @@ func (suite *KeeperTestSuite) TestUpdateClientTendermint() {
suite.Require().Equal(updatedClientState, newClientState, "updatedClient state not persisted correctly")
// Determine if clientState should be updated or not
if uint64(updateHeader.Height) > clientState.GetLatestHeight() {
// Header Height is greater than clientState latest Height, clientState should be updated with header.Height
suite.Require().Equal(uint64(updateHeader.Height), updatedClientState.GetLatestHeight(), "clientstate height did not update")
if uint64(updateHeader.GetHeight()) > clientState.GetLatestHeight() {
// Header Height is greater than clientState latest Height, clientState should be updated with header.GetHeight()
suite.Require().Equal(uint64(updateHeader.GetHeight()), updatedClientState.GetLatestHeight(), "clientstate height did not update")
} else {
// Update will add past consensus state, clientState should not be updated at all
suite.Require().Equal(clientState.GetLatestHeight(), updatedClientState.GetLatestHeight(), "client state height updated for past header")

View File

@ -191,7 +191,7 @@ func (k Keeper) GetSelfConsensusState(ctx sdk.Context, height uint64) (exported.
consensusState := &ibctmtypes.ConsensusState{
Height: height,
Timestamp: histInfo.Header.Time,
Root: commitmenttypes.NewMerkleRoot(histInfo.Header.AppHash),
Root: commitmenttypes.NewMerkleRoot(histInfo.Header.GetAppHash()),
NextValidatorsHash: histInfo.Header.NextValidatorsHash,
}
return consensusState, true

View File

@ -212,11 +212,11 @@ func (suite KeeperTestSuite) TestConsensusStateHelpers() {
nextState := ibctmtypes.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot([]byte("next")), testClientHeight+5, suite.valSetHash)
header := ibctmtypes.CreateTestHeader(testClientID, testClientHeight+5, testClientHeight, suite.header.Time.Add(time.Minute),
header := ibctmtypes.CreateTestHeader(testClientID, testClientHeight+5, testClientHeight, suite.header.Header.Time.Add(time.Minute),
suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal})
// mock update functionality
clientState.LatestHeight = uint64(header.Height)
clientState.LatestHeight = header.GetHeight()
suite.keeper.SetClientConsensusState(suite.ctx, testClientID, testClientHeight+5, nextState)
suite.keeper.SetClientState(suite.ctx, testClientID, clientState)

View File

@ -60,7 +60,7 @@ func TestValidateGenesis(t *testing.T) {
clientID,
[]exported.ConsensusState{
ibctmtypes.NewConsensusState(
header.Time, commitmenttypes.NewMerkleRoot(header.AppHash), header.GetHeight(), header.NextValidatorsHash,
header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.GetHeight(), header.Header.NextValidatorsHash,
),
},
),
@ -85,7 +85,7 @@ func TestValidateGenesis(t *testing.T) {
clientID,
[]exported.ConsensusState{
ibctmtypes.NewConsensusState(
header.Time, commitmenttypes.NewMerkleRoot(header.AppHash), header.GetHeight(), header.NextValidatorsHash,
header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.GetHeight(), header.Header.NextValidatorsHash,
),
},
),
@ -124,7 +124,7 @@ func TestValidateGenesis(t *testing.T) {
"(CLIENTID2)",
[]exported.ConsensusState{
ibctmtypes.NewConsensusState(
header.Time, commitmenttypes.NewMerkleRoot(header.AppHash), 0, header.NextValidatorsHash,
header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), 0, header.Header.NextValidatorsHash,
),
},
),
@ -149,7 +149,7 @@ func TestValidateGenesis(t *testing.T) {
clientID,
[]exported.ConsensusState{
ibctmtypes.NewConsensusState(
header.Time, commitmenttypes.NewMerkleRoot(header.AppHash), 0, header.NextValidatorsHash,
header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), 0, header.Header.NextValidatorsHash,
),
},
),

View File

@ -118,12 +118,12 @@ func (suite *KeeperTestSuite) TestGetTimestampAtHeight() {
tc.malleate()
actualTimestamp, err := suite.chainA.App.IBCKeeper.ConnectionKeeper.GetTimestampAtHeight(
suite.chainA.GetContext(), connection, uint64(suite.chainB.LastHeader.Height),
suite.chainA.GetContext(), connection, uint64(suite.chainB.LastHeader.GetHeight()),
)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().EqualValues(uint64(suite.chainB.LastHeader.Time.UnixNano()), actualTimestamp)
suite.Require().EqualValues(uint64(suite.chainB.LastHeader.GetTime().UnixNano()), actualTimestamp)
} else {
suite.Require().Error(err)
}

View File

@ -106,7 +106,7 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
// name: "successful verification",
// clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
// consensusState: ibctmtypes.ConsensusState{
// Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
// Root: commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()),
// },
// prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
// expPass: true,
@ -115,7 +115,7 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
name: "ApplyPrefix failed",
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
consensusState: ibctmtypes.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
Root: commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()),
},
prefix: commitmenttypes.MerklePrefix{},
expPass: false,
@ -124,7 +124,7 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
name: "latest client height < height",
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
consensusState: ibctmtypes.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
Root: commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()),
},
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
expPass: false,
@ -133,7 +133,7 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
name: "client is frozen",
clientState: &ibctmtypes.ClientState{LatestHeight: height, FrozenHeight: height - 1},
consensusState: ibctmtypes.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
Root: commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()),
},
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),
expPass: false,
@ -142,7 +142,7 @@ func (suite *TendermintTestSuite) TestVerifyClientConsensusState() {
name: "proof verification failed",
clientState: ibctmtypes.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
consensusState: ibctmtypes.ConsensusState{
Root: commitmenttypes.NewMerkleRoot(suite.header.AppHash),
Root: commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()),
NextValidatorsHash: suite.valsHash,
},
prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")),

View File

@ -8,6 +8,7 @@ import (
"github.com/tendermint/tendermint/crypto/tmhash"
tmbytes "github.com/tendermint/tendermint/libs/bytes"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmtypes "github.com/tendermint/tendermint/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
@ -72,14 +73,14 @@ func (ev Evidence) Hash() tmbytes.HexBytes {
//
// NOTE: assumes that evidence headers have the same height
func (ev Evidence) GetHeight() int64 {
return int64(math.Min(float64(ev.Header1.Height), float64(ev.Header2.Height)))
return int64(math.Min(float64(ev.Header1.GetHeight()), float64(ev.Header2.GetHeight())))
}
// GetTime returns the timestamp at which misbehaviour occurred. It uses the
// maximum value from both headers to prevent producing an invalid header outside
// of the evidence age range.
func (ev Evidence) GetTime() time.Time {
minTime := int64(math.Max(float64(ev.Header1.Time.UnixNano()), float64(ev.Header2.Time.UnixNano())))
minTime := int64(math.Max(float64(ev.Header1.GetTime().UnixNano()), float64(ev.Header2.GetTime().UnixNano())))
return time.Unix(0, minTime)
}
@ -116,12 +117,22 @@ func (ev Evidence) ValidateBasic() error {
)
}
// Ensure that Heights are the same
if ev.Header1.Height != ev.Header2.Height {
return sdkerrors.Wrapf(clienttypes.ErrInvalidEvidence, "headers in evidence are on different heights (%d ≠ %d)", ev.Header1.Height, ev.Header2.Height)
if ev.Header1.GetHeight() != ev.Header2.GetHeight() {
return sdkerrors.Wrapf(clienttypes.ErrInvalidEvidence, "headers in evidence are on different heights (%d ≠ %d)", ev.Header1.GetHeight(), ev.Header2.GetHeight())
}
blockID1, err := tmtypes.BlockIDFromProto(&ev.Header1.SignedHeader.Commit.BlockID)
if err != nil {
return sdkerrors.Wrap(err, "invalid block ID from header 1 in evidence")
}
blockID2, err := tmtypes.BlockIDFromProto(&ev.Header2.SignedHeader.Commit.BlockID)
if err != nil {
return sdkerrors.Wrap(err, "invalid block ID from header 2 in evidence")
}
// Ensure that Commit Hashes are different
if ev.Header1.Commit.BlockID.Equals(ev.Header2.Commit.BlockID) {
return sdkerrors.Wrap(clienttypes.ErrInvalidEvidence, "headers commit to same blockID")
if blockID1.Equals(*blockID2) {
return sdkerrors.Wrap(clienttypes.ErrInvalidEvidence, "headers blockIDs are not equal")
}
if err := ValidCommit(ev.ChainID, ev.Header1.Commit, ev.Header1.ValidatorSet); err != nil {
return err
@ -137,21 +148,30 @@ func (ev Evidence) ValidateBasic() error {
// CommitToVoteSet will panic if the commit cannot be converted to a valid voteset given the validatorset
// This implies that someone tried to submit evidence that wasn't actually committed by the validatorset
// thus we should return an error here and reject the evidence rather than panicing.
func ValidCommit(chainID string, commit *tmtypes.Commit, valSet *tmtypes.ValidatorSet) (err error) {
func ValidCommit(chainID string, commit *tmproto.Commit, valSet *tmproto.ValidatorSet) (err error) {
defer func() {
if r := recover(); r != nil {
err = sdkerrors.Wrapf(clienttypes.ErrInvalidEvidence, "invalid commit: %v", r)
}
}()
tmCommit, err := tmtypes.CommitFromProto(commit)
if err != nil {
return sdkerrors.Wrap(err, "commit is not tendermint commit type")
}
tmValset, err := tmtypes.ValidatorSetFromProto(valSet)
if err != nil {
return sdkerrors.Wrap(err, "validator set is not tendermint validator set type")
}
// Convert commits to vote-sets given the validator set so we can check if they both have 2/3 power
voteSet := tmtypes.CommitToVoteSet(chainID, commit, valSet)
voteSet := tmtypes.CommitToVoteSet(chainID, tmCommit, tmValset)
blockID, ok := voteSet.TwoThirdsMajority()
// Check that ValidatorSet did indeed commit to blockID in Commit
if !ok || !blockID.Equals(commit.BlockID) {
return sdkerrors.Wrap(clienttypes.ErrInvalidEvidence, "validator set did not commit to header 1")
if !ok || !blockID.Equals(tmCommit.BlockID) {
return sdkerrors.Wrap(clienttypes.ErrInvalidEvidence, "validator set did not commit to header")
}
return nil

View File

@ -4,7 +4,6 @@ import (
"time"
"github.com/tendermint/tendermint/crypto/tmhash"
tmbytes "github.com/tendermint/tendermint/libs/bytes"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmtypes "github.com/tendermint/tendermint/types"
@ -27,7 +26,8 @@ func (suite *TendermintTestSuite) TestEvidence() {
suite.Require().Equal(ev.GetClientID(), clientID)
suite.Require().Equal(ev.Route(), "client")
suite.Require().Equal(ev.Type(), "client_misbehaviour")
suite.Require().Equal(ev.Hash(), tmbytes.HexBytes(tmhash.Sum(suite.aminoCdc.MustMarshalBinaryBare(ev))))
// uncomment when evidence is migrated to proto
// suite.Require().Equal(ev.Hash(), tmbytes.HexBytes(tmhash.Sum(suite.aminoCdc.MustMarshalBinaryBare(ev))))
suite.Require().Equal(ev.GetHeight(), int64(height))
}
@ -188,9 +188,14 @@ func (suite *TendermintTestSuite) TestEvidenceValidateBasic() {
},
func(ev *ibctmtypes.Evidence) error {
// voteSet contains only altVal which is less than 2/3 of total power (height/1height)
wrongVoteSet := tmtypes.NewVoteSet(chainID, ev.Header1.Height, 1, tmproto.PrecommitType, altValSet)
var err error
ev.Header1.Commit, err = tmtypes.MakeCommit(ev.Header1.Commit.BlockID, ev.Header2.Height, ev.Header1.Commit.Round, wrongVoteSet, altSigners, suite.now)
wrongVoteSet := tmtypes.NewVoteSet(chainID, int64(ev.Header1.GetHeight()), 1, tmproto.PrecommitType, altValSet)
blockID, err := tmtypes.BlockIDFromProto(&ev.Header1.Commit.BlockID)
if err != nil {
return err
}
tmCommit, err := tmtypes.MakeCommit(*blockID, int64(ev.Header2.GetHeight()), ev.Header1.Commit.Round, wrongVoteSet, altSigners, suite.now)
ev.Header1.Commit = tmCommit.ToProto()
return err
},
false,
@ -205,9 +210,14 @@ func (suite *TendermintTestSuite) TestEvidenceValidateBasic() {
},
func(ev *ibctmtypes.Evidence) error {
// voteSet contains only altVal which is less than 2/3 of total power (height/1height)
wrongVoteSet := tmtypes.NewVoteSet(chainID, ev.Header2.Height, 1, tmproto.PrecommitType, altValSet)
var err error
ev.Header2.Commit, err = tmtypes.MakeCommit(ev.Header2.Commit.BlockID, ev.Header2.Height, ev.Header2.Commit.Round, wrongVoteSet, altSigners, suite.now)
wrongVoteSet := tmtypes.NewVoteSet(chainID, int64(ev.Header2.GetHeight()), 1, tmproto.PrecommitType, altValSet)
blockID, err := tmtypes.BlockIDFromProto(&ev.Header2.Commit.BlockID)
if err != nil {
return err
}
tmCommit, err := tmtypes.MakeCommit(*blockID, int64(ev.Header2.GetHeight()), ev.Header2.Commit.Round, wrongVoteSet, altSigners, suite.now)
ev.Header2.Commit = tmCommit.ToProto()
return err
},
false,
@ -221,7 +231,8 @@ func (suite *TendermintTestSuite) TestEvidenceValidateBasic() {
ClientID: clientID,
},
func(ev *ibctmtypes.Evidence) error {
ev.Header2.Commit.BlockID = ibctmtypes.MakeBlockID(tmhash.Sum([]byte("other_hash")), 3, tmhash.Sum([]byte("other_partset")))
tmBlockID := ibctmtypes.MakeBlockID(tmhash.Sum([]byte("other_hash")), 3, tmhash.Sum([]byte("other_partset")))
ev.Header2.Commit.BlockID = tmBlockID.ToProto()
return nil
},
false,

View File

@ -2,6 +2,7 @@ package types
import (
"bytes"
"time"
tmtypes "github.com/tendermint/tendermint/types"
@ -13,22 +14,6 @@ import (
var _ clientexported.Header = Header{}
// Header defines the Tendermint client consensus Header.
// It encapsulates all the information necessary to update from a trusted Tendermint ConsensusState.
// The inclusion of TrustedHeight and TrustedValidators allows this update to process correctly, so long
// as the ConsensusState for the TrustedHeight exists, this removes race conditions among relayers
// The SignedHeader and ValidatorSet are the new untrusted update fields for the client.
// The TrustedHeight is the height of a stored ConsensusState on the client that will be used to verify the new untrusted header.
// The Trusted ConsensusState must be within the unbonding period of current time in order to correctly verify,
// and the TrustedValidators must hash to TrustedConsensusState.NextValidatorsHash since that is the last trusted validator set
// at the TrustedHeight.
type Header struct {
tmtypes.SignedHeader `json:"signed_header" yaml:"signed_header"` // contains the commitment root
ValidatorSet *tmtypes.ValidatorSet `json:"validator_set" yaml:"validator_set"` // the validator set that signed Header
TrustedHeight uint64 `json:"trusted_height" yaml:"trusted_height"` // the height of a trusted header seen by client less than or equal to Header
TrustedValidators *tmtypes.ValidatorSet `json:"trusted_vals" yaml:"trusted_vals"` // the last trusted validator set at trusted height
}
// ClientType defines that the Header is a Tendermint consensus algorithm
func (h Header) ClientType() clientexported.ClientType {
return clientexported.Tendermint
@ -37,38 +22,65 @@ func (h Header) ClientType() clientexported.ClientType {
// ConsensusState returns the updated consensus state associated with the header
func (h Header) ConsensusState() *ConsensusState {
return &ConsensusState{
Height: uint64(h.Height),
Timestamp: h.Time,
Root: commitmenttypes.NewMerkleRoot(h.AppHash),
NextValidatorsHash: h.NextValidatorsHash,
Height: h.GetHeight(),
Timestamp: h.GetTime(),
Root: commitmenttypes.NewMerkleRoot(h.Header.GetAppHash()),
NextValidatorsHash: h.Header.NextValidatorsHash,
}
}
// GetHeight returns the current height
// GetHeight returns the current height. It returns 0 if the tendermint
// header is nil.
//
// NOTE: also referred as `sequence`
func (h Header) GetHeight() uint64 {
return uint64(h.Height)
if h.Header == nil {
return 0
}
return uint64(h.Header.Height)
}
// ValidateBasic calls the SignedHeader ValidateBasic function
// and checks that validatorsets are not nil
// GetTime returns the current block timestamp. It returns a zero time if
// the tendermint header is nil.
func (h Header) GetTime() time.Time {
if h.Header == nil {
return time.Time{}
}
return h.Header.Time
}
// ValidateBasic calls the SignedHeader ValidateBasic function and checks
// that validatorsets are not nil.
// NOTE: TrustedHeight and TrustedValidators may be empty when creating client
// with MsgCreateClient
func (h Header) ValidateBasic(chainID string) error {
if err := h.SignedHeader.ValidateBasic(chainID); err != nil {
if h.Header == nil {
return sdkerrors.Wrap(clienttypes.ErrInvalidHeader, "tendermint header cannot be nil")
}
tmSignedHeader, err := tmtypes.SignedHeaderFromProto(&h.SignedHeader)
if err != nil {
return sdkerrors.Wrap(err, "header is not a tendermint header")
}
if err := tmSignedHeader.ValidateBasic(chainID); err != nil {
return sdkerrors.Wrap(err, "header failed basic validation")
}
// TrustedHeight is less than Header for updates
// and less than or equal to Header for misbehaviour
if h.TrustedHeight > uint64(h.Height) {
if h.TrustedHeight > h.GetHeight() {
return sdkerrors.Wrapf(ErrInvalidHeaderHeight, "TrustedHeight %d must be less than or equal to header height %d",
h.TrustedHeight, h.Height)
h.TrustedHeight, h.GetHeight())
}
if h.ValidatorSet == nil {
return sdkerrors.Wrap(clienttypes.ErrInvalidHeader, "validator set is nil")
}
if !bytes.Equal(h.ValidatorsHash, h.ValidatorSet.Hash()) {
tmValset, err := tmtypes.ValidatorSetFromProto(h.ValidatorSet)
if err != nil {
return sdkerrors.Wrap(err, "validator set is not tendermint validator set")
}
if !bytes.Equal(h.Header.ValidatorsHash, tmValset.Hash()) {
return sdkerrors.Wrap(clienttypes.ErrInvalidHeader, "validator set does not match hash")
}
return nil

View File

@ -1,30 +1,76 @@
package types_test
import (
"time"
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
"github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
)
func (suite *TendermintTestSuite) TestGetHeight() {
header := suite.chainA.LastHeader
suite.Require().NotEqual(uint64(0), header.GetHeight())
header.Header = nil
suite.Require().Equal(uint64(0), header.GetHeight())
}
func (suite *TendermintTestSuite) TestGetTime() {
header := suite.chainA.LastHeader
suite.Require().NotEqual(time.Time{}, header.GetTime())
header.Header = nil
suite.Require().Equal(time.Time{}, header.GetTime())
}
func (suite *TendermintTestSuite) TestHeaderValidateBasic() {
testCases := []struct {
name string
header ibctmtypes.Header
var (
header types.Header
chainID string
expPass bool
)
testCases := []struct {
name string
malleate func()
expPass bool
}{
{"valid header", suite.header, chainID, true},
{"signed header basic validation failed", suite.header, "chainID", false},
{"validator set nil", ibctmtypes.Header{suite.header.SignedHeader, nil, 0, suite.valSet}, chainID, false},
{"valid header", func() {}, true},
{"signed header is nil", func() {
header.Header = nil
}, false},
{"signed header failed tendermint ValidateBasic", func() {
header = suite.chainA.LastHeader
chainID = "chainid"
}, false},
{"trusted height is greater than header height", func() {
header.TrustedHeight = header.GetHeight() + 1
}, false},
{"validator set nil", func() {
header.ValidatorSet = nil
}, false},
{"header validator hash does not equal hash of validator set", func() {
// use chainB's randomly generated validator set
header.ValidatorSet = suite.chainB.LastHeader.ValidatorSet
}, false},
}
suite.Require().Equal(clientexported.Tendermint, suite.header.ClientType())
for i, tc := range testCases {
for _, tc := range testCases {
tc := tc
if tc.expPass {
suite.Require().NoError(tc.header.ValidateBasic(tc.chainID), "valid test case %d failed: %s", i, tc.name)
} else {
suite.Require().Error(tc.header.ValidateBasic(tc.chainID), "invalid test case %d passed: %s", i, tc.name)
}
suite.Run(tc.name, func() {
chainID = suite.chainA.ChainID // must be explicitly changed in malleate
header = suite.chainA.LastHeader // must be explicitly changed in malleate
tc.malleate()
err := header.ValidateBasic(chainID)
if tc.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}

View File

@ -3,6 +3,8 @@ package types
import (
"time"
tmtypes "github.com/tendermint/tendermint/types"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
@ -103,6 +105,17 @@ func (cs ClientState) CheckMisbehaviourAndUpdateState(
func checkMisbehaviourHeader(
clientState *ClientState, consState *ConsensusState, header Header, currentTimestamp time.Time,
) error {
tmTrustedValset, err := tmtypes.ValidatorSetFromProto(header.TrustedValidators)
if err != nil {
return sdkerrors.Wrap(err, "trusted validator set is not tendermint validator set type")
}
tmCommit, err := tmtypes.CommitFromProto(header.Commit)
if err != nil {
return sdkerrors.Wrap(err, "commit is not tendermint commit type")
}
// check the trusted fields for the header against ConsensusState
if err := checkTrustedHeader(header, consState); err != nil {
return err
@ -119,8 +132,8 @@ func checkMisbehaviourHeader(
// - ValidatorSet must have 2/3 similarity with trusted FromValidatorSet
// - ValidatorSets on both headers are valid given the last trusted ValidatorSet
if err := header.TrustedValidators.VerifyCommitLightTrusting(
clientState.GetChainID(), header.Commit, clientState.TrustLevel.ToTendermint(),
if err := tmTrustedValset.VerifyCommitLightTrusting(
clientState.GetChainID(), tmCommit, clientState.TrustLevel.ToTendermint(),
); err != nil {
return sdkerrors.Wrapf(clienttypes.ErrInvalidEvidence, "validator set in header has too much change from trusted validator set: %v", err)
}

View File

@ -95,7 +95,7 @@ func (msg MsgCreateClient) ValidateBasic() error {
return sdkerrors.Wrap(ErrInvalidHeader, "header cannot be nil")
}
// ValidateBasic of provided header with self-attested chain-id
if err := msg.Header.ValidateBasic(msg.Header.ChainID); err != nil {
if err := msg.Header.ValidateBasic(msg.Header.Header.GetChainID()); err != nil {
return sdkerrors.Wrapf(ErrInvalidHeader, "header failed validatebasic with its own chain-id: %v", err)
}
if msg.TrustingPeriod >= msg.UnbondingPeriod {
@ -139,20 +139,20 @@ func (msg MsgCreateClient) GetClientType() string {
// GetConsensusState implements clientexported.MsgCreateClient
func (msg MsgCreateClient) GetConsensusState() clientexported.ConsensusState {
// Construct initial consensus state from provided Header
root := commitmenttypes.NewMerkleRoot(msg.Header.AppHash)
root := commitmenttypes.NewMerkleRoot(msg.Header.Header.GetAppHash())
return &ConsensusState{
Timestamp: msg.Header.Time,
Timestamp: msg.Header.GetTime(),
Root: root,
Height: uint64(msg.Header.Height),
NextValidatorsHash: msg.Header.NextValidatorsHash,
Height: msg.Header.GetHeight(),
NextValidatorsHash: msg.Header.Header.NextValidatorsHash,
}
}
// InitializeFromMsg creates a tendermint client state from a CreateClientMsg
func (msg MsgCreateClient) InitializeClientState() clientexported.ClientState {
return NewClientState(msg.Header.ChainID, msg.TrustLevel,
return NewClientState(msg.Header.Header.GetChainID(), msg.TrustLevel,
msg.TrustingPeriod, msg.UnbondingPeriod, msg.MaxClockDrift,
uint64(msg.Header.Height), msg.ProofSpecs,
msg.Header.GetHeight(), msg.ProofSpecs,
)
}

View File

@ -14,7 +14,7 @@ import (
func (suite *TendermintTestSuite) TestMsgCreateClientValidateBasic() {
privKey := secp256k1.GenPrivKey()
signer := sdk.AccAddress(privKey.PubKey().Address())
invalidHeader := types.CreateTestHeader(suite.header.ChainID, height, 0, suite.now, suite.valSet, nil, []tmtypes.PrivValidator{suite.privVal})
invalidHeader := types.CreateTestHeader(suite.header.Header.GetChainID(), height, 0, suite.now, suite.valSet, nil, []tmtypes.PrivValidator{suite.privVal})
invalidHeader.ValidatorSet = nil
cases := []struct {

View File

@ -13,6 +13,7 @@ import (
_ "github.com/golang/protobuf/ptypes/duration"
_ "github.com/golang/protobuf/ptypes/timestamp"
github_com_tendermint_tendermint_libs_bytes "github.com/tendermint/tendermint/libs/bytes"
types1 "github.com/tendermint/tendermint/proto/tendermint/types"
io "io"
math "math"
math_bits "math/bits"
@ -129,6 +130,79 @@ func (m *ConsensusState) XXX_DiscardUnknown() {
var xxx_messageInfo_ConsensusState proto.InternalMessageInfo
// Header defines the Tendermint client consensus Header.
// It encapsulates all the information necessary to update from a trusted
// Tendermint ConsensusState. The inclusion of TrustedHeight and
// TrustedValidators allows this update to process correctly, so long as the
// ConsensusState for the TrustedHeight exists, this removes race conditions
// among relayers The SignedHeader and ValidatorSet are the new untrusted update
// fields for the client. The TrustedHeight is the height of a stored
// ConsensusState on the client that will be used to verify the new untrusted
// header. The Trusted ConsensusState must be within the unbonding period of
// current time in order to correctly verify, and the TrustedValidators must
// hash to TrustedConsensusState.NextValidatorsHash since that is the last
// trusted validator set at the TrustedHeight.
type Header struct {
types1.SignedHeader `protobuf:"bytes,1,opt,name=signed_header,json=signedHeader,proto3,embedded=signed_header" json:"signed_header" yaml:"signed_header"`
ValidatorSet *types1.ValidatorSet `protobuf:"bytes,2,opt,name=validator_set,json=validatorSet,proto3" json:"validator_set,omitempty" yaml:"validator_set"`
TrustedHeight uint64 `protobuf:"varint,3,opt,name=trusted_height,json=trustedHeight,proto3" json:"trusted_height,omitempty" yaml:"trusted_height"`
TrustedValidators *types1.ValidatorSet `protobuf:"bytes,4,opt,name=trusted_validators,json=trustedValidators,proto3" json:"trusted_validators,omitempty" yaml:"trusted_validators"`
}
func (m *Header) Reset() { *m = Header{} }
func (m *Header) String() string { return proto.CompactTextString(m) }
func (*Header) ProtoMessage() {}
func (*Header) Descriptor() ([]byte, []int) {
return fileDescriptor_76a953d5a747dd66, []int{2}
}
func (m *Header) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *Header) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_Header.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *Header) XXX_Merge(src proto.Message) {
xxx_messageInfo_Header.Merge(m, src)
}
func (m *Header) XXX_Size() int {
return m.Size()
}
func (m *Header) XXX_DiscardUnknown() {
xxx_messageInfo_Header.DiscardUnknown(m)
}
var xxx_messageInfo_Header proto.InternalMessageInfo
func (m *Header) GetValidatorSet() *types1.ValidatorSet {
if m != nil {
return m.ValidatorSet
}
return nil
}
func (m *Header) GetTrustedHeight() uint64 {
if m != nil {
return m.TrustedHeight
}
return 0
}
func (m *Header) GetTrustedValidators() *types1.ValidatorSet {
if m != nil {
return m.TrustedValidators
}
return nil
}
// Fraction defines the protobuf message type for tmmath.Fraction
type Fraction struct {
Numerator int64 `protobuf:"varint,1,opt,name=numerator,proto3" json:"numerator,omitempty"`
@ -139,7 +213,7 @@ func (m *Fraction) Reset() { *m = Fraction{} }
func (m *Fraction) String() string { return proto.CompactTextString(m) }
func (*Fraction) ProtoMessage() {}
func (*Fraction) Descriptor() ([]byte, []int) {
return fileDescriptor_76a953d5a747dd66, []int{2}
return fileDescriptor_76a953d5a747dd66, []int{3}
}
func (m *Fraction) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -185,57 +259,67 @@ func (m *Fraction) GetDenominator() int64 {
func init() {
proto.RegisterType((*ClientState)(nil), "ibc.tendermint.ClientState")
proto.RegisterType((*ConsensusState)(nil), "ibc.tendermint.ConsensusState")
proto.RegisterType((*Header)(nil), "ibc.tendermint.Header")
proto.RegisterType((*Fraction)(nil), "ibc.tendermint.Fraction")
}
func init() { proto.RegisterFile("ibc/tendermint/tendermint.proto", fileDescriptor_76a953d5a747dd66) }
var fileDescriptor_76a953d5a747dd66 = []byte{
// 698 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0xcd, 0x4e, 0xdb, 0x4c,
0x14, 0x8d, 0x21, 0x40, 0x18, 0xf3, 0x27, 0x7f, 0x88, 0xcf, 0xa4, 0x95, 0x1d, 0xb9, 0x9b, 0x6c,
0xb0, 0xab, 0x80, 0x5a, 0x09, 0xa9, 0x1b, 0x83, 0x2a, 0xa8, 0x5a, 0x09, 0x99, 0xfe, 0x48, 0xdd,
0x58, 0xfe, 0x99, 0xd8, 0x23, 0xec, 0x19, 0xcb, 0x33, 0x46, 0xa1, 0x4f, 0x40, 0x77, 0x2c, 0xbb,
0xec, 0x43, 0xf4, 0x21, 0x58, 0xb2, 0xec, 0x2a, 0xad, 0xe0, 0x0d, 0x58, 0x76, 0x55, 0xcd, 0xd8,
0x26, 0x26, 0x45, 0xaa, 0xba, 0xca, 0xdc, 0x73, 0xcf, 0xb9, 0x77, 0xee, 0xcd, 0xf1, 0x00, 0x1d,
0xf9, 0x81, 0xc5, 0x20, 0x0e, 0x61, 0x9e, 0x22, 0xcc, 0x1a, 0x47, 0x33, 0xcb, 0x09, 0x23, 0xca,
0x0a, 0xf2, 0x03, 0x73, 0x82, 0x76, 0xff, 0x0b, 0x08, 0x1e, 0x22, 0x62, 0x65, 0x39, 0x21, 0x43,
0x5a, 0x92, 0xba, 0x5a, 0x44, 0x48, 0x94, 0x40, 0x4b, 0x44, 0x7e, 0x31, 0xb4, 0xc2, 0x22, 0xf7,
0x18, 0x22, 0xb8, 0xca, 0xeb, 0xd3, 0x79, 0x86, 0x52, 0x48, 0x99, 0x97, 0x66, 0x35, 0x81, 0x5f,
0x23, 0x20, 0x69, 0x8a, 0x58, 0x0a, 0x31, 0x6b, 0x1c, 0x2b, 0xc2, 0x7a, 0x44, 0x22, 0x22, 0x8e,
0x16, 0x3f, 0x95, 0xa8, 0x71, 0x3e, 0x07, 0xe4, 0xbd, 0x04, 0x41, 0xcc, 0x8e, 0x99, 0xc7, 0xa0,
0xb2, 0x09, 0x3a, 0x41, 0xec, 0x21, 0xec, 0xa2, 0x50, 0x95, 0x7a, 0x52, 0x7f, 0xd1, 0x59, 0x10,
0xf1, 0x61, 0xa8, 0xbc, 0x03, 0x32, 0xcb, 0x0b, 0xca, 0xdc, 0x04, 0x9e, 0xc2, 0x44, 0x9d, 0xe9,
0x49, 0x7d, 0x79, 0xa0, 0x9a, 0xf7, 0xa7, 0x33, 0x5f, 0xe6, 0x5e, 0xc0, 0xef, 0x6d, 0x77, 0x2f,
0xc7, 0x7a, 0xeb, 0x76, 0xac, 0x2b, 0x67, 0x5e, 0x9a, 0xec, 0x1a, 0x0d, 0xa9, 0xe1, 0x00, 0x11,
0xbd, 0xe6, 0x81, 0x32, 0x04, 0xab, 0x22, 0x42, 0x38, 0x72, 0x33, 0x98, 0x23, 0x12, 0xaa, 0xb3,
0xa2, 0xf4, 0xa6, 0x59, 0xce, 0x6c, 0xd6, 0x33, 0x9b, 0xfb, 0xd5, 0x4e, 0x6c, 0xa3, 0xaa, 0xbd,
0xd1, 0xa8, 0x3d, 0xd1, 0x1b, 0x5f, 0x7e, 0xe8, 0x92, 0xb3, 0x52, 0xa3, 0x47, 0x02, 0x54, 0x10,
0x58, 0x2b, 0xb0, 0x4f, 0x70, 0xd8, 0x68, 0xd4, 0xfe, 0x5b, 0xa3, 0x27, 0x55, 0xa3, 0xff, 0xcb,
0x46, 0xd3, 0x05, 0xca, 0x4e, 0xab, 0x77, 0x70, 0xd5, 0x0a, 0x82, 0xd5, 0xd4, 0x1b, 0xb9, 0x41,
0x42, 0x82, 0x13, 0x37, 0xcc, 0xd1, 0x90, 0xa9, 0x73, 0xff, 0x38, 0xd2, 0x94, 0xbe, 0x6c, 0xb4,
0x9c, 0x7a, 0xa3, 0x3d, 0x0e, 0xee, 0x73, 0x4c, 0x79, 0x01, 0x96, 0x87, 0x39, 0xf9, 0x04, 0xb1,
0x1b, 0x43, 0x14, 0xc5, 0x4c, 0x9d, 0xef, 0x49, 0xfd, 0xb6, 0xad, 0xde, 0x8e, 0xf5, 0xf5, 0xb2,
0xca, 0xbd, 0xb4, 0xe1, 0x2c, 0x95, 0xf1, 0x81, 0x08, 0xb9, 0x3c, 0xf1, 0x18, 0xa4, 0xac, 0x96,
0x2f, 0x4c, 0xcb, 0xef, 0xa5, 0x0d, 0x67, 0xa9, 0x8c, 0x2b, 0xf9, 0x21, 0x90, 0x85, 0x83, 0x5d,
0x9a, 0xc1, 0x80, 0xaa, 0x9d, 0xde, 0x6c, 0x5f, 0x1e, 0xac, 0x99, 0x28, 0xa0, 0x83, 0x6d, 0xf3,
0x88, 0x67, 0x8e, 0x33, 0x18, 0xd8, 0x1b, 0x13, 0x0b, 0x34, 0xe8, 0x86, 0x03, 0xb2, 0x9a, 0x42,
0x77, 0xdb, 0xe7, 0x5f, 0xf5, 0x96, 0xf1, 0x6d, 0x06, 0xac, 0xec, 0x11, 0x4c, 0x21, 0xa6, 0x05,
0x2d, 0xdd, 0x68, 0x83, 0xc5, 0x3b, 0x9f, 0x0b, 0x3b, 0xca, 0x83, 0xee, 0x1f, 0x2b, 0x7c, 0x5b,
0x33, 0xec, 0x0e, 0xdf, 0xe1, 0x05, 0xdf, 0xd4, 0x44, 0xa6, 0xec, 0x80, 0x76, 0x4e, 0x08, 0xab,
0xfc, 0xda, 0x15, 0x7e, 0x6d, 0x7c, 0x1c, 0x6f, 0x60, 0x7e, 0x92, 0x40, 0x87, 0x10, 0x66, 0xb7,
0xb9, 0xdc, 0x11, 0x6c, 0x65, 0x03, 0xcc, 0x57, 0x5b, 0xe1, 0x66, 0x6c, 0x3b, 0x55, 0xa4, 0x7c,
0x96, 0xc0, 0x3a, 0x86, 0x23, 0xe6, 0x9e, 0x7a, 0x09, 0x0a, 0x3d, 0x46, 0x72, 0xea, 0xc6, 0x1e,
0x8d, 0x85, 0x95, 0x96, 0xec, 0x0f, 0xb7, 0x63, 0xfd, 0x51, 0x39, 0xed, 0x43, 0x2c, 0xe3, 0xd7,
0x58, 0xdf, 0x89, 0x10, 0x8b, 0x0b, 0x9f, 0xdf, 0xe1, 0xe1, 0x67, 0xc3, 0x4a, 0x90, 0x4f, 0x2d,
0xff, 0x8c, 0x41, 0x6a, 0x1e, 0xc0, 0x91, 0xcd, 0x0f, 0x8e, 0xc2, 0xcb, 0xbd, 0xbf, 0xab, 0x76,
0xe0, 0xd1, 0xb8, 0x5a, 0xdb, 0x2b, 0xd0, 0xa9, 0xbf, 0x39, 0xe5, 0x31, 0x58, 0xc4, 0x45, 0x0a,
0x73, 0xce, 0x11, 0xfb, 0x9a, 0x75, 0x26, 0x80, 0xd2, 0x03, 0x72, 0x08, 0x31, 0x49, 0x11, 0x16,
0xf9, 0x19, 0x91, 0x6f, 0x42, 0xf6, 0xd1, 0xe5, 0xb5, 0x26, 0x5d, 0x5d, 0x6b, 0xd2, 0xcf, 0x6b,
0x4d, 0xba, 0xb8, 0xd1, 0x5a, 0x57, 0x37, 0x5a, 0xeb, 0xfb, 0x8d, 0xd6, 0xfa, 0xf8, 0xac, 0x71,
0xeb, 0x80, 0xd0, 0x94, 0xd0, 0xea, 0x67, 0x8b, 0x86, 0x27, 0xd6, 0xc8, 0xe2, 0xaf, 0xcf, 0xd3,
0xe7, 0x5b, 0xcd, 0x81, 0xce, 0x32, 0x48, 0xfd, 0x79, 0xf1, 0x37, 0x6d, 0xff, 0x0e, 0x00, 0x00,
0xff, 0xff, 0x07, 0xd7, 0x7b, 0xa7, 0x26, 0x05, 0x00, 0x00,
// 845 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x55, 0xcd, 0x6e, 0xe4, 0x44,
0x10, 0x1e, 0x27, 0xb3, 0xd9, 0xa4, 0x67, 0x26, 0x59, 0x9a, 0x10, 0x9c, 0x61, 0xb1, 0x47, 0xe6,
0x92, 0xcb, 0xda, 0x28, 0xbb, 0x02, 0x69, 0x25, 0x24, 0xe4, 0xac, 0x50, 0x16, 0x81, 0x14, 0x79,
0xf8, 0x91, 0x90, 0x90, 0xe5, 0x9f, 0x1e, 0xbb, 0x15, 0xbb, 0xdb, 0x72, 0xf7, 0x44, 0x13, 0x9e,
0x60, 0xb9, 0xed, 0x91, 0x23, 0x0f, 0xc1, 0x43, 0xec, 0x31, 0x47, 0x4e, 0x06, 0x25, 0x6f, 0x30,
0x47, 0x0e, 0x08, 0x75, 0xbb, 0x3d, 0xf6, 0xcc, 0x46, 0x5a, 0x71, 0x49, 0xba, 0xbe, 0xfa, 0xaa,
0xca, 0x55, 0xfd, 0x55, 0x0f, 0x30, 0x71, 0x18, 0x39, 0x1c, 0x91, 0x18, 0x95, 0x39, 0x26, 0xbc,
0x73, 0xb4, 0x8b, 0x92, 0x72, 0x0a, 0xf7, 0x71, 0x18, 0xd9, 0x2d, 0x3a, 0x9e, 0x74, 0xc9, 0xd7,
0x05, 0x62, 0xce, 0x55, 0x90, 0xe1, 0x38, 0xe0, 0xb4, 0xac, 0x23, 0xc6, 0x8f, 0xdf, 0x62, 0xc8,
0xbf, 0xca, 0xfb, 0x7e, 0x44, 0xc9, 0x0c, 0x53, 0xa7, 0x28, 0x29, 0x9d, 0x35, 0xa0, 0x91, 0x50,
0x9a, 0x64, 0xc8, 0x91, 0x56, 0x38, 0x9f, 0x39, 0xf1, 0xbc, 0x0c, 0x38, 0xa6, 0x44, 0xf9, 0xcd,
0x4d, 0x3f, 0xc7, 0x39, 0x62, 0x3c, 0xc8, 0x8b, 0x86, 0x20, 0xda, 0x88, 0x68, 0x9e, 0x63, 0x9e,
0x23, 0xc2, 0x3b, 0x47, 0x45, 0x38, 0x4c, 0x68, 0x42, 0xe5, 0xd1, 0x11, 0xa7, 0x1a, 0xb5, 0x5e,
0x3d, 0x00, 0x83, 0xb3, 0x0c, 0x23, 0xc2, 0xa7, 0x3c, 0xe0, 0x08, 0x1e, 0x83, 0xdd, 0x28, 0x0d,
0x30, 0xf1, 0x71, 0xac, 0x6b, 0x13, 0xed, 0x64, 0xcf, 0x7b, 0x28, 0xed, 0x97, 0x31, 0xfc, 0x1e,
0x0c, 0x78, 0x39, 0x67, 0xdc, 0xcf, 0xd0, 0x15, 0xca, 0xf4, 0xad, 0x89, 0x76, 0x32, 0x38, 0xd5,
0xed, 0xf5, 0xe9, 0xd8, 0x5f, 0x95, 0x41, 0x24, 0xbe, 0xdb, 0x1d, 0xbf, 0xa9, 0xcc, 0xde, 0xb2,
0x32, 0xe1, 0x75, 0x90, 0x67, 0xcf, 0xad, 0x4e, 0xa8, 0xe5, 0x01, 0x69, 0x7d, 0x23, 0x0c, 0x38,
0x03, 0x07, 0xd2, 0xc2, 0x24, 0xf1, 0x0b, 0x54, 0x62, 0x1a, 0xeb, 0xdb, 0x32, 0xf5, 0xb1, 0x5d,
0xf7, 0x6c, 0x37, 0x3d, 0xdb, 0x2f, 0xd4, 0x4c, 0x5c, 0x4b, 0xe5, 0x3e, 0xea, 0xe4, 0x6e, 0xe3,
0xad, 0xdf, 0xfe, 0x32, 0x35, 0x6f, 0xbf, 0x41, 0x2f, 0x24, 0x08, 0x31, 0x78, 0x34, 0x27, 0x21,
0x25, 0x71, 0xa7, 0x50, 0xff, 0x5d, 0x85, 0x3e, 0x51, 0x85, 0x3e, 0xac, 0x0b, 0x6d, 0x26, 0xa8,
0x2b, 0x1d, 0xac, 0x60, 0x55, 0x0a, 0x81, 0x83, 0x3c, 0x58, 0xf8, 0x51, 0x46, 0xa3, 0x4b, 0x3f,
0x2e, 0xf1, 0x8c, 0xeb, 0x0f, 0xfe, 0x67, 0x4b, 0x1b, 0xf1, 0x75, 0xa1, 0x51, 0x1e, 0x2c, 0xce,
0x04, 0xf8, 0x42, 0x60, 0xf0, 0x0b, 0x30, 0x9a, 0x95, 0xf4, 0x17, 0x44, 0xfc, 0x14, 0xe1, 0x24,
0xe5, 0xfa, 0xce, 0x44, 0x3b, 0xe9, 0xbb, 0xfa, 0xb2, 0x32, 0x0f, 0xeb, 0x2c, 0x6b, 0x6e, 0xcb,
0x1b, 0xd6, 0xf6, 0xb9, 0x34, 0x45, 0x78, 0x16, 0x70, 0xc4, 0x78, 0x13, 0xfe, 0x70, 0x33, 0x7c,
0xcd, 0x6d, 0x79, 0xc3, 0xda, 0x56, 0xe1, 0x2f, 0xc1, 0x40, 0x2a, 0xd8, 0x67, 0x05, 0x8a, 0x98,
0xbe, 0x3b, 0xd9, 0x3e, 0x19, 0x9c, 0x3e, 0xb2, 0x71, 0xc4, 0x4e, 0x9f, 0xda, 0x17, 0xc2, 0x33,
0x2d, 0x50, 0xe4, 0x1e, 0xb5, 0x12, 0xe8, 0xd0, 0x2d, 0x0f, 0x14, 0x0d, 0x85, 0x3d, 0xef, 0xbf,
0xfa, 0xdd, 0xec, 0x59, 0x7f, 0x6c, 0x81, 0xfd, 0x33, 0x4a, 0x18, 0x22, 0x6c, 0xce, 0x6a, 0x35,
0xba, 0x60, 0x6f, 0xa5, 0x73, 0x29, 0xc7, 0xc1, 0xe9, 0xf8, 0xad, 0x11, 0x7e, 0xd7, 0x30, 0xdc,
0x5d, 0x31, 0xc3, 0xd7, 0x62, 0x52, 0x6d, 0x18, 0x7c, 0x06, 0xfa, 0x25, 0xa5, 0x5c, 0xe9, 0x75,
0x2c, 0xf5, 0xda, 0x59, 0x8e, 0x6f, 0x51, 0x79, 0x99, 0x21, 0x8f, 0x52, 0xee, 0xf6, 0x45, 0xb8,
0x27, 0xd9, 0xf0, 0x08, 0xec, 0xa8, 0xa9, 0x08, 0x31, 0xf6, 0x3d, 0x65, 0xc1, 0x5f, 0x35, 0x70,
0x48, 0xd0, 0x82, 0xfb, 0xab, 0x9d, 0x67, 0x7e, 0x1a, 0xb0, 0x54, 0x4a, 0x69, 0xe8, 0xfe, 0xb8,
0xac, 0xcc, 0x8f, 0xea, 0x6e, 0xef, 0x63, 0x59, 0xff, 0x54, 0xe6, 0xb3, 0x04, 0xf3, 0x74, 0x1e,
0x8a, 0x6f, 0xb8, 0xff, 0xd9, 0x71, 0x32, 0x1c, 0x32, 0x27, 0xbc, 0xe6, 0x88, 0xd9, 0xe7, 0x68,
0xe1, 0x8a, 0x83, 0x07, 0x45, 0xba, 0x1f, 0x56, 0xd9, 0xce, 0x03, 0x96, 0xaa, 0xb1, 0xfd, 0xbb,
0x05, 0x76, 0xce, 0x51, 0x10, 0xa3, 0x12, 0x22, 0x30, 0x62, 0x38, 0x21, 0x28, 0xf6, 0x53, 0x09,
0xa8, 0x91, 0x19, 0xdd, 0xfd, 0xac, 0x5f, 0xa2, 0xa9, 0xa4, 0xd5, 0x61, 0xee, 0x44, 0xf4, 0x7d,
0x53, 0x99, 0x5a, 0x7b, 0xf3, 0x6b, 0x69, 0x2c, 0x6f, 0xc8, 0x3a, 0x7c, 0xf8, 0x33, 0x18, 0xad,
0xfa, 0xf2, 0x19, 0x6a, 0x46, 0x7b, 0x4f, 0x99, 0xd5, 0x07, 0x4f, 0x11, 0xef, 0x0a, 0x6b, 0x2d,
0xdc, 0xf2, 0x86, 0x57, 0x1d, 0x1e, 0xfc, 0x12, 0xd4, 0xab, 0x2b, 0xeb, 0xb7, 0x57, 0xe0, 0x1e,
0x2f, 0x2b, 0xf3, 0x83, 0xce, 0xc2, 0xaf, 0xfc, 0x96, 0x37, 0x52, 0x80, 0x92, 0x66, 0x06, 0x60,
0xc3, 0x68, 0x2f, 0x40, 0x2d, 0xfb, 0xbb, 0xbe, 0xf2, 0xe3, 0x65, 0x65, 0x1e, 0xaf, 0x57, 0x69,
0x73, 0x58, 0xde, 0x7b, 0x0a, 0x6c, 0xaf, 0xc2, 0xfa, 0x1a, 0xec, 0x36, 0x8f, 0x1e, 0x7c, 0x0c,
0xf6, 0xc8, 0x3c, 0x47, 0xa5, 0xf0, 0xc8, 0xe9, 0x6f, 0x7b, 0x2d, 0x00, 0x27, 0x60, 0x10, 0x23,
0x42, 0x73, 0x4c, 0xa4, 0x7f, 0x4b, 0xfa, 0xbb, 0x90, 0x7b, 0xf1, 0xe6, 0xd6, 0xd0, 0x6e, 0x6e,
0x0d, 0xed, 0xef, 0x5b, 0x43, 0x7b, 0x7d, 0x67, 0xf4, 0x6e, 0xee, 0x8c, 0xde, 0x9f, 0x77, 0x46,
0xef, 0xa7, 0xcf, 0x3a, 0xb2, 0x89, 0x28, 0xcb, 0x29, 0x53, 0xff, 0x9e, 0xb0, 0xf8, 0xd2, 0x59,
0x38, 0xe2, 0xf9, 0xff, 0xf4, 0xf3, 0x27, 0x9b, 0xbf, 0x3c, 0xe1, 0x8e, 0xdc, 0x93, 0xa7, 0xff,
0x05, 0x00, 0x00, 0xff, 0xff, 0xa1, 0x78, 0x14, 0xd9, 0xe7, 0x06, 0x00, 0x00,
}
func (m *ClientState) Marshal() (dAtA []byte, err error) {
@ -379,6 +463,68 @@ func (m *ConsensusState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil
}
func (m *Header) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *Header) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *Header) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.TrustedValidators != nil {
{
size, err := m.TrustedValidators.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintTendermint(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x22
}
if m.TrustedHeight != 0 {
i = encodeVarintTendermint(dAtA, i, uint64(m.TrustedHeight))
i--
dAtA[i] = 0x18
}
if m.ValidatorSet != nil {
{
size, err := m.ValidatorSet.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintTendermint(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x12
}
{
size, err := m.SignedHeader.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintTendermint(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0xa
return len(dAtA) - i, nil
}
func (m *Fraction) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
@ -476,6 +622,28 @@ func (m *ConsensusState) Size() (n int) {
return n
}
func (m *Header) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = m.SignedHeader.Size()
n += 1 + l + sovTendermint(uint64(l))
if m.ValidatorSet != nil {
l = m.ValidatorSet.Size()
n += 1 + l + sovTendermint(uint64(l))
}
if m.TrustedHeight != 0 {
n += 1 + sovTendermint(uint64(m.TrustedHeight))
}
if m.TrustedValidators != nil {
l = m.TrustedValidators.Size()
n += 1 + l + sovTendermint(uint64(l))
}
return n
}
func (m *Fraction) Size() (n int) {
if m == nil {
return 0
@ -958,6 +1126,183 @@ func (m *ConsensusState) Unmarshal(dAtA []byte) error {
}
return nil
}
func (m *Header) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTendermint
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Header: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Header: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field SignedHeader", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTendermint
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthTendermint
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthTendermint
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := m.SignedHeader.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ValidatorSet", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTendermint
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthTendermint
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthTendermint
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.ValidatorSet == nil {
m.ValidatorSet = &types1.ValidatorSet{}
}
if err := m.ValidatorSet.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field TrustedHeight", wireType)
}
m.TrustedHeight = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTendermint
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.TrustedHeight |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field TrustedValidators", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTendermint
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthTendermint
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthTendermint
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.TrustedValidators == nil {
m.TrustedValidators = &types1.ValidatorSet{}
}
if err := m.TrustedValidators.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipTendermint(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthTendermint
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthTendermint
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *Fraction) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0

View File

@ -10,7 +10,7 @@ import (
tmtypes "github.com/tendermint/tendermint/types"
)
// Copied unimported test functions from tmtypes to use them here
// MakeBlockID is a copied unimported test function from tmtypes to use here
func MakeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) tmtypes.BlockID {
return tmtypes.BlockID{
Hash: hash,
@ -22,8 +22,12 @@ func MakeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) tmtypes.Bl
}
// CreateTestHeader creates a mock header for testing only.
func CreateTestHeader(chainID string, height, trustedHeight int64, timestamp time.Time, valSet, trustedVals *tmtypes.ValidatorSet, signers []tmtypes.PrivValidator) Header {
vsetHash := valSet.Hash()
func CreateTestHeader(chainID string, height, trustedHeight int64, timestamp time.Time, tmValSet, tmTrustedVals *tmtypes.ValidatorSet, signers []tmtypes.PrivValidator) Header {
var (
valSet *tmproto.ValidatorSet
trustedVals *tmproto.ValidatorSet
)
vsetHash := tmValSet.Hash()
tmHeader := tmtypes.Header{
Version: version.Consensus{Block: 2, App: 2},
ChainID: chainID,
@ -38,20 +42,34 @@ func CreateTestHeader(chainID string, height, trustedHeight int64, timestamp tim
AppHash: tmhash.Sum([]byte("app_hash")),
LastResultsHash: tmhash.Sum([]byte("last_results_hash")),
EvidenceHash: tmhash.Sum([]byte("evidence_hash")),
ProposerAddress: valSet.Proposer.Address,
ProposerAddress: tmValSet.Proposer.Address,
}
hhash := tmHeader.Hash()
blockID := MakeBlockID(hhash, 3, tmhash.Sum([]byte("part_set")))
voteSet := tmtypes.NewVoteSet(chainID, height, 1, tmproto.PrecommitType, valSet)
voteSet := tmtypes.NewVoteSet(chainID, height, 1, tmproto.PrecommitType, tmValSet)
commit, err := tmtypes.MakeCommit(blockID, height, 1, voteSet, signers, timestamp)
if err != nil {
panic(err)
}
signedHeader := tmtypes.SignedHeader{
Header: &tmHeader,
Commit: commit,
signedHeader := tmproto.SignedHeader{
Header: tmHeader.ToProto(),
Commit: commit.ToProto(),
}
if tmValSet != nil {
valSet, err = tmValSet.ToProto()
if err != nil {
panic(err)
}
}
if tmTrustedVals != nil {
trustedVals, err = tmTrustedVals.ToProto()
if err != nil {
panic(err)
}
}
return Header{

View File

@ -70,9 +70,15 @@ func checkTrustedHeader(header Header, consState *ConsensusState) error {
header.TrustedHeight, consState.Height,
)
}
tmTrustedValidators, err := tmtypes.ValidatorSetFromProto(header.TrustedValidators)
if err != nil {
return sdkerrors.Wrap(err, "trusted validator set in not tendermint validator set type")
}
// assert that trustedVals is NextValidators of last trusted header
// to do this, we check that trustedVals.Hash() == consState.NextValidatorsHash
tvalHash := header.TrustedValidators.Hash()
tvalHash := tmTrustedValidators.Hash()
if !bytes.Equal(consState.NextValidatorsHash, tvalHash) {
return sdkerrors.Wrapf(
ErrInvalidValidatorSet,
@ -93,6 +99,21 @@ func checkValidity(
return err
}
tmTrustedValidators, err := tmtypes.ValidatorSetFromProto(header.TrustedValidators)
if err != nil {
return sdkerrors.Wrap(err, "trusted validator set in not tendermint validator set type")
}
tmSignedHeader, err := tmtypes.SignedHeaderFromProto(&header.SignedHeader)
if err != nil {
return sdkerrors.Wrap(err, "signed header in not tendermint signed header type")
}
tmValidatorSet, err := tmtypes.ValidatorSetFromProto(header.ValidatorSet)
if err != nil {
return sdkerrors.Wrap(err, "validator set in not tendermint validator set type")
}
// assert header height is newer than consensus state
if header.GetHeight() <= consState.Height {
return sdkerrors.Wrapf(
@ -117,9 +138,9 @@ func checkValidity(
// - assert header timestamp is not past the trusting period
// - assert header timestamp is past latest stored consensus state timestamp
// - assert that a TrustLevel proportion of TrustedValidators signed new Commit
err := light.Verify(
err = light.Verify(
clientState.GetChainID(), &signedHeader,
header.TrustedValidators, &header.SignedHeader, header.ValidatorSet,
tmTrustedValidators, tmSignedHeader, tmValidatorSet,
clientState.TrustingPeriod, currentTimestamp, clientState.MaxClockDrift, clientState.TrustLevel.ToTendermint(),
)
if err != nil {
@ -130,14 +151,14 @@ func checkValidity(
// update the consensus state from a new header
func update(clientState *ClientState, header Header) (*ClientState, *ConsensusState) {
if uint64(header.Height) > clientState.LatestHeight {
clientState.LatestHeight = uint64(header.Height)
if header.GetHeight() > clientState.LatestHeight {
clientState.LatestHeight = header.GetHeight()
}
consensusState := &ConsensusState{
Height: uint64(header.Height),
Timestamp: header.Time,
Root: commitmenttypes.NewMerkleRoot(header.AppHash),
NextValidatorsHash: header.NextValidatorsHash,
Height: header.GetHeight(),
Timestamp: header.GetTime(),
Root: commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()),
NextValidatorsHash: header.Header.NextValidatorsHash,
}
return clientState, consensusState

View File

@ -46,7 +46,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
name: "successful update with next height and same validator set",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.AppHash), height, suite.valsHash)
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), height, suite.valsHash)
newHeader = types.CreateTestHeader(chainID, height+1, height, suite.headerTime, suite.valSet, suite.valSet, signers)
currentTime = suite.now
},
@ -56,7 +56,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
name: "successful update with future height and different validator set",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.AppHash), height, suite.valsHash)
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), height, suite.valsHash)
newHeader = types.CreateTestHeader(chainID, height+5, height, suite.headerTime, bothValSet, suite.valSet, bothSigners)
currentTime = suite.now
},
@ -66,7 +66,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
name: "successful update with next height and different validator set",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.AppHash), height, bothValSet.Hash())
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), height, bothValSet.Hash())
newHeader = types.CreateTestHeader(chainID, height+1, height, suite.headerTime, bothValSet, bothValSet, bothSigners)
currentTime = suite.now
},
@ -76,7 +76,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
name: "successful update for a previous height",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.AppHash), height-3, suite.valsHash)
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), height-3, suite.valsHash)
newHeader = types.CreateTestHeader(chainID, height-1, height-3, suite.headerTime, bothValSet, suite.valSet, bothSigners)
currentTime = suite.now
},
@ -86,7 +86,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
name: "unsuccessful update with next height: update header mismatches nextValSetHash",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.AppHash), height, suite.valsHash)
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), height, suite.valsHash)
newHeader = types.CreateTestHeader(chainID, height+1, height, suite.headerTime, bothValSet, suite.valSet, bothSigners)
currentTime = suite.now
},
@ -96,7 +96,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
name: "unsuccessful update with next height: update header mismatches different nextValSetHash",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.AppHash), height, bothValSet.Hash())
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), height, bothValSet.Hash())
newHeader = types.CreateTestHeader(chainID, height+1, height, suite.headerTime, suite.valSet, bothValSet, signers)
currentTime = suite.now
},
@ -106,7 +106,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
name: "unsuccessful update with future height: too much change in validator set",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.AppHash), height, suite.valsHash)
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), height, suite.valsHash)
newHeader = types.CreateTestHeader(chainID, height+5, height, suite.headerTime, altValSet, suite.valSet, altSigners)
currentTime = suite.now
},
@ -116,7 +116,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
name: "unsuccessful updates, passed in incorrect trusted validators for given consensus state",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.AppHash), height, suite.valsHash)
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), height, suite.valsHash)
newHeader = types.CreateTestHeader(chainID, height+5, height, suite.headerTime, bothValSet, bothValSet, bothSigners)
currentTime = suite.now
},
@ -126,7 +126,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
name: "unsuccessful update: trusting period has passed since last client timestamp",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.AppHash), height, suite.valsHash)
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), height, suite.valsHash)
newHeader = types.CreateTestHeader(chainID, height+1, height, suite.headerTime, suite.valSet, suite.valSet, signers)
// make current time pass trusting period from last timestamp on clientstate
currentTime = suite.now.Add(trustingPeriod)
@ -137,7 +137,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
name: "unsuccessful update: header timestamp is past current timestamp",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.AppHash), height, suite.valsHash)
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), height, suite.valsHash)
newHeader = types.CreateTestHeader(chainID, height+1, height, suite.now.Add(time.Minute), suite.valSet, suite.valSet, signers)
currentTime = suite.now
},
@ -147,7 +147,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
name: "unsuccessful update: header timestamp is not past last client timestamp",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.AppHash), height, suite.valsHash)
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), height, suite.valsHash)
newHeader = types.CreateTestHeader(chainID, height+1, height, suite.clientTime, suite.valSet, suite.valSet, signers)
currentTime = suite.now
},
@ -157,7 +157,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
name: "header basic validation failed",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs())
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.AppHash), height, suite.valsHash)
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), height, suite.valsHash)
newHeader = types.CreateTestHeader(chainID, height+1, height, suite.headerTime, suite.valSet, suite.valSet, signers)
// cause new header to fail validatebasic by changing commit height to mismatch header height
newHeader.SignedHeader.Commit.Height = height - 1
@ -169,7 +169,7 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
name: "header height < consensus height",
setup: func() {
clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height+5, commitmenttypes.GetSDKSpecs())
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.AppHash), height, suite.valsHash)
consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), height, suite.valsHash)
// Make new header at height less than latest client state
newHeader = types.CreateTestHeader(chainID, height-1, height, suite.headerTime, suite.valSet, suite.valSet, signers)
currentTime = suite.now
@ -187,13 +187,13 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
ctx := suite.chainA.GetContext().WithBlockTime(currentTime)
// Set trusted consensus state in client store
suite.chainA.App.IBCKeeper.ClientKeeper.SetClientConsensusState(ctx, clientID, consensusState.Height, consensusState)
suite.chainA.App.IBCKeeper.ClientKeeper.SetClientConsensusState(ctx, clientID, consensusState.GetHeight(), consensusState)
expectedConsensus := &types.ConsensusState{
Height: uint64(newHeader.Height),
Timestamp: newHeader.Time,
Root: commitmenttypes.NewMerkleRoot(newHeader.AppHash),
NextValidatorsHash: newHeader.NextValidatorsHash,
Height: uint64(newHeader.GetHeight()),
Timestamp: newHeader.GetTime(),
Root: commitmenttypes.NewMerkleRoot(newHeader.Header.GetAppHash()),
NextValidatorsHash: newHeader.Header.NextValidatorsHash,
}
newClientState, consensusState, err := clientState.CheckHeaderAndUpdateState(
@ -207,9 +207,9 @@ func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() {
suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
// Determine if clientState should be updated or not
if uint64(newHeader.Height) > clientState.LatestHeight {
// Header Height is greater than clientState latest Height, clientState should be updated with header.Height
suite.Require().Equal(uint64(newHeader.Height), newClientState.GetLatestHeight(), "clientstate height did not update")
if uint64(newHeader.GetHeight()) > clientState.LatestHeight {
// Header Height is greater than clientState latest Height, clientState should be updated with header.GetHeight()
suite.Require().Equal(uint64(newHeader.GetHeight()), newClientState.GetLatestHeight(), "clientstate height did not update")
} else {
// Update will add past consensus state, clientState should not be updated at all
suite.Require().Equal(clientState.LatestHeight, newClientState.GetLatestHeight(), "client state height updated for past header")

View File

@ -48,7 +48,7 @@ func (suite *IBCTestSuite) TestValidateGenesis() {
clientID,
[]clientexported.ConsensusState{
ibctmtypes.NewConsensusState(
suite.header.Time, commitmenttypes.NewMerkleRoot(suite.header.AppHash), suite.header.GetHeight(), suite.header.NextValidatorsHash,
suite.header.GetTime(), commitmenttypes.NewMerkleRoot(suite.header.Header.AppHash), suite.header.GetHeight(), suite.header.Header.NextValidatorsHash,
),
},
),
@ -177,7 +177,7 @@ func (suite *IBCTestSuite) TestInitGenesis() {
clientID,
[]clientexported.ConsensusState{
ibctmtypes.NewConsensusState(
suite.header.Time, commitmenttypes.NewMerkleRoot(suite.header.AppHash), suite.header.GetHeight(), suite.header.ValidatorSet.Hash(),
suite.header.GetTime(), commitmenttypes.NewMerkleRoot(suite.header.Header.AppHash), suite.header.GetHeight(), suite.header.Header.NextValidatorsHash,
),
},
),

View File

@ -356,26 +356,31 @@ func (chain *TestChain) UpdateTMClient(counterparty *TestChain, clientID string)
// Relayer must query for LatestHeight on client to get TrustedHeight
trustedHeight := chain.GetClientState(clientID).GetLatestHeight()
var (
trustedVals *tmtypes.ValidatorSet
ok bool
tmTrustedVals *tmtypes.ValidatorSet
ok bool
)
// Once we get TrustedHeight from client, we must query the validators from the counterparty chain
// If the LatestHeight == LastHeader.Height, then TrustedValidators are current validators
// If LatestHeight < LastHeader.Height, we can query the historical validator set from HistoricalInfo
if trustedHeight == uint64(counterparty.LastHeader.Height) {
trustedVals = counterparty.Vals
if trustedHeight == counterparty.LastHeader.GetHeight() {
tmTrustedVals = counterparty.Vals
} else {
// NOTE: We need to get validators from counterparty at height: trustedHeight+1
// since the last trusted validators for a header at height h
// is the NextValidators at h+1 committed to in header h by
// NextValidatorsHash
trustedVals, ok = counterparty.GetValsAtHeight(int64(trustedHeight + 1))
tmTrustedVals, ok = counterparty.GetValsAtHeight(int64(trustedHeight + 1))
if !ok {
return sdkerrors.Wrapf(ibctmtypes.ErrInvalidHeaderHeight, "could not retrieve trusted validators at trustedHeight: %d", trustedHeight)
}
}
// inject trusted fields into last header
header.TrustedHeight = trustedHeight
trustedVals, err := tmTrustedVals.ToProto()
if err != nil {
return err
}
header.TrustedValidators = trustedVals
msg := ibctmtypes.NewMsgUpdateClient(
@ -414,16 +419,21 @@ func (chain *TestChain) CreateTMClientHeader() ibctmtypes.Header {
commit, err := tmtypes.MakeCommit(blockID, chain.CurrentHeader.Height, 1, voteSet, chain.Signers, chain.CurrentHeader.Time)
require.NoError(chain.t, err)
signedHeader := tmtypes.SignedHeader{
Header: &tmHeader,
Commit: commit,
signedHeader := tmproto.SignedHeader{
Header: tmHeader.ToProto(),
Commit: commit.ToProto(),
}
valSet, err := chain.Vals.ToProto()
if err != nil {
panic(err)
}
// Do not set trusted field here, these fields can be inserted before relaying messages to a client.
// The relayer is responsible for querying client and injecting appropriate trusted fields.
return ibctmtypes.Header{
SignedHeader: signedHeader,
ValidatorSet: chain.Vals,
ValidatorSet: valSet,
}
}