From 90bcc82387cbcabb982b3d04ffac86babfe3bc76 Mon Sep 17 00:00:00 2001
From: Christopher Goes <cwgoes@pluranimity.org>
Date: Sun, 9 Jun 2019 13:31:45 +0200
Subject: [PATCH] Merge PR #79: ICS 25: Handler interface

---
 Makefile                                      |   2 +-
 deps.png                                      |   4 +-
 scripts/check_links.py                        |   2 +-
 spec/ics-002-consensus-verification/README.md |   2 +-
 spec/ics-003-connection-semantics/README.md   |   8 +
 spec/ics-003-connection-semantics/state.png   |   2 +-
 .../README.md                                 |  10 -
 .../channel-state-machine.png                 |   2 +-
 .../dataflow.png                              |   2 +-
 .../packet-state-machine.png                  |   2 +-
 spec/ics-025-handler-interface/README.md      | 371 ++++++++++++++++++
 spec/ics-026-relayer-module/README.md         |  71 +++-
 spec/ics-3-connection-semantics/state.png     |   3 +
 13 files changed, 461 insertions(+), 20 deletions(-)
 create mode 100644 spec/ics-025-handler-interface/README.md
 create mode 100644 spec/ics-3-connection-semantics/state.png

diff --git a/Makefile b/Makefile
index 4206ab1f600a..2d72a3c8a881 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-SUBDIRS := spec/ics-3-connection-semantics spec/ics-4-channel-and-packet-semantics
+SUBDIRS := spec/ics-003-connection-semantics spec/ics-004-channel-and-packet-semantics
 TOPTARGETS := all clean
 
 $(TOPTARGETS): $(SUBDIRS)
diff --git a/deps.png b/deps.png
index ad29abe4c231..88ca202245b1 100644
--- a/deps.png
+++ b/deps.png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:0ae6d783a726ce480749ff90e43e201fbb39e169a3e532a6ec836451e00926d5
-size 28176
+oid sha256:1edf4d25fe00d7f3d448a1fae16c5a92193aa0672f7f72e0e1e44b54c0b698ae
+size 57153
diff --git a/scripts/check_links.py b/scripts/check_links.py
index 7ee1af0bb86a..f5c6ad8b70c2 100755
--- a/scripts/check_links.py
+++ b/scripts/check_links.py
@@ -21,7 +21,7 @@
             sys.exit(1)
     titles = [int(x[0]) for x in title_regex.findall(data)]
     for num in titles:
-        matched = [f for f in files if f[7:7+4+len(str(num))+1] == 'ics-' + str(num) + '-']
+        matched = [f for f in files if f[7:7+4+len(str(num).zfill(3))+1] == 'ics-' + str(num).zfill(3) + '-']
         if len(matched) > 0:
             print('Expected "ICS {}" to link to {} but not found!'.format(num, matched[0]))
             sys.exit(1)
diff --git a/spec/ics-002-consensus-verification/README.md b/spec/ics-002-consensus-verification/README.md
index 23cd80ce2111..f846cfec339b 100644
--- a/spec/ics-002-consensus-verification/README.md
+++ b/spec/ics-002-consensus-verification/README.md
@@ -47,7 +47,7 @@ as long as associated light client algorithms fulfilling the requirements are pr
   verified state roots which can be utilized by downstream logic to verify subcomponents
   of state at particular heights.
 
-* `createClient`, `queryClient`, `updateClient`, `freezeClient`, and `deleteClient` function signatures are as defined in ICS 25.
+* `createClient`, `queryClient`, `updateClient`, `freezeClient`, and `deleteClient` function signatures are as defined in [ICS 25](../ics-025-handler-interface).
   The function implementations are defined in this standard.
 
 ### Desired Properties
diff --git a/spec/ics-003-connection-semantics/README.md b/spec/ics-003-connection-semantics/README.md
index 1fa23715bd30..487fd7798139 100644
--- a/spec/ics-003-connection-semantics/README.md
+++ b/spec/ics-003-connection-semantics/README.md
@@ -3,8 +3,16 @@ 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
 author: Christopher Goes <cwgoes@tendermint.com>, Juwoon Yun <joon@tendermint.com>
 created: 2019-03-07
 modified: 2019-05-17
