Skip to content

Commit

Permalink
Merge branch 'main' into gnad/add-allowed-packet
Browse files Browse the repository at this point in the history
  • Loading branch information
GNaD13 authored Dec 5, 2023
2 parents 97bf329 + 54e2172 commit 8f21fc9
Show file tree
Hide file tree
Showing 11 changed files with 249 additions and 90 deletions.
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

# CODEOWNERS for 08-wasm light client module

/modules/light-clients/08-wasm/ @colin-axner @AdityaSripal @damiannolan @charleenfei @chatton @DimitrisJim @srdtrk
/modules/light-clients/08-wasm/ @colin-axner @AdityaSripal @damiannolan @charleenfei @chatton @DimitrisJim @srdtrk @crodriguezvega

# CODEOWNERS for ICS 20

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@e6428a5c4e294a61438ed7f43155db912025b6b3
uses: docker/metadata-action@31cebacef4805868f9ce9a0cb03ee36c32df2ac4
with:
images: ${{ env.REGISTRY }}/cosmos/${{ env.IMAGE_NAME }}

Expand Down
53 changes: 53 additions & 0 deletions .github/workflows/e2e-fork.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,31 @@ jobs:
env:
TEST_EXCLUSIONS: 'TestUpgradeTestSuite,TestGrandpaTestSuite'

# dynamically build a matrix of test/test suite pairs to run
build-test-matrix-wasm:
if: ${{ github.event.pull_request.head.repo.fork || github.actor == 'dependabot[bot]' || github.event_name == 'workflow_dispatch' }}
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v4
with:
go-version: '1.21'
- id: set-matrix
run: echo "matrix=$(go run cmd/build_test_matrix/main.go)" >> $GITHUB_OUTPUT
env:
TEST_ENTRYPOINT: 'TestGrandpaTestSuite'


# e2e-fork runs the e2e tests directly by using a matrix strategy.
e2e-fork:
env:
CHAIN_A_TAG: latest
CHAIN_B_TAG: latest
CHAIN_IMAGE: ibc-go-simd
RELAYER_ID: "hermes" # by default use hermes for fork e2es.
FORK: "true"
if: ${{ github.event.pull_request.head.repo.fork || github.actor == 'dependabot[bot]' || github.event_name == 'workflow_dispatch' }}
needs:
- build-test-matrix
Expand All @@ -52,3 +70,38 @@ jobs:
run: |
cd e2e
make e2e-test test=${{ matrix.test }}
# this workflow runs only the wasm tests.
e2e-fork-wasm:
env:
CHAIN_A_TAG: latest
CHAIN_B_TAG: latest
CHAIN_IMAGE: ibc-go-wasm-simd
RELAYER_ID: "hyperspace" # by default use hyperspace relayer for fork wasm tests.
FORK: "true"
if: ${{ github.event.pull_request.head.repo.fork || github.actor == 'dependabot[bot]' || github.event_name == 'workflow_dispatch' }}
needs: build-test-matrix-wasm
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.build-test-matrix-wasm.outputs.matrix) }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install dependencies
run: make python-install-deps
- name: Docker Build Wasm
run: |
version="$(scripts/get-libwasm-version.py --get-version)"
checksum="$(scripts/get-libwasm-version.py --get-checksum)"
docker build . -t "${CHAIN_IMAGE}:${CHAIN_A_TAG}" -f modules/light-clients/08-wasm/Dockerfile --build-arg LIBWASM_VERSION=${version} --build-arg LIBWASM_CHECKSUM=${checksum}
- name: Setup Go
uses: actions/setup-go@v4
with:
go-version: '1.21'
- name: Run e2e Test
run: |
cd e2e
make e2e-test test=${{ matrix.test }}
4 changes: 2 additions & 2 deletions .github/workflows/e2e-test-workflow-call.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ jobs:
- name: Extract metadata (tags, labels) for Docker
if: ${{ inputs.build-and-push-docker-image }}
id: meta
uses: docker/metadata-action@e6428a5c4e294a61438ed7f43155db912025b6b3
uses: docker/metadata-action@31cebacef4805868f9ce9a0cb03ee36c32df2ac4
with:
images: ${{ env.REGISTRY }}/cosmos/${{ env.IMAGE_NAME }}

