Skip to content

Commit

Permalink
Merge PR #482: Flexible identifier selection
Browse files Browse the repository at this point in the history
  • Loading branch information
cwgoes authored Oct 2, 2020
1 parent c01d584 commit 699422b
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 15 deletions.
Binary file modified spec.pdf
Binary file not shown.
51 changes: 38 additions & 13 deletions spec/ics-003-connection-semantics/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,13 @@ At the end of an opening handshake between two chains implementing the sub-proto
This sub-protocol need not be permissioned, modulo anti-spam measures.
In `connOpenInit`, a sentinel empty-string identifier can be used to allow the recipient chain to choose its own connection identifier. Chains may implement a function `desiredIdentifier` which chooses an identifier, e.g. by incrementing a counter:
```typescript
type desiredIdentifier = (provedIdentifier: Identifier) -> Identifier
```
A specific version can optionally be passed as `version` to ensure that the handshake will either complete with that version or fail.
*ConnOpenInit* initialises a connection attempt on chain A.
Expand All @@ -290,12 +297,20 @@ function connOpenInit(
desiredCounterpartyConnectionIdentifier: Identifier,
counterpartyPrefix: CommitmentPrefix,
clientIdentifier: Identifier,
counterpartyClientIdentifier: Identifier) {
counterpartyClientIdentifier: Identifier,
version: string) {
abortTransactionUnless(validateConnectionIdentifier(identifier))
abortTransactionUnless(provableStore.get(connectionPath(identifier)) == null)
state = INIT
if version != "" {
// manually selected version must be one we can support
abortTransactionUnless(getCompatibleVersions().indexOf(version) > -1)
versions = [version]
} else {
versions = getCompatibleVersions()
}
connection = ConnectionEnd{state, desiredCounterpartyConnectionIdentifier, counterpartyPrefix,
clientIdentifier, counterpartyClientIdentifier, getCompatibleVersions()}
clientIdentifier, counterpartyClientIdentifier, versions}
provableStore.set(connectionPath(identifier), connection)
addConnectionToClient(clientIdentifier, identifier)
}
Expand All @@ -306,6 +321,7 @@ function connOpenInit(
```typescript
function connOpenTry(
desiredIdentifier: Identifier,
provedIdentifier: Identifier,
counterpartyConnectionIdentifier: Identifier,
counterpartyPrefix: CommitmentPrefix,
counterpartyClientIdentifier: Identifier,
Expand All @@ -318,24 +334,27 @@ function connOpenTry(
abortTransactionUnless(validateConnectionIdentifier(desiredIdentifier))
abortTransactionUnless(consensusHeight < getCurrentHeight())
expectedConsensusState = getConsensusState(consensusHeight)
expected = ConnectionEnd{INIT, desiredIdentifier, getCommitmentPrefix(), counterpartyClientIdentifier,
abortTransationUnless(
provedIdentifier === desiredIdentifier ||
provedIdentifier === ""
)
expected = ConnectionEnd{INIT, provedIdentifier, getCommitmentPrefix(), counterpartyClientIdentifier,
clientIdentifier, counterpartyVersions}
versionsIntersection = intersection(counterpartyVersions, getCompatibleVersions())
version = pickVersion(versionsIntersection)
connection = ConnectionEnd{TRYOPEN, counterpartyConnectionIdentifier, counterpartyPrefix,
clientIdentifier, counterpartyClientIdentifier, version}
abortTransactionUnless(connection.verifyConnectionState(proofHeight, proofInit, counterpartyConnectionIdentifier, expected))
abortTransactionUnless(connection.verifyClientConsensusState(
proofHeight, proofConsensus, counterpartyClientIdentifier, consensusHeight, expectedConsensusState))
previous = provableStore.get(connectionPath(desiredIdentifier))
abortTransactionUnless(
(previous === null) ||
(previous.state === INIT &&
previous.counterpartyConnectionIdentifier === counterpartyConnectionIdentifier &&
previous.counterpartyPrefix === counterpartyPrefix &&
previous.clientIdentifier === clientIdentifier &&
previous.counterpartyClientIdentifier === counterpartyClientIdentifier &&
previous.version === getCompatibleVersions()))
previous.counterpartyClientIdentifier === counterpartyClientIdentifier))
versionsIntersection = intersection(counterpartyVersions, previous !== null ? previous.version : getCompatibleVersions())
version = pickVersion(versionsIntersection) // throws if there is no intersection
connection = ConnectionEnd{TRYOPEN, counterpartyConnectionIdentifier, counterpartyPrefix,
clientIdentifier, counterpartyClientIdentifier, version}
abortTransactionUnless(connection.verifyConnectionState(proofHeight, proofInit, counterpartyConnectionIdentifier, expected))
abortTransactionUnless(connection.verifyClientConsensusState(
proofHeight, proofConsensus, counterpartyClientIdentifier, consensusHeight, expectedConsensusState))
identifier = desiredIdentifier
provableStore.set(connectionPath(identifier), connection)
addConnectionToClient(clientIdentifier, identifier)
Expand All @@ -348,24 +367,30 @@ function connOpenTry(
function connOpenAck(
identifier: Identifier,
version: string,
counterpartyIdentifier: Identifier,
proofTry: CommitmentProof,
proofConsensus: CommitmentProof,
proofHeight: Height,
consensusHeight: Height) {
abortTransactionUnless(consensusHeight < getCurrentHeight())
connection = provableStore.get(connectionPath(identifier))
abortTransactionUnless(
counterpartyIdentifier === connection.counterpartyConnectionIdentifier ||
connection.counterpartyConnectionIdentifier === ""
)
abortTransactionUnless(
(connection.state === INIT && connection.version.indexOf(version) !== -1)
|| (connection.state === TRYOPEN && connection.version === version))
expectedConsensusState = getConsensusState(consensusHeight)
expected = ConnectionEnd{TRYOPEN, identifier, getCommitmentPrefix(),
connection.counterpartyClientIdentifier, connection.clientIdentifier,
version}
abortTransactionUnless(connection.verifyConnectionState(proofHeight, proofTry, connection.counterpartyConnectionIdentifier, expected))
abortTransactionUnless(connection.verifyConnectionState(proofHeight, proofTry, counterpartyIdentifier, expected))
abortTransactionUnless(connection.verifyClientConsensusState(
proofHeight, proofConsensus, connection.counterpartyClientIdentifier, consensusHeight, expectedConsensusState))
connection.state = OPEN
connection.version = version
connection.counterpartyConnectionIdentifier = counterpartyIdentifier
provableStore.set(connectionPath(identifier), connection)
}
```
Expand Down
19 changes: 17 additions & 2 deletions spec/ics-004-channel-and-packet-semantics/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,8 @@ When the opening handshake is complete, the module which initiates the handshake
it specifies will own the other end of the created channel on the counterparty chain. Once a channel is created, ownership cannot be changed (although higher-level abstractions
could be implemented to provide this).
A sentinel empty-string identifier can be used to allow the recipient chain to choose its own channel identifier.
```typescript
function chanOpenInit(
order: ChannelOrder,
Expand Down Expand Up @@ -311,6 +313,7 @@ function chanOpenTry(
connectionHops: [Identifier],
portIdentifier: Identifier,
channelIdentifier: Identifier,
provedIdentifier: Identifier,
counterpartyPortIdentifier: Identifier,
counterpartyChannelIdentifier: Identifier,
version: string,
Expand All @@ -319,6 +322,11 @@ function chanOpenTry(
proofHeight: Height): CapabilityKey {
abortTransactionUnless(validateChannelIdentifier(portIdentifier, channelIdentifier))
abortTransactionUnless(connectionHops.length === 1) // for v1 of the IBC protocol
// empty-string is a sentinel value for "allow any identifier"
abortTransationUnless(
provedIdentifier === channelIdentifier ||
provedIdentifier === ""
)
previous = provableStore.get(channelPath(portIdentifier, channelIdentifier))
abortTransactionUnless(
(previous === null) ||
Expand All @@ -334,7 +342,7 @@ function chanOpenTry(
abortTransactionUnless(connection !== null)
abortTransactionUnless(connection.state === OPEN)
expected = ChannelEnd{INIT, order, portIdentifier,
channelIdentifier, [connection.counterpartyConnectionIdentifier], counterpartyVersion}
provedIdentifier, [connection.counterpartyConnectionIdentifier], counterpartyVersion}
abortTransactionUnless(connection.verifyChannelState(
proofHeight,
proofInit,
Expand All @@ -361,11 +369,17 @@ function chanOpenAck(
portIdentifier: Identifier,
channelIdentifier: Identifier,
counterpartyVersion: string,
counterpartyChannelIdentifier: string,
proofTry: CommitmentProof,
proofHeight: Height) {
channel = provableStore.get(channelPath(portIdentifier, channelIdentifier))
abortTransactionUnless(channel.state === INIT || channel.state === TRYOPEN)
abortTransactionUnless(authenticateCapability(channelCapabilityPath(portIdentifier, channelIdentifier), capability))
// empty-string is a sentinel value for "allow any identifier"
abortTransactionUnless(
counterpartyChannelIdentifier === channel.counterpartyChannelIdentifier ||
channel.counterpartyChannelIdentifier === ""
)
connection = provableStore.get(connectionPath(channel.connectionHops[0]))
abortTransactionUnless(connection !== null)
abortTransactionUnless(connection.state === OPEN)
Expand All @@ -375,11 +389,12 @@ function chanOpenAck(
proofHeight,
proofTry,
channel.counterpartyPortIdentifier,
channel.counterpartyChannelIdentifier,
counterpartyChannelIdentifier,
expected
))
channel.state = OPEN
channel.version = counterpartyVersion
channel.counterpartyChannelIdentifier = counterpartyChannelIdentifier
provableStore.set(channelPath(portIdentifier, channelIdentifier), channel)
}
```
Expand Down

0 comments on commit 699422b

Please sign in to comment.