Skip to content

Commit

Permalink
Merge branch 'master' into jack/api
Browse files Browse the repository at this point in the history
  • Loading branch information
akhilkumarpilli committed Feb 3, 2021
2 parents dea3362 + 2f1a812 commit a237c8b
Show file tree
Hide file tree
Showing 51 changed files with 1,365 additions and 608 deletions.
3 changes: 3 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# CODEOWNERS: https://help.github.com/articles/about-codeowners/

* @colin-axner @fedekunze @AdityaSripal
4 changes: 2 additions & 2 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ further defined and clarified by project maintainers.
## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at [oss@iqlusion.io]. All
reported by contacting the project team at [community@interchain.io]. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Expand All @@ -71,4 +71,4 @@ This Code of Conduct is adapted from the [Contributor Covenant][homepage], versi
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html

[homepage]: https://www.contributor-covenant.org
[oss@iqlusion.io]: mailto:oss@iqlusion.io
[community@interchain.io]: mailto:community@interchain.io
18 changes: 15 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
VERSION := $(shell echo $(shell git describe --tags) | sed 's/^v//')
COMMIT := $(shell git log -1 --format='%H')
SDKCOMMIT := $(shell go list -m -u -f '{{.Version}}' github.com/cosmos/cosmos-sdk)
GAIA_VERSION := main
GAIA_VERSION := v4.0.0
AKASH_VERSION := jack/update-sdk
WASMD_VERSION := v0.14.1

GOPATH := $(shell go env GOPATH)
GOBIN := $(GOPATH)/bin

all: ci-lint install

###############################################################################
Expand Down Expand Up @@ -38,7 +43,7 @@ compile-clib:

install: go.sum
@echo "installing rly binary..."
@go build -mod=readonly $(BUILD_FLAGS) -o $${GOBIN-$${GOPATH-$$HOME/go}/bin}/rly main.go
@go build -mod=readonly $(BUILD_FLAGS) -o $(GOBIN)/rly main.go

###############################################################################
# Tests / CI
Expand Down Expand Up @@ -81,7 +86,14 @@ get-akash:
@mkdir -p ./chain-code/
@git clone --branch $(AKASH_VERSION) [email protected]:ovrclk/akash.git ./chain-code/akash

get-chains: get-gaia get-akash
get-chains: get-gaia get-akash get-wasmd

get-wasmd:
@mkdir -p ./chain-code/
@git clone --branch $(WASMD_VERSION) [email protected]:CosmWasm/wasmd.git ./chain-code/wasmd

build-wasmd:
@./scripts/build-wasmd

delete-chains:
@echo "Removing the ./chain-code/ directory..."
Expand Down
52 changes: 46 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
# Relayer

![GOZ](./docs/images/github-repo-banner.png)
![Relayer](./docs/images/github-repo-banner.gif)

