Skip to content

Commit

Permalink
Merge branch 'aditya/block-delay' of github.com:cosmos/ibc-go into ad…
Browse files Browse the repository at this point in the history
…itya/block-delay
  • Loading branch information
AdityaSripal committed May 18, 2021
2 parents ed5c706 + f716b61 commit 78fb8ce
Show file tree
Hide file tree
Showing 53 changed files with 994 additions and 1,036 deletions.
14 changes: 7 additions & 7 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ jobs:
matrix:
go-arch: ["amd64", "arm", "arm64"]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v2.3.4
- uses: actions/setup-go@v2.1.3
with:
go-version: 1.15
- uses: technote-space/get-diff-action@v4
- uses: technote-space/get-diff-action@v4.1.1
id: git_diff
with:
PATTERNS: |
Expand All @@ -54,7 +54,7 @@ jobs:
split-test-files:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v2.3.4
- name: Create a file with all the pkgs
run: go list ./... > pkgs.txt
- name: Split pkgs into 4 files
Expand Down Expand Up @@ -85,11 +85,11 @@ jobs:
matrix:
part: ["00", "01", "02", "03"]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v2.3.4
- uses: actions/setup-go@v2.1.3
with:
go-version: 1.15
- uses: technote-space/get-diff-action@v4
- uses: technote-space/get-diff-action@v4.1.1
with:
PATTERNS: |
**/**.go
Expand All @@ -112,8 +112,8 @@ jobs:
runs-on: ubuntu-latest
needs: tests
steps:
- uses: actions/checkout@v2
- uses: technote-space/get-diff-action@v4
- uses: actions/checkout@v2.3.4
- uses: technote-space/get-diff-action@v4.1.1
with:
PATTERNS: |
**/**.go
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,18 @@ Ref: https://keepachangelog.com/en/1.0.0/

### Bug Fixes

