Skip to content

Commit

Permalink
Merge PR cosmos#121: Unification & cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
cwgoes authored Jun 9, 2019
1 parent 90bcc82 commit d823635
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 117 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ All standards in the "draft" stage are listed here in order of their ICS numbers
| [18](spec/ics-018-relayer-algorithms) | Relayer Algorithms | Draft |
| [23](spec/ics-023-vector-commitments) | Vector Commitments | Draft |
| [24](spec/ics-024-host-requirements) | Host Requirements | Draft |
| [25](spec/ics-025-handler-interface) | Handler Interface | Draft |
| [26](spec/ics-026-relayer-module) | Relayer Module | Draft |

## Standard Dependency Visualization
Expand Down
2 changes: 2 additions & 0 deletions ibc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ For an overview of the IBC protocol, read the following documents in numerical o
1. [IBC Terminology](./3_IBC_TERMINOLOGY.md)
1. [IBC Usecases](./4_IBC_USECASES.md)
1. [IBC Design Patterns](./5_IBC_DESIGN_PATTERNS.md)

You might also be interested in the [research compilation](./RESEARCH.md).
5 changes: 5 additions & 0 deletions ibc/RESEARCH.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Possibly Relevant Research

## Multi-chain routing & state transition atomicity

- [Anonymous Multi-Hop Locks for Blockchain Scalability and Interoperability](https://eprint.iacr.org/2018/472.pdf) - analyzes the lightning network, but possibly relevant.
162 changes: 89 additions & 73 deletions spec/ics-003-connection-semantics/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,8 @@ ics: 3
title: Connection Semantics
stage: draft
category: ibc-core
<<<<<<< HEAD
requires: 23, 24
required-by: 25
=======
requires: 2, 23, 24
<<<<<<< HEAD:spec/ics-3-connection-semantics/README.md
>>>>>>> master
=======
required-by: 4
>>>>>>> master:spec/ics-003-connection-semantics/README.md
required-by: 4, 25
author: Christopher Goes <cwgoes@tendermint.com>, Juwoon Yun <joon@tendermint.com>
created: 2019-03-07
modified: 2019-05-17
Expand Down Expand Up @@ -72,7 +64,7 @@ Once a negotiation handshake has completed:

### Data Structures

This ICS defines the `Connection` type:
This ICS defines the `ConnectionState` and `ConnectionEnd` types:

```typescript
enum ConnectionState {
Expand All @@ -85,15 +77,25 @@ enum ConnectionState {
```

```typescript
interface Connection {
interface ConnectionEnd {
state: ConnectionState
counterpartyIdentifier: Identifier
counterpartyConnectionIdentifier: Identifier
clientIdentifier: Identifier
counterpartyClientIdentifier: Identifier
nextTimeoutHeight: uint64
}
```

### Store keys

Connection keys are stored under a unique identifier.

```typescript
function connectionKey(id: Identifier): Key {
return "connections/{id}"
}
```

### 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 @@ -125,36 +127,38 @@ This subprotocol need not be permissioned, modulo anti-spam measures.

```typescript
function connOpenInit(
identifier: Identifier, desiredCounterpartyIdentifier: Identifier,
identifier: Identifier, desiredCounterpartyConnectionIdentifier: Identifier,
clientIdentifier: Identifier, counterpartyClientIdentifier: Identifier, nextTimeoutHeight: uint64) {
assert(get("connections/{identifier}") == null)
assert(get(connectionKey(identifier)) == null)
state = INIT
connection = Connection{state, desiredCounterpartyIdentifier, clientIdentifier,
connection = ConnectionEnd{state, desiredCounterpartyConnectionIdentifier, clientIdentifier,
counterpartyClientIdentifier, nextTimeoutHeight}
set("connections/{identifier}", connection)
set(connectionKey(identifier), connection)
}
```

*ConnOpenTry* relays notice of a connection attempt on chain A to chain B.

```typescript
function connOpenTry(
desiredIdentifier: Identifier, counterpartyIdentifier: Identifier,
desiredIdentifier: Identifier, counterpartyConnectionIdentifier: Identifier,
counterpartyClientIdentifier: Identifier, clientIdentifier: Identifier,
proofInit: CommitmentProof, timeoutHeight: uint64, nextTimeoutHeight: uint64) {
assert(getConsensusState().getHeight() <= timeoutHeight)
consensusState = get("clients/{clientIdentifier}")
consensusState = get(consensusStateKey(clientIdentifier))
expectedConsensusState = getConsensusState()
expected = Connection{INIT, desiredIdentifier, counterpartyClientIdentifier, clientIdentifier, timeoutHeight}
assert(verifyMembership(consensusState.getRoot(), proofInit, "connections/{counterpartyIdentifier}", expected))
expected = ConnectionEnd{INIT, desiredIdentifier, counterpartyClientIdentifier, clientIdentifier, timeoutHeight}
assert(verifyMembership(consensusState.getRoot(), proofInit,
connectionKey(counterpartyConnectionIdentifier), expected))
assert(verifyMembership(consensusState.getRoot(), proofInit,
"clients/{counterpartyClientIdentifier}", expectedConsensusState))
assert(get("connections/{desiredIdentifier}") === null)
consensusStateKey(counterpartyClientIdentifier),
expectedConsensusState))
assert(get(connectionKey(desiredIdentifier)) === null)
identifier = desiredIdentifier
state = TRYOPEN
connection = Connection{state, counterpartyIdentifier, clientIdentifier,
counterpartyClientIdentifier, nextTimeoutHeight}
set("connections/{identifier}", connection)
connection = ConnectionEnd{state, counterpartyConnectionIdentifier, clientIdentifier,
counterpartyClientIdentifier, nextTimeoutHeight}
set(connectionKey(identifier), connection)
}
```

Expand All @@ -165,18 +169,19 @@ function connOpenAck(
identifier: Identifier, proofTry: CommitmentProof,
timeoutHeight: uint64, nextTimeoutHeight: uint64) {
assert(getConsensusState().getHeight() <= timeoutHeight)
connection = get("connections/{identifier}")
connection = get(connectionKey(identifier))
assert(connection.state === INIT)
consensusState = get("clients/{connection.clientIdentifier}")
consensusState = get(consensusStateKey(connection.clientIdentifier))
expectedConsensusState = getConsensusState()
expected = Connection{TRYOPEN, identifier, connection.counterpartyClientIdentifier,
connection.clientIdentifier, timeoutHeight}
assert(verifyMembership(consensusState, proofTry, "connections/{connection.counterpartyIdentifier}", expected))
expected = ConnectionEnd{TRYOPEN, identifier, connection.counterpartyClientIdentifier,
connection.clientIdentifier, timeoutHeight}
assert(verifyMembership(consensusState, proofTry,
connectionKey(connection.counterpartyConnectionIdentifier), expected))
assert(verifyMembership(consensusState, proofTry,
"clients/{connection.counterpartyClientIdentifier}", expectedConsensusState))
consensusStateKey(connection.counterpartyClientIdentifier), expectedConsensusState))
connection.state = OPEN
connection.nextTimeoutHeight = nextTimeoutHeight
set("connections/{identifier}", connection)
set(connectionKey(identifier), connection)
}
```

Expand All @@ -185,52 +190,53 @@ function connOpenAck(
```typescript
function connOpenConfirm(identifier: Identifier, proofAck: CommitmentProof, timeoutHeight: uint64)
assert(getConsensusState().getHeight() <= timeoutHeight)
connection = get("connections/{identifier}")
connection = get(connectionKey(identifier))
assert(connection.state === TRYOPEN)
consensusState = get("clients/{connection.clientIdentifier}")
expected = Connection{OPEN, identifier, connection.counterpartyClientIdentifier,
Gconnection.clientIdentifier, timeoutHeight}
assert(verifyMembership(consensusState, proofAck, "connections/{connection.counterpartyIdentifier}", expected))
consensusState = get(consensusStateKey(connection.clientIdentifier))
expected = ConnectionEnd{OPEN, identifier, connection.counterpartyClientIdentifier,
connection.clientIdentifier, timeoutHeight}
assert(verifyMembership(consensusState, proofAck,
connectionKey(connection.counterpartyConnectionIdentifier), expected))
connection.state = OPEN
connection.nextTimeoutHeight = 0
set("connections/{identifier}", connection)
set(connectionKey(identifier), connection)
```
*ConnOpenTimeout* aborts a connection opening attempt due to a timeout on the other side.
```typescript
function connOpenTimeout(identifier: Identifier, proofTimeout: CommitmentProof, timeoutHeight: uint64) {
connection = get("connections/{identifier}")
consensusState = get("clients/{connection.clientIdentifier}")
connection = get(connectionKey(identifier))
consensusState = get(consensusStateKey(connection.clientIdentifier))
assert(consensusState.getHeight() > connection.nextTimeoutHeight)
switch state {
case INIT:
assert(verifyNonMembership(
consensusState, proofTimeout,
"connections/{connection.counterpartyIdentifier}"))
connectionKey(connection.counterpartyConnectionIdentifier)))
case TRYOPEN:
assert(
verifyMembership(
consensusState, proofTimeout,
"connections/{connection.counterpartyIdentifier}",
Connection{INIT, identifier, connection.counterpartyClientIdentifier,
connection.clientIdentifier, timeoutHeight}
connectionKey(connection.counterpartyConnectionIdentifier),
ConnectionEnd{INIT, identifier, connection.counterpartyClientIdentifier,
connection.clientIdentifier, timeoutHeight}
)
||
verifyNonMembership(
consensusState, proofTimeout,
"connections/{connection.counterpartyIdentifier}"
connectionKey(connection.counterpartyConnectionIdentifier)
)
)
case OPEN:
assert(verifyMembership(
consensusState, proofTimeout,
"connections/{connection.counterpartyIdentifier}",
Connection{TRYOPEN, identifier, connection.counterpartyClientIdentifier,
connection.clientIdentifier, timeoutHeight}
connectionKey(connection.counterpartyConnectionIdentifier),
ConnectionEnd{TRYOPEN, identifier, connection.counterpartyClientIdentifier,
connection.clientIdentifier, timeoutHeight}
))
}
delete("connections/{identifier}")
delete(connectionKey(identifier))
}
```
Expand Down Expand Up @@ -258,11 +264,11 @@ A correct protocol execution flows as follows (note that all calls are made thro
```typescript
function connCloseInit(identifier: Identifier, nextTimeoutHeight: uint64) {
connection = get("connections/{identifier}")
connection = get(connectionKey(identifier))
assert(connection.state === OPEN)
connection.state = CLOSETRY
connection.nextTimeoutHeight = nextTimeoutHeight
set("connections/{identifier}", connection)
set(connectionKey(identifier), connection)
}
```
Expand All @@ -273,15 +279,15 @@ function connCloseTry(
identifier: Identifier, proofInit: CommitmentProof,
timeoutHeight: uint64, nextTimeoutHeight: uint64) {
assert(getConsensusState().getHeight() <= timeoutHeight)
connection = get("connections/{identifier}")
connection = get(connectionKey(identifier))
assert(connection.state === OPEN)
consensusState = get("clients/{connection.clientIdentifier}")
expected = Connection{CLOSETRY, identifier, connection.counterpartyClientIdentifier,
connection.clientIdentifier, timeoutHeight}
assert(verifyMembership(consensusState, proofInit, "connections/{counterpartyIdentifier}", expected))
consensusState = get(consensusStateKey(connection.clientIdentifier))
expected = ConnectionEnd{CLOSETRY, identifier, connection.counterpartyClientIdentifier,
connection.clientIdentifier, timeoutHeight}
assert(verifyMembership(consensusState, proofInit, connectionKey(counterpartyConnectionIdentifier), expected))
connection.state = CLOSED
connection.nextTimeoutHeight = nextTimeoutHeight
set("connections/{identifier}", connection)
set(connectionKey(identifier), connection)
}
```
Expand All @@ -290,46 +296,46 @@ function connCloseTry(
```typescript
function connCloseAck(identifier: Identifier, proofTry: CommitmentProof, timeoutHeight: uint64) {
assert(getConsensusState().getHeight() <= timeoutHeight)
connection = get("connections/{identifier}")
connection = get(connectionKey(identifier))
assert(connection.state === CLOSETRY)
consensusState = get("clients/{connection.clientIdentifier}")
expected = Connection{CLOSED, identifier, connection.counterpartyClientIdentifier,
connection.clientIdentifier, timeoutHeight}
assert(verifyMembership(consensusState, proofTry, "connections/{counterpartyIdentifier}", expected))
consensusState = get(consensusStateKey(connection.clientIdentifier))
expected = ConnectionEnd{CLOSED, identifier, connection.counterpartyClientIdentifier,
connection.clientIdentifier, timeoutHeight}
assert(verifyMembership(consensusState, proofTry, connectionKey(counterpartyConnectionIdentifier), expected))
connection.state = CLOSED
connection.nextTimeoutHeight = 0
set("connections/{identifier}", connection)
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, timeoutHeight: uint64) {
connection = get("connections/{identifier}")
consensusState = get("clients/{connection/clientIdentifier}")
connection = get(connectionKey(identifier))
consensusState = get(consensusStateKey(connection.clientIdentifier))
assert(consensusState.getHeight() > connection.nextTimeoutHeight)
switch state {
case CLOSETRY:
expected = Connection{OPEN, identifier, connection.counterpartyClientIdentifier,
connection.clientIdentifier, timeoutHeight}
expected = ConnectionEnd{OPEN, identifier, connection.counterpartyClientIdentifier,
connection.clientIdentifier, timeoutHeight}
assert(verifyMembership(
consensusState, proofTimeout,
"connections/{counterpartyIdentifier}", expected
connectionKey(counterpartyConnectionIdentifier), expected
))
connection.state = OPEN
connection.nextTimeoutHeight = 0
set("connections/{identifier}", connection)
set(connectionKey(identifier), connection)
case CLOSED:
expected = Connection{CLOSETRY, identifier, connection.counterpartyClientIdentifier,
connection.clientIdentifier, timeoutHeight}
expected = ConnectionEnd{CLOSETRY, identifier, connection.counterpartyClientIdentifier,
connection.clientIdentifier, timeoutHeight}
assert(verifyMembership(
consensusState, proofTimeout,
"connections/{counterpartyIdentifier}", expected
connectionKey(counterpartyConnectionIdentifier), expected
))
connection.state = OPEN
connection.nextTimeoutHeight = 0
set("connections/{identifier}", connection)
set(connectionKey(identifier), connection)
}
}
```
Expand All @@ -340,6 +346,16 @@ The equivocation detection subprotocol is defined in [ICS 2](../ics-002-consensu
Implementing chains may want to allow applications to register handlers to take action upon discovery of an equivocation. Further discussion is deferred to ICS 12.
#### Querying
Connections can be queried by identifier with `queryConnection`.
```typescript
function queryConnection(id: Identifier): ConnectionEnd | void {
return get(connectionKey(id))
}
```
## Backwards Compatibility
Not applicable.
Expand Down
Loading

0 comments on commit d823635

Please sign in to comment.