Expand Down Expand Up @@ -168,7 +168,7 @@ jobs:
- name: Extract metadata (tags, labels) for Docker
if: ${{ inputs.build-and-push-docker-image-wasm }}
id: meta
uses: docker/metadata-action@e6428a5c4e294a61438ed7f43155db912025b6b3
uses: docker/metadata-action@31cebacef4805868f9ce9a0cb03ee36c32df2ac4
with:
images: ${{ env.REGISTRY }}/cosmos/${{ env.IMAGE_NAME_WASM }}

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@e6428a5c4e294a61438ed7f43155db912025b6b3
uses: docker/metadata-action@31cebacef4805868f9ce9a0cb03ee36c32df2ac4
with:
images: ${{ env.REGISTRY }}/cosmos/${{ env.IMAGE_NAME }}

Expand Down
16 changes: 14 additions & 2 deletions docs/docs/01-ibc/09-roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ slug: /ibc/roadmap

# Roadmap ibc-go

*Lastest update: November 12th, 2023*
*Lastest update: December 4th, 2023*

This document endeavours to inform the wider IBC community about plans and priorities for work on ibc-go by the team at Interchain GmbH. It is intended to broadly inform all users of ibc-go, including developers and operators of IBC, relayer, chain and wallet applications.

Expand All @@ -21,14 +21,26 @@ The first release of this new module will add support for Wasm light clients. Th

This feature has been developed by Composable and Strangelove.

## v9.0.0
## v8.1.0

### Channel upgradability