![Relayer Build](https://github.com/cosmos/relayer/workflows/Build%20then%20run%20CI%20Chains/badge.svg)

The Cosmos IBC `relayer` package contains a basic relayer implementation that is
meant for users wishing to relay packets/data between sets of IBC enabled chains.
In addition, it is well documented and intended as an example where anyone who is
interested in building their own relayer can come for complete, working, examples.
In addition, it is intended as an example where anyone who is interested in building
their own relayer can come for complete, working, examples.

**NOTE:** The relayer is in alpha and is not production ready. If it is used in production,
it should always be run in a secure environment and only with just enough funds to
relay transactions. Security critical operations **should** manually verify that the
client identifier used in the configuration file corresponds to the correct initial
consensus state of the counterparty chain. This can be done by querying the initial
consensus state and the header of the counterparty and verifying that the root and
hash of the next validator set match. This can be considered equivalent to checking
the sha hash of a download or a GPG signature.

### Security Notice

If you would like to report a security critical bug related to the relayer repo, please send an email to [`[email protected]`](mailto:[email protected])

## Code of Conduct

The iqlusion team is dedicated to providing an inclusive and harassment free experience for contributors. Please visit [Code of Conduct](CODE_OF_CONDUCT.md) for more information.
The Cosmos community is dedicated to providing an inclusive and harassment free experience for contributors. Please visit [Code of Conduct](CODE_OF_CONDUCT.md) for more information.

## Testnet

Expand All @@ -29,6 +37,38 @@ If you would like to join a relayer testnet, please [check out the instructions]
|-------|--------|----------------|
| [`gaia`](https://github.com/cosmos/gaia) | ![gaia](https://github.com/cosmos/relayer/workflows/TESTING%20-%20gaia%20to%20gaia%20integration/badge.svg) | `transfer` |

## Features

The relayer supports the following:
- creating/updating IBC Tendermint light clients
- creating IBC connections
- creating IBC transfer channels.
- initiating a cross chain transfer
- relaying a cross chain transfer transaction, its acknowledgement, and timeouts
- relaying from state
- relaying from streaming events
- sending an UpgradePlan proposal for an IBC breaking upgrade
- upgrading clients after a counterparty chain has performed an upgrade for IBC breaking changes

The relayer currently cannot:
- create clients with user chosen parameters (such as UpgradePath)
- submit IBC client unfreezing proposals
- monitor and submit misbehaviour for clients
- use IBC light clients other than Tendermint such as Solo Machine
- connect to chains which don't implement/enable IBC
- connect to chains using a different IBC implementation (chains not using SDK's `x/ibc` module)

## Relayer Terminology

A Path in the relayer represents one very specific path followed to get from one chain to another.
Two chains may have many different paths between them. Any path with different clients, connections,
or channels are considered unqiuely different and non-fungible.

When using with live networks, it is advised to pre-select your desired parameters for your client,
connection, and channel. The relayer will automatically reuse any existing clients that match your
configurations since clients, connections, and channels are public goods (no one has control over
them).

## Demoing the Relayer

![Demo](./docs/images/demo.gif)
Expand Down Expand Up @@ -75,7 +115,7 @@ $ rly q bal ibc-0
$ rly q bal ibc-1

# Send the tokens back to the account on ibc-0
$ rly tx xfer ibc-1 ibc-0 1000000transfer/ibczeroxfer/samoleans $(rly ch addr ibc-0)
$ rly tx xfer ibc-1 ibc-0 1000000ibc/27A6394C3F9FF9C9DCF5DFFADF9BB5FE9A37C7E92B006199894CF1824DF9AC7C $(rly ch addr ibc-0)
$ rly tx rly demo -d

# See that the return trip has completed
Expand Down
3 changes: 3 additions & 0 deletions clib/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ var clibPort = 0
var replies = map[int]chan goReturn{}
var lastReply = 0

//nolint:golint
//export RunClib
func RunClib(nodePort C.int, toNode C.sendFunc, clibArgs []*C.char) C.int {
if relayer.SendToController == nil {
Expand Down Expand Up @@ -75,6 +76,7 @@ func RunClib(nodePort C.int, toNode C.sendFunc, clibArgs []*C.char) C.int {
return C.int(clibPort)
}

//nolint:golint
//export ReplyToClib
func ReplyToClib(replyPort C.int, isError C.int, str C.Body) C.int {
goStr := C.GoString(str)
Expand All @@ -92,6 +94,7 @@ func ReplyToClib(replyPort C.int, isError C.int, str C.Body) C.int {
return C.int(0)
}

//nolint:golint
//export SendToClib
func SendToClib(port C.int, str C.Body) C.Body {
goStr := C.GoString(str)
Expand Down
158 changes: 150 additions & 8 deletions cmd/config.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*
Package cmd includes relayer commands
Copyright © 2020 Jack Zampolin [email protected]
Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -32,7 +33,9 @@ import (
)

const (
ORDERED = "ORDERED"
// ORDERED is exported channel type constant
ORDERED = "ORDERED"
// UNORDERED is exported channel type constant
UNORDERED = "UNORDERED"
defaultOrder = ORDERED
defaultVersion = "ics20-1"
Expand Down Expand Up @@ -77,17 +80,36 @@ $ %s cfg list`, appName, defaultHome, appName)),
return fmt.Errorf("config does not exist: %s", cfgPath)
}

out, err := yaml.Marshal(config)
jsn, err := cmd.Flags().GetBool(flagJSON)
if err != nil {
return err
}

fmt.Println(string(out))
return nil
yml, err := cmd.Flags().GetBool(flagYAML)
if err != nil {
return err
}
switch {
case yml && jsn:
return fmt.Errorf("can't pass both --json and --yaml, must pick one")
case jsn:
out, err := json.Marshal(config)
if err != nil {
return err
}
fmt.Println(string(out))
return nil
default:
out, err := yaml.Marshal(config)
if err != nil {
return err
}
fmt.Println(string(out))
return nil
}
},
}

return cmd
return yamlFlag(jsonFlag(cmd))
}

// Command for inititalizing an empty config at the --home location
Expand Down Expand Up @@ -218,15 +240,17 @@ func cfgFilesAdd(dir string) (cfg *Config, err error) {
}

pthName := strings.Split(f.Name(), ".")[0]
if err = config.ValidatePath(p); err != nil {
fmt.Printf("%s: %s\n", pth, err.Error())
continue
}
if err = cfg.AddPath(pthName, p); err != nil {
fmt.Printf("%s: %s\n", pth, err.Error())
continue
}

// TODO: Do bottom up validation
// For now, we assume that all chain files must have same filename as chain-id
// this is to ensure non-chain files (global config) does not get parsed into chain struct.
// Future work should implement bottom-up validation.
if c.ChainID != pthName {
fmt.Printf("Skipping non chain file: %s\n", f.Name())
continue
Expand Down Expand Up @@ -414,3 +438,121 @@ func overWriteConfig(cfg *Config) (err error) {
}
return err
}

// ValidatePath checks that a path is valid
func (c *Config) ValidatePath(p *relayer.Path) (err error) {
if p.Src.Version == "" {
return fmt.Errorf("source must specify a version")
}
if err = c.ValidatePathEnd(p.Src); err != nil {
return err
}
if err = c.ValidatePathEnd(p.Dst); err != nil {
return err
}
if _, err = p.GetStrategy(); err != nil {
return err
}
if p.Src.Order != p.Dst.Order {
return fmt.Errorf("both sides must have same order ('ORDERED' or 'UNORDERED'), got src(%s) and dst(%s)",
p.Src.Order, p.Dst.Order)
}
return nil
}

// ValidatePathEnd validates provided pathend and returns error for invalid identifiers
func (c *Config) ValidatePathEnd(pe *relayer.PathEnd) error {
if err := pe.ValidateBasic(); err != nil {
return err
}

chain, err := c.Chains.Get(pe.ChainID)
if err != nil {
return err
}

height, err := chain.QueryLatestHeight()
if err != nil {
return err
}

if pe.ClientID != "" {
if err := c.ValidateClient(chain, height, pe); err != nil {
return err
}

if pe.ConnectionID != "" {
if err := c.ValidateConnection(chain, height, pe); err != nil {
return err
}

if pe.ChannelID != "" {
if err := c.ValidateChannel(chain, height, pe); err != nil {
return err
}
}
}

if pe.ConnectionID == "" && pe.ChannelID != "" {
return fmt.Errorf("connectionID is not configured for the channel: %s", pe.ChannelID)
}
}

if pe.ClientID == "" && pe.ConnectionID != "" {
return fmt.Errorf("clientID is not configured for the connection: %s", pe.ConnectionID)
}

return nil
}

// ValidateClient validates client id in provided pathend
func (c *Config) ValidateClient(chain *relayer.Chain, height int64, pe *relayer.PathEnd) error {
if err := pe.Vclient(); err != nil {
return err
}

_, err := chain.QueryClientState(height)
if err != nil {
return err
}

return nil
}

// ValidateConnection validates connection id in provided pathend
func (c *Config) ValidateConnection(chain *relayer.Chain, height int64, pe *relayer.PathEnd) error {
if err := pe.Vconn(); err != nil {
return err
}

connection, err := chain.QueryConnection(height)
if err != nil {
return err
}

if connection.Connection.ClientId != pe.ClientID {
return fmt.Errorf("clientID of connection: %s didn't match with provided ClientID", pe.ConnectionID)
}

return nil
}

// ValidateChannel validates channel id in provided pathend
func (c *Config) ValidateChannel(chain *relayer.Chain, height int64, pe *relayer.PathEnd) error {
if err := pe.Vchan(); err != nil {
return err
}

channel, err := chain.QueryChannel(height)
if err != nil {
return err
}

for _, connection := range channel.Channel.ConnectionHops {
if connection == pe.ConnectionID {
return nil
}
}

return fmt.Errorf("connectionID of channel: %s didn't match with provided ConnectionID", pe.ChannelID)
}
Loading

0 comments on commit a237c8b

Please sign in to comment.