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

imp: add query and sudo message types to encapsulate all variants of calls #4133

45 changes: 6 additions & 39 deletions modules/light-clients/08-wasm/types/client_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,6 @@ func (cs ClientState) Validate() error {
return nil
}

type (
statusInnerPayload struct{}
statusPayload struct {
Status statusInnerPayload `json:"status"`
}
)

// Status returns the status of the wasm client.
// The client may be:
// - Active: frozen height is zero and client is not expired
Expand All @@ -71,7 +64,7 @@ type (
// A frozen client will become expired, so the Frozen status
// has higher precedence.
func (cs ClientState) Status(ctx sdk.Context, clientStore sdk.KVStore, _ codec.BinaryCodec) exported.Status {
payload := statusPayload{Status: statusInnerPayload{}}
payload := QueryMsg{Status: &statusMsg{}}

encodedData, err := json.Marshal(payload)
if err != nil {
Expand All @@ -96,6 +89,7 @@ func (cs ClientState) ZeroCustomFields() exported.ClientState {
return &cs
}

// GetTimestampAtHeight returns the timestamp in nanoseconds of the consensus state at the given height.
func (cs ClientState) GetTimestampAtHeight(
_ sdk.Context,
clientStore sdk.KVStore,
Expand Down Expand Up @@ -129,20 +123,6 @@ func (cs ClientState) Initialize(ctx sdk.Context, marshaler codec.BinaryCodec, c
return nil
}

type (
verifyMembershipInnerPayload struct {
Height exported.Height `json:"height"`
DelayTimePeriod uint64 `json:"delay_time_period"`
DelayBlockPeriod uint64 `json:"delay_block_period"`
Proof []byte `json:"proof"`
Path exported.Path `json:"path"`
Value []byte `json:"value"`
}
verifyMembershipPayload struct {
VerifyMembership verifyMembershipInnerPayload `json:"verify_membership"`
}
)

// VerifyMembership is a generic proof verification method which verifies a proof of the existence of a value at a given CommitmentPath at the specified height.
// The caller is expected to construct the full CommitmentPath from a CommitmentPrefix and a standardized path (as defined in ICS 24).
// If a zero proof height is passed in, it will fail to retrieve the associated consensus state.
Expand Down Expand Up @@ -174,8 +154,8 @@ func (cs ClientState) VerifyMembership(
return errorsmod.Wrap(err, "please ensure the proof was constructed against a height that exists on the client")
}

payload := verifyMembershipPayload{
VerifyMembership: verifyMembershipInnerPayload{
payload := QueryMsg{
VerifyMembership: &verifyMembershipMsg{
Height: height,
DelayTimePeriod: delayTimePeriod,
DelayBlockPeriod: delayBlockPeriod,
Expand All @@ -188,19 +168,6 @@ func (cs ClientState) VerifyMembership(
return err
}

type (
verifyNonMembershipInnerPayload struct {
Height exported.Height `json:"height"`
DelayTimePeriod uint64 `json:"delay_time_period"`
DelayBlockPeriod uint64 `json:"delay_block_period"`
Proof []byte `json:"proof"`
Path exported.Path `json:"path"`
}
verifyNonMembershipPayload struct {
VerifyNonMembership verifyNonMembershipInnerPayload `json:"verify_non_membership"`
}
)

// VerifyNonMembership is a generic proof verification method which verifies the absence of a given CommitmentPath at a specified height.
// The caller is expected to construct the full CommitmentPath from a CommitmentPrefix and a standardized path (as defined in ICS 24).
// If a zero proof height is passed in, it will fail to retrieve the associated consensus state.
Expand Down Expand Up @@ -231,8 +198,8 @@ func (cs ClientState) VerifyNonMembership(
return errorsmod.Wrap(err, "please ensure the proof was constructed against a height that exists on the client")
}

payload := verifyNonMembershipPayload{
VerifyNonMembership: verifyNonMembershipInnerPayload{
payload := QueryMsg{
VerifyNonMembership: &verifyNonMembershipMsg{
Height: height,
DelayTimePeriod: delayTimePeriod,
DelayBlockPeriod: delayBlockPeriod,
Expand Down
11 changes: 3 additions & 8 deletions modules/light-clients/08-wasm/types/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,6 @@ import (
"github.com/cosmos/ibc-go/v7/modules/core/exported"
)

type (
exportMetadataInnerPayload struct{}
exportMetadataPayload struct {
ExportMetadata exportMetadataInnerPayload `json:"export_metadata"`
}
)

// NewGenesisState creates an 08-wasm GenesisState instance.
func NewGenesisState(contracts []GenesisContract) *GenesisState {
return &GenesisState{Contracts: contracts}
Expand All @@ -26,7 +19,9 @@ func NewGenesisState(contracts []GenesisContract) *GenesisState {
// ExportMetadata exports all the consensus metadata in the client store so they
// can be included in clients genesis and imported by a ClientKeeper
func (cs ClientState) ExportMetadata(store sdk.KVStore) []exported.GenesisMetadata {
var payload exportMetadataPayload
payload := QueryMsg{
ExportMetadata: &exportMetadataMsg{},
}

encodedData, err := json.Marshal(payload)
if err != nil {
Expand Down
24 changes: 6 additions & 18 deletions modules/light-clients/08-wasm/types/misbehaviour_handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,26 @@ import (
"github.com/cosmos/ibc-go/v7/modules/core/exported"
)

type (
checkForMisbehaviourInnerPayload struct {
ClientMessage clientMessage `json:"client_message"`
}
checkForMisbehaviourPayload struct {
CheckForMisbehaviour checkForMisbehaviourInnerPayload `json:"check_for_misbehaviour"`
}
)

// CheckForMisbehaviour detects misbehaviour in a submitted Header message and verifies
// the correctness of a submitted Misbehaviour ClientMessage
func (cs ClientState) CheckForMisbehaviour(ctx sdk.Context, _ codec.BinaryCodec, clientStore sdk.KVStore, msg exported.ClientMessage) bool {
clientMsgConcrete := clientMessage{
checkForMisbehaviourMsg := checkForMisbehaviourMsg{
Header: nil,
Misbehaviour: nil,
}
switch clientMsg := msg.(type) {
case *Header:
clientMsgConcrete.Header = clientMsg
checkForMisbehaviourMsg.Header = clientMsg
case *Misbehaviour:
clientMsgConcrete.Misbehaviour = clientMsg
checkForMisbehaviourMsg.Misbehaviour = clientMsg
}

if clientMsgConcrete.Header == nil && clientMsgConcrete.Misbehaviour == nil {
if checkForMisbehaviourMsg.Header == nil && checkForMisbehaviourMsg.Misbehaviour == nil {
return false
}

inner := checkForMisbehaviourInnerPayload{
ClientMessage: clientMsgConcrete,
}
payload := checkForMisbehaviourPayload{
CheckForMisbehaviour: inner,
payload := QueryMsg{
CheckForMisbehaviour: &checkForMisbehaviourMsg,
}

result, err := call[contractResult](ctx, clientStore, &cs, payload)
Expand Down
72 changes: 72 additions & 0 deletions modules/light-clients/08-wasm/types/msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package types

import (
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/cosmos/ibc-go/v7/modules/core/exported"
)

var _ sdk.Msg = (*MsgStoreCode)(nil)
Expand Down Expand Up @@ -33,3 +35,73 @@ func (m MsgStoreCode) GetSigners() []sdk.AccAddress {
}
return []sdk.AccAddress{signer}
}

type QueryMsg struct {
crodriguezvega marked this conversation as resolved.
Show resolved Hide resolved
crodriguezvega marked this conversation as resolved.
Show resolved Hide resolved
Status *statusMsg `json:"status,omitempty"`
ExportMetadata *exportMetadataMsg `json:"export_metadata,omitempty"`
TimestampAtHeight *timestampAtHeightMsg `json:"timestamp_at_height,omitempty"`
VerifyClientMessage *verifyClientMessageMsg `json:"verify_client_message,omitempty"`
VerifyMembership *verifyMembershipMsg `json:"verify_membership,omitempty"`
VerifyNonMembership *verifyNonMembershipMsg `json:"verify_non_membership,omitempty"`
CheckForMisbehaviour *checkForMisbehaviourMsg `json:"check_for_misbehaviour,omitempty"`
}

type (
crodriguezvega marked this conversation as resolved.
Show resolved Hide resolved
statusMsg struct{}
exportMetadataMsg struct{}
timestampAtHeightMsg struct {
Height exported.Height `json:"height"`
}
verifyClientMessageMsg struct {
Header *Header `json:"header,omitempty"`
Misbehaviour *Misbehaviour `json:"misbehaviour,omitempty"`
}
verifyMembershipMsg struct {
Height exported.Height `json:"height"`
DelayTimePeriod uint64 `json:"delay_time_period"`
DelayBlockPeriod uint64 `json:"delay_block_period"`
Proof []byte `json:"proof"`
Path exported.Path `json:"path"`
Value []byte `json:"value"`
}
verifyNonMembershipMsg struct {
Height exported.Height `json:"height"`
DelayTimePeriod uint64 `json:"delay_time_period"`
DelayBlockPeriod uint64 `json:"delay_block_period"`
Proof []byte `json:"proof"`
Path exported.Path `json:"path"`
}
checkForMisbehaviourMsg struct {
Header *Header `json:"header,omitempty"`
Misbehaviour *Misbehaviour `json:"misbehaviour,omitempty"`
}
)

type SudoMsg struct {
crodriguezvega marked this conversation as resolved.
Show resolved Hide resolved
Initialize *initializeMsg `json:"initialize,omitempty"`
UpdateState *updateStateMsg `json:"update_state,omitempty"`
UpdateStateOnMisbehaviour *updateStateOnMisbehaviourMsg `json:"update_state_on_misbehaviour,omitempty"`
VerifyUpgradeAndUpdateState *verifyUpgradeAndUpdateStateMsg `json:"verify_upgrade_and_update_state,omitempty"`
CheckSubstituteAndUpdateState *checkSubstituteAndUpdateStateMsg `json:"check_substitute_and_update_state,omitempty"`
}

type (
initializeMsg struct {
ClientState *ClientState `json:"client_state"`
ConsensusState *ConsensusState `json:"consensus_state"`
}
updateStateMsg struct {
Header *Header `json:"header,omitempty"`
}
updateStateOnMisbehaviourMsg struct {
Header *Header `json:"header,omitempty"`
Misbehaviour *Misbehaviour `json:"misbehaviour,omitempty"`
}
verifyUpgradeAndUpdateStateMsg struct {
UpgradeClientState exported.ClientState `json:"upgrade_client_state"`
UpgradeConsensusState exported.ConsensusState `json:"upgrade_consensus_state"`
ProofUpgradeClient []byte `json:"proof_upgrade_client"`
ProofUpgradeConsensusState []byte `json:"proof_upgrade_consensus_state"`
}
checkSubstituteAndUpdateStateMsg struct{}
)
11 changes: 2 additions & 9 deletions modules/light-clients/08-wasm/types/proposal_handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,6 @@ import (
"github.com/cosmos/ibc-go/v7/modules/core/exported"
)

type (
checkSubstituteAndUpdateStateInnerPayload struct{}
checkSubstituteAndUpdateStatePayload struct {
CheckSubstituteAndUpdateState checkSubstituteAndUpdateStateInnerPayload `json:"check_substitute_and_update_state"`
}
)

// CheckSubstituteAndUpdateState will try to update the client with the state of the
// substitute.
func (cs ClientState) CheckSubstituteAndUpdateState(
Expand All @@ -42,8 +35,8 @@ func (cs ClientState) CheckSubstituteAndUpdateState(

store := newWrappedStore(subjectClientStore, substituteClientStore, SubjectPrefix, SubstitutePrefix)

payload := checkSubstituteAndUpdateStatePayload{
CheckSubstituteAndUpdateState: checkSubstituteAndUpdateStateInnerPayload{},
payload := SudoMsg{
CheckSubstituteAndUpdateState: &checkSubstituteAndUpdateStateMsg{},
}

_, err := call[contractResult](ctx, store, &cs, payload)
Expand Down
66 changes: 12 additions & 54 deletions modules/light-clients/08-wasm/types/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,66 +11,37 @@ import (

var _ exported.ClientState = (*ClientState)(nil)

type (
verifyClientMessageInnerPayload struct {
ClientMessage clientMessage `json:"client_message"`
}
clientMessage struct {
Header *Header `json:"header,omitempty"`
Misbehaviour *Misbehaviour `json:"misbehaviour,omitempty"`
}
verifyClientMessagePayload struct {
VerifyClientMessage verifyClientMessageInnerPayload `json:"verify_client_message"`
}
)

// VerifyClientMessage must verify a ClientMessage. A ClientMessage could be a Header, Misbehaviour, or batch update.
// It must handle each type of ClientMessage appropriately. Calls to CheckForMisbehaviour, UpdateState, and UpdateStateOnMisbehaviour
// will assume that the content of the ClientMessage has been verified and can be trusted. An error should be returned
// if the ClientMessage fails to verify.
func (cs ClientState) VerifyClientMessage(ctx sdk.Context, _ codec.BinaryCodec, clientStore sdk.KVStore, clientMsg exported.ClientMessage) error {
clientMsgConcrete := clientMessage{
verifyClientMessageMsg := verifyClientMessageMsg{
Header: nil,
Misbehaviour: nil,
}
switch clientMsg := clientMsg.(type) {
case *Header:
clientMsgConcrete.Header = clientMsg
verifyClientMessageMsg.Header = clientMsg
case *Misbehaviour:
clientMsgConcrete.Misbehaviour = clientMsg
}
inner := verifyClientMessageInnerPayload{
ClientMessage: clientMsgConcrete,
verifyClientMessageMsg.Misbehaviour = clientMsg
}
payload := verifyClientMessagePayload{
VerifyClientMessage: inner,
payload := QueryMsg{
VerifyClientMessage: &verifyClientMessageMsg,
}
_, err := call[contractResult](ctx, clientStore, &cs, payload)
return err
}

type (
updateStateInnerPayload struct {
ClientMessage clientMessage `json:"client_message"`
}
updateStatePayload struct {
UpdateState updateStateInnerPayload `json:"update_state"`
}
)

// Client state and new consensus states are updated in the store by the contract
func (cs ClientState) UpdateState(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, clientMsg exported.ClientMessage) []exported.Height {
header, ok := clientMsg.(*Header)
if !ok {
panic(fmt.Errorf("expected type %T, got %T", &Header{}, clientMsg))
}

payload := updateStatePayload{
UpdateState: updateStateInnerPayload{
ClientMessage: clientMessage{
Header: header,
},
},
payload := SudoMsg{
UpdateState: &updateStateMsg{Header: header},
}

_, err := call[contractResult](ctx, clientStore, &cs, payload)
Expand All @@ -81,32 +52,19 @@ func (cs ClientState) UpdateState(ctx sdk.Context, cdc codec.BinaryCodec, client
return []exported.Height{clientMsg.(*Header).Height}
}

type (
updateStateOnMisbehaviourInnerPayload struct {
ClientMessage clientMessage `json:"client_message"`
}
updateStateOnMisbehaviourPayload struct {
UpdateStateOnMisbehaviour updateStateOnMisbehaviourInnerPayload `json:"update_state_on_misbehaviour"`
}
)

// UpdateStateOnMisbehaviour should perform appropriate state changes on a client state given that misbehaviour has been detected and verified
// Client state is updated in the store by contract.
func (cs ClientState) UpdateStateOnMisbehaviour(ctx sdk.Context, _ codec.BinaryCodec, clientStore sdk.KVStore, clientMsg exported.ClientMessage) {
var clientMsgConcrete clientMessage
var updateStateOnMisbehaviourMsg updateStateOnMisbehaviourMsg
switch clientMsg := clientMsg.(type) {
case *Header:
clientMsgConcrete.Header = clientMsg
updateStateOnMisbehaviourMsg.Header = clientMsg
case *Misbehaviour:
clientMsgConcrete.Misbehaviour = clientMsg
}

inner := updateStateOnMisbehaviourInnerPayload{
ClientMessage: clientMsgConcrete,
updateStateOnMisbehaviourMsg.Misbehaviour = clientMsg
}

payload := updateStateOnMisbehaviourPayload{
UpdateStateOnMisbehaviour: inner,
payload := SudoMsg{
UpdateStateOnMisbehaviour: &updateStateOnMisbehaviourMsg,
}

_, err := call[contractResult](ctx, clientStore, &cs, payload)
Expand Down
Loading
Loading