Skip to content

Commit 5e5e2cd

Browse files
authored
fix: deprecate AllowUpdateAfter...check (cosmos#1511)
* fix: deprecate AllowUpdateAfter...check * update IsMatchingClientState * rm unnecessary fields in testing
1 parent 08d91ad commit 5e5e2cd

File tree

8 files changed

+110
-227
lines changed

8 files changed

+110
-227
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
5151
### State Machine Breaking
5252

5353
### Improvements
54+
5455
* (cleanup) [\#1335](https://github.com/cosmos/ibc-go/pull/1335/) `gofumpt -w -l .` to standardize the code layout more strictly than `go fmt ./...`
5556
* (transfer) [\#1342](https://github.com/cosmos/ibc-go/pull/1342) `DenomTrace` grpc now takes in either an `ibc denom` or a `hash` instead of only accepting a `hash`.
5657
* (modules/core/keeper) [\#1284](https://github.com/cosmos/ibc-go/pull/1284) Add sanity check for the keepers passed into `ibckeeper.NewKeeper`. `ibckeeper.NewKeeper` now panics if any of the keepers passed in is empty.
@@ -62,6 +63,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
6263
* (app/29-fee) [\#1341](https://github.com/cosmos/ibc-go/pull/1341) Check if the fee module is locked and if the fee module is enabled before refunding all fees
6364
* (transfer) [\#1414](https://github.com/cosmos/ibc-go/pull/1414) Emitting Sender address from `fungible_token_packet` events in `OnRecvPacket` and `OnAcknowledgementPacket`.
6465
* (modules/core/04-channel) [\#1464](https://github.com/cosmos/ibc-go/pull/1464) Emit a channel close event when an ordered channel is closed.
66+
* (modules/light-clients/07-tendermint) [\#1118](https://github.com/cosmos/ibc-go/pull/1118) Deprecating `AllowUpdateAfterExpiry and AllowUpdateAfterMisbehaviour`. See ADR-026 for context.
6567

6668
### Features
6769

docs/architecture/adr-026-ibc-client-recovery-mechanisms.md

+6-7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
- 2020/08/06: Revisions per review & to reference version
77
- 2021/01/15: Revision to support substitute clients for unfreezing
88
- 2021/05/20: Revision to simplify consensus state copying, remove initial height
9+
- 2022/04/08: Revision to deprecate AllowUpdateAfterExpiry and AllowUpdateAfterMisbehaviour
910

1011
## Status
1112

@@ -35,21 +36,20 @@ Two-thirds of the validator set (the quorum for governance, module participation
3536
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).
3637

3738
1. Require Tendermint light clients (ICS 07) to be created with the following additional flags
38-
1. `allow_governance_override_after_expiry` (boolean, default false)
39+
1. `allow_update_after_expiry` (boolean, default true). Note that this flag has been deprecated, it remains to signal intent but checks against this value will not be enforced.
3940
1. Require Tendermint light clients (ICS 07) to expose the following additional internal query functions
4041
1. `Expired() boolean`, which returns whether or not the client has passed the trusting period since the last update (in which case no headers can be validated)
4142
1. Require Tendermint light clients (ICS 07) & solo machine clients (ICS 06) to be created with the following additional flags
42-
1. `allow_governance_override_after_misbehaviour` (boolean, default false)
43+
1. `allow_update_after_misbehaviour` (boolean, default true). Note that this flag has been deprecated, it remains to signal intent but checks against this value will not be enforced.
4344
1. Require Tendermint light clients (ICS 07) to expose the following additional state mutation functions
4445
1. `Unfreeze()`, which unfreezes a light client after misbehaviour and clears any frozen height previously set
4546
1. Add a new governance proposal type, `ClientUpdateProposal`, in the `x/ibc` module
4647
1. Extend the base `Proposal` with two client identifiers (`string`).
4748
1. The first client identifier is the proposed client to be updated. This client must be either frozen or expired.
4849
1. The second client is a substitute client. It carries all the state for the client which may be updated. It must have identitical client and chain parameters to the client which may be updated (except for latest height, frozen height, and chain-id). It should be continually updated during the voting period.
49-
1. If this governance proposal passes, the client on trial will be updated to the latest state of the substitute, if and only if:
50-
1. `allow_governance_override_after_expiry` is true and the client has expired (`Expired()` returns true)
51-
1. `allow_governance_override_after_misbehaviour` is true and the client has been frozen (`Frozen()` returns true)
52-
1. In this case, additionally, the client is unfrozen by calling `Unfreeze()`
50+
1. If this governance proposal passes, the client on trial will be updated to the latest state of the substitute.
51+
52+
Previously, AllowUpdateAfterExpiry and AllowUpdateAfterMisbehaviour were used to signal the recovery options for an expired or frozen client, and governance proposals were not allowed to overwrite the client if these parameters were set to false. However, this has now been deprecated because a code migration can overwrite the client and consensus states regardless of the value of these parameters. If governance would vote to overwrite a client or consensus state, it is likely that governance would also willing to perform a code migration to do the same.
5353

5454

5555
Note that clients frozen due to misbehaviour must wait for the evidence to expire to avoid becoming refrozen.
@@ -62,7 +62,6 @@ This ADR does not address planned upgrades, which are handled separately as per
6262

6363
- Establishes a mechanism for client recovery in the case of expiry
6464
- Establishes a mechanism for client recovery in the case of misbehaviour
65-
- Clients can elect to disallow this recovery mechanism if they do not wish to allow for it
6665
- Constructing an ClientUpdate Proposal is as difficult as creating a new client
6766

6867
### Negative

docs/ibc/proposals.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ See also the relevant documentation: [ADR-026, IBC client recovery mechanisms](.
4646

4747
### Preconditions
4848
- The chain is updated with ibc-go >= v1.1.0.
49-
- Recovery parameters are set to `true` for the Tendermint light client (this determines if a governance proposal can be used). If the recovery parameters are set to `false`, recovery will require custom migration code.
5049
- The client identifier of an active client for the same counterparty chain.
5150
- The governance deposit.
5251

@@ -67,7 +66,7 @@ Check if the client is attached to the expected `chain-id`. For example, for an
6766
}
6867
```
6968

70-
The client is attached to the expected Akash `chain-id` and the recovery parameters (`allow_update_after_expiry` and `allow_update_after_misbehaviour`) are set to `true`.
69+
The client is attached to the expected Akash `chain-id`. Note that although the parameters (`allow_update_after_expiry` and `allow_update_after_misbehaviour`) exist to signal intent, these parameters have been deprecated and will not enforce any checks on the revival of client. See ADR-026 for more context on this deprecation.
7170

7271
### Step 2
7372

docs/ibc/proto-docs.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -5019,8 +5019,8 @@ and a possible frozen height.
50195019
| `latest_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Latest height the client was updated to |
50205020
| `proof_specs` | [ics23.ProofSpec](#ics23.ProofSpec) | repeated | Proof specifications used in verifying counterparty state |
50215021
| `upgrade_path` | [string](#string) | repeated | Path at which next upgraded client will be committed. Each element corresponds to the key for a single CommitmentProof in the chained proof. NOTE: ClientState must stored under `{upgradePath}/{upgradeHeight}/clientState` ConsensusState must be stored under `{upgradepath}/{upgradeHeight}/consensusState` For SDK chains using the default upgrade module, upgrade_path should be []string{"upgrade", "upgradedIBCState"}` |
5022-
| `allow_update_after_expiry` | [bool](#bool) | | This flag, when set to true, will allow governance to recover a client which has expired |
5023-
| `allow_update_after_misbehaviour` | [bool](#bool) | | This flag, when set to true, will allow governance to unfreeze a client whose chain has experienced a misbehaviour event |
5022+
| `allow_update_after_expiry` | [bool](#bool) | | **Deprecated.** allow_update_after_expiry is deprecated |
5023+
| `allow_update_after_misbehaviour` | [bool](#bool) | | **Deprecated.** allow_update_after_misbehaviour is deprecated |
50245024

50255025

50265026

modules/light-clients/07-tendermint/types/proposal_handle.go

+11-21
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,17 @@ import (
1212
)
1313

1414
// CheckSubstituteAndUpdateState will try to update the client with the state of the
15-
// substitute if and only if the proposal passes and one of the following conditions are
16-
// satisfied:
17-
// 1) AllowUpdateAfterMisbehaviour and Status() == Frozen
18-
// 2) AllowUpdateAfterExpiry=true and Status() == Expired
15+
// substitute.
16+
//
17+
// AllowUpdateAfterMisbehaviour and AllowUpdateAfterExpiry have been deprecated.
18+
// Please see ADR 026 for more information.
1919
//
2020
// The following must always be true:
2121
// - The substitute client is the same type as the subject client
2222
// - The subject and substitute client states match in all parameters (expect frozen height, latest height, and chain-id)
2323
//
2424
// In case 1) before updating the client, the client will be unfrozen by resetting
25-
// the FrozenHeight to the zero Height. If a client is frozen and AllowUpdateAfterMisbehaviour
26-
// is set to true, the client will be unexpired even if AllowUpdateAfterExpiry is set to false.
25+
// the FrozenHeight to the zero Height.
2726
func (cs ClientState) CheckSubstituteAndUpdateState(
2827
ctx sdk.Context, cdc codec.BinaryCodec, subjectClientStore,
2928
substituteClientStore sdk.KVStore, substituteClient exported.ClientState,
@@ -39,23 +38,9 @@ func (cs ClientState) CheckSubstituteAndUpdateState(
3938
return nil, sdkerrors.Wrap(clienttypes.ErrInvalidSubstitute, "subject client state does not match substitute client state")
4039
}
4140

42-
switch cs.Status(ctx, subjectClientStore, cdc) {
43-
44-
case exported.Frozen:
45-
if !cs.AllowUpdateAfterMisbehaviour {
46-
return nil, sdkerrors.Wrap(clienttypes.ErrUpdateClientFailed, "client is not allowed to be unfrozen")
47-
}
48-
41+
if cs.Status(ctx, subjectClientStore, cdc) == exported.Frozen {
4942
// unfreeze the client
5043
cs.FrozenHeight = clienttypes.ZeroHeight()
51-
52-
case exported.Expired:
53-
if !cs.AllowUpdateAfterExpiry {
54-
return nil, sdkerrors.Wrap(clienttypes.ErrUpdateClientFailed, "client is not allowed to be unexpired")
55-
}
56-
57-
default:
58-
return nil, sdkerrors.Wrap(clienttypes.ErrUpdateClientFailed, "client cannot be updated with proposal")
5944
}
6045

6146
// copy consensus states and processed time from substitute to subject
@@ -101,6 +86,11 @@ func IsMatchingClientState(subject, substitute ClientState) bool {
10186
substitute.FrozenHeight = clienttypes.ZeroHeight()
10287
subject.ChainId = ""
10388
substitute.ChainId = ""
89+
// sets both sets of flags to true as these flags have been DEPRECATED, see ADR-026 for more information
90+
subject.AllowUpdateAfterExpiry = true
91+
substitute.AllowUpdateAfterExpiry = true
92+
subject.AllowUpdateAfterMisbehaviour = true
93+
substitute.AllowUpdateAfterMisbehaviour = true
10494

10595
return reflect.DeepEqual(subject, substitute)
10696
}

modules/light-clients/07-tendermint/types/proposal_handle_test.go

+11-115
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,12 @@ func (suite *TendermintTestSuite) TestCheckSubstituteUpdateStateBasic() {
2828
{
2929
"non-matching substitute", func() {
3030
suite.coordinator.SetupClients(substitutePath)
31-
substituteClientState = suite.chainA.GetClientState(substitutePath.EndpointA.ClientID).(*types.ClientState)
32-
tmClientState, ok := substituteClientState.(*types.ClientState)
31+
substituteClientState, ok := suite.chainA.GetClientState(substitutePath.EndpointA.ClientID).(*types.ClientState)
3332
suite.Require().True(ok)
33+
// change trusting period so that test should fail
34+
substituteClientState.TrustingPeriod = time.Hour * 24 * 7
3435

36+
tmClientState := substituteClientState
3537
tmClientState.ChainId = tmClientState.ChainId + "different chain"
3638
},
3739
},
@@ -47,8 +49,6 @@ func (suite *TendermintTestSuite) TestCheckSubstituteUpdateStateBasic() {
4749

4850
suite.coordinator.SetupClients(subjectPath)
4951
subjectClientState := suite.chainA.GetClientState(subjectPath.EndpointA.ClientID).(*types.ClientState)
50-
subjectClientState.AllowUpdateAfterMisbehaviour = true
51-
subjectClientState.AllowUpdateAfterExpiry = true
5252

5353
// expire subject client
5454
suite.coordinator.IncrementTimeBy(subjectClientState.TrustingPeriod)
@@ -71,140 +71,40 @@ func (suite *TendermintTestSuite) TestCheckSubstituteUpdateStateBasic() {
7171
func (suite *TendermintTestSuite) TestCheckSubstituteAndUpdateState() {
7272
testCases := []struct {
7373
name string
74-
AllowUpdateAfterExpiry bool
75-
AllowUpdateAfterMisbehaviour bool
7674
FreezeClient bool
7775
ExpireClient bool
7876
expPass bool
7977
}{
8078
{
81-
name: "not allowed to be updated, not frozen or expired",
82-
AllowUpdateAfterExpiry: false,
83-
AllowUpdateAfterMisbehaviour: false,
84-
FreezeClient: false,
85-
ExpireClient: false,
86-
expPass: false,
87-
},
88-
{
89-
name: "not allowed to be updated, client is frozen",
90-
AllowUpdateAfterExpiry: false,
91-
AllowUpdateAfterMisbehaviour: false,
92-
FreezeClient: true,
93-
ExpireClient: false,
94-
expPass: false,
95-
},
96-
{
97-
name: "not allowed to be updated, client is expired",
98-
AllowUpdateAfterExpiry: false,
99-
AllowUpdateAfterMisbehaviour: false,
100-
FreezeClient: false,
101-
ExpireClient: true,
102-
expPass: false,
103-
},
104-
{
105-
name: "not allowed to be updated, client is frozen and expired",
106-
AllowUpdateAfterExpiry: false,
107-
AllowUpdateAfterMisbehaviour: false,
108-
FreezeClient: true,
109-
ExpireClient: true,
110-
expPass: false,
111-
},
112-
{
113-
name: "allowed to be updated only after misbehaviour, not frozen or expired",
114-
AllowUpdateAfterExpiry: false,
115-
AllowUpdateAfterMisbehaviour: true,
116-
FreezeClient: false,
117-
ExpireClient: false,
118-
expPass: false,
119-
},
120-
{
121-
name: "allowed to be updated only after misbehaviour, client is expired",
122-
AllowUpdateAfterExpiry: false,
123-
AllowUpdateAfterMisbehaviour: true,
124-
FreezeClient: false,
125-
ExpireClient: true,
126-
expPass: false,
127-
},
128-
{
129-
name: "allowed to be updated only after expiry, not frozen or expired",
130-
AllowUpdateAfterExpiry: true,
131-
AllowUpdateAfterMisbehaviour: false,
132-
FreezeClient: false,
133-
ExpireClient: false,
134-
expPass: false,
135-
},
136-
{
137-
name: "allowed to be updated only after expiry, client is frozen",
138-
AllowUpdateAfterExpiry: true,
139-
AllowUpdateAfterMisbehaviour: false,
140-
FreezeClient: true,
141-
ExpireClient: false,
142-
expPass: false,
143-
},
144-
{
145-
name: "PASS: allowed to be updated only after misbehaviour, client is frozen",
146-
AllowUpdateAfterExpiry: false,
147-
AllowUpdateAfterMisbehaviour: true,
148-
FreezeClient: true,
149-
ExpireClient: false,
150-
expPass: true,
151-
},
152-
{
153-
name: "PASS: allowed to be updated only after misbehaviour, client is frozen and expired",
154-
AllowUpdateAfterExpiry: false,
155-
AllowUpdateAfterMisbehaviour: true,
79+
name: "PASS: update checks are deprecated, client is frozen and expired",
15680
FreezeClient: true,
15781
ExpireClient: true,
15882
expPass: true,
15983
},
16084
{
161-
name: "PASS: allowed to be updated only after expiry, client is expired",
162-
AllowUpdateAfterExpiry: true,
163-
AllowUpdateAfterMisbehaviour: false,
85+
name: "PASS: update checks are deprecated, not frozen or expired",
16486
FreezeClient: false,
165-
ExpireClient: true,
87+
ExpireClient: false,
16688
expPass: true,
16789
},
16890
{
169-
name: "allowed to be updated only after expiry, client is frozen and expired",
170-
AllowUpdateAfterExpiry: true,
171-
AllowUpdateAfterMisbehaviour: false,
172-
FreezeClient: true,
173-
ExpireClient: true,
174-
expPass: false,
175-
},
176-
{
177-
name: "allowed to be updated after expiry and misbehaviour, not frozen or expired",
178-
AllowUpdateAfterExpiry: true,
179-
AllowUpdateAfterMisbehaviour: true,
91+
name: "PASS: update checks are deprecated, not frozen or expired",
18092
FreezeClient: false,
18193
ExpireClient: false,
182-
expPass: false,
94+
expPass: true,
18395
},
18496
{
185-
name: "PASS: allowed to be updated after expiry and misbehaviour, client is frozen",
186-
AllowUpdateAfterExpiry: true,
187-
AllowUpdateAfterMisbehaviour: true,
97+
name: "PASS: update checks are deprecated, client is frozen",
18898
FreezeClient: true,
18999
ExpireClient: false,
190100
expPass: true,
191101
},
192102
{
193-
name: "PASS: allowed to be updated after expiry and misbehaviour, client is expired",
194-
AllowUpdateAfterExpiry: true,
195-
AllowUpdateAfterMisbehaviour: true,
103+
name: "PASS: update checks are deprecated, client is expired",
196104
FreezeClient: false,
197105
ExpireClient: true,
198106
expPass: true,
199107
},
200-
{
201-
name: "PASS: allowed to be updated after expiry and misbehaviour, client is frozen and expired",
202-
AllowUpdateAfterExpiry: true,
203-
AllowUpdateAfterMisbehaviour: true,
204-
FreezeClient: true,
205-
ExpireClient: true,
206-
expPass: true,
207-
},
208108
}
209109

210110
for _, tc := range testCases {
@@ -221,8 +121,6 @@ func (suite *TendermintTestSuite) TestCheckSubstituteAndUpdateState() {
221121
subjectPath := ibctesting.NewPath(suite.chainA, suite.chainB)
222122
suite.coordinator.SetupClients(subjectPath)
223123
subjectClientState := suite.chainA.GetClientState(subjectPath.EndpointA.ClientID).(*types.ClientState)
224-
subjectClientState.AllowUpdateAfterExpiry = tc.AllowUpdateAfterExpiry
225-
subjectClientState.AllowUpdateAfterMisbehaviour = tc.AllowUpdateAfterMisbehaviour
226124

227125
// apply freezing or expiry as determined by the test case
228126
if tc.FreezeClient {
@@ -243,8 +141,6 @@ func (suite *TendermintTestSuite) TestCheckSubstituteAndUpdateState() {
243141
substitutePath := ibctesting.NewPath(suite.chainA, suite.chainB)
244142
suite.coordinator.SetupClients(substitutePath)
245143
substituteClientState := suite.chainA.GetClientState(substitutePath.EndpointA.ClientID).(*types.ClientState)
246-
substituteClientState.AllowUpdateAfterExpiry = tc.AllowUpdateAfterExpiry
247-
substituteClientState.AllowUpdateAfterMisbehaviour = tc.AllowUpdateAfterMisbehaviour
248144
suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), substitutePath.EndpointA.ClientID, substituteClientState)
249145

250146
// update substitute a few times

0 commit comments

Comments
 (0)