From f6b6aef2f77dc877129e765fb8bcf3827042f088 Mon Sep 17 00:00:00 2001 From: --global Date: Mon, 15 Mar 2021 17:34:19 +0530 Subject: [PATCH 1/5] Handle misbehaviour on update client event --- Makefile | 2 +- relayer/naive-strategy.go | 58 +++++++++++++++++++++++++++++++-------- 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index e2fe1cfd0..f1acf9bac 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION := $(shell echo $(shell git describe --tags) | sed 's/^v//') COMMIT := $(shell git log -1 --format='%H') SDKCOMMIT := $(shell go list -m -u -f '{{.Version}}' github.com/cosmos/cosmos-sdk) -GAIA_VERSION := v4.0.0 +GAIA_VERSION := v4.1.0 AKASH_VERSION := jack/update-sdk WASMD_VERSION := v0.14.1 diff --git a/relayer/naive-strategy.go b/relayer/naive-strategy.go index 59372d5bb..cddef06b0 100644 --- a/relayer/naive-strategy.go +++ b/relayer/naive-strategy.go @@ -1,7 +1,9 @@ package relayer import ( + "encoding/hex" "fmt" + "reflect" "strconv" "strings" @@ -9,6 +11,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" chantypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" + tmclient "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" ctypes "github.com/tendermint/tendermint/rpc/core/types" "golang.org/x/sync/errgroup" ) @@ -18,17 +21,20 @@ var ( _ Strategy = &NaiveStrategy{} // Strings for parsing events - spTag = "send_packet" - waTag = "write_acknowledgement" - srcChanTag = "packet_src_channel" - dstChanTag = "packet_dst_channel" - srcPortTag = "packet_src_port" - dstPortTag = "packet_dst_port" - dataTag = "packet_data" - ackTag = "packet_ack" - toHeightTag = "packet_timeout_height" - toTSTag = "packet_timeout_timestamp" - seqTag = "packet_sequence" + spTag = "send_packet" + waTag = "write_acknowledgement" + srcChanTag = "packet_src_channel" + dstChanTag = "packet_dst_channel" + srcPortTag = "packet_src_port" + dstPortTag = "packet_dst_port" + dataTag = "packet_data" + ackTag = "packet_ack" + toHeightTag = "packet_timeout_height" + toTSTag = "packet_timeout_timestamp" + seqTag = "packet_sequence" + updateCliTag = "update_client" + headerTag = "header" + clientIDTag = "client_id" ) // NewNaiveStrategy returns the proper config for the NaiveStrategy @@ -232,6 +238,36 @@ func (nrs *NaiveStrategy) UnrelayedAcknowledgements(src, dst *Chain) (*RelaySequ // HandleEvents defines how the relayer will handle block and transaction events as they are emitted func (nrs *NaiveStrategy) HandleEvents(src, dst *Chain, events map[string][]string) { + // check for misbehaviour + if hdrs, ok := events[fmt.Sprintf("%s.%s", updateCliTag, headerTag)]; ok { + for i, hdr := range hdrs { + clientIDs := events[fmt.Sprintf("%s.%s", updateCliTag, clientIDTag)] + + if src.PathEnd.ClientID == clientIDs[i] && dst.PathEnd.ClientID == clientIDs[i] { + hdrBytes, err := hex.DecodeString(hdr) + if err == nil { + exportedHeader, err := clienttypes.UnmarshalHeader(src.Encoding.Marshaler, hdrBytes) + if err == nil { + gotHeader, ok := exportedHeader.(*tmclient.Header) + if ok { + trustedHeader, err := src.GetLatestLightHeader() + if err == nil && !reflect.DeepEqual(gotHeader, trustedHeader) { + misbehaviour := tmclient.NewMisbehaviour(clientIDs[i], gotHeader, trustedHeader) + msg, err := clienttypes.NewMsgSubmitMisbehaviour(clientIDs[i], misbehaviour, src.MustGetAddress()) + if err == nil { + _, _, _ = src.SendMsg(msg) + } + } + } + } + + } else { + src.Error(err) + } + } + } + } + rlyPackets, err := relayPacketsFromEventListener(src.PathEnd, dst.PathEnd, events) if len(rlyPackets) > 0 && err == nil { nrs.sendTxFromEventPackets(src, dst, rlyPackets) From fb273d984789f2e8ca242a51538e13273dbbd350 Mon Sep 17 00:00:00 2001 From: --global Date: Tue, 16 Mar 2021 14:32:07 +0530 Subject: [PATCH 2/5] Address few PR comments --- relayer/naive-strategy.go | 73 ++++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 24 deletions(-) diff --git a/relayer/naive-strategy.go b/relayer/naive-strategy.go index cddef06b0..0137ddc76 100644 --- a/relayer/naive-strategy.go +++ b/relayer/naive-strategy.go @@ -3,7 +3,6 @@ package relayer import ( "encoding/hex" "fmt" - "reflect" "strconv" "strings" @@ -238,40 +237,66 @@ func (nrs *NaiveStrategy) UnrelayedAcknowledgements(src, dst *Chain) (*RelaySequ // HandleEvents defines how the relayer will handle block and transaction events as they are emitted func (nrs *NaiveStrategy) HandleEvents(src, dst *Chain, events map[string][]string) { - // check for misbehaviour + // check for misbehaviour and submit if found + err := checkAndSubmitMisbehaviour(src, events) + if err != nil { + src.Error(err) + } + + rlyPackets, err := relayPacketsFromEventListener(src.PathEnd, dst.PathEnd, events) + if len(rlyPackets) > 0 && err == nil { + nrs.sendTxFromEventPackets(src, dst, rlyPackets) + } +} + +func checkAndSubmitMisbehaviour(src *Chain, events map[string][]string) error { if hdrs, ok := events[fmt.Sprintf("%s.%s", updateCliTag, headerTag)]; ok { for i, hdr := range hdrs { clientIDs := events[fmt.Sprintf("%s.%s", updateCliTag, clientIDTag)] + emittedClientID := clientIDs[i] - if src.PathEnd.ClientID == clientIDs[i] && dst.PathEnd.ClientID == clientIDs[i] { + if src.PathEnd.ClientID == emittedClientID { hdrBytes, err := hex.DecodeString(hdr) - if err == nil { - exportedHeader, err := clienttypes.UnmarshalHeader(src.Encoding.Marshaler, hdrBytes) - if err == nil { - gotHeader, ok := exportedHeader.(*tmclient.Header) - if ok { - trustedHeader, err := src.GetLatestLightHeader() - if err == nil && !reflect.DeepEqual(gotHeader, trustedHeader) { - misbehaviour := tmclient.NewMisbehaviour(clientIDs[i], gotHeader, trustedHeader) - msg, err := clienttypes.NewMsgSubmitMisbehaviour(clientIDs[i], misbehaviour, src.MustGetAddress()) - if err == nil { - _, _, _ = src.SendMsg(msg) - } - } - } - } + if err != nil { + return err + } + + exportedHeader, err := clienttypes.UnmarshalHeader(src.Encoding.Marshaler, hdrBytes) + if err != nil { + return err + } - } else { - src.Error(err) + emittedHeader, ok := exportedHeader.(*tmclient.Header) + if !ok { + return fmt.Errorf("emitted header is not tendermint type") + } + + trustedHeader, err := src.GetLightSignedHeaderAtHeight(emittedHeader.Header.Height) + if err != nil { + return err + } + + if !IsMatchingConsensusState(emittedHeader.ConsensusState(), trustedHeader.ConsensusState()) { + misbehaviour := tmclient.NewMisbehaviour(emittedClientID, emittedHeader, trustedHeader) + msg, err := clienttypes.NewMsgSubmitMisbehaviour(emittedClientID, misbehaviour, src.MustGetAddress()) + if err != nil { + return err + } + res, success, err := src.SendMsg(msg) + if err != nil { + return err + } + if !success { + return fmt.Errorf("submit misbehaviour tx failed: %s", res.RawLog) + } + src.Log(fmt.Sprintf("Submitted misbehaviour for emitted header with height: %d", + emittedHeader.Header.Height)) } } } } - rlyPackets, err := relayPacketsFromEventListener(src.PathEnd, dst.PathEnd, events) - if len(rlyPackets) > 0 && err == nil { - nrs.sendTxFromEventPackets(src, dst, rlyPackets) - } + return nil } func relayPacketsFromEventListener(src, dst *PathEnd, events map[string][]string) (rlyPkts []relayPacket, err error) { From 5e5a15c04777d29abb6454cd47cbcf79227d18c9 Mon Sep 17 00:00:00 2001 From: --global Date: Thu, 18 Mar 2021 17:17:36 +0530 Subject: [PATCH 3/5] Apply @colin-axner suggestions --- relayer/misbehaviour.go | 71 ++++++++++++++++++++++++++++++++++++ relayer/naive-strategy.go | 77 ++++++--------------------------------- 2 files changed, 82 insertions(+), 66 deletions(-) create mode 100644 relayer/misbehaviour.go diff --git a/relayer/misbehaviour.go b/relayer/misbehaviour.go new file mode 100644 index 000000000..7e075dde7 --- /dev/null +++ b/relayer/misbehaviour.go @@ -0,0 +1,71 @@ +package relayer + +import ( + "encoding/hex" + "fmt" + + clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" + tmclient "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" +) + +var ( + // strings for parsing events + updateCliTag = "update_client" + headerTag = "header" + clientIDTag = "client_id" +) + +// checkAndSubmitMisbehaviour check headers from update_client tx events +// and submit misbehaviour if found any +func checkAndSubmitMisbehaviour(src *Chain, events map[string][]string) error { + if hdrs, ok := events[fmt.Sprintf("%s.%s", updateCliTag, headerTag)]; ok { + for i, hdr := range hdrs { + clientIDs := events[fmt.Sprintf("%s.%s", updateCliTag, clientIDTag)] + emittedClientID := clientIDs[i] + + if src.PathEnd.ClientID == emittedClientID { + hdrBytes, err := hex.DecodeString(hdr) + if err != nil { + return err + } + + exportedHeader, err := clienttypes.UnmarshalHeader(src.Encoding.Marshaler, hdrBytes) + if err != nil { + return err + } + + emittedHeader, ok := exportedHeader.(*tmclient.Header) + if !ok { + return fmt.Errorf("emitted header is not tendermint type") + } + + trustedHeader, err := src.GetLightSignedHeaderAtHeight(emittedHeader.Header.Height) + if err != nil { + return err + } + + trustedHeader.TrustedValidators = emittedHeader.TrustedValidators + trustedHeader.TrustedHeight = emittedHeader.TrustedHeight + + if !IsMatchingConsensusState(emittedHeader.ConsensusState(), trustedHeader.ConsensusState()) { + misbehaviour := tmclient.NewMisbehaviour(emittedClientID, emittedHeader, trustedHeader) + msg, err := clienttypes.NewMsgSubmitMisbehaviour(emittedClientID, misbehaviour, src.MustGetAddress()) + if err != nil { + return err + } + res, success, err := src.SendMsg(msg) + if err != nil { + return err + } + if !success { + return fmt.Errorf("submit misbehaviour tx failed: %s", res.RawLog) + } + src.Log(fmt.Sprintf("Submitted misbehaviour for emitted header with height: %d", + emittedHeader.Header.Height)) + } + } + } + } + + return nil +} diff --git a/relayer/naive-strategy.go b/relayer/naive-strategy.go index 0137ddc76..53f7d0292 100644 --- a/relayer/naive-strategy.go +++ b/relayer/naive-strategy.go @@ -1,7 +1,6 @@ package relayer import ( - "encoding/hex" "fmt" "strconv" "strings" @@ -10,7 +9,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" chantypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - tmclient "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" ctypes "github.com/tendermint/tendermint/rpc/core/types" "golang.org/x/sync/errgroup" ) @@ -20,20 +18,17 @@ var ( _ Strategy = &NaiveStrategy{} // Strings for parsing events - spTag = "send_packet" - waTag = "write_acknowledgement" - srcChanTag = "packet_src_channel" - dstChanTag = "packet_dst_channel" - srcPortTag = "packet_src_port" - dstPortTag = "packet_dst_port" - dataTag = "packet_data" - ackTag = "packet_ack" - toHeightTag = "packet_timeout_height" - toTSTag = "packet_timeout_timestamp" - seqTag = "packet_sequence" - updateCliTag = "update_client" - headerTag = "header" - clientIDTag = "client_id" + spTag = "send_packet" + waTag = "write_acknowledgement" + srcChanTag = "packet_src_channel" + dstChanTag = "packet_dst_channel" + srcPortTag = "packet_src_port" + dstPortTag = "packet_dst_port" + dataTag = "packet_data" + ackTag = "packet_ack" + toHeightTag = "packet_timeout_height" + toTSTag = "packet_timeout_timestamp" + seqTag = "packet_sequence" ) // NewNaiveStrategy returns the proper config for the NaiveStrategy @@ -249,56 +244,6 @@ func (nrs *NaiveStrategy) HandleEvents(src, dst *Chain, events map[string][]stri } } -func checkAndSubmitMisbehaviour(src *Chain, events map[string][]string) error { - if hdrs, ok := events[fmt.Sprintf("%s.%s", updateCliTag, headerTag)]; ok { - for i, hdr := range hdrs { - clientIDs := events[fmt.Sprintf("%s.%s", updateCliTag, clientIDTag)] - emittedClientID := clientIDs[i] - - if src.PathEnd.ClientID == emittedClientID { - hdrBytes, err := hex.DecodeString(hdr) - if err != nil { - return err - } - - exportedHeader, err := clienttypes.UnmarshalHeader(src.Encoding.Marshaler, hdrBytes) - if err != nil { - return err - } - - emittedHeader, ok := exportedHeader.(*tmclient.Header) - if !ok { - return fmt.Errorf("emitted header is not tendermint type") - } - - trustedHeader, err := src.GetLightSignedHeaderAtHeight(emittedHeader.Header.Height) - if err != nil { - return err - } - - if !IsMatchingConsensusState(emittedHeader.ConsensusState(), trustedHeader.ConsensusState()) { - misbehaviour := tmclient.NewMisbehaviour(emittedClientID, emittedHeader, trustedHeader) - msg, err := clienttypes.NewMsgSubmitMisbehaviour(emittedClientID, misbehaviour, src.MustGetAddress()) - if err != nil { - return err - } - res, success, err := src.SendMsg(msg) - if err != nil { - return err - } - if !success { - return fmt.Errorf("submit misbehaviour tx failed: %s", res.RawLog) - } - src.Log(fmt.Sprintf("Submitted misbehaviour for emitted header with height: %d", - emittedHeader.Header.Height)) - } - } - } - } - - return nil -} - func relayPacketsFromEventListener(src, dst *PathEnd, events map[string][]string) (rlyPkts []relayPacket, err error) { // check for send packets if pdval, ok := events[fmt.Sprintf("%s.%s", spTag, dataTag)]; ok { From f4039f47526133fc3c3f3d7c440ec28960473c04 Mon Sep 17 00:00:00 2001 From: --global Date: Fri, 19 Mar 2021 10:24:15 +0530 Subject: [PATCH 4/5] Address new PR comments --- relayer/misbehaviour.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/relayer/misbehaviour.go b/relayer/misbehaviour.go index 7e075dde7..06c53a166 100644 --- a/relayer/misbehaviour.go +++ b/relayer/misbehaviour.go @@ -16,7 +16,9 @@ var ( ) // checkAndSubmitMisbehaviour check headers from update_client tx events -// and submit misbehaviour if found any +// against the associated light client. If the headers do not match, the emitted +// header and a reconstructed header are used in misbehaviour submission to +// the IBC client on the source chain. func checkAndSubmitMisbehaviour(src *Chain, events map[string][]string) error { if hdrs, ok := events[fmt.Sprintf("%s.%s", updateCliTag, headerTag)]; ok { for i, hdr := range hdrs { @@ -44,10 +46,10 @@ func checkAndSubmitMisbehaviour(src *Chain, events map[string][]string) error { return err } - trustedHeader.TrustedValidators = emittedHeader.TrustedValidators - trustedHeader.TrustedHeight = emittedHeader.TrustedHeight - if !IsMatchingConsensusState(emittedHeader.ConsensusState(), trustedHeader.ConsensusState()) { + trustedHeader.TrustedValidators = emittedHeader.TrustedValidators + trustedHeader.TrustedHeight = emittedHeader.TrustedHeight + misbehaviour := tmclient.NewMisbehaviour(emittedClientID, emittedHeader, trustedHeader) msg, err := clienttypes.NewMsgSubmitMisbehaviour(emittedClientID, misbehaviour, src.MustGetAddress()) if err != nil { From 3c5d4010ef44b1b7e70ba927ea8c981d3ba7cceb Mon Sep 17 00:00:00 2001 From: --global Date: Sat, 20 Mar 2021 10:38:45 +0530 Subject: [PATCH 5/5] Address @fedekunze review comments --- relayer/misbehaviour.go | 94 +++++++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 40 deletions(-) diff --git a/relayer/misbehaviour.go b/relayer/misbehaviour.go index 06c53a166..2f8cd6a11 100644 --- a/relayer/misbehaviour.go +++ b/relayer/misbehaviour.go @@ -4,6 +4,7 @@ import ( "encoding/hex" "fmt" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" tmclient "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" ) @@ -20,53 +21,66 @@ var ( // header and a reconstructed header are used in misbehaviour submission to // the IBC client on the source chain. func checkAndSubmitMisbehaviour(src *Chain, events map[string][]string) error { - if hdrs, ok := events[fmt.Sprintf("%s.%s", updateCliTag, headerTag)]; ok { - for i, hdr := range hdrs { - clientIDs := events[fmt.Sprintf("%s.%s", updateCliTag, clientIDTag)] - emittedClientID := clientIDs[i] + hdrs, ok := events[fmt.Sprintf("%s.%s", updateCliTag, headerTag)] + if !ok { + return nil + } + for i, hdr := range hdrs { + clientIDs := events[fmt.Sprintf("%s.%s", updateCliTag, clientIDTag)] + if len(clientIDs) <= i { + return fmt.Errorf("emitted client-ids count is less than emitted headers count") + } - if src.PathEnd.ClientID == emittedClientID { - hdrBytes, err := hex.DecodeString(hdr) - if err != nil { - return err - } + emittedClientID := clientIDs[i] + if src.PathEnd.ClientID != emittedClientID { + continue + } - exportedHeader, err := clienttypes.UnmarshalHeader(src.Encoding.Marshaler, hdrBytes) - if err != nil { - return err - } + hdrBytes, err := hex.DecodeString(hdr) + if err != nil { + return sdkerrors.Wrapf(err, "failed decoding hexadecimal string of header with client-id: %s", + emittedClientID) + } - emittedHeader, ok := exportedHeader.(*tmclient.Header) - if !ok { - return fmt.Errorf("emitted header is not tendermint type") - } + exportedHeader, err := clienttypes.UnmarshalHeader(src.Encoding.Marshaler, hdrBytes) + if err != nil { + return sdkerrors.Wrapf(err, "failed unmarshaling header with client-id: %s", emittedClientID) + } - trustedHeader, err := src.GetLightSignedHeaderAtHeight(emittedHeader.Header.Height) - if err != nil { - return err - } + emittedHeader, ok := exportedHeader.(*tmclient.Header) + if !ok { + return fmt.Errorf("emitted header is not tendermint type") + } - if !IsMatchingConsensusState(emittedHeader.ConsensusState(), trustedHeader.ConsensusState()) { - trustedHeader.TrustedValidators = emittedHeader.TrustedValidators - trustedHeader.TrustedHeight = emittedHeader.TrustedHeight + trustedHeader, err := src.GetLightSignedHeaderAtHeight(emittedHeader.Header.Height) + if err != nil { + return err + } - misbehaviour := tmclient.NewMisbehaviour(emittedClientID, emittedHeader, trustedHeader) - msg, err := clienttypes.NewMsgSubmitMisbehaviour(emittedClientID, misbehaviour, src.MustGetAddress()) - if err != nil { - return err - } - res, success, err := src.SendMsg(msg) - if err != nil { - return err - } - if !success { - return fmt.Errorf("submit misbehaviour tx failed: %s", res.RawLog) - } - src.Log(fmt.Sprintf("Submitted misbehaviour for emitted header with height: %d", - emittedHeader.Header.Height)) - } - } + if IsMatchingConsensusState(emittedHeader.ConsensusState(), trustedHeader.ConsensusState()) { + continue + } + + trustedHeader.TrustedValidators = emittedHeader.TrustedValidators + trustedHeader.TrustedHeight = emittedHeader.TrustedHeight + + misbehaviour := tmclient.NewMisbehaviour(emittedClientID, emittedHeader, trustedHeader) + msg, err := clienttypes.NewMsgSubmitMisbehaviour(emittedClientID, misbehaviour, src.MustGetAddress()) + if err != nil { + return err + } + if err := msg.ValidateBasic(); err != nil { + return err + } + res, success, err := src.SendMsg(msg) + if err != nil { + return err + } + if !success { + return fmt.Errorf("submit misbehaviour tx failed: %s", res.RawLog) } + src.Log(fmt.Sprintf("Submitted misbehaviour for emitted header with height: %d", + emittedHeader.Header.Height)) } return nil