Channel upgradability will allow chains to renegotiate an existing channel to take advantage of new features without having to create a new channel, thus preserving all existing packet state processed on the channel. This feature will enable, for example, the adoption of existing channels of features like [path unwinding](https://github.com/cosmos/ibc/discussions/824) or fee middleware.

Follow the progress with the [alpha milestone](https://github.com/cosmos/ibc-go/milestone/29) or the [project board](https://github.com/orgs/cosmos/projects/7/views/17).

## v9.0.0

### Conditional clients

Conditional clients are light clients which are dependent on another client in order to verify or update state. Conditional clients are essential for integration with modular blockchains which break up consensus and state management, such as rollups. Currently, light clients receive a single provable store they maintain. There is an unidirectional communication channel with 02-client: the 02-client module will call into the light client, without allowing for the light client to call into the 02-client module. But modular blockchains break up a logical blockchain into many constituent parts, so in order to accurately represent these chains and also to account for various types of shared security primitives that are coming up, we need to introduce dependencies between clients. In the case of optimistic rollups, for example, in order to prove execution (allowing for fraud proofs), you must prove data availability and sequencing. A potential solution to this problem is that a light client may optionally specify a list of dependencies and the 02-client module would lookup read-only provable stores for each dependency and provide this to the conditional client to perform verification. Please see [this issue](https://github.com/cosmos/ibc-go/issues/5112) for more details.

## v10.0.0

### Multihop channels

Multihop channels specify a way to route messages across a path of IBC enabled blockchains utilizing multiple pre-existing IBC connections. The current IBC protocol defines messaging in a point-to-point paradigm which allows message passing between two directly connected IBC chains, but as more IBC enabled chains come into existence there becomes a need to relay IBC packets across chains because IBC connections may not exist between the two chains wishing to exchange messages. IBC connections may not exist for a variety of reasons which could include economic inviability since connections require client state to be continuously exchanged between connection ends which carries a cost. Please see the [ICS 33 spec](https://github.com/cosmos/ibc/blob/main/spec/core/ics-033-multi-hop/README.md) for more information.

---

This roadmap is also available as a [project board](https://github.com/orgs/cosmos/projects/7/views/25).
Expand Down
2 changes: 1 addition & 1 deletion e2e/tests/wasm/grandpa_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func TestGrandpaTestSuite(t *testing.T) {

// TODO: this value should be passed in via the config file / CI, not hard coded in the test.
// This configuration can be handled in https://github.com/cosmos/ibc-go/issues/4697
if testsuite.IsCI() {
if testsuite.IsCI() && !testsuite.IsFork() {
t.Setenv(testsuite.ChainImageEnv, wasmSimdImage)
}

Expand Down
5 changes: 5 additions & 0 deletions e2e/testsuite/testconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,11 @@ func IsCI() bool {
return strings.ToLower(os.Getenv("CI")) == "true"
}

// IsFork returns true if the tests are running in fork mode, false is returned otherwise.
func IsFork() bool {
return strings.ToLower(os.Getenv("FORK")) == "true"
}

// ChainOptions stores chain configurations for the chains that will be
// created for the tests. They can be modified by passing ChainOptionConfiguration
// to E2ETestSuite.GetChains.
Expand Down
2 changes: 1 addition & 1 deletion modules/light-clients/08-wasm/types/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func NewMigrateProposalWrappedStore(subjectStore, substituteStore storetypes.KVS
}

// GetStore is a wrapper around getStore to allow the function to be directly called in tests.
func (ws migrateClientWrappedStore) GetStore(key []byte) storetypes.KVStore {
func (ws migrateClientWrappedStore) GetStore(key []byte) (storetypes.KVStore, bool) {
return ws.getStore(key)
}

Expand Down
83 changes: 61 additions & 22 deletions modules/light-clients/08-wasm/types/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package types
import (
"bytes"
"errors"
"fmt"
"io"
"reflect"
"strings"
Expand All @@ -29,13 +28,20 @@ var (
//
// Both stores are used for reads, but only the subjectStore is used for writes. For all operations, the key
// is checked to determine which store to use and must be prefixed with either "subject/" or "substitute/" accordingly.
// If the key is not prefixed with either "subject/" or "substitute/", a panic is thrown.
// If the key is not prefixed with either "subject/" or "substitute/", a default action is taken (e.g. no-op for Set/Delete).
type migrateClientWrappedStore struct {
subjectStore storetypes.KVStore
substituteStore storetypes.KVStore
}

func newMigrateClientWrappedStore(subjectStore, substituteStore storetypes.KVStore) migrateClientWrappedStore {
if subjectStore == nil {
panic(errors.New("subjectStore must not be nil"))
}
if substituteStore == nil {
panic(errors.New("substituteStore must not be nil"))
}

return migrateClientWrappedStore{
subjectStore: subjectStore,
substituteStore: substituteStore,
Expand All @@ -44,11 +50,17 @@ func newMigrateClientWrappedStore(subjectStore, substituteStore storetypes.KVSto

// Get implements the storetypes.KVStore interface. It allows reads from both the subjectStore and substituteStore.
//
// Get will panic if the key is not prefixed with either "subject/" or "substitute/".
// Get will return an empty byte slice if the key is not prefixed with either "subject/" or "substitute/".
func (ws migrateClientWrappedStore) Get(key []byte) []byte {
prefix, key := splitPrefix(key)

return ws.getStore(prefix).Get(key)
store, found := ws.getStore(prefix)
if !found {
// return a nil byte slice as KVStore.Get() does by default
return []byte(nil)
}

return store.Get(key)
}

// Has implements the storetypes.KVStore interface. It allows reads from both the subjectStore and substituteStore.
Expand All @@ -57,59 +69,75 @@ func (ws migrateClientWrappedStore) Get(key []byte) []byte {
func (ws migrateClientWrappedStore) Has(key []byte) bool {
prefix, key := splitPrefix(key)

return ws.getStore(prefix).Has(key)
store, found := ws.getStore(prefix)
if !found {
// return false as value when store is not found
return false
}

return store.Has(key)
}

// Set implements the storetypes.KVStore interface. It allows writes solely to the subjectStore.
//
// Set will panic if the key is not prefixed with "subject/".
// Set will no-op if the key is not prefixed with "subject/".
func (ws migrateClientWrappedStore) Set(key, value []byte) {
prefix, key := splitPrefix(key)
if !bytes.Equal(prefix, subjectPrefix) {
panic(fmt.Errorf("writes only allowed on subject store; key must be prefixed with \"%s\"", subjectPrefix))
return // no-op
}

ws.subjectStore.Set(key, value)
}

// Delete implements the storetypes.KVStore interface. It allows deletions solely to the subjectStore.
//
// Delete will panic if the key is not prefixed with "subject/".
// Delete will no-op if the key is not prefixed with "subject/".
func (ws migrateClientWrappedStore) Delete(key []byte) {
prefix, key := splitPrefix(key)
if !bytes.Equal(prefix, subjectPrefix) {
panic(fmt.Errorf("writes only allowed on subject store; key must be prefixed with \"%s\"", subjectPrefix))
return // no-op
}

ws.subjectStore.Delete(key)
}

// Iterator implements the storetypes.KVStore interface. It allows iteration over both the subjectStore and substituteStore.
//
// Iterator will panic if the start or end keys are not prefixed with either "subject/" or "substitute/".
// Iterator will return a closed iterator if the start or end keys are not prefixed with either "subject/" or "substitute/".
func (ws migrateClientWrappedStore) Iterator(start, end []byte) storetypes.Iterator {
prefixStart, start := splitPrefix(start)
prefixEnd, end := splitPrefix(end)

if !bytes.Equal(prefixStart, prefixEnd) {
panic(errors.New("start and end keys must be prefixed with the same prefix"))
return ws.closedIterator()
}

return ws.getStore(prefixStart).Iterator(start, end)
store, found := ws.getStore(prefixStart)
if !found {
return ws.closedIterator()
}

return store.Iterator(start, end)
}

// ReverseIterator implements the storetypes.KVStore interface. It allows iteration over both the subjectStore and substituteStore.
//
// ReverseIterator will panic if the start or end keys are not prefixed with either "subject/" or "substitute/".
// ReverseIterator will return a closed iterator if the start or end keys are not prefixed with either "subject/" or "substitute/".
func (ws migrateClientWrappedStore) ReverseIterator(start, end []byte) storetypes.Iterator {
prefixStart, start := splitPrefix(start)
prefixEnd, end := splitPrefix(end)

if !bytes.Equal(prefixStart, prefixEnd) {
panic(errors.New("start and end keys must be prefixed with the same prefix"))
return ws.closedIterator()
}

store, found := ws.getStore(prefixStart)
if !found {
return ws.closedIterator()
}

return ws.getStore(prefixStart).ReverseIterator(start, end)
return store.ReverseIterator(start, end)
}

// GetStoreType implements the storetypes.KVStore interface, it is implemented solely to satisfy the interface.
Expand All @@ -127,18 +155,29 @@ func (ws migrateClientWrappedStore) CacheWrapWithTrace(w io.Writer, tc storetype
return cachekv.NewStore(tracekv.NewStore(ws, w, tc))
}

// getStore returns the store to be used for the given key. If the key is prefixed with "subject/", the subjectStore
// is returned. If the key is prefixed with "substitute/", the substituteStore is returned.
// getStore returns the store to be used for the given key and a boolean flag indicating if that store was found.
// If the key is prefixed with "subject/", the subjectStore is returned. If the key is prefixed with "substitute/",
// the substituteStore is returned.
//
// If the key is not prefixed with either "subject/" or "substitute/", a panic is thrown.
func (ws migrateClientWrappedStore) getStore(prefix []byte) storetypes.KVStore {
// If the key is not prefixed with either "subject/" or "substitute/", a nil store is returned and the boolean flag is false.
func (ws migrateClientWrappedStore) getStore(prefix []byte) (storetypes.KVStore, bool) {
if bytes.Equal(prefix, subjectPrefix) {
return ws.subjectStore
return ws.subjectStore, true
} else if bytes.Equal(prefix, substitutePrefix) {
return ws.substituteStore
return ws.substituteStore, true
}

panic(fmt.Errorf("key must be prefixed with either \"%s\" or \"%s\"", subjectPrefix, substitutePrefix))
return nil, false
}

// closedIterator returns an iterator that is always closed, used when Iterator() or ReverseIterator() is called
// with an invalid prefix or start/end key.
func (ws migrateClientWrappedStore) closedIterator() storetypes.Iterator {
// Create a dummy iterator that is always closed right away.
it := ws.subjectStore.Iterator([]byte{0}, []byte{1})
it.Close()

return it
}

// splitPrefix splits the key into the prefix and the key itself, if the key is prefixed with either "subject/" or "substitute/".
Expand Down
Loading

0 comments on commit 8f21fc9

Please sign in to comment.