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:
parent
e09c8d9360
commit
9fc0dbbe05
|
@ -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.
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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"];
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
|
|||
)
|
||||
registry.RegisterImplementations(
|
||||
(*evidenceexported.Evidence)(nil),
|
||||
&Evidence{},
|
||||
&Misbehaviour{},
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue