Rename Evidence to Misbehaviour in IBC (#7151)

* rename Evidence to Misbehaviour in IBC code

* tidy go.sum

* remove more references to evidence

* Apply suggestions from code review

Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com>

* Update x/ibc/07-tendermint/client/cli/tx.go

* nit and doc

Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com>
Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
This commit is contained in:
Aditya 2020-08-26 13:51:13 -04:00 committed by GitHub
parent e09c8d9360
commit 9fc0dbbe05
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 1392 additions and 1371 deletions

View File

@ -214,7 +214,7 @@ func init() {
}
var fileDescriptor_d48c054165687f5c = []byte{
// 393 bytes of a gzipped FileDescriptorProto
// 395 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x4f, 0xce, 0x2f, 0xce,
0xcd, 0x2f, 0xd6, 0x4f, 0x4a, 0x2c, 0x4e, 0xd5, 0x2f, 0x4a, 0x4d, 0xcb, 0x49, 0x4d, 0x2e, 0xc9,
0xcc, 0xcf, 0xd3, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0x44, 0x12, 0xd2, 0x2b, 0x28, 0xca,
@ -228,18 +228,18 @@ var fileDescriptor_d48c054165687f5c = []byte{
0x0b, 0x72, 0x52, 0x73, 0x53, 0xf3, 0xa0, 0xd6, 0x43, 0xed, 0x10, 0x52, 0xe5, 0xe2, 0x43, 0x35,
0x46, 0x82, 0x51, 0x81, 0x51, 0x83, 0x33, 0x88, 0x17, 0xc5, 0x14, 0xa5, 0x78, 0x2e, 0x69, 0xac,
0x86, 0x40, 0x1d, 0xe3, 0xc0, 0x25, 0x93, 0x89, 0x22, 0x15, 0x9f, 0x9b, 0x5a, 0x5c, 0x9c, 0x98,
0x8e, 0xea, 0x32, 0x29, 0x54, 0x35, 0xbe, 0x10, 0x25, 0x60, 0x57, 0x1a, 0xad, 0x65, 0xe6, 0x12,
0x8e, 0xea, 0x32, 0x29, 0x54, 0x35, 0xbe, 0x10, 0x25, 0x60, 0x57, 0x1a, 0xed, 0x60, 0xe6, 0x12,
0x0c, 0x82, 0x07, 0x5e, 0x70, 0x6a, 0x51, 0x59, 0x66, 0x72, 0xaa, 0xd0, 0x1e, 0x46, 0x2e, 0x41,
0x8c, 0x20, 0x10, 0xb2, 0xd0, 0xc3, 0x1f, 0xe4, 0x7a, 0xb8, 0x42, 0x54, 0xca, 0x92, 0x0c, 0x9d,
0x10, 0x2f, 0x2a, 0x19, 0x35, 0x5d, 0x7e, 0x32, 0x99, 0x49, 0x47, 0x48, 0x8b, 0x50, 0x02, 0xc9,
0x44, 0x38, 0xf4, 0x06, 0x23, 0x97, 0x30, 0x96, 0x60, 0x13, 0xb2, 0x22, 0xc6, 0x19, 0xd8, 0x23,
0x4c, 0xca, 0x9a, 0x2c, 0xbd, 0x50, 0x4f, 0x78, 0x80, 0x3d, 0xe1, 0x24, 0xe4, 0x40, 0xd0, 0x13,
0xa8, 0x06, 0xe8, 0x57, 0xa3, 0x26, 0x92, 0x5a, 0x27, 0xdf, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c,
0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e,
0x3c, 0x96, 0x63, 0x88, 0x32, 0x4e, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0x85,
0xd9, 0x02, 0xa1, 0x74, 0x8b, 0x53, 0xb2, 0xf5, 0x93, 0x73, 0x32, 0x53, 0xf3, 0x4a, 0xf4, 0xd3,
0x8b, 0x0a, 0x92, 0x91, 0xec, 0x4d, 0x62, 0x03, 0xe7, 0x06, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff,
0xff, 0xd2, 0xbf, 0x07, 0xa6, 0x7e, 0x03, 0x00, 0x00,
0x44, 0x38, 0xf4, 0x31, 0x23, 0x97, 0x30, 0x96, 0x60, 0x13, 0xb2, 0x22, 0xc6, 0x19, 0xd8, 0x23,
0x4c, 0xca, 0x9a, 0x2c, 0xbd, 0x50, 0x4f, 0x04, 0x83, 0x3d, 0xe1, 0x2b, 0xe4, 0x4d, 0xbc, 0x27,
0xf4, 0xab, 0x51, 0xd3, 0x47, 0xad, 0x3e, 0x6a, 0x2c, 0x16, 0x3b, 0xf9, 0x9e, 0x78, 0x24, 0xc7,
0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x13, 0x1e, 0xcb, 0x31, 0x5c, 0x78, 0x2c,
0xc7, 0x70, 0xe3, 0xb1, 0x1c, 0x43, 0x94, 0x71, 0x7a, 0x66, 0x49, 0x46, 0x69, 0x92, 0x5e, 0x72,
0x7e, 0x2e, 0xcc, 0x42, 0x08, 0xa5, 0x5b, 0x9c, 0x92, 0xad, 0x9f, 0x9c, 0x93, 0x99, 0x9a, 0x57,
0xa2, 0x9f, 0x5e, 0x54, 0x90, 0x8c, 0xe4, 0x84, 0x24, 0x36, 0x70, 0xc6, 0x30, 0x06, 0x04, 0x00,
0x00, 0xff, 0xff, 0x32, 0x5b, 0x2b, 0x51, 0x89, 0x03, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.

View File

@ -235,7 +235,7 @@ func RegisterReflectionServiceHandlerClient(ctx context.Context, mux *runtime.Se
var (
pattern_ReflectionService_ListAllInterfaces_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"cosmos", "base", "reflection", "v1beta1", "interfaces"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_ReflectionService_ListImplementations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"cosmos", "base", "reflection", "v1beta1", "implementations", "interface_name"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_ReflectionService_ListImplementations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6}, []string{"cosmos", "base", "reflection", "v1beta1", "interfaces", "interface_name", "implementations"}, "", runtime.AssumeColonVerbOpt(true)))
)
var (

View File

@ -38,9 +38,9 @@ message Header {
[(gogoproto.moretags) = "yaml:\"new_public_key\""];
}
// Evidence defines evidence of misbehaviour for a solo machine which consists
// Misbehaviour defines misbehaviour for a solo machine which consists
// of a sequence and two signatures over different messages at that sequence.
message Evidence {
message Misbehaviour {
option (gogoproto.goproto_getters) = false;
option (gogoproto.goproto_stringer) = false;
string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
@ -82,11 +82,11 @@ message MsgUpdateClient {
}
// MsgSubmitClientMisbehaviour defines an sdk.Msg type that supports submitting
// arbitrary Evidence.
// arbitrary Misbehaviour.
message MsgSubmitClientMisbehaviour {
option (gogoproto.goproto_getters) = false;
bytes submitter = 1
[(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"];
Evidence evidence = 2;
Misbehaviour misbehaviour = 2;
}

View File

@ -68,9 +68,9 @@ message ConsensusState {
];
}
// Evidence is a wrapper over two conflicting Headers
// that implements Evidence interface expected by ICS-02
message Evidence {
// Misbehaviour is a wrapper over two conflicting Headers
// that implements Misbehaviour interface expected by ICS-02
message Misbehaviour {
option (gogoproto.goproto_getters) = false;
option (gogoproto.goproto_stringer) = false;
@ -164,7 +164,7 @@ message MsgUpdateClient {
message MsgSubmitClientMisbehaviour {
option (gogoproto.goproto_getters) = false;
Evidence evidence = 1;
bytes submitter = 2
Misbehaviour misbehaviour = 1;
bytes submitter = 2
[(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"];
}

View File

@ -133,7 +133,7 @@ type ConsensusState interface {
ValidateBasic() error
}
// Misbehaviour defines a specific consensus kind and an evidence
// Misbehaviour defines counterparty misbehaviour for a specific consensus type
type Misbehaviour interface {
evidenceexported.Evidence
ClientType() ClientType
@ -146,11 +146,12 @@ type Header interface {
GetHeight() uint64
}
// message types for the IBC client
// message and evidence types for the IBC client
const (
TypeMsgCreateClient string = "create_client"
TypeMsgUpdateClient string = "update_client"
TypeMsgSubmitClientMisbehaviour string = "submit_client_misbehaviour"
TypeEvidenceClientMisbehaviour string = "client_misbehaviour"
)
// MsgCreateClient defines the msg interface that the

View File

@ -84,7 +84,7 @@ func HandlerClientMisbehaviour(k keeper.Keeper) evidencetypes.Handler {
return func(ctx sdk.Context, evidence evidenceexported.Evidence) error {
misbehaviour, ok := evidence.(exported.Misbehaviour)
if !ok {
return sdkerrors.Wrapf(types.ErrInvalidEvidence,
return sdkerrors.Wrapf(types.ErrInvalidMisbehaviour,
"expected evidence to implement client Misbehaviour interface, got %T", evidence,
)
}

View File

@ -266,14 +266,14 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
altTime := suite.ctx.BlockTime().Add(time.Minute)
testCases := []struct {
name string
evidence *ibctmtypes.Evidence
malleate func() error
expPass bool
name string
misbehaviour *ibctmtypes.Misbehaviour
malleate func() error
expPass bool
}{
{
"trusting period misbehavior should pass",
&ibctmtypes.Evidence{
&ibctmtypes.Misbehaviour{
Header1: ibctmtypes.CreateTestHeader(testChainID, testClientHeight, testClientHeight, altTime, bothValSet, bothValSet, bothSigners),
Header2: ibctmtypes.CreateTestHeader(testChainID, testClientHeight, testClientHeight, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners),
ChainId: testChainID,
@ -290,7 +290,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
{
"misbehavior at later height should pass",
&ibctmtypes.Evidence{
&ibctmtypes.Misbehaviour{
Header1: ibctmtypes.CreateTestHeader(testChainID, testClientHeight+5, testClientHeight, altTime, bothValSet, valSet, bothSigners),
Header2: ibctmtypes.CreateTestHeader(testChainID, testClientHeight+5, testClientHeight, suite.ctx.BlockTime(), bothValSet, valSet, bothSigners),
ChainId: testChainID,
@ -318,7 +318,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
{
"misbehavior at later height with different trusted heights should pass",
&ibctmtypes.Evidence{
&ibctmtypes.Misbehaviour{
Header1: ibctmtypes.CreateTestHeader(testChainID, testClientHeight+5, testClientHeight, altTime, bothValSet, valSet, bothSigners),
Header2: ibctmtypes.CreateTestHeader(testChainID, testClientHeight+5, testClientHeight+3, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners),
ChainId: testChainID,
@ -346,7 +346,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
{
"misbehaviour fails validatebasic",
&ibctmtypes.Evidence{
&ibctmtypes.Misbehaviour{
Header1: ibctmtypes.CreateTestHeader(testChainID, testClientHeight+1, testClientHeight, altTime, bothValSet, bothValSet, bothSigners),
Header2: ibctmtypes.CreateTestHeader(testChainID, testClientHeight, testClientHeight, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners),
ChainId: testChainID,
@ -363,7 +363,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
{
"trusted ConsensusState1 not found",
&ibctmtypes.Evidence{
&ibctmtypes.Misbehaviour{
Header1: ibctmtypes.CreateTestHeader(testChainID, testClientHeight+5, testClientHeight+3, altTime, bothValSet, bothValSet, bothSigners),
Header2: ibctmtypes.CreateTestHeader(testChainID, testClientHeight+5, testClientHeight, suite.ctx.BlockTime(), bothValSet, valSet, bothSigners),
ChainId: testChainID,
@ -380,7 +380,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
},
{
"trusted ConsensusState2 not found",
&ibctmtypes.Evidence{
&ibctmtypes.Misbehaviour{
Header1: ibctmtypes.CreateTestHeader(testChainID, testClientHeight+5, testClientHeight, altTime, bothValSet, valSet, bothSigners),
Header2: ibctmtypes.CreateTestHeader(testChainID, testClientHeight+5, testClientHeight+3, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners),
ChainId: testChainID,
@ -398,13 +398,13 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
{
"client state not found",
&ibctmtypes.Evidence{},
&ibctmtypes.Misbehaviour{},
func() error { return nil },
false,
},
{
"client already frozen at earlier height",
&ibctmtypes.Evidence{
&ibctmtypes.Misbehaviour{
Header1: ibctmtypes.CreateTestHeader(testChainID, testClientHeight, testClientHeight, altTime, bothValSet, bothValSet, bothSigners),
Header2: ibctmtypes.CreateTestHeader(testChainID, testClientHeight, testClientHeight, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners),
ChainId: testChainID,
@ -425,7 +425,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
{
"misbehaviour check failed",
&ibctmtypes.Evidence{
&ibctmtypes.Misbehaviour{
Header1: ibctmtypes.CreateTestHeader(testChainID, testClientHeight, testClientHeight, altTime, bothValSet, bothValSet, bothSigners),
Header2: ibctmtypes.CreateTestHeader(testChainID, testClientHeight, testClientHeight, suite.ctx.BlockTime(), altValSet, bothValSet, altSigners),
ChainId: testChainID,
@ -453,7 +453,7 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
err := tc.malleate()
suite.Require().NoError(err)
err = suite.keeper.CheckMisbehaviourAndUpdateState(suite.ctx, tc.evidence)
err = suite.keeper.CheckMisbehaviourAndUpdateState(suite.ctx, tc.misbehaviour)
if tc.expPass {
suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
@ -461,8 +461,8 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
clientState, found := suite.keeper.GetClientState(suite.ctx, testClientID)
suite.Require().True(found, "valid test case %d failed: %s", i, tc.name)
suite.Require().True(clientState.IsFrozen(), "valid test case %d failed: %s", i, tc.name)
suite.Require().Equal(uint64(tc.evidence.GetHeight()), clientState.GetFrozenHeight(),
"valid test case %d failed: %s. Expected FrozenHeight %d got %d", tc.evidence.GetHeight(), clientState.GetFrozenHeight())
suite.Require().Equal(uint64(tc.misbehaviour.GetHeight()), clientState.GetFrozenHeight(),
"valid test case %d failed: %s. Expected FrozenHeight %d got %d", tc.misbehaviour.GetHeight(), clientState.GetFrozenHeight())
} else {
suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
}

View File

@ -16,7 +16,7 @@ var (
ErrInvalidClientType = sdkerrors.Register(SubModuleName, 9, "invalid client type")
ErrRootNotFound = sdkerrors.Register(SubModuleName, 10, "commitment root not found")
ErrInvalidHeader = sdkerrors.Register(SubModuleName, 11, "invalid client header")
ErrInvalidEvidence = sdkerrors.Register(SubModuleName, 12, "invalid light client misbehaviour evidence")
ErrInvalidMisbehaviour = sdkerrors.Register(SubModuleName, 12, "invalid light client misbehaviour")
ErrFailedClientStateVerification = sdkerrors.Register(SubModuleName, 13, "client state verification failed")
ErrFailedClientConsensusStateVerification = sdkerrors.Register(SubModuleName, 14, "client consensus state verification failed")
ErrFailedConnectionStateVerification = sdkerrors.Register(SubModuleName, 15, "connection state verification failed")

View File

@ -290,7 +290,6 @@ func local_request_Query_ConsensusStates_0(ctx context.Context, marshaler runtim
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
// UnaryRPC :call QueryServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
mux.Handle("GET", pattern_Query_ClientState_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {

View File

@ -183,11 +183,11 @@ func NewUpdateClientCmd() *cobra.Command {
// https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#misbehaviour
func NewSubmitMisbehaviourCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "misbehaviour [path/to/evidence.json]",
Use: "misbehaviour [path/to/misbehaviour.json]",
Short: "submit a client misbehaviour",
Long: "submit a client misbehaviour to invalidate to invalidate previous state roots and prevent future updates",
Example: fmt.Sprintf(
"$ %s tx ibc %s misbehaviour [path/to/evidence.json] --from node0 --home ../node0/<app>cli --chain-id $CID",
"$ %s tx ibc %s misbehaviour [path/to/misbehaviour.json] --from node0 --home ../node0/<app>cli --chain-id $CID",
version.AppName, types.SubModuleName,
),
Args: cobra.ExactArgs(1),
@ -200,19 +200,19 @@ func NewSubmitMisbehaviourCmd() *cobra.Command {
cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry)
var ev *types.Evidence
if err := cdc.UnmarshalJSON([]byte(args[0]), ev); err != nil {
var m *types.Misbehaviour
if err := cdc.UnmarshalJSON([]byte(args[0]), m); err != nil {
// check for file path if JSON input is not provided
contents, err := ioutil.ReadFile(args[0])
if err != nil {
return errors.New("neither JSON input nor path to .json file were provided")
}
if err := cdc.UnmarshalJSON(contents, ev); err != nil {
return errors.Wrap(err, "error unmarshalling evidence file")
if err := cdc.UnmarshalJSON(contents, m); err != nil {
return errors.Wrap(err, "error unmarshalling misbehaviour file")
}
}
msg := types.NewMsgSubmitClientMisbehaviour(ev, clientCtx.GetFromAddress())
msg := types.NewMsgSubmitClientMisbehaviour(m, clientCtx.GetFromAddress())
if err := msg.ValidateBasic(); err != nil {
return err
}

View File

@ -20,7 +20,7 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
)
registry.RegisterImplementations(
(*evidenceexported.Evidence)(nil),
&Evidence{},
&Misbehaviour{},
)
}

View File

@ -1,185 +0,0 @@
package types
import (
"math"
"time"
yaml "gopkg.in/yaml.v2"
"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"
evidenceexported "github.com/cosmos/cosmos-sdk/x/evidence/exported"
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
)
var (
_ evidenceexported.Evidence = Evidence{}
_ clientexported.Misbehaviour = Evidence{}
)
// NewEvidence creates a new Evidence instance.
func NewEvidence(clientID, chainID string, header1, header2 *Header) *Evidence {
return &Evidence{
ClientId: clientID,
ChainId: chainID,
Header1: header1,
Header2: header2,
}
}
// ClientType is Tendermint light client
func (ev Evidence) ClientType() clientexported.ClientType {
return clientexported.Tendermint
}
// GetClientID returns the ID of the client that committed a misbehaviour.
func (ev Evidence) GetClientID() string {
return ev.ClientId
}
// Route implements Evidence interface
func (ev Evidence) Route() string {
return clienttypes.SubModuleName
}
// Type implements Evidence interface
func (ev Evidence) Type() string {
return "client_misbehaviour"
}
// String implements Evidence interface
func (ev Evidence) String() string {
// FIXME: implement custom marshaller
bz, err := yaml.Marshal(ev)
if err != nil {
panic(err)
}
return string(bz)
}
// Hash implements Evidence interface
func (ev Evidence) Hash() tmbytes.HexBytes {
bz := SubModuleCdc.MustMarshalBinaryBare(&ev)
return tmhash.Sum(bz)
}
// GetHeight returns the height at which misbehaviour occurred
//
// NOTE: assumes that evidence headers have the same height
func (ev Evidence) GetHeight() int64 {
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.GetTime().UnixNano()), float64(ev.Header2.GetTime().UnixNano())))
return time.Unix(0, minTime)
}
// ValidateBasic implements Evidence interface
func (ev Evidence) ValidateBasic() error {
if ev.Header1 == nil {
return sdkerrors.Wrap(ErrInvalidHeader, "evidence Header1 cannot be nil")
}
if ev.Header2 == nil {
return sdkerrors.Wrap(ErrInvalidHeader, "evidence Header2 cannot be nil")
}
if ev.Header1.TrustedHeight == 0 {
return sdkerrors.Wrap(ErrInvalidHeaderHeight, "evidence Header1 must have non-zero trusted height")
}
if ev.Header2.TrustedHeight == 0 {
return sdkerrors.Wrap(ErrInvalidHeaderHeight, "evidence Header2 must have non-zero trusted height")
}
if ev.Header1.TrustedValidators == nil {
return sdkerrors.Wrap(ErrInvalidValidatorSet, "trusted validator set in Header1 cannot be empty")
}
if ev.Header2.TrustedValidators == nil {
return sdkerrors.Wrap(ErrInvalidValidatorSet, "trusted validator set in Header2 cannot be empty")
}
if err := host.ClientIdentifierValidator(ev.ClientId); err != nil {
return sdkerrors.Wrap(err, "evidence client ID is invalid")
}
// ValidateBasic on both validators
if err := ev.Header1.ValidateBasic(ev.ChainId); err != nil {
return sdkerrors.Wrap(
clienttypes.ErrInvalidEvidence,
sdkerrors.Wrap(err, "header 1 failed validation").Error(),
)
}
if err := ev.Header2.ValidateBasic(ev.ChainId); err != nil {
return sdkerrors.Wrap(
clienttypes.ErrInvalidEvidence,
sdkerrors.Wrap(err, "header 2 failed validation").Error(),
)
}
// Ensure that Heights are the same
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 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
}
if err := ValidCommit(ev.ChainId, ev.Header2.Commit, ev.Header2.ValidatorSet); err != nil {
return err
}
return nil
}
// ValidCommit checks if the given commit is a valid commit from the passed-in validatorset
//
// 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 *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, tmCommit, tmValset)
blockID, ok := voteSet.TwoThirdsMajority()
// Check that ValidatorSet did indeed commit to blockID in Commit
if !ok || !blockID.Equals(tmCommit.BlockID) {
return sdkerrors.Wrap(clienttypes.ErrInvalidEvidence, "validator set did not commit to header")
}
return nil
}

View File

@ -1,266 +0,0 @@
package types_test
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"
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
"github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
)
func (suite *TendermintTestSuite) TestEvidence() {
signers := []tmtypes.PrivValidator{suite.privVal}
ev := &types.Evidence{
Header1: suite.header,
Header2: types.CreateTestHeader(chainID, height, height-1, suite.now, suite.valSet, suite.valSet, signers),
ChainId: chainID,
ClientId: clientID,
}
suite.Require().Equal(ev.ClientType(), clientexported.Tendermint)
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.cdc.MustMarshalBinaryBare(ev))))
suite.Require().Equal(ev.GetHeight(), int64(height))
}
func (suite *TendermintTestSuite) TestEvidenceValidateBasic() {
altPrivVal := tmtypes.NewMockPV()
altPubKey, err := altPrivVal.GetPubKey()
suite.Require().NoError(err)
altVal := tmtypes.NewValidator(altPubKey, height)
// Create bothValSet with both suite validator and altVal
bothValSet := tmtypes.NewValidatorSet(append(suite.valSet.Validators, altVal))
// Create alternative validator set with only altVal
altValSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{altVal})
signers := []tmtypes.PrivValidator{suite.privVal}
// Create signer array and ensure it is in same order as bothValSet
_, suiteVal := suite.valSet.GetByIndex(0)
bothSigners := types.CreateSortedSignerArray(altPrivVal, suite.privVal, altVal, suiteVal)
altSigners := []tmtypes.PrivValidator{altPrivVal}
testCases := []struct {
name string
evidence *types.Evidence
malleateEvidence func(ev *types.Evidence) error
expPass bool
}{
{
"valid evidence",
&types.Evidence{
Header1: suite.header,
Header2: types.CreateTestHeader(chainID, height, height-1, suite.now.Add(time.Minute), suite.valSet, suite.valSet, signers),
ChainId: chainID,
ClientId: clientID,
},
func(ev *types.Evidence) error { return nil },
true,
},
{
"evidence Header1 is nil",
types.NewEvidence(clientID, chainID, nil, suite.header),
func(ev *types.Evidence) error { return nil },
false,
},
{
"evidence Header2 is nil",
types.NewEvidence(clientID, chainID, suite.header, nil),
func(ev *types.Evidence) error { return nil },
false,
},
{
"valid evidence with different trusted headers",
&types.Evidence{
Header1: suite.header,
Header2: types.CreateTestHeader(chainID, height, height-3, suite.now.Add(time.Minute), suite.valSet, bothValSet, signers),
ChainId: chainID,
ClientId: clientID,
},
func(ev *types.Evidence) error { return nil },
true,
},
{
"trusted height is 0 in Header1",
&types.Evidence{
Header1: types.CreateTestHeader(chainID, height, 0, suite.now.Add(time.Minute), suite.valSet, suite.valSet, signers),
Header2: suite.header,
ChainId: chainID,
ClientId: clientID,
},
func(ev *types.Evidence) error { return nil },
false,
},
{
"trusted height is 0 in Header2",
&types.Evidence{
Header1: suite.header,
Header2: types.CreateTestHeader(chainID, height, 0, suite.now.Add(time.Minute), suite.valSet, suite.valSet, signers),
ChainId: chainID,
ClientId: clientID,
},
func(ev *types.Evidence) error { return nil },
false,
},
{
"trusted valset is nil in Header1",
&types.Evidence{
Header1: types.CreateTestHeader(chainID, height, height-1, suite.now.Add(time.Minute), suite.valSet, nil, signers),
Header2: suite.header,
ChainId: chainID,
ClientId: clientID,
},
func(ev *types.Evidence) error { return nil },
false,
},
{
"trusted valset is nil in Header2",
&types.Evidence{
Header1: suite.header,
Header2: types.CreateTestHeader(chainID, height, height-1, suite.now.Add(time.Minute), suite.valSet, nil, signers),
ChainId: chainID,
ClientId: clientID,
},
func(ev *types.Evidence) error { return nil },
false,
},
{
"invalid client ID ",
&types.Evidence{
Header1: suite.header,
Header2: types.CreateTestHeader(chainID, height, height-1, suite.now, suite.valSet, suite.valSet, signers),
ChainId: chainID,
ClientId: "GAIA",
},
func(ev *types.Evidence) error { return nil },
false,
},
{
"wrong chainID on header1",
&types.Evidence{
Header1: suite.header,
Header2: types.CreateTestHeader("ethermint", height, height-1, suite.now, suite.valSet, suite.valSet, signers),
ChainId: "ethermint",
ClientId: clientID,
},
func(ev *types.Evidence) error { return nil },
false,
},
{
"wrong chainID on header2",
&types.Evidence{
Header1: suite.header,
Header2: types.CreateTestHeader("ethermint", height, height-1, suite.now, suite.valSet, suite.valSet, signers),
ChainId: chainID,
ClientId: clientID,
},
func(ev *types.Evidence) error { return nil },
false,
},
{
"mismatched heights",
&types.Evidence{
Header1: suite.header,
Header2: types.CreateTestHeader(chainID, 6, 4, suite.now, suite.valSet, suite.valSet, signers),
ChainId: chainID,
ClientId: clientID,
},
func(ev *types.Evidence) error { return nil },
false,
},
{
"same block id",
&types.Evidence{
Header1: suite.header,
Header2: suite.header,
ChainId: chainID,
ClientId: clientID,
},
func(ev *types.Evidence) error { return nil },
false,
},
{
"header 1 doesn't have 2/3 majority",
&types.Evidence{
Header1: types.CreateTestHeader(chainID, height, height-1, suite.now, bothValSet, suite.valSet, bothSigners),
Header2: suite.header,
ChainId: chainID,
ClientId: clientID,
},
func(ev *types.Evidence) error {
// voteSet contains only altVal which is less than 2/3 of total power (height/1height)
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,
},
{
"header 2 doesn't have 2/3 majority",
&types.Evidence{
Header1: suite.header,
Header2: types.CreateTestHeader(chainID, height, height-1, suite.now, bothValSet, suite.valSet, bothSigners),
ChainId: chainID,
ClientId: clientID,
},
func(ev *types.Evidence) error {
// voteSet contains only altVal which is less than 2/3 of total power (height/1height)
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,
},
{
"validators sign off on wrong commit",
&types.Evidence{
Header1: suite.header,
Header2: types.CreateTestHeader(chainID, height, height-1, suite.now, bothValSet, suite.valSet, bothSigners),
ChainId: chainID,
ClientId: clientID,
},
func(ev *types.Evidence) error {
tmBlockID := types.MakeBlockID(tmhash.Sum([]byte("other_hash")), 3, tmhash.Sum([]byte("other_partset")))
ev.Header2.Commit.BlockID = tmBlockID.ToProto()
return nil
},
false,
},
}
for i, tc := range testCases {
tc := tc
err := tc.malleateEvidence(tc.evidence)
suite.Require().NoError(err)
if tc.expPass {
suite.Require().NoError(tc.evidence.ValidateBasic(), "valid test case %d failed: %s", i, tc.name)
} else {
suite.Require().Error(tc.evidence.ValidateBasic(), "invalid test case %d passed: %s", i, tc.name)
}
}
}

View File

@ -1,141 +1,185 @@
package types
import (
"math"
"time"
yaml "gopkg.in/yaml.v2"
"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"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
evidenceexported "github.com/cosmos/cosmos-sdk/x/evidence/exported"
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
)
// CheckMisbehaviourAndUpdateState determines whether or not two conflicting
// headers at the same height would have convinced the light client.
//
// NOTE: consensusState1 is the trusted consensus state that corresponds to the TrustedHeight
// of misbehaviour.Header1
// Similarly, consensusState2 is the trusted consensus state that corresponds
// to misbehaviour.Header2
func (cs ClientState) CheckMisbehaviourAndUpdateState(
ctx sdk.Context,
cdc codec.BinaryMarshaler,
clientStore sdk.KVStore,
misbehaviour clientexported.Misbehaviour,
) (clientexported.ClientState, error) {
var (
_ evidenceexported.Evidence = Misbehaviour{}
_ clientexported.Misbehaviour = Misbehaviour{}
)
// If client is already frozen at earlier height than evidence, return with error
if cs.IsFrozen() && cs.FrozenHeight <= uint64(misbehaviour.GetHeight()) {
return nil, sdkerrors.Wrapf(clienttypes.ErrInvalidEvidence,
"client is already frozen at earlier height %d than misbehaviour height %d", cs.FrozenHeight, misbehaviour.GetHeight())
// NewMisbehaviour creates a new Misbehaviour instance.
func NewMisbehaviour(clientID, chainID string, header1, header2 *Header) *Misbehaviour {
return &Misbehaviour{
ClientId: clientID,
ChainId: chainID,
Header1: header1,
Header2: header2,
}
tmEvidence, ok := misbehaviour.(*Evidence)
if !ok {
return nil, sdkerrors.Wrapf(clienttypes.ErrInvalidClientType, "expected type %T, got %T", misbehaviour, &Evidence{})
}
// Retrieve trusted consensus states for each Header in misbehaviour
// and unmarshal from clientStore
// Get consensus bytes from clientStore
tmConsensusState1, err := GetConsensusState(clientStore, cdc, tmEvidence.Header1.TrustedHeight)
if err != nil {
return nil, sdkerrors.Wrapf(err, "could not get trusted consensus state from clientStore for Header1 at TrustedHeight: %d", tmEvidence.Header1.TrustedHeight)
}
// Get consensus bytes from clientStore
tmConsensusState2, err := GetConsensusState(clientStore, cdc, tmEvidence.Header2.TrustedHeight)
if err != nil {
return nil, sdkerrors.Wrapf(err, "could not get trusted consensus state from clientStore for Header2 at TrustedHeight: %d", tmEvidence.Header2.TrustedHeight)
}
// calculate the age of the misbehaviour evidence
infractionHeight := tmEvidence.GetHeight()
infractionTime := tmEvidence.GetTime()
ageDuration := ctx.BlockTime().Sub(infractionTime)
ageBlocks := int64(cs.LatestHeight) - infractionHeight
// TODO: Retrieve consensusparams from client state and not context
// Issue #6516: https://github.com/cosmos/cosmos-sdk/issues/6516
consensusParams := ctx.ConsensusParams()
// Reject misbehaviour if the age is too old. Evidence is considered stale
// if the difference in time and number of blocks is greater than the allowed
// parameters defined.
//
// NOTE: The first condition is a safety check as the consensus params cannot
// be nil since the previous param values will be used in case they can't be
// retrieved. If they are not set during initialization, Tendermint will always
// use the default values.
if consensusParams != nil &&
consensusParams.Evidence != nil &&
(ageDuration > consensusParams.Evidence.MaxAgeDuration ||
ageBlocks > consensusParams.Evidence.MaxAgeNumBlocks) {
return nil, sdkerrors.Wrapf(clienttypes.ErrInvalidEvidence,
"age duration (%s) and age blocks (%d) are greater than max consensus params for duration (%s) and block (%d)",
ageDuration, ageBlocks, consensusParams.Evidence.MaxAgeDuration, consensusParams.Evidence.MaxAgeNumBlocks,
)
}
// Check the validity of the two conflicting headers against their respective
// trusted consensus states
// NOTE: header height and commitment root assertions are checked in
// evidence.ValidateBasic by the client keeper and msg.ValidateBasic
// by the base application.
if err := checkMisbehaviourHeader(
&cs, tmConsensusState1, tmEvidence.Header1, ctx.BlockTime(),
); err != nil {
return nil, sdkerrors.Wrap(err, "verifying Header1 in Evidence failed")
}
if err := checkMisbehaviourHeader(
&cs, tmConsensusState2, tmEvidence.Header2, ctx.BlockTime(),
); err != nil {
return nil, sdkerrors.Wrap(err, "verifying Header2 in Evidence failed")
}
cs.FrozenHeight = uint64(tmEvidence.GetHeight())
return &cs, nil
}
// checkMisbehaviourHeader checks that a Header in Misbehaviour is valid evidence given
// a trusted ConsensusState
func checkMisbehaviourHeader(
clientState *ClientState, consState *ConsensusState, header *Header, currentTimestamp time.Time,
) error {
// ClientType is Tendermint light client
func (misbehaviour Misbehaviour) ClientType() clientexported.ClientType {
return clientexported.Tendermint
}
tmTrustedValset, err := tmtypes.ValidatorSetFromProto(header.TrustedValidators)
// GetClientID returns the ID of the client that committed a misbehaviour.
func (misbehaviour Misbehaviour) GetClientID() string {
return misbehaviour.ClientId
}
// Route implements Misbehaviour interface
func (misbehaviour Misbehaviour) Route() string {
return clienttypes.SubModuleName
}
// Type implements Misbehaviour interface
func (misbehaviour Misbehaviour) Type() string {
return clientexported.TypeEvidenceClientMisbehaviour
}
// String implements Misbehaviour interface
func (misbehaviour Misbehaviour) String() string {
// FIXME: implement custom marshaller
bz, err := yaml.Marshal(misbehaviour)
if err != nil {
return sdkerrors.Wrap(err, "trusted validator set is not tendermint validator set type")
panic(err)
}
return string(bz)
}
// Hash implements Misbehaviour interface
func (misbehaviour Misbehaviour) Hash() tmbytes.HexBytes {
bz := SubModuleCdc.MustMarshalBinaryBare(&misbehaviour)
return tmhash.Sum(bz)
}
// GetHeight returns the height at which misbehaviour occurred
//
// NOTE: assumes that misbehaviour headers have the same height
func (misbehaviour Misbehaviour) GetHeight() int64 {
return int64(math.Min(float64(misbehaviour.Header1.GetHeight()), float64(misbehaviour.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 misbehaviour age range.
func (misbehaviour Misbehaviour) GetTime() time.Time {
minTime := int64(math.Max(float64(misbehaviour.Header1.GetTime().UnixNano()), float64(misbehaviour.Header2.GetTime().UnixNano())))
return time.Unix(0, minTime)
}
// ValidateBasic implements Misbehaviour interface
func (misbehaviour Misbehaviour) ValidateBasic() error {
if misbehaviour.Header1 == nil {
return sdkerrors.Wrap(ErrInvalidHeader, "misbehaviour Header1 cannot be nil")
}
if misbehaviour.Header2 == nil {
return sdkerrors.Wrap(ErrInvalidHeader, "misbehaviour Header2 cannot be nil")
}
if misbehaviour.Header1.TrustedHeight == 0 {
return sdkerrors.Wrap(ErrInvalidHeaderHeight, "misbehaviour Header1 must have non-zero trusted height")
}
if misbehaviour.Header2.TrustedHeight == 0 {
return sdkerrors.Wrap(ErrInvalidHeaderHeight, "misbehaviour Header2 must have non-zero trusted height")
}
if misbehaviour.Header1.TrustedValidators == nil {
return sdkerrors.Wrap(ErrInvalidValidatorSet, "trusted validator set in Header1 cannot be empty")
}
if misbehaviour.Header2.TrustedValidators == nil {
return sdkerrors.Wrap(ErrInvalidValidatorSet, "trusted validator set in Header2 cannot be empty")
}
tmCommit, err := tmtypes.CommitFromProto(header.Commit)
if err != nil {
return sdkerrors.Wrap(err, "commit is not tendermint commit type")
if err := host.ClientIdentifierValidator(misbehaviour.ClientId); err != nil {
return sdkerrors.Wrap(err, "misbehaviour client ID is invalid")
}
// check the trusted fields for the header against ConsensusState
if err := checkTrustedHeader(header, consState); err != nil {
return err
}
// assert that the timestamp is not from more than an unbonding period ago
if currentTimestamp.Sub(consState.Timestamp) >= clientState.UnbondingPeriod {
return sdkerrors.Wrapf(
ErrUnbondingPeriodExpired,
"current timestamp minus the latest consensus state timestamp is greater than or equal to the unbonding period (%s >= %s)",
currentTimestamp.Sub(consState.Timestamp), clientState.UnbondingPeriod,
// ValidateBasic on both validators
if err := misbehaviour.Header1.ValidateBasic(misbehaviour.ChainId); err != nil {
return sdkerrors.Wrap(
clienttypes.ErrInvalidMisbehaviour,
sdkerrors.Wrap(err, "header 1 failed validation").Error(),
)
}
if err := misbehaviour.Header2.ValidateBasic(misbehaviour.ChainId); err != nil {
return sdkerrors.Wrap(
clienttypes.ErrInvalidMisbehaviour,
sdkerrors.Wrap(err, "header 2 failed validation").Error(),
)
}
// Ensure that Heights are the same
if misbehaviour.Header1.GetHeight() != misbehaviour.Header2.GetHeight() {
return sdkerrors.Wrapf(clienttypes.ErrInvalidMisbehaviour, "headers in misbehaviour are on different heights (%d ≠ %d)", misbehaviour.Header1.GetHeight(), misbehaviour.Header2.GetHeight())
}
// - ValidatorSet must have 2/3 similarity with trusted FromValidatorSet
// - ValidatorSets on both headers are valid given the last trusted ValidatorSet
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)
blockID1, err := tmtypes.BlockIDFromProto(&misbehaviour.Header1.SignedHeader.Commit.BlockID)
if err != nil {
return sdkerrors.Wrap(err, "invalid block ID from header 1 in misbehaviour")
}
blockID2, err := tmtypes.BlockIDFromProto(&misbehaviour.Header2.SignedHeader.Commit.BlockID)
if err != nil {
return sdkerrors.Wrap(err, "invalid block ID from header 2 in misbehaviour")
}
// Ensure that Commit Hashes are different
if blockID1.Equals(*blockID2) {
return sdkerrors.Wrap(clienttypes.ErrInvalidMisbehaviour, "headers blockIDs are not equal")
}
if err := ValidCommit(misbehaviour.ChainId, misbehaviour.Header1.Commit, misbehaviour.Header1.ValidatorSet); err != nil {
return err
}
if err := ValidCommit(misbehaviour.ChainId, misbehaviour.Header2.Commit, misbehaviour.Header2.ValidatorSet); err != nil {
return err
}
return nil
}
// ValidCommit checks if the given commit is a valid commit from the passed-in validatorset
//
// CommitToVoteSet will panic if the commit cannot be converted to a valid voteset given the validatorset
// This implies that someone tried to submit misbehaviour that wasn't actually committed by the validatorset
// thus we should return an error here and reject the misbehaviour rather than panicing.
func ValidCommit(chainID string, commit *tmproto.Commit, valSet *tmproto.ValidatorSet) (err error) {
defer func() {
if r := recover(); r != nil {
err = sdkerrors.Wrapf(clienttypes.ErrInvalidMisbehaviour, "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, tmCommit, tmValset)
blockID, ok := voteSet.TwoThirdsMajority()
// Check that ValidatorSet did indeed commit to blockID in Commit
if !ok || !blockID.Equals(tmCommit.BlockID) {
return sdkerrors.Wrap(clienttypes.ErrInvalidMisbehaviour, "validator set did not commit to header")
}
return nil
}

View File

@ -0,0 +1,141 @@
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"
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
)
// CheckMisbehaviourAndUpdateState determines whether or not two conflicting
// headers at the same height would have convinced the light client.
//
// NOTE: consensusState1 is the trusted consensus state that corresponds to the TrustedHeight
// of misbehaviour.Header1
// Similarly, consensusState2 is the trusted consensus state that corresponds
// to misbehaviour.Header2
func (cs ClientState) CheckMisbehaviourAndUpdateState(
ctx sdk.Context,
cdc codec.BinaryMarshaler,
clientStore sdk.KVStore,
misbehaviour clientexported.Misbehaviour,
) (clientexported.ClientState, error) {
// If client is already frozen at earlier height than misbehaviour, return with error
if cs.IsFrozen() && cs.FrozenHeight <= uint64(misbehaviour.GetHeight()) {
return nil, sdkerrors.Wrapf(clienttypes.ErrInvalidMisbehaviour,
"client is already frozen at earlier height %d than misbehaviour height %d", cs.FrozenHeight, misbehaviour.GetHeight())
}
tmEvidence, ok := misbehaviour.(*Misbehaviour)
if !ok {
return nil, sdkerrors.Wrapf(clienttypes.ErrInvalidClientType, "expected type %T, got %T", misbehaviour, &Misbehaviour{})
}
// Retrieve trusted consensus states for each Header in misbehaviour
// and unmarshal from clientStore
// Get consensus bytes from clientStore
tmConsensusState1, err := GetConsensusState(clientStore, cdc, tmEvidence.Header1.TrustedHeight)
if err != nil {
return nil, sdkerrors.Wrapf(err, "could not get trusted consensus state from clientStore for Header1 at TrustedHeight: %d", tmEvidence.Header1.TrustedHeight)
}
// Get consensus bytes from clientStore
tmConsensusState2, err := GetConsensusState(clientStore, cdc, tmEvidence.Header2.TrustedHeight)
if err != nil {
return nil, sdkerrors.Wrapf(err, "could not get trusted consensus state from clientStore for Header2 at TrustedHeight: %d", tmEvidence.Header2.TrustedHeight)
}
// calculate the age of the misbehaviour
infractionHeight := tmEvidence.GetHeight()
infractionTime := tmEvidence.GetTime()
ageDuration := ctx.BlockTime().Sub(infractionTime)
ageBlocks := int64(cs.LatestHeight) - infractionHeight
// TODO: Retrieve consensusparams from client state and not context
// Issue #6516: https://github.com/cosmos/cosmos-sdk/issues/6516
consensusParams := ctx.ConsensusParams()
// Reject misbehaviour if the age is too old. Misbehaviour is considered stale
// if the difference in time and number of blocks is greater than the allowed
// parameters defined.
//
// NOTE: The first condition is a safety check as the consensus params cannot
// be nil since the previous param values will be used in case they can't be
// retrieved. If they are not set during initialization, Tendermint will always
// use the default values.
if consensusParams != nil &&
consensusParams.Evidence != nil &&
(ageDuration > consensusParams.Evidence.MaxAgeDuration ||
ageBlocks > consensusParams.Evidence.MaxAgeNumBlocks) {
return nil, sdkerrors.Wrapf(clienttypes.ErrInvalidMisbehaviour,
"age duration (%s) and age blocks (%d) are greater than max consensus params for duration (%s) and block (%d)",
ageDuration, ageBlocks, consensusParams.Evidence.MaxAgeDuration, consensusParams.Evidence.MaxAgeNumBlocks,
)
}
// Check the validity of the two conflicting headers against their respective
// trusted consensus states
// NOTE: header height and commitment root assertions are checked in
// misbehaviour.ValidateBasic by the client keeper and msg.ValidateBasic
// by the base application.
if err := checkMisbehaviourHeader(
&cs, tmConsensusState1, tmEvidence.Header1, ctx.BlockTime(),
); err != nil {
return nil, sdkerrors.Wrap(err, "verifying Header1 in Misbehaviour failed")
}
if err := checkMisbehaviourHeader(
&cs, tmConsensusState2, tmEvidence.Header2, ctx.BlockTime(),
); err != nil {
return nil, sdkerrors.Wrap(err, "verifying Header2 in Misbehaviour failed")
}
cs.FrozenHeight = uint64(tmEvidence.GetHeight())
return &cs, nil
}
// checkMisbehaviourHeader checks that a Header in Misbehaviour is valid misbehaviour given
// a trusted ConsensusState
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
}
// assert that the timestamp is not from more than an unbonding period ago
if currentTimestamp.Sub(consState.Timestamp) >= clientState.UnbondingPeriod {
return sdkerrors.Wrapf(
ErrUnbondingPeriodExpired,
"current timestamp minus the latest consensus state timestamp is greater than or equal to the unbonding period (%s >= %s)",
currentTimestamp.Sub(consState.Timestamp), clientState.UnbondingPeriod,
)
}
// - ValidatorSet must have 2/3 similarity with trusted FromValidatorSet
// - ValidatorSets on both headers are valid given the last trusted ValidatorSet
if err := tmTrustedValset.VerifyCommitLightTrusting(
clientState.GetChainID(), tmCommit, clientState.TrustLevel.ToTendermint(),
); err != nil {
return sdkerrors.Wrapf(clienttypes.ErrInvalidMisbehaviour, "validator set in header has too much change from trusted validator set: %v", err)
}
return nil
}

View File

@ -0,0 +1,318 @@
package types_test
import (
"fmt"
"time"
"github.com/tendermint/tendermint/crypto/tmhash"
tmtypes "github.com/tendermint/tendermint/types"
"github.com/cosmos/cosmos-sdk/simapp"
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
"github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
)
func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
altPrivVal := tmtypes.NewMockPV()
altPubKey, err := altPrivVal.GetPubKey()
suite.Require().NoError(err)
altVal := tmtypes.NewValidator(altPubKey, 4)
// Create bothValSet with both suite validator and altVal
bothValSet := tmtypes.NewValidatorSet(append(suite.valSet.Validators, altVal))
bothValsHash := bothValSet.Hash()
// Create alternative validator set with only altVal
altValSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{altVal})
_, suiteVal := suite.valSet.GetByIndex(0)
// Create signer array and ensure it is in same order as bothValSet
bothSigners := types.CreateSortedSignerArray(altPrivVal, suite.privVal, altVal, suiteVal)
altSigners := []tmtypes.PrivValidator{altPrivVal}
testCases := []struct {
name string
clientState clientexported.ClientState
consensusState1 clientexported.ConsensusState
consensusState2 clientexported.ConsensusState
misbehaviour clientexported.Misbehaviour
timestamp time.Time
expPass bool
}{
{
"valid misbehavior misbehaviour",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Misbehaviour{
Header1: types.CreateTestHeader(chainID, height, height, suite.now, bothValSet, bothValSet, bothSigners),
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
ChainId: chainID,
ClientId: chainID,
},
suite.now,
true,
},
{
"valid misbehavior at height greater than last consensusState",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height-1, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height-1, bothValsHash),
&types.Misbehaviour{
Header1: types.CreateTestHeader(chainID, height, height-1, suite.now, bothValSet, bothValSet, bothSigners),
Header2: types.CreateTestHeader(chainID, height, height-1, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
ChainId: chainID,
ClientId: chainID,
},
suite.now,
true,
},
{
"valid misbehavior misbehaviour with different trusted heights",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height-1, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height-3, suite.valsHash),
&types.Misbehaviour{
Header1: types.CreateTestHeader(chainID, height, height-1, suite.now, bothValSet, bothValSet, bothSigners),
Header2: types.CreateTestHeader(chainID, height, height-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()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, suite.valsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, suite.valsHash),
&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,
ClientId: chainID,
},
suite.now,
true,
},
{
"invalid misbehavior misbehaviour with trusted height different from trusted consensus state",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height-1, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height-3, suite.valsHash),
&types.Misbehaviour{
Header1: types.CreateTestHeader(chainID, height, height-1, suite.now, bothValSet, bothValSet, bothSigners),
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), bothValSet, suite.valSet, bothSigners),
ChainId: chainID,
ClientId: chainID,
},
suite.now,
false,
},
{
"invalid misbehavior misbehaviour with trusted validators different from trusted consensus state",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height-1, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height-3, suite.valsHash),
&types.Misbehaviour{
Header1: types.CreateTestHeader(chainID, height, height-1, suite.now, bothValSet, bothValSet, bothSigners),
Header2: types.CreateTestHeader(chainID, height, height-3, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
ChainId: chainID,
ClientId: chainID,
},
suite.now,
false,
},
{
"already frozen client state",
types.ClientState{FrozenHeight: 1},
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Misbehaviour{
Header1: types.CreateTestHeader(chainID, height, height, suite.now, bothValSet, bothValSet, bothSigners),
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
ChainId: chainID,
ClientId: chainID,
},
suite.now,
false,
},
{
"trusted consensus state does not exist",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
nil, // consensus state for trusted height - 1 does not exist in store
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Misbehaviour{
Header1: types.CreateTestHeader(chainID, height, height-1, suite.now, bothValSet, bothValSet, bothSigners),
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
ChainId: chainID,
ClientId: chainID,
},
suite.now,
false,
},
{
"invalid tendermint misbehaviour misbehaviour",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
nil,
suite.now,
false,
},
{
"rejected misbehaviour due to expired age duration",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Misbehaviour{
Header1: types.CreateTestHeader(chainID, height, height, suite.now, bothValSet, bothValSet, bothSigners),
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
ChainId: chainID,
ClientId: chainID,
},
suite.now.Add(2 * time.Minute).Add(simapp.DefaultConsensusParams.Evidence.MaxAgeDuration),
false,
},
{
"rejected misbehaviour due to expired block duration",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, uint64(height+simapp.DefaultConsensusParams.Evidence.MaxAgeNumBlocks+1), commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Misbehaviour{
Header1: types.CreateTestHeader(chainID, height, height, suite.now, bothValSet, bothValSet, bothSigners),
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
ChainId: chainID,
ClientId: chainID,
},
suite.now.Add(time.Hour),
false,
},
{
"provided height > header height",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Misbehaviour{
Header1: types.CreateTestHeader(chainID, height, height-1, suite.now, bothValSet, bothValSet, bothSigners),
Header2: types.CreateTestHeader(chainID, height, height-1, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
ChainId: chainID,
ClientId: chainID,
},
suite.now,
false,
},
{
"unbonding period expired",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
&types.ConsensusState{Timestamp: time.Time{}, Root: commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), NextValidatorsHash: bothValsHash},
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Misbehaviour{
Header1: types.CreateTestHeader(chainID, height, height, suite.now, bothValSet, bothValSet, bothSigners),
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
ChainId: chainID,
ClientId: chainID,
},
suite.now.Add(ubdPeriod),
false,
},
{
"trusted validators is incorrect for given consensus state",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&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,
ClientId: chainID,
},
suite.now,
false,
},
{
"first valset has too much change",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Misbehaviour{
Header1: types.CreateTestHeader(chainID, height, height, suite.now, altValSet, bothValSet, altSigners),
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
ChainId: chainID,
ClientId: chainID,
},
suite.now,
false,
},
{
"second valset has too much change",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Misbehaviour{
Header1: types.CreateTestHeader(chainID, height, height, suite.now, bothValSet, bothValSet, bothSigners),
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), altValSet, bothValSet, altSigners),
ChainId: chainID,
ClientId: chainID,
},
suite.now,
false,
},
{
"both valsets have too much change",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Misbehaviour{
Header1: types.CreateTestHeader(chainID, height, height, suite.now, altValSet, bothValSet, altSigners),
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), altValSet, bothValSet, altSigners),
ChainId: chainID,
ClientId: chainID,
},
suite.now,
false,
},
}
for i, tc := range testCases {
tc := tc
suite.Run(fmt.Sprintf("Case: %s", tc.name), func() {
// reset suite to create fresh application state
suite.SetupTest()
// Set current timestamp in context
ctx := suite.chainA.GetContext().WithBlockTime(tc.timestamp)
ctx = ctx.WithConsensusParams(simapp.DefaultConsensusParams)
// Set trusted consensus states in client store
if tc.consensusState1 != nil {
suite.chainA.App.IBCKeeper.ClientKeeper.SetClientConsensusState(ctx, clientID, tc.consensusState1.GetHeight(), tc.consensusState1)
}
if tc.consensusState2 != nil {
suite.chainA.App.IBCKeeper.ClientKeeper.SetClientConsensusState(ctx, clientID, tc.consensusState2.GetHeight(), tc.consensusState2)
}
clientState, err := tc.clientState.CheckMisbehaviourAndUpdateState(
ctx,
suite.cdc,
suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(ctx, clientID), // pass in clientID prefixed clientStore
tc.misbehaviour,
)
if tc.expPass {
suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
suite.Require().NotNil(clientState, "valid test case %d failed: %s", i, tc.name)
suite.Require().True(clientState.IsFrozen(), "valid test case %d failed: %s", i, tc.name)
suite.Require().Equal(uint64(tc.misbehaviour.GetHeight()), clientState.GetFrozenHeight(),
"valid test case %d failed: %s. Expected FrozenHeight %d got %d", tc.misbehaviour.GetHeight(), clientState.GetFrozenHeight())
} else {
suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
suite.Require().Nil(clientState, "invalid test case %d passed: %s", i, tc.name)
}
})
}
}

View File

@ -1,318 +1,265 @@
package types_test
import (
"fmt"
"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"
"github.com/cosmos/cosmos-sdk/simapp"
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
"github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment/types"
)
func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() {
func (suite *TendermintTestSuite) TestEvidence() {
signers := []tmtypes.PrivValidator{suite.privVal}
misbehaviour := &types.Misbehaviour{
Header1: suite.header,
Header2: types.CreateTestHeader(chainID, height, height-1, suite.now, suite.valSet, suite.valSet, signers),
ChainId: chainID,
ClientId: clientID,
}
suite.Require().Equal(misbehaviour.ClientType(), clientexported.Tendermint)
suite.Require().Equal(misbehaviour.GetClientID(), clientID)
suite.Require().Equal(misbehaviour.Route(), "client")
suite.Require().Equal(misbehaviour.Type(), "client_misbehaviour")
suite.Require().Equal(misbehaviour.Hash(), tmbytes.HexBytes(tmhash.Sum(suite.cdc.MustMarshalBinaryBare(misbehaviour))))
suite.Require().Equal(misbehaviour.GetHeight(), int64(height))
}
func (suite *TendermintTestSuite) TestEvidenceValidateBasic() {
altPrivVal := tmtypes.NewMockPV()
altPubKey, err := altPrivVal.GetPubKey()
suite.Require().NoError(err)
altVal := tmtypes.NewValidator(altPubKey, 4)
altVal := tmtypes.NewValidator(altPubKey, height)
// Create bothValSet with both suite validator and altVal
bothValSet := tmtypes.NewValidatorSet(append(suite.valSet.Validators, altVal))
bothValsHash := bothValSet.Hash()
// Create alternative validator set with only altVal
altValSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{altVal})
_, suiteVal := suite.valSet.GetByIndex(0)
signers := []tmtypes.PrivValidator{suite.privVal}
// Create signer array and ensure it is in same order as bothValSet
_, suiteVal := suite.valSet.GetByIndex(0)
bothSigners := types.CreateSortedSignerArray(altPrivVal, suite.privVal, altVal, suiteVal)
altSigners := []tmtypes.PrivValidator{altPrivVal}
testCases := []struct {
name string
clientState clientexported.ClientState
consensusState1 clientexported.ConsensusState
consensusState2 clientexported.ConsensusState
evidence clientexported.Misbehaviour
timestamp time.Time
expPass bool
name string
misbehaviour *types.Misbehaviour
malleateMisbehaviour func(misbehaviour *types.Misbehaviour) error
expPass bool
}{
{
"valid misbehavior evidence",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Evidence{
Header1: types.CreateTestHeader(chainID, height, height, suite.now, bothValSet, bothValSet, bothSigners),
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
"valid misbehaviour",
&types.Misbehaviour{
Header1: suite.header,
Header2: types.CreateTestHeader(chainID, height, height-1, suite.now.Add(time.Minute), suite.valSet, suite.valSet, signers),
ChainId: chainID,
ClientId: chainID,
ClientId: clientID,
},
suite.now,
func(misbehaviour *types.Misbehaviour) error { return nil },
true,
},
{
"valid misbehavior at height greater than last consensusState",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height-1, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height-1, bothValsHash),
&types.Evidence{
Header1: types.CreateTestHeader(chainID, height, height-1, suite.now, bothValSet, bothValSet, bothSigners),
Header2: types.CreateTestHeader(chainID, height, height-1, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
"misbehaviour Header1 is nil",
types.NewMisbehaviour(clientID, chainID, nil, suite.header),
func(m *types.Misbehaviour) error { return nil },
false,
},
{
"misbehaviour Header2 is nil",
types.NewMisbehaviour(clientID, chainID, suite.header, nil),
func(m *types.Misbehaviour) error { return nil },
false,
},
{
"valid misbehaviour with different trusted headers",
&types.Misbehaviour{
Header1: suite.header,
Header2: types.CreateTestHeader(chainID, height, height-3, suite.now.Add(time.Minute), suite.valSet, bothValSet, signers),
ChainId: chainID,
ClientId: chainID,
ClientId: clientID,
},
suite.now,
func(misbehaviour *types.Misbehaviour) error { return nil },
true,
},
{
"valid misbehavior evidence with different trusted heights",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height-1, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height-3, suite.valsHash),
&types.Evidence{
Header1: types.CreateTestHeader(chainID, height, height-1, suite.now, bothValSet, bothValSet, bothSigners),
Header2: types.CreateTestHeader(chainID, height, height-3, suite.now.Add(time.Minute), bothValSet, suite.valSet, bothSigners),
"trusted height is 0 in Header1",
&types.Misbehaviour{
Header1: types.CreateTestHeader(chainID, height, 0, suite.now.Add(time.Minute), suite.valSet, suite.valSet, signers),
Header2: suite.header,
ChainId: chainID,
ClientId: chainID,
ClientId: clientID,
},
suite.now,
true,
},
{
"consensus state's valset hash different from evidence should still pass",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, suite.valsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, suite.valsHash),
&types.Evidence{
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,
ClientId: chainID,
},
suite.now,
true,
},
{
"invalid misbehavior evidence with trusted height different from trusted consensus state",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height-1, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height-3, suite.valsHash),
&types.Evidence{
Header1: types.CreateTestHeader(chainID, height, height-1, suite.now, bothValSet, bothValSet, bothSigners),
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), bothValSet, suite.valSet, bothSigners),
ChainId: chainID,
ClientId: chainID,
},
suite.now,
func(misbehaviour *types.Misbehaviour) error { return nil },
false,
},
{
"invalid misbehavior evidence with trusted validators different from trusted consensus state",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height-1, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height-3, suite.valsHash),
&types.Evidence{
Header1: types.CreateTestHeader(chainID, height, height-1, suite.now, bothValSet, bothValSet, bothSigners),
Header2: types.CreateTestHeader(chainID, height, height-3, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
"trusted height is 0 in Header2",
&types.Misbehaviour{
Header1: suite.header,
Header2: types.CreateTestHeader(chainID, height, 0, suite.now.Add(time.Minute), suite.valSet, suite.valSet, signers),
ChainId: chainID,
ClientId: chainID,
ClientId: clientID,
},
suite.now,
func(misbehaviour *types.Misbehaviour) error { return nil },
false,
},
{
"already frozen client state",
types.ClientState{FrozenHeight: 1},
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Evidence{
Header1: types.CreateTestHeader(chainID, height, height, suite.now, bothValSet, bothValSet, bothSigners),
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
"trusted valset is nil in Header1",
&types.Misbehaviour{
Header1: types.CreateTestHeader(chainID, height, height-1, suite.now.Add(time.Minute), suite.valSet, nil, signers),
Header2: suite.header,
ChainId: chainID,
ClientId: chainID,
ClientId: clientID,
},
suite.now,
func(misbehaviour *types.Misbehaviour) error { return nil },
false,
},
{
"trusted consensus state does not exist",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
nil, // consensus state for trusted height - 1 does not exist in store
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Evidence{
Header1: types.CreateTestHeader(chainID, height, height-1, suite.now, bothValSet, bothValSet, bothSigners),
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
"trusted valset is nil in Header2",
&types.Misbehaviour{
Header1: suite.header,
Header2: types.CreateTestHeader(chainID, height, height-1, suite.now.Add(time.Minute), suite.valSet, nil, signers),
ChainId: chainID,
ClientId: chainID,
ClientId: clientID,
},
suite.now,
func(misbehaviour *types.Misbehaviour) error { return nil },
false,
},
{
"invalid tendermint misbehaviour evidence",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
nil,
suite.now,
"invalid client ID ",
&types.Misbehaviour{
Header1: suite.header,
Header2: types.CreateTestHeader(chainID, height, height-1, suite.now, suite.valSet, suite.valSet, signers),
ChainId: chainID,
ClientId: "GAIA",
},
func(misbehaviour *types.Misbehaviour) error { return nil },
false,
},
{
"rejected misbehaviour due to expired age duration",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Evidence{
Header1: types.CreateTestHeader(chainID, height, height, suite.now, bothValSet, bothValSet, bothSigners),
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
ChainId: chainID,
ClientId: chainID,
"wrong chainID on header1",
&types.Misbehaviour{
Header1: suite.header,
Header2: types.CreateTestHeader("ethermint", height, height-1, suite.now, suite.valSet, suite.valSet, signers),
ChainId: "ethermint",
ClientId: clientID,
},
suite.now.Add(2 * time.Minute).Add(simapp.DefaultConsensusParams.Evidence.MaxAgeDuration),
func(misbehaviour *types.Misbehaviour) error { return nil },
false,
},
{
"rejected misbehaviour due to expired block duration",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, uint64(height+simapp.DefaultConsensusParams.Evidence.MaxAgeNumBlocks+1), commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Evidence{
Header1: types.CreateTestHeader(chainID, height, height, suite.now, bothValSet, bothValSet, bothSigners),
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
"wrong chainID on header2",
&types.Misbehaviour{
Header1: suite.header,
Header2: types.CreateTestHeader("ethermint", height, height-1, suite.now, suite.valSet, suite.valSet, signers),
ChainId: chainID,
ClientId: chainID,
ClientId: clientID,
},
suite.now.Add(time.Hour),
func(misbehaviour *types.Misbehaviour) error { return nil },
false,
},
{
"provided height > header height",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Evidence{
Header1: types.CreateTestHeader(chainID, height, height-1, suite.now, bothValSet, bothValSet, bothSigners),
Header2: types.CreateTestHeader(chainID, height, height-1, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
"mismatched heights",
&types.Misbehaviour{
Header1: suite.header,
Header2: types.CreateTestHeader(chainID, 6, 4, suite.now, suite.valSet, suite.valSet, signers),
ChainId: chainID,
ClientId: chainID,
ClientId: clientID,
},
suite.now,
func(misbehaviour *types.Misbehaviour) error { return nil },
false,
},
{
"unbonding period expired",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
&types.ConsensusState{Timestamp: time.Time{}, Root: commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), NextValidatorsHash: bothValsHash},
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Evidence{
Header1: types.CreateTestHeader(chainID, height, height, suite.now, bothValSet, bothValSet, bothSigners),
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
"same block id",
&types.Misbehaviour{
Header1: suite.header,
Header2: suite.header,
ChainId: chainID,
ClientId: chainID,
ClientId: clientID,
},
suite.now.Add(ubdPeriod),
func(misbehaviour *types.Misbehaviour) error { return nil },
false,
},
{
"trusted validators is incorrect for given consensus state",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Evidence{
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),
"header 1 doesn't have 2/3 majority",
&types.Misbehaviour{
Header1: types.CreateTestHeader(chainID, height, height-1, suite.now, bothValSet, suite.valSet, bothSigners),
Header2: suite.header,
ChainId: chainID,
ClientId: chainID,
ClientId: clientID,
},
func(misbehaviour *types.Misbehaviour) error {
// voteSet contains only altVal which is less than 2/3 of total power (height/1height)
wrongVoteSet := tmtypes.NewVoteSet(chainID, int64(misbehaviour.Header1.GetHeight()), 1, tmproto.PrecommitType, altValSet)
blockID, err := tmtypes.BlockIDFromProto(&misbehaviour.Header1.Commit.BlockID)
if err != nil {
return err
}
tmCommit, err := tmtypes.MakeCommit(*blockID, int64(misbehaviour.Header2.GetHeight()), misbehaviour.Header1.Commit.Round, wrongVoteSet, altSigners, suite.now)
misbehaviour.Header1.Commit = tmCommit.ToProto()
return err
},
suite.now,
false,
},
{
"first valset has too much change",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Evidence{
Header1: types.CreateTestHeader(chainID, height, height, suite.now, altValSet, bothValSet, altSigners),
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners),
"header 2 doesn't have 2/3 majority",
&types.Misbehaviour{
Header1: suite.header,
Header2: types.CreateTestHeader(chainID, height, height-1, suite.now, bothValSet, suite.valSet, bothSigners),
ChainId: chainID,
ClientId: chainID,
ClientId: clientID,
},
func(misbehaviour *types.Misbehaviour) error {
// voteSet contains only altVal which is less than 2/3 of total power (height/1height)
wrongVoteSet := tmtypes.NewVoteSet(chainID, int64(misbehaviour.Header2.GetHeight()), 1, tmproto.PrecommitType, altValSet)
blockID, err := tmtypes.BlockIDFromProto(&misbehaviour.Header2.Commit.BlockID)
if err != nil {
return err
}
tmCommit, err := tmtypes.MakeCommit(*blockID, int64(misbehaviour.Header2.GetHeight()), misbehaviour.Header2.Commit.Round, wrongVoteSet, altSigners, suite.now)
misbehaviour.Header2.Commit = tmCommit.ToProto()
return err
},
suite.now,
false,
},
{
"second valset has too much change",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Evidence{
Header1: types.CreateTestHeader(chainID, height, height, suite.now, bothValSet, bothValSet, bothSigners),
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), altValSet, bothValSet, altSigners),
"validators sign off on wrong commit",
&types.Misbehaviour{
Header1: suite.header,
Header2: types.CreateTestHeader(chainID, height, height-1, suite.now, bothValSet, suite.valSet, bothSigners),
ChainId: chainID,
ClientId: chainID,
ClientId: clientID,
},
suite.now,
false,
},
{
"both valsets have too much change",
types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), height, bothValsHash),
&types.Evidence{
Header1: types.CreateTestHeader(chainID, height, height, suite.now, altValSet, bothValSet, altSigners),
Header2: types.CreateTestHeader(chainID, height, height, suite.now.Add(time.Minute), altValSet, bothValSet, altSigners),
ChainId: chainID,
ClientId: chainID,
func(misbehaviour *types.Misbehaviour) error {
tmBlockID := types.MakeBlockID(tmhash.Sum([]byte("other_hash")), 3, tmhash.Sum([]byte("other_partset")))
misbehaviour.Header2.Commit.BlockID = tmBlockID.ToProto()
return nil
},
suite.now,
false,
},
}
for i, tc := range testCases {
tc := tc
suite.Run(fmt.Sprintf("Case: %s", tc.name), func() {
// reset suite to create fresh application state
suite.SetupTest()
// Set current timestamp in context
ctx := suite.chainA.GetContext().WithBlockTime(tc.timestamp)
ctx = ctx.WithConsensusParams(simapp.DefaultConsensusParams)
err := tc.malleateMisbehaviour(tc.misbehaviour)
suite.Require().NoError(err)
// Set trusted consensus states in client store
if tc.consensusState1 != nil {
suite.chainA.App.IBCKeeper.ClientKeeper.SetClientConsensusState(ctx, clientID, tc.consensusState1.GetHeight(), tc.consensusState1)
}
if tc.consensusState2 != nil {
suite.chainA.App.IBCKeeper.ClientKeeper.SetClientConsensusState(ctx, clientID, tc.consensusState2.GetHeight(), tc.consensusState2)
}
clientState, err := tc.clientState.CheckMisbehaviourAndUpdateState(
ctx,
suite.cdc,
suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(ctx, clientID), // pass in clientID prefixed clientStore
tc.evidence,
)
if tc.expPass {
suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name)
suite.Require().NotNil(clientState, "valid test case %d failed: %s", i, tc.name)
suite.Require().True(clientState.IsFrozen(), "valid test case %d failed: %s", i, tc.name)
suite.Require().Equal(uint64(tc.evidence.GetHeight()), clientState.GetFrozenHeight(),
"valid test case %d failed: %s. Expected FrozenHeight %d got %d", tc.evidence.GetHeight(), clientState.GetFrozenHeight())
} else {
suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name)
suite.Require().Nil(clientState, "invalid test case %d passed: %s", i, tc.name)
}
})
if tc.expPass {
suite.Require().NoError(tc.misbehaviour.ValidateBasic(), "valid test case %d failed: %s", i, tc.name)
} else {
suite.Require().Error(tc.misbehaviour.ValidateBasic(), "invalid test case %d passed: %s", i, tc.name)
}
}
}

View File

@ -186,8 +186,8 @@ func (msg MsgUpdateClient) GetHeader() clientexported.Header {
// NewMsgSubmitClientMisbehaviour creates a new MsgSubmitClientMisbehaviour
// instance.
func NewMsgSubmitClientMisbehaviour(e *Evidence, s sdk.AccAddress) *MsgSubmitClientMisbehaviour {
return &MsgSubmitClientMisbehaviour{Evidence: e, Submitter: s}
func NewMsgSubmitClientMisbehaviour(m *Misbehaviour, s sdk.AccAddress) *MsgSubmitClientMisbehaviour {
return &MsgSubmitClientMisbehaviour{Misbehaviour: m, Submitter: s}
}
// Route returns the MsgSubmitClientMisbehaviour's route.
@ -200,10 +200,10 @@ func (msg MsgSubmitClientMisbehaviour) Type() string {
// ValidateBasic performs basic (non-state-dependant) validation on a MsgSubmitClientMisbehaviour.
func (msg MsgSubmitClientMisbehaviour) ValidateBasic() error {
if msg.Evidence == nil {
if msg.Misbehaviour == nil {
return sdkerrors.Wrap(evidencetypes.ErrInvalidEvidence, "missing evidence")
}
if err := msg.Evidence.ValidateBasic(); err != nil {
if err := msg.Misbehaviour.ValidateBasic(); err != nil {
return err
}
if msg.Submitter.Empty() {
@ -225,7 +225,7 @@ func (msg MsgSubmitClientMisbehaviour) GetSigners() []sdk.AccAddress {
}
func (msg MsgSubmitClientMisbehaviour) GetEvidence() evidenceexported.Evidence {
return msg.Evidence
return msg.Misbehaviour
}
func (msg MsgSubmitClientMisbehaviour) GetSubmitter() sdk.AccAddress {

View File

@ -131,26 +131,26 @@ func (m *ConsensusState) XXX_DiscardUnknown() {
var xxx_messageInfo_ConsensusState proto.InternalMessageInfo
// Evidence is a wrapper over two conflicting Headers
// that implements Evidence interface expected by ICS-02
type Evidence struct {
// Misbehaviour is a wrapper over two conflicting Headers
// that implements Misbehaviour interface expected by ICS-02
type Misbehaviour struct {
ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"`
ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty" yaml:"chain_id"`
Header1 *Header `protobuf:"bytes,3,opt,name=header_1,json=header1,proto3" json:"header_1,omitempty" yaml:"header_1"`
Header2 *Header `protobuf:"bytes,4,opt,name=header_2,json=header2,proto3" json:"header_2,omitempty" yaml:"header_2"`
}
func (m *Evidence) Reset() { *m = Evidence{} }
func (*Evidence) ProtoMessage() {}
func (*Evidence) Descriptor() ([]byte, []int) {
func (m *Misbehaviour) Reset() { *m = Misbehaviour{} }
func (*Misbehaviour) ProtoMessage() {}
func (*Misbehaviour) Descriptor() ([]byte, []int) {
return fileDescriptor_76a953d5a747dd66, []int{2}
}
func (m *Evidence) XXX_Unmarshal(b []byte) error {
func (m *Misbehaviour) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *Evidence) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
func (m *Misbehaviour) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_Evidence.Marshal(b, m, deterministic)
return xxx_messageInfo_Misbehaviour.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
@ -160,17 +160,17 @@ func (m *Evidence) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return b[:n], nil
}
}
func (m *Evidence) XXX_Merge(src proto.Message) {
xxx_messageInfo_Evidence.Merge(m, src)
func (m *Misbehaviour) XXX_Merge(src proto.Message) {
xxx_messageInfo_Misbehaviour.Merge(m, src)
}
func (m *Evidence) XXX_Size() int {
func (m *Misbehaviour) XXX_Size() int {
return m.Size()
}
func (m *Evidence) XXX_DiscardUnknown() {
xxx_messageInfo_Evidence.DiscardUnknown(m)
func (m *Misbehaviour) XXX_DiscardUnknown() {
xxx_messageInfo_Misbehaviour.DiscardUnknown(m)
}
var xxx_messageInfo_Evidence proto.InternalMessageInfo
var xxx_messageInfo_Misbehaviour proto.InternalMessageInfo
// Header defines the Tendermint client consensus Header.
// It encapsulates all the information necessary to update from a trusted
@ -387,8 +387,8 @@ var xxx_messageInfo_MsgUpdateClient proto.InternalMessageInfo
// MsgSubmitClientMisbehaviour defines an sdk.Msg type that submits Evidence for
// light client misbehaviour.
type MsgSubmitClientMisbehaviour struct {
Evidence *Evidence `protobuf:"bytes,1,opt,name=evidence,proto3" json:"evidence,omitempty"`
Submitter github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,2,opt,name=submitter,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"submitter,omitempty"`
Misbehaviour *Misbehaviour `protobuf:"bytes,1,opt,name=misbehaviour,proto3" json:"misbehaviour,omitempty"`
Submitter github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,2,opt,name=submitter,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"submitter,omitempty"`
}
func (m *MsgSubmitClientMisbehaviour) Reset() { *m = MsgSubmitClientMisbehaviour{} }
@ -427,7 +427,7 @@ var xxx_messageInfo_MsgSubmitClientMisbehaviour proto.InternalMessageInfo
func init() {
proto.RegisterType((*ClientState)(nil), "ibc.tendermint.ClientState")
proto.RegisterType((*ConsensusState)(nil), "ibc.tendermint.ConsensusState")
proto.RegisterType((*Evidence)(nil), "ibc.tendermint.Evidence")
proto.RegisterType((*Misbehaviour)(nil), "ibc.tendermint.Misbehaviour")
proto.RegisterType((*Header)(nil), "ibc.tendermint.Header")
proto.RegisterType((*Fraction)(nil), "ibc.tendermint.Fraction")
proto.RegisterType((*MsgCreateClient)(nil), "ibc.tendermint.MsgCreateClient")
@ -438,76 +438,76 @@ func init() {
func init() { proto.RegisterFile("ibc/tendermint/tendermint.proto", fileDescriptor_76a953d5a747dd66) }
var fileDescriptor_76a953d5a747dd66 = []byte{
// 1103 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0xcf, 0x4f, 0xe3, 0xc6,
0x17, 0xc7, 0x21, 0x84, 0x30, 0x09, 0x3f, 0xbe, 0xb3, 0x7c, 0x69, 0x60, 0x69, 0x1c, 0xb9, 0x17,
0x2e, 0x38, 0x25, 0x8b, 0x5a, 0x09, 0xa9, 0x52, 0xd7, 0x6c, 0x2b, 0xa8, 0x8a, 0x4a, 0x87, 0x6e,
0x2b, 0x55, 0xaa, 0x2c, 0xc7, 0x9e, 0x24, 0x23, 0x6c, 0x4f, 0xe4, 0x99, 0x20, 0xe8, 0x5f, 0xb0,
0xbd, 0xed, 0x71, 0x2f, 0x95, 0xda, 0x6b, 0xcf, 0xfd, 0x17, 0x2a, 0xed, 0x91, 0x63, 0x4f, 0x6e,
0x05, 0xff, 0x41, 0x8e, 0x9c, 0x2a, 0xcf, 0x8c, 0x7f, 0x24, 0xa0, 0xdd, 0x76, 0xb5, 0xcb, 0x05,
0x66, 0xde, 0x8f, 0xcf, 0x9b, 0xf7, 0xf2, 0x79, 0xef, 0x19, 0xe8, 0xa4, 0xeb, 0xb6, 0x39, 0x0e,
0x3d, 0x1c, 0x05, 0x24, 0xe4, 0x85, 0xa3, 0x39, 0x8c, 0x28, 0xa7, 0x70, 0x89, 0x74, 0x5d, 0x33,
0x97, 0x6e, 0xb4, 0x8a, 0xc6, 0x17, 0x43, 0xcc, 0xda, 0x67, 0x8e, 0x4f, 0x3c, 0x87, 0xd3, 0x48,
0x7a, 0x6c, 0x6c, 0xde, 0xb2, 0x10, 0x7f, 0x95, 0xf6, 0x81, 0x4b, 0xc3, 0x1e, 0xa1, 0xed, 0x61,
0x44, 0x69, 0x2f, 0x15, 0x36, 0xfb, 0x94, 0xf6, 0x7d, 0xdc, 0x16, 0xb7, 0xee, 0xa8, 0xd7, 0xf6,
0x46, 0x91, 0xc3, 0x09, 0x0d, 0x95, 0x5e, 0x9f, 0xd6, 0x73, 0x12, 0x60, 0xc6, 0x9d, 0x60, 0x98,
0x1a, 0x24, 0x69, 0xb8, 0x34, 0x08, 0x08, 0x0f, 0x70, 0xc8, 0x0b, 0x47, 0x65, 0xb0, 0xda, 0xa7,
0x7d, 0x2a, 0x8e, 0xed, 0xe4, 0x24, 0xa5, 0xc6, 0xb3, 0x39, 0x50, 0xdb, 0xf7, 0x09, 0x0e, 0xf9,
0x09, 0x77, 0x38, 0x86, 0xeb, 0xa0, 0xea, 0x0e, 0x1c, 0x12, 0xda, 0xc4, 0x6b, 0x68, 0x2d, 0x6d,
0x6b, 0x01, 0xcd, 0x8b, 0xfb, 0xa1, 0x07, 0x9f, 0x82, 0x1a, 0x8f, 0x46, 0x8c, 0xdb, 0x3e, 0x3e,
0xc3, 0x7e, 0xa3, 0xd4, 0xd2, 0xb6, 0x6a, 0x9d, 0x86, 0x39, 0x59, 0x1d, 0xf3, 0xf3, 0xc8, 0x71,
0x93, 0x77, 0x5b, 0x1b, 0x2f, 0x63, 0x7d, 0x66, 0x1c, 0xeb, 0xf0, 0xc2, 0x09, 0xfc, 0x3d, 0xa3,
0xe0, 0x6a, 0x20, 0x20, 0x6e, 0x5f, 0x26, 0x17, 0xd8, 0x03, 0xcb, 0xe2, 0x46, 0xc2, 0xbe, 0x3d,
0xc4, 0x11, 0xa1, 0x5e, 0x63, 0x56, 0x40, 0xaf, 0x9b, 0x32, 0x67, 0x33, 0xcd, 0xd9, 0x7c, 0xa2,
0x6a, 0x62, 0x19, 0x0a, 0x7b, 0xad, 0x80, 0x9d, 0xfb, 0x1b, 0x2f, 0xfe, 0xd2, 0x35, 0xb4, 0x94,
0x4a, 0x8f, 0x85, 0x10, 0x12, 0xb0, 0x32, 0x0a, 0xbb, 0x34, 0xf4, 0x0a, 0x81, 0xca, 0xaf, 0x0b,
0xf4, 0x81, 0x0a, 0xf4, 0x9e, 0x0c, 0x34, 0x0d, 0x20, 0x23, 0x2d, 0x67, 0x62, 0x15, 0x0a, 0x83,
0xe5, 0xc0, 0x39, 0xb7, 0x5d, 0x9f, 0xba, 0xa7, 0xb6, 0x17, 0x91, 0x1e, 0x6f, 0xcc, 0xfd, 0xc7,
0x94, 0xa6, 0xfc, 0x65, 0xa0, 0xc5, 0xc0, 0x39, 0xdf, 0x4f, 0x84, 0x4f, 0x12, 0x19, 0xfc, 0x04,
0x2c, 0xf6, 0x22, 0xfa, 0x23, 0x0e, 0xed, 0x01, 0x26, 0xfd, 0x01, 0x6f, 0x54, 0x5a, 0xda, 0x56,
0xd9, 0x6a, 0x8c, 0x63, 0x7d, 0x55, 0xa2, 0x4c, 0xa8, 0x0d, 0x54, 0x97, 0xf7, 0x03, 0x71, 0x4d,
0xdc, 0x7d, 0x87, 0x63, 0xc6, 0x53, 0xf7, 0xf9, 0x69, 0xf7, 0x09, 0xb5, 0x81, 0xea, 0xf2, 0xae,
0xdc, 0x0f, 0x41, 0x4d, 0x30, 0xd8, 0x66, 0x43, 0xec, 0xb2, 0x46, 0xb5, 0x35, 0xbb, 0x55, 0xeb,
0xac, 0x98, 0xc4, 0x65, 0x9d, 0x47, 0xe6, 0x71, 0xa2, 0x39, 0x19, 0x62, 0xd7, 0x5a, 0xcb, 0x29,
0x50, 0x30, 0x37, 0x10, 0x18, 0xa6, 0x26, 0x6c, 0xaf, 0xfc, 0xec, 0x17, 0x7d, 0xc6, 0xf8, 0xbd,
0x04, 0x96, 0xf6, 0x69, 0xc8, 0x70, 0xc8, 0x46, 0x4c, 0xb2, 0xd1, 0x02, 0x0b, 0x19, 0xcf, 0x05,
0x1d, 0x6b, 0x9d, 0x8d, 0x5b, 0x25, 0xfc, 0x26, 0xb5, 0xb0, 0xaa, 0x49, 0x0d, 0x9f, 0x27, 0x95,
0xca, 0xdd, 0xe0, 0x2e, 0x28, 0x47, 0x94, 0x72, 0xc5, 0xd7, 0x0d, 0xc1, 0xd7, 0x42, 0x73, 0x1c,
0xe1, 0xe8, 0xd4, 0xc7, 0x88, 0x52, 0x6e, 0x95, 0x13, 0x77, 0x24, 0xac, 0xe1, 0x1a, 0xa8, 0xa8,
0xaa, 0x24, 0x64, 0x2c, 0x23, 0x75, 0x83, 0x3f, 0x69, 0x60, 0x35, 0xc4, 0xe7, 0xdc, 0xce, 0x7a,
0x9e, 0xd9, 0x03, 0x87, 0x0d, 0x04, 0x95, 0xea, 0xd6, 0x77, 0xe3, 0x58, 0x7f, 0x28, 0xb3, 0xbd,
0xcb, 0xca, 0xb8, 0x89, 0xf5, 0xdd, 0x3e, 0xe1, 0x83, 0x51, 0x37, 0x79, 0xc3, 0xdd, 0x63, 0xa7,
0xed, 0x93, 0x2e, 0x6b, 0x77, 0x2f, 0x38, 0x66, 0xe6, 0x01, 0x3e, 0xb7, 0x92, 0x03, 0x82, 0x09,
0xdc, 0xb7, 0x19, 0xda, 0x81, 0xc3, 0x06, 0xaa, 0x6c, 0x3f, 0x97, 0x40, 0xf5, 0xb3, 0x33, 0xe2,
0xe1, 0xd0, 0xc5, 0x70, 0x07, 0x2c, 0xb8, 0xa2, 0x9b, 0xb3, 0xfe, 0xb5, 0x56, 0xc7, 0xb1, 0xbe,
0x22, 0x9f, 0x94, 0xa9, 0x0c, 0x54, 0x95, 0xe7, 0x43, 0x0f, 0x9a, 0x85, 0x8e, 0x2f, 0x09, 0x8f,
0x07, 0xe3, 0x58, 0x5f, 0x56, 0x1e, 0x4a, 0x63, 0xe4, 0x63, 0xe0, 0x6b, 0x50, 0x1d, 0x60, 0xc7,
0xc3, 0x91, 0xbd, 0xa3, 0x1a, 0x75, 0x6d, 0x7a, 0x06, 0x1c, 0x08, 0xbd, 0xd5, 0xbc, 0x8a, 0xf5,
0x79, 0x79, 0xde, 0xc9, 0x21, 0x53, 0x67, 0x03, 0xcd, 0xcb, 0xe3, 0x4e, 0x01, 0xb2, 0xa3, 0x5a,
0xf2, 0x5f, 0x40, 0x76, 0x6e, 0x41, 0x76, 0x32, 0xc8, 0xce, 0x5e, 0x35, 0xa9, 0xcd, 0x8b, 0xa4,
0x3e, 0x37, 0x25, 0x50, 0x91, 0x1e, 0xd0, 0x01, 0x8b, 0x8c, 0xf4, 0x43, 0xec, 0xd9, 0xd2, 0x4c,
0x51, 0xaa, 0x59, 0x0c, 0x24, 0x27, 0xf5, 0x89, 0x30, 0x53, 0x41, 0x37, 0x2f, 0x63, 0x5d, 0xcb,
0xbb, 0x62, 0x02, 0xc2, 0x40, 0x75, 0x56, 0xb0, 0x85, 0x3f, 0x80, 0xc5, 0xec, 0x37, 0xb7, 0x19,
0x4e, 0x69, 0x77, 0x47, 0x88, 0xec, 0xc7, 0x3c, 0xc1, 0xbc, 0xd8, 0x74, 0x13, 0xee, 0x06, 0xaa,
0x9f, 0x15, 0xec, 0xe0, 0xa7, 0x40, 0x8e, 0x35, 0x11, 0x3f, 0xa7, 0xa7, 0xb5, 0x3e, 0x8e, 0xf5,
0xff, 0x17, 0x86, 0x61, 0xa6, 0x37, 0xd0, 0xa2, 0x12, 0xa8, 0xb6, 0xf5, 0x01, 0x4c, 0x2d, 0x72,
0x72, 0xaa, 0xaa, 0xbf, 0xee, 0x95, 0xef, 0x8f, 0x63, 0x7d, 0x7d, 0x32, 0x4a, 0x8e, 0x61, 0xa0,
0xff, 0x29, 0x61, 0x4e, 0x53, 0xe3, 0x0b, 0x50, 0x4d, 0x17, 0x02, 0xdc, 0x04, 0x0b, 0xe1, 0x28,
0xc0, 0x51, 0xa2, 0x11, 0x95, 0x9f, 0x45, 0xb9, 0x00, 0xb6, 0x40, 0xcd, 0xc3, 0x21, 0x0d, 0x48,
0x28, 0xf4, 0x25, 0xa1, 0x2f, 0x8a, 0x8c, 0x5f, 0xe7, 0xc0, 0xf2, 0x11, 0xeb, 0xef, 0x47, 0xd8,
0xe1, 0x58, 0xee, 0xac, 0x37, 0xe3, 0x7b, 0x45, 0xfd, 0xfa, 0xa5, 0x57, 0x51, 0x0d, 0x29, 0xab,
0xe9, 0xb5, 0x37, 0xfb, 0xee, 0xd6, 0x5e, 0xf9, 0xbe, 0xd6, 0xde, 0xdc, 0xbd, 0xad, 0xbd, 0xca,
0x3b, 0x58, 0x7b, 0x6f, 0x6f, 0xf1, 0xc0, 0x43, 0x50, 0x11, 0xdd, 0x1b, 0x89, 0xdd, 0x57, 0xb7,
0x76, 0x6e, 0x62, 0x7d, 0xbb, 0x30, 0x9f, 0x5d, 0xca, 0x02, 0xca, 0xd4, 0xbf, 0x6d, 0xe6, 0x9d,
0xaa, 0x0f, 0xb9, 0xc7, 0xae, 0xfb, 0xd8, 0xf3, 0x22, 0xcc, 0x18, 0x52, 0x00, 0x6a, 0x18, 0xff,
0xa1, 0x09, 0x8e, 0x3e, 0x1d, 0x7a, 0xf7, 0xca, 0xd1, 0x3c, 0x8f, 0xd9, 0xb7, 0x93, 0xc7, 0x6f,
0x1a, 0x78, 0x78, 0xc4, 0xfa, 0x27, 0xa3, 0x6e, 0x40, 0xb8, 0xcc, 0xe3, 0x88, 0xb0, 0x2e, 0x1e,
0x38, 0x67, 0x84, 0x8e, 0x22, 0xb8, 0x0b, 0xaa, 0x58, 0xed, 0x1c, 0x35, 0x44, 0x6f, 0x75, 0x44,
0xba, 0x93, 0x50, 0x66, 0x09, 0xbf, 0x02, 0x0b, 0x4c, 0x20, 0x72, 0x95, 0xd9, 0x1b, 0xbd, 0x34,
0xc7, 0x90, 0x8f, 0xb5, 0x8e, 0x5f, 0x5e, 0x35, 0xb5, 0xcb, 0xab, 0xa6, 0xf6, 0xf7, 0x55, 0x53,
0x7b, 0x7e, 0xdd, 0x9c, 0xb9, 0xbc, 0x6e, 0xce, 0xfc, 0x79, 0xdd, 0x9c, 0xf9, 0xfe, 0xa3, 0x57,
0x22, 0x9f, 0xb7, 0x93, 0x6f, 0xe6, 0x0f, 0x3f, 0xde, 0x9e, 0xfe, 0x5c, 0xef, 0x56, 0x04, 0x51,
0x1f, 0xfd, 0x13, 0x00, 0x00, 0xff, 0xff, 0x59, 0x41, 0xd4, 0xdb, 0x1c, 0x0c, 0x00, 0x00,
// 1096 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0x4f, 0x4f, 0x1b, 0x47,
0x14, 0x67, 0x8d, 0x31, 0x66, 0x6c, 0xfe, 0x74, 0x42, 0xa9, 0x21, 0xd4, 0x6b, 0x6d, 0x2f, 0x5c,
0x58, 0x17, 0x27, 0x6a, 0x25, 0xa4, 0x4a, 0xc9, 0x12, 0x55, 0x50, 0x15, 0x95, 0x0e, 0x4d, 0x2b,
0x55, 0xaa, 0x56, 0xeb, 0xdd, 0xb1, 0x3d, 0x62, 0x77, 0xc7, 0xda, 0x19, 0x23, 0xe8, 0x27, 0x48,
0x6f, 0x39, 0xe6, 0xd8, 0x7c, 0x87, 0xaa, 0xdf, 0xa0, 0x52, 0x8e, 0x1c, 0x7b, 0xda, 0x56, 0xf0,
0x0d, 0x7c, 0xe4, 0x54, 0xed, 0xcc, 0xec, 0x1f, 0x1b, 0x94, 0x34, 0x51, 0xc2, 0x05, 0xe6, 0xfd,
0xfb, 0xbd, 0x99, 0xe7, 0xdf, 0x7b, 0x6f, 0x81, 0x4e, 0xba, 0x6e, 0x9b, 0xe3, 0xd0, 0xc3, 0x51,
0x40, 0x42, 0x5e, 0x38, 0x9a, 0xc3, 0x88, 0x72, 0x0a, 0x97, 0x48, 0xd7, 0x35, 0x73, 0xed, 0x46,
0xab, 0xe8, 0x7c, 0x3e, 0xc4, 0xac, 0x7d, 0xea, 0xf8, 0xc4, 0x73, 0x38, 0x8d, 0x64, 0xc4, 0xc6,
0xe6, 0x0d, 0x0f, 0xf1, 0x57, 0x59, 0xef, 0xb9, 0x34, 0xec, 0x11, 0xda, 0x1e, 0x46, 0x94, 0xf6,
0x52, 0x65, 0xb3, 0x4f, 0x69, 0xdf, 0xc7, 0x6d, 0x21, 0x75, 0x47, 0xbd, 0xb6, 0x37, 0x8a, 0x1c,
0x4e, 0x68, 0xa8, 0xec, 0xfa, 0xb4, 0x9d, 0x93, 0x00, 0x33, 0xee, 0x04, 0xc3, 0xd4, 0x21, 0x79,
0x86, 0x4b, 0x83, 0x80, 0xf0, 0x00, 0x87, 0xbc, 0x70, 0x54, 0x0e, 0xab, 0x7d, 0xda, 0xa7, 0xe2,
0xd8, 0x4e, 0x4e, 0x52, 0x6b, 0x3c, 0x9b, 0x03, 0xb5, 0x3d, 0x9f, 0xe0, 0x90, 0x1f, 0x73, 0x87,
0x63, 0xb8, 0x0e, 0xaa, 0xee, 0xc0, 0x21, 0xa1, 0x4d, 0xbc, 0x86, 0xd6, 0xd2, 0xb6, 0x16, 0xd0,
0xbc, 0x90, 0x0f, 0x3c, 0xf8, 0x14, 0xd4, 0x78, 0x34, 0x62, 0xdc, 0xf6, 0xf1, 0x29, 0xf6, 0x1b,
0xa5, 0x96, 0xb6, 0x55, 0xeb, 0x34, 0xcc, 0xc9, 0xea, 0x98, 0x5f, 0x47, 0x8e, 0x9b, 0xdc, 0xdb,
0xda, 0x78, 0x15, 0xeb, 0x33, 0xe3, 0x58, 0x87, 0xe7, 0x4e, 0xe0, 0xef, 0x1a, 0x85, 0x50, 0x03,
0x01, 0x21, 0x7d, 0x9b, 0x08, 0xb0, 0x07, 0x96, 0x85, 0x44, 0xc2, 0xbe, 0x3d, 0xc4, 0x11, 0xa1,
0x5e, 0x63, 0x56, 0x40, 0xaf, 0x9b, 0xf2, 0xcd, 0x66, 0xfa, 0x66, 0xf3, 0x89, 0xaa, 0x89, 0x65,
0x28, 0xec, 0xb5, 0x02, 0x76, 0x1e, 0x6f, 0xbc, 0xf8, 0x47, 0xd7, 0xd0, 0x52, 0xaa, 0x3d, 0x12,
0x4a, 0x48, 0xc0, 0xca, 0x28, 0xec, 0xd2, 0xd0, 0x2b, 0x24, 0x2a, 0xbf, 0x29, 0xd1, 0x67, 0x2a,
0xd1, 0x27, 0x32, 0xd1, 0x34, 0x80, 0xcc, 0xb4, 0x9c, 0xa9, 0x55, 0x2a, 0x0c, 0x96, 0x03, 0xe7,
0xcc, 0x76, 0x7d, 0xea, 0x9e, 0xd8, 0x5e, 0x44, 0x7a, 0xbc, 0x31, 0xf7, 0x96, 0x4f, 0x9a, 0x8a,
0x97, 0x89, 0x16, 0x03, 0xe7, 0x6c, 0x2f, 0x51, 0x3e, 0x49, 0x74, 0xf0, 0x2b, 0xb0, 0xd8, 0x8b,
0xe8, 0xaf, 0x38, 0xb4, 0x07, 0x98, 0xf4, 0x07, 0xbc, 0x51, 0x69, 0x69, 0x5b, 0x65, 0xab, 0x31,
0x8e, 0xf5, 0x55, 0x89, 0x32, 0x61, 0x36, 0x50, 0x5d, 0xca, 0xfb, 0x42, 0x4c, 0xc2, 0x7d, 0x87,
0x63, 0xc6, 0xd3, 0xf0, 0xf9, 0xe9, 0xf0, 0x09, 0xb3, 0x81, 0xea, 0x52, 0x56, 0xe1, 0x07, 0xa0,
0x26, 0x18, 0x6c, 0xb3, 0x21, 0x76, 0x59, 0xa3, 0xda, 0x9a, 0xdd, 0xaa, 0x75, 0x56, 0x4c, 0xe2,
0xb2, 0xce, 0x03, 0xf3, 0x28, 0xb1, 0x1c, 0x0f, 0xb1, 0x6b, 0xad, 0xe5, 0x14, 0x28, 0xb8, 0x1b,
0x08, 0x0c, 0x53, 0x17, 0xb6, 0x5b, 0x7e, 0xf6, 0xbb, 0x3e, 0x63, 0xfc, 0x51, 0x02, 0x4b, 0x7b,
0x34, 0x64, 0x38, 0x64, 0x23, 0x26, 0xd9, 0x68, 0x81, 0x85, 0x8c, 0xe7, 0x82, 0x8e, 0xb5, 0xce,
0xc6, 0x8d, 0x12, 0xfe, 0x90, 0x7a, 0x58, 0xd5, 0xa4, 0x86, 0xcf, 0x93, 0x4a, 0xe5, 0x61, 0xf0,
0x21, 0x28, 0x47, 0x94, 0x72, 0xc5, 0xd7, 0x0d, 0xc1, 0xd7, 0x42, 0x73, 0x1c, 0xe2, 0xe8, 0xc4,
0xc7, 0x88, 0x52, 0x6e, 0x95, 0x93, 0x70, 0x24, 0xbc, 0xe1, 0x1a, 0xa8, 0xa8, 0xaa, 0x24, 0x64,
0x2c, 0x23, 0x25, 0xc1, 0xdf, 0x34, 0xb0, 0x1a, 0xe2, 0x33, 0x6e, 0x67, 0x3d, 0xcf, 0xec, 0x81,
0xc3, 0x06, 0x82, 0x4a, 0x75, 0xeb, 0xa7, 0x71, 0xac, 0xdf, 0x97, 0xaf, 0xbd, 0xcd, 0xcb, 0xb8,
0x8e, 0xf5, 0x87, 0x7d, 0xc2, 0x07, 0xa3, 0x6e, 0x72, 0x87, 0xdb, 0xc7, 0x4e, 0xdb, 0x27, 0x5d,
0xd6, 0xee, 0x9e, 0x73, 0xcc, 0xcc, 0x7d, 0x7c, 0x66, 0x25, 0x07, 0x04, 0x13, 0xb8, 0x1f, 0x33,
0xb4, 0x7d, 0x87, 0x0d, 0x54, 0xd9, 0x5e, 0x96, 0x40, 0xfd, 0x90, 0xb0, 0x2e, 0x1e, 0x38, 0xa7,
0x84, 0x8e, 0x22, 0xb8, 0x03, 0x16, 0x5c, 0xd1, 0xd1, 0x59, 0x0f, 0x5b, 0xab, 0xe3, 0x58, 0x5f,
0x91, 0xd7, 0xca, 0x4c, 0x06, 0xaa, 0xca, 0xf3, 0x81, 0x07, 0xcd, 0x42, 0xd7, 0x97, 0x44, 0xc4,
0xbd, 0x71, 0xac, 0x2f, 0xab, 0x08, 0x65, 0x31, 0xf2, 0x51, 0xf0, 0x3d, 0xa8, 0x0e, 0xb0, 0xe3,
0xe1, 0xc8, 0xde, 0x51, 0xcd, 0xba, 0x36, 0x3d, 0x07, 0xf6, 0x85, 0xdd, 0x6a, 0x5e, 0xc6, 0xfa,
0xbc, 0x3c, 0xef, 0xe4, 0x90, 0x69, 0xb0, 0x81, 0xe6, 0xe5, 0x71, 0xa7, 0x00, 0xd9, 0x51, 0x6d,
0xf9, 0x3f, 0x20, 0x3b, 0x37, 0x20, 0x3b, 0x19, 0x64, 0x67, 0xb7, 0x9a, 0xd4, 0xe7, 0x45, 0x52,
0xa3, 0xeb, 0x12, 0xa8, 0xc8, 0x08, 0xe8, 0x80, 0x45, 0x46, 0xfa, 0x21, 0xf6, 0x6c, 0xe9, 0xa6,
0x68, 0xd5, 0x2c, 0x26, 0x92, 0xd3, 0xfa, 0x58, 0xb8, 0xa9, 0xa4, 0x9b, 0x17, 0xb1, 0xae, 0xe5,
0x9d, 0x31, 0x01, 0x61, 0xa0, 0x3a, 0x2b, 0xf8, 0xc2, 0x5f, 0xc0, 0x62, 0xf6, 0xbb, 0xdb, 0x0c,
0xa7, 0xd4, 0xbb, 0x25, 0x45, 0xf6, 0x83, 0x1e, 0x63, 0x5e, 0x6c, 0xbc, 0x89, 0x70, 0x03, 0xd5,
0x4f, 0x0b, 0x7e, 0xf0, 0x11, 0x90, 0xa3, 0x4d, 0xe4, 0xcf, 0x29, 0x6a, 0xad, 0x8f, 0x63, 0xfd,
0xe3, 0xc2, 0x40, 0xcc, 0xec, 0x06, 0x5a, 0x54, 0x0a, 0xd5, 0xba, 0x3e, 0x80, 0xa9, 0x47, 0x4e,
0x50, 0x55, 0xf5, 0x37, 0xdd, 0xf2, 0xd3, 0x71, 0xac, 0xaf, 0x4f, 0x66, 0xc9, 0x31, 0x0c, 0xf4,
0x91, 0x52, 0xe6, 0x54, 0x35, 0xbe, 0x01, 0xd5, 0x74, 0x29, 0xc0, 0x4d, 0xb0, 0x10, 0x8e, 0x02,
0x1c, 0x25, 0x16, 0x51, 0xf9, 0x59, 0x94, 0x2b, 0x60, 0x0b, 0xd4, 0x3c, 0x1c, 0xd2, 0x80, 0x84,
0xc2, 0x5e, 0x12, 0xf6, 0xa2, 0xca, 0x78, 0x39, 0x07, 0x96, 0x0f, 0x59, 0x7f, 0x2f, 0xc2, 0x0e,
0xc7, 0x72, 0x6f, 0xbd, 0x1b, 0xdf, 0x2b, 0xea, 0xd7, 0x2f, 0xbd, 0x8e, 0x6a, 0x48, 0x79, 0x4d,
0xaf, 0xbe, 0xd9, 0x0f, 0xb7, 0xfa, 0xca, 0x77, 0xb5, 0xfa, 0xe6, 0xee, 0x6c, 0xf5, 0x55, 0x3e,
0xc0, 0xea, 0x7b, 0x7f, 0xcb, 0x07, 0x1e, 0x80, 0x8a, 0xe8, 0xde, 0x48, 0xec, 0xbf, 0xba, 0xb5,
0x73, 0x1d, 0xeb, 0xdb, 0x85, 0x19, 0xed, 0x52, 0x16, 0x50, 0xa6, 0xfe, 0x6d, 0x33, 0xef, 0x44,
0x7d, 0xcc, 0x3d, 0x76, 0xdd, 0xc7, 0x9e, 0x17, 0x61, 0xc6, 0x90, 0x02, 0x50, 0x03, 0xf9, 0x2f,
0x4d, 0x70, 0xf4, 0xe9, 0xd0, 0xbb, 0x53, 0x8e, 0xe6, 0xef, 0x98, 0x7d, 0x3f, 0xef, 0xf8, 0x53,
0x03, 0xf7, 0x0f, 0x59, 0xff, 0x78, 0xd4, 0x0d, 0x08, 0x97, 0xef, 0x98, 0xd8, 0x33, 0x8f, 0x40,
0x3d, 0x28, 0xc8, 0x6a, 0x90, 0x6e, 0x4e, 0x5f, 0xb3, 0x18, 0x83, 0x26, 0x22, 0xe0, 0x77, 0x60,
0x81, 0x09, 0x74, 0xae, 0x5e, 0xf9, 0x4e, 0xb7, 0xce, 0x31, 0xe4, 0xc5, 0xad, 0xa3, 0x57, 0x97,
0x4d, 0xed, 0xe2, 0xb2, 0xa9, 0xfd, 0x7b, 0xd9, 0xd4, 0x9e, 0x5f, 0x35, 0x67, 0x2e, 0xae, 0x9a,
0x33, 0x7f, 0x5f, 0x35, 0x67, 0x7e, 0xfe, 0xe2, 0xb5, 0xc8, 0x67, 0xed, 0xe4, 0x1b, 0xfa, 0xf3,
0x2f, 0xb7, 0xa7, 0x3f, 0xdf, 0xbb, 0x15, 0x41, 0xda, 0x07, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff,
0xbf, 0xdb, 0xea, 0x9e, 0x2c, 0x0c, 0x00, 0x00,
}
func (m *ClientState) Marshal() (dAtA []byte, err error) {
@ -651,7 +651,7 @@ func (m *ConsensusState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil
}
func (m *Evidence) Marshal() (dAtA []byte, err error) {
func (m *Misbehaviour) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
@ -661,12 +661,12 @@ func (m *Evidence) Marshal() (dAtA []byte, err error) {
return dAtA[:n], nil
}
func (m *Evidence) MarshalTo(dAtA []byte) (int, error) {
func (m *Misbehaviour) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *Evidence) MarshalToSizedBuffer(dAtA []byte) (int, error) {
func (m *Misbehaviour) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
@ -982,9 +982,9 @@ func (m *MsgSubmitClientMisbehaviour) MarshalToSizedBuffer(dAtA []byte) (int, er
i--
dAtA[i] = 0x12
}
if m.Evidence != nil {
if m.Misbehaviour != nil {
{
size, err := m.Evidence.MarshalToSizedBuffer(dAtA[:i])
size, err := m.Misbehaviour.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
@ -1061,7 +1061,7 @@ func (m *ConsensusState) Size() (n int) {
return n
}
func (m *Evidence) Size() (n int) {
func (m *Misbehaviour) Size() (n int) {
if m == nil {
return 0
}
@ -1187,8 +1187,8 @@ func (m *MsgSubmitClientMisbehaviour) Size() (n int) {
}
var l int
_ = l
if m.Evidence != nil {
l = m.Evidence.Size()
if m.Misbehaviour != nil {
l = m.Misbehaviour.Size()
n += 1 + l + sovTendermint(uint64(l))
}
l = len(m.Submitter)
@ -1665,7 +1665,7 @@ func (m *ConsensusState) Unmarshal(dAtA []byte) error {
}
return nil
}
func (m *Evidence) Unmarshal(dAtA []byte) error {
func (m *Misbehaviour) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
@ -1688,10 +1688,10 @@ func (m *Evidence) Unmarshal(dAtA []byte) error {
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Evidence: wiretype end group for non-group")
return fmt.Errorf("proto: Misbehaviour: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Evidence: illegal tag %d (wire type %d)", fieldNum, wire)
return fmt.Errorf("proto: Misbehaviour: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
@ -2632,7 +2632,7 @@ func (m *MsgSubmitClientMisbehaviour) Unmarshal(dAtA []byte) error {
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Evidence", wireType)
return fmt.Errorf("proto: wrong wireType = %d for field Misbehaviour", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
@ -2659,10 +2659,10 @@ func (m *MsgSubmitClientMisbehaviour) Unmarshal(dAtA []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.Evidence == nil {
m.Evidence = &Evidence{}
if m.Misbehaviour == nil {
m.Misbehaviour = &Misbehaviour{}
}
if err := m.Evidence.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
if err := m.Misbehaviour.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex

View File

@ -88,7 +88,7 @@ func (cs ClientState) CheckHeaderAndUpdateState(
func (cs ClientState) CheckMisbehaviourAndUpdateState(
_ sdk.Context, _ codec.BinaryMarshaler, _ sdk.KVStore, _ clientexported.Misbehaviour,
) (clientexported.ClientState, error) {
return nil, sdkerrors.Wrap(clienttypes.ErrInvalidEvidence, "cannot submit misbehaviour to localhost client")
return nil, sdkerrors.Wrap(clienttypes.ErrInvalidMisbehaviour, "cannot submit misbehaviour to localhost client")
}
// VerifyClientState verifies that the localhost client state is stored locally

View File

@ -102,10 +102,10 @@ func NewUpdateClientCmd() *cobra.Command {
// future updates.
func NewSubmitMisbehaviourCmd() *cobra.Command {
return &cobra.Command{
Use: "misbehaviour [path/to/evidence.json]",
Use: "misbehaviour [path/to/misbehaviour.json]",
Short: "submit a client misbehaviour",
Long: "submit a client misbehaviour to prevent future updates",
Example: fmt.Sprintf("%s tx ibc %s misbehaviour [path/to/evidence.json] --from node0 --home ../node0/<app>cli --chain-id $CID", version.AppName, types.SubModuleName),
Example: fmt.Sprintf("%s tx ibc %s misbehaviour [path/to/misbehaviour.json] --from node0 --home ../node0/<app>cli --chain-id $CID", version.AppName, types.SubModuleName),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx := client.GetClientContextFromCmd(cmd)
@ -116,19 +116,19 @@ func NewSubmitMisbehaviourCmd() *cobra.Command {
cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry)
var ev *types.Evidence
if err := cdc.UnmarshalJSON([]byte(args[0]), ev); err != nil {
var m *types.Misbehaviour
if err := cdc.UnmarshalJSON([]byte(args[0]), m); err != nil {
// check for file path if JSON input is not provided
contents, err := ioutil.ReadFile(args[0])
if err != nil {
return errors.New("neither JSON input nor path to .json file were provided")
}
if err := cdc.UnmarshalJSON(contents, ev); err != nil {
return errors.Wrap(err, "error unmarshalling evidence file")
if err := cdc.UnmarshalJSON(contents, m); err != nil {
return errors.Wrap(err, "error unmarshalling misbehaviour file")
}
}
msg := types.NewMsgSubmitClientMisbehaviour(ev, clientCtx.GetFromAddress())
msg := types.NewMsgSubmitClientMisbehaviour(m, clientCtx.GetFromAddress())
if err := msg.ValidateBasic(); err != nil {
return err
}

View File

@ -1,101 +0,0 @@
package types
import (
"bytes"
yaml "gopkg.in/yaml.v2"
"github.com/tendermint/tendermint/crypto/tmhash"
tmbytes "github.com/tendermint/tendermint/libs/bytes"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
evidenceexported "github.com/cosmos/cosmos-sdk/x/evidence/exported"
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
)
var (
_ evidenceexported.Evidence = (*Evidence)(nil)
_ clientexported.Misbehaviour = (*Evidence)(nil)
)
// ClientType is a Solo Machine light client.
func (ev Evidence) ClientType() clientexported.ClientType {
return clientexported.SoloMachine
}
// GetClientID returns the ID of the client that committed a misbehaviour.
func (ev Evidence) GetClientID() string {
return ev.ClientId
}
// Route implements Evidence interface.
func (ev Evidence) Route() string {
return clienttypes.SubModuleName
}
// Type implements Evidence interface.
func (ev Evidence) Type() string {
return "client_misbehaviour"
}
// String implements Evidence interface.
func (ev Evidence) String() string {
out, _ := yaml.Marshal(ev)
return string(out)
}
// Hash implements Evidence interface
func (ev Evidence) Hash() tmbytes.HexBytes {
bz := SubModuleCdc.MustMarshalBinaryBare(&ev)
return tmhash.Sum(bz)
}
// GetHeight returns the sequence at which misbehaviour occurred.
func (ev Evidence) GetHeight() int64 {
return int64(ev.Sequence)
}
// ValidateBasic implements Evidence interface.
func (ev Evidence) ValidateBasic() error {
if err := host.ClientIdentifierValidator(ev.ClientId); err != nil {
return sdkerrors.Wrap(err, "invalid client identifier for solo machine")
}
if ev.Sequence == 0 {
return sdkerrors.Wrap(clienttypes.ErrInvalidEvidence, "sequence cannot be 0")
}
if err := ev.SignatureOne.ValidateBasic(); err != nil {
return sdkerrors.Wrap(err, "signature one failed basic validation")
}
if err := ev.SignatureTwo.ValidateBasic(); err != nil {
return sdkerrors.Wrap(err, "signature two failed basic validation")
}
// evidence signatures cannot be identical
if bytes.Equal(ev.SignatureOne.Signature, ev.SignatureTwo.Signature) {
return sdkerrors.Wrap(clienttypes.ErrInvalidEvidence, "evidence signatures cannot be equal")
}
// message data signed cannot be identical
if bytes.Equal(ev.SignatureOne.Data, ev.SignatureTwo.Data) {
return sdkerrors.Wrap(clienttypes.ErrInvalidEvidence, "evidence signature data must be signed over different messages")
}
return nil
}
// ValidateBasic ensures that the signature and data fields are non-empty.
func (sd SignatureAndData) ValidateBasic() error {
if len(sd.Signature) == 0 {
return sdkerrors.Wrap(ErrInvalidSignatureAndData, "signature cannot be empty")
}
if len(sd.Data) == 0 {
return sdkerrors.Wrap(ErrInvalidSignatureAndData, "data for signature cannot be empty")
}
return nil
}

View File

@ -1,108 +0,0 @@
package types_test
import (
"github.com/tendermint/tendermint/crypto/tmhash"
tmbytes "github.com/tendermint/tendermint/libs/bytes"
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
"github.com/cosmos/cosmos-sdk/x/ibc/light-clients/solomachine/types"
)
func (suite *SoloMachineTestSuite) TestEvidence() {
ev := suite.solomachine.CreateEvidence()
suite.Require().Equal(clientexported.SoloMachine, ev.ClientType())
suite.Require().Equal(suite.solomachine.ClientID, ev.GetClientID())
suite.Require().Equal("client", ev.Route())
suite.Require().Equal("client_misbehaviour", ev.Type())
suite.Require().Equal(tmbytes.HexBytes(tmhash.Sum(types.SubModuleCdc.MustMarshalBinaryBare(ev))), ev.Hash())
suite.Require().Equal(int64(suite.solomachine.Sequence), ev.GetHeight())
}
func (suite *SoloMachineTestSuite) TestEvidenceValidateBasic() {
testCases := []struct {
name string
malleateEvidence func(ev *types.Evidence)
expPass bool
}{
{
"valid evidence",
func(*types.Evidence) {},
true,
},
{
"invalid client ID",
func(ev *types.Evidence) {
ev.ClientId = "(badclientid)"
},
false,
},
{
"sequence is zero",
func(ev *types.Evidence) {
ev.Sequence = 0
},
false,
},
{
"signature one sig is empty",
func(ev *types.Evidence) {
ev.SignatureOne.Signature = []byte{}
},
false,
},
{
"signature two sig is empty",
func(ev *types.Evidence) {
ev.SignatureTwo.Signature = []byte{}
},
false,
},
{
"signature one data is empty",
func(ev *types.Evidence) {
ev.SignatureOne.Data = nil
},
false,
},
{
"signature two data is empty",
func(ev *types.Evidence) {
ev.SignatureTwo.Data = []byte{}
},
false,
},
{
"signatures are identical",
func(ev *types.Evidence) {
ev.SignatureTwo.Signature = ev.SignatureOne.Signature
},
false,
},
{
"data signed is identical",
func(ev *types.Evidence) {
ev.SignatureTwo.Data = ev.SignatureOne.Data
},
false,
},
}
for _, tc := range testCases {
tc := tc
suite.Run(tc.name, func() {
ev := suite.solomachine.CreateEvidence()
tc.malleateEvidence(ev)
err := ev.ValidateBasic()
if tc.expPass {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
}
})
}
}

View File

@ -1,62 +1,100 @@
package types
import (
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"bytes"
yaml "gopkg.in/yaml.v2"
"github.com/tendermint/tendermint/crypto/tmhash"
tmbytes "github.com/tendermint/tendermint/libs/bytes"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
evidenceexported "github.com/cosmos/cosmos-sdk/x/evidence/exported"
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
)
// CheckMisbehaviourAndUpdateState determines whether or not the currently registered
// public key signed over two different messages with the same sequence. If this is true
// the client state is updated to a frozen status.
func (cs ClientState) CheckMisbehaviourAndUpdateState(
ctx sdk.Context,
cdc codec.BinaryMarshaler,
clientStore sdk.KVStore,
misbehaviour clientexported.Misbehaviour,
) (clientexported.ClientState, error) {
var (
_ evidenceexported.Evidence = (*Misbehaviour)(nil)
_ clientexported.Misbehaviour = (*Misbehaviour)(nil)
)
evidence, ok := misbehaviour.(*Evidence)
if !ok {
return nil, sdkerrors.Wrapf(
clienttypes.ErrInvalidClientType,
"evidence type %T, expected %T", misbehaviour, &Evidence{},
)
}
if cs.IsFrozen() {
return nil, sdkerrors.Wrapf(clienttypes.ErrClientFrozen, "client is already frozen")
}
if err := checkMisbehaviour(cs, evidence); err != nil {
return nil, err
}
cs.FrozenSequence = uint64(evidence.GetHeight())
return cs, nil
// ClientType is a Solo Machine light client.
func (misbehaviour Misbehaviour) ClientType() clientexported.ClientType {
return clientexported.SoloMachine
}
// checkMisbehaviour checks if the currently registered public key has signed
// over two different messages at the same sequence.
// NOTE: a check that the evidence message data are not equal is done by
// evidence.ValidateBasic which is called by the 02-client keeper.
func checkMisbehaviour(clientState ClientState, evidence *Evidence) error {
pubKey := clientState.ConsensusState.GetPubKey()
// GetClientID returns the ID of the client that committed a misbehaviour.
func (misbehaviour Misbehaviour) GetClientID() string {
return misbehaviour.ClientId
}
data := EvidenceSignBytes(evidence.Sequence, evidence.SignatureOne.Data)
// Route implements Evidence interface.
func (misbehaviour Misbehaviour) Route() string {
return clienttypes.SubModuleName
}
// check first signature
if err := VerifySignature(pubKey, data, evidence.SignatureOne.Signature); err != nil {
return sdkerrors.Wrap(err, "evidence signature one failed to be verified")
// Type implements Evidence interface.
func (misbehaviour Misbehaviour) Type() string {
return clientexported.TypeEvidenceClientMisbehaviour
}
// String implements Evidence interface.
func (misbehaviour Misbehaviour) String() string {
out, _ := yaml.Marshal(misbehaviour)
return string(out)
}
// Hash implements Evidence interface
func (misbehaviour Misbehaviour) Hash() tmbytes.HexBytes {
bz := SubModuleCdc.MustMarshalBinaryBare(&misbehaviour)
return tmhash.Sum(bz)
}
// GetHeight returns the sequence at which misbehaviour occurred.
func (misbehaviour Misbehaviour) GetHeight() int64 {
return int64(misbehaviour.Sequence)
}
// ValidateBasic implements Evidence interface.
func (misbehaviour Misbehaviour) ValidateBasic() error {
if err := host.ClientIdentifierValidator(misbehaviour.ClientId); err != nil {
return sdkerrors.Wrap(err, "invalid client identifier for solo machine")
}
data = EvidenceSignBytes(evidence.Sequence, evidence.SignatureTwo.Data)
if misbehaviour.Sequence == 0 {
return sdkerrors.Wrap(clienttypes.ErrInvalidMisbehaviour, "sequence cannot be 0")
}
// check second signature
if err := VerifySignature(pubKey, data, evidence.SignatureTwo.Signature); err != nil {
return sdkerrors.Wrap(err, "evidence signature two failed to be verified")
if err := misbehaviour.SignatureOne.ValidateBasic(); err != nil {
return sdkerrors.Wrap(err, "signature one failed basic validation")
}
if err := misbehaviour.SignatureTwo.ValidateBasic(); err != nil {
return sdkerrors.Wrap(err, "signature two failed basic validation")
}
// misbehaviour signatures cannot be identical
if bytes.Equal(misbehaviour.SignatureOne.Signature, misbehaviour.SignatureTwo.Signature) {
return sdkerrors.Wrap(clienttypes.ErrInvalidMisbehaviour, "misbehaviour signatures cannot be equal")
}
// message data signed cannot be identical
if bytes.Equal(misbehaviour.SignatureOne.Data, misbehaviour.SignatureTwo.Data) {
return sdkerrors.Wrap(clienttypes.ErrInvalidMisbehaviour, "misbehaviour signature data must be signed over different messages")
}
return nil
}
// ValidateBasic ensures that the signature and data fields are non-empty.
func (sd SignatureAndData) ValidateBasic() error {
if len(sd.Signature) == 0 {
return sdkerrors.Wrap(ErrInvalidSignatureAndData, "signature cannot be empty")
}
if len(sd.Data) == 0 {
return sdkerrors.Wrap(ErrInvalidSignatureAndData, "data for signature cannot be empty")
}
return nil

View File

@ -0,0 +1,63 @@
package types
import (
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
)
// CheckMisbehaviourAndUpdateState determines whether or not the currently registered
// public key signed over two different messages with the same sequence. If this is true
// the client state is updated to a frozen status.
func (cs ClientState) CheckMisbehaviourAndUpdateState(
ctx sdk.Context,
cdc codec.BinaryMarshaler,
clientStore sdk.KVStore,
misbehaviour clientexported.Misbehaviour,
) (clientexported.ClientState, error) {
soloMisbehaviour, ok := misbehaviour.(*Misbehaviour)
if !ok {
return nil, sdkerrors.Wrapf(
clienttypes.ErrInvalidClientType,
"misbehaviour type %T, expected %T", misbehaviour, &Misbehaviour{},
)
}
if cs.IsFrozen() {
return nil, sdkerrors.Wrapf(clienttypes.ErrClientFrozen, "client is already frozen")
}
if err := checkMisbehaviour(cs, soloMisbehaviour); err != nil {
return nil, err
}
cs.FrozenSequence = uint64(soloMisbehaviour.GetHeight())
return cs, nil
}
// checkMisbehaviour checks if the currently registered public key has signed
// over two different messages at the same sequence.
// NOTE: a check that the misbehaviour message data are not equal is done by
// misbehaviour.ValidateBasic which is called by the 02-client keeper.
func checkMisbehaviour(clientState ClientState, soloMisbehaviour *Misbehaviour) error {
pubKey := clientState.ConsensusState.GetPubKey()
data := EvidenceSignBytes(soloMisbehaviour.Sequence, soloMisbehaviour.SignatureOne.Data)
// check first signature
if err := VerifySignature(pubKey, data, soloMisbehaviour.SignatureOne.Signature); err != nil {
return sdkerrors.Wrap(err, "misbehaviour signature one failed to be verified")
}
data = EvidenceSignBytes(soloMisbehaviour.Sequence, soloMisbehaviour.SignatureTwo.Data)
// check second signature
if err := VerifySignature(pubKey, data, soloMisbehaviour.SignatureTwo.Signature); err != nil {
return sdkerrors.Wrap(err, "misbehaviour signature two failed to be verified")
}
return nil
}

View File

@ -0,0 +1,145 @@
package types_test
import (
sdk "github.com/cosmos/cosmos-sdk/types"
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/07-tendermint/types"
)
func (suite *SoloMachineTestSuite) TestCheckMisbehaviourAndUpdateState() {
var (
clientState clientexported.ClientState
misbehaviour clientexported.Misbehaviour
)
testCases := []struct {
name string
setup func()
expPass bool
}{
{
"valid misbehaviour",
func() {
clientState = suite.solomachine.ClientState()
misbehaviour = suite.solomachine.CreateMisbehaviour()
},
true,
},
{
"client is frozen",
func() {
cs := suite.solomachine.ClientState()
cs.FrozenSequence = 1
clientState = cs
misbehaviour = suite.solomachine.CreateMisbehaviour()
},
false,
},
{
"wrong client state type",
func() {
clientState = ibctmtypes.ClientState{}
misbehaviour = suite.solomachine.CreateMisbehaviour()
},
false,
},
{
"invalid misbehaviour type",
func() {
clientState = suite.solomachine.ClientState()
misbehaviour = ibctmtypes.Misbehaviour{}
},
false,
},
{
"invalid first signature",
func() {
clientState = suite.solomachine.ClientState()
// store in temp before assigning to interface type
m := suite.solomachine.CreateMisbehaviour()
msg := []byte("DATA ONE")
data := append(sdk.Uint64ToBigEndian(suite.solomachine.Sequence+1), msg...)
sig, err := suite.solomachine.PrivateKey.Sign(data)
suite.Require().NoError(err)
m.SignatureOne.Signature = sig
m.SignatureOne.Data = msg
misbehaviour = m
},
false,
},
{
"invalid second signature",
func() {
clientState = suite.solomachine.ClientState()
// store in temp before assigning to interface type
m := suite.solomachine.CreateMisbehaviour()
msg := []byte("DATA TWO")
data := append(sdk.Uint64ToBigEndian(suite.solomachine.Sequence+1), msg...)
sig, err := suite.solomachine.PrivateKey.Sign(data)
suite.Require().NoError(err)
m.SignatureTwo.Signature = sig
m.SignatureTwo.Data = msg
misbehaviour = m
},
false,
},
{
"signatures sign over different sequence",
func() {
clientState = suite.solomachine.ClientState()
// store in temp before assigning to interface type
m := suite.solomachine.CreateMisbehaviour()
// Signature One
msg := []byte("DATA ONE")
// sequence used is plus 1
data := append(sdk.Uint64ToBigEndian(suite.solomachine.Sequence+1), msg...)
sig, err := suite.solomachine.PrivateKey.Sign(data)
suite.Require().NoError(err)
m.SignatureOne.Signature = sig
m.SignatureOne.Data = msg
// Signature Two
msg = []byte("DATA TWO")
// sequence used is minus 1
data = append(sdk.Uint64ToBigEndian(suite.solomachine.Sequence-1), msg...)
sig, err = suite.solomachine.PrivateKey.Sign(data)
suite.Require().NoError(err)
m.SignatureTwo.Signature = sig
m.SignatureTwo.Data = msg
misbehaviour = m
},
false,
},
}
for _, tc := range testCases {
tc := tc
suite.Run(tc.name, func() {
// setup test
tc.setup()
clientState, err := clientState.CheckMisbehaviourAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), suite.store, misbehaviour)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().True(clientState.IsFrozen(), "client not frozen")
} else {
suite.Require().Error(err)
suite.Require().Nil(clientState)
}
})
}
}

View File

@ -1,124 +1,88 @@
package types_test
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/tendermint/tendermint/crypto/tmhash"
tmbytes "github.com/tendermint/tendermint/libs/bytes"
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/light-clients/solomachine/types"
)
func (suite *SoloMachineTestSuite) TestCheckMisbehaviourAndUpdateState() {
var (
clientState clientexported.ClientState
evidence clientexported.Misbehaviour
)
func (suite *SoloMachineTestSuite) TestMisbehaviour() {
misbehaviour := suite.solomachine.CreateMisbehaviour()
suite.Require().Equal(clientexported.SoloMachine, misbehaviour.ClientType())
suite.Require().Equal(suite.solomachine.ClientID, misbehaviour.GetClientID())
suite.Require().Equal("client", misbehaviour.Route())
suite.Require().Equal("client_misbehaviour", misbehaviour.Type())
suite.Require().Equal(tmbytes.HexBytes(tmhash.Sum(types.SubModuleCdc.MustMarshalBinaryBare(misbehaviour))), misbehaviour.Hash())
suite.Require().Equal(int64(suite.solomachine.Sequence), misbehaviour.GetHeight())
}
func (suite *SoloMachineTestSuite) TestMisbehaviourValidateBasic() {
testCases := []struct {
name string
setup func()
expPass bool
name string
malleateMisbehaviour func(misbehaviour *types.Misbehaviour)
expPass bool
}{
{
"valid misbehaviour evidence",
func() {
clientState = suite.solomachine.ClientState()
evidence = suite.solomachine.CreateEvidence()
},
"valid misbehaviour",
func(*types.Misbehaviour) {},
true,
},
{
"client is frozen",
func() {
cs := suite.solomachine.ClientState()
cs.FrozenSequence = 1
clientState = cs
evidence = suite.solomachine.CreateEvidence()
"invalid client ID",
func(misbehaviour *types.Misbehaviour) {
misbehaviour.ClientId = "(badclientid)"
},
false,
},
{
"wrong client state type",
func() {
clientState = ibctmtypes.ClientState{}
evidence = suite.solomachine.CreateEvidence()
"sequence is zero",
func(misbehaviour *types.Misbehaviour) {
misbehaviour.Sequence = 0
},
false,
},
{
"invalid evidence type",
func() {
clientState = suite.solomachine.ClientState()
evidence = ibctmtypes.Evidence{}
"signature one sig is empty",
func(misbehaviour *types.Misbehaviour) {
misbehaviour.SignatureOne.Signature = []byte{}
},
false,
},
{
"invalid first signature",
func() {
clientState = suite.solomachine.ClientState()
// store in temp before assigning to interface type
ev := suite.solomachine.CreateEvidence()
msg := []byte("DATA ONE")
data := append(sdk.Uint64ToBigEndian(suite.solomachine.Sequence+1), msg...)
sig, err := suite.solomachine.PrivateKey.Sign(data)
suite.Require().NoError(err)
ev.SignatureOne.Signature = sig
ev.SignatureOne.Data = msg
evidence = ev
"signature two sig is empty",
func(misbehaviour *types.Misbehaviour) {
misbehaviour.SignatureTwo.Signature = []byte{}
},
false,
},
{
"invalid second signature",
func() {
clientState = suite.solomachine.ClientState()
// store in temp before assigning to interface type
ev := suite.solomachine.CreateEvidence()
msg := []byte("DATA TWO")
data := append(sdk.Uint64ToBigEndian(suite.solomachine.Sequence+1), msg...)
sig, err := suite.solomachine.PrivateKey.Sign(data)
suite.Require().NoError(err)
ev.SignatureTwo.Signature = sig
ev.SignatureTwo.Data = msg
evidence = ev
"signature one data is empty",
func(misbehaviour *types.Misbehaviour) {
misbehaviour.SignatureOne.Data = nil
},
false,
},
{
"signatures sign over different sequence",
func() {
clientState = suite.solomachine.ClientState()
// store in temp before assigning to interface type
ev := suite.solomachine.CreateEvidence()
// Signature One
msg := []byte("DATA ONE")
// sequence used is plus 1
data := append(sdk.Uint64ToBigEndian(suite.solomachine.Sequence+1), msg...)
sig, err := suite.solomachine.PrivateKey.Sign(data)
suite.Require().NoError(err)
ev.SignatureOne.Signature = sig
ev.SignatureOne.Data = msg
// Signature Two
msg = []byte("DATA TWO")
// sequence used is minus 1
data = append(sdk.Uint64ToBigEndian(suite.solomachine.Sequence-1), msg...)
sig, err = suite.solomachine.PrivateKey.Sign(data)
suite.Require().NoError(err)
ev.SignatureTwo.Signature = sig
ev.SignatureTwo.Data = msg
evidence = ev
"signature two data is empty",
func(misbehaviour *types.Misbehaviour) {
misbehaviour.SignatureTwo.Data = []byte{}
},
false,
},
{
"signatures are identical",
func(misbehaviour *types.Misbehaviour) {
misbehaviour.SignatureTwo.Signature = misbehaviour.SignatureOne.Signature
},
false,
},
{
"data signed is identical",
func(misbehaviour *types.Misbehaviour) {
misbehaviour.SignatureTwo.Data = misbehaviour.SignatureOne.Data
},
false,
},
@ -128,17 +92,16 @@ func (suite *SoloMachineTestSuite) TestCheckMisbehaviourAndUpdateState() {
tc := tc
suite.Run(tc.name, func() {
// setup test
tc.setup()
clientState, err := clientState.CheckMisbehaviourAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), suite.store, evidence)
misbehaviour := suite.solomachine.CreateMisbehaviour()
tc.malleateMisbehaviour(misbehaviour)
err := misbehaviour.ValidateBasic()
if tc.expPass {
suite.Require().NoError(err)
suite.Require().True(clientState.IsFrozen(), "client not frozen")
} else {
suite.Require().Error(err)
suite.Require().Nil(clientState)
}
})
}

View File

@ -126,8 +126,8 @@ func (msg MsgUpdateClient) GetHeader() clientexported.Header {
// NewMsgSubmitClientMisbehaviour creates a new MsgSubmitClientMisbehaviour
// instance.
func NewMsgSubmitClientMisbehaviour(e *Evidence, s sdk.AccAddress) *MsgSubmitClientMisbehaviour {
return &MsgSubmitClientMisbehaviour{Evidence: e, Submitter: s}
func NewMsgSubmitClientMisbehaviour(m *Misbehaviour, s sdk.AccAddress) *MsgSubmitClientMisbehaviour {
return &MsgSubmitClientMisbehaviour{Misbehaviour: m, Submitter: s}
}
// Route returns the MsgSubmitClientMisbehaviour's route.
@ -140,7 +140,7 @@ func (msg MsgSubmitClientMisbehaviour) Type() string {
// ValidateBasic performs basic (non-state-dependent) validation on a MsgSubmitClientMisbehaviour.
func (msg MsgSubmitClientMisbehaviour) ValidateBasic() error {
if err := msg.Evidence.ValidateBasic(); err != nil {
if err := msg.Misbehaviour.ValidateBasic(); err != nil {
return err
}
if msg.Submitter.Empty() {
@ -162,7 +162,7 @@ func (msg MsgSubmitClientMisbehaviour) GetSigners() []sdk.AccAddress {
}
func (msg MsgSubmitClientMisbehaviour) GetEvidence() evidenceexported.Evidence {
return msg.Evidence
return msg.Misbehaviour
}
func (msg MsgSubmitClientMisbehaviour) GetSubmitter() sdk.AccAddress {

View File

@ -149,26 +149,26 @@ func (m *Header) XXX_DiscardUnknown() {
var xxx_messageInfo_Header proto.InternalMessageInfo
// Evidence defines evidence of misbehaviour for a solo machine which consists
// Misbehaviour defines misbehaviour for a solo machine which consists
// of a sequence and two signatures over different messages at that sequence.
type Evidence struct {
type Misbehaviour struct {
ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"`
Sequence uint64 `protobuf:"varint,2,opt,name=sequence,proto3" json:"sequence,omitempty"`
SignatureOne *SignatureAndData `protobuf:"bytes,3,opt,name=signature_one,json=signatureOne,proto3" json:"signature_one,omitempty" yaml:"signature_one"`
SignatureTwo *SignatureAndData `protobuf:"bytes,4,opt,name=signature_two,json=signatureTwo,proto3" json:"signature_two,omitempty" yaml:"signature_two"`
}
func (m *Evidence) Reset() { *m = Evidence{} }
func (*Evidence) ProtoMessage() {}
func (*Evidence) Descriptor() ([]byte, []int) {
func (m *Misbehaviour) Reset() { *m = Misbehaviour{} }
func (*Misbehaviour) ProtoMessage() {}
func (*Misbehaviour) Descriptor() ([]byte, []int) {
return fileDescriptor_6cc2ee18f7f86d4e, []int{3}
}
func (m *Evidence) XXX_Unmarshal(b []byte) error {
func (m *Misbehaviour) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *Evidence) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
func (m *Misbehaviour) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_Evidence.Marshal(b, m, deterministic)
return xxx_messageInfo_Misbehaviour.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
@ -178,17 +178,17 @@ func (m *Evidence) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return b[:n], nil
}
}
func (m *Evidence) XXX_Merge(src proto.Message) {
xxx_messageInfo_Evidence.Merge(m, src)
func (m *Misbehaviour) XXX_Merge(src proto.Message) {
xxx_messageInfo_Misbehaviour.Merge(m, src)
}
func (m *Evidence) XXX_Size() int {
func (m *Misbehaviour) XXX_Size() int {
return m.Size()
}
func (m *Evidence) XXX_DiscardUnknown() {
xxx_messageInfo_Evidence.DiscardUnknown(m)
func (m *Misbehaviour) XXX_DiscardUnknown() {
xxx_messageInfo_Misbehaviour.DiscardUnknown(m)
}
var xxx_messageInfo_Evidence proto.InternalMessageInfo
var xxx_messageInfo_Misbehaviour proto.InternalMessageInfo
// SignatureAndData contains a signature and the data signed over to create that
// signature.
@ -349,10 +349,10 @@ func (m *MsgUpdateClient) XXX_DiscardUnknown() {
var xxx_messageInfo_MsgUpdateClient proto.InternalMessageInfo
// MsgSubmitClientMisbehaviour defines an sdk.Msg type that supports submitting
// arbitrary Evidence.
// arbitrary Misbehaviour.
type MsgSubmitClientMisbehaviour struct {
Submitter github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,1,opt,name=submitter,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"submitter,omitempty"`
Evidence *Evidence `protobuf:"bytes,2,opt,name=evidence,proto3" json:"evidence,omitempty"`
Submitter github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,1,opt,name=submitter,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"submitter,omitempty"`
Misbehaviour *Misbehaviour `protobuf:"bytes,2,opt,name=misbehaviour,proto3" json:"misbehaviour,omitempty"`
}
func (m *MsgSubmitClientMisbehaviour) Reset() { *m = MsgSubmitClientMisbehaviour{} }
@ -392,7 +392,7 @@ func init() {
proto.RegisterType((*ClientState)(nil), "ibc.lightclients.solomachine.v1.ClientState")
proto.RegisterType((*ConsensusState)(nil), "ibc.lightclients.solomachine.v1.ConsensusState")
proto.RegisterType((*Header)(nil), "ibc.lightclients.solomachine.v1.Header")
proto.RegisterType((*Evidence)(nil), "ibc.lightclients.solomachine.v1.Evidence")
proto.RegisterType((*Misbehaviour)(nil), "ibc.lightclients.solomachine.v1.Misbehaviour")
proto.RegisterType((*SignatureAndData)(nil), "ibc.lightclients.solomachine.v1.SignatureAndData")
proto.RegisterType((*TimestampedSignature)(nil), "ibc.lightclients.solomachine.v1.TimestampedSignature")
proto.RegisterType((*MsgCreateClient)(nil), "ibc.lightclients.solomachine.v1.MsgCreateClient")
@ -405,52 +405,52 @@ func init() {
}
var fileDescriptor_6cc2ee18f7f86d4e = []byte{
// 716 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x55, 0x4d, 0x6f, 0xd3, 0x4c,
0x10, 0x8e, 0xd3, 0xa8, 0x4a, 0xb6, 0x7d, 0xd3, 0xbe, 0x56, 0x8a, 0x42, 0xa8, 0xe2, 0xca, 0x12,
0x6a, 0x39, 0xd4, 0x96, 0xe1, 0xd6, 0x0b, 0xaa, 0x43, 0x25, 0x3e, 0x54, 0x15, 0x39, 0x45, 0x42,
0x80, 0x14, 0xad, 0xed, 0xad, 0xb3, 0x6a, 0xec, 0x35, 0xde, 0x75, 0x42, 0xf8, 0x05, 0x48, 0x5c,
0x38, 0x72, 0xe4, 0x0f, 0x20, 0x71, 0xe7, 0xc2, 0x0d, 0x4e, 0xa8, 0x47, 0x4e, 0x11, 0x6a, 0xfe,
0x41, 0x8e, 0x9c, 0x50, 0xbc, 0x1b, 0x27, 0x8e, 0xaa, 0x46, 0x7c, 0x48, 0x9c, 0xbc, 0x3b, 0x9e,
0x79, 0xe6, 0x79, 0x66, 0x66, 0x77, 0x81, 0x81, 0x6d, 0x47, 0xef, 0x60, 0xaf, 0xcd, 0x9c, 0x0e,
0x46, 0x01, 0xa3, 0x3a, 0x25, 0x1d, 0xe2, 0x43, 0xa7, 0x8d, 0x03, 0xa4, 0x77, 0x8d, 0xd9, 0xad,
0x16, 0x46, 0x84, 0x11, 0x59, 0xc1, 0xb6, 0xa3, 0xcd, 0x86, 0x68, 0xb3, 0x3e, 0x5d, 0xa3, 0xb6,
0xed, 0x10, 0xea, 0x13, 0xaa, 0xdb, 0x90, 0x22, 0xdd, 0x89, 0xfa, 0x21, 0x23, 0x7a, 0xd7, 0xb0,
0x11, 0x83, 0x86, 0xd8, 0x72, 0xa4, 0x5a, 0xc5, 0x23, 0x1e, 0x49, 0x96, 0xfa, 0x78, 0xc5, 0xad,
0xea, 0x57, 0x09, 0xac, 0x34, 0x12, 0xe4, 0x26, 0x83, 0x0c, 0xc9, 0x0d, 0xb0, 0x76, 0x12, 0x91,
0x97, 0x28, 0x68, 0x51, 0xf4, 0x3c, 0x46, 0x81, 0x83, 0xaa, 0xd2, 0x96, 0xb4, 0x53, 0x30, 0x6b,
0xa3, 0x81, 0x72, 0xa5, 0x0f, 0xfd, 0xce, 0x9e, 0x3a, 0xe7, 0xa0, 0x5a, 0x65, 0x6e, 0x69, 0x0a,
0x83, 0xcc, 0xc0, 0x9a, 0x43, 0x02, 0x8a, 0x02, 0x1a, 0xd3, 0x16, 0x1d, 0xe3, 0x56, 0xf3, 0x5b,
0xd2, 0xce, 0xca, 0x4d, 0x5d, 0x5b, 0x20, 0x47, 0x6b, 0x4c, 0xe2, 0x12, 0x3a, 0xb3, 0x59, 0xe7,
0x10, 0x55, 0xab, 0xec, 0x64, 0x7c, 0xf7, 0x0a, 0xaf, 0xde, 0x29, 0x39, 0xf5, 0xbd, 0x04, 0xca,
0x59, 0x10, 0xb9, 0x06, 0x8a, 0x59, 0x31, 0x56, 0xba, 0x97, 0x9f, 0x02, 0x10, 0xc6, 0x76, 0x07,
0x3b, 0xad, 0x53, 0xd4, 0x17, 0x2c, 0xaf, 0x6b, 0xbc, 0xa6, 0xda, 0xb8, 0xa6, 0x9a, 0x28, 0xa2,
0xa8, 0xa9, 0xf6, 0x30, 0xf1, 0x7e, 0x80, 0xfa, 0xe6, 0xc6, 0x68, 0xa0, 0xfc, 0xcf, 0xb9, 0x4d,
0x21, 0x54, 0xab, 0x14, 0x4e, 0x3c, 0xe4, 0x4d, 0x50, 0x62, 0xd8, 0x47, 0x94, 0x41, 0x3f, 0xac,
0x2e, 0x25, 0x99, 0xa7, 0x06, 0xc1, 0xf7, 0x83, 0x04, 0x96, 0xef, 0x22, 0xe8, 0xa2, 0xe8, 0x52,
0x9e, 0x9b, 0xa0, 0x44, 0xb1, 0x17, 0x40, 0x16, 0x47, 0xbc, 0x98, 0xab, 0xd6, 0xd4, 0x20, 0x9f,
0x80, 0x72, 0x80, 0x7a, 0xad, 0x19, 0x25, 0x4b, 0xbf, 0xa2, 0xe4, 0xea, 0x68, 0xa0, 0x6c, 0x70,
0x25, 0x59, 0x18, 0xd5, 0x5a, 0x0d, 0x50, 0x2f, 0x75, 0x14, 0x94, 0x3f, 0xe7, 0x41, 0xf1, 0xa0,
0x8b, 0xdd, 0x84, 0x98, 0x01, 0x4a, 0xbc, 0x95, 0x2d, 0xec, 0x26, 0xac, 0x4b, 0x66, 0x65, 0x34,
0x50, 0xd6, 0x45, 0xd3, 0x26, 0xbf, 0x54, 0xab, 0xc8, 0xd7, 0xf7, 0xdc, 0x8c, 0xce, 0xfc, 0x9c,
0xce, 0x10, 0xfc, 0x97, 0xca, 0x6a, 0x91, 0x00, 0x09, 0x21, 0xc6, 0xc2, 0xc1, 0x69, 0x4e, 0xa2,
0xf6, 0x03, 0xf7, 0x0e, 0x64, 0xd0, 0xac, 0x8e, 0x06, 0x4a, 0x85, 0xb3, 0xc8, 0x20, 0xaa, 0xd6,
0x6a, 0xba, 0x3f, 0x0a, 0xe6, 0x32, 0xb2, 0x1e, 0xa9, 0x16, 0xfe, 0x6a, 0x46, 0xd6, 0x23, 0xb3,
0x19, 0x8f, 0x7b, 0x64, 0xaf, 0x38, 0xae, 0xe2, 0xdb, 0x71, 0x25, 0xef, 0x83, 0xf5, 0x79, 0x94,
0x6c, 0xa7, 0xa5, 0xf9, 0x4e, 0xcb, 0xa0, 0xe0, 0x42, 0x06, 0xc5, 0x08, 0x24, 0x6b, 0xd1, 0x95,
0xc7, 0xa0, 0x72, 0x3c, 0x99, 0x2d, 0xe4, 0xa6, 0xb0, 0x0b, 0xf0, 0x32, 0x23, 0x9a, 0xbf, 0x78,
0x44, 0x3f, 0x49, 0x60, 0xed, 0x90, 0x7a, 0x8d, 0x08, 0x41, 0x86, 0xf8, 0x65, 0xf1, 0x3b, 0x6d,
0xff, 0x97, 0xb7, 0xc2, 0x6b, 0x2e, 0xe1, 0x51, 0xe8, 0xfe, 0x91, 0x84, 0xdb, 0x60, 0xb9, 0x9d,
0x9c, 0x55, 0xc1, 0x7c, 0x7b, 0x21, 0x73, 0x7e, 0xb4, 0x2d, 0x11, 0x26, 0xd8, 0x7c, 0x94, 0xc0,
0xb5, 0x43, 0xea, 0x35, 0x63, 0xdb, 0xc7, 0x8c, 0xb3, 0x39, 0xc4, 0xd4, 0x46, 0x6d, 0xd8, 0xc5,
0x24, 0x8e, 0xe4, 0x23, 0x50, 0xa2, 0xc9, 0x3f, 0x86, 0x22, 0xde, 0x32, 0xd3, 0xf8, 0x31, 0x50,
0x76, 0x3d, 0xcc, 0xda, 0xb1, 0xad, 0x39, 0xc4, 0xd7, 0xc5, 0xad, 0xcf, 0x3f, 0xbb, 0xd4, 0x3d,
0xd5, 0x59, 0x3f, 0x44, 0x54, 0xdb, 0x77, 0x9c, 0x7d, 0xd7, 0x8d, 0x10, 0xa5, 0xd6, 0x14, 0x43,
0x3e, 0x00, 0x45, 0x24, 0x0e, 0xac, 0x60, 0x7e, 0x63, 0x21, 0xf3, 0xc9, 0x09, 0xb7, 0xd2, 0x50,
0xce, 0xde, 0x7c, 0xf6, 0xe5, 0xbc, 0x2e, 0x9d, 0x9d, 0xd7, 0xa5, 0xef, 0xe7, 0x75, 0xe9, 0xcd,
0xb0, 0x9e, 0x3b, 0x1b, 0xd6, 0x73, 0xdf, 0x86, 0xf5, 0xdc, 0x13, 0xf3, 0x52, 0x82, 0x2f, 0xf4,
0xf4, 0xf9, 0xdb, 0xbd, 0xe8, 0xfd, 0x4b, 0x04, 0xd8, 0xcb, 0xc9, 0xbb, 0x74, 0xeb, 0x67, 0x00,
0x00, 0x00, 0xff, 0xff, 0xee, 0x37, 0x2c, 0xb2, 0x2c, 0x07, 0x00, 0x00,
// 712 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x55, 0xcf, 0x6e, 0xd3, 0x4e,
0x10, 0x8e, 0xd3, 0xa8, 0x6a, 0xb6, 0xf9, 0xa5, 0xfd, 0x59, 0x29, 0x0a, 0xa1, 0x8a, 0x2b, 0x4b,
0xa8, 0xbd, 0xc4, 0x96, 0xe1, 0xd6, 0x0b, 0xaa, 0xc3, 0x81, 0x3f, 0xaa, 0x0a, 0x4e, 0x91, 0x10,
0x20, 0x45, 0x6b, 0x7b, 0xeb, 0xac, 0x1a, 0x7b, 0x8d, 0x77, 0x9d, 0x10, 0x9e, 0x00, 0x89, 0x0b,
0x47, 0x8e, 0xbc, 0x00, 0x12, 0x8f, 0xc0, 0x0d, 0x24, 0x24, 0xd4, 0x23, 0xa7, 0x08, 0x35, 0x6f,
0x90, 0x23, 0x27, 0x14, 0xef, 0x26, 0xb1, 0xa3, 0xaa, 0x11, 0x7f, 0x24, 0x4e, 0xde, 0x1d, 0xcf,
0x7c, 0xf3, 0x7d, 0x33, 0xb3, 0xbb, 0xc0, 0xc0, 0xb6, 0xa3, 0x77, 0xb1, 0xd7, 0x61, 0x4e, 0x17,
0xa3, 0x80, 0x51, 0x9d, 0x92, 0x2e, 0xf1, 0xa1, 0xd3, 0xc1, 0x01, 0xd2, 0x7b, 0x46, 0x7a, 0xab,
0x85, 0x11, 0x61, 0x44, 0x56, 0xb0, 0xed, 0x68, 0xe9, 0x10, 0x2d, 0xed, 0xd3, 0x33, 0x6a, 0xbb,
0x0e, 0xa1, 0x3e, 0xa1, 0xba, 0x0d, 0x29, 0xd2, 0x9d, 0x68, 0x10, 0x32, 0xa2, 0xf7, 0x0c, 0x1b,
0x31, 0x68, 0x88, 0x2d, 0x47, 0xaa, 0x55, 0x3c, 0xe2, 0x91, 0x64, 0xa9, 0x4f, 0x56, 0xdc, 0xaa,
0x7e, 0x95, 0xc0, 0x7a, 0x33, 0x41, 0x6e, 0x31, 0xc8, 0x90, 0xdc, 0x04, 0x1b, 0x27, 0x11, 0x79,
0x89, 0x82, 0x36, 0x45, 0xcf, 0x63, 0x14, 0x38, 0xa8, 0x2a, 0xed, 0x48, 0x7b, 0x05, 0xb3, 0x36,
0x1e, 0x2a, 0x57, 0x06, 0xd0, 0xef, 0xee, 0xab, 0x0b, 0x0e, 0xaa, 0x55, 0xe6, 0x96, 0x96, 0x30,
0xc8, 0x0c, 0x6c, 0x38, 0x24, 0xa0, 0x28, 0xa0, 0x31, 0x6d, 0xd3, 0x09, 0x6e, 0x35, 0xbf, 0x23,
0xed, 0xad, 0xdf, 0xd0, 0xb5, 0x25, 0x72, 0xb4, 0xe6, 0x34, 0x2e, 0xa1, 0x93, 0xce, 0xba, 0x80,
0xa8, 0x5a, 0x65, 0x27, 0xe3, 0xbb, 0x5f, 0x78, 0xf5, 0x4e, 0xc9, 0xa9, 0xef, 0x25, 0x50, 0xce,
0x82, 0xc8, 0x35, 0xb0, 0x96, 0x15, 0x63, 0xcd, 0xf6, 0xf2, 0x53, 0x00, 0xc2, 0xd8, 0xee, 0x62,
0xa7, 0x7d, 0x8a, 0x06, 0x82, 0xe5, 0x75, 0x8d, 0xd7, 0x54, 0x9b, 0xd4, 0x54, 0x13, 0x45, 0x14,
0x35, 0xd5, 0x1e, 0x24, 0xde, 0xf7, 0xd1, 0xc0, 0xdc, 0x1a, 0x0f, 0x95, 0xff, 0x39, 0xb7, 0x39,
0x84, 0x6a, 0x15, 0xc3, 0xa9, 0x87, 0xbc, 0x0d, 0x8a, 0x0c, 0xfb, 0x88, 0x32, 0xe8, 0x87, 0xd5,
0x95, 0x24, 0xf3, 0xdc, 0x20, 0xf8, 0x7e, 0x90, 0xc0, 0xea, 0x1d, 0x04, 0x5d, 0x14, 0x5d, 0xca,
0x73, 0x1b, 0x14, 0x29, 0xf6, 0x02, 0xc8, 0xe2, 0x88, 0x17, 0xb3, 0x64, 0xcd, 0x0d, 0xf2, 0x09,
0x28, 0x07, 0xa8, 0xdf, 0x4e, 0x29, 0x59, 0xf9, 0x15, 0x25, 0x57, 0xc7, 0x43, 0x65, 0x8b, 0x2b,
0xc9, 0xc2, 0xa8, 0x56, 0x29, 0x40, 0xfd, 0x99, 0xa3, 0xa0, 0xfc, 0x25, 0x0f, 0x4a, 0x87, 0x98,
0xda, 0xa8, 0x03, 0x7b, 0x98, 0xc4, 0x91, 0x6c, 0x80, 0x22, 0x6f, 0x67, 0x1b, 0xbb, 0x09, 0xf3,
0xa2, 0x59, 0x19, 0x0f, 0x95, 0x4d, 0xd1, 0xb8, 0xe9, 0x2f, 0xd5, 0x5a, 0xe3, 0xeb, 0xbb, 0x6e,
0x46, 0x6b, 0x7e, 0x41, 0x6b, 0x08, 0xfe, 0x9b, 0x49, 0x6b, 0x93, 0x00, 0x09, 0x31, 0xc6, 0xd2,
0xe1, 0x69, 0x4d, 0xa3, 0x0e, 0x02, 0xf7, 0x36, 0x64, 0xd0, 0xac, 0x8e, 0x87, 0x4a, 0x85, 0xb3,
0xc8, 0x20, 0xaa, 0x56, 0x69, 0xb6, 0x3f, 0x0a, 0x16, 0x32, 0xb2, 0x3e, 0xa9, 0x16, 0xfe, 0x6a,
0x46, 0xd6, 0x27, 0xe9, 0x8c, 0xc7, 0x7d, 0xb2, 0xbf, 0x36, 0xa9, 0xe4, 0xdb, 0x49, 0x35, 0xef,
0x81, 0xcd, 0x45, 0x94, 0x6c, 0xb7, 0xa5, 0xc5, 0x6e, 0xcb, 0xa0, 0xe0, 0x42, 0x06, 0xc5, 0x18,
0x24, 0x6b, 0xd1, 0x99, 0xc7, 0xa0, 0x72, 0x3c, 0x9d, 0x2f, 0xe4, 0xce, 0x60, 0x97, 0xe0, 0x65,
0xc6, 0x34, 0x7f, 0xf1, 0x98, 0x7e, 0x94, 0xc0, 0xc6, 0x21, 0xf5, 0x9a, 0x11, 0x82, 0x0c, 0xf1,
0x0b, 0xe3, 0x77, 0xda, 0xfe, 0x2f, 0x6f, 0x86, 0xd7, 0x5c, 0xc2, 0xa3, 0xd0, 0xfd, 0x23, 0x09,
0xb7, 0xc0, 0x6a, 0x27, 0x39, 0xaf, 0x82, 0xf9, 0xee, 0x52, 0xe6, 0xfc, 0x78, 0x5b, 0x22, 0x4c,
0xb0, 0xf9, 0x24, 0x81, 0x6b, 0x87, 0xd4, 0x6b, 0xc5, 0xb6, 0x8f, 0x19, 0x67, 0x93, 0x39, 0x53,
0x47, 0xa0, 0x48, 0x93, 0x7f, 0x0c, 0x45, 0xbc, 0x65, 0xa6, 0xf1, 0x63, 0xa8, 0x34, 0x3c, 0xcc,
0x3a, 0xb1, 0xad, 0x39, 0xc4, 0xd7, 0xc5, 0xcd, 0xcf, 0x3f, 0x0d, 0xea, 0x9e, 0xea, 0x6c, 0x10,
0x22, 0xaa, 0x1d, 0x38, 0xce, 0x81, 0xeb, 0x46, 0x88, 0x52, 0x6b, 0x8e, 0x21, 0x3f, 0x04, 0x25,
0x3f, 0x95, 0x40, 0xb0, 0x6f, 0x2c, 0x65, 0x9f, 0x66, 0x65, 0x65, 0x20, 0xb8, 0x12, 0xf3, 0xd9,
0xe7, 0xf3, 0xba, 0x74, 0x76, 0x5e, 0x97, 0xbe, 0x9f, 0xd7, 0xa5, 0x37, 0xa3, 0x7a, 0xee, 0x6c,
0x54, 0xcf, 0x7d, 0x1b, 0xd5, 0x73, 0x4f, 0xcc, 0x4b, 0xc9, 0xbe, 0xd0, 0x67, 0xcf, 0x61, 0xe3,
0xa2, 0xf7, 0x30, 0x11, 0x63, 0xaf, 0x26, 0xef, 0xd4, 0xcd, 0x9f, 0x01, 0x00, 0x00, 0xff, 0xff,
0xec, 0x46, 0x40, 0x5d, 0x3c, 0x07, 0x00, 0x00,
}
func (m *ClientState) Marshal() (dAtA []byte, err error) {
@ -585,7 +585,7 @@ func (m *Header) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil
}
func (m *Evidence) Marshal() (dAtA []byte, err error) {
func (m *Misbehaviour) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
@ -595,12 +595,12 @@ func (m *Evidence) Marshal() (dAtA []byte, err error) {
return dAtA[:n], nil
}
func (m *Evidence) MarshalTo(dAtA []byte) (int, error) {
func (m *Misbehaviour) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *Evidence) MarshalToSizedBuffer(dAtA []byte) (int, error) {
func (m *Misbehaviour) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
@ -820,9 +820,9 @@ func (m *MsgSubmitClientMisbehaviour) MarshalToSizedBuffer(dAtA []byte) (int, er
_ = i
var l int
_ = l
if m.Evidence != nil {
if m.Misbehaviour != nil {
{
size, err := m.Evidence.MarshalToSizedBuffer(dAtA[:i])
size, err := m.Misbehaviour.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
@ -908,7 +908,7 @@ func (m *Header) Size() (n int) {
return n
}
func (m *Evidence) Size() (n int) {
func (m *Misbehaviour) Size() (n int) {
if m == nil {
return 0
}
@ -1009,8 +1009,8 @@ func (m *MsgSubmitClientMisbehaviour) Size() (n int) {
if l > 0 {
n += 1 + l + sovSolomachine(uint64(l))
}
if m.Evidence != nil {
l = m.Evidence.Size()
if m.Misbehaviour != nil {
l = m.Misbehaviour.Size()
n += 1 + l + sovSolomachine(uint64(l))
}
return n
@ -1399,7 +1399,7 @@ func (m *Header) Unmarshal(dAtA []byte) error {
}
return nil
}
func (m *Evidence) Unmarshal(dAtA []byte) error {
func (m *Misbehaviour) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
@ -1422,10 +1422,10 @@ func (m *Evidence) Unmarshal(dAtA []byte) error {
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Evidence: wiretype end group for non-group")
return fmt.Errorf("proto: Misbehaviour: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Evidence: illegal tag %d (wire type %d)", fieldNum, wire)
return fmt.Errorf("proto: Misbehaviour: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
@ -2109,7 +2109,7 @@ func (m *MsgSubmitClientMisbehaviour) Unmarshal(dAtA []byte) error {
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Evidence", wireType)
return fmt.Errorf("proto: wrong wireType = %d for field Misbehaviour", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
@ -2136,10 +2136,10 @@ func (m *MsgSubmitClientMisbehaviour) Unmarshal(dAtA []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.Evidence == nil {
m.Evidence = &Evidence{}
if m.Misbehaviour == nil {
m.Misbehaviour = &Misbehaviour{}
}
if err := m.Evidence.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
if err := m.Misbehaviour.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex

View File

@ -7,6 +7,28 @@ order: 1
> NOTE: if you are not familiar with the IBC terminology and concepts, please read
this [document](https://github.com/cosmos/ics/blob/master/ibc/1_IBC_TERMINOLOGY.md) as prerequisite reading.
## Client Misbehaviour
IBC clients must freeze when the counterparty chain becomes malicious and
takes actions that could fool the light client into accepting invalid state
transitions. Thus, relayers are able to submit Misbehaviour proofs that prove
that a counterparty chain has signed two Headers for the same height. This
constitutes misbehaviour as the IBC client could have accepted either header
as valid. Upon verifying the misbehaviour the IBC client must freeze at that
height so that any proof verifications for the frozen height or later fail.
Note, there is a difference between the chain-level Misbehaviour that IBC is
concerned with and the validator-level Evidence that Tendermint is concerned
with. Tendermint must be able to detect, submit, and punish any evidence of
individual validators breaking the Tendermint consensus protocol and attempting
to mount an attack. IBC clients must only act when an attack is successful
and the chain has successfully forked. In this case, valid Headers submitted
to the IBC client can no longer be trusted and the client must freeze.
Governance may then choose to override a frozen client and provide the correct,
canonical Header so that the client can continue operating after the Misbehaviour
submission.
## Connection Version Negotation
During the handshake procedure for connections a version string is agreed

View File

@ -80,9 +80,9 @@ func (solo *Solomachine) CreateHeader() *solomachinetypes.Header {
return header
}
// CreateEvidence constructs testing evidence for the solo machine client
// CreateMisbehaviour constructs testing misbehaviour for the solo machine client
// by signing over two different data bytes at the same sequence.
func (solo *Solomachine) CreateEvidence() *solomachinetypes.Evidence {
func (solo *Solomachine) CreateMisbehaviour() *solomachinetypes.Misbehaviour {
dataOne := []byte("DATA ONE")
dataTwo := []byte("DATA TWO")
@ -102,7 +102,7 @@ func (solo *Solomachine) CreateEvidence() *solomachinetypes.Evidence {
Data: dataTwo,
}
return &solomachinetypes.Evidence{
return &solomachinetypes.Misbehaviour{
ClientId: solo.ClientID,
Sequence: solo.Sequence,
SignatureOne: &signatureOne,