Skip to content

Commit 699422b

Browse files
authored
Merge PR #482: Flexible identifier selection
1 parent c01d584 commit 699422b

File tree

3 files changed

+55
-15
lines changed

3 files changed

+55
-15
lines changed

spec.pdf

0 Bytes
Binary file not shown.

spec/ics-003-connection-semantics/README.md

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,13 @@ At the end of an opening handshake between two chains implementing the sub-proto
281281
282282
This sub-protocol need not be permissioned, modulo anti-spam measures.
283283
284+
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:
285+
286+
```typescript
287+
type desiredIdentifier = (provedIdentifier: Identifier) -> Identifier
288+
```
289+
290+
A specific version can optionally be passed as `version` to ensure that the handshake will either complete with that version or fail.
284291
285292
*ConnOpenInit* initialises a connection attempt on chain A.
286293
@@ -290,12 +297,20 @@ function connOpenInit(
290297
desiredCounterpartyConnectionIdentifier: Identifier,
291298
counterpartyPrefix: CommitmentPrefix,
292299
clientIdentifier: Identifier,
293-
counterpartyClientIdentifier: Identifier) {
300+
counterpartyClientIdentifier: Identifier,
301+
version: string) {
294302
abortTransactionUnless(validateConnectionIdentifier(identifier))
295303
abortTransactionUnless(provableStore.get(connectionPath(identifier)) == null)
296304
state = INIT
305+
if version != "" {
306+
// manually selected version must be one we can support
307+
abortTransactionUnless(getCompatibleVersions().indexOf(version) > -1)
308+
versions = [version]
309+
} else {
310+
versions = getCompatibleVersions()
311+
}
297312
connection = ConnectionEnd{state, desiredCounterpartyConnectionIdentifier, counterpartyPrefix,
298-
clientIdentifier, counterpartyClientIdentifier, getCompatibleVersions()}
313+
clientIdentifier, counterpartyClientIdentifier, versions}
299314
provableStore.set(connectionPath(identifier), connection)
300315
addConnectionToClient(clientIdentifier, identifier)
301316
}
@@ -306,6 +321,7 @@ function connOpenInit(
306321
```typescript
307322
function connOpenTry(
308323
desiredIdentifier: Identifier,
324+
provedIdentifier: Identifier,
309325
counterpartyConnectionIdentifier: Identifier,
310326
counterpartyPrefix: CommitmentPrefix,
311327
counterpartyClientIdentifier: Identifier,
@@ -318,24 +334,27 @@ function connOpenTry(
318334
abortTransactionUnless(validateConnectionIdentifier(desiredIdentifier))
319335
abortTransactionUnless(consensusHeight < getCurrentHeight())
320336
expectedConsensusState = getConsensusState(consensusHeight)
321-
expected = ConnectionEnd{INIT, desiredIdentifier, getCommitmentPrefix(), counterpartyClientIdentifier,
337+
abortTransationUnless(
338+
provedIdentifier === desiredIdentifier ||
339+
provedIdentifier === ""
340+
)
341+
expected = ConnectionEnd{INIT, provedIdentifier, getCommitmentPrefix(), counterpartyClientIdentifier,
322342
clientIdentifier, counterpartyVersions}
323-
versionsIntersection = intersection(counterpartyVersions, getCompatibleVersions())
324-
version = pickVersion(versionsIntersection)
325-
connection = ConnectionEnd{TRYOPEN, counterpartyConnectionIdentifier, counterpartyPrefix,
326-
clientIdentifier, counterpartyClientIdentifier, version}
327-
abortTransactionUnless(connection.verifyConnectionState(proofHeight, proofInit, counterpartyConnectionIdentifier, expected))
328-
abortTransactionUnless(connection.verifyClientConsensusState(
329-
proofHeight, proofConsensus, counterpartyClientIdentifier, consensusHeight, expectedConsensusState))
330343
previous = provableStore.get(connectionPath(desiredIdentifier))
331344
abortTransactionUnless(
332345
(previous === null) ||
333346
(previous.state === INIT &&
334347
previous.counterpartyConnectionIdentifier === counterpartyConnectionIdentifier &&
335348
previous.counterpartyPrefix === counterpartyPrefix &&
336349
previous.clientIdentifier === clientIdentifier &&
337-
previous.counterpartyClientIdentifier === counterpartyClientIdentifier &&
338-
previous.version === getCompatibleVersions()))
350+
previous.counterpartyClientIdentifier === counterpartyClientIdentifier))
351+
versionsIntersection = intersection(counterpartyVersions, previous !== null ? previous.version : getCompatibleVersions())
352+
version = pickVersion(versionsIntersection) // throws if there is no intersection
353+
connection = ConnectionEnd{TRYOPEN, counterpartyConnectionIdentifier, counterpartyPrefix,
354+
clientIdentifier, counterpartyClientIdentifier, version}
355+
abortTransactionUnless(connection.verifyConnectionState(proofHeight, proofInit, counterpartyConnectionIdentifier, expected))
356+
abortTransactionUnless(connection.verifyClientConsensusState(
357+
proofHeight, proofConsensus, counterpartyClientIdentifier, consensusHeight, expectedConsensusState))
339358
identifier = desiredIdentifier
340359
provableStore.set(connectionPath(identifier), connection)
341360
addConnectionToClient(clientIdentifier, identifier)
@@ -348,24 +367,30 @@ function connOpenTry(
348367
function connOpenAck(
349368
identifier: Identifier,
350369
version: string,
370+
counterpartyIdentifier: Identifier,
351371
proofTry: CommitmentProof,
352372
proofConsensus: CommitmentProof,
353373
proofHeight: Height,
354374
consensusHeight: Height) {
355375
abortTransactionUnless(consensusHeight < getCurrentHeight())
356376
connection = provableStore.get(connectionPath(identifier))
377+
abortTransactionUnless(
378+
counterpartyIdentifier === connection.counterpartyConnectionIdentifier ||
379+
connection.counterpartyConnectionIdentifier === ""
380+
)
357381
abortTransactionUnless(
358382
(connection.state === INIT && connection.version.indexOf(version) !== -1)
359383
|| (connection.state === TRYOPEN && connection.version === version))
360384
expectedConsensusState = getConsensusState(consensusHeight)
361385
expected = ConnectionEnd{TRYOPEN, identifier, getCommitmentPrefix(),
362386
connection.counterpartyClientIdentifier, connection.clientIdentifier,
363387
version}
364-
abortTransactionUnless(connection.verifyConnectionState(proofHeight, proofTry, connection.counterpartyConnectionIdentifier, expected))
388+
abortTransactionUnless(connection.verifyConnectionState(proofHeight, proofTry, counterpartyIdentifier, expected))
365389
abortTransactionUnless(connection.verifyClientConsensusState(
366390
proofHeight, proofConsensus, connection.counterpartyClientIdentifier, consensusHeight, expectedConsensusState))
367391
connection.state = OPEN
368392
connection.version = version
393+
connection.counterpartyConnectionIdentifier = counterpartyIdentifier
369394
provableStore.set(connectionPath(identifier), connection)
370395
}
371396
```

spec/ics-004-channel-and-packet-semantics/README.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,8 @@ When the opening handshake is complete, the module which initiates the handshake
273273
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
274274
could be implemented to provide this).
275275
276+
A sentinel empty-string identifier can be used to allow the recipient chain to choose its own channel identifier.
277+
276278
```typescript
277279
function chanOpenInit(
278280
order: ChannelOrder,
@@ -311,6 +313,7 @@ function chanOpenTry(
311313
connectionHops: [Identifier],
312314
portIdentifier: Identifier,
313315
channelIdentifier: Identifier,
316+
provedIdentifier: Identifier,
314317
counterpartyPortIdentifier: Identifier,
315318
counterpartyChannelIdentifier: Identifier,
316319
version: string,
@@ -319,6 +322,11 @@ function chanOpenTry(
319322
proofHeight: Height): CapabilityKey {
320323
abortTransactionUnless(validateChannelIdentifier(portIdentifier, channelIdentifier))
321324
abortTransactionUnless(connectionHops.length === 1) // for v1 of the IBC protocol
325+
// empty-string is a sentinel value for "allow any identifier"
326+
abortTransationUnless(
327+
provedIdentifier === channelIdentifier ||
328+
provedIdentifier === ""
329+
)
322330
previous = provableStore.get(channelPath(portIdentifier, channelIdentifier))
323331
abortTransactionUnless(
324332
(previous === null) ||
@@ -334,7 +342,7 @@ function chanOpenTry(
334342
abortTransactionUnless(connection !== null)
335343
abortTransactionUnless(connection.state === OPEN)
336344
expected = ChannelEnd{INIT, order, portIdentifier,
337-
channelIdentifier, [connection.counterpartyConnectionIdentifier], counterpartyVersion}
345+
provedIdentifier, [connection.counterpartyConnectionIdentifier], counterpartyVersion}
338346
abortTransactionUnless(connection.verifyChannelState(
339347
proofHeight,
340348
proofInit,
@@ -361,11 +369,17 @@ function chanOpenAck(
361369
portIdentifier: Identifier,
362370
channelIdentifier: Identifier,
363371
counterpartyVersion: string,
372+
counterpartyChannelIdentifier: string,
364373
proofTry: CommitmentProof,
365374
proofHeight: Height) {
366375
channel = provableStore.get(channelPath(portIdentifier, channelIdentifier))
367376
abortTransactionUnless(channel.state === INIT || channel.state === TRYOPEN)
368377
abortTransactionUnless(authenticateCapability(channelCapabilityPath(portIdentifier, channelIdentifier), capability))
378+
// empty-string is a sentinel value for "allow any identifier"
379+
abortTransactionUnless(
380+
counterpartyChannelIdentifier === channel.counterpartyChannelIdentifier ||
381+
channel.counterpartyChannelIdentifier === ""
382+
)
369383
connection = provableStore.get(connectionPath(channel.connectionHops[0]))
370384
abortTransactionUnless(connection !== null)
371385
abortTransactionUnless(connection.state === OPEN)
@@ -375,11 +389,12 @@ function chanOpenAck(
375389
proofHeight,
376390
proofTry,
377391
channel.counterpartyPortIdentifier,
378-
channel.counterpartyChannelIdentifier,
392+
counterpartyChannelIdentifier,
379393
expected
380394
))
381395
channel.state = OPEN
382396
channel.version = counterpartyVersion
397+
channel.counterpartyChannelIdentifier = counterpartyChannelIdentifier
383398
provableStore.set(channelPath(portIdentifier, channelIdentifier), channel)
384399
}
385400
```

0 commit comments

Comments
 (0)