Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update relayer module & handler interface; loopback; closure handling; proto3 schemas #152

Merged
merged 22 commits into from
Jul 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ jobs:
- run: sudo apt-get update && sudo apt-get -y install nodejs npm && sudo npm install codedown typescript tslint -g
- run: make check_syntax

check_proto:
<<: *linux_defaults
steps:
- checkout
- run: sudo apt-get update && sudo apt-get -y install protobuf-compiler
- run: make check_proto

workflows:
version: 2
test-suite:
Expand All @@ -40,3 +47,4 @@ workflows:
- check_links
- check_sections
- check_syntax
- check_proto
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ $(TOPTARGETS): $(SUBDIRS)
$(SUBDIRS):
$(MAKE) -C $@ $(MAKECMDGOALS)

check: check_links check_dependencies check_syntax check_sections
check: check_links check_dependencies check_syntax check_sections check_proto

check_links:
python ./scripts/check_links.py
Expand All @@ -19,7 +19,10 @@ check_syntax:
check_sections:
python ./scripts/check_sections.py

check_proto:
$(MAKE) -C spec/ics-026-relayer-module check_proto

spec_pdf:
pandoc --pdf-engine=xelatex --template eisvogel --filter pandoc-include --mathjax --toc --number-sections -o spec.pdf spec.pdc

.PHONY: $(TOPTARGETS) $(SUBDIRS) check check_links check_dependencies check_syntax check_sections spec_pdf
.PHONY: $(TOPTARGETS) $(SUBDIRS) check check_links check_dependencies check_syntax check_sections check_proto spec_pdf
Binary file modified spec.pdf
Binary file not shown.
6 changes: 3 additions & 3 deletions spec/ics-002-consensus-verification/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -282,9 +282,9 @@ activity on the client. Frozen client SHOULD NOT be deleted from the state, as a
method can be introduced in the future versions.

```typescript
function freezeClient(id: Identifier, h1: Header, h2: Header) {
consensusState = get(consensusStateKey(id))
assert(consensusState.equivocationPredicate(h1, h2))
function freezeClient(identifier: Identifier, firstHeader: Header, secondHeader: Header) {
consensusState = get(consensusStateKey(identifier))
assert(consensusState.equivocationPredicate(firstHeader, secondHeader))
set(frozenKey(id), true)
}
```
Expand Down
112 changes: 49 additions & 63 deletions spec/ics-003-connection-semantics/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,36 @@ function connectionKey(id: Identifier): Key {
}
```

A reverse mapping from clients to a set of connections (utilized to look up all connections using a client) is stored under a unique prefix per-client:

```typescript
function clientConnectionsKey(clientIdentifier: Identifier): Key {
return "clients/{clientIdentifier}/connections"
}
```

### Helper functions

`addConnectionToClient` is used to add a connection identifier to the set of connections associated with a client.

```typescript
function addConnectionToClient(clientIdentifier: Identifier, connectionIdentifier: Identifier) {
conns = get(clientConnectionsKey(clientIdentifier, connectionIdentifier))
conns.add(connectionIdentifier)
set(clientConnectionsKey(clientIdentifier, connectionIdentifier), conns)
}
```

`removeConnectionFromClient` is used to remove a connection identifier from the set of connections associated with a client.

```
function removeConnectionFromClient(clientIdentifier: Identifier, connectionIdentifier: Identifier) {
conns = get(clientConnectionsKey(clientIdentifier, connectionIdentifier))
conns.remove(connectionIdentifier)
set(clientConnectionsKey(clientIdentifier, connectionIdentifier), conns)
}
```

### Subprotocols

This ICS defines two subprotocols: opening handshake and closing handshake. Header tracking and closing-by-equivocation are defined in [ICS 2](../ics-002-consensus-verification). Datagrams defined herein are handled as external messages by the IBC relayer module defined in [ICS 26](../ics-026-relayer-module).
Expand Down Expand Up @@ -134,6 +164,7 @@ function connOpenInit(
connection = ConnectionEnd{state, desiredCounterpartyConnectionIdentifier, clientIdentifier,
counterpartyClientIdentifier, nextTimeoutHeight}
set(connectionKey(identifier), connection)
addConnectionToClient(clientIdentifier, identifier)
}
```

Expand All @@ -160,6 +191,7 @@ function connOpenTry(
connection = ConnectionEnd{state, counterpartyConnectionIdentifier, clientIdentifier,
counterpartyClientIdentifier, nextTimeoutHeight}
set(connectionKey(identifier), connection)
addConnectionToClient(clientIdentifier, identifier)
}
```

Expand Down Expand Up @@ -242,6 +274,7 @@ function connOpenTimeout(
))
}
delete(connectionKey(identifier))
removeConnectionFromClient(clientIdentifier, identifier)
}
```