* (modules/light-clients/06-solomachine) [\153](https://github.com/cosmos/ibc-go/pull/153) Fix solo machine proof height sequence mismatch bug.
* (modules/light-clients/06-solomachine) [\#122](https://github.com/cosmos/ibc-go/pull/122) Fix solo machine merkle prefix casting bug.
* (modules/light-clients/06-solomachine) [\#120](https://github.com/cosmos/ibc-go/pull/120) Fix solo machine handshake verification bug.


### API Breaking

* (06-solomachine) [\#169](https://github.com/cosmos/ibc-go/pull/169) Change FrozenSequence to boolean in solomachine ClientState. The solo machine proto package has been bumped from `v1` to `v2`.
* (module/core/02-client) [\#165](https://github.com/cosmos/ibc-go/pull/165) Remove GetFrozenHeight from the ClientState interface.
* (modules) [\#166](https://github.com/cosmos/ibc-go/pull/166) Remove GetHeight from the misbehaviour interface. The `consensus_height` attribute has been removed from Misbehaviour events.
* (modules) [\#162](https://github.com/cosmos/ibc-go/pull/162) Remove deprecated Handler types in core IBC and the ICS 20 transfer module.
* (modules/core) [\#161](https://github.com/cosmos/ibc-go/pull/161) Remove Type(), Route(), GetSignBytes() from 02-client, 03-connection, and 04-channel messages.
* (modules) [\#140](https://github.com/cosmos/ibc-go/pull/140) IsFrozen() client state interface changed to Status(). gRPC `ClientStatus` route added.
* (modules/core) [\#109](https://github.com/cosmos/ibc-go/pull/109) Remove connection and channel handshake CLI commands.
* (modules) [\#107](https://github.com/cosmos/ibc-go/pull/107) Modify OnRecvPacket callback to return an acknowledgement which indicates if it is successful or not. Callback state changes are discarded for unsuccessful acknowledgements only.
Expand All @@ -52,6 +58,8 @@ Ref: https://keepachangelog.com/en/1.0.0/
### State Machine Breaking

* (modules/light-clients/07-tendermint) [\#99](https://github.com/cosmos/ibc-go/pull/99) Enforce maximum chain-id length for tendermint client.
* (modules/light-clients/07-tendermint) [\#141](https://github.com/cosmos/ibc-go/pull/141) Allow a new form of misbehaviour that proves counterparty chain breaks time monotonicity, automatically enforce monotonicity in UpdateClient and freeze client if monotonicity is broken.
* (modules/light-clients/07-tendermint) [\#141](https://github.com/cosmos/ibc-go/pull/141) Freeze the client if there's a conflicting header submitted for an existing consensus state.
* (modules/core/02-client) [\#8405](https://github.com/cosmos/cosmos-sdk/pull/8405) Refactor IBC client update governance proposals to use a substitute client to update a frozen or expired client.
* (modules/core/02-client) [\#8673](https://github.com/cosmos/cosmos-sdk/pull/8673) IBC upgrade logic moved to 02-client and an IBC UpgradeProposal is added.

Expand All @@ -60,6 +68,8 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (modules/core/04-channel) [\#7949](https://github.com/cosmos/cosmos-sdk/issues/7949) Standardized channel `Acknowledgement` moved to its own file. Codec registration redundancy removed.
* (modules/core/04-channel) [\#144](https://github.com/cosmos/ibc-go/pull/144) Introduced a `packet_data_hex` attribute to emit the hex-encoded packet data in events. This allows for raw binary (proto-encoded message) to be sent over events and decoded correctly on relayer. Original `packet_data` is DEPRECATED. All relayers and IBC event consumers are encouraged to switch to `packet_data_hex` as soon as possible.
* (modules/light-clients/07-tendermint) [\#125](https://github.com/cosmos/ibc-go/pull/125) Implement efficient iteration of consensus states and pruning of earliest expired consensus state on UpdateClient.
* (modules/light-clients/07-tendermint) [\#141](https://github.com/cosmos/ibc-go/pull/141) Return early in case there's a duplicate update call to save Gas.


## IBC in the Cosmos SDK Repository

Expand Down
1 change: 1 addition & 0 deletions docs/OLD_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ consensus states in order to verify their membership in the counterparty clients
* [ADR 020 - Protocol Buffer Transaction Encoding](./../../docs/architecture/adr-020-protobuf-transaction-encoding.md): Client side migration to Protobuf.
* [ADR 021 - Protocol Buffer Query Encoding](../../../docs/architecture/adr-020-protobuf-query-encoding.md): Queries migration to Protobuf.
* [ADR 026 - IBC Client Recovery Mechanisms](../../../docs/architecture/adr-026-ibc-client-recovery-mechanisms.md): Allows IBC Clients to be recovered after freezing or expiry.
* [ADR 027 - IBC WASM Client](../../../docs/architecture/adr-027-ibc-wasm.md)

### SDK Modules

Expand Down
2 changes: 2 additions & 0 deletions docs/architecture/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,6 @@ To suggest an ADR, please make use of the [ADR template](./adr-template.md) prov
| [015](./adr-015-ibc-packet-receiver.md) | IBC Packet Routing | Accepted |
| [025](./adr-025-ibc-passive-channels.md) | IBC passive channels | Deprecated |
| [026](./adr-026-ibc-client-recovery-mechanisms.md) | IBC client recovery mechansisms | Accepted |
| [027](./adr-027-ibc-wasm.md) | Wasm based light clients | Accepted |


147 changes: 147 additions & 0 deletions docs/architecture/adr-027-ibc-wasm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# ADR 27: Add support for Wasm based light client

## Changelog

- 26/11/2020: Initial Draft

## Status

*Draft*

## Abstract

In the Cosmos SDK light clients are current hardcoded in Go. This makes upgrading existing IBC light clients or adding
support for new light client a multi step process involving on-chain governance which is time-consuming.

To remedy this, we are proposing a WASM VM to host light client bytecode, which allows easier upgrading of
existing IBC light clients as well as adding support for new IBC light clients without requiring a code release and corresponding
hard-fork event.

## Context
Currently in the SDK, light clients are defined as part of the codebase and are implemented as submodules under
`ibc-go/core/modules/light-clients/`.

Adding support for new light client or update an existing light client in the event of security
issue or consensus update is multi-step process which is both time consuming and error prone:

1. To add support for new light client or update an existing light client in the
event of security issue or consensus update, we need to modify the codebase and integrate it in numerous places.

2. Governance voting: Adding new light client implementations require governance support and is expensive: This is
not ideal as chain governance is gatekeeper for new light client implementations getting added. If a small community
want support for light client X, they may not be able to convince governance to support it.

3. Validator upgrade: After governance voting succeeds, validators need to upgrade their nodes in order to enable new
IBC light client implementation.

Another problem stemming from the above process is that if a chain wants to upgrade its own consensus, it will need to convince every chain
or hub connected to it to upgrade its light client in order to stay connected. Due to time consuming process required
to upgrade light client, a chain with lots of connections needs to be disconnected for quite some time after upgrading
its consensus, which can be very expensive in terms of time and effort.

We are proposing simplifying this workflow by integrating a WASM light client module which makes adding support for
a new light client a simple transaction. The light client bytecode, written in Wasm-compilable Rust, runs inside a WASM
VM. The Wasm light client submodule exposes a proxy light client interface that routes incoming messages to the
appropriate handler function, inside the Wasm VM for execution.

With WASM light client module, anybody can add new IBC light client in the form of WASM bytecode (provided they are able to pay the requisite gas fee for the transaction)
as well as instantiate clients using any created client type. This allows any chain to update its own light client in other chains
without going through steps outlined above.


## Decision

We decided to use WASM light client module as a light client proxy which will interface with the actual light client
uploaded as WASM bytecode. This will require changing client selection method to allow any client if the client type
has prefix of `wasm/`.

```go
// IsAllowedClient checks if the given client type is registered on the allowlist.
func (p Params) IsAllowedClient(clientType string) bool {
if p.AreWASMClientsAllowed && isWASMClient(clientType) {
return true
}

for _, allowedClient := range p.AllowedClients {
if allowedClient == clientType {
return true
}
}

return false
}
```

To upload new light client, user need to create a transaction with Wasm byte code which will be
processed by IBC Wasm module.

```go
func (k Keeper) UploadLightClient (wasmCode: []byte, description: String) {
wasmRegistry = getWASMRegistry()
id := hex.EncodeToString(sha256.Sum256(wasmCode))
assert(!wasmRegistry.Exists(id))
assert(wasmRegistry.ValidateAndStoreCode(id, description, wasmCode, false))
}
```

As name implies, Wasm registry is a registry which stores set of Wasm client code indexed by its hash and allows
client code to retrieve latest code uploaded.

`ValidateAndStoreCode` checks if the wasm bytecode uploaded is valid and confirms to VM interface.

### How light client proxy works?

The light client proxy behind the scenes will call a cosmwasm smart contract instance with incoming arguments in json
serialized format with appropriate environment information. Data returned by the smart contract is deserialized and
returned to the caller.

Consider an example of `CheckProposedHeaderAndUpdateState` function of `ClientState` interface. Incoming arguments are
packaged inside a payload which is json serialized and passed to `callContract` which calls `vm.Execute` and returns the
array of bytes returned by the smart contract. This data is deserialized and passed as return argument.

```go
func (c *ClientState) CheckProposedHeaderAndUpdateState(context sdk.Context, marshaler codec.BinaryMarshaler, store sdk.KVStore, header exported.Header) (exported.ClientState, exported.ConsensusState, error) {
// get consensus state corresponding to client state to check if the client is expired
consensusState, err := GetConsensusState(store, marshaler, c.LatestHeight)
if err != nil {
return nil, nil, sdkerrors.Wrapf(
err, "could not get consensus state from clientstore at height: %d", c.LatestHeight,
)
}

payload := make(map[string]map[string]interface{})
payload[CheckProposedHeaderAndUpdateState] = make(map[string]interface{})
inner := payload[CheckProposedHeaderAndUpdateState]
inner["me"] = c
inner["header"] = header
inner["consensus_state"] = consensusState

encodedData, err := json.Marshal(payload)
if err != nil {
return nil, nil, sdkerrors.Wrapf(ErrUnableToMarshalPayload, fmt.Sprintf("underlying error: %s", err.Error()))
}
out, err := callContract(c.CodeId, context, store, encodedData)
if err != nil {
return nil, nil, sdkerrors.Wrapf(ErrUnableToCall, fmt.Sprintf("underlying error: %s", err.Error()))
}
output := clientStateCallResponse{}
if err := json.Unmarshal(out.Data, &output); err != nil {
return nil, nil, sdkerrors.Wrapf(ErrUnableToUnmarshalPayload, fmt.Sprintf("underlying error: %s", err.Error()))
}
if !output.Result.IsValid {
return nil, nil, fmt.Errorf("%s error ocurred while updating client state", output.Result.ErrorMsg)
}
output.resetImmutables(c)
return output.NewClientState, output.NewConsensusState, nil
}
```

## Consequences

### Positive
- Adding support for new light client or upgrading existing light client is way easier than before and only requires single transaction.
- Improves maintainability of Cosmos SDK, since no change in codebase is required to support new client or upgrade it.

### Negative
- Light clients need to be written in subset of rust which could compile in Wasm.
- Introspecting light client code is difficult as only compiled bytecode exists in the blockchain.
Loading

0 comments on commit 78fb8ce

Please sign in to comment.