diff --git a/spec/ics-003-connection-semantics/state.png b/spec/ics-003-connection-semantics/state.png
index 084f5b567b86..421ada96ea63 100644
--- a/spec/ics-003-connection-semantics/state.png
+++ b/spec/ics-003-connection-semantics/state.png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:eccc68322c50e782089a702e773c4f504eb079a5895c0b5d2d70b48fedf075c7
+oid sha256:178874921a98d971f7a518323ce619115cae48f560b4937726a5a06c6449b780
 size 346289
diff --git a/spec/ics-004-channel-and-packet-semantics/README.md b/spec/ics-004-channel-and-packet-semantics/README.md
index 06f1ab688714..e96daf87b871 100644
--- a/spec/ics-004-channel-and-packet-semantics/README.md
+++ b/spec/ics-004-channel-and-packet-semantics/README.md
@@ -361,16 +361,6 @@ function chanCloseInit(
 The `chanCloseTry` function is called by the handshake-accepting module
 to acknowledge the channel close request and continue the closing process.
 
-```typescript
-interface ChanCloseTry {
-  connectionIdentifier: Identifier
-  channelIdentifier: Identifier
-  timeoutHeight: uint64
-  nextTimeoutHeight: uint64
-  proofInit: CommitmentProof
-}
-```
-
 ```typescript
 function chanCloseTry(
   connectionIdentifier: Identifier, channelIdentifier: Identifier,
diff --git a/spec/ics-004-channel-and-packet-semantics/channel-state-machine.png b/spec/ics-004-channel-and-packet-semantics/channel-state-machine.png
index 70b1e223bf8d..2fbcbb73336f 100644
--- a/spec/ics-004-channel-and-packet-semantics/channel-state-machine.png
+++ b/spec/ics-004-channel-and-packet-semantics/channel-state-machine.png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:3313a9411f8be69a4f82d0288d3f1a2919274539faeaf243c0e8b03895e23502
+oid sha256:bb4363007c4d94ac6dde035380c6caa11cc0a94a6bec9b2a2562ff9f27a14223
 size 250240
diff --git a/spec/ics-004-channel-and-packet-semantics/dataflow.png b/spec/ics-004-channel-and-packet-semantics/dataflow.png
index 273da75e9d66..883d35095ab8 100644
--- a/spec/ics-004-channel-and-packet-semantics/dataflow.png
+++ b/spec/ics-004-channel-and-packet-semantics/dataflow.png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:275be29bcb7438a3895383dbc4bee0591ccbbe608dfa13beee26b36f75a07684
+oid sha256:1335fe0137556cf9e29678293fcea1ae6f8edd4f154e79efc977076b512b2b09
 size 55196
diff --git a/spec/ics-004-channel-and-packet-semantics/packet-state-machine.png b/spec/ics-004-channel-and-packet-semantics/packet-state-machine.png
index ae8c54342087..40a55ee2d7a0 100644
--- a/spec/ics-004-channel-and-packet-semantics/packet-state-machine.png
+++ b/spec/ics-004-channel-and-packet-semantics/packet-state-machine.png
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:2eb6839f73cf92ab674aa714df494bda52285116765e4e3bdb02337eeeca2364
+oid sha256:a01f7ba5b95d6aef715e3a57f56311029e62d64bb8472d325668637083f8f6f7
 size 139070
diff --git a/spec/ics-025-handler-interface/README.md b/spec/ics-025-handler-interface/README.md
new file mode 100644
index 000000000000..5f3b5bbe58d5
--- /dev/null
+++ b/spec/ics-025-handler-interface/README.md
@@ -0,0 +1,371 @@
+---
+ics: 25
+title: Handler Interface
+stage: draft
+category: ibc-core
+requires: 2, 3, 4, 23, 24
+author: Christopher Goes <cwgoes@tendermint.com>
+created: 2019-04-23
+modified: 2019-06-09
+---
+
+## Synopsis
+
+This document describes the interface exposed by the standard IBC implementation (referred to as the IBC handler) to modules within the same state machine, and the implementation of that interface by the IBC handler.
+
+### Motivation
+
+IBC is an inter-module communication protocol, designed to faciliate reliable, authentication message passing between modules on separate blockchains. Modules should be able to reason about the interface they interact with and the requirements they must adhere to in order to utilize it safely.
+
+### Definitions
+
+`ClientState`, `Header`, and `ConsensusState` are as defined in [ICS 2](../ics-002-consensus-verification).
+
+`Connection` and `ConnectionState` are as defined in [ICS 3](../ics-003-connection-semantics).
+
+`ChannelState` and `Packet` are as defined in [ICS 4](../ics-004-channel-and-packet-semantics).
+
+`CommitmentProof` is as defined in [ICS 23](../ics-023-vector-commitments).
+
+`Identifier`s must conform to the schema defined in [ICS 24](../ics-024-host-requirements).
+
+### Desired Properties
+
+- Creation of clients, connections, and channels should be as permissionless as possible.
+- The module set should be dynamic: chains should be able to add and destroy modules at will with a persistent IBC handler.
+- Modules should be able to write their own more complex abstractions on top of IBC to provide additional semantics or guarantees.
+
+## Technical Specification
+
+### Client lifecycle management
+
+By default, clients are unowned: any module can create a new client, query any existing client, update any existing client, and delete any existing client not in use.
+
+`createClient` creates a new client with a specified identifier.
+
+```typescript
+function createClient(id: Identifier, consensusState: ConsensusState): void {
+  // defined in ICS 2
+}
+```
+
+`queryClientConsensusState` queries a client by a known identifier, returning the associated consensus state if found.
+
+```typescript
+function queryClientConsensusState(id: string): ConsensusState | void {
+  // defined in ICS 2
+}
+```
+
+`updateClient` updates an existing client with a new header, returning an error if the client was not found or the header was not a valid update.
+
+The default IBC relayer module will allow external calls to `updateClient`.
+
+```typescript
+function updateClient(id: Identifier, header; Header): error | void {
+  // defined in ICS 2
+}
+```
+
+`freezeClient` freezes an existing client by providing proof-of-equivocation, automatically freezing any associated connections & channels.
+
+The default IBC relayer module will allow external calls to `freezeClient`.
+
+```typescript
+function freezeClient(id: Identifier, headerOne: Header, headerTwo: Header): error | void {
+  // defined in ICS 2
+}
+```
+
+`deleteClient` deletes an existing client, returning an error if the identifier is not found or if the associated client was just created or is still in use by any connection.
+
+```typescript
+function deleteClient(id: Identifier): error | void {
+  // defined in ICS 2
+}
+```
+
+Implementations of `createClient`, `queryClientConsensusState`, `updateClient`, `freezeClient`, and `deleteClient` are defined in [ICS 2](../ics-002-consensus-verification).
+
+### Connection lifecycle management
+
+By default, connections are unowned. Connections can be closed by any module, but only when all channels associated with the connection have been closed by the modules which opened them and a timeout has passed since the connection was opened.
+
+```typescript
+function connOpenInit(
+  identifier: Identifier, desiredCounterpartyIdentifier: Identifier,
+  clientIdentifier: Identifier, counterpartyClientIdentifier: Identifier, nextTimeoutHeight: uint64) {
+  // defined in ICS 3
+}
+```
+
+`connOpenTry` acknowledges a connection initialization on the initiating chain.
+
+The default IBC relayer module will allow external calls to `connOpenTry`.
+
+```typescript
+function connOpenTry(
+  desiredIdentifier: Identifier, counterpartyIdentifier: Identifier,
+  counterpartyClientIdentifier: Identifier, clientIdentifier: Identifier,
+  proofInit: CommitmentProof, timeoutHeight: uint64, nextTimeoutHeight: uint64) {
+  // defined in ICS 3
+}
+```
+
+`connOpenAck` acknowledges a connection in progress on another chain.
+
+The default IBC relayer module will allow external calls to `connOpenAck`.
+
+```typescript
+function connOpenAck(
+  identifier: Identifier, proofTry: CommitmentProof,
+  timeoutHeight: uint64, nextTimeoutHeight: uint64) {
+  // defined in ICS 3
+}
+```
+
+`connOpenConfirm` acknowledges the acknowledgement and finalizes a new connection.
+
+The default IBC relayer module will allow external calls to `connOpenConfirm`.
+
+```typescript
+function connOpenConfirm(identifier: Identifier, proofAck: CommitmentProof, timeoutHeight: uint64) {
+  // defined in ICS 3
+}
+```
+
+`connOpenTimeout` proves that a connection handshake has timed-out and resets the process.
+
+The default IBC relayer module will allow external calls to `connOpenTimeout`.
+
+```typescript
+function connOpenTimeout(identifier: Identifier, proofTimeout: CommitmentProof, timeoutHeight: uint64) {
+  // defined in ICS 3
+}
+```
+
+`connCloseInit` initiates the graceful connection closing process. It will fail if there are any open channels using the connection or if the identifier is invalid.
+
+```typescript
+function connCloseInit(identifier: Identifier, nextTimeoutHeight: uint64) {
+  // defined in ICS 3
+}
+```
+
+`connCloseTry` continues the graceful connection closing process. It will fail if there are any open channels using the connection, if the proof is invalid, or if the identifier is invalid.
+
+The default IBC relayer module will allow external calls to `connCloseTry`.
+
+```typescript
+function connCloseTry(
+  identifier: Identifier, proofInit: CommitmentProof,
+  timeoutHeight: uint64, nextTimeoutHeight: uint64) {
+  // defined in ICS 3
+}
+```
+
+`connCloseAck` finalizes the graceful connection closing process. It will fail if the proof is invalid or if the identifier is invalid.
+
+The default IBC relayer module will allow external calls to `connCloseAck`.
+
+```typescript
+function connCloseAck(identifier: Identifier, proofTry: CommitmentProof, timeoutHeight: uint64) {
+  // defined in ICS 3
+}
+```
+
+`connCloseTimeout` proves that a connection closing handshake has timed-out and resets the process.
+
+The default IBC relayer module will allow external calls to `connCloseTimeout`.
+
+```typescript
+function connCloseTimeout(identifier: Identifier, proofTimeout: CommitmentProof, timeoutHeight: uint64) {
+  // defined in ICS 3
+}
+```
+
+### Channel lifecycle management
+
+By default, channels are owned by the creating module, meaning only the creating module can inspect, close, or send on the channel. A module can create any number of channels.
+
+`chanOpenInit` tries to start the handshake to create a new channel with the provided options, failing if the connection is not found or the options are invalid.
+
+```typescript
+function chanOpenInit(
+  connectionIdentifier: Identifier, channelIdentifier: Identifier,
+  counterpartyChannelIdentifier: Identifier, counterpartyModuleIdentifier: Identifier, nextTimeoutHeight: uint64) {
+  // defined in ICS 4
+}
+```
+
+`chanOpenTry` tries to initialize a channel based on proof of an initialization attempt on the counterparty chain, failing if the channel identifier is unavailable, the proof is invalid, or the calling module is not authorized.
+
+The default IBC relayer module will allow external calls to `chanOpenTry`.
+
+```typescript
+function chanOpenTry(
+  connectionIdentifier: Identifier, channelIdentifier: Identifier, counterpartyChannelIdentifier: Identifier,
+  moduleIdentifier: Identifier, counterpartyModuleIdentifier: Identifier,
+  timeoutHeight: uint64, nextTimeoutHeight: uint64, proofInit: CommitmentProof) {
+  // defined in ICS 4
+}
+```
+
+`chanOpenAck` acknowledges a channel creation in progress on another chain, failing if the channel identifier is not found, the proof is invalid, or the calling module is not authorized.
+
+The default IBC relayer module will allow external calls to `chanOpenAck`.
+
+```typescript
+function chanOpenAck(
+  connectionIdentifier: Identifier, channelIdentifier: Identifier,
+  timeoutHeight: uint64, nextTimeoutHeight: uint64, proofTry: CommitmentProof) {
+  // defined in ICS 4
+}
+```
+
+`chanOpenConfirm` finalizes the channel opening handshake, failing if the channel identifier is not found, the proof is invalid, or the calling module is not authorized.
+
+The default IBC relayer module will allow external calls to `chanOpenConfirm`.
+
+```typescript
+function chanOpenConfirm(
+  connectionIdentifier: Identifier, channelIdentifier: Identifier,
+  timeoutHeight: uint64, proofAck: CommitmentProof) {
+  // defined in ICS 4
+}
+```
+
+`chanOpenTimeout` proves that a channel opening handshake has timed-out and resets the process.
+
+The default IBC relayer module will allow external calls to `chanOpenTimeout`.
+
+```typescript
+function chanOpenTimeout(
+  connectionIdentifier: Identifier, channelIdentifier: Identifier,
+  timeoutHeight: uint64, proofTimeout: CommitmentProof) {
+  // defined in ICS 4
+}
+```
+
+`queryChannel` queries an existing channel by known identifier, returning the associated metadata if found.
+
+```typeescript
+function queryChannel(string identifier): void {
+  // defined in ICS 4
+}
+```
+
+`chanCloseInit` initiates the channel closing handshake.
+
+```typescript
+function chanCloseInit(
+  connectionIdentifier: Identifier, channelIdentifier: Identifier, nextTimeoutHeight: uint64) {
+  // defined in ICS 4
+}
+```
+
+`chanCloseTry` acknowledges the initialization of the channel closing handshake on the counterparty chain.
+
+The default IBC relayer module will allow external calls to `chanCloseTry`.
+
+```typescript
+function chanCloseTry(
+  connectionIdentifier: Identifier, channelIdentifier: Identifier,
+  timeoutHeight: uint64, nextTimeoutHeight: uint64, proofInit: CommitmentProof) {
+  // defined in ICS 4
+}
+```
+
+`chanCloseAck` acknowledges the acknowledgement and finalizes the channel closing handshake.
+
+The default IBC relayer module will allow external calls to `chanCloseAck`.
+
+```typescript
+function chanCloseAck(
+  connectionIdentifier: Identifier, channelIdentifier: Identifier,
+  timeoutHeight: uint64, proofTry: CommitmentProof) {
+  // defined in ICS 4
+}
+```
+
+`chanCloseTimeout` proves that a channel closing handshake has timed-out and resets the process.
+
+The default IBC relayer module will allow external calls to `chanCloseTimeout`.
+
+```typescript
+function chanCloseTimeout(
+  connectionIdentifier: Identifier, channelIdentifier: Identifier,
+  timeoutHeight: uint64, proofTimeout: CommitmentProof) {
+  // defined in ICS 4
+}
+```
+
+### Packet relay
+
+Packets are permissioned by channel (only a module which owns a channel can send on it).
+
+`sendPacket` attempts to send a packet, returning an error if the packet cannot be sent (perhaps because the sending module does not own the channel in question or because the channel is frozen), and returning a unique identifier if successful.
+
+The returned identifier will be the same as that sent by the timeout handler `timeoutPacket`, so it can be used by the sending module to associate a specific action with a specific packet timeout.
+
+The default IBC relayer module will allow external calls to `sendPacket`.
+
+```typescript
+function sendPacket(packet: Packet) {
+  // defined in ICS 4
+}
+```
+
+`recvPacket` attempts to receive a packet, returning an error if the calling module is not authorized to handle the packet, or if the packet does not exist or has been already handled.
+
+The default IBC relayer module will allow external calls to `recvPacket`.
+
+```typescript
+function recvPacket(packet: Packet, proof: CommitmentProof) {
+  // defined in ICS 4
+}
+```
+
+`timeoutPacket` attemps to handle a packet timeout, returning an error if the calling module is not authorized to handle the packet timeout, or if the packet does not exist, has not timed out, or has already been handled.
+
+The default IBC relayer module will allow external calls to `timeoutPacket`.
+
+```coffeescript
+function timeoutPacket(packet: Packet, proof: CommitmentProof, nextSequenceRecv: uint64) {
+  // defined in ICS 4
+}
+```
+
+`recvTimeoutPacket` function is called by a module in order to process an IBC packet sent on the corresponding channel which has timed out.
+
+The default IBC relayer module will allow external calls to `recvTimeoutPacket`.
+
+```typescript
+function recvTimeoutPacket(packet: Packet, proof: CommitmentProof) {
+  // defined in ICS 4
+}
+```
+
+## Backwards Compatibility
+
+Not applicable.
+
+## Forwards Compatibility
+
+The interface can change when implemented on new chains (or upgrades to an existing chain) as long as the semantics remain the same.
+
+## Example Implementation
+
+Coming soon.
+
+## Other Implementations
+
+Coming soon.
+
+## History
+
+9 June 2019 - Draft written
+
+## Copyright
+
+Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
diff --git a/spec/ics-026-relayer-module/README.md b/spec/ics-026-relayer-module/README.md
index 6394816c91b3..9b059cb7ed2e 100644
--- a/spec/ics-026-relayer-module/README.md
+++ b/spec/ics-026-relayer-module/README.md
@@ -20,7 +20,7 @@ but is a bit tricky to understand and may require extra work on the part of rela
 
 ### Definitions
 
-All functions provided by the IBC handler interface are defined as in ICS 25.
+All functions provided by the IBC handler interface are defined as in [ICS 25](../ics-025-handler-interface).
 
 ### Desired Properties
 
@@ -179,6 +179,16 @@ interface ChanCloseInit {
 }
 ```
 
+```typescript
+interface ChanCloseTry {
+  connectionIdentifier: Identifier
+  channelIdentifier: Identifier
+  timeoutHeight: uint64
+  nextTimeoutHeight: uint64
+  proofInit: CommitmentProof
+}
+```
+
 ```typescript
 interface ChanCloseAck {
   connectionIdentifier: Identifier
@@ -201,6 +211,65 @@ interface ChanCloseTimeout {
 
 ### Subprotocols
 
+### Interface usage example
+
+As a demonstration of interface usage, a simple module handling send/receive of a native asset could be implemented as follows:
+
+```golang
+type State struct {
+  channel     string
+}
+```
+
+```golang
+type PacketData struct {
+  asset         string
+  amount        integer
+  source        address
+  destination   address
+}
+```
+
+```coffeescript
+function myModuleInit()
+  client = createClient(consensusState)
+  connection = createConnection(nil, client)
+  state.channel = createChannel(nil, connection, myModuleRecv, myModuleTimeout)
+```
+
+```coffeescript
+function myModuleSend(string asset, integer amount, address source, address destination)
+  checkSignature(source)
+  deductBalance(source, asset, amount)
+  escrow(asset, amount)
+  sendPacket({
+    channel: state.channel,
+    data: {
+      asset       : asset,
+      amount      : amount,
+      source      : source,
+      destination : destination,
+    }
+  })
+```
+
+```coffeescript
+function myModuleRecv(Packet packet)
+  recvPacket(packet)
+  assert(packet.channel == channel)
+  data = packet.data
+  unescrow(data.asset, data.amount)
+  increaseBalance(data.destination, data.asset, data.amount)
+```
+
+```coffeescript
+function myModuleTimeout(Packet packet)
+  timeoutPacket(packet)
+  data = packet.data
+  unescrow(packet.asset, packet.amount)
+  increaseBalance(packet.source, packet.asset, packet.amount)
+```
+
 ## Backwards Compatibility
 
 Not applicable.
diff --git a/spec/ics-3-connection-semantics/state.png b/spec/ics-3-connection-semantics/state.png
new file mode 100644
index 000000000000..fd205c32661c
--- /dev/null
+++ b/spec/ics-3-connection-semantics/state.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:8f92215f43e0a87c91eaa22962940efbd5a693a6688cd4fff2af605d919c7a0f
+size 346289