diff --git a/spec/client/ics-006-solo-machine-client/README.md b/spec/client/ics-006-solo-machine-client/README.md index 29e3f2266..a2df3a3ab 100644 --- a/spec/client/ics-006-solo-machine-client/README.md +++ b/spec/client/ics-006-solo-machine-client/README.md @@ -212,6 +212,20 @@ function verifyMisbehaviour(misbehaviour: Misbehaviour) { } ``` +### Retrieve client status + +Return the status of the solo machine client. Status can be either `Active` or `Frozen`. + +```typescript +// returns the status of a client +function Status (clientIdentifier: Identifier, clientState: clientState): Status { + if clientState.frozen == true + return Frozen + } + return Active +} +``` + ### Misbehaviour predicate Since misbehaviour is checked in `verifyClientMessage`, if the client message is of type `Misbehaviour` then we return true: diff --git a/spec/client/ics-007-tendermint-client/README.md b/spec/client/ics-007-tendermint-client/README.md index aa706e24b..a3bfb75db 100644 --- a/spec/client/ics-007-tendermint-client/README.md +++ b/spec/client/ics-007-tendermint-client/README.md @@ -238,6 +238,31 @@ function verifyHeader(header: Header) { } ``` +### Retrieve client status + +Return the Status of the Tendermint client. Status can be either `Active`, `Expired` or `Frozen`. + +```typescript +// returns the status of a client +function Status (clientIdentifier: Identifier, clientState: clientState): Status { + if (clientState.frozenHeight !== 0) { + return Frozen + } + // get consensus state for the latest height + height = clientState.latestClientHeight() + consensusState = provableStore.get("clients/{clientIdentifier}/consensusStates/{height}") + if consensusState == nil { + return Expired + } + // check if the trusting period has passed since the last update + let expirationTime := consensusState.timestamp + clientState.trustingPeriod + if (expirationTime <= now){ + return Expired + } + return Active +} +``` + ### Misbehaviour predicate Function `checkForMisbehaviour` will check if an update contains evidence of Misbehaviour. If the ClientMessage is a header we check for implicit evidence of misbehaviour by checking if there already exists a conflicting consensus state in the store or if the header breaks time monotonicity. diff --git a/spec/client/ics-008-wasm-client/README.md b/spec/client/ics-008-wasm-client/README.md index 3be041ff0..fa5dfa39f 100644 --- a/spec/client/ics-008-wasm-client/README.md +++ b/spec/client/ics-008-wasm-client/README.md @@ -201,6 +201,28 @@ function verifyClientMessage(clientMsg: ClientMessage) { } ``` +### Retrieve client status + +Return the status of the wasm client. Status can be either `Active`, `Expired`, `Unknown` or `Frozen`. + +```typescript +interface StatusMsg {} +``` + +```typescript +// returns the status of a client +function Status(clientIdentifier: Identifier, clientState: clientState): Status { + payload = StatusMsg{} + + // retrieve client identifier-prefixed store + clientStore = provableStore.prefixStore("clients/{clientIdentifier}") + + // use underlying wasm contract to retrieve the status + result = callContract(clientStore, clientState, marshalJSON(payload)) + return Status(result.status) +} +``` + ### Misbehaviour predicate Function `checkForMisbehaviour` will check if an update contains evidence of misbehaviour. Wasm client misbehaviour checking determines whether or not two conflicting headers at the same height would have convinced the light client. diff --git a/spec/core/ics-002-client-semantics/README.md b/spec/core/ics-002-client-semantics/README.md index df0ec4d90..2cf58fbd1 100644 --- a/spec/core/ics-002-client-semantics/README.md +++ b/spec/core/ics-002-client-semantics/README.md @@ -337,6 +337,25 @@ Once misbehaviour is detected, clients SHOULD be frozen so that no future update A permissioned entity such as a chain governance system or trusted multi-signature MAY be allowed to intervene to unfreeze a frozen client & provide a new correct ClientMessage which updates the client to a valid state. +#### Retrieve client status + +Status is an opaque function defined by a client type to retrieve the current clientState. Status can be either `Active`, `Expired`, `Unknown` or `Frozen`. + +```typescript +enum Status { + Unknown + Active + Expired + Frozen +} +``` + +The function is defined as: + +```typescript +type Status = (Identifier, Client) => Status +``` + #### `CommitmentProof` `CommitmentProof` is an opaque data structure defined by a client type in accordance with [ICS 23](../ics-023-vector-commitments). diff --git a/spec/core/ics-004-channel-and-packet-semantics/README.md b/spec/core/ics-004-channel-and-packet-semantics/README.md index 0f439ece8..d72ba9b9d 100644 --- a/spec/core/ics-004-channel-and-packet-semantics/README.md +++ b/spec/core/ics-004-channel-and-packet-semantics/README.md @@ -743,6 +743,7 @@ The IBC handler performs the following steps in order: - Checks that the channel is not closed to send packets - Checks that the calling module owns the sending port (see [ICS 5](../ics-005-port-allocation)) +- Checks that the client is not frozen or expired - Checks that the timeout height specified has not already passed on the destination chain - Increments the send sequence counter associated with the channel - Stores a constant-size commitment to the packet data & packet timeout @@ -763,8 +764,14 @@ function sendPacket( // check that the channel must be OPEN to send packets; abortTransactionUnless(channel !== null) abortTransactionUnless(channel.state === OPEN) + connection = provableStore.get(connectionPath(channel.connectionHops[0])) abortTransactionUnless(connection !== null) + + clientState = queryClientState(connection.clientIdenfier) + abortTransactionUnless(clientState !== null) + // Checks that client is Active, abort otherwise. + abortTransactionUnless(Status(clientState) === Active) // check if the calling module owns the sending port abortTransactionUnless(authenticateCapability(channelCapabilityPath(sourcePort, sourceChannel), capability))