Skip to content

Commit

Permalink
Emit header in MsgUpdateClient events (#8624)
Browse files Browse the repository at this point in the history
* emit header in update client msg

* update CHANGELOG

* update spec

* fix nil header bug

* use JSON encoding for emitting header

* Update x/ibc/core/spec/06_events.md

* use proto for encoding

* add tests

* encode to hex before emitting header in event

* add comment addressing reasoning for hex encoding

* Update CHANGELOG.md

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

Co-authored-by: Alessio Treglia <alessio@tendermint.com>
Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
(cherry picked from commit a9b034b)

# Conflicts:
#	CHANGELOG.md
  • Loading branch information
colin-axner authored and mergify-bot committed Mar 3, 2021
1 parent 3aaf1bc commit dfea11d
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 4 deletions.
15 changes: 15 additions & 0 deletions CHANGELOG.md
Expand Up @@ -53,8 +53,23 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Improvements

* (store/cachekv), (x/bank/types) [\#8719](https://github.com/cosmos/cosmos-sdk/pull/8719) algorithmically fix pathologically slow code
<<<<<<< HEAD
* [\#8701](https://github.com/cosmos/cosmos-sdk/pull/8701) Upgrade tendermint v0.34.8.
* [\#8714](https://github.com/cosmos/cosmos-sdk/pull/8714) Allow accounts to have a balance of 0 at genesis.
=======
* (x/ibc) [\#8624](https://github.com/cosmos/cosmos-sdk/pull/8624) Emit full header in IBC UpdateClient message.

### Bug Fixes

* (keyring) [#\8635](https://github.com/cosmos/cosmos-sdk/issues/8635) Remove hardcoded default passphrase value on `NewMnemonic`
* (x/evidence) [#8461](https://github.com/cosmos/cosmos-sdk/pull/8461) Fix bech32 prefix in evidence validator address conversion
* (x/bank) [\#8434](https://github.com/cosmos/cosmos-sdk/pull/8434) Fix legacy REST API `GET /bank/total` and `GET /bank/total/{denom}` in swagger
* (x/slashing) [\#8427](https://github.com/cosmos/cosmos-sdk/pull/8427) Fix query signing infos command
* (server) [\#8399](https://github.com/cosmos/cosmos-sdk/pull/8399) fix gRPC-web flag default value
* (server) [\#8641](https://github.com/cosmos/cosmos-sdk/pull/8641) Fix Tendermint and application configuration reading from file
* (rest) [\#8730](https://github.com/cosmos/cosmos-sdk/pull/8730) Fix querying txs with multisigs on legacy REST endpoints.
* (client/keys) [\#8639] (https://github.com/cosmos/cosmos-sdk/pull/8639) Fix keys migrate for mulitisig, offline, and ledger keys. The migrate command now takes a positional old_home_dir argument.
>>>>>>> a9b034b5f... Emit header in MsgUpdateClient events (#8624)
## [v0.41.3](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.41.3) - 2021-02-18

Expand Down
13 changes: 13 additions & 0 deletions x/ibc/core/02-client/keeper/client.go
@@ -1,6 +1,8 @@
package keeper

import (
"encoding/hex"

"github.com/armon/go-metrics"

"github.com/cosmos/cosmos-sdk/telemetry"
Expand Down Expand Up @@ -95,13 +97,24 @@ func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.H
)
}()

// emit the full header in events
var headerStr string
if header != nil {
// Marshal the Header as an Any and encode the resulting bytes to hex.
// This prevents the event value from containing invalid UTF-8 characters
// which may cause data to be lost when JSON encoding/decoding.
headerStr = hex.EncodeToString(types.MustMarshalHeader(k.cdc, header))

}

// emitting events in the keeper emits for both begin block and handler client updates
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeUpdateClient,
sdk.NewAttribute(types.AttributeKeyClientID, clientID),
sdk.NewAttribute(types.AttributeKeyClientType, clientState.ClientType()),
sdk.NewAttribute(types.AttributeKeyConsensusHeight, consensusHeight.String()),
sdk.NewAttribute(types.AttributeKeyHeader, headerStr),
),
)

Expand Down
37 changes: 37 additions & 0 deletions x/ibc/core/02-client/keeper/client_test.go
@@ -1,6 +1,7 @@
package keeper_test

import (
"encoding/hex"
"fmt"
"time"

Expand Down Expand Up @@ -601,3 +602,39 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() {
})
}
}

func (suite *KeeperTestSuite) TestUpdateClientEventEmission() {
clientID, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint)
header, err := suite.chainA.ConstructUpdateTMClientHeader(suite.chainB, clientID)
suite.Require().NoError(err)

msg, err := clienttypes.NewMsgUpdateClient(
clientID, header,
suite.chainA.SenderAccount.GetAddress(),
)

result, err := suite.chainA.SendMsgs(msg)
suite.Require().NoError(err)
// first event type is "message"
updateEvent := result.Events[1]

suite.Require().Equal(clienttypes.EventTypeUpdateClient, updateEvent.Type)

// use a boolean to ensure the update event contains the header
contains := false
for _, attr := range updateEvent.Attributes {
if string(attr.Key) == clienttypes.AttributeKeyHeader {
contains = true

bz, err := hex.DecodeString(string(attr.Value))
suite.Require().NoError(err)

emittedHeader, err := types.UnmarshalHeader(suite.chainA.App.AppCodec(), bz)
suite.Require().NoError(err)
suite.Require().Equal(header, emittedHeader)
}

}
suite.Require().True(contains)

}
33 changes: 30 additions & 3 deletions x/ibc/core/02-client/types/encoding.go
Expand Up @@ -57,7 +57,7 @@ func MustUnmarshalConsensusState(cdc codec.BinaryMarshaler, bz []byte) exported.
return consensusState
}

// MustMarshalConsensusState attempts to encode an ConsensusState object and returns the
// MustMarshalConsensusState attempts to encode a ConsensusState object and returns the
// raw encoded bytes. It panics on error.
func MustMarshalConsensusState(cdc codec.BinaryMarshaler, consensusState exported.ConsensusState) []byte {
bz, err := MarshalConsensusState(cdc, consensusState)
Expand All @@ -68,12 +68,12 @@ func MustMarshalConsensusState(cdc codec.BinaryMarshaler, consensusState exporte
return bz
}

// MarshalConsensusState protobuf serializes an ConsensusState interface
// MarshalConsensusState protobuf serializes a ConsensusState interface
func MarshalConsensusState(cdc codec.BinaryMarshaler, cs exported.ConsensusState) ([]byte, error) {
return cdc.MarshalInterface(cs)
}

// UnmarshalConsensusState returns an ConsensusState interface from raw encoded clientState
// UnmarshalConsensusState returns a ConsensusState interface from raw encoded consensus state
// bytes of a Proto-based ConsensusState type. An error is returned upon decoding
// failure.
func UnmarshalConsensusState(cdc codec.BinaryMarshaler, bz []byte) (exported.ConsensusState, error) {
Expand All @@ -84,3 +84,30 @@ func UnmarshalConsensusState(cdc codec.BinaryMarshaler, bz []byte) (exported.Con

return consensusState, nil
}

// MarshalHeader protobuf serializes a Header interface
func MarshalHeader(cdc codec.BinaryMarshaler, h exported.Header) ([]byte, error) {
return cdc.MarshalInterface(h)
}

// MustMarshalHeader attempts to encode a Header object and returns the
// raw encoded bytes. It panics on error.
func MustMarshalHeader(cdc codec.BinaryMarshaler, header exported.Header) []byte {
bz, err := MarshalHeader(cdc, header)
if err != nil {
panic(fmt.Errorf("failed to encode header: %w", err))
}

return bz
}

// UnmarshalHeader returns a Header interface from raw proto encoded header bytes.
// An error is returned upon decoding failure.
func UnmarshalHeader(cdc codec.BinaryMarshaler, bz []byte) (exported.Header, error) {
var header exported.Header
if err := cdc.UnmarshalInterface(bz, &header); err != nil {
return nil, err
}

return header, nil
}
30 changes: 30 additions & 0 deletions x/ibc/core/02-client/types/encoding_test.go
@@ -0,0 +1,30 @@
package types_test

import (
"github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types"
)

func (suite *TypesTestSuite) TestMarshalHeader() {

cdc := suite.chainA.App.AppCodec()
h := &ibctmtypes.Header{
TrustedHeight: types.NewHeight(4, 100),
}

// marshal header
bz, err := types.MarshalHeader(cdc, h)
suite.Require().NoError(err)

// unmarshal header
newHeader, err := types.UnmarshalHeader(cdc, bz)
suite.Require().NoError(err)

suite.Require().Equal(h, newHeader)

// use invalid bytes
invalidHeader, err := types.UnmarshalHeader(cdc, []byte("invalid bytes"))
suite.Require().Error(err)
suite.Require().Nil(invalidHeader)

}
1 change: 1 addition & 0 deletions x/ibc/core/02-client/types/events.go
Expand Up @@ -11,6 +11,7 @@ const (
AttributeKeyClientID = "client_id"
AttributeKeyClientType = "client_type"
AttributeKeyConsensusHeight = "consensus_height"
AttributeKeyHeader = "header"
)

// IBC client events vars
Expand Down
2 changes: 1 addition & 1 deletion x/ibc/core/spec/06_events.md
Expand Up @@ -32,6 +32,7 @@ callbacks to IBC applications.
| update_client | client_id | {clientId} |
| update_client | client_type | {clientType} |
| update_client | consensus_height | {consensusHeight} |
| update_client | header | {header} |
| message | action | update_client |
| message | module | ibc_client |

Expand Down Expand Up @@ -238,4 +239,3 @@ callbacks to IBC applications.
| message | action | timeout_packet |
| message | module | ibc-channel |


0 comments on commit dfea11d

Please sign in to comment.