Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate Evidence Implementation into ICS-02 #5258

Merged
merged 5 commits into from
Nov 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 22 additions & 21 deletions x/ibc/02-client/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,21 @@ package client
import (
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/keeper"
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types/errors"
)

const (
DefaultCodespace = types.DefaultCodespace
CodeClientExists = types.CodeClientExists
CodeClientNotFound = types.CodeClientNotFound
CodeClientFrozen = types.CodeClientFrozen
CodeConsensusStateNotFound = types.CodeConsensusStateNotFound
CodeInvalidConsensusState = types.CodeInvalidConsensusState
CodeClientTypeNotFound = types.CodeClientTypeNotFound
CodeInvalidClientType = types.CodeInvalidClientType
CodeRootNotFound = types.CodeRootNotFound
CodeInvalidHeader = types.CodeInvalidHeader
CodeInvalidEvidence = types.CodeInvalidEvidence
DefaultCodespace = errors.DefaultCodespace
CodeClientExists = errors.CodeClientExists
CodeClientNotFound = errors.CodeClientNotFound
CodeClientFrozen = errors.CodeClientFrozen
CodeConsensusStateNotFound = errors.CodeConsensusStateNotFound
CodeInvalidConsensusState = errors.CodeInvalidConsensusState
CodeClientTypeNotFound = errors.CodeClientTypeNotFound
CodeInvalidClientType = errors.CodeInvalidClientType
CodeRootNotFound = errors.CodeRootNotFound
CodeInvalidHeader = errors.CodeInvalidHeader
CodeInvalidEvidence = errors.CodeInvalidEvidence
AttributeKeyClientID = types.AttributeKeyClientID
SubModuleName = types.SubModuleName
StoreKey = types.StoreKey
Expand All @@ -40,16 +41,16 @@ var (
QuerierConsensusState = keeper.QuerierConsensusState
QuerierVerifiedRoot = keeper.QuerierVerifiedRoot
RegisterCodec = types.RegisterCodec
ErrClientExists = types.ErrClientExists
ErrClientNotFound = types.ErrClientNotFound
ErrClientFrozen = types.ErrClientFrozen
ErrConsensusStateNotFound = types.ErrConsensusStateNotFound
ErrInvalidConsensus = types.ErrInvalidConsensus
ErrClientTypeNotFound = types.ErrClientTypeNotFound
ErrInvalidClientType = types.ErrInvalidClientType
ErrRootNotFound = types.ErrRootNotFound
ErrInvalidHeader = types.ErrInvalidHeader
ErrInvalidEvidence = types.ErrInvalidEvidence
ErrClientExists = errors.ErrClientExists
ErrClientNotFound = errors.ErrClientNotFound
ErrClientFrozen = errors.ErrClientFrozen
ErrConsensusStateNotFound = errors.ErrConsensusStateNotFound
ErrInvalidConsensus = errors.ErrInvalidConsensus
ErrClientTypeNotFound = errors.ErrClientTypeNotFound
ErrInvalidClientType = errors.ErrInvalidClientType
ErrRootNotFound = errors.ErrRootNotFound
ErrInvalidHeader = errors.ErrInvalidHeader
ErrInvalidEvidence = errors.ErrInvalidEvidence
ClientStatePath = types.ClientStatePath
ClientTypePath = types.ClientTypePath
ConsensusStatePath = types.ConsensusStatePath
Expand Down
2 changes: 2 additions & 0 deletions x/ibc/02-client/exported/exported.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"

commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment"
cmn "github.com/tendermint/tendermint/libs/common"
)

// Blockchain is consensus algorithm which generates valid Headers. It generates
Expand Down Expand Up @@ -37,6 +38,7 @@ type Evidence interface {
Route() string
Type() string
String() string
Hash() cmn.HexBytes
ValidateBasic() sdk.Error

// The consensus address of the malicious validator at time of infraction
Expand Down
15 changes: 8 additions & 7 deletions x/ibc/02-client/keeper/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types/errors"
)

// CreateClient creates a new client state and populates it with a given consensus
Expand All @@ -17,7 +18,7 @@ func (k Keeper) CreateClient(
) (types.State, error) {
_, found := k.GetClientState(ctx, clientID)
if found {
return types.State{}, types.ErrClientExists(k.codespace, clientID)
return types.State{}, errors.ErrClientExists(k.codespace, clientID)
}

_, found = k.GetClientType(ctx, clientID)
Expand All @@ -36,26 +37,26 @@ func (k Keeper) CreateClient(
func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.Header) error {
clientType, found := k.GetClientType(ctx, clientID)
if !found {
return sdkerrors.Wrap(types.ErrClientTypeNotFound(k.codespace), "cannot update client")
return sdkerrors.Wrap(errors.ErrClientTypeNotFound(k.codespace), "cannot update client")
}

// check that the header consensus matches the client one
if header.ClientType() != clientType {
return sdkerrors.Wrap(types.ErrInvalidConsensus(k.codespace), "cannot update client")
return sdkerrors.Wrap(errors.ErrInvalidConsensus(k.codespace), "cannot update client")
}

clientState, found := k.GetClientState(ctx, clientID)
if !found {
return sdkerrors.Wrap(types.ErrClientNotFound(k.codespace, clientID), "cannot update client")
return sdkerrors.Wrap(errors.ErrClientNotFound(k.codespace, clientID), "cannot update client")
}

if clientState.Frozen {
return sdkerrors.Wrap(types.ErrClientFrozen(k.codespace, clientID), "cannot update client")
return sdkerrors.Wrap(errors.ErrClientFrozen(k.codespace, clientID), "cannot update client")
}

consensusState, found := k.GetConsensusState(ctx, clientID)
if !found {
return sdkerrors.Wrap(types.ErrConsensusStateNotFound(k.codespace), "cannot update client")
return sdkerrors.Wrap(errors.ErrConsensusStateNotFound(k.codespace), "cannot update client")
}

if header.GetHeight() < consensusState.GetHeight() {
Expand Down Expand Up @@ -83,7 +84,7 @@ func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.H
func (k Keeper) CheckMisbehaviourAndUpdateState(ctx sdk.Context, clientID string, evidence exported.Evidence) error {
clientState, found := k.GetClientState(ctx, clientID)
if !found {
sdk.ResultFromError(types.ErrClientNotFound(k.codespace, clientID))
sdk.ResultFromError(errors.ErrClientNotFound(k.codespace, clientID))
}

err := k.checkMisbehaviour(ctx, evidence)
Expand Down
34 changes: 19 additions & 15 deletions x/ibc/02-client/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types/errors"
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types/tendermint"
commitment "github.com/cosmos/cosmos-sdk/x/ibc/23-commitment"
ibctypes "github.com/cosmos/cosmos-sdk/x/ibc/types"
)
Expand All @@ -29,8 +31,8 @@ func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, codespace sdk.CodespaceType)
return Keeper{
storeKey: key,
cdc: cdc,
codespace: sdk.CodespaceType(fmt.Sprintf("%s/%s", codespace, types.DefaultCodespace)), // "ibc/client",
prefix: []byte(types.SubModuleName + "/"), // "client/"
codespace: sdk.CodespaceType(fmt.Sprintf("%s/%s", codespace, errors.DefaultCodespace)), // "ibc/client",
prefix: []byte(types.SubModuleName + "/"), // "client/"
}
}

Expand Down Expand Up @@ -127,25 +129,27 @@ func (k Keeper) initialize(ctx sdk.Context, clientID string, consensusState expo
}

func (k Keeper) checkMisbehaviour(ctx sdk.Context, evidence exported.Evidence) error {
// switch evidence.H1().ClientType() {
// case exported.Tendermint:
// var tmEvidence tendermint.Evidence
// _, ok := evidence.(tendermint.Evidence)
// if !ok {
// return sdkerrors.Wrap(types.ErrInvalidClientType(k.codespace), "consensus type is not Tendermint")
// }
// // TODO: pass past consensus states
// return tendermint.CheckMisbehaviour(tmEvidence)
// default:
// panic("unregistered consensus type")
// }
switch evidence.Type() {
case exported.ClientTypeTendermint:
var tmEvidence tendermint.Evidence
_, ok := evidence.(tendermint.Evidence)
if !ok {
return errors.ErrInvalidClientType(k.codespace, "consensus type is not Tendermint")
}
err := tendermint.CheckMisbehaviour(tmEvidence)
if err != nil {
return errors.ErrInvalidEvidence(k.codespace, err.Error())
}
default:
panic(fmt.Sprintf("unregistered evidence type: %s", evidence.Type()))
}
return nil
}

// freeze updates the state of the client in the event of a misbehaviour
func (k Keeper) freeze(ctx sdk.Context, clientState types.State) (types.State, error) {
if clientState.Frozen {
return types.State{}, sdkerrors.Wrap(types.ErrClientFrozen(k.codespace, clientState.ID()), "already frozen")
return types.State{}, sdkerrors.Wrap(errors.ErrClientFrozen(k.codespace, clientState.ID()), "already frozen")
}

clientState.Frozen = true
Expand Down
7 changes: 4 additions & 3 deletions x/ibc/02-client/keeper/querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types"
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types/errors"
)

// QuerierClientState defines the sdk.Querier to query the IBC client state
Expand All @@ -20,7 +21,7 @@ func QuerierClientState(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byt

clientState, found := k.GetClientState(ctx, params.ClientID)
if !found {
return nil, types.ErrClientTypeNotFound(k.codespace)
return nil, errors.ErrClientTypeNotFound(k.codespace)
}

bz, err := types.SubModuleCdc.MarshalJSON(clientState)
Expand All @@ -42,7 +43,7 @@ func QuerierConsensusState(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]

consensusState, found := k.GetConsensusState(ctx, params.ClientID)
if !found {
return nil, types.ErrConsensusStateNotFound(k.codespace)
return nil, errors.ErrConsensusStateNotFound(k.codespace)
}

bz, err := types.SubModuleCdc.MarshalJSON(consensusState)
Expand All @@ -64,7 +65,7 @@ func QuerierVerifiedRoot(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]by

root, found := k.GetVerifiedRoot(ctx, params.ClientID, params.Height)
if !found {
return nil, types.ErrRootNotFound(k.codespace)
return nil, errors.ErrRootNotFound(k.codespace)
}

bz, err := types.SubModuleCdc.MarshalJSON(root)
Expand Down
7 changes: 6 additions & 1 deletion x/ibc/02-client/types/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types/tendermint"
)

var SubModuleCdc *codec.Codec
var SubModuleCdc = codec.New()

// RegisterCodec registers the IBC client interfaces and types
func RegisterCodec(cdc *codec.Codec) {
Expand All @@ -21,4 +21,9 @@ func RegisterCodec(cdc *codec.Codec) {

cdc.RegisterConcrete(tendermint.ConsensusState{}, "ibc/client/tendermint/ConsensusState", nil)
cdc.RegisterConcrete(tendermint.Header{}, "ibc/client/tendermint/Header", nil)
cdc.RegisterConcrete(tendermint.Evidence{}, "ibc/client/tendermint/Evidence", nil)
}

func init() {
RegisterCodec(SubModuleCdc)
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package types
package errors
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not against this change, but it breaks the standard module structure.

I like how @alexanderbez implemented the errors on the evidence module here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If i leave errors.go in types/, there wasn't a way for me to use those errors in the types/tendermint package without creating an import cycle. This is why i split it into its own package

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently the codebase is a mix of using the old errors (sdk.Error defined in types), and the new errors defined in types/errors. The current ICS-02 implementation uses the old sdk.Error, should I switch it to use new error type?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current ICS-02 implementation uses the old sdk.Error, should I switch it to use new error type?

Thoughts @alexanderbez ?

Copy link
Contributor

@alexanderbez alexanderbez Oct 30, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the approach I've taken in the evidence module PR and for future PRs is the following:

Return error where ever and as much as possible up and until I can no longer return an error. When I can no longer return an error, I call sdk.ConvertError(err) which gives me the old (soon to be deprecated) sdk.Error.

Behind the scenes I'm returning a concrete type of sdkerrors.New(...) which fulfills the error interface and fulfills the ABCI semantics.

so tl;dr, return error using sdkerrors.New(...) as much as possible until you cant.


import (
"fmt"
Expand All @@ -8,7 +8,7 @@ import (

// client error codes
const (
DefaultCodespace sdk.CodespaceType = SubModuleName
DefaultCodespace sdk.CodespaceType = "client"

CodeClientExists sdk.CodeType = 101
CodeClientNotFound sdk.CodeType = 102
Expand Down Expand Up @@ -68,6 +68,6 @@ func ErrInvalidHeader(codespace sdk.CodespaceType) sdk.Error {
}

// ErrInvalidEvidence implements sdk.Error
func ErrInvalidEvidence(codespace sdk.CodespaceType) sdk.Error {
return sdk.NewError(codespace, CodeInvalidEvidence, "invalid evidence")
func ErrInvalidEvidence(codespace sdk.CodespaceType, msg string) sdk.Error {
return sdk.NewError(codespace, CodeInvalidEvidence, "invalid evidence: %s", msg)
}
12 changes: 8 additions & 4 deletions x/ibc/02-client/types/msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
"github.com/cosmos/cosmos-sdk/x/ibc/02-client/types/errors"
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
ibctypes "github.com/cosmos/cosmos-sdk/x/ibc/types"
)
Expand Down Expand Up @@ -45,10 +46,10 @@ func (msg MsgCreateClient) ValidateBasic() sdk.Error {
return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid client ID: %s", err.Error()))
}
if _, err := exported.ClientTypeFromString(msg.ClientType); err != nil {
return ErrInvalidClientType(DefaultCodespace, err.Error())
return errors.ErrInvalidClientType(errors.DefaultCodespace, err.Error())
}
if msg.ConsensusState == nil {
return ErrInvalidConsensus(DefaultCodespace)
return errors.ErrInvalidConsensus(errors.DefaultCodespace)
}
if msg.Signer.Empty() {
return sdk.ErrInvalidAddress("empty address")
Expand Down Expand Up @@ -100,7 +101,7 @@ func (msg MsgUpdateClient) ValidateBasic() sdk.Error {
return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid client ID: %s", err.Error()))
}
if msg.Header == nil {
return ErrInvalidHeader(DefaultCodespace)
return errors.ErrInvalidHeader(errors.DefaultCodespace)
}
if msg.Signer.Empty() {
return sdk.ErrInvalidAddress("empty address")
Expand Down Expand Up @@ -150,7 +151,10 @@ func (msg MsgSubmitMisbehaviour) ValidateBasic() sdk.Error {
return sdk.NewError(host.IBCCodeSpace, 1, fmt.Sprintf("invalid client ID: %s", err.Error()))
}
if msg.Evidence == nil {
AdityaSripal marked this conversation as resolved.
Show resolved Hide resolved
return ErrInvalidEvidence(DefaultCodespace)
return errors.ErrInvalidEvidence(errors.DefaultCodespace, "evidence is nil")
}
if err := msg.Evidence.ValidateBasic(); err != nil {
return errors.ErrInvalidEvidence(errors.DefaultCodespace, err.Error())
}
if msg.Signer.Empty() {
return sdk.ErrInvalidAddress("empty address")
Expand Down
18 changes: 18 additions & 0 deletions x/ibc/02-client/types/tendermint/codec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package tendermint

import (
"github.com/cosmos/cosmos-sdk/codec"
)

var SubModuleCdc = codec.New()

// RegisterCodec registers the Tendermint types
func RegisterCodec(cdc *codec.Codec) {
cdc.RegisterConcrete(ConsensusState{}, "ibc/client/tendermint/ConsensusState", nil)
cdc.RegisterConcrete(Header{}, "ibc/client/tendermint/Header", nil)
cdc.RegisterConcrete(Evidence{}, "ibc/client/tendermint/Evidence", nil)
}

func init() {
RegisterCodec(SubModuleCdc)
}
Loading