Expand All @@ -268,87 +301,31 @@ A correct protocol execution flows as follows (note that all calls are made thro
*ConnCloseInit* initializes a close attempt on chain A.

```typescript
function connCloseInit(identifier: Identifier, nextTimeoutHeight: uint64) {
function connCloseInit(identifier: Identifier) {
connection = get(connectionKey(identifier))
assert(connection.state === OPEN)
connection.state = CLOSETRY
connection.nextTimeoutHeight = nextTimeoutHeight
set(connectionKey(identifier), connection)
}
```

*ConnCloseTry* relays the intent to close a connection from chain A to chain B.

```typescript
function connCloseTry(
identifier: Identifier, proofInit: CommitmentProof, proofHeight: uint64,
timeoutHeight: uint64, nextTimeoutHeight: uint64) {
assert(getConsensusState().getHeight() <= timeoutHeight)
connection = get(connectionKey(identifier))
assert(connection.state === OPEN)
counterpartyStateRoot = get(rootKey(connection.clientIdentifier, proofHeight))
expected = ConnectionEnd{CLOSETRY, identifier, connection.counterpartyClientIdentifier,
connection.clientIdentifier, timeoutHeight}
assert(verifyMembership(counterpartyStateRoot, proofInit, connectionKey(counterpartyConnectionIdentifier), expected))
connection.state = CLOSED
connection.nextTimeoutHeight = nextTimeoutHeight
set(connectionKey(identifier), connection)
}
```

*ConnCloseAck* acknowledges a connection closure on chain B.
*ConnCloseConfirm* relays the intent to close a connection from chain A to chain B.

```typescript
function connCloseAck(
identifier: Identifier, proofTry: CommitmentProof,
proofHeight: uint64, timeoutHeight: uint64) {
function connCloseConfirm(
identifier: Identifier, proofInit: CommitmentProof, proofHeight: uint64) {
assert(getConsensusState().getHeight() <= timeoutHeight)
connection = get(connectionKey(identifier))
assert(connection.state === CLOSETRY)
assert(connection.state === OPEN)
counterpartyStateRoot = get(rootKey(connection.clientIdentifier, proofHeight))
expected = ConnectionEnd{CLOSED, identifier, connection.counterpartyClientIdentifier,
connection.clientIdentifier, timeoutHeight}
assert(verifyMembership(counterpartyStateRoot, proofTry, connectionKey(counterpartyConnectionIdentifier), expected))
connection.clientIdentifier, 0}
assert(verifyMembership(counterpartyStateRoot, proofInit, connectionKey(counterpartyConnectionIdentifier), expected))
connection.state = CLOSED
connection.nextTimeoutHeight = 0
set(connectionKey(identifier), connection)
}
```

*ConnCloseTimeout* aborts a connection closing attempt due to a timeout on the other side and reopens the connection.

```typescript
function connCloseTimeout(
identifier: Identifier, proofTimeout: CommitmentProof,
proofHeight: uint64, timeoutHeight: uint64) {
connection = get(connectionKey(identifier))
counterpartyStateRoot = get(rootKey(connection.clientIdentifier, proofHeight))
assert(proofHeight > connection.nextTimeoutHeight)
switch state {
case CLOSETRY:
expected = ConnectionEnd{OPEN, identifier, connection.counterpartyClientIdentifier,
connection.clientIdentifier, timeoutHeight}
assert(verifyMembership(
counterpartyStateRoot, proofTimeout,
connectionKey(counterpartyConnectionIdentifier), expected
))
connection.state = OPEN
connection.nextTimeoutHeight = 0
set(connectionKey(identifier), connection)
case CLOSED:
expected = ConnectionEnd{CLOSETRY, identifier, connection.counterpartyClientIdentifier,
connection.clientIdentifier, timeoutHeight}
assert(verifyMembership(
counterpartyStateRoot, proofTimeout,
connectionKey(counterpartyConnectionIdentifier), expected
))
connection.state = OPEN
connection.nextTimeoutHeight = 0
set(connectionKey(identifier), connection)
}
}
```

#### Freezing by Equivocation

The equivocation detection subprotocol is defined in [ICS 2](../ics-002-consensus-verification). If a client is frozen by equivocation, all associated connections are immediately frozen as well.
Expand All @@ -365,6 +342,14 @@ function queryConnection(id: Identifier): ConnectionEnd | void {
}
```

Connections associated with a particular client can be queried by client identifier with `queryClientConnections`.

```typescript
function queryClientConnections(id: Identifier): Set<Identifier> {
return get(clientConnectionsKey(id))
}
```

## Backwards Compatibility

Not applicable.
Expand All @@ -389,6 +374,7 @@ Parts of this document were inspired by the [previous IBC specification](https:/

29 March 2019 - Initial draft version submitted
17 May 2019 - Draft finalized
29 July 2019 - Revisions to track connection set associated with client

## Copyright

Expand Down
22 changes: 11 additions & 11 deletions spec/ics-004-channel-and-packet-semantics/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ category: ibc-core
requires: 2, 3, 5, 23, 24
author: Christopher Goes <cwgoes@tendermint.com>
created: 2019-03-07
modified: 2019-06-05
modified: 2019-06-29
---

## Synopsis
Expand Down Expand Up @@ -367,13 +367,12 @@ function chanOpenTimeout(

##### Closing handshake

The `chanClose` function is called by either module to close their end of the channel.
The `chanCloseInit` function is called by either module to close their end of the channel.

Calling modules MAY atomically execute appropriate application logic in conjunction with calling `chanClose`.
Calling modules MAY atomically execute appropriate application logic in conjunction with calling `chanCloseInit`.

```typescript
function chanClose(
portIdentifier: Identifier, channelIdentifier: Identifier) {
function chanCloseInit(portIdentifier: Identifier, channelIdentifier: Identifier) {
channel = get(channelKey(portIdentifier, channelIdentifier))
assert(channel.state === OPEN)
connection = get(connectionKey(channel.connectionHops[0]))
Expand All @@ -391,7 +390,7 @@ Calling modules MAY atomically execute appropriate application logic in conjunct
```typescript
function chanCloseConfirm(
portIdentifier: Identifier, channelIdentifier: Identifier,
proof: CommitmentProof, proofHeight: uint64) {
proofInit: CommitmentProof, proofHeight: uint64) {
channel = get(channelKey(portIdentifier, channelIdentifier))
assert(channel.state === OPEN)
connection = get(connectionKey(channel.connectionHops[0]))
Expand Down Expand Up @@ -566,7 +565,7 @@ function timeoutPacketOrdered(packet: Packet, proof: CommitmentProof, proofHeigh
assert(packet.destChannel === channel.counterpartyChannelIdentifier)

connection = get(connectionKey(packet.connectionHops[0]))
assert(connection.state === OPEN)
// note: the connection may have been closed
assert(packet.destPort === channel.counterpartyPortIdentifier)
assert(packet.connectionHops === channel.connectionHops)

Expand Down Expand Up @@ -614,7 +613,7 @@ function timeoutPacketUnordered(packet: Packet, proof: CommitmentProof, proofHei
assert(packet.destChannel === channel.counterpartyChannelIdentifier)

connection = get(connectionKey(packet.connectionHops[0]))
assert(connection.state === OPEN)
// note: the connection may have been closed
assert(packet.destPort === channel.counterpartyPortIdentifier)
assert(packet.connectionHops === channel.connectionHops)

Expand Down Expand Up @@ -656,7 +655,7 @@ function timeoutClose(packet: Packet, proof: CommitmentProof, proofHeight: uint6
assert(packet.sourceChannel === channel.counterpartyChannelIdentifier)

connection = get(connectionKey(channel.connectionHops[0]))
assert(connection.state === OPEN)
// note: the connection may have been closed
assert(packet.sourcePort === channel.counterpartyPortIdentifier)
assert(packet.connectionHops === channel.connectionHops)

Expand Down Expand Up @@ -693,7 +692,7 @@ function cleanupPacketOrdered(packet: Packet, proof: CommitmentProof, proofHeigh
assert(packet.destChannel === channel.counterpartyChannelIdentifier)

connection = get(connectionKey(packet.connectionHops[0]))
assert(connection.state === OPEN)
// note: the connection may have been closed
assert(packet.destPort === channel.counterpartyPortIdentifier)
assert(packet.connectionHops === channel.connectionHops)

Expand Down Expand Up @@ -730,7 +729,7 @@ function cleanupPacketUnordered(packet: Packet, proof: CommitmentProof, proofHei
assert(packet.destChannel === channel.counterpartyChannelIdentifier)

connection = get(connectionKey(packet.connectionHops[0]))
assert(connection.state === OPEN)
// note: the connection may have been closed
assert(packet.destPort === channel.counterpartyPortIdentifier)
assert(packet.connectionHops === channel.connectionHops)

Expand Down Expand Up @@ -784,6 +783,7 @@ Coming soon.
5 June 2019 - Draft submitted
4 July 2019 - Modifications for unordered channels & acknowledgements
16 July 2019 - Alterations for multi-hop routing future compatibility
29 July 2019 - Revisions to handle timeouts after connection closure

## Copyright

Expand Down
Loading