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

Initial ADR for IBC client recovery mechanisms #6488

Merged
merged 10 commits into from
Aug 10, 2020
1 change: 1 addition & 0 deletions docs/architecture/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,4 @@ Please add a entry below in your Pull Request for an ADR.
- [ADR 022: Custom baseapp panic handling](./adr-022-custom-panic-handling.md)
- [ADR 023: Protocol Buffer Naming and Versioning](./adr-023-protobuf-naming.md)
- [ADR 024: Coin Metadata](./adr-024-coin-metadata.md)
- [ADR 026: IBC Client Recovery Mechanisms](./adr-026-ibc-client-recovery-mechanisms.md)
65 changes: 65 additions & 0 deletions docs/architecture/adr-026-ibc-client-recovery-mechanisms.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# ADR 026: IBC Client Recovery Mechanisms

## Changelog

- 2020/06/23: Initial version

## Status

*Proposed*

## Context

### Summary

At launch, IBC will be a novel protocol, without an experienced user-base. At the protocol layer, it is not possible to distinguish between client expiry or misbehaviour due to genuine faults (Byzantine behavior) and client expiry or misbehaviour due to user mistakes (failing to update a client, or accidentally double-signing). In the base IBC protocol and ICS 20 fungible token transfer implementation, if a client can no longer be updated, funds in that channel will be permanently locked and can no longer be transferred. To the degree that it is safe to do so, it would be preferable to provide users with a recovery mechanism which can be utilised in these exceptional cases.

### Exceptional cases

The state of concern is where a client associated with connection(s) and channel(s) can no longer be updated. This can happen for several reasons:

1. The chain which the client is following has halted and is no longer producing blocks/headers, so no updates can be made to the client
1. The chain which the client is following has continued to operate, but no relayer has submitted a new header within the unbonding period, and the client has expired
1. This could be due to real misbehaviour (intentional Byzantine behaviour) or merely a mistake by validators, but the client cannot distinguish these two cases
1. The chain which the client is following has experienced a misbehaviour event, and the client has been frozen & thus can no longer be updated

### Security model

Two-thirds of the validator set (the quorum for governance, module participation) can already sign arbitrary data, so allowing governance to manually force-update a client with a new header after a delay period does not substantially alter the security model.

## Decision

We elect not to deal with chains which have actually halted, which is necessarily Byzantine behaviour and in which case token recovery is not likely possible anyways (in-flight packets cannot be timed-out, but the relative impact of that is minor).

1. Require Tendermint light clients (ICS 07) to be created with the following additional flags
1. `allow_governance_override_after_expiry` (boolean)
cwgoes marked this conversation as resolved.
Show resolved Hide resolved
1. Require Tendermint light clients (ICS 07) to expose the following additional internal query functions
1. `Expired() boolean`, which returns whether or not the client has passed the unbonding period since the last update
cwgoes marked this conversation as resolved.
Show resolved Hide resolved
1. Require Tendermint light clients (ICS 07) & solo machine clients (ICS 06) to be created with the following additional flags
1. `allow_governance_override_after_misbehaviour` (boolean)
cwgoes marked this conversation as resolved.
Show resolved Hide resolved
1. Add a new governance proposal type, `ClientUpdateProposal`, in the `x/ibc` module
1. Extend the base `Proposal` with a client identifier (`string`) and a header (`bytes`, encoded in a client-type-specific format)
1. If this governance proposal passes, the client is updated with the provided header, if and only if:
cwgoes marked this conversation as resolved.
Show resolved Hide resolved
1. `allow_governance_override_after_expiry` is true and the client has expired (`Expired()` returns true)
1. `allow_governance_override_after_misbehaviour` is true and the client has been frozen (`Frozen()` returns true)

## Consequences

### Positive

- Establishes a mechanism for client recovery in the case of expiry
- Establishes a mechanism for client recovery in the case of misbehaviour
- Clients can elect to disallow this recovery mechanism if they do not wish to allow for it

### Negative

- Additional complexity in client creation which must be understood by the user
- Governance participants must pick a new header, which is a bit different from their usual tasks

### Neutral

No neutral consequences.

## References

- [Prior discussion](https://github.com/cosmos/ics/issues/421)