Skip to content

Commit

Permalink
chore: 06-solomachine rename checkHeader to VerifyClientMessage (#1109)
Browse files Browse the repository at this point in the history
* adding VerifyClientMessage and tests

* splitting tests for verify header and misbehaviour

* cleaning up error handling

* adding additional test for old misbehaviour is sucessful

* split type switch logic into verifyHeader and verifyMisbehaviour priv funcs

* updating godoc for VerifyClientMessage
  • Loading branch information
damiannolan authored Mar 16, 2022
1 parent ebf40bb commit b0fa240
Show file tree
Hide file tree
Showing 2 changed files with 436 additions and 15 deletions.
58 changes: 44 additions & 14 deletions modules/light-clients/06-solomachine/types/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,38 +17,52 @@ import (
// - the currently registered public key did not provide the update signature
func (cs ClientState) CheckHeaderAndUpdateState(
ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore,
header exported.ClientMessage,
msg exported.ClientMessage,
) (exported.ClientState, exported.ConsensusState, error) {
smHeader, ok := header.(*Header)
if err := cs.VerifyClientMessage(ctx, cdc, clientStore, msg); err != nil {
return nil, nil, err
}

// TODO: Remove this type assertion, replace with misbehaviour checking and update state
smHeader, ok := msg.(*Header)
if !ok {
return nil, nil, sdkerrors.Wrapf(
clienttypes.ErrInvalidHeader, "header type %T, expected %T", header, &Header{},
clienttypes.ErrInvalidHeader, "expected %T, got %T", &Header{}, msg,
)
}

if err := checkHeader(cdc, &cs, smHeader); err != nil {
return nil, nil, err
}

clientState, consensusState := update(&cs, smHeader)
return clientState, consensusState, nil
}

// checkHeader checks if the Solo Machine update signature is valid.
func checkHeader(cdc codec.BinaryCodec, clientState *ClientState, header *Header) error {
// VerifyClientMessage introspects the provided ClientMessage and checks its validity
// A Solomachine Header is considered valid if the currently registered public key has signed over the new public key with the correct sequence
// A Solomachine Misbehaviour is considered valid if duplicate signatures of the current public key are found on two different messages at a given sequence
func (cs ClientState) VerifyClientMessage(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, clientMsg exported.ClientMessage) error {
switch msg := clientMsg.(type) {
case *Header:
return cs.verifyHeader(ctx, cdc, clientStore, msg)
case *Misbehaviour:
return cs.verifyMisbehaviour(ctx, cdc, clientStore, msg)
default:
return sdkerrors.Wrapf(clienttypes.ErrInvalidClientType, "expected type of %T or %T, got type %T", Header{}, Misbehaviour{}, msg)
}
}

func (cs ClientState) verifyHeader(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, header *Header) error {
// assert update sequence is current sequence
if header.Sequence != clientState.Sequence {
if header.Sequence != cs.Sequence {
return sdkerrors.Wrapf(
clienttypes.ErrInvalidHeader,
"header sequence does not match the client state sequence (%d != %d)", header.Sequence, clientState.Sequence,
"header sequence does not match the client state sequence (%d != %d)", header.Sequence, cs.Sequence,
)
}

// assert update timestamp is not less than current consensus state timestamp
if header.Timestamp < clientState.ConsensusState.Timestamp {
if header.Timestamp < cs.ConsensusState.Timestamp {
return sdkerrors.Wrapf(
clienttypes.ErrInvalidHeader,
"header timestamp is less than to the consensus state timestamp (%d < %d)", header.Timestamp, clientState.ConsensusState.Timestamp,
"header timestamp is less than to the consensus state timestamp (%d < %d)", header.Timestamp, cs.ConsensusState.Timestamp,
)
}

Expand All @@ -63,7 +77,7 @@ func checkHeader(cdc codec.BinaryCodec, clientState *ClientState, header *Header
return err
}

publicKey, err := clientState.ConsensusState.GetPubKey()
publicKey, err := cs.ConsensusState.GetPubKey()
if err != nil {
return err
}
Expand All @@ -75,6 +89,22 @@ func checkHeader(cdc codec.BinaryCodec, clientState *ClientState, header *Header
return nil
}

func (cs ClientState) verifyMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore sdk.KVStore, misbehaviour *Misbehaviour) error {
// NOTE: a check that the misbehaviour message data are not equal is done by
// misbehaviour.ValidateBasic which is called by the 02-client keeper.
// verify first signature
if err := verifySignatureAndData(cdc, cs, misbehaviour, misbehaviour.SignatureOne); err != nil {
return sdkerrors.Wrap(err, "failed to verify signature one")
}

// verify second signature
if err := verifySignatureAndData(cdc, cs, misbehaviour, misbehaviour.SignatureTwo); err != nil {
return sdkerrors.Wrap(err, "failed to verify signature two")
}

return nil
}

// update the consensus state to the new public key and an incremented sequence
func update(clientState *ClientState, header *Header) (*ClientState, *ConsensusState) {
consensusState := &ConsensusState{
Expand Down
Loading

0 comments on commit b0fa240

Please sign in to comment.