Add ConsensusState to IBC Upgrades (#7919)
* upgrade progress * fix build minus cli * write state at block before upgrade height * refix build * Apply suggestions from code review Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> * fix upgrade and start with tests * fix tendermint tests * add tests and remove unnecessary relayer options on upgradedClient * fix all tests except weird msg panic * add invalid final client test and codec stuff * fix everything but msg issue * remove problematic test for now * safer self validation * upgrade fixes * proto-linting * remove unnecessary last height * add timestamp to committed upgrade consensus state * address final nits * address nit Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
This commit is contained in:
parent
74435137e9
commit
def3c5ba71
557
client/docs/swagger-ui/swagger.yaml
vendored
557
client/docs/swagger-ui/swagger.yaml
vendored
@ -15760,6 +15760,396 @@ paths:
|
||||
}
|
||||
tags:
|
||||
- Query
|
||||
'/cosmos/upgrade/v1beta1/upgraded_consensus_state/{last_height}':
|
||||
get:
|
||||
summary: |-
|
||||
UpgradedConsensusState queries the consensus state that will serve
|
||||
as a trusted kernel for the next version of this chain. It will only be
|
||||
stored at the last height of this chain.
|
||||
UpgradedConsensusState RPC not supported with legacy querier
|
||||
operationId: UpgradedConsensusState
|
||||
responses:
|
||||
'200':
|
||||
description: A successful response.
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
upgraded_consensus_state:
|
||||
type: object
|
||||
properties:
|
||||
type_url:
|
||||
type: string
|
||||
description: >-
|
||||
A URL/resource name that uniquely identifies the type of
|
||||
the serialized
|
||||
|
||||
protocol buffer message. This string must contain at least
|
||||
|
||||
one "/" character. The last segment of the URL's path must
|
||||
represent
|
||||
|
||||
the fully qualified name of the type (as in
|
||||
|
||||
`path/google.protobuf.Duration`). The name should be in a
|
||||
canonical form
|
||||
|
||||
(e.g., leading "." is not accepted).
|
||||
|
||||
|
||||
In practice, teams usually precompile into the binary all
|
||||
types that they
|
||||
|
||||
expect it to use in the context of Any. However, for URLs
|
||||
which use the
|
||||
|
||||
scheme `http`, `https`, or no scheme, one can optionally
|
||||
set up a type
|
||||
|
||||
server that maps type URLs to message definitions as
|
||||
follows:
|
||||
|
||||
|
||||
* If no scheme is provided, `https` is assumed.
|
||||
|
||||
* An HTTP GET on the URL must yield a
|
||||
[google.protobuf.Type][]
|
||||
value in binary format, or produce an error.
|
||||
* Applications are allowed to cache lookup results based
|
||||
on the
|
||||
URL, or have them precompiled into a binary to avoid any
|
||||
lookup. Therefore, binary compatibility needs to be preserved
|
||||
on changes to types. (Use versioned type names to manage
|
||||
breaking changes.)
|
||||
|
||||
Note: this functionality is not currently available in the
|
||||
official
|
||||
|
||||
protobuf release, and it is not used for type URLs
|
||||
beginning with
|
||||
|
||||
type.googleapis.com.
|
||||
|
||||
|
||||
Schemes other than `http`, `https` (or the empty scheme)
|
||||
might be
|
||||
|
||||
used with implementation specific semantics.
|
||||
value:
|
||||
type: string
|
||||
format: byte
|
||||
description: >-
|
||||
Must be a valid serialized protocol buffer of the above
|
||||
specified type.
|
||||
description: >-
|
||||
`Any` contains an arbitrary serialized protocol buffer message
|
||||
along with a
|
||||
|
||||
URL that describes the type of the serialized message.
|
||||
|
||||
|
||||
Protobuf library provides support to pack/unpack Any values in
|
||||
the form
|
||||
|
||||
of utility functions or additional generated methods of the
|
||||
Any type.
|
||||
|
||||
|
||||
Example 1: Pack and unpack a message in C++.
|
||||
|
||||
Foo foo = ...;
|
||||
Any any;
|
||||
any.PackFrom(foo);
|
||||
...
|
||||
if (any.UnpackTo(&foo)) {
|
||||
...
|
||||
}
|
||||
|
||||
Example 2: Pack and unpack a message in Java.
|
||||
|
||||
Foo foo = ...;
|
||||
Any any = Any.pack(foo);
|
||||
...
|
||||
if (any.is(Foo.class)) {
|
||||
foo = any.unpack(Foo.class);
|
||||
}
|
||||
|
||||
Example 3: Pack and unpack a message in Python.
|
||||
|
||||
foo = Foo(...)
|
||||
any = Any()
|
||||
any.Pack(foo)
|
||||
...
|
||||
if any.Is(Foo.DESCRIPTOR):
|
||||
any.Unpack(foo)
|
||||
...
|
||||
|
||||
Example 4: Pack and unpack a message in Go
|
||||
|
||||
foo := &pb.Foo{...}
|
||||
any, err := ptypes.MarshalAny(foo)
|
||||
...
|
||||
foo := &pb.Foo{}
|
||||
if err := ptypes.UnmarshalAny(any, foo); err != nil {
|
||||
...
|
||||
}
|
||||
|
||||
The pack methods provided by protobuf library will by default
|
||||
use
|
||||
|
||||
'type.googleapis.com/full.type.name' as the type URL and the
|
||||
unpack
|
||||
|
||||
methods only use the fully qualified type name after the last
|
||||
'/'
|
||||
|
||||
in the type URL, for example "foo.bar.com/x/y.z" will yield
|
||||
type
|
||||
|
||||
name "y.z".
|
||||
|
||||
|
||||
|
||||
JSON
|
||||
|
||||
====
|
||||
|
||||
The JSON representation of an `Any` value uses the regular
|
||||
|
||||
representation of the deserialized, embedded message, with an
|
||||
|
||||
additional field `@type` which contains the type URL. Example:
|
||||
|
||||
package google.profile;
|
||||
message Person {
|
||||
string first_name = 1;
|
||||
string last_name = 2;
|
||||
}
|
||||
|
||||
{
|
||||
"@type": "type.googleapis.com/google.profile.Person",
|
||||
"firstName": <string>,
|
||||
"lastName": <string>
|
||||
}
|
||||
|
||||
If the embedded message type is well-known and has a custom
|
||||
JSON
|
||||
|
||||
representation, that representation will be embedded adding a
|
||||
field
|
||||
|
||||
`value` which holds the custom JSON in addition to the `@type`
|
||||
|
||||
field. Example (for message [google.protobuf.Duration][]):
|
||||
|
||||
{
|
||||
"@type": "type.googleapis.com/google.protobuf.Duration",
|
||||
"value": "1.212s"
|
||||
}
|
||||
description: >-
|
||||
QueryUpgradedConsensusStateResponse is the response type for the
|
||||
Query/UpgradedConsensusState
|
||||
|
||||
RPC method.
|
||||
default:
|
||||
description: An unexpected error response.
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
code:
|
||||
type: integer
|
||||
format: int32
|
||||
message:
|
||||
type: string
|
||||
details:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
type_url:
|
||||
type: string
|
||||
description: >-
|
||||
A URL/resource name that uniquely identifies the type of
|
||||
the serialized
|
||||
|
||||
protocol buffer message. This string must contain at
|
||||
least
|
||||
|
||||
one "/" character. The last segment of the URL's path
|
||||
must represent
|
||||
|
||||
the fully qualified name of the type (as in
|
||||
|
||||
`path/google.protobuf.Duration`). The name should be in
|
||||
a canonical form
|
||||
|
||||
(e.g., leading "." is not accepted).
|
||||
|
||||
|
||||
In practice, teams usually precompile into the binary
|
||||
all types that they
|
||||
|
||||
expect it to use in the context of Any. However, for
|
||||
URLs which use the
|
||||
|
||||
scheme `http`, `https`, or no scheme, one can optionally
|
||||
set up a type
|
||||
|
||||
server that maps type URLs to message definitions as
|
||||
follows:
|
||||
|
||||
|
||||
* If no scheme is provided, `https` is assumed.
|
||||
|
||||
* An HTTP GET on the URL must yield a
|
||||
[google.protobuf.Type][]
|
||||
value in binary format, or produce an error.
|
||||
* Applications are allowed to cache lookup results based
|
||||
on the
|
||||
URL, or have them precompiled into a binary to avoid any
|
||||
lookup. Therefore, binary compatibility needs to be preserved
|
||||
on changes to types. (Use versioned type names to manage
|
||||
breaking changes.)
|
||||
|
||||
Note: this functionality is not currently available in
|
||||
the official
|
||||
|
||||
protobuf release, and it is not used for type URLs
|
||||
beginning with
|
||||
|
||||
type.googleapis.com.
|
||||
|
||||
|
||||
Schemes other than `http`, `https` (or the empty scheme)
|
||||
might be
|
||||
|
||||
used with implementation specific semantics.
|
||||
value:
|
||||
type: string
|
||||
format: byte
|
||||
description: >-
|
||||
Must be a valid serialized protocol buffer of the above
|
||||
specified type.
|
||||
description: >-
|
||||
`Any` contains an arbitrary serialized protocol buffer
|
||||
message along with a
|
||||
|
||||
URL that describes the type of the serialized message.
|
||||
|
||||
|
||||
Protobuf library provides support to pack/unpack Any values
|
||||
in the form
|
||||
|
||||
of utility functions or additional generated methods of the
|
||||
Any type.
|
||||
|
||||
|
||||
Example 1: Pack and unpack a message in C++.
|
||||
|
||||
Foo foo = ...;
|
||||
Any any;
|
||||
any.PackFrom(foo);
|
||||
...
|
||||
if (any.UnpackTo(&foo)) {
|
||||
...
|
||||
}
|
||||
|
||||
Example 2: Pack and unpack a message in Java.
|
||||
|
||||
Foo foo = ...;
|
||||
Any any = Any.pack(foo);
|
||||
...
|
||||
if (any.is(Foo.class)) {
|
||||
foo = any.unpack(Foo.class);
|
||||
}
|
||||
|
||||
Example 3: Pack and unpack a message in Python.
|
||||
|
||||
foo = Foo(...)
|
||||
any = Any()
|
||||
any.Pack(foo)
|
||||
...
|
||||
if any.Is(Foo.DESCRIPTOR):
|
||||
any.Unpack(foo)
|
||||
...
|
||||
|
||||
Example 4: Pack and unpack a message in Go
|
||||
|
||||
foo := &pb.Foo{...}
|
||||
any, err := ptypes.MarshalAny(foo)
|
||||
...
|
||||
foo := &pb.Foo{}
|
||||
if err := ptypes.UnmarshalAny(any, foo); err != nil {
|
||||
...
|
||||
}
|
||||
|
||||
The pack methods provided by protobuf library will by
|
||||
default use
|
||||
|
||||
'type.googleapis.com/full.type.name' as the type URL and the
|
||||
unpack
|
||||
|
||||
methods only use the fully qualified type name after the
|
||||
last '/'
|
||||
|
||||
in the type URL, for example "foo.bar.com/x/y.z" will yield
|
||||
type
|
||||
|
||||
name "y.z".
|
||||
|
||||
|
||||
|
||||
JSON
|
||||
|
||||
====
|
||||
|
||||
The JSON representation of an `Any` value uses the regular
|
||||
|
||||
representation of the deserialized, embedded message, with
|
||||
an
|
||||
|
||||
additional field `@type` which contains the type URL.
|
||||
Example:
|
||||
|
||||
package google.profile;
|
||||
message Person {
|
||||
string first_name = 1;
|
||||
string last_name = 2;
|
||||
}
|
||||
|
||||
{
|
||||
"@type": "type.googleapis.com/google.profile.Person",
|
||||
"firstName": <string>,
|
||||
"lastName": <string>
|
||||
}
|
||||
|
||||
If the embedded message type is well-known and has a custom
|
||||
JSON
|
||||
|
||||
representation, that representation will be embedded adding
|
||||
a field
|
||||
|
||||
`value` which holds the custom JSON in addition to the
|
||||
`@type`
|
||||
|
||||
field. Example (for message [google.protobuf.Duration][]):
|
||||
|
||||
{
|
||||
"@type": "type.googleapis.com/google.protobuf.Duration",
|
||||
"value": "1.212s"
|
||||
}
|
||||
parameters:
|
||||
- name: last_height
|
||||
description: |-
|
||||
last height of the current chain must be sent in request
|
||||
as this is the height under which next consensus state is stored
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
format: int64
|
||||
tags:
|
||||
- Query
|
||||
/ibc/core/channel/v1beta1/channels:
|
||||
get:
|
||||
summary: Channels queries all the IBC channels of a chain.
|
||||
@ -31438,6 +31828,173 @@ definitions:
|
||||
RPC
|
||||
|
||||
method.
|
||||
cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateResponse:
|
||||
type: object
|
||||
properties:
|
||||
upgraded_consensus_state:
|
||||
type: object
|
||||
properties:
|
||||
type_url:
|
||||
type: string
|
||||
description: >-
|
||||
A URL/resource name that uniquely identifies the type of the
|
||||
serialized
|
||||
|
||||
protocol buffer message. This string must contain at least
|
||||
|
||||
one "/" character. The last segment of the URL's path must
|
||||
represent
|
||||
|
||||
the fully qualified name of the type (as in
|
||||
|
||||
`path/google.protobuf.Duration`). The name should be in a
|
||||
canonical form
|
||||
|
||||
(e.g., leading "." is not accepted).
|
||||
|
||||
|
||||
In practice, teams usually precompile into the binary all types
|
||||
that they
|
||||
|
||||
expect it to use in the context of Any. However, for URLs which
|
||||
use the
|
||||
|
||||
scheme `http`, `https`, or no scheme, one can optionally set up a
|
||||
type
|
||||
|
||||
server that maps type URLs to message definitions as follows:
|
||||
|
||||
|
||||
* If no scheme is provided, `https` is assumed.
|
||||
|
||||
* An HTTP GET on the URL must yield a [google.protobuf.Type][]
|
||||
value in binary format, or produce an error.
|
||||
* Applications are allowed to cache lookup results based on the
|
||||
URL, or have them precompiled into a binary to avoid any
|
||||
lookup. Therefore, binary compatibility needs to be preserved
|
||||
on changes to types. (Use versioned type names to manage
|
||||
breaking changes.)
|
||||
|
||||
Note: this functionality is not currently available in the
|
||||
official
|
||||
|
||||
protobuf release, and it is not used for type URLs beginning with
|
||||
|
||||
type.googleapis.com.
|
||||
|
||||
|
||||
Schemes other than `http`, `https` (or the empty scheme) might be
|
||||
|
||||
used with implementation specific semantics.
|
||||
value:
|
||||
type: string
|
||||
format: byte
|
||||
description: >-
|
||||
Must be a valid serialized protocol buffer of the above specified
|
||||
type.
|
||||
description: >-
|
||||
`Any` contains an arbitrary serialized protocol buffer message along
|
||||
with a
|
||||
|
||||
URL that describes the type of the serialized message.
|
||||
|
||||
|
||||
Protobuf library provides support to pack/unpack Any values in the
|
||||
form
|
||||
|
||||
of utility functions or additional generated methods of the Any type.
|
||||
|
||||
|
||||
Example 1: Pack and unpack a message in C++.
|
||||
|
||||
Foo foo = ...;
|
||||
Any any;
|
||||
any.PackFrom(foo);
|
||||
...
|
||||
if (any.UnpackTo(&foo)) {
|
||||
...
|
||||
}
|
||||
|
||||
Example 2: Pack and unpack a message in Java.
|
||||
|
||||
Foo foo = ...;
|
||||
Any any = Any.pack(foo);
|
||||
...
|
||||
if (any.is(Foo.class)) {
|
||||
foo = any.unpack(Foo.class);
|
||||
}
|
||||
|
||||
Example 3: Pack and unpack a message in Python.
|
||||
|
||||
foo = Foo(...)
|
||||
any = Any()
|
||||
any.Pack(foo)
|
||||
...
|
||||
if any.Is(Foo.DESCRIPTOR):
|
||||
any.Unpack(foo)
|
||||
...
|
||||
|
||||
Example 4: Pack and unpack a message in Go
|
||||
|
||||
foo := &pb.Foo{...}
|
||||
any, err := ptypes.MarshalAny(foo)
|
||||
...
|
||||
foo := &pb.Foo{}
|
||||
if err := ptypes.UnmarshalAny(any, foo); err != nil {
|
||||
...
|
||||
}
|
||||
|
||||
The pack methods provided by protobuf library will by default use
|
||||
|
||||
'type.googleapis.com/full.type.name' as the type URL and the unpack
|
||||
|
||||
methods only use the fully qualified type name after the last '/'
|
||||
|
||||
in the type URL, for example "foo.bar.com/x/y.z" will yield type
|
||||
|
||||
name "y.z".
|
||||
|
||||
|
||||
|
||||
JSON
|
||||
|
||||
====
|
||||
|
||||
The JSON representation of an `Any` value uses the regular
|
||||
|
||||
representation of the deserialized, embedded message, with an
|
||||
|
||||
additional field `@type` which contains the type URL. Example:
|
||||
|
||||
package google.profile;
|
||||
message Person {
|
||||
string first_name = 1;
|
||||
string last_name = 2;
|
||||
}
|
||||
|
||||
{
|
||||
"@type": "type.googleapis.com/google.profile.Person",
|
||||
"firstName": <string>,
|
||||
"lastName": <string>
|
||||
}
|
||||
|
||||
If the embedded message type is well-known and has a custom JSON
|
||||
|
||||
representation, that representation will be embedded adding a field
|
||||
|
||||
`value` which holds the custom JSON in addition to the `@type`
|
||||
|
||||
field. Example (for message [google.protobuf.Duration][]):
|
||||
|
||||
{
|
||||
"@type": "type.googleapis.com/google.protobuf.Duration",
|
||||
"value": "1.212s"
|
||||
}
|
||||
description: >-
|
||||
QueryUpgradedConsensusStateResponse is the response type for the
|
||||
Query/UpgradedConsensusState
|
||||
|
||||
RPC method.
|
||||
ibc.core.channel.v1.Channel:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
syntax = "proto3";
|
||||
package cosmos.upgrade.v1beta1;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "google/api/annotations.proto";
|
||||
import "cosmos/upgrade/v1beta1/upgrade.proto";
|
||||
|
||||
@ -17,6 +18,14 @@ service Query {
|
||||
rpc AppliedPlan(QueryAppliedPlanRequest) returns (QueryAppliedPlanResponse) {
|
||||
option (google.api.http).get = "/cosmos/upgrade/v1beta1/applied_plan/{name}";
|
||||
}
|
||||
|
||||
// UpgradedConsensusState queries the consensus state that will serve
|
||||
// as a trusted kernel for the next version of this chain. It will only be
|
||||
// stored at the last height of this chain.
|
||||
// UpgradedConsensusState RPC not supported with legacy querier
|
||||
rpc UpgradedConsensusState(QueryUpgradedConsensusStateRequest) returns (QueryUpgradedConsensusStateResponse) {
|
||||
option (google.api.http).get = "/cosmos/upgrade/v1beta1/upgraded_consensus_state/{last_height}";
|
||||
}
|
||||
}
|
||||
|
||||
// QueryCurrentPlanRequest is the request type for the Query/CurrentPlan RPC
|
||||
@ -43,3 +52,17 @@ message QueryAppliedPlanResponse {
|
||||
// height is the block height at which the plan was applied.
|
||||
int64 height = 1;
|
||||
}
|
||||
|
||||
// QueryUpgradedConsensusStateRequest is the request type for the Query/UpgradedConsensusState
|
||||
// RPC method.
|
||||
message QueryUpgradedConsensusStateRequest {
|
||||
// last height of the current chain must be sent in request
|
||||
// as this is the height under which next consensus state is stored
|
||||
int64 last_height = 1;
|
||||
}
|
||||
|
||||
// QueryUpgradedConsensusStateResponse is the response type for the Query/UpgradedConsensusState
|
||||
// RPC method.
|
||||
message QueryUpgradedConsensusStateResponse {
|
||||
google.protobuf.Any upgraded_consensus_state = 1;
|
||||
}
|
||||
|
||||
@ -60,16 +60,21 @@ message MsgUpdateClientResponse {}
|
||||
|
||||
// MsgUpgradeClient defines an sdk.Msg to upgrade an IBC client to a new client state
|
||||
message MsgUpgradeClient {
|
||||
option (gogoproto.equal) = false;
|
||||
option (gogoproto.goproto_getters) = false;
|
||||
|
||||
// client unique identifier
|
||||
string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""];
|
||||
// upgraded client state
|
||||
google.protobuf.Any client_state = 2 [(gogoproto.moretags) = "yaml:\"client_state\""];
|
||||
// height at which old chain halts and upgrades (i.e last block executed)
|
||||
Height upgrade_height = 3 [(gogoproto.moretags) = "yaml:\"upgrade_height\""];
|
||||
// upgraded consensus state, only contains enough information to serve as a basis of trust in update logic
|
||||
google.protobuf.Any consensus_state = 3 [(gogoproto.moretags) = "yaml:\"consensus_state\""];
|
||||
// proof that old chain committed to new client
|
||||
bytes proof_upgrade = 4 [(gogoproto.moretags) = "yaml:\"proof_upgrade\""];
|
||||
bytes proof_upgrade_client = 4 [(gogoproto.moretags) = "yaml:\"proof_upgrade_client\""];
|
||||
// proof that old chain committed to new consensus state
|
||||
bytes proof_upgrade_consensus_state = 5 [(gogoproto.moretags) = "yaml:\"proof_upgrade_consensus_state\""];
|
||||
// signer address
|
||||
string signer = 5;
|
||||
string signer = 6;
|
||||
}
|
||||
|
||||
// MsgUpgradeClientResponse defines the Msg/UpgradeClient response type.
|
||||
|
||||
@ -42,8 +42,12 @@ message ClientState {
|
||||
// Proof specifications used in verifying counterparty state
|
||||
repeated ics23.ProofSpec proof_specs = 8 [(gogoproto.moretags) = "yaml:\"proof_specs\""];
|
||||
|
||||
// Path at which next upgraded client will be committed
|
||||
string upgrade_path = 9 [(gogoproto.moretags) = "yaml:\"upgrade_path\""];
|
||||
// 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"}`
|
||||
repeated string upgrade_path = 9 [(gogoproto.moretags) = "yaml:\"upgrade_path\""];
|
||||
|
||||
// This flag, when set to true, will allow governance to recover a client
|
||||
// which has expired
|
||||
|
||||
@ -107,7 +107,8 @@ func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.H
|
||||
|
||||
// UpgradeClient upgrades the client to a new client state if this new client was committed to
|
||||
// by the old client at the specified upgrade height
|
||||
func (k Keeper) UpgradeClient(ctx sdk.Context, clientID string, upgradedClient exported.ClientState, upgradeHeight exported.Height, proofUpgrade []byte) error {
|
||||
func (k Keeper) UpgradeClient(ctx sdk.Context, clientID string, upgradedClient exported.ClientState, upgradedConsState exported.ConsensusState,
|
||||
proofUpgradeClient, proofUpgradeConsState []byte) error {
|
||||
clientState, found := k.GetClientState(ctx, clientID)
|
||||
if !found {
|
||||
return sdkerrors.Wrapf(types.ErrClientNotFound, "cannot update client with ID %s", clientID)
|
||||
@ -118,13 +119,14 @@ func (k Keeper) UpgradeClient(ctx sdk.Context, clientID string, upgradedClient e
|
||||
return sdkerrors.Wrapf(types.ErrClientFrozen, "cannot update client with ID %s", clientID)
|
||||
}
|
||||
|
||||
updatedClientState, updatedConsensusState, err := clientState.VerifyUpgradeAndUpdateState(ctx, k.cdc, k.ClientStore(ctx, clientID), upgradedClient, upgradeHeight, proofUpgrade)
|
||||
updatedClientState, updatedConsState, err := clientState.VerifyUpgradeAndUpdateState(ctx, k.cdc, k.ClientStore(ctx, clientID),
|
||||
upgradedClient, upgradedConsState, proofUpgradeClient, proofUpgradeConsState)
|
||||
if err != nil {
|
||||
return sdkerrors.Wrapf(err, "cannot upgrade client with ID %s", clientID)
|
||||
}
|
||||
|
||||
k.SetClientState(ctx, clientID, updatedClientState)
|
||||
k.SetClientConsensusState(ctx, clientID, updatedClientState.GetLatestHeight(), updatedConsensusState)
|
||||
k.SetClientConsensusState(ctx, clientID, updatedClientState.GetLatestHeight(), updatedConsState)
|
||||
|
||||
k.Logger(ctx).Info("client state upgraded", "client-id", clientID, "height", updatedClientState.GetLatestHeight().String())
|
||||
|
||||
|
||||
@ -235,10 +235,11 @@ func (suite *KeeperTestSuite) TestUpdateClientLocalhost() {
|
||||
|
||||
func (suite *KeeperTestSuite) TestUpgradeClient() {
|
||||
var (
|
||||
upgradedClient exported.ClientState
|
||||
upgradeHeight exported.Height
|
||||
clientA string
|
||||
proofUpgrade []byte
|
||||
upgradedClient exported.ClientState
|
||||
upgradedConsState exported.ConsensusState
|
||||
lastHeight exported.Height
|
||||
clientA string
|
||||
proofUpgradedClient, proofUpgradedConsState []byte
|
||||
)
|
||||
|
||||
testCases := []struct {
|
||||
@ -251,12 +252,16 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
|
||||
setup: func() {
|
||||
|
||||
upgradedClient = ibctmtypes.NewClientState("newChainId", ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
|
||||
upgradedConsState = &ibctmtypes.ConsensusState{
|
||||
NextValidatorsHash: []byte("nextValsHash"),
|
||||
}
|
||||
|
||||
// upgrade Height is at next block
|
||||
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
// last Height is at next block
|
||||
lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
|
||||
// zero custom fields and store in upgrade store
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedConsState)
|
||||
|
||||
// commit upgrade store changes and update clients
|
||||
|
||||
@ -267,7 +272,8 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
proofUpgrade, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
},
|
||||
expPass: true,
|
||||
},
|
||||
@ -276,12 +282,16 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
|
||||
setup: func() {
|
||||
|
||||
upgradedClient = ibctmtypes.NewClientState("newChainId", ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
|
||||
upgradedConsState = &ibctmtypes.ConsensusState{
|
||||
NextValidatorsHash: []byte("nextValsHash"),
|
||||
}
|
||||
|
||||
// upgrade Height is at next block
|
||||
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
// last Height is at next block
|
||||
lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
|
||||
// zero custom fields and store in upgrade store
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedConsState)
|
||||
|
||||
// commit upgrade store changes and update clients
|
||||
|
||||
@ -292,7 +302,8 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
proofUpgrade, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
|
||||
clientA = "wrongclientid"
|
||||
},
|
||||
@ -303,12 +314,16 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
|
||||
setup: func() {
|
||||
|
||||
upgradedClient = ibctmtypes.NewClientState("newChainId", ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
|
||||
upgradedConsState = &ibctmtypes.ConsensusState{
|
||||
NextValidatorsHash: []byte("nextValsHash"),
|
||||
}
|
||||
|
||||
// upgrade Height is at next block
|
||||
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
// last Height is at next block
|
||||
lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
|
||||
// zero custom fields and store in upgrade store
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedConsState)
|
||||
|
||||
// commit upgrade store changes and update clients
|
||||
|
||||
@ -319,7 +334,8 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
proofUpgrade, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
|
||||
// set frozen client in store
|
||||
tmClient, ok := cs.(*ibctmtypes.ClientState)
|
||||
@ -334,12 +350,16 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
|
||||
setup: func() {
|
||||
|
||||
upgradedClient = ibctmtypes.NewClientState("newChainId", ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
|
||||
upgradedConsState = &ibctmtypes.ConsensusState{
|
||||
NextValidatorsHash: []byte("nextValsHash"),
|
||||
}
|
||||
|
||||
// upgrade Height is at next block
|
||||
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
// last Height is at next block
|
||||
lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
|
||||
// zero custom fields and store in upgrade store
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedConsState)
|
||||
|
||||
// change upgradedClient client-specified parameters
|
||||
upgradedClient = ibctmtypes.NewClientState("wrongchainID", ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, true, true)
|
||||
@ -351,7 +371,8 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
proofUpgrade, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
@ -363,7 +384,10 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
|
||||
|
||||
tc.setup()
|
||||
|
||||
err := suite.chainA.App.IBCKeeper.ClientKeeper.UpgradeClient(suite.chainA.GetContext(), clientA, upgradedClient, upgradeHeight, proofUpgrade)
|
||||
// Call ZeroCustomFields on upgraded clients to clear any client-chosen parameters in test-case upgradedClient
|
||||
upgradedClient = upgradedClient.ZeroCustomFields()
|
||||
|
||||
err := suite.chainA.App.IBCKeeper.ClientKeeper.UpgradeClient(suite.chainA.GetContext(), clientA, upgradedClient, upgradedConsState, proofUpgradedClient, proofUpgradedConsState)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err, "verify upgrade failed on valid case: %s", tc.name)
|
||||
|
||||
@ -2,7 +2,6 @@ package keeper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
@ -246,13 +245,11 @@ func (k Keeper) ValidateSelfClient(ctx sdk.Context, clientState exported.ClientS
|
||||
tmClient.UnbondingPeriod, tmClient.TrustingPeriod)
|
||||
}
|
||||
|
||||
if tmClient.UpgradePath != "" {
|
||||
if len(tmClient.UpgradePath) != 0 {
|
||||
// For now, SDK IBC implementation assumes that upgrade path (if defined) is defined by SDK upgrade module
|
||||
// Must escape any merkle key before adding it to upgrade path
|
||||
upgradeKey := url.PathEscape(upgradetypes.KeyUpgradedClient)
|
||||
expectedUpgradePath := fmt.Sprintf("%s/%s", upgradetypes.StoreKey, upgradeKey)
|
||||
if tmClient.UpgradePath != expectedUpgradePath {
|
||||
return sdkerrors.Wrapf(types.ErrInvalidClient, "upgrade path must be the upgrade path defined by upgrade module. expected %s, got %s",
|
||||
expectedUpgradePath := []string{upgradetypes.StoreKey, upgradetypes.KeyUpgradedIBCState}
|
||||
if !reflect.DeepEqual(expectedUpgradePath, tmClient.UpgradePath) {
|
||||
return sdkerrors.Wrapf(types.ErrInvalidClient, "upgrade path must be the upgrade path defined by upgrade module. expected %v, got %v",
|
||||
expectedUpgradePath, tmClient.UpgradePath)
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,7 +166,7 @@ func (suite *KeeperTestSuite) TestValidateSelfClient() {
|
||||
},
|
||||
{
|
||||
"success with nil UpgradePath",
|
||||
ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), "", false, false),
|
||||
ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), nil, false, false),
|
||||
true,
|
||||
},
|
||||
{
|
||||
@ -216,7 +216,7 @@ func (suite *KeeperTestSuite) TestValidateSelfClient() {
|
||||
},
|
||||
{
|
||||
"invalid upgrade path",
|
||||
ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), "bad/upgrade/path", false, false),
|
||||
ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), []string{"bad", "upgrade", "path"}, false, false),
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
@ -37,6 +37,7 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
|
||||
(*sdk.Msg)(nil),
|
||||
&MsgCreateClient{},
|
||||
&MsgUpdateClient{},
|
||||
&MsgUpgradeClient{},
|
||||
&MsgSubmitMisbehaviour{},
|
||||
)
|
||||
|
||||
|
||||
@ -182,23 +182,24 @@ func (msg MsgUpdateClient) UnpackInterfaces(unpacker codectypes.AnyUnpacker) err
|
||||
|
||||
// NewMsgUpgradeClient creates a new MsgUpgradeClient instance
|
||||
// nolint: interfacer
|
||||
func NewMsgUpgradeClient(clientID string, clientState exported.ClientState, upgradeHeight exported.Height, proofUpgrade []byte, signer sdk.AccAddress) (*MsgUpgradeClient, error) {
|
||||
func NewMsgUpgradeClient(clientID string, clientState exported.ClientState, consState exported.ConsensusState,
|
||||
proofUpgradeClient, proofUpgradeConsState []byte, signer sdk.AccAddress) (*MsgUpgradeClient, error) {
|
||||
anyClient, err := PackClientState(clientState)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
height, ok := upgradeHeight.(Height)
|
||||
if !ok {
|
||||
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidHeight, "invalid height type. expected: %T, got: %T", &Height{}, upgradeHeight)
|
||||
anyConsState, err := PackConsensusState(consState)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &MsgUpgradeClient{
|
||||
ClientId: clientID,
|
||||
ClientState: anyClient,
|
||||
ProofUpgrade: proofUpgrade,
|
||||
UpgradeHeight: &height,
|
||||
Signer: signer.String(),
|
||||
ClientId: clientID,
|
||||
ClientState: anyClient,
|
||||
ConsensusState: anyConsState,
|
||||
ProofUpgradeClient: proofUpgradeClient,
|
||||
ProofUpgradeConsensusState: proofUpgradeConsState,
|
||||
Signer: signer.String(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -214,21 +215,28 @@ func (msg MsgUpgradeClient) Type() string {
|
||||
|
||||
// ValidateBasic implements sdk.Msg
|
||||
func (msg MsgUpgradeClient) ValidateBasic() error {
|
||||
// will not validate client state as committed client may not form a valid client state.
|
||||
// client implementations are responsible for ensuring final upgraded client is valid.
|
||||
clientState, err := UnpackClientState(msg.ClientState)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := clientState.Validate(); err != nil {
|
||||
// will not validate consensus state here since the trusted kernel may not form a valid consenus state.
|
||||
// client implementations are responsible for ensuring client can submit new headers against this consensus state.
|
||||
consensusState, err := UnpackConsensusState(msg.ConsensusState)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(msg.ProofUpgrade) == 0 {
|
||||
return sdkerrors.Wrap(ErrInvalidUpgradeClient, "proof of upgrade cannot be empty")
|
||||
|
||||
if clientState.ClientType() != consensusState.ClientType() {
|
||||
return sdkerrors.Wrapf(ErrInvalidUpgradeClient, "consensus state's client-type does not match client. expected: %s, got: %s",
|
||||
clientState.ClientType(), consensusState.ClientType())
|
||||
}
|
||||
if msg.UpgradeHeight == nil {
|
||||
return sdkerrors.Wrap(ErrInvalidUpgradeClient, "upgrade height cannot be nil")
|
||||
if len(msg.ProofUpgradeClient) == 0 {
|
||||
return sdkerrors.Wrap(ErrInvalidUpgradeClient, "proof of upgrade client cannot be empty")
|
||||
}
|
||||
if msg.UpgradeHeight.IsZero() {
|
||||
return sdkerrors.Wrap(ErrInvalidUpgradeClient, "upgrade height cannot be zero")
|
||||
if len(msg.ProofUpgradeConsensusState) == 0 {
|
||||
return sdkerrors.Wrap(ErrInvalidUpgradeClient, "proof of upgrade consensus state cannot be empty")
|
||||
}
|
||||
_, err = sdk.AccAddressFromBech32(msg.Signer)
|
||||
if err != nil {
|
||||
@ -254,8 +262,14 @@ func (msg MsgUpgradeClient) GetSigners() []sdk.AccAddress {
|
||||
|
||||
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
|
||||
func (msg MsgUpgradeClient) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
|
||||
var clientState exported.ClientState
|
||||
return unpacker.UnpackAny(msg.ClientState, &clientState)
|
||||
var (
|
||||
clientState exported.ClientState
|
||||
consState exported.ConsensusState
|
||||
)
|
||||
if err := unpacker.UnpackAny(msg.ClientState, &clientState); err != nil {
|
||||
return err
|
||||
}
|
||||
return unpacker.UnpackAny(msg.ConsensusState, &consState)
|
||||
}
|
||||
|
||||
// NewMsgSubmitMisbehaviour creates a new MsgSubmitMisbehaviour instance.
|
||||
|
||||
@ -339,8 +339,6 @@ func (suite *TypesTestSuite) TestMarshalMsgUpgradeClient() {
|
||||
err error
|
||||
)
|
||||
|
||||
newClientHeight := types.NewHeight(1, 1)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func()
|
||||
@ -349,7 +347,8 @@ func (suite *TypesTestSuite) TestMarshalMsgUpgradeClient() {
|
||||
"client upgrades to new tendermint client",
|
||||
func() {
|
||||
tendermintClient := ibctmtypes.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
|
||||
msg, err = types.NewMsgUpgradeClient("clientid", tendermintClient, newClientHeight, []byte("proofUpgrade"), suite.chainA.SenderAccount.GetAddress())
|
||||
tendermintConsState := &ibctmtypes.ConsensusState{NextValidatorsHash: []byte("nextValsHash")}
|
||||
msg, err = types.NewMsgUpgradeClient("clientid", tendermintClient, tendermintConsState, []byte("proofUpgradeClient"), []byte("proofUpgradeConsState"), suite.chainA.SenderAccount.GetAddress())
|
||||
suite.Require().NoError(err)
|
||||
},
|
||||
},
|
||||
@ -357,7 +356,7 @@ func (suite *TypesTestSuite) TestMarshalMsgUpgradeClient() {
|
||||
"client upgrades to new solomachine client",
|
||||
func() {
|
||||
soloMachine := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 1)
|
||||
msg, err = types.NewMsgUpgradeClient("clientid", soloMachine.ClientState(), newClientHeight, []byte("proofUpgrade"), suite.chainA.SenderAccount.GetAddress())
|
||||
msg, err = types.NewMsgUpgradeClient("clientid", soloMachine.ClientState(), soloMachine.ConsensusState(), []byte("proofUpgradeClient"), []byte("proofUpgradeConsState"), suite.chainA.SenderAccount.GetAddress())
|
||||
suite.Require().NoError(err)
|
||||
},
|
||||
},
|
||||
@ -381,8 +380,6 @@ func (suite *TypesTestSuite) TestMarshalMsgUpgradeClient() {
|
||||
newMsg := &types.MsgUpgradeClient{}
|
||||
err = cdc.UnmarshalJSON(bz, newMsg)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Require().True(proto.Equal(msg, newMsg))
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -412,20 +409,6 @@ func (suite *TypesTestSuite) TestMsgUpgradeClient_ValidateBasic() {
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "upgrade height is nil",
|
||||
malleate: func(msg *types.MsgUpgradeClient) {
|
||||
msg.UpgradeHeight = nil
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "upgrade height is zero",
|
||||
malleate: func(msg *types.MsgUpgradeClient) {
|
||||
msg.UpgradeHeight = &types.Height{}
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "unpacking clientstate fails",
|
||||
malleate: func(msg *types.MsgUpgradeClient) {
|
||||
@ -434,19 +417,33 @@ func (suite *TypesTestSuite) TestMsgUpgradeClient_ValidateBasic() {
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "invalid client state",
|
||||
name: "unpacking consensus state fails",
|
||||
malleate: func(msg *types.MsgUpgradeClient) {
|
||||
cs := &ibctmtypes.ClientState{}
|
||||
var err error
|
||||
msg.ClientState, err = types.PackClientState(cs)
|
||||
suite.Require().NoError(err)
|
||||
msg.ConsensusState = nil
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "empty proof",
|
||||
name: "client and consensus type does not match",
|
||||
malleate: func(msg *types.MsgUpgradeClient) {
|
||||
msg.ProofUpgrade = nil
|
||||
soloMachine := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 2)
|
||||
soloConsensus, err := types.PackConsensusState(soloMachine.ConsensusState())
|
||||
suite.Require().NoError(err)
|
||||
msg.ConsensusState = soloConsensus
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "empty client proof",
|
||||
malleate: func(msg *types.MsgUpgradeClient) {
|
||||
msg.ProofUpgradeClient = nil
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "empty consensus state proof",
|
||||
malleate: func(msg *types.MsgUpgradeClient) {
|
||||
msg.ProofUpgradeConsensusState = nil
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
@ -463,18 +460,18 @@ func (suite *TypesTestSuite) TestMsgUpgradeClient_ValidateBasic() {
|
||||
tc := tc
|
||||
|
||||
clientState := ibctmtypes.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
|
||||
newClientHeight := types.NewHeight(1, 1)
|
||||
msg, _ := types.NewMsgUpgradeClient("testclientid", clientState, newClientHeight, []byte("proofUpgrade"), suite.chainA.SenderAccount.GetAddress())
|
||||
consState := &ibctmtypes.ConsensusState{NextValidatorsHash: []byte("nextValsHash")}
|
||||
msg, err := types.NewMsgUpgradeClient("testclientid", clientState, consState, []byte("proofUpgradeClient"), []byte("proofUpgradeConsState"), suite.chainA.SenderAccount.GetAddress())
|
||||
suite.Require().NoError(err)
|
||||
|
||||
tc.malleate(msg)
|
||||
err := msg.ValidateBasic()
|
||||
err = msg.ValidateBasic()
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err, "valid case %s failed", tc.name)
|
||||
} else {
|
||||
suite.Require().Error(err, "invalid case %s passed", tc.name)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// tests that different misbehaviours within MsgSubmitMisbehaviour can be marshaled
|
||||
|
||||
@ -199,12 +199,14 @@ type MsgUpgradeClient struct {
|
||||
ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"`
|
||||
// upgraded client state
|
||||
ClientState *types.Any `protobuf:"bytes,2,opt,name=client_state,json=clientState,proto3" json:"client_state,omitempty" yaml:"client_state"`
|
||||
// height at which old chain halts and upgrades (i.e last block executed)
|
||||
UpgradeHeight *Height `protobuf:"bytes,3,opt,name=upgrade_height,json=upgradeHeight,proto3" json:"upgrade_height,omitempty" yaml:"upgrade_height"`
|
||||
// upgraded consensus state, only contains enough information to serve as a basis of trust in update logic
|
||||
ConsensusState *types.Any `protobuf:"bytes,3,opt,name=consensus_state,json=consensusState,proto3" json:"consensus_state,omitempty" yaml:"consensus_state"`
|
||||
// proof that old chain committed to new client
|
||||
ProofUpgrade []byte `protobuf:"bytes,4,opt,name=proof_upgrade,json=proofUpgrade,proto3" json:"proof_upgrade,omitempty" yaml:"proof_upgrade"`
|
||||
ProofUpgradeClient []byte `protobuf:"bytes,4,opt,name=proof_upgrade_client,json=proofUpgradeClient,proto3" json:"proof_upgrade_client,omitempty" yaml:"proof_upgrade_client"`
|
||||
// proof that old chain committed to new consensus state
|
||||
ProofUpgradeConsensusState []byte `protobuf:"bytes,5,opt,name=proof_upgrade_consensus_state,json=proofUpgradeConsensusState,proto3" json:"proof_upgrade_consensus_state,omitempty" yaml:"proof_upgrade_consensus_state"`
|
||||
// signer address
|
||||
Signer string `protobuf:"bytes,5,opt,name=signer,proto3" json:"signer,omitempty"`
|
||||
Signer string `protobuf:"bytes,6,opt,name=signer,proto3" json:"signer,omitempty"`
|
||||
}
|
||||
|
||||
func (m *MsgUpgradeClient) Reset() { *m = MsgUpgradeClient{} }
|
||||
@ -240,41 +242,6 @@ func (m *MsgUpgradeClient) XXX_DiscardUnknown() {
|
||||
|
||||
var xxx_messageInfo_MsgUpgradeClient proto.InternalMessageInfo
|
||||
|
||||
func (m *MsgUpgradeClient) GetClientId() string {
|
||||
if m != nil {
|
||||
return m.ClientId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *MsgUpgradeClient) GetClientState() *types.Any {
|
||||
if m != nil {
|
||||
return m.ClientState
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MsgUpgradeClient) GetUpgradeHeight() *Height {
|
||||
if m != nil {
|
||||
return m.UpgradeHeight
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MsgUpgradeClient) GetProofUpgrade() []byte {
|
||||
if m != nil {
|
||||
return m.ProofUpgrade
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MsgUpgradeClient) GetSigner() string {
|
||||
if m != nil {
|
||||
return m.Signer
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// MsgUpgradeClientResponse defines the Msg/UpgradeClient response type.
|
||||
type MsgUpgradeClientResponse struct {
|
||||
}
|
||||
@ -407,45 +374,45 @@ func init() {
|
||||
func init() { proto.RegisterFile("ibc/core/client/v1/tx.proto", fileDescriptor_cb5dc4651eb49a04) }
|
||||
|
||||
var fileDescriptor_cb5dc4651eb49a04 = []byte{
|
||||
// 608 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x55, 0x3f, 0x6f, 0xd3, 0x40,
|
||||
0x14, 0x8f, 0x1b, 0x88, 0xda, 0x6b, 0xd2, 0x56, 0x26, 0x6d, 0x13, 0x23, 0xec, 0xca, 0x30, 0x14,
|
||||
0xd1, 0xda, 0x24, 0x0c, 0xa0, 0x4a, 0x0c, 0xa4, 0x0b, 0x0c, 0x91, 0xc0, 0x15, 0x03, 0x08, 0x29,
|
||||
0xf8, 0xcf, 0xf5, 0x62, 0x91, 0xf8, 0x22, 0xdf, 0x39, 0x6a, 0xbe, 0x01, 0x23, 0x12, 0x7c, 0x80,
|
||||
0x8a, 0x81, 0xcf, 0xc2, 0xc0, 0xd0, 0x91, 0x29, 0x42, 0xc9, 0xc2, 0x9c, 0x4f, 0x80, 0x7c, 0x77,
|
||||
0xb1, 0xec, 0x34, 0x89, 0x22, 0x58, 0x98, 0xe2, 0x77, 0xef, 0xf7, 0x7e, 0xef, 0xe7, 0xdf, 0x7b,
|
||||
0x17, 0x83, 0xdb, 0xbe, 0xe3, 0x9a, 0x2e, 0x0e, 0xa1, 0xe9, 0x76, 0x7c, 0x18, 0x50, 0xb3, 0x5f,
|
||||
0x33, 0xe9, 0x85, 0xd1, 0x0b, 0x31, 0xc5, 0xb2, 0xec, 0x3b, 0xae, 0x11, 0x27, 0x0d, 0x9e, 0x34,
|
||||
0xfa, 0x35, 0xa5, 0x8c, 0x30, 0xc2, 0x2c, 0x6d, 0xc6, 0x4f, 0x1c, 0xa9, 0x54, 0x11, 0xc6, 0xa8,
|
||||
0x03, 0x4d, 0x16, 0x39, 0xd1, 0xb9, 0x69, 0x07, 0x03, 0x91, 0xd2, 0xe6, 0x74, 0x10, 0x74, 0x0c,
|
||||
0xa0, 0x7f, 0x5e, 0x03, 0xdb, 0x4d, 0x82, 0x4e, 0x43, 0x68, 0x53, 0x78, 0xca, 0x32, 0x72, 0x0d,
|
||||
0x6c, 0x70, 0x4c, 0xcb, 0xf7, 0x2a, 0xd2, 0x81, 0x74, 0xb8, 0xd1, 0x28, 0x4f, 0x86, 0xda, 0xce,
|
||||
0xc0, 0xee, 0x76, 0x4e, 0xf4, 0x24, 0xa5, 0x5b, 0xeb, 0xfc, 0xf9, 0x85, 0x27, 0xbf, 0x04, 0x45,
|
||||
0x71, 0x4e, 0xa8, 0x4d, 0x61, 0x65, 0xed, 0x40, 0x3a, 0xdc, 0xac, 0x97, 0x0d, 0xae, 0xcc, 0x98,
|
||||
0x2a, 0x33, 0x9e, 0x05, 0x83, 0xc6, 0xfe, 0x64, 0xa8, 0xdd, 0xca, 0x70, 0xb1, 0x1a, 0xdd, 0xda,
|
||||
0xe4, 0xe1, 0x59, 0x1c, 0xc9, 0x6f, 0xc0, 0xb6, 0x8b, 0x03, 0x02, 0x03, 0x12, 0x11, 0x41, 0x9a,
|
||||
0x5f, 0x42, 0xaa, 0x4c, 0x86, 0xda, 0x9e, 0x20, 0xcd, 0x96, 0xe9, 0xd6, 0x56, 0x72, 0xc2, 0xa9,
|
||||
0xf7, 0x40, 0x81, 0xf8, 0x28, 0x80, 0x61, 0xe5, 0x46, 0xfc, 0x72, 0x96, 0x88, 0x4e, 0xd6, 0x3f,
|
||||
0x5e, 0x6a, 0xb9, 0xdf, 0x97, 0x5a, 0x4e, 0xaf, 0x82, 0xfd, 0x19, 0x53, 0x2c, 0x48, 0x7a, 0x31,
|
||||
0x8b, 0xfe, 0x45, 0x62, 0x86, 0xbd, 0xee, 0x79, 0xff, 0x64, 0xd8, 0x11, 0x28, 0xb4, 0xa1, 0xed,
|
||||
0xc1, 0x70, 0x99, 0x55, 0x96, 0xc0, 0xa4, 0x14, 0xe7, 0x97, 0x2a, 0x4e, 0xab, 0x4a, 0x14, 0xff,
|
||||
0x58, 0x03, 0x3b, 0x2c, 0x87, 0x42, 0xdb, 0xfb, 0xaf, 0x66, 0xfc, 0x0e, 0x6c, 0x45, 0x5c, 0x55,
|
||||
0xab, 0x0d, 0x7d, 0xd4, 0xa6, 0x62, 0xc4, 0x8a, 0x71, 0x7d, 0xf7, 0x8d, 0xe7, 0x0c, 0xd1, 0xa8,
|
||||
0x4e, 0x86, 0xda, 0x2e, 0x67, 0xce, 0xd6, 0xea, 0x56, 0x49, 0x1c, 0x70, 0xa4, 0xfc, 0x14, 0x94,
|
||||
0x7a, 0x21, 0xc6, 0xe7, 0x2d, 0x71, 0xcc, 0xa6, 0x5d, 0x6c, 0x54, 0x26, 0x43, 0xad, 0xcc, 0x09,
|
||||
0x32, 0x69, 0xdd, 0x2a, 0xb2, 0x58, 0xf8, 0x94, 0xf2, 0xfc, 0x66, 0xda, 0x73, 0x5d, 0x01, 0x95,
|
||||
0x59, 0x37, 0x13, 0xab, 0xbf, 0x49, 0x60, 0xb7, 0x49, 0xd0, 0x59, 0xe4, 0x74, 0x7d, 0xda, 0xf4,
|
||||
0x89, 0x03, 0xdb, 0x76, 0xdf, 0xc7, 0x51, 0xf8, 0x37, 0x7e, 0x3f, 0x01, 0xc5, 0x6e, 0x8a, 0x62,
|
||||
0xe9, 0xa2, 0x64, 0x90, 0x2b, 0xac, 0x8b, 0x06, 0xee, 0xcc, 0xd5, 0x39, 0x7d, 0x93, 0xfa, 0xd7,
|
||||
0x3c, 0xc8, 0x37, 0x09, 0x92, 0xdf, 0x83, 0x62, 0xe6, 0xbf, 0xe1, 0xee, 0xbc, 0xd1, 0xcc, 0xdc,
|
||||
0x15, 0xe5, 0xc1, 0x0a, 0xa0, 0x69, 0xa7, 0xb8, 0x43, 0xe6, 0x32, 0x2d, 0xea, 0x90, 0x06, 0x2d,
|
||||
0xec, 0x30, 0xef, 0x02, 0xc8, 0x2e, 0x28, 0x65, 0x97, 0xff, 0xde, 0xc2, 0xea, 0x14, 0x4a, 0x39,
|
||||
0x5a, 0x05, 0x95, 0x34, 0x09, 0x81, 0x3c, 0x67, 0xec, 0xf7, 0x17, 0x70, 0x5c, 0x87, 0x2a, 0xb5,
|
||||
0x95, 0xa1, 0xd3, 0x9e, 0x8d, 0x57, 0xdf, 0x47, 0xaa, 0x74, 0x35, 0x52, 0xa5, 0x5f, 0x23, 0x55,
|
||||
0xfa, 0x34, 0x56, 0x73, 0x57, 0x63, 0x35, 0xf7, 0x73, 0xac, 0xe6, 0xde, 0x3e, 0x46, 0x3e, 0x6d,
|
||||
0x47, 0x8e, 0xe1, 0xe2, 0xae, 0xe9, 0x62, 0xd2, 0xc5, 0x44, 0xfc, 0x1c, 0x13, 0xef, 0x83, 0x79,
|
||||
0x61, 0x26, 0x9f, 0x85, 0x87, 0xf5, 0x63, 0xf1, 0x65, 0xa0, 0x83, 0x1e, 0x24, 0x4e, 0x81, 0xad,
|
||||
0xd5, 0xa3, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xb1, 0x03, 0x55, 0x1e, 0x9b, 0x06, 0x00, 0x00,
|
||||
// 598 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x55, 0x3f, 0x6f, 0xd3, 0x4e,
|
||||
0x18, 0x8e, 0x9b, 0xdf, 0x2f, 0x6a, 0xaf, 0x81, 0x56, 0x26, 0xb4, 0xa9, 0xab, 0xda, 0x95, 0xe9,
|
||||
0x10, 0x44, 0xeb, 0x23, 0x61, 0x00, 0x75, 0x23, 0x9d, 0x18, 0x22, 0x51, 0x57, 0x0c, 0xb0, 0x04,
|
||||
0xff, 0xb9, 0x5e, 0xac, 0x26, 0xbe, 0xc8, 0x67, 0x47, 0xcd, 0x37, 0x60, 0x44, 0x82, 0x0f, 0x50,
|
||||
0x31, 0xf0, 0x59, 0x18, 0x3b, 0x30, 0x30, 0x45, 0x28, 0x59, 0x98, 0xf3, 0x09, 0x90, 0xef, 0x1c,
|
||||
0xcb, 0x76, 0xed, 0x28, 0x82, 0x91, 0xc9, 0x7e, 0xef, 0x7d, 0xee, 0x79, 0x9e, 0x7b, 0xdf, 0xf7,
|
||||
0x6c, 0xb0, 0xef, 0x98, 0x16, 0xb4, 0x88, 0x87, 0xa0, 0xd5, 0x77, 0x90, 0xeb, 0xc3, 0x51, 0x13,
|
||||
0xfa, 0xd7, 0xda, 0xd0, 0x23, 0x3e, 0x11, 0x45, 0xc7, 0xb4, 0xb4, 0x30, 0xa9, 0xf1, 0xa4, 0x36,
|
||||
0x6a, 0x4a, 0x35, 0x4c, 0x30, 0x61, 0x69, 0x18, 0xbe, 0x71, 0xa4, 0xb4, 0x87, 0x09, 0xc1, 0x7d,
|
||||
0x04, 0x59, 0x64, 0x06, 0x97, 0xd0, 0x70, 0xc7, 0x51, 0x4a, 0xc9, 0x51, 0x88, 0xe8, 0x18, 0x40,
|
||||
0xfd, 0xb4, 0x06, 0xb6, 0x3a, 0x14, 0x9f, 0x79, 0xc8, 0xf0, 0xd1, 0x19, 0xcb, 0x88, 0x4d, 0xb0,
|
||||
0xc1, 0x31, 0x5d, 0xc7, 0xae, 0x0b, 0x87, 0x42, 0x63, 0xa3, 0x5d, 0x9b, 0x4f, 0x94, 0xed, 0xb1,
|
||||
0x31, 0xe8, 0x9f, 0xaa, 0x71, 0x4a, 0xd5, 0xd7, 0xf9, 0xfb, 0x2b, 0x5b, 0x7c, 0x0d, 0xaa, 0xd1,
|
||||
0x3a, 0xf5, 0x0d, 0x1f, 0xd5, 0xd7, 0x0e, 0x85, 0xc6, 0x66, 0xab, 0xa6, 0x71, 0x67, 0xda, 0xc2,
|
||||
0x99, 0xf6, 0xd2, 0x1d, 0xb7, 0x77, 0xe7, 0x13, 0xe5, 0x41, 0x8a, 0x8b, 0xed, 0x51, 0xf5, 0x4d,
|
||||
0x1e, 0x5e, 0x84, 0x91, 0xf8, 0x16, 0x6c, 0x59, 0xc4, 0xa5, 0xc8, 0xa5, 0x01, 0x8d, 0x48, 0xcb,
|
||||
0x4b, 0x48, 0xa5, 0xf9, 0x44, 0xd9, 0x89, 0x48, 0xd3, 0xdb, 0x54, 0xfd, 0x7e, 0xbc, 0xc2, 0xa9,
|
||||
0x77, 0x40, 0x85, 0x3a, 0xd8, 0x45, 0x5e, 0xfd, 0xbf, 0xf0, 0x70, 0x7a, 0x14, 0x9d, 0xae, 0x7f,
|
||||
0xb8, 0x51, 0x4a, 0xbf, 0x6e, 0x94, 0x92, 0xba, 0x07, 0x76, 0x33, 0x45, 0xd1, 0x11, 0x1d, 0x86,
|
||||
0x2c, 0xea, 0x67, 0x81, 0x15, 0xec, 0xcd, 0xd0, 0xfe, 0xab, 0x82, 0x1d, 0x83, 0x4a, 0x0f, 0x19,
|
||||
0x36, 0xf2, 0x96, 0x95, 0x4a, 0x8f, 0x30, 0x09, 0xc7, 0xe5, 0xa5, 0x8e, 0x93, 0xae, 0x62, 0xc7,
|
||||
0xdf, 0xcb, 0x60, 0x9b, 0xe5, 0xb0, 0x67, 0xd8, 0xff, 0x4a, 0x8f, 0xcf, 0x41, 0x6d, 0xe8, 0x11,
|
||||
0x72, 0xd9, 0x0d, 0xf8, 0xb1, 0xbb, 0x5c, 0x97, 0x75, 0xbc, 0xda, 0x56, 0xe6, 0x13, 0x65, 0x9f,
|
||||
0x33, 0xe5, 0xa1, 0x54, 0x5d, 0x64, 0xcb, 0xe9, 0x92, 0x5d, 0x81, 0x83, 0x0c, 0x38, 0xe3, 0xfd,
|
||||
0x7f, 0xc6, 0xdd, 0x98, 0x4f, 0x94, 0xa3, 0x5c, 0xee, 0xac, 0x67, 0x29, 0x25, 0x52, 0x34, 0xa3,
|
||||
0x95, 0x82, 0x8e, 0x4b, 0xa0, 0x9e, 0xed, 0x6a, 0xdc, 0xf2, 0xaf, 0x02, 0x78, 0xd8, 0xa1, 0xf8,
|
||||
0x22, 0x30, 0x07, 0x8e, 0xdf, 0x71, 0xa8, 0x89, 0x7a, 0xc6, 0xc8, 0x21, 0x81, 0xf7, 0x27, 0x7d,
|
||||
0x7f, 0x01, 0xaa, 0x83, 0x04, 0xc5, 0xd2, 0x81, 0x4d, 0x21, 0x57, 0x18, 0x5b, 0x05, 0x1c, 0xe4,
|
||||
0xfa, 0x5c, 0x9c, 0xa4, 0xf5, 0xa5, 0x0c, 0xca, 0x1d, 0x8a, 0xc5, 0xf7, 0xa0, 0x9a, 0xfa, 0x46,
|
||||
0x3d, 0xd2, 0xee, 0x7e, 0x1e, 0xb5, 0xcc, 0x9d, 0x95, 0x9e, 0xac, 0x00, 0x5a, 0x28, 0x85, 0x0a,
|
||||
0xa9, 0x4b, 0x5d, 0xa4, 0x90, 0x04, 0x15, 0x2a, 0xe4, 0x5d, 0x44, 0xd1, 0x02, 0xf7, 0xd2, 0x13,
|
||||
0x75, 0x54, 0xb8, 0x3b, 0x81, 0x92, 0x8e, 0x57, 0x41, 0xc5, 0x22, 0x1e, 0x10, 0x73, 0xda, 0xfe,
|
||||
0xb8, 0x80, 0xe3, 0x2e, 0x54, 0x6a, 0xae, 0x0c, 0x5d, 0x68, 0xb6, 0xcf, 0xbf, 0x4d, 0x65, 0xe1,
|
||||
0x76, 0x2a, 0x0b, 0x3f, 0xa7, 0xb2, 0xf0, 0x71, 0x26, 0x97, 0x6e, 0x67, 0x72, 0xe9, 0xc7, 0x4c,
|
||||
0x2e, 0xbd, 0x7b, 0x8e, 0x1d, 0xbf, 0x17, 0x98, 0x9a, 0x45, 0x06, 0xd0, 0x22, 0x74, 0x40, 0x68,
|
||||
0xf4, 0x38, 0xa1, 0xf6, 0x15, 0xbc, 0x86, 0xf1, 0xef, 0xe9, 0x69, 0xeb, 0x24, 0xfa, 0x43, 0xf9,
|
||||
0xe3, 0x21, 0xa2, 0x66, 0x85, 0x8d, 0xd5, 0xb3, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xd2, 0x19,
|
||||
0x59, 0x52, 0x23, 0x07, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
@ -825,18 +792,25 @@ func (m *MsgUpgradeClient) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
copy(dAtA[i:], m.Signer)
|
||||
i = encodeVarintTx(dAtA, i, uint64(len(m.Signer)))
|
||||
i--
|
||||
dAtA[i] = 0x32
|
||||
}
|
||||
if len(m.ProofUpgradeConsensusState) > 0 {
|
||||
i -= len(m.ProofUpgradeConsensusState)
|
||||
copy(dAtA[i:], m.ProofUpgradeConsensusState)
|
||||
i = encodeVarintTx(dAtA, i, uint64(len(m.ProofUpgradeConsensusState)))
|
||||
i--
|
||||
dAtA[i] = 0x2a
|
||||
}
|
||||
if len(m.ProofUpgrade) > 0 {
|
||||
i -= len(m.ProofUpgrade)
|
||||
copy(dAtA[i:], m.ProofUpgrade)
|
||||
i = encodeVarintTx(dAtA, i, uint64(len(m.ProofUpgrade)))
|
||||
if len(m.ProofUpgradeClient) > 0 {
|
||||
i -= len(m.ProofUpgradeClient)
|
||||
copy(dAtA[i:], m.ProofUpgradeClient)
|
||||
i = encodeVarintTx(dAtA, i, uint64(len(m.ProofUpgradeClient)))
|
||||
i--
|
||||
dAtA[i] = 0x22
|
||||
}
|
||||
if m.UpgradeHeight != nil {
|
||||
if m.ConsensusState != nil {
|
||||
{
|
||||
size, err := m.UpgradeHeight.MarshalToSizedBuffer(dAtA[:i])
|
||||
size, err := m.ConsensusState.MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -1052,11 +1026,15 @@ func (m *MsgUpgradeClient) Size() (n int) {
|
||||
l = m.ClientState.Size()
|
||||
n += 1 + l + sovTx(uint64(l))
|
||||
}
|
||||
if m.UpgradeHeight != nil {
|
||||
l = m.UpgradeHeight.Size()
|
||||
if m.ConsensusState != nil {
|
||||
l = m.ConsensusState.Size()
|
||||
n += 1 + l + sovTx(uint64(l))
|
||||
}
|
||||
l = len(m.ProofUpgrade)
|
||||
l = len(m.ProofUpgradeClient)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovTx(uint64(l))
|
||||
}
|
||||
l = len(m.ProofUpgradeConsensusState)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovTx(uint64(l))
|
||||
}
|
||||
@ -1659,7 +1637,7 @@ func (m *MsgUpgradeClient) Unmarshal(dAtA []byte) error {
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field UpgradeHeight", wireType)
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ConsensusState", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
@ -1686,16 +1664,16 @@ func (m *MsgUpgradeClient) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.UpgradeHeight == nil {
|
||||
m.UpgradeHeight = &Height{}
|
||||
if m.ConsensusState == nil {
|
||||
m.ConsensusState = &types.Any{}
|
||||
}
|
||||
if err := m.UpgradeHeight.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
if err := m.ConsensusState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 4:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ProofUpgrade", wireType)
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ProofUpgradeClient", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
@ -1722,12 +1700,46 @@ func (m *MsgUpgradeClient) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.ProofUpgrade = append(m.ProofUpgrade[:0], dAtA[iNdEx:postIndex]...)
|
||||
if m.ProofUpgrade == nil {
|
||||
m.ProofUpgrade = []byte{}
|
||||
m.ProofUpgradeClient = append(m.ProofUpgradeClient[:0], dAtA[iNdEx:postIndex]...)
|
||||
if m.ProofUpgradeClient == nil {
|
||||
m.ProofUpgradeClient = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 5:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ProofUpgradeConsensusState", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTx
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthTx
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthTx
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.ProofUpgradeConsensusState = append(m.ProofUpgradeConsensusState[:0], dAtA[iNdEx:postIndex]...)
|
||||
if m.ProofUpgradeConsensusState == nil {
|
||||
m.ProofUpgradeConsensusState = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 6:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType)
|
||||
}
|
||||
|
||||
@ -39,13 +39,19 @@ type ClientState interface {
|
||||
CheckProposedHeaderAndUpdateState(sdk.Context, codec.BinaryMarshaler, sdk.KVStore, Header) (ClientState, ConsensusState, error)
|
||||
|
||||
// Upgrade functions
|
||||
// NOTE: proof heights are not included as upgrade to a new version is expected to pass only on the last
|
||||
// height committed by the current version. Clients are responsible for ensuring that the planned last
|
||||
// height of the current version is somehow encoded in the proof verification process.
|
||||
// This is to ensure that no premature upgrades occur, since upgrade plans committed to by the counterparty
|
||||
// may be cancelled or modified before the last planned height.
|
||||
VerifyUpgradeAndUpdateState(
|
||||
ctx sdk.Context,
|
||||
cdc codec.BinaryMarshaler,
|
||||
store sdk.KVStore,
|
||||
newClient ClientState,
|
||||
upgradeHeight Height,
|
||||
proofUpgrade []byte,
|
||||
newConsState ConsensusState,
|
||||
proofUpgradeClient,
|
||||
proofUpgradeConsState []byte,
|
||||
) (ClientState, ConsensusState, error)
|
||||
// Utility function that zeroes out any client customizable fields in client state
|
||||
// Ledger enforced fields are maintained while all custom fields are zero values
|
||||
|
||||
@ -83,8 +83,13 @@ func (k Keeper) UpgradeClient(goCtx context.Context, msg *clienttypes.MsgUpgrade
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
upgradedConsState, err := clienttypes.UnpackConsensusState(msg.ConsensusState)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = k.ClientKeeper.UpgradeClient(ctx, msg.ClientId, upgradedClient, msg.UpgradeHeight, msg.ProofUpgrade); err != nil {
|
||||
if err = k.ClientKeeper.UpgradeClient(ctx, msg.ClientId, upgradedClient, upgradedConsState,
|
||||
msg.ProofUpgradeClient, msg.ProofUpgradeConsensusState); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,6 @@ package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
@ -611,10 +610,11 @@ func (suite *KeeperTestSuite) TestHandleTimeoutOnClosePacket() {
|
||||
|
||||
func (suite *KeeperTestSuite) TestUpgradeClient() {
|
||||
var (
|
||||
clientA string
|
||||
upgradedClient exported.ClientState
|
||||
upgradeHeight exported.Height
|
||||
msg *clienttypes.MsgUpgradeClient
|
||||
clientA string
|
||||
upgradedClient exported.ClientState
|
||||
upgradedConsState exported.ConsensusState
|
||||
lastHeight exported.Height
|
||||
msg *clienttypes.MsgUpgradeClient
|
||||
)
|
||||
|
||||
newClientHeight := clienttypes.NewHeight(1, 1)
|
||||
@ -628,13 +628,20 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
|
||||
name: "successful upgrade",
|
||||
setup: func() {
|
||||
|
||||
upgradedClient = ibctmtypes.NewClientState("newChainId", ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod+ibctesting.TrustingPeriod, ibctesting.MaxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
|
||||
upgradedClient = ibctmtypes.NewClientState("newChainId", ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod+ibctesting.TrustingPeriod, ibctesting.MaxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
|
||||
// Call ZeroCustomFields on upgraded clients to clear any client-chosen parameters in test-case upgradedClient
|
||||
upgradedClient = upgradedClient.ZeroCustomFields()
|
||||
|
||||
// upgrade Height is at next block
|
||||
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
upgradedConsState = &ibctmtypes.ConsensusState{
|
||||
NextValidatorsHash: []byte("nextValsHash"),
|
||||
}
|
||||
|
||||
// last Height is at next block
|
||||
lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
|
||||
// zero custom fields and store in upgrade store
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedConsState)
|
||||
|
||||
// commit upgrade store changes and update clients
|
||||
|
||||
@ -645,46 +652,33 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
proofUpgrade, _ := suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradeClient, _ := suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedConsState, _ := suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
|
||||
msg, err = clienttypes.NewMsgUpgradeClient(clientA, upgradedClient, upgradeHeight, proofUpgrade, suite.chainA.SenderAccount.GetAddress())
|
||||
msg, err = clienttypes.NewMsgUpgradeClient(clientA, upgradedClient, upgradedConsState,
|
||||
proofUpgradeClient, proofUpgradedConsState, suite.chainA.SenderAccount.GetAddress())
|
||||
suite.Require().NoError(err)
|
||||
},
|
||||
expPass: true,
|
||||
},
|
||||
{
|
||||
name: "invalid upgrade: msg.ClientState does not contain valid clientstate",
|
||||
setup: func() {
|
||||
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
// upgrade Height is at next block
|
||||
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
|
||||
proofUpgrade, _ := suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
|
||||
consState := ibctmtypes.NewConsensusState(time.Now(), commitmenttypes.NewMerkleRoot([]byte("app_hash")), []byte("next_vals_hash"))
|
||||
consAny, err := clienttypes.PackConsensusState(consState)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
height, _ := upgradeHeight.(clienttypes.Height)
|
||||
|
||||
msg = &clienttypes.MsgUpgradeClient{ClientId: clientA, ClientState: consAny, UpgradeHeight: &height, ProofUpgrade: proofUpgrade, Signer: suite.chainA.SenderAccount.GetAddress().String()}
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "VerifyUpgrade fails",
|
||||
setup: func() {
|
||||
|
||||
upgradedClient = ibctmtypes.NewClientState("newChainId", ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod+ibctesting.TrustingPeriod, ibctesting.MaxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
|
||||
upgradedClient = ibctmtypes.NewClientState("newChainId", ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod+ibctesting.TrustingPeriod, ibctesting.MaxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
|
||||
// Call ZeroCustomFields on upgraded clients to clear any client-chosen parameters in test-case upgradedClient
|
||||
upgradedClient = upgradedClient.ZeroCustomFields()
|
||||
|
||||
// upgrade Height is at next block
|
||||
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
upgradedConsState = &ibctmtypes.ConsensusState{
|
||||
NextValidatorsHash: []byte("nextValsHash"),
|
||||
}
|
||||
|
||||
// last Height is at next block
|
||||
lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
|
||||
// zero custom fields and store in upgrade store
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedConsState)
|
||||
|
||||
// commit upgrade store changes and update clients
|
||||
|
||||
@ -692,7 +686,7 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
|
||||
err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
msg, err = clienttypes.NewMsgUpgradeClient(clientA, upgradedClient, upgradeHeight, nil, suite.chainA.SenderAccount.GetAddress())
|
||||
msg, err = clienttypes.NewMsgUpgradeClient(clientA, upgradedClient, upgradedConsState, nil, nil, suite.chainA.SenderAccount.GetAddress())
|
||||
suite.Require().NoError(err)
|
||||
},
|
||||
expPass: false,
|
||||
@ -711,7 +705,8 @@ func (suite *KeeperTestSuite) TestUpgradeClient() {
|
||||
suite.Require().NoError(err, "upgrade handler failed on valid case: %s", tc.name)
|
||||
newClient, ok := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(ok)
|
||||
suite.Require().Equal(upgradedClient, newClient)
|
||||
newChainSpecifiedClient := newClient.ZeroCustomFields()
|
||||
suite.Require().Equal(upgradedClient, newChainSpecifiedClient)
|
||||
} else {
|
||||
suite.Require().Error(err, "upgrade handler passed on invalid case: %s", tc.name)
|
||||
}
|
||||
|
||||
@ -77,7 +77,7 @@ func (cs ClientState) ZeroCustomFields() exported.ClientState {
|
||||
// VerifyUpgradeAndUpdateState returns an error since solomachine client does not support upgrades
|
||||
func (cs ClientState) VerifyUpgradeAndUpdateState(
|
||||
_ sdk.Context, _ codec.BinaryMarshaler, _ sdk.KVStore,
|
||||
_ exported.ClientState, _ exported.Height, _ []byte,
|
||||
_ exported.ClientState, _ exported.ConsensusState, _, _ []byte,
|
||||
) (exported.ClientState, exported.ConsensusState, error) {
|
||||
return nil, nil, sdkerrors.Wrap(clienttypes.ErrInvalidUpgradeClient, "cannot upgrade solomachine client")
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ func NewCreateClientCmd() *cobra.Command {
|
||||
Long: `Create a new tendermint IBC client.
|
||||
- 'trust-level' flag can be a fraction (eg: '1/3') or 'default'
|
||||
- 'proof-specs' flag can be JSON input, a path to a .json file or 'default'
|
||||
- 'upgrade-path' flag is a string specifying the upgrade path for this chain where a future upgraded client will be stored. The path represents a keypath for the store with each key separated by a '/'. Any slash within a key must be escaped.
|
||||
- 'upgrade-path' flag is a string specifying the upgrade path for this chain where a future upgraded client will be stored. The path is a comma-separated list representing the keys in order of the keyPath to the committed upgraded client.
|
||||
e.g. 'upgrade/upgradedClient'`,
|
||||
Example: fmt.Sprintf("%s tx ibc %s create [client-id] [path/to/consensus_state.json] [trusting_period] [unbonding_period] [max_clock_drift] --trust-level default --consensus-params [path/to/consensus-params.json] --proof-specs [path/to/proof-specs.json] --upgrade-path upgrade/upgradedClient --from node0 --home ../node0/<app>cli --chain-id $CID", version.AppName, types.SubModuleName),
|
||||
Args: cobra.ExactArgs(5),
|
||||
@ -119,7 +119,8 @@ func NewCreateClientCmd() *cobra.Command {
|
||||
allowUpdateAfterExpiry, _ := cmd.Flags().GetBool(flagAllowUpdateAfterExpiry)
|
||||
allowUpdateAfterMisbehaviour, _ := cmd.Flags().GetBool(flagAllowUpdateAfterMisbehaviour)
|
||||
|
||||
upgradePath, _ := cmd.Flags().GetString(flagUpgradePath)
|
||||
upgradePathStr, _ := cmd.Flags().GetString(flagUpgradePath)
|
||||
upgradePath := strings.Split(upgradePathStr, ",")
|
||||
|
||||
// validate header
|
||||
if err := header.ValidateBasic(); err != nil {
|
||||
|
||||
@ -25,7 +25,7 @@ func NewClientState(
|
||||
chainID string, trustLevel Fraction,
|
||||
trustingPeriod, ubdPeriod, maxClockDrift time.Duration,
|
||||
latestHeight clienttypes.Height, specs []*ics23.ProofSpec,
|
||||
upgradePath string, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour bool,
|
||||
upgradePath []string, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour bool,
|
||||
) *ClientState {
|
||||
return &ClientState{
|
||||
ChainId: chainID,
|
||||
@ -105,17 +105,15 @@ func (cs ClientState) Validate() error {
|
||||
if cs.ProofSpecs == nil {
|
||||
return sdkerrors.Wrap(ErrInvalidProofSpecs, "proof specs cannot be nil for tm client")
|
||||
}
|
||||
for _, spec := range cs.ProofSpecs {
|
||||
for i, spec := range cs.ProofSpecs {
|
||||
if spec == nil {
|
||||
return sdkerrors.Wrap(ErrInvalidProofSpecs, "proof spec cannot be nil")
|
||||
return sdkerrors.Wrapf(ErrInvalidProofSpecs, "proof spec cannot be nil at index: %d", i)
|
||||
}
|
||||
}
|
||||
if cs.UpgradePath != "" {
|
||||
keys := strings.Split(cs.UpgradePath, "/")
|
||||
for _, k := range keys {
|
||||
if strings.TrimSpace(k) == "" {
|
||||
return sdkerrors.Wrapf(clienttypes.ErrInvalidUpgradeClient, "upgrade path contains an empty string when splitting by '/': %s", cs.UpgradePath)
|
||||
}
|
||||
// UpgradePath may be empty, but if it isn't, each key must be non-empty
|
||||
for i, k := range cs.UpgradePath {
|
||||
if strings.TrimSpace(k) == "" {
|
||||
return sdkerrors.Wrapf(clienttypes.ErrInvalidClient, "key in upgrade path at index %d cannot be empty", i)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -38,7 +38,7 @@ func (suite *TendermintTestSuite) TestValidate() {
|
||||
},
|
||||
{
|
||||
name: "valid client with nil upgrade path",
|
||||
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), "", false, false),
|
||||
clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), nil, false, false),
|
||||
expPass: true,
|
||||
},
|
||||
{
|
||||
|
||||
@ -51,8 +51,12 @@ type ClientState struct {
|
||||
LatestHeight types.Height `protobuf:"bytes,7,opt,name=latest_height,json=latestHeight,proto3" json:"latest_height" yaml:"latest_height"`
|
||||
// Proof specifications used in verifying counterparty state
|
||||
ProofSpecs []*_go.ProofSpec `protobuf:"bytes,8,rep,name=proof_specs,json=proofSpecs,proto3" json:"proof_specs,omitempty" yaml:"proof_specs"`
|
||||
// Path at which next upgraded client will be committed
|
||||
UpgradePath string `protobuf:"bytes,9,opt,name=upgrade_path,json=upgradePath,proto3" json:"upgrade_path,omitempty" yaml:"upgrade_path"`
|
||||
// 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"}`
|
||||
UpgradePath []string `protobuf:"bytes,9,rep,name=upgrade_path,json=upgradePath,proto3" json:"upgrade_path,omitempty" yaml:"upgrade_path"`
|
||||
// This flag, when set to true, will allow governance to recover a client
|
||||
// which has expired
|
||||
AllowUpdateAfterExpiry bool `protobuf:"varint,10,opt,name=allow_update_after_expiry,json=allowUpdateAfterExpiry,proto3" json:"allow_update_after_expiry,omitempty" yaml:"allow_update_after_expiry"`
|
||||
@ -317,75 +321,75 @@ func init() {
|
||||
}
|
||||
|
||||
var fileDescriptor_c6d6cf2b288949be = []byte{
|
||||
// 1079 bytes of a gzipped FileDescriptorProto
|
||||
// 1081 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xcf, 0x6f, 0xe3, 0xc4,
|
||||
0x17, 0x6f, 0xda, 0x7e, 0xb7, 0xe9, 0x24, 0xdd, 0xf6, 0xeb, 0x2d, 0xdd, 0xb4, 0x74, 0xe3, 0xc8,
|
||||
0xa0, 0xa5, 0x42, 0xaa, 0x4d, 0xb2, 0x48, 0x48, 0x15, 0x17, 0xdc, 0x82, 0x5a, 0xc4, 0x4a, 0x95,
|
||||
0xcb, 0x0f, 0x09, 0x09, 0xcc, 0xc4, 0x9e, 0x24, 0xa3, 0xda, 0x1e, 0xe3, 0x99, 0x84, 0x94, 0xbf,
|
||||
0x17, 0x6f, 0xda, 0x7e, 0xb7, 0xc9, 0x24, 0xdd, 0xf6, 0xeb, 0x2d, 0xdd, 0xb4, 0x74, 0xe3, 0xc8,
|
||||
0xa0, 0x25, 0x42, 0xaa, 0x4d, 0xb2, 0x48, 0x48, 0x15, 0x17, 0xdc, 0x82, 0x5a, 0xc4, 0x4a, 0x95,
|
||||
0xcb, 0x0f, 0x09, 0x09, 0xcc, 0xc4, 0x9e, 0xc4, 0xa3, 0xda, 0x1e, 0xe3, 0x99, 0x84, 0x94, 0xbf,
|
||||
0x00, 0x0e, 0x48, 0x7b, 0x44, 0x9c, 0x38, 0xf0, 0xc7, 0xec, 0xb1, 0x47, 0x4e, 0x06, 0xb5, 0x17,
|
||||
0xce, 0x39, 0x72, 0x42, 0xf3, 0xc3, 0xf6, 0x34, 0xdb, 0xa5, 0x5a, 0x2e, 0xed, 0xbc, 0xf7, 0x3e,
|
||||
0xef, 0xf3, 0xc9, 0xbc, 0x79, 0xf3, 0xc6, 0xc0, 0xc1, 0xfd, 0xc0, 0x89, 0xf0, 0x70, 0xc4, 0x82,
|
||||
0x08, 0xa3, 0x84, 0x51, 0x87, 0xa1, 0x24, 0x44, 0x59, 0x8c, 0x13, 0xe6, 0x4c, 0xba, 0x9a, 0x65,
|
||||
0xa7, 0x19, 0x61, 0xc4, 0x68, 0xe3, 0x7e, 0x60, 0xeb, 0x09, 0xb6, 0x06, 0x99, 0x74, 0x77, 0x3a,
|
||||
0x5a, 0x3e, 0xbb, 0x48, 0x11, 0x75, 0x26, 0x30, 0xc2, 0x21, 0x64, 0x24, 0x93, 0x0c, 0x3b, 0xbb,
|
||||
0x2f, 0x20, 0xc4, 0x5f, 0x15, 0x7d, 0x10, 0x90, 0x64, 0x80, 0x89, 0x93, 0x66, 0x84, 0x0c, 0x0a,
|
||||
0x67, 0x7b, 0x48, 0xc8, 0x30, 0x42, 0x8e, 0xb0, 0xfa, 0xe3, 0x81, 0x13, 0x8e, 0x33, 0xc8, 0x30,
|
||||
0x49, 0x54, 0xdc, 0x9c, 0x8f, 0x33, 0x1c, 0x23, 0xca, 0x60, 0x9c, 0x16, 0x00, 0xbe, 0xcd, 0x80,
|
||||
0x64, 0xc8, 0x91, 0xbf, 0x9a, 0x6f, 0x4d, 0xae, 0x14, 0xe0, 0xad, 0x0a, 0x40, 0xe2, 0x18, 0xb3,
|
||||
0xb8, 0x00, 0x95, 0x96, 0x02, 0x6e, 0x0e, 0xc9, 0x90, 0x88, 0xa5, 0xc3, 0x57, 0xd2, 0x6b, 0xfd,
|
||||
0xb5, 0x02, 0x1a, 0x87, 0x82, 0xef, 0x8c, 0x41, 0x86, 0x8c, 0x6d, 0x50, 0x0f, 0x46, 0x10, 0x27,
|
||||
0x3e, 0x0e, 0x5b, 0xb5, 0x4e, 0x6d, 0x6f, 0xd5, 0x5b, 0x11, 0xf6, 0x49, 0x68, 0x20, 0xd0, 0x60,
|
||||
0xd9, 0x98, 0x32, 0x3f, 0x42, 0x13, 0x14, 0xb5, 0x16, 0x3b, 0xb5, 0xbd, 0x46, 0x6f, 0xcf, 0xfe,
|
||||
0xf7, 0xb2, 0xda, 0x1f, 0x65, 0x30, 0xe0, 0x1b, 0x76, 0x77, 0x9e, 0xe7, 0xe6, 0xc2, 0x2c, 0x37,
|
||||
0x8d, 0x0b, 0x18, 0x47, 0x07, 0x96, 0x46, 0x65, 0x79, 0x40, 0x58, 0x9f, 0x70, 0xc3, 0x18, 0x80,
|
||||
0x75, 0x61, 0xe1, 0x64, 0xe8, 0xa7, 0x28, 0xc3, 0x24, 0x6c, 0x2d, 0x09, 0xa9, 0x6d, 0x5b, 0x16,
|
||||
0xcb, 0x2e, 0x8a, 0x65, 0x1f, 0xa9, 0x62, 0xba, 0x96, 0xe2, 0xde, 0xd2, 0xb8, 0xab, 0x7c, 0xeb,
|
||||
0xe7, 0x3f, 0xcc, 0x9a, 0x77, 0xbf, 0xf0, 0x9e, 0x0a, 0xa7, 0x81, 0xc1, 0xc6, 0x38, 0xe9, 0x93,
|
||||
0x24, 0xd4, 0x84, 0x96, 0xef, 0x12, 0x7a, 0x43, 0x09, 0x3d, 0x94, 0x42, 0xf3, 0x04, 0x52, 0x69,
|
||||
0xbd, 0x74, 0x2b, 0x29, 0x04, 0xd6, 0x63, 0x38, 0xf5, 0x83, 0x88, 0x04, 0xe7, 0x7e, 0x98, 0xe1,
|
||||
0x01, 0x6b, 0xfd, 0xef, 0x15, 0xb7, 0x34, 0x97, 0x2f, 0x85, 0xd6, 0x62, 0x38, 0x3d, 0xe4, 0xce,
|
||||
0x23, 0xee, 0x33, 0xbe, 0x02, 0x6b, 0x83, 0x8c, 0x7c, 0x8f, 0x12, 0x7f, 0x84, 0xf8, 0x81, 0xb4,
|
||||
0xee, 0x09, 0x91, 0x1d, 0x71, 0x44, 0xbc, 0x45, 0x6c, 0xd5, 0x39, 0x93, 0xae, 0x7d, 0x2c, 0x10,
|
||||
0xee, 0xae, 0x52, 0xd9, 0x94, 0x2a, 0x37, 0xd2, 0x2d, 0xaf, 0x29, 0x6d, 0x89, 0xe5, 0xf4, 0x11,
|
||||
0x64, 0x88, 0xb2, 0x82, 0x7e, 0xe5, 0x55, 0xe9, 0x6f, 0xa4, 0x5b, 0x5e, 0x53, 0xda, 0x8a, 0xfe,
|
||||
0x04, 0x34, 0xc4, 0xd5, 0xf1, 0x69, 0x8a, 0x02, 0xda, 0xaa, 0x77, 0x96, 0xf6, 0x1a, 0xbd, 0x0d,
|
||||
0x1b, 0x07, 0xb4, 0xf7, 0xc4, 0x3e, 0xe5, 0x91, 0xb3, 0x14, 0x05, 0xee, 0x56, 0xd5, 0x42, 0x1a,
|
||||
0xdc, 0xf2, 0x40, 0x5a, 0x40, 0xa8, 0x71, 0x00, 0x9a, 0xe3, 0x74, 0x98, 0xc1, 0x10, 0xf9, 0x29,
|
||||
0x64, 0xa3, 0xd6, 0x2a, 0x6f, 0x64, 0xf7, 0xe1, 0x2c, 0x37, 0x1f, 0xa8, 0x73, 0xd3, 0xa2, 0x96,
|
||||
0xd7, 0x50, 0xe6, 0x29, 0x64, 0x23, 0xc3, 0x07, 0xdb, 0x30, 0x8a, 0xc8, 0x77, 0xfe, 0x38, 0x0d,
|
||||
0x21, 0x43, 0x3e, 0x1c, 0x30, 0x94, 0xf9, 0x68, 0x9a, 0xe2, 0xec, 0xa2, 0x05, 0x3a, 0xb5, 0xbd,
|
||||
0xba, 0xfb, 0xe6, 0x2c, 0x37, 0x3b, 0x92, 0xe8, 0xa5, 0x50, 0xcb, 0xdb, 0x12, 0xb1, 0xcf, 0x44,
|
||||
0xe8, 0x03, 0x1e, 0xf9, 0x50, 0x04, 0x8c, 0x6f, 0x81, 0x79, 0x4b, 0x56, 0x8c, 0x69, 0x1f, 0x8d,
|
||||
0xe0, 0x04, 0x93, 0x71, 0xd6, 0x6a, 0x08, 0x99, 0xb7, 0x67, 0xb9, 0xf9, 0xf8, 0xa5, 0x32, 0x7a,
|
||||
0x82, 0xe5, 0xed, 0xce, 0x8b, 0x3d, 0xd5, 0xc2, 0x07, 0xcb, 0x3f, 0xfc, 0x6a, 0x2e, 0x58, 0xbf,
|
||||
0x2d, 0x82, 0xfb, 0x87, 0x24, 0xa1, 0x28, 0xa1, 0x63, 0x2a, 0x6f, 0xbb, 0x0b, 0x56, 0xcb, 0x81,
|
||||
0x23, 0xae, 0x3b, 0x3f, 0xce, 0xf9, 0x96, 0xfc, 0xb4, 0x40, 0xb8, 0x75, 0x7e, 0x9c, 0xcf, 0x78,
|
||||
0xe7, 0x55, 0x69, 0xc6, 0xfb, 0x60, 0x39, 0x23, 0x84, 0xa9, 0x79, 0x60, 0x69, 0xdd, 0x50, 0x4d,
|
||||
0xa0, 0x49, 0xd7, 0x7e, 0x8a, 0xb2, 0xf3, 0x08, 0x79, 0x84, 0x30, 0x77, 0x99, 0xd3, 0x78, 0x22,
|
||||
0xcb, 0xf8, 0xb1, 0x06, 0x36, 0x13, 0x34, 0x65, 0x7e, 0x39, 0x6c, 0xa9, 0x3f, 0x82, 0x74, 0x24,
|
||||
0xee, 0x7c, 0xd3, 0xfd, 0x62, 0x96, 0x9b, 0xaf, 0xcb, 0x1a, 0xdc, 0x86, 0xb2, 0xfe, 0xce, 0xcd,
|
||||
0x77, 0x87, 0x98, 0x8d, 0xc6, 0x7d, 0x2e, 0xa7, 0x3f, 0x01, 0xda, 0x32, 0xc2, 0x7d, 0xea, 0xf4,
|
||||
0x2f, 0x18, 0xa2, 0xf6, 0x31, 0x9a, 0xba, 0x7c, 0xe1, 0x19, 0x9c, 0xee, 0xf3, 0x92, 0xed, 0x18,
|
||||
0xd2, 0x91, 0x2a, 0xd3, 0x4f, 0x8b, 0xa0, 0xa9, 0x57, 0xcf, 0xe8, 0x82, 0x55, 0xd9, 0xd8, 0xe5,
|
||||
0x4c, 0x74, 0x37, 0x67, 0xb9, 0xb9, 0x21, 0x7f, 0x56, 0x19, 0xb2, 0xbc, 0xba, 0x5c, 0x9f, 0x84,
|
||||
0x06, 0x04, 0xf5, 0x11, 0x82, 0x21, 0xca, 0xfc, 0xae, 0xaa, 0xcb, 0xe3, 0xbb, 0xe6, 0xe4, 0xb1,
|
||||
0xc0, 0xbb, 0xed, 0xab, 0xdc, 0x5c, 0x91, 0xeb, 0xee, 0x2c, 0x37, 0xd7, 0xa5, 0x48, 0x41, 0x66,
|
||||
0x79, 0x2b, 0x72, 0xd9, 0xd5, 0x24, 0x7a, 0x6a, 0x3e, 0xfe, 0x07, 0x89, 0xde, 0x0b, 0x12, 0xbd,
|
||||
0x52, 0xa2, 0xa7, 0xea, 0xf1, 0xcb, 0x12, 0xb8, 0x27, 0xd1, 0x06, 0x04, 0x6b, 0x14, 0x0f, 0x13,
|
||||
0x14, 0xfa, 0x12, 0xa2, 0x5a, 0xa6, 0xad, 0xeb, 0xc8, 0x27, 0xf1, 0x4c, 0xc0, 0x94, 0xe0, 0xee,
|
||||
0x65, 0x6e, 0xd6, 0xaa, 0x29, 0x70, 0x83, 0xc2, 0xf2, 0x9a, 0x54, 0xc3, 0xf2, 0x21, 0x53, 0x9e,
|
||||
0xb1, 0x4f, 0x51, 0xd1, 0x56, 0xb7, 0x48, 0x94, 0x87, 0x77, 0x86, 0x98, 0xdb, 0xaa, 0xe8, 0x6f,
|
||||
0xa4, 0x5b, 0x5e, 0x73, 0xa2, 0xe1, 0x8c, 0x6f, 0x80, 0x7c, 0x06, 0x84, 0xbe, 0x18, 0x62, 0x4b,
|
||||
0x77, 0x0e, 0xb1, 0x47, 0x6a, 0x88, 0xbd, 0xa6, 0x3d, 0x2e, 0x65, 0xbe, 0xe5, 0xad, 0x29, 0x87,
|
||||
0x1a, 0x63, 0x11, 0x30, 0x0a, 0x44, 0xd5, 0xac, 0xea, 0x61, 0xb9, 0x6b, 0x17, 0x8f, 0x66, 0xb9,
|
||||
0xb9, 0x7d, 0x53, 0xa5, 0xe2, 0xb0, 0xbc, 0xff, 0x2b, 0x67, 0xd5, 0xb6, 0xd6, 0xc7, 0xa0, 0x5e,
|
||||
0x3c, 0xb0, 0xc6, 0x2e, 0x58, 0x4d, 0xc6, 0x31, 0xca, 0x78, 0x44, 0x9c, 0xcc, 0xb2, 0x57, 0x39,
|
||||
0x8c, 0x0e, 0x68, 0x84, 0x28, 0x21, 0x31, 0x4e, 0x44, 0x7c, 0x51, 0xc4, 0x75, 0x97, 0xfb, 0xf5,
|
||||
0xf3, 0xab, 0x76, 0xed, 0xf2, 0xaa, 0x5d, 0xfb, 0xf3, 0xaa, 0x5d, 0x7b, 0x76, 0xdd, 0x5e, 0xb8,
|
||||
0xbc, 0x6e, 0x2f, 0xfc, 0x7e, 0xdd, 0x5e, 0xf8, 0xf2, 0x48, 0xbb, 0x62, 0x01, 0xa1, 0x31, 0xa1,
|
||||
0xea, 0xdf, 0x3e, 0x0d, 0xcf, 0x9d, 0x69, 0xf5, 0x29, 0xb6, 0x5f, 0x7c, 0x8b, 0xbd, 0xf3, 0xde,
|
||||
0xfe, 0xfc, 0xc7, 0x52, 0xff, 0x9e, 0x98, 0x28, 0x4f, 0xfe, 0x09, 0x00, 0x00, 0xff, 0xff, 0x4c,
|
||||
0xb7, 0x2c, 0x8e, 0xba, 0x09, 0x00, 0x00,
|
||||
0xce, 0x39, 0x72, 0x42, 0x9e, 0x19, 0xdb, 0xd3, 0x6c, 0x97, 0x6a, 0xb9, 0xb4, 0xf3, 0xde, 0xfb,
|
||||
0xbc, 0xcf, 0x27, 0xf3, 0xe6, 0xcd, 0x1b, 0x03, 0x0b, 0x0f, 0x3d, 0x2b, 0xc4, 0xe3, 0x80, 0x79,
|
||||
0x21, 0x46, 0x31, 0xa3, 0x16, 0x43, 0xb1, 0x8f, 0xd2, 0x08, 0xc7, 0xcc, 0x9a, 0xf6, 0x15, 0xcb,
|
||||
0x4c, 0x52, 0xc2, 0x88, 0xd6, 0xc1, 0x43, 0xcf, 0x54, 0x13, 0x4c, 0x05, 0x32, 0xed, 0xef, 0x76,
|
||||
0x95, 0x7c, 0x76, 0x91, 0x20, 0x6a, 0x4d, 0x61, 0x88, 0x7d, 0xc8, 0x48, 0x2a, 0x18, 0x76, 0xf7,
|
||||
0x5e, 0x40, 0xf0, 0xbf, 0x32, 0xfa, 0xc0, 0x23, 0xf1, 0x08, 0x13, 0x2b, 0x49, 0x09, 0x19, 0x15,
|
||||
0xce, 0xce, 0x98, 0x90, 0x71, 0x88, 0x2c, 0x6e, 0x0d, 0x27, 0x23, 0xcb, 0x9f, 0xa4, 0x90, 0x61,
|
||||
0x12, 0xcb, 0xb8, 0xbe, 0x18, 0x67, 0x38, 0x42, 0x94, 0xc1, 0x28, 0x29, 0x00, 0xf9, 0x36, 0x3d,
|
||||
0x92, 0x22, 0x4b, 0xfc, 0xea, 0x7c, 0x6b, 0x62, 0x25, 0x01, 0x6f, 0x55, 0x00, 0x12, 0x45, 0x98,
|
||||
0x45, 0x05, 0xa8, 0xb4, 0x24, 0x70, 0x6b, 0x4c, 0xc6, 0x84, 0x2f, 0xad, 0x7c, 0x25, 0xbc, 0xc6,
|
||||
0x5f, 0x6b, 0xa0, 0x79, 0xc8, 0xf9, 0xce, 0x18, 0x64, 0x48, 0xdb, 0x01, 0x75, 0x2f, 0x80, 0x38,
|
||||
0x76, 0xb1, 0xdf, 0xae, 0x75, 0x6b, 0xbd, 0x86, 0xb3, 0xc6, 0xed, 0x13, 0x5f, 0x43, 0xa0, 0xc9,
|
||||
0xd2, 0x09, 0x65, 0x6e, 0x88, 0xa6, 0x28, 0x6c, 0x2f, 0x77, 0x6b, 0xbd, 0xe6, 0xa0, 0x67, 0xfe,
|
||||
0x7b, 0x59, 0xcd, 0x8f, 0x52, 0xe8, 0xe5, 0x1b, 0xb6, 0x77, 0x9f, 0x67, 0xfa, 0xd2, 0x3c, 0xd3,
|
||||
0xb5, 0x0b, 0x18, 0x85, 0x07, 0x86, 0x42, 0x65, 0x38, 0x80, 0x5b, 0x9f, 0xe4, 0x86, 0x36, 0x02,
|
||||
0x1b, 0xdc, 0xc2, 0xf1, 0xd8, 0x4d, 0x50, 0x8a, 0x89, 0xdf, 0x5e, 0xe1, 0x52, 0x3b, 0xa6, 0x28,
|
||||
0x96, 0x59, 0x14, 0xcb, 0x3c, 0x92, 0xc5, 0xb4, 0x0d, 0xc9, 0xbd, 0xad, 0x70, 0x57, 0xf9, 0xc6,
|
||||
0xcf, 0x7f, 0xe8, 0x35, 0xe7, 0x7e, 0xe1, 0x3d, 0xe5, 0x4e, 0x0d, 0x83, 0xcd, 0x49, 0x3c, 0x24,
|
||||
0xb1, 0xaf, 0x08, 0xad, 0xde, 0x25, 0xf4, 0x86, 0x14, 0x7a, 0x28, 0x84, 0x16, 0x09, 0x84, 0xd2,
|
||||
0x46, 0xe9, 0x96, 0x52, 0x08, 0x6c, 0x44, 0x70, 0xe6, 0x7a, 0x21, 0xf1, 0xce, 0x5d, 0x3f, 0xc5,
|
||||
0x23, 0xd6, 0xfe, 0xdf, 0x2b, 0x6e, 0x69, 0x21, 0x5f, 0x08, 0xad, 0x47, 0x70, 0x76, 0x98, 0x3b,
|
||||
0x8f, 0x72, 0x9f, 0xf6, 0x15, 0x58, 0x1f, 0xa5, 0xe4, 0x7b, 0x14, 0xbb, 0x01, 0xca, 0x0f, 0xa4,
|
||||
0x7d, 0x8f, 0x8b, 0xec, 0xf2, 0x23, 0xca, 0x5b, 0xc4, 0x94, 0x9d, 0x33, 0xed, 0x9b, 0xc7, 0x1c,
|
||||
0x61, 0xef, 0x49, 0x95, 0x2d, 0xa1, 0x72, 0x23, 0xdd, 0x70, 0x5a, 0xc2, 0x16, 0xd8, 0x9c, 0x3e,
|
||||
0x84, 0x0c, 0x51, 0x56, 0xd0, 0xaf, 0xbd, 0x2a, 0xfd, 0x8d, 0x74, 0xc3, 0x69, 0x09, 0x5b, 0xd2,
|
||||
0x9f, 0x80, 0x26, 0xbf, 0x3a, 0x2e, 0x4d, 0x90, 0x47, 0xdb, 0xf5, 0xee, 0x4a, 0xaf, 0x39, 0xd8,
|
||||
0x34, 0xb1, 0x47, 0x07, 0x4f, 0xcc, 0xd3, 0x3c, 0x72, 0x96, 0x20, 0xcf, 0xde, 0xae, 0x5a, 0x48,
|
||||
0x81, 0x1b, 0x0e, 0x48, 0x0a, 0x08, 0xd5, 0x0e, 0x40, 0x6b, 0x92, 0x8c, 0x53, 0xe8, 0x23, 0x37,
|
||||
0x81, 0x2c, 0x68, 0x37, 0xba, 0x2b, 0xbd, 0x86, 0xfd, 0x70, 0x9e, 0xe9, 0x0f, 0xe4, 0xb9, 0x29,
|
||||
0x51, 0xc3, 0x69, 0x4a, 0xf3, 0x14, 0xb2, 0x40, 0x73, 0xc1, 0x0e, 0x0c, 0x43, 0xf2, 0x9d, 0x3b,
|
||||
0x49, 0x7c, 0xc8, 0x90, 0x0b, 0x47, 0x0c, 0xa5, 0x2e, 0x9a, 0x25, 0x38, 0xbd, 0x68, 0x83, 0x6e,
|
||||
0xad, 0x57, 0xb7, 0xdf, 0x9c, 0x67, 0x7a, 0x57, 0x10, 0xbd, 0x14, 0x6a, 0x38, 0xdb, 0x3c, 0xf6,
|
||||
0x19, 0x0f, 0x7d, 0x90, 0x47, 0x3e, 0xe4, 0x01, 0xed, 0x5b, 0xa0, 0xdf, 0x92, 0x15, 0x61, 0x3a,
|
||||
0x44, 0x01, 0x9c, 0x62, 0x32, 0x49, 0xdb, 0x4d, 0x2e, 0xf3, 0xf6, 0x3c, 0xd3, 0x1f, 0xbf, 0x54,
|
||||
0x46, 0x4d, 0x30, 0x9c, 0xbd, 0x45, 0xb1, 0xa7, 0x4a, 0xf8, 0x60, 0xf5, 0x87, 0x5f, 0xf5, 0x25,
|
||||
0xe3, 0xb7, 0x65, 0x70, 0xff, 0x90, 0xc4, 0x14, 0xc5, 0x74, 0x42, 0xc5, 0x6d, 0xb7, 0x41, 0xa3,
|
||||
0x1c, 0x38, 0xfc, 0xba, 0xe7, 0xc7, 0xb9, 0xd8, 0x92, 0x9f, 0x16, 0x08, 0xbb, 0x9e, 0x1f, 0xe7,
|
||||
0xb3, 0xbc, 0xf3, 0xaa, 0x34, 0xed, 0x7d, 0xb0, 0x9a, 0x12, 0xc2, 0xe4, 0x3c, 0x30, 0x94, 0x6e,
|
||||
0xa8, 0x26, 0xd0, 0xb4, 0x6f, 0x3e, 0x45, 0xe9, 0x79, 0x88, 0x1c, 0x42, 0x98, 0xbd, 0x9a, 0xd3,
|
||||
0x38, 0x3c, 0x4b, 0xfb, 0xb1, 0x06, 0xb6, 0x62, 0x34, 0x63, 0x6e, 0x39, 0x6c, 0xa9, 0x1b, 0x40,
|
||||
0x1a, 0xf0, 0x3b, 0xdf, 0xb2, 0xbf, 0x98, 0x67, 0xfa, 0xeb, 0xa2, 0x06, 0xb7, 0xa1, 0x8c, 0xbf,
|
||||
0x33, 0xfd, 0xdd, 0x31, 0x66, 0xc1, 0x64, 0x98, 0xcb, 0xa9, 0x4f, 0x80, 0xb2, 0x0c, 0xf1, 0x90,
|
||||
0x5a, 0xc3, 0x0b, 0x86, 0xa8, 0x79, 0x8c, 0x66, 0x76, 0xbe, 0x70, 0xb4, 0x9c, 0xee, 0xf3, 0x92,
|
||||
0xed, 0x18, 0xd2, 0x40, 0x96, 0xe9, 0xa7, 0x65, 0xd0, 0x52, 0xab, 0xa7, 0xf5, 0x41, 0x43, 0x34,
|
||||
0x76, 0x39, 0x13, 0xed, 0xad, 0x79, 0xa6, 0x6f, 0x8a, 0x9f, 0x55, 0x86, 0x0c, 0xa7, 0x2e, 0xd6,
|
||||
0x27, 0xbe, 0x06, 0x41, 0x3d, 0x40, 0xd0, 0x47, 0xa9, 0xdb, 0x97, 0x75, 0x79, 0x7c, 0xd7, 0x9c,
|
||||
0x3c, 0xe6, 0x78, 0xbb, 0x73, 0x95, 0xe9, 0x6b, 0x62, 0xdd, 0x9f, 0x67, 0xfa, 0x86, 0x10, 0x29,
|
||||
0xc8, 0x0c, 0x67, 0x4d, 0x2c, 0xfb, 0x8a, 0xc4, 0x40, 0xce, 0xc7, 0xff, 0x20, 0x31, 0x78, 0x41,
|
||||
0x62, 0x50, 0x4a, 0x0c, 0x64, 0x3d, 0x7e, 0x59, 0x01, 0xf7, 0x04, 0x5a, 0x83, 0x60, 0x9d, 0xe2,
|
||||
0x71, 0x8c, 0x7c, 0x57, 0x40, 0x64, 0xcb, 0x74, 0x54, 0x1d, 0xf1, 0x24, 0x9e, 0x71, 0x98, 0x14,
|
||||
0xdc, 0xbb, 0xcc, 0xf4, 0x5a, 0x35, 0x05, 0x6e, 0x50, 0x18, 0x4e, 0x8b, 0x2a, 0xd8, 0x7c, 0xc8,
|
||||
0x94, 0x67, 0xec, 0x52, 0x54, 0xb4, 0xd5, 0x2d, 0x12, 0xe5, 0xe1, 0x9d, 0x21, 0x66, 0xb7, 0x2b,
|
||||
0xfa, 0x1b, 0xe9, 0x86, 0xd3, 0x9a, 0x2a, 0x38, 0xed, 0x1b, 0x20, 0x9e, 0x01, 0xae, 0xcf, 0x87,
|
||||
0xd8, 0xca, 0x9d, 0x43, 0xec, 0x91, 0x1c, 0x62, 0xaf, 0x29, 0x8f, 0x4b, 0x99, 0x6f, 0x38, 0xeb,
|
||||
0xd2, 0x21, 0xc7, 0x58, 0x08, 0xb4, 0x02, 0x51, 0x35, 0xab, 0x7c, 0x58, 0xee, 0xda, 0xc5, 0xa3,
|
||||
0x79, 0xa6, 0xef, 0xdc, 0x54, 0xa9, 0x38, 0x0c, 0xe7, 0xff, 0xd2, 0x59, 0xb5, 0xad, 0xf1, 0x31,
|
||||
0xa8, 0x17, 0x0f, 0xac, 0xb6, 0x07, 0x1a, 0xf1, 0x24, 0x42, 0x69, 0x1e, 0xe1, 0x27, 0xb3, 0xea,
|
||||
0x54, 0x0e, 0xad, 0x0b, 0x9a, 0x3e, 0x8a, 0x49, 0x84, 0x63, 0x1e, 0x5f, 0xe6, 0x71, 0xd5, 0x65,
|
||||
0x7f, 0xfd, 0xfc, 0xaa, 0x53, 0xbb, 0xbc, 0xea, 0xd4, 0xfe, 0xbc, 0xea, 0xd4, 0x9e, 0x5d, 0x77,
|
||||
0x96, 0x2e, 0xaf, 0x3b, 0x4b, 0xbf, 0x5f, 0x77, 0x96, 0xbe, 0x3c, 0x52, 0xae, 0x98, 0x47, 0x68,
|
||||
0x44, 0xa8, 0xfc, 0xb7, 0x4f, 0xfd, 0x73, 0x6b, 0x56, 0x7d, 0x8a, 0xed, 0x17, 0xdf, 0x62, 0xef,
|
||||
0xbc, 0xb7, 0xbf, 0xf8, 0xb1, 0x34, 0xbc, 0xc7, 0x27, 0xca, 0x93, 0x7f, 0x02, 0x00, 0x00, 0xff,
|
||||
0xff, 0x8f, 0xde, 0xf9, 0xa9, 0xba, 0x09, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *ClientState) Marshal() (dAtA []byte, err error) {
|
||||
@ -429,11 +433,13 @@ func (m *ClientState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
dAtA[i] = 0x50
|
||||
}
|
||||
if len(m.UpgradePath) > 0 {
|
||||
i -= len(m.UpgradePath)
|
||||
copy(dAtA[i:], m.UpgradePath)
|
||||
i = encodeVarintTendermint(dAtA, i, uint64(len(m.UpgradePath)))
|
||||
i--
|
||||
dAtA[i] = 0x4a
|
||||
for iNdEx := len(m.UpgradePath) - 1; iNdEx >= 0; iNdEx-- {
|
||||
i -= len(m.UpgradePath[iNdEx])
|
||||
copy(dAtA[i:], m.UpgradePath[iNdEx])
|
||||
i = encodeVarintTendermint(dAtA, i, uint64(len(m.UpgradePath[iNdEx])))
|
||||
i--
|
||||
dAtA[i] = 0x4a
|
||||
}
|
||||
}
|
||||
if len(m.ProofSpecs) > 0 {
|
||||
for iNdEx := len(m.ProofSpecs) - 1; iNdEx >= 0; iNdEx-- {
|
||||
@ -756,9 +762,11 @@ func (m *ClientState) Size() (n int) {
|
||||
n += 1 + l + sovTendermint(uint64(l))
|
||||
}
|
||||
}
|
||||
l = len(m.UpgradePath)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovTendermint(uint64(l))
|
||||
if len(m.UpgradePath) > 0 {
|
||||
for _, s := range m.UpgradePath {
|
||||
l = len(s)
|
||||
n += 1 + l + sovTendermint(uint64(l))
|
||||
}
|
||||
}
|
||||
if m.AllowUpdateAfterExpiry {
|
||||
n += 2
|
||||
@ -1174,7 +1182,7 @@ func (m *ClientState) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.UpgradePath = string(dAtA[iNdEx:postIndex])
|
||||
m.UpgradePath = append(m.UpgradePath, string(dAtA[iNdEx:postIndex]))
|
||||
iNdEx = postIndex
|
||||
case 10:
|
||||
if wireType != 0 {
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
package types_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -32,7 +31,7 @@ const (
|
||||
var (
|
||||
height = clienttypes.NewHeight(0, 4)
|
||||
newClientHeight = clienttypes.NewHeight(1, 1)
|
||||
upgradePath = fmt.Sprintf("%s/%s", "upgrade", "upgradedClient")
|
||||
upgradePath = []string{"upgrade", "upgradedIBCState"}
|
||||
)
|
||||
|
||||
type TendermintTestSuite struct {
|
||||
|
||||
@ -2,8 +2,6 @@ package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
@ -11,6 +9,7 @@ import (
|
||||
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
|
||||
commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc/core/exported"
|
||||
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
|
||||
)
|
||||
|
||||
// VerifyUpgradeAndUpdateState checks if the upgraded client has been committed by the current client
|
||||
@ -26,102 +25,130 @@ import (
|
||||
// and ProofSpecs do not match parameters set by committed client
|
||||
func (cs ClientState) VerifyUpgradeAndUpdateState(
|
||||
ctx sdk.Context, cdc codec.BinaryMarshaler, clientStore sdk.KVStore,
|
||||
upgradedClient exported.ClientState, upgradeHeight exported.Height, proofUpgrade []byte,
|
||||
upgradedClient exported.ClientState, upgradedConsState exported.ConsensusState,
|
||||
proofUpgradeClient, proofUpgradeConsState []byte,
|
||||
) (exported.ClientState, exported.ConsensusState, error) {
|
||||
if cs.UpgradePath == "" {
|
||||
if len(cs.UpgradePath) == 0 {
|
||||
return nil, nil, sdkerrors.Wrap(clienttypes.ErrInvalidUpgradeClient, "cannot upgrade client, no upgrade path set")
|
||||
}
|
||||
upgradePath, err := constructUpgradeMerklePath(cs.UpgradePath, upgradeHeight)
|
||||
if err != nil {
|
||||
return nil, nil, sdkerrors.Wrapf(clienttypes.ErrInvalidUpgradeClient, "cannot upgrade client, unescaping key with URL format failed: %v", err)
|
||||
}
|
||||
|
||||
// UpgradeHeight must be in same version as client state height
|
||||
if cs.GetLatestHeight().GetVersionNumber() != upgradeHeight.GetVersionNumber() {
|
||||
return nil, nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidHeight, "version at which upgrade occurs must be same as current client version. expected version %d, got %d",
|
||||
cs.GetLatestHeight().GetVersionNumber(), upgradeHeight.GetVersionNumber())
|
||||
}
|
||||
// last height of current counterparty chain must be client's latest height
|
||||
lastHeight := cs.GetLatestHeight()
|
||||
|
||||
// UpgradeHeight must be greater than or equal to current client state height
|
||||
if cs.GetLatestHeight().GetVersionHeight() > upgradeHeight.GetVersionHeight() {
|
||||
return nil, nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidHeight, "version height at which upgrade occurs must be greater than or equal to current client height (%d > %d)",
|
||||
cs.GetLatestHeight().GetVersionHeight(), upgradeHeight.GetVersionHeight(),
|
||||
)
|
||||
}
|
||||
|
||||
if !upgradedClient.GetLatestHeight().GT(cs.GetLatestHeight()) {
|
||||
return nil, nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidHeight, "upgraded client height %s must be greater than current client height %s",
|
||||
upgradedClient.GetLatestHeight(), cs.GetLatestHeight())
|
||||
}
|
||||
|
||||
if len(proofUpgrade) == 0 {
|
||||
return nil, nil, sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "proof of upgrade is empty")
|
||||
}
|
||||
|
||||
var merkleProof commitmenttypes.MerkleProof
|
||||
if err := cdc.UnmarshalBinaryBare(proofUpgrade, &merkleProof); err != nil {
|
||||
return nil, nil, sdkerrors.Wrapf(commitmenttypes.ErrInvalidProof, "could not unmarshal merkle proof: %v", err)
|
||||
if upgradedClient.GetLatestHeight().GetVersionNumber() <= lastHeight.GetVersionNumber() {
|
||||
return nil, nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidHeight, "upgraded client height %s must be at greater version than current client height %s",
|
||||
upgradedClient.GetLatestHeight(), lastHeight)
|
||||
}
|
||||
|
||||
// counterparty chain must commit the upgraded client with all client-customizable fields zeroed out
|
||||
// at the upgrade path specified by current client
|
||||
committedClient := upgradedClient.ZeroCustomFields()
|
||||
bz, err := codec.MarshalAny(cdc, committedClient)
|
||||
if err != nil {
|
||||
return nil, nil, sdkerrors.Wrapf(clienttypes.ErrInvalidClient, "could not marshal client state: %v", err)
|
||||
// counterparty must also commit to the upgraded consensus state at a sub-path under the upgrade path specified
|
||||
tmUpgradeClient, ok := upgradedClient.(*ClientState)
|
||||
if !ok {
|
||||
return nil, nil, sdkerrors.Wrapf(clienttypes.ErrInvalidClientType, "upgraded client must be Tendermint client. expected: %T got: %T",
|
||||
&ClientState{}, upgradedClient)
|
||||
}
|
||||
tmUpgradeConsState, ok := upgradedConsState.(*ConsensusState)
|
||||
if !ok {
|
||||
return nil, nil, sdkerrors.Wrapf(clienttypes.ErrInvalidConsensus, "upgraded consensus state must be Tendermint consensus state. expected %T, got: %T",
|
||||
&ConsensusState{}, upgradedConsState)
|
||||
}
|
||||
|
||||
// unmarshal proofs
|
||||
var merkleProofClient, merkleProofConsState commitmenttypes.MerkleProof
|
||||
if err := cdc.UnmarshalBinaryBare(proofUpgradeClient, &merkleProofClient); err != nil {
|
||||
return nil, nil, sdkerrors.Wrapf(commitmenttypes.ErrInvalidProof, "could not unmarshal client merkle proof: %v", err)
|
||||
}
|
||||
if err := cdc.UnmarshalBinaryBare(proofUpgradeConsState, &merkleProofConsState); err != nil {
|
||||
return nil, nil, sdkerrors.Wrapf(commitmenttypes.ErrInvalidProof, "could not unmarshal consensus state merkle proof: %v", err)
|
||||
}
|
||||
|
||||
// Must prove against latest consensus state to ensure we are verifying against latest upgrade plan
|
||||
// This verifies that upgrade is intended for the provided version, since committed client must exist
|
||||
// at this consensus state
|
||||
consState, err := GetConsensusState(clientStore, cdc, upgradeHeight)
|
||||
consState, err := GetConsensusState(clientStore, cdc, lastHeight)
|
||||
if err != nil {
|
||||
return nil, nil, sdkerrors.Wrap(err, "could not retrieve consensus state for upgradeHeight")
|
||||
return nil, nil, sdkerrors.Wrap(err, "could not retrieve consensus state for lastHeight")
|
||||
}
|
||||
|
||||
if cs.IsExpired(consState.Timestamp, ctx.BlockTime()) {
|
||||
return nil, nil, sdkerrors.Wrap(clienttypes.ErrInvalidClient, "cannot upgrade an expired client")
|
||||
}
|
||||
|
||||
tmCommittedClient, ok := committedClient.(*ClientState)
|
||||
if !ok {
|
||||
return nil, nil, sdkerrors.Wrapf(clienttypes.ErrInvalidClientType, "upgraded client must be Tendermint client. expected: %T got: %T",
|
||||
&ClientState{}, upgradedClient)
|
||||
// Verify client proof
|
||||
bz, err := codec.MarshalAny(cdc, upgradedClient)
|
||||
if err != nil {
|
||||
return nil, nil, sdkerrors.Wrapf(clienttypes.ErrInvalidClient, "could not marshal client state: %v", err)
|
||||
}
|
||||
|
||||
// Relayer chosen client parameters are ignored.
|
||||
// All chain-chosen parameters come from committed client, all client-chosen parameters
|
||||
// come from current client.
|
||||
updatedClientState := NewClientState(
|
||||
tmCommittedClient.ChainId, cs.TrustLevel, cs.TrustingPeriod, tmCommittedClient.UnbondingPeriod,
|
||||
cs.MaxClockDrift, tmCommittedClient.LatestHeight, tmCommittedClient.ProofSpecs, tmCommittedClient.UpgradePath,
|
||||
cs.AllowUpdateAfterExpiry, cs.AllowUpdateAfterMisbehaviour,
|
||||
)
|
||||
|
||||
if err := updatedClientState.Validate(); err != nil {
|
||||
return nil, nil, sdkerrors.Wrap(err, "updated client state failed basic validation")
|
||||
}
|
||||
|
||||
if err := merkleProof.VerifyMembership(cs.ProofSpecs, consState.GetRoot(), upgradePath, bz); err != nil {
|
||||
// construct clientState Merkle path
|
||||
upgradeClientPath := constructUpgradeClientMerklePath(cs.UpgradePath, lastHeight)
|
||||
if err := merkleProofClient.VerifyMembership(cs.ProofSpecs, consState.GetRoot(), upgradeClientPath, bz); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// TODO: Return valid consensus state https://github.com/cosmos/cosmos-sdk/issues/7708
|
||||
return updatedClientState, &ConsensusState{}, nil
|
||||
// Verify consensus state proof
|
||||
bz, err = codec.MarshalAny(cdc, upgradedConsState)
|
||||
if err != nil {
|
||||
return nil, nil, sdkerrors.Wrapf(clienttypes.ErrInvalidConsensus, "could not marshal consensus state: %v", err)
|
||||
}
|
||||
// construct consensus state Merkle path
|
||||
upgradeConsStatePath := constructUpgradeConsStateMerklePath(cs.UpgradePath, lastHeight)
|
||||
if err := merkleProofConsState.VerifyMembership(cs.ProofSpecs, consState.GetRoot(), upgradeConsStatePath, bz); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Construct new client state and consensus state
|
||||
// Relayer chosen client parameters are ignored.
|
||||
// All chain-chosen parameters come from committed client, all client-chosen parameters
|
||||
// come from current client.
|
||||
newClientState := NewClientState(
|
||||
tmUpgradeClient.ChainId, cs.TrustLevel, cs.TrustingPeriod, tmUpgradeClient.UnbondingPeriod,
|
||||
cs.MaxClockDrift, tmUpgradeClient.LatestHeight, tmUpgradeClient.ProofSpecs, tmUpgradeClient.UpgradePath,
|
||||
cs.AllowUpdateAfterExpiry, cs.AllowUpdateAfterMisbehaviour,
|
||||
)
|
||||
|
||||
if err := newClientState.Validate(); err != nil {
|
||||
return nil, nil, sdkerrors.Wrap(err, "updated client state failed basic validation")
|
||||
}
|
||||
|
||||
// The new consensus state is merely used as a trusted kernel against which headers on the new
|
||||
// chain can be verified. The root is empty as it cannot be known in advance, thus no proof verification will pass.
|
||||
// The timestamp and the NextValidatorsHash of the consensus state is the blocktime and NextValidatorsHash
|
||||
// of the last block committed by the old chain. This will allow the first block of the new chain to be verified against
|
||||
// the last validators of the old chain so long as it is submitted within the TrustingPeriod of this client.
|
||||
newConsState := NewConsensusState(
|
||||
tmUpgradeConsState.Timestamp, commitmenttypes.MerkleRoot{}, tmUpgradeConsState.NextValidatorsHash,
|
||||
)
|
||||
|
||||
return newClientState, newConsState, nil
|
||||
}
|
||||
|
||||
// construct MerklePath from upgradePath
|
||||
func constructUpgradeMerklePath(upgradePath string, upgradeHeight exported.Height) (commitmenttypes.MerklePath, error) {
|
||||
// assume that all keys here are separated by `/` and
|
||||
// any `/` within a merkle key is correctly escaped
|
||||
upgradeKeys := strings.Split(upgradePath, "/")
|
||||
// unescape the last key so that we can append `/{height}` to the last key
|
||||
lastKey, err := url.PathUnescape(upgradeKeys[len(upgradeKeys)-1])
|
||||
if err != nil {
|
||||
return commitmenttypes.MerklePath{}, err
|
||||
}
|
||||
// append upgradeHeight to last key in merkle path
|
||||
// construct MerklePath for the committed client from upgradePath
|
||||
func constructUpgradeClientMerklePath(upgradePath []string, lastHeight exported.Height) commitmenttypes.MerklePath {
|
||||
// copy all elements from upgradePath except final element
|
||||
clientPath := make([]string, len(upgradePath)-1)
|
||||
copy(clientPath, upgradePath)
|
||||
|
||||
// append lastHeight and `upgradedClient` to last key of upgradePath and use as lastKey of clientPath
|
||||
// this will create the IAVL key that is used to store client in upgrade store
|
||||
upgradeKeys[len(upgradeKeys)-1] = fmt.Sprintf("%s/%d", lastKey, upgradeHeight.GetVersionHeight())
|
||||
return commitmenttypes.NewMerklePath(upgradeKeys...), nil
|
||||
lastKey := upgradePath[len(upgradePath)-1]
|
||||
appendedKey := fmt.Sprintf("%s/%d/%s", lastKey, lastHeight.GetVersionHeight(), upgradetypes.KeyUpgradedClient)
|
||||
|
||||
clientPath = append(clientPath, appendedKey)
|
||||
return commitmenttypes.NewMerklePath(clientPath...)
|
||||
}
|
||||
|
||||
// construct MerklePath for the committed consensus state from upgradePath
|
||||
func constructUpgradeConsStateMerklePath(upgradePath []string, lastHeight exported.Height) commitmenttypes.MerklePath {
|
||||
// copy all elements from upgradePath except final element
|
||||
consPath := make([]string, len(upgradePath)-1)
|
||||
copy(consPath, upgradePath)
|
||||
|
||||
// append lastHeight and `upgradedClient` to last key of upgradePath and use as lastKey of clientPath
|
||||
// this will create the IAVL key that is used to store client in upgrade store
|
||||
lastKey := upgradePath[len(upgradePath)-1]
|
||||
appendedKey := fmt.Sprintf("%s/%d/%s", lastKey, lastHeight.GetVersionHeight(), upgradetypes.KeyUpgradedConsState)
|
||||
|
||||
consPath = append(consPath, appendedKey)
|
||||
return commitmenttypes.NewMerklePath(consPath...)
|
||||
}
|
||||
|
||||
@ -10,10 +10,11 @@ import (
|
||||
|
||||
func (suite *TendermintTestSuite) TestVerifyUpgrade() {
|
||||
var (
|
||||
upgradedClient exported.ClientState
|
||||
upgradeHeight clienttypes.Height
|
||||
clientA string
|
||||
proofUpgrade []byte
|
||||
upgradedClient exported.ClientState
|
||||
upgradedConsState exported.ConsensusState
|
||||
lastHeight clienttypes.Height
|
||||
clientA string
|
||||
proofUpgradedClient, proofUpgradedConsState []byte
|
||||
)
|
||||
|
||||
testCases := []struct {
|
||||
@ -26,12 +27,16 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
|
||||
setup: func() {
|
||||
|
||||
upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
|
||||
upgradedConsState = &types.ConsensusState{
|
||||
NextValidatorsHash: []byte("nextValsHash"),
|
||||
}
|
||||
|
||||
// upgrade Height is at next block
|
||||
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
|
||||
// zero custom fields and store in upgrade store
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedConsState)
|
||||
|
||||
// commit upgrade store changes and update clients
|
||||
|
||||
@ -42,52 +47,26 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
proofUpgrade, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
},
|
||||
expPass: true,
|
||||
},
|
||||
{
|
||||
name: "successful upgrade with different client chosen parameters set in upgraded client",
|
||||
name: "unsuccessful upgrade: upgrade height version height is more than the current client version height",
|
||||
setup: func() {
|
||||
|
||||
upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
|
||||
upgradedConsState = &types.ConsensusState{
|
||||
NextValidatorsHash: []byte("nextValsHash"),
|
||||
}
|
||||
|
||||
// upgrade Height is at next block
|
||||
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
// upgrade Height is 10 blocks from now
|
||||
lastHeight = clienttypes.NewHeight(10, uint64(suite.chainB.GetContext().BlockHeight()+10))
|
||||
|
||||
// zero custom fields and store in upgrade store
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
|
||||
|
||||
// change upgradedClient client-specified parameters
|
||||
upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, ubdPeriod, ubdPeriod+trustingPeriod, maxClockDrift+5, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, true, false)
|
||||
|
||||
suite.coordinator.CommitBlock(suite.chainB)
|
||||
err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
// Previous client-chosen parameters must be the same as upgraded client chosen parameters
|
||||
tmClient, _ := cs.(*types.ClientState)
|
||||
oldClient := types.NewClientState(tmClient.ChainId, types.DefaultTrustLevel, ubdPeriod, ubdPeriod+trustingPeriod, maxClockDrift+5, tmClient.LatestHeight, commitmenttypes.GetSDKSpecs(), upgradePath, true, false)
|
||||
suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), clientA, oldClient)
|
||||
|
||||
proofUpgrade, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
},
|
||||
expPass: true,
|
||||
},
|
||||
{
|
||||
name: "unsuccessful upgrade: upgrade height version does not match current client version",
|
||||
setup: func() {
|
||||
|
||||
upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
|
||||
|
||||
// upgrade Height is at next block
|
||||
upgradeHeight = clienttypes.NewHeight(10, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
|
||||
// zero custom fields and store in upgrade store
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedConsState)
|
||||
|
||||
// commit upgrade store changes and update clients
|
||||
|
||||
@ -98,47 +77,26 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
proofUpgrade, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "unsuccessful upgrade: upgrade height version height is less than the current client version height",
|
||||
setup: func() {
|
||||
|
||||
upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
|
||||
|
||||
// upgrade Height is at next block
|
||||
upgradeHeight = clienttypes.NewHeight(10, uint64(suite.chainB.GetContext().BlockHeight()-1))
|
||||
|
||||
// zero custom fields and store in upgrade store
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
|
||||
|
||||
// commit upgrade store changes and update clients
|
||||
|
||||
suite.coordinator.CommitBlock(suite.chainB)
|
||||
err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
proofUpgrade, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
|
||||
{
|
||||
name: "unsuccessful upgrade: chain-specified parameters do not match committed client",
|
||||
setup: func() {
|
||||
|
||||
upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
|
||||
upgradedConsState = &types.ConsensusState{
|
||||
NextValidatorsHash: []byte("nextValsHash"),
|
||||
}
|
||||
|
||||
// upgrade Height is at next block
|
||||
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
|
||||
// zero custom fields and store in upgrade store
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedConsState)
|
||||
|
||||
// change upgradedClient client-specified parameters
|
||||
upgradedClient = types.NewClientState("wrongchainID", types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, true, true)
|
||||
@ -150,7 +108,8 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
proofUpgrade, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
@ -158,12 +117,17 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
|
||||
name: "unsuccessful upgrade: client-specified parameters do not match previous client",
|
||||
setup: func() {
|
||||
|
||||
upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, upgradeHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
|
||||
upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, lastHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
|
||||
upgradedConsState = &types.ConsensusState{
|
||||
NextValidatorsHash: []byte("nextValsHash"),
|
||||
}
|
||||
|
||||
// zero custom fields and store in upgrade store
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedConsState)
|
||||
|
||||
// change upgradedClient client-specified parameters
|
||||
upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, ubdPeriod, ubdPeriod+trustingPeriod, maxClockDrift+5, upgradeHeight, commitmenttypes.GetSDKSpecs(), upgradePath, true, false)
|
||||
upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, ubdPeriod, ubdPeriod+trustingPeriod, maxClockDrift+5, lastHeight, commitmenttypes.GetSDKSpecs(), upgradePath, true, false)
|
||||
|
||||
suite.coordinator.CommitBlock(suite.chainB)
|
||||
err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint)
|
||||
@ -172,39 +136,124 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
proofUpgrade, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "unsuccessful upgrade: proof is empty",
|
||||
name: "unsuccessful upgrade: relayer-submitted consensus state does not match counterparty-committed consensus state",
|
||||
setup: func() {
|
||||
|
||||
upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
|
||||
proofUpgrade = []byte{}
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "unsuccessful upgrade: proof unmarshal failed",
|
||||
setup: func() {
|
||||
upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
|
||||
proofUpgrade = []byte("proof")
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "unsuccessful upgrade: proof verification failed",
|
||||
setup: func() {
|
||||
// create but do not store upgraded client
|
||||
upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
|
||||
upgradedConsState = &types.ConsensusState{
|
||||
NextValidatorsHash: []byte("nextValsHash"),
|
||||
}
|
||||
|
||||
// upgrade Height is at next block
|
||||
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
|
||||
// zero custom fields and store in upgrade store
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedConsState)
|
||||
|
||||
// change submitted upgradedConsensusState
|
||||
upgradedConsState = &types.ConsensusState{
|
||||
NextValidatorsHash: []byte("maliciousValidators"),
|
||||
}
|
||||
|
||||
// commit upgrade store changes and update clients
|
||||
|
||||
suite.coordinator.CommitBlock(suite.chainB)
|
||||
err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
proofUpgrade, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "unsuccessful upgrade: client proof unmarshal failed",
|
||||
setup: func() {
|
||||
upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
|
||||
upgradedConsState = &types.ConsensusState{
|
||||
NextValidatorsHash: []byte("nextValsHash"),
|
||||
}
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedConsState)
|
||||
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
|
||||
proofUpgradedClient = []byte("proof")
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "unsuccessful upgrade: consensus state proof unmarshal failed",
|
||||
setup: func() {
|
||||
upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
|
||||
upgradedConsState = &types.ConsensusState{
|
||||
NextValidatorsHash: []byte("nextValsHash"),
|
||||
}
|
||||
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedClient)
|
||||
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
|
||||
proofUpgradedConsState = []byte("proof")
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "unsuccessful upgrade: client proof verification failed",
|
||||
setup: func() {
|
||||
// create but do not store upgraded client
|
||||
upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
|
||||
upgradedConsState = &types.ConsensusState{
|
||||
NextValidatorsHash: []byte("nextValsHash"),
|
||||
}
|
||||
|
||||
// upgrade Height is at next block
|
||||
lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedConsState)
|
||||
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "unsuccessful upgrade: consensus state proof verification failed",
|
||||
setup: func() {
|
||||
// create but do not store upgraded client
|
||||
upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
|
||||
upgradedConsState = &types.ConsensusState{
|
||||
NextValidatorsHash: []byte("nextValsHash"),
|
||||
}
|
||||
|
||||
// upgrade Height is at next block
|
||||
lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedClient)
|
||||
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
@ -213,12 +262,15 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
|
||||
setup: func() {
|
||||
|
||||
upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
|
||||
upgradedConsState = &types.ConsensusState{
|
||||
NextValidatorsHash: []byte("nextValsHash"),
|
||||
}
|
||||
|
||||
// upgrade Height is at next block
|
||||
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
|
||||
// zero custom fields and store in upgrade store
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedClient)
|
||||
|
||||
// commit upgrade store changes and update clients
|
||||
|
||||
@ -229,41 +281,12 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
proofUpgrade, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
|
||||
// SetClientState with empty upgrade path
|
||||
tmClient, _ := cs.(*types.ClientState)
|
||||
tmClient.UpgradePath = ""
|
||||
suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), clientA, tmClient)
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "unsuccessful upgrade: upgrade path is malformed and cannot be correctly unescaped",
|
||||
setup: func() {
|
||||
|
||||
upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
|
||||
|
||||
// upgrade Height is at next block
|
||||
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
|
||||
// zero custom fields and store in upgrade store
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
|
||||
|
||||
// commit upgrade store changes and update clients
|
||||
|
||||
suite.coordinator.CommitBlock(suite.chainB)
|
||||
err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
proofUpgrade, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
|
||||
// SetClientState with nil upgrade path
|
||||
tmClient, _ := cs.(*types.ClientState)
|
||||
tmClient.UpgradePath = "upgraded%Client"
|
||||
tmClient.UpgradePath = []string{""}
|
||||
suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), clientA, tmClient)
|
||||
},
|
||||
expPass: false,
|
||||
@ -273,12 +296,15 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
|
||||
setup: func() {
|
||||
|
||||
upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
|
||||
upgradedConsState = &types.ConsensusState{
|
||||
NextValidatorsHash: []byte("nextValsHash"),
|
||||
}
|
||||
|
||||
// upgrade Height is at next block
|
||||
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
|
||||
// zero custom fields and store in upgrade store
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedClient)
|
||||
|
||||
// commit upgrade store changes and update clients
|
||||
|
||||
@ -289,7 +315,8 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
proofUpgrade, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
@ -298,12 +325,15 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
|
||||
setup: func() {
|
||||
|
||||
upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
|
||||
upgradedConsState = &types.ConsensusState{
|
||||
NextValidatorsHash: []byte("nextValsHash"),
|
||||
}
|
||||
|
||||
// upgrade Height is at next block
|
||||
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+100))
|
||||
lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+100))
|
||||
|
||||
// zero custom fields and store in upgrade store
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedClient)
|
||||
|
||||
// commit upgrade store changes and update clients
|
||||
|
||||
@ -314,7 +344,8 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
proofUpgrade, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
@ -322,9 +353,13 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
|
||||
name: "unsuccessful upgrade: client is expired",
|
||||
setup: func() {
|
||||
|
||||
upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, upgradeHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
|
||||
upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, lastHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
|
||||
upgradedConsState = &types.ConsensusState{
|
||||
NextValidatorsHash: []byte("nextValsHash"),
|
||||
}
|
||||
|
||||
// zero custom fields and store in upgrade store
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedClient)
|
||||
|
||||
// commit upgrade store changes and update clients
|
||||
|
||||
@ -338,7 +373,8 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
proofUpgrade, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
@ -347,12 +383,15 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
|
||||
setup: func() {
|
||||
|
||||
upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
|
||||
upgradedConsState = &types.ConsensusState{
|
||||
NextValidatorsHash: []byte("nextValsHash"),
|
||||
}
|
||||
|
||||
// upgrade Height is at next block
|
||||
upgradeHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
|
||||
// zero custom fields and store in upgrade store
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(upgradeHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedClient)
|
||||
|
||||
// commit upgrade store changes and update clients
|
||||
|
||||
@ -363,7 +402,39 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
proofUpgrade, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(upgradeHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "unsuccessful upgrade: final client is not valid",
|
||||
setup: func() {
|
||||
|
||||
// new client has smaller unbonding period such that old trusting period is no longer valid
|
||||
upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false)
|
||||
upgradedConsState = &types.ConsensusState{
|
||||
NextValidatorsHash: []byte("nextValsHash"),
|
||||
}
|
||||
|
||||
// upgrade Height is at next block
|
||||
lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1))
|
||||
|
||||
// zero custom fields and store in upgrade store
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedClient)
|
||||
suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetVersionHeight()), upgradedConsState)
|
||||
|
||||
// commit upgrade store changes and update clients
|
||||
|
||||
suite.coordinator.CommitBlock(suite.chainB)
|
||||
err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA)
|
||||
suite.Require().True(found)
|
||||
|
||||
proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetVersionHeight())), cs.GetLatestHeight().GetVersionHeight())
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
@ -382,13 +453,17 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() {
|
||||
cs := suite.chainA.GetClientState(clientA)
|
||||
clientStore := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA)
|
||||
|
||||
// Call ZeroCustomFields on upgraded clients to clear any client-chosen parameters in test-case upgradedClient
|
||||
upgradedClient = upgradedClient.ZeroCustomFields()
|
||||
|
||||
clientState, consensusState, err := cs.VerifyUpgradeAndUpdateState(
|
||||
suite.chainA.GetContext(),
|
||||
suite.cdc,
|
||||
clientStore,
|
||||
upgradedClient,
|
||||
upgradeHeight,
|
||||
proofUpgrade,
|
||||
upgradedConsState,
|
||||
proofUpgradedClient,
|
||||
proofUpgradedConsState,
|
||||
)
|
||||
|
||||
if tc.expPass {
|
||||
|
||||
@ -105,7 +105,7 @@ func (cs ClientState) CheckProposedHeaderAndUpdateState(
|
||||
// VerifyUpgradeAndUpdateState returns an error since localhost cannot be upgraded
|
||||
func (cs ClientState) VerifyUpgradeAndUpdateState(
|
||||
_ sdk.Context, _ codec.BinaryMarshaler, _ sdk.KVStore,
|
||||
_ exported.ClientState, _ exported.Height, _ []byte,
|
||||
_ exported.ClientState, _ exported.ConsensusState, _, _ []byte,
|
||||
) (exported.ClientState, exported.ConsensusState, error) {
|
||||
return nil, nil, sdkerrors.Wrap(clienttypes.ErrInvalidUpgradeClient, "cannot upgrade localhost client")
|
||||
}
|
||||
|
||||
@ -67,7 +67,7 @@ var (
|
||||
TestHash = tmhash.Sum([]byte("TESTING HASH"))
|
||||
TestCoin = sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100))
|
||||
|
||||
UpgradePath = fmt.Sprintf("%s/%s", "upgrade", "upgradedClient")
|
||||
UpgradePath = []string{"upgrade", "upgradedIBCState"}
|
||||
|
||||
ConnectionVersion = connectiontypes.ExportedVersionsToProto(connectiontypes.GetCompatibleVersions())[0]
|
||||
|
||||
|
||||
@ -10,6 +10,8 @@ import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/upgrade/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/upgrade/types"
|
||||
|
||||
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types"
|
||||
)
|
||||
|
||||
// BeginBlock will check if there is a scheduled plan and if it is ready to be executed.
|
||||
@ -28,6 +30,19 @@ func BeginBlocker(k keeper.Keeper, ctx sdk.Context, _ abci.RequestBeginBlock) {
|
||||
return
|
||||
}
|
||||
|
||||
// Once we are at the last block this chain will commit, set the upgraded consensus state
|
||||
// so that IBC clients can use the last NextValidatorsHash as a trusted kernel for verifying
|
||||
// headers on the next version of the chain.
|
||||
// Set the time to the last block time of the current chain.
|
||||
// In order for a client to upgrade successfully, the first block of the new chain must be committed
|
||||
// within the trusting period of the last block time on this chain.
|
||||
if plan.IsIBCPlan() && ctx.BlockHeight() == plan.Height-1 {
|
||||
upgradedConsState := &ibctmtypes.ConsensusState{
|
||||
Timestamp: ctx.BlockTime(),
|
||||
NextValidatorsHash: ctx.BlockHeader().NextValidatorsHash,
|
||||
}
|
||||
k.SetUpgradedConsensusState(ctx, ctx.BlockHeight(), upgradedConsState)
|
||||
}
|
||||
// To make sure clear upgrade is executed at the same block
|
||||
if plan.ShouldExecute(ctx) {
|
||||
// If skip upgrade has been set for current height, we clear the upgrade plan
|
||||
|
||||
@ -120,6 +120,58 @@ func TestCanOverwriteScheduleUpgrade(t *testing.T) {
|
||||
VerifyDoUpgrade(t)
|
||||
}
|
||||
|
||||
func VerifyDoIBCLastBlock(t *testing.T) {
|
||||
t.Log("Verify that chain committed to consensus state on the last height it will commit")
|
||||
nextValsHash := []byte("nextValsHash")
|
||||
newCtx := s.ctx.WithBlockHeader(tmproto.Header{
|
||||
Height: s.ctx.BlockHeight(),
|
||||
NextValidatorsHash: nextValsHash,
|
||||
})
|
||||
|
||||
req := abci.RequestBeginBlock{Header: newCtx.BlockHeader()}
|
||||
s.module.BeginBlock(newCtx, req)
|
||||
|
||||
consState, err := s.keeper.GetUpgradedConsensusState(newCtx, s.ctx.BlockHeight())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, &ibctmtypes.ConsensusState{Timestamp: newCtx.BlockTime(), NextValidatorsHash: nextValsHash}, consState)
|
||||
}
|
||||
|
||||
func VerifyDoIBCUpgrade(t *testing.T) {
|
||||
t.Log("Verify that a panic happens at the upgrade time/height")
|
||||
newCtx := s.ctx.WithBlockHeight(s.ctx.BlockHeight() + 1).WithBlockTime(time.Now())
|
||||
|
||||
// Check IBC state is set before upgrade using last height: s.ctx.BlockHeight()
|
||||
cs, err := s.keeper.GetUpgradedClient(newCtx, s.ctx.BlockHeight())
|
||||
require.NoError(t, err, "could not retrieve upgraded client before upgrade plan is applied")
|
||||
require.NotNil(t, cs, "IBC client is nil before upgrade")
|
||||
|
||||
consState, err := s.keeper.GetUpgradedConsensusState(newCtx, s.ctx.BlockHeight())
|
||||
require.NoError(t, err, "could not retrieve upgraded consensus state before upgrade plan is applied")
|
||||
require.NotNil(t, consState, "IBC consensus state is nil before upgrade")
|
||||
|
||||
req := abci.RequestBeginBlock{Header: newCtx.BlockHeader()}
|
||||
require.Panics(t, func() {
|
||||
s.module.BeginBlock(newCtx, req)
|
||||
})
|
||||
|
||||
t.Log("Verify that the upgrade can be successfully applied with a handler")
|
||||
s.keeper.SetUpgradeHandler("test", func(ctx sdk.Context, plan types.Plan) {})
|
||||
require.NotPanics(t, func() {
|
||||
s.module.BeginBlock(newCtx, req)
|
||||
})
|
||||
|
||||
VerifyCleared(t, newCtx)
|
||||
|
||||
// Check IBC state is cleared after upgrade using last height: s.ctx.BlockHeight()
|
||||
cs, err = s.keeper.GetUpgradedClient(newCtx, s.ctx.BlockHeight())
|
||||
require.Error(t, err, "retrieved upgraded client after upgrade plan is applied")
|
||||
require.Nil(t, cs, "IBC client is not-nil after upgrade")
|
||||
|
||||
consState, err = s.keeper.GetUpgradedConsensusState(newCtx, s.ctx.BlockHeight())
|
||||
require.Error(t, err, "retrieved upgraded consensus state after upgrade plan is applied")
|
||||
require.Nil(t, consState, "IBC consensus state is not-nil after upgrade")
|
||||
}
|
||||
|
||||
func VerifyDoUpgrade(t *testing.T) {
|
||||
t.Log("Verify that a panic happens at the upgrade time/height")
|
||||
newCtx := s.ctx.WithBlockHeight(s.ctx.BlockHeight() + 1).WithBlockTime(time.Now())
|
||||
@ -414,6 +466,27 @@ func TestUpgradeWithoutSkip(t *testing.T) {
|
||||
VerifyDone(t, s.ctx, "test")
|
||||
}
|
||||
|
||||
func TestIBCUpgradeWithoutSkip(t *testing.T) {
|
||||
s := setupTest(10, map[int64]bool{})
|
||||
cs, err := clienttypes.PackClientState(&ibctmtypes.ClientState{})
|
||||
require.NoError(t, err)
|
||||
err = s.handler(s.ctx, &types.SoftwareUpgradeProposal{
|
||||
Title: "prop",
|
||||
Plan: types.Plan{
|
||||
Name: "test",
|
||||
Height: s.ctx.BlockHeight() + 1,
|
||||
UpgradedClientState: cs,
|
||||
},
|
||||
})
|
||||
require.Nil(t, err)
|
||||
|
||||
t.Log("Verify if last height stores consensus state")
|
||||
VerifyDoIBCLastBlock(t)
|
||||
|
||||
VerifyDoUpgrade(t)
|
||||
VerifyDone(t, s.ctx, "test")
|
||||
}
|
||||
|
||||
func TestDumpUpgradeInfoToFile(t *testing.T) {
|
||||
s := setupTest(10, map[int64]bool{})
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/upgrade/types"
|
||||
)
|
||||
|
||||
@ -32,3 +33,22 @@ func (k Keeper) AppliedPlan(c context.Context, req *types.QueryAppliedPlanReques
|
||||
|
||||
return &types.QueryAppliedPlanResponse{Height: applied}, nil
|
||||
}
|
||||
|
||||
// UpgradedConsensusState implements the Query/UpgradedConsensusState gRPC method
|
||||
func (k Keeper) UpgradedConsensusState(c context.Context, req *types.QueryUpgradedConsensusStateRequest) (*types.QueryUpgradedConsensusStateResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(c)
|
||||
|
||||
consState, err := k.GetUpgradedConsensusState(ctx, req.LastHeight)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cs, err := clienttypes.PackConsensusState(consState)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &types.QueryUpgradedConsensusStateResponse{
|
||||
UpgradedConsensusState: cs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -8,8 +8,6 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
tmos "github.com/tendermint/tendermint/libs/os"
|
||||
@ -76,39 +74,33 @@ func (k Keeper) ScheduleUpgrade(ctx sdk.Context, plan types.Plan) error {
|
||||
}
|
||||
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
|
||||
// clear any old IBC state stored by previous plan
|
||||
oldPlan, exists := k.GetUpgradePlan(ctx)
|
||||
if exists && oldPlan.IsIBCPlan() {
|
||||
k.ClearIBCState(ctx, oldPlan.Height-1)
|
||||
}
|
||||
|
||||
bz := k.cdc.MustMarshalBinaryBare(&plan)
|
||||
store.Set(types.PlanKey(), bz)
|
||||
|
||||
if plan.UpgradedClientState == nil {
|
||||
// if latest UpgradedClientState is nil, but upgraded client exists in store,
|
||||
// then delete client state from store.
|
||||
_, height, _ := k.GetUpgradedClient(ctx)
|
||||
if height != 0 {
|
||||
store.Delete(types.UpgradedClientKey(height))
|
||||
if plan.IsIBCPlan() {
|
||||
// Set UpgradedClientState in store
|
||||
clientState, err := clienttypes.UnpackClientState(plan.UpgradedClientState)
|
||||
if err != nil {
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "could not unpack clientstate: %v", err)
|
||||
}
|
||||
return nil
|
||||
// sets the new upgraded client in last height committed on this chain is at plan.Height - 1,
|
||||
// since the chain will panic at plan.Height and new chain will resume at plan.Height
|
||||
return k.SetUpgradedClient(ctx, plan.Height-1, clientState)
|
||||
}
|
||||
|
||||
// Set UpgradedClientState in store
|
||||
clientState, err := clienttypes.UnpackClientState(plan.UpgradedClientState)
|
||||
if err != nil {
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "could not unpack clientstate: %v", err)
|
||||
}
|
||||
// deletes any previously stored upgraded client and sets the new upgraded client in
|
||||
return k.SetUpgradedClient(ctx, plan.Height, clientState)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetUpgradedClient sets the expected upgraded client for the next version of this chain
|
||||
func (k Keeper) SetUpgradedClient(ctx sdk.Context, upgradeHeight int64, cs ibcexported.ClientState) error {
|
||||
// SetUpgradedClient sets the expected upgraded client for the next version of this chain at the last height the current chain will commit.
|
||||
func (k Keeper) SetUpgradedClient(ctx sdk.Context, lastHeight int64, cs ibcexported.ClientState) error {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
|
||||
// delete any previously stored upgraded client before setting a new one
|
||||
// since there should only ever be one upgraded client in the store at any given time
|
||||
_, setHeight, _ := k.GetUpgradedClient(ctx)
|
||||
if setHeight != 0 {
|
||||
store.Delete(types.UpgradedClientKey(setHeight))
|
||||
}
|
||||
|
||||
// zero out any custom fields before setting
|
||||
cs = cs.ZeroCustomFields()
|
||||
bz, err := clienttypes.MarshalClientState(k.cdc, cs)
|
||||
@ -116,49 +108,52 @@ func (k Keeper) SetUpgradedClient(ctx sdk.Context, upgradeHeight int64, cs ibcex
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "could not marshal clientstate: %v", err)
|
||||
}
|
||||
|
||||
store.Set(types.UpgradedClientKey(upgradeHeight), bz)
|
||||
store.Set(types.UpgradedClientKey(lastHeight), bz)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetUpgradedClient gets the expected upgraded client for the next version of this chain
|
||||
// along with the planned upgrade height
|
||||
// Since there is only ever one upgraded client in store, we do not need to know key beforehand
|
||||
func (k Keeper) GetUpgradedClient(ctx sdk.Context) (ibcexported.ClientState, int64, error) {
|
||||
func (k Keeper) GetUpgradedClient(ctx sdk.Context, height int64) (ibcexported.ClientState, error) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
iterator := sdk.KVStorePrefixIterator(store, []byte(types.KeyUpgradedClient))
|
||||
var (
|
||||
count, height int
|
||||
bz []byte
|
||||
)
|
||||
|
||||
defer iterator.Close()
|
||||
for ; iterator.Valid(); iterator.Next() {
|
||||
count++
|
||||
// we must panic if the upgraded clients in store is ever more than one since
|
||||
// that would break upgrade functionality and chain must halt and fix issue manually
|
||||
if count > 1 {
|
||||
panic("more than 1 upgrade client stored in state")
|
||||
}
|
||||
|
||||
keySplit := strings.Split(string(iterator.Key()), "/")
|
||||
var err error
|
||||
height, err = strconv.Atoi(keySplit[len(keySplit)-1])
|
||||
if err != nil {
|
||||
return nil, 0, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "could not parse upgrade height from key: %s", err)
|
||||
}
|
||||
|
||||
bz = iterator.Value()
|
||||
}
|
||||
|
||||
if count == 0 {
|
||||
return nil, 0, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "upgrade client not found in store")
|
||||
bz := store.Get(types.UpgradedClientKey(height))
|
||||
if len(bz) == 0 {
|
||||
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "upgraded client not found in store for height %d", height)
|
||||
}
|
||||
|
||||
clientState, err := clienttypes.UnmarshalClientState(k.cdc, bz)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
return nil, err
|
||||
}
|
||||
return clientState, int64(height), nil
|
||||
return clientState, nil
|
||||
}
|
||||
|
||||
// SetUpgradedConsensusState set the expected upgraded consensus state for the next version of this chain
|
||||
// using the last height committed on this chain.
|
||||
func (k Keeper) SetUpgradedConsensusState(ctx sdk.Context, lastHeight int64, cs ibcexported.ConsensusState) error {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
bz, err := clienttypes.MarshalConsensusState(k.cdc, cs)
|
||||
if err != nil {
|
||||
return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "could not marshal consensus state: %v", err)
|
||||
}
|
||||
|
||||
store.Set(types.UpgradedConsStateKey(lastHeight), bz)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetUpgradedConsensusState set the expected upgraded consensus state for the next version of this chain
|
||||
func (k Keeper) GetUpgradedConsensusState(ctx sdk.Context, lastHeight int64) (ibcexported.ConsensusState, error) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
|
||||
bz := store.Get(types.UpgradedConsStateKey(lastHeight))
|
||||
if len(bz) == 0 {
|
||||
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "upgraded consensus state not found in store for height: %d", lastHeight)
|
||||
}
|
||||
consState, err := clienttypes.UnmarshalConsensusState(k.cdc, bz)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return consState, nil
|
||||
}
|
||||
|
||||
// GetDoneHeight returns the height at which the given upgrade was executed
|
||||
@ -172,6 +167,14 @@ func (k Keeper) GetDoneHeight(ctx sdk.Context, name string) int64 {
|
||||
return int64(binary.BigEndian.Uint64(bz))
|
||||
}
|
||||
|
||||
// ClearIBCState clears any planned IBC state
|
||||
func (k Keeper) ClearIBCState(ctx sdk.Context, lastHeight int64) {
|
||||
// delete IBC client and consensus state from store if this is IBC plan
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
store.Delete(types.UpgradedClientKey(lastHeight))
|
||||
store.Delete(types.UpgradedConsStateKey(lastHeight))
|
||||
}
|
||||
|
||||
// ClearUpgradePlan clears any schedule upgrade
|
||||
func (k Keeper) ClearUpgradePlan(ctx sdk.Context) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
@ -219,6 +222,11 @@ func (k Keeper) ApplyUpgrade(ctx sdk.Context, plan types.Plan) {
|
||||
|
||||
handler(ctx, plan)
|
||||
|
||||
// Must clear IBC state after upgrade is applied as it is stored separately from the upgrade plan.
|
||||
// This will prevent resubmission of upgrade msg after upgrade is already completed.
|
||||
if plan.IsIBCPlan() {
|
||||
k.ClearIBCState(ctx, plan.Height-1)
|
||||
}
|
||||
k.ClearUpgradePlan(ctx)
|
||||
k.setDone(ctx, plan.Name)
|
||||
}
|
||||
|
||||
@ -235,13 +235,12 @@ func (s *KeeperTestSuite) TestScheduleUpgrade() {
|
||||
if tc.expPass {
|
||||
s.Require().NoError(err, "valid test case failed")
|
||||
if tc.plan.UpgradedClientState != nil {
|
||||
got, height, err := s.app.UpgradeKeeper.GetUpgradedClient(s.ctx)
|
||||
got, err := s.app.UpgradeKeeper.GetUpgradedClient(s.ctx, tc.plan.Height-1)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(tc.plan.Height, height, "upgradedClient not stored at correct upgrade height")
|
||||
s.Require().Equal(clientState, got, "upgradedClient not equal to expected value")
|
||||
} else {
|
||||
// check that upgraded client is empty if latest plan does not specify an upgraded client
|
||||
got, _, err := s.app.UpgradeKeeper.GetUpgradedClient(s.ctx)
|
||||
got, err := s.app.UpgradeKeeper.GetUpgradedClient(s.ctx, tc.plan.Height-1)
|
||||
s.Require().Error(err)
|
||||
s.Require().Nil(got)
|
||||
}
|
||||
@ -255,36 +254,24 @@ func (s *KeeperTestSuite) TestScheduleUpgrade() {
|
||||
func (s *KeeperTestSuite) TestSetUpgradedClient() {
|
||||
var (
|
||||
clientState ibcexported.ClientState
|
||||
height int64
|
||||
)
|
||||
cases := []struct {
|
||||
name string
|
||||
height int64
|
||||
setup func()
|
||||
exists bool
|
||||
}{
|
||||
{
|
||||
name: "no upgraded client exists",
|
||||
height: 10,
|
||||
setup: func() {},
|
||||
exists: false,
|
||||
},
|
||||
{
|
||||
name: "success",
|
||||
name: "success",
|
||||
height: 10,
|
||||
setup: func() {
|
||||
clientState = &ibctmtypes.ClientState{ChainId: "gaiachain"}
|
||||
height = 10
|
||||
|
||||
s.app.UpgradeKeeper.SetUpgradedClient(s.ctx, 10, clientState)
|
||||
},
|
||||
exists: true,
|
||||
},
|
||||
{
|
||||
name: "successful overwrite",
|
||||
setup: func() {
|
||||
clientState = &ibctmtypes.ClientState{ChainId: "gaiachain"}
|
||||
altCs := &ibctmtypes.ClientState{ChainId: "ethermint"}
|
||||
height = 10
|
||||
|
||||
s.app.UpgradeKeeper.SetUpgradedClient(s.ctx, 50, altCs)
|
||||
s.app.UpgradeKeeper.SetUpgradedClient(s.ctx, 10, clientState)
|
||||
},
|
||||
exists: true,
|
||||
@ -298,14 +285,12 @@ func (s *KeeperTestSuite) TestSetUpgradedClient() {
|
||||
// setup test case
|
||||
tc.setup()
|
||||
|
||||
gotCs, gotHeight, err := s.app.UpgradeKeeper.GetUpgradedClient(s.ctx)
|
||||
gotCs, err := s.app.UpgradeKeeper.GetUpgradedClient(s.ctx, tc.height)
|
||||
if tc.exists {
|
||||
s.Require().Equal(clientState, gotCs, "valid case: %s did not retrieve correct client state", tc.name)
|
||||
s.Require().Equal(height, gotHeight, "valid case: %s did not retrieve correct upgrade height", tc.name)
|
||||
s.Require().NoError(err, "valid case: %s returned error")
|
||||
} else {
|
||||
s.Require().Nil(gotCs, "invalid case: %s retrieved valid client state", tc.name)
|
||||
s.Require().Equal(int64(0), gotHeight, "invalid case: %s retrieved valid upgrade height", tc.name)
|
||||
s.Require().Error(err, "invalid case: %s did not return error", tc.name)
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,8 +22,14 @@ const (
|
||||
// DoneByte is a prefix for to look up completed upgrade plan by name
|
||||
DoneByte = 0x1
|
||||
|
||||
// KeyUpgradedClient is the key under which upgraded client is stored in the upgrade store
|
||||
// KeyUpgradedIBCState is the key under which upgraded ibc state is stored in the upgrade store
|
||||
KeyUpgradedIBCState = "upgradedIBCState"
|
||||
|
||||
// KeyUpgradedClient is the sub-key under which upgraded client state will be stored
|
||||
KeyUpgradedClient = "upgradedClient"
|
||||
|
||||
// KeyUpgradedConsState is the sub-key under which upgraded consensus state will be stored
|
||||
KeyUpgradedConsState = "upgradedConsState"
|
||||
)
|
||||
|
||||
// PlanKey is the key under which the current plan is saved
|
||||
@ -36,5 +42,12 @@ func PlanKey() []byte {
|
||||
// Connecting IBC chains can verify against the upgraded client in this path before
|
||||
// upgrading their clients
|
||||
func UpgradedClientKey(height int64) []byte {
|
||||
return []byte(fmt.Sprintf("%s/%d", KeyUpgradedClient, height))
|
||||
return []byte(fmt.Sprintf("%s/%d/%s", KeyUpgradedIBCState, height, KeyUpgradedClient))
|
||||
}
|
||||
|
||||
// UpgradedConsStateKey is the key under which the upgraded consensus state is saved
|
||||
// Connecting IBC chains can verify against the upgraded consensus state in this path before
|
||||
// upgrading their clients.
|
||||
func UpgradedConsStateKey(height int64) []byte {
|
||||
return []byte(fmt.Sprintf("%s/%d/%s", KeyUpgradedIBCState, height, KeyUpgradedConsState))
|
||||
}
|
||||
|
||||
@ -72,6 +72,11 @@ func (p Plan) DueAt() string {
|
||||
return fmt.Sprintf("height: %d", p.Height)
|
||||
}
|
||||
|
||||
// IsIBCPlan will return true if plan includes IBC client information
|
||||
func (p Plan) IsIBCPlan() bool {
|
||||
return p.UpgradedClientState != nil
|
||||
}
|
||||
|
||||
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
|
||||
func (p Plan) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
|
||||
// UpgradedClientState may be nil
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package types
|
||||
package types_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -12,6 +12,7 @@ import (
|
||||
|
||||
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
|
||||
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/upgrade/types"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
@ -29,11 +30,11 @@ func TestPlanString(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
cases := map[string]struct {
|
||||
p Plan
|
||||
p types.Plan
|
||||
expect string
|
||||
}{
|
||||
"with time": {
|
||||
p: Plan{
|
||||
p: types.Plan{
|
||||
Name: "due_time",
|
||||
Info: "https://foo.bar",
|
||||
Time: mustParseTime("2019-07-08T11:33:55Z"),
|
||||
@ -41,7 +42,7 @@ func TestPlanString(t *testing.T) {
|
||||
expect: "Upgrade Plan\n Name: due_time\n Time: 2019-07-08T11:33:55Z\n Info: https://foo.bar.\n Upgraded IBC Client: no upgraded client provided",
|
||||
},
|
||||
"with height": {
|
||||
p: Plan{
|
||||
p: types.Plan{
|
||||
Name: "by height",
|
||||
Info: "https://foo.bar/baz",
|
||||
Height: 7890,
|
||||
@ -49,7 +50,7 @@ func TestPlanString(t *testing.T) {
|
||||
expect: "Upgrade Plan\n Name: by height\n Height: 7890\n Info: https://foo.bar/baz.\n Upgraded IBC Client: no upgraded client provided",
|
||||
},
|
||||
"with IBC client": {
|
||||
p: Plan{
|
||||
p: types.Plan{
|
||||
Name: "by height",
|
||||
Info: "https://foo.bar/baz",
|
||||
Height: 7890,
|
||||
@ -59,7 +60,7 @@ func TestPlanString(t *testing.T) {
|
||||
},
|
||||
|
||||
"neither": {
|
||||
p: Plan{
|
||||
p: types.Plan{
|
||||
Name: "almost-empty",
|
||||
},
|
||||
expect: "Upgrade Plan\n Name: almost-empty\n Height: 0\n Info: .\n Upgraded IBC Client: no upgraded client provided",
|
||||
@ -80,11 +81,11 @@ func TestPlanValid(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
cases := map[string]struct {
|
||||
p Plan
|
||||
p types.Plan
|
||||
valid bool
|
||||
}{
|
||||
"proper": {
|
||||
p: Plan{
|
||||
p: types.Plan{
|
||||
Name: "all-good",
|
||||
Info: "some text here",
|
||||
Time: mustParseTime("2019-07-08T11:33:55Z"),
|
||||
@ -92,7 +93,7 @@ func TestPlanValid(t *testing.T) {
|
||||
valid: true,
|
||||
},
|
||||
"proper ibc upgrade": {
|
||||
p: Plan{
|
||||
p: types.Plan{
|
||||
Name: "ibc-all-good",
|
||||
Info: "some text here",
|
||||
Height: 123450000,
|
||||
@ -101,31 +102,31 @@ func TestPlanValid(t *testing.T) {
|
||||
valid: true,
|
||||
},
|
||||
"proper by height": {
|
||||
p: Plan{
|
||||
p: types.Plan{
|
||||
Name: "all-good",
|
||||
Height: 123450000,
|
||||
},
|
||||
valid: true,
|
||||
},
|
||||
"no name": {
|
||||
p: Plan{
|
||||
p: types.Plan{
|
||||
Height: 123450000,
|
||||
},
|
||||
},
|
||||
"no due at": {
|
||||
p: Plan{
|
||||
p: types.Plan{
|
||||
Name: "missing",
|
||||
Info: "important",
|
||||
},
|
||||
},
|
||||
"negative height": {
|
||||
p: Plan{
|
||||
p: types.Plan{
|
||||
Name: "minus",
|
||||
Height: -12345,
|
||||
},
|
||||
},
|
||||
"time due date defined for IBC plan": {
|
||||
p: Plan{
|
||||
p: types.Plan{
|
||||
Name: "ibc-all-good",
|
||||
Info: "some text here",
|
||||
Time: mustParseTime("2019-07-08T11:33:55Z"),
|
||||
@ -151,13 +152,13 @@ func TestPlanValid(t *testing.T) {
|
||||
|
||||
func TestShouldExecute(t *testing.T) {
|
||||
cases := map[string]struct {
|
||||
p Plan
|
||||
p types.Plan
|
||||
ctxTime time.Time
|
||||
ctxHeight int64
|
||||
expected bool
|
||||
}{
|
||||
"past time": {
|
||||
p: Plan{
|
||||
p: types.Plan{
|
||||
Name: "do-good",
|
||||
Info: "some text here",
|
||||
Time: mustParseTime("2019-07-08T11:33:55Z"),
|
||||
@ -167,7 +168,7 @@ func TestShouldExecute(t *testing.T) {
|
||||
expected: false,
|
||||
},
|
||||
"on time": {
|
||||
p: Plan{
|
||||
p: types.Plan{
|
||||
Name: "do-good",
|
||||
Time: mustParseTime("2019-07-08T11:33:55Z"),
|
||||
},
|
||||
@ -176,7 +177,7 @@ func TestShouldExecute(t *testing.T) {
|
||||
expected: true,
|
||||
},
|
||||
"future time": {
|
||||
p: Plan{
|
||||
p: types.Plan{
|
||||
Name: "do-good",
|
||||
Time: mustParseTime("2019-07-08T11:33:55Z"),
|
||||
},
|
||||
@ -185,7 +186,7 @@ func TestShouldExecute(t *testing.T) {
|
||||
expected: true,
|
||||
},
|
||||
"past height": {
|
||||
p: Plan{
|
||||
p: types.Plan{
|
||||
Name: "do-good",
|
||||
Height: 1234,
|
||||
},
|
||||
@ -194,7 +195,7 @@ func TestShouldExecute(t *testing.T) {
|
||||
expected: false,
|
||||
},
|
||||
"on height": {
|
||||
p: Plan{
|
||||
p: types.Plan{
|
||||
Name: "do-good",
|
||||
Height: 1234,
|
||||
},
|
||||
@ -203,7 +204,7 @@ func TestShouldExecute(t *testing.T) {
|
||||
expected: true,
|
||||
},
|
||||
"future height": {
|
||||
p: Plan{
|
||||
p: types.Plan{
|
||||
Name: "do-good",
|
||||
Height: 1234,
|
||||
},
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package types
|
||||
package types_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
gov "github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/upgrade/types"
|
||||
)
|
||||
|
||||
type ProposalWrapper struct {
|
||||
@ -23,7 +24,7 @@ func TestContentAccessors(t *testing.T) {
|
||||
str string
|
||||
}{
|
||||
"upgrade": {
|
||||
p: NewSoftwareUpgradeProposal("Title", "desc", Plan{
|
||||
p: types.NewSoftwareUpgradeProposal("Title", "desc", types.Plan{
|
||||
Name: "due_time",
|
||||
Info: "https://foo.bar",
|
||||
Time: mustParseTime("2019-07-08T11:33:55Z"),
|
||||
@ -34,7 +35,7 @@ func TestContentAccessors(t *testing.T) {
|
||||
str: "Software Upgrade Proposal:\n Title: Title\n Description: desc\n",
|
||||
},
|
||||
"cancel": {
|
||||
p: NewCancelSoftwareUpgradeProposal("Cancel", "bad idea"),
|
||||
p: types.NewCancelSoftwareUpgradeProposal("Cancel", "bad idea"),
|
||||
title: "Cancel",
|
||||
desc: "bad idea",
|
||||
typ: "CancelSoftwareUpgrade",
|
||||
@ -44,7 +45,7 @@ func TestContentAccessors(t *testing.T) {
|
||||
|
||||
cdc := codec.NewLegacyAmino()
|
||||
gov.RegisterLegacyAminoCodec(cdc)
|
||||
RegisterLegacyAminoCodec(cdc)
|
||||
types.RegisterLegacyAminoCodec(cdc)
|
||||
|
||||
for name, tc := range cases {
|
||||
tc := tc // copy to local variable for scopelint
|
||||
|
||||
@ -6,6 +6,7 @@ package types
|
||||
import (
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
types "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
grpc1 "github.com/gogo/protobuf/grpc"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
_ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
@ -207,11 +208,107 @@ func (m *QueryAppliedPlanResponse) GetHeight() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// QueryUpgradedConsensusStateRequest is the request type for the Query/UpgradedConsensusState
|
||||
// RPC method.
|
||||
type QueryUpgradedConsensusStateRequest struct {
|
||||
// last height of the current chain must be sent in request
|
||||
// as this is the height under which next consensus state is stored
|
||||
LastHeight int64 `protobuf:"varint,1,opt,name=last_height,json=lastHeight,proto3" json:"last_height,omitempty"`
|
||||
}
|
||||
|
||||
func (m *QueryUpgradedConsensusStateRequest) Reset() { *m = QueryUpgradedConsensusStateRequest{} }
|
||||
func (m *QueryUpgradedConsensusStateRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*QueryUpgradedConsensusStateRequest) ProtoMessage() {}
|
||||
func (*QueryUpgradedConsensusStateRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_4a334d07ad8374f0, []int{4}
|
||||
}
|
||||
func (m *QueryUpgradedConsensusStateRequest) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *QueryUpgradedConsensusStateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_QueryUpgradedConsensusStateRequest.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *QueryUpgradedConsensusStateRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_QueryUpgradedConsensusStateRequest.Merge(m, src)
|
||||
}
|
||||
func (m *QueryUpgradedConsensusStateRequest) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *QueryUpgradedConsensusStateRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_QueryUpgradedConsensusStateRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_QueryUpgradedConsensusStateRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *QueryUpgradedConsensusStateRequest) GetLastHeight() int64 {
|
||||
if m != nil {
|
||||
return m.LastHeight
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// QueryUpgradedConsensusStateResponse is the response type for the Query/UpgradedConsensusState
|
||||
// RPC method.
|
||||
type QueryUpgradedConsensusStateResponse struct {
|
||||
UpgradedConsensusState *types.Any `protobuf:"bytes,1,opt,name=upgraded_consensus_state,json=upgradedConsensusState,proto3" json:"upgraded_consensus_state,omitempty"`
|
||||
}
|
||||
|
||||
func (m *QueryUpgradedConsensusStateResponse) Reset() { *m = QueryUpgradedConsensusStateResponse{} }
|
||||
func (m *QueryUpgradedConsensusStateResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*QueryUpgradedConsensusStateResponse) ProtoMessage() {}
|
||||
func (*QueryUpgradedConsensusStateResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_4a334d07ad8374f0, []int{5}
|
||||
}
|
||||
func (m *QueryUpgradedConsensusStateResponse) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *QueryUpgradedConsensusStateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_QueryUpgradedConsensusStateResponse.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *QueryUpgradedConsensusStateResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_QueryUpgradedConsensusStateResponse.Merge(m, src)
|
||||
}
|
||||
func (m *QueryUpgradedConsensusStateResponse) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *QueryUpgradedConsensusStateResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_QueryUpgradedConsensusStateResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_QueryUpgradedConsensusStateResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *QueryUpgradedConsensusStateResponse) GetUpgradedConsensusState() *types.Any {
|
||||
if m != nil {
|
||||
return m.UpgradedConsensusState
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*QueryCurrentPlanRequest)(nil), "cosmos.upgrade.v1beta1.QueryCurrentPlanRequest")
|
||||
proto.RegisterType((*QueryCurrentPlanResponse)(nil), "cosmos.upgrade.v1beta1.QueryCurrentPlanResponse")
|
||||
proto.RegisterType((*QueryAppliedPlanRequest)(nil), "cosmos.upgrade.v1beta1.QueryAppliedPlanRequest")
|
||||
proto.RegisterType((*QueryAppliedPlanResponse)(nil), "cosmos.upgrade.v1beta1.QueryAppliedPlanResponse")
|
||||
proto.RegisterType((*QueryUpgradedConsensusStateRequest)(nil), "cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateRequest")
|
||||
proto.RegisterType((*QueryUpgradedConsensusStateResponse)(nil), "cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateResponse")
|
||||
}
|
||||
|
||||
func init() {
|
||||
@ -219,30 +316,38 @@ func init() {
|
||||
}
|
||||
|
||||
var fileDescriptor_4a334d07ad8374f0 = []byte{
|
||||
// 362 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0x3d, 0x4f, 0xfa, 0x40,
|
||||
0x1c, 0xc7, 0x39, 0xfe, 0xfc, 0x49, 0x3c, 0xb6, 0x1b, 0x10, 0x09, 0x69, 0xcc, 0x85, 0x18, 0x13,
|
||||
0xa1, 0xc7, 0xc3, 0x2b, 0x50, 0x13, 0x27, 0x07, 0x65, 0x74, 0x31, 0x07, 0xfc, 0x52, 0x1a, 0xcb,
|
||||
0xdd, 0xd1, 0xbb, 0x1a, 0x89, 0x71, 0xf1, 0x15, 0x98, 0xb8, 0xbb, 0xf9, 0x5e, 0x1c, 0x49, 0x5c,
|
||||
0x1c, 0x0d, 0xf8, 0x42, 0x0c, 0xd7, 0x62, 0x6a, 0xa0, 0xc1, 0xa9, 0x6d, 0xfa, 0x7d, 0xf8, 0xdc,
|
||||
0xb7, 0xc5, 0x74, 0x20, 0xf5, 0x58, 0x6a, 0x16, 0x29, 0x2f, 0xe4, 0x43, 0x60, 0xb7, 0xed, 0x3e,
|
||||
0x18, 0xde, 0x66, 0x93, 0x08, 0xc2, 0xa9, 0xab, 0x42, 0x69, 0x24, 0x29, 0xc7, 0x1a, 0x37, 0xd1,
|
||||
0xb8, 0x89, 0xa6, 0x5a, 0xf3, 0xa4, 0xf4, 0x02, 0x60, 0x5c, 0xf9, 0x8c, 0x0b, 0x21, 0x0d, 0x37,
|
||||
0xbe, 0x14, 0x3a, 0x76, 0x55, 0xeb, 0x19, 0xc9, 0xab, 0x14, 0xab, 0xa2, 0x7b, 0x78, 0xf7, 0x72,
|
||||
0x59, 0x75, 0x1a, 0x85, 0x21, 0x08, 0x73, 0x11, 0x70, 0xd1, 0x83, 0x49, 0x04, 0xda, 0xd0, 0x73,
|
||||
0x5c, 0x59, 0x7f, 0xa5, 0x95, 0x14, 0x1a, 0x48, 0x0b, 0x17, 0x54, 0xc0, 0x45, 0x05, 0xed, 0xa3,
|
||||
0xc3, 0x52, 0xa7, 0xe6, 0x6e, 0x26, 0x74, 0xad, 0xc7, 0x2a, 0x69, 0x33, 0x29, 0x3a, 0x56, 0x2a,
|
||||
0xf0, 0x61, 0x98, 0x2a, 0x22, 0x04, 0x17, 0x04, 0x1f, 0x83, 0x0d, 0xdb, 0xe9, 0xd9, 0x7b, 0xda,
|
||||
0x49, 0xca, 0x7f, 0xc9, 0x93, 0xf2, 0x32, 0x2e, 0x8e, 0xc0, 0xf7, 0x46, 0xc6, 0x3a, 0xfe, 0xf5,
|
||||
0x92, 0xa7, 0xce, 0x2c, 0x8f, 0xff, 0x5b, 0x13, 0x79, 0x41, 0xb8, 0x94, 0xc2, 0x26, 0x2c, 0x0b,
|
||||
0x30, 0xe3, 0xec, 0xd5, 0xd6, 0xdf, 0x0d, 0x31, 0x14, 0x6d, 0x3c, 0xbe, 0x7f, 0x3d, 0xe7, 0x0f,
|
||||
0x48, 0x9d, 0x65, 0xec, 0x3e, 0x88, 0x4d, 0xd7, 0xcb, 0x35, 0xc8, 0x2b, 0xc2, 0xa5, 0xd4, 0xd1,
|
||||
0xb6, 0x00, 0xae, 0x6f, 0xb6, 0x05, 0x70, 0xc3, 0x6a, 0xb4, 0x6b, 0x01, 0x9b, 0xe4, 0x28, 0x0b,
|
||||
0x90, 0xc7, 0x26, 0x0b, 0xc8, 0xee, 0x97, 0x5f, 0xe1, 0xe1, 0xe4, 0xec, 0x6d, 0xee, 0xa0, 0xd9,
|
||||
0xdc, 0x41, 0x9f, 0x73, 0x07, 0x3d, 0x2d, 0x9c, 0xdc, 0x6c, 0xe1, 0xe4, 0x3e, 0x16, 0x4e, 0xee,
|
||||
0xaa, 0xe1, 0xf9, 0x66, 0x14, 0xf5, 0xdd, 0x81, 0x1c, 0xaf, 0x02, 0xe3, 0x4b, 0x53, 0x0f, 0x6f,
|
||||
0xd8, 0xdd, 0x4f, 0xba, 0x99, 0x2a, 0xd0, 0xfd, 0xa2, 0xfd, 0xdb, 0xba, 0xdf, 0x01, 0x00, 0x00,
|
||||
0xff, 0xff, 0xca, 0xa9, 0x39, 0xfe, 0xef, 0x02, 0x00, 0x00,
|
||||
// 487 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x53, 0x41, 0x8b, 0x13, 0x31,
|
||||
0x18, 0x6d, 0xb4, 0x2e, 0x98, 0xde, 0x82, 0xd4, 0x6e, 0x59, 0x46, 0x89, 0x8b, 0x08, 0x6e, 0x93,
|
||||
0xdd, 0xee, 0x4d, 0x41, 0x5c, 0x17, 0x17, 0x0f, 0x22, 0x5a, 0xf1, 0xe2, 0xa5, 0xa4, 0x9d, 0x38,
|
||||
0x1d, 0x9c, 0x26, 0xd9, 0x49, 0x22, 0x96, 0x65, 0x2f, 0xfe, 0x02, 0xc1, 0xbb, 0x37, 0x6f, 0xfe,
|
||||
0x10, 0x8f, 0x0b, 0x5e, 0xf4, 0x26, 0xad, 0x3f, 0x44, 0x26, 0xc9, 0x48, 0x97, 0x76, 0x66, 0xc5,
|
||||
0x53, 0x3b, 0x93, 0xf7, 0xbe, 0xf7, 0xbe, 0xbc, 0x37, 0x10, 0x8f, 0xa5, 0x9e, 0x4a, 0x4d, 0xad,
|
||||
0x4a, 0x72, 0x16, 0x73, 0xfa, 0x6e, 0x6f, 0xc4, 0x0d, 0xdb, 0xa3, 0xc7, 0x96, 0xe7, 0x33, 0xa2,
|
||||
0x72, 0x69, 0x24, 0x6a, 0x7b, 0x0c, 0x09, 0x18, 0x12, 0x30, 0xdd, 0xcd, 0x44, 0xca, 0x24, 0xe3,
|
||||
0xd4, 0xa1, 0x46, 0xf6, 0x0d, 0x65, 0x22, 0x50, 0xba, 0x5b, 0xe1, 0x88, 0xa9, 0x94, 0x32, 0x21,
|
||||
0xa4, 0x61, 0x26, 0x95, 0x42, 0x87, 0xd3, 0xed, 0x0a, 0xd1, 0x52, 0xc0, 0xa1, 0xf0, 0x26, 0xbc,
|
||||
0xfe, 0xa2, 0x70, 0x71, 0x68, 0xf3, 0x9c, 0x0b, 0xf3, 0x3c, 0x63, 0x62, 0xc0, 0x8f, 0x2d, 0xd7,
|
||||
0x06, 0x3f, 0x85, 0x9d, 0xd5, 0x23, 0xad, 0xa4, 0xd0, 0x1c, 0xed, 0xc2, 0xa6, 0xca, 0x98, 0xe8,
|
||||
0x80, 0x9b, 0xe0, 0x4e, 0xab, 0xbf, 0x45, 0xd6, 0x9b, 0x27, 0x8e, 0xe3, 0x90, 0xb8, 0x17, 0x84,
|
||||
0x0e, 0x94, 0xca, 0x52, 0x1e, 0x2f, 0x09, 0x21, 0x04, 0x9b, 0x82, 0x4d, 0xb9, 0x1b, 0x76, 0x75,
|
||||
0xe0, 0xfe, 0xe3, 0x7e, 0x10, 0x3f, 0x07, 0x0f, 0xe2, 0x6d, 0xb8, 0x31, 0xe1, 0x69, 0x32, 0x31,
|
||||
0x8e, 0x71, 0x79, 0x10, 0x9e, 0xf0, 0x63, 0x88, 0x1d, 0xe7, 0x95, 0x77, 0x11, 0x1f, 0x16, 0x68,
|
||||
0xa1, 0xad, 0x7e, 0x69, 0x98, 0xe1, 0xa5, 0xda, 0x0d, 0xd8, 0xca, 0x98, 0x36, 0xc3, 0x73, 0x23,
|
||||
0x60, 0xf1, 0xea, 0x89, 0x1f, 0x63, 0xe1, 0xad, 0xda, 0x31, 0xc1, 0xc5, 0x33, 0xd8, 0x09, 0xeb,
|
||||
0xc6, 0xc3, 0x71, 0x09, 0x19, 0xea, 0x02, 0x13, 0xae, 0xe5, 0x1a, 0xf1, 0x01, 0x91, 0x32, 0x3b,
|
||||
0x72, 0x20, 0x66, 0x83, 0xb6, 0x5d, 0x3b, 0xb7, 0xff, 0xb5, 0x09, 0xaf, 0x38, 0x5d, 0xf4, 0x19,
|
||||
0xc0, 0xd6, 0xd2, 0xa5, 0x23, 0x5a, 0x75, 0xbd, 0x15, 0xc9, 0x75, 0x77, 0xff, 0x9d, 0xe0, 0x97,
|
||||
0xc1, 0x3b, 0x1f, 0xbe, 0xff, 0xfe, 0x74, 0xe9, 0x36, 0xda, 0xa6, 0x15, 0xad, 0x19, 0x7b, 0xd2,
|
||||
0xb0, 0xc8, 0x12, 0x7d, 0x01, 0xb0, 0xb5, 0x14, 0xcc, 0x05, 0x06, 0x57, 0x13, 0xbf, 0xc0, 0xe0,
|
||||
0x9a, 0xcc, 0xf1, 0xbe, 0x33, 0xd8, 0x43, 0x77, 0xab, 0x0c, 0x32, 0x4f, 0x72, 0x06, 0xe9, 0x49,
|
||||
0xd1, 0xa1, 0x53, 0xf4, 0x13, 0xc0, 0xf6, 0xfa, 0x14, 0xd1, 0xbd, 0x5a, 0x07, 0xb5, 0x0d, 0xea,
|
||||
0xde, 0xff, 0x2f, 0x6e, 0x58, 0xe4, 0xc8, 0x2d, 0xf2, 0x10, 0x3d, 0xa0, 0xf5, 0xdf, 0xe7, 0x4a,
|
||||
0xa9, 0xe8, 0xc9, 0x52, 0x6d, 0x4f, 0x1f, 0x1d, 0x7d, 0x9b, 0x47, 0xe0, 0x6c, 0x1e, 0x81, 0x5f,
|
||||
0xf3, 0x08, 0x7c, 0x5c, 0x44, 0x8d, 0xb3, 0x45, 0xd4, 0xf8, 0xb1, 0x88, 0x1a, 0xaf, 0x77, 0x92,
|
||||
0xd4, 0x4c, 0xec, 0x88, 0x8c, 0xe5, 0xb4, 0xd4, 0xf0, 0x3f, 0x3d, 0x1d, 0xbf, 0xa5, 0xef, 0xff,
|
||||
0x0a, 0x9a, 0x99, 0xe2, 0x7a, 0xb4, 0xe1, 0xca, 0xb9, 0xff, 0x27, 0x00, 0x00, 0xff, 0xff, 0xee,
|
||||
0x4b, 0xe2, 0xe8, 0xa4, 0x04, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
@ -261,6 +366,11 @@ type QueryClient interface {
|
||||
CurrentPlan(ctx context.Context, in *QueryCurrentPlanRequest, opts ...grpc.CallOption) (*QueryCurrentPlanResponse, error)
|
||||
// AppliedPlan queries a previously applied upgrade plan by its name.
|
||||
AppliedPlan(ctx context.Context, in *QueryAppliedPlanRequest, opts ...grpc.CallOption) (*QueryAppliedPlanResponse, error)
|
||||
// UpgradedConsensusState queries the consensus state that will serve
|
||||
// as a trusted kernel for the next version of this chain. It will only be
|
||||
// stored at the last height of this chain.
|
||||
// UpgradedConsensusState RPC not supported with legacy querier
|
||||
UpgradedConsensusState(ctx context.Context, in *QueryUpgradedConsensusStateRequest, opts ...grpc.CallOption) (*QueryUpgradedConsensusStateResponse, error)
|
||||
}
|
||||
|
||||
type queryClient struct {
|
||||
@ -289,12 +399,26 @@ func (c *queryClient) AppliedPlan(ctx context.Context, in *QueryAppliedPlanReque
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *queryClient) UpgradedConsensusState(ctx context.Context, in *QueryUpgradedConsensusStateRequest, opts ...grpc.CallOption) (*QueryUpgradedConsensusStateResponse, error) {
|
||||
out := new(QueryUpgradedConsensusStateResponse)
|
||||
err := c.cc.Invoke(ctx, "/cosmos.upgrade.v1beta1.Query/UpgradedConsensusState", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// QueryServer is the server API for Query service.
|
||||
type QueryServer interface {
|
||||
// CurrentPlan queries the current upgrade plan.
|
||||
CurrentPlan(context.Context, *QueryCurrentPlanRequest) (*QueryCurrentPlanResponse, error)
|
||||
// AppliedPlan queries a previously applied upgrade plan by its name.
|
||||
AppliedPlan(context.Context, *QueryAppliedPlanRequest) (*QueryAppliedPlanResponse, error)
|
||||
// UpgradedConsensusState queries the consensus state that will serve
|
||||
// as a trusted kernel for the next version of this chain. It will only be
|
||||
// stored at the last height of this chain.
|
||||
// UpgradedConsensusState RPC not supported with legacy querier
|
||||
UpgradedConsensusState(context.Context, *QueryUpgradedConsensusStateRequest) (*QueryUpgradedConsensusStateResponse, error)
|
||||
}
|
||||
|
||||
// UnimplementedQueryServer can be embedded to have forward compatible implementations.
|
||||
@ -307,6 +431,9 @@ func (*UnimplementedQueryServer) CurrentPlan(ctx context.Context, req *QueryCurr
|
||||
func (*UnimplementedQueryServer) AppliedPlan(ctx context.Context, req *QueryAppliedPlanRequest) (*QueryAppliedPlanResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AppliedPlan not implemented")
|
||||
}
|
||||
func (*UnimplementedQueryServer) UpgradedConsensusState(ctx context.Context, req *QueryUpgradedConsensusStateRequest) (*QueryUpgradedConsensusStateResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpgradedConsensusState not implemented")
|
||||
}
|
||||
|
||||
func RegisterQueryServer(s grpc1.Server, srv QueryServer) {
|
||||
s.RegisterService(&_Query_serviceDesc, srv)
|
||||
@ -348,6 +475,24 @@ func _Query_AppliedPlan_Handler(srv interface{}, ctx context.Context, dec func(i
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Query_UpgradedConsensusState_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(QueryUpgradedConsensusStateRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(QueryServer).UpgradedConsensusState(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/cosmos.upgrade.v1beta1.Query/UpgradedConsensusState",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(QueryServer).UpgradedConsensusState(ctx, req.(*QueryUpgradedConsensusStateRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Query_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "cosmos.upgrade.v1beta1.Query",
|
||||
HandlerType: (*QueryServer)(nil),
|
||||
@ -360,6 +505,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{
|
||||
MethodName: "AppliedPlan",
|
||||
Handler: _Query_AppliedPlan_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "UpgradedConsensusState",
|
||||
Handler: _Query_UpgradedConsensusState_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "cosmos/upgrade/v1beta1/query.proto",
|
||||
@ -481,6 +630,69 @@ func (m *QueryAppliedPlanResponse) MarshalToSizedBuffer(dAtA []byte) (int, error
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *QueryUpgradedConsensusStateRequest) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *QueryUpgradedConsensusStateRequest) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *QueryUpgradedConsensusStateRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.LastHeight != 0 {
|
||||
i = encodeVarintQuery(dAtA, i, uint64(m.LastHeight))
|
||||
i--
|
||||
dAtA[i] = 0x8
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *QueryUpgradedConsensusStateResponse) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *QueryUpgradedConsensusStateResponse) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *QueryUpgradedConsensusStateResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.UpgradedConsensusState != nil {
|
||||
{
|
||||
size, err := m.UpgradedConsensusState.MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintQuery(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintQuery(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovQuery(v)
|
||||
base := offset
|
||||
@ -539,6 +751,31 @@ func (m *QueryAppliedPlanResponse) Size() (n int) {
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *QueryUpgradedConsensusStateRequest) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
if m.LastHeight != 0 {
|
||||
n += 1 + sovQuery(uint64(m.LastHeight))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *QueryUpgradedConsensusStateResponse) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
if m.UpgradedConsensusState != nil {
|
||||
l = m.UpgradedConsensusState.Size()
|
||||
n += 1 + l + sovQuery(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovQuery(x uint64) (n int) {
|
||||
return (math_bits.Len64(x|1) + 6) / 7
|
||||
}
|
||||
@ -844,6 +1081,167 @@ func (m *QueryAppliedPlanResponse) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *QueryUpgradedConsensusStateRequest) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowQuery
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: QueryUpgradedConsensusStateRequest: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: QueryUpgradedConsensusStateRequest: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field LastHeight", wireType)
|
||||
}
|
||||
m.LastHeight = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowQuery
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.LastHeight |= int64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipQuery(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthQuery
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthQuery
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *QueryUpgradedConsensusStateResponse) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowQuery
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: QueryUpgradedConsensusStateResponse: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: QueryUpgradedConsensusStateResponse: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field UpgradedConsensusState", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowQuery
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthQuery
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthQuery
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.UpgradedConsensusState == nil {
|
||||
m.UpgradedConsensusState = &types.Any{}
|
||||
}
|
||||
if err := m.UpgradedConsensusState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipQuery(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthQuery
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthQuery
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipQuery(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
|
||||
@ -103,6 +103,60 @@ func local_request_Query_AppliedPlan_0(ctx context.Context, marshaler runtime.Ma
|
||||
|
||||
}
|
||||
|
||||
func request_Query_UpgradedConsensusState_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryUpgradedConsensusStateRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["last_height"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "last_height")
|
||||
}
|
||||
|
||||
protoReq.LastHeight, err = runtime.Int64(val)
|
||||
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "last_height", err)
|
||||
}
|
||||
|
||||
msg, err := client.UpgradedConsensusState(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Query_UpgradedConsensusState_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryUpgradedConsensusStateRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["last_height"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "last_height")
|
||||
}
|
||||
|
||||
protoReq.LastHeight, err = runtime.Int64(val)
|
||||
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "last_height", err)
|
||||
}
|
||||
|
||||
msg, err := server.UpgradedConsensusState(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
|
||||
// UnaryRPC :call QueryServer directly.
|
||||
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
|
||||
@ -149,6 +203,26 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_UpgradedConsensusState_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Query_UpgradedConsensusState_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Query_UpgradedConsensusState_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -230,6 +304,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_UpgradedConsensusState_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Query_UpgradedConsensusState_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Query_UpgradedConsensusState_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -237,10 +331,14 @@ var (
|
||||
pattern_Query_CurrentPlan_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "upgrade", "v1beta1", "current_plan"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_Query_AppliedPlan_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "upgrade", "v1beta1", "applied_plan", "name"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_Query_UpgradedConsensusState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "upgrade", "v1beta1", "upgraded_consensus_state", "last_height"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
)
|
||||
|
||||
var (
|
||||
forward_Query_CurrentPlan_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Query_AppliedPlan_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Query_UpgradedConsensusState_0 = runtime.ForwardResponseMessage
|
||||
)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user