Skip to content

Commit 1421d33

Browse files
dshiellAdityaSripalcrodriguezvegablueleHaifeng Xi
committed
Polymer/multihop (#1)
* ICS20: Replace Metadata with Memo (cosmos#877) * memo string replacement * formatting Co-authored-by: Carlos Rodriguez <[email protected]> * ICS9: remove localhost client (cosmos#878) * remove localhost client * Update CHANGELOG.md * Update README.md * fix: update comment about channel state check in `sendPacket` (cosmos#865) * update comment * typo * remove comment Co-authored-by: Carlos Rodriguez <[email protected]> * ICS5: fix releasePort signature (cosmos#885) Signed-off-by: Jun Kimura <[email protected]> Signed-off-by: Jun Kimura <[email protected]> * ICS721: Add tokenData to PacketData (cosmos#876) * add tokenData to PacketData; improve TypeScript formatting * revert else style * extend 03-connection with a proof object for chains that can't introspect their own consensus state. (cosmos#839) * extend 03-connection with HostConsensusStateProof * make hostConsensusStateProof optional * ICS28: Reflect deferred unbonding completion in spec (cosmos#826) * call UnbondingCanComplete in EndBlock * update README * update ics23 link (cosmos#891) * update eli5 blog post link (cosmos#892) * ICS28: Sovereign to consumer chain transition (cosmos#840) * update CreateConsumerClient for sovereign chains * update InitGenesis for sovereign chains * establish CCV on ACK and handle preCCV completion * update Channel Uniqueness Correctness Reasoning * add pre-CCV module interface with staking * add clarifications * add overview TODO * fix pendingChanges bug * refactor proposal names (cosmos#855) * Update spec/app/ics-028-cross-chain-validation/system_model_and_properties.md Co-authored-by: Daniel T <[email protected]> * enable optimistic opening handshakes * remove ConsumerAdditionProposal.initialHeight * handle proposals in BeginBlock * pass consumer unbonding period via gov proposal * update channel init overview - wip * update overview * update modified date * add note re. the existing staking module Co-authored-by: Daniel T <[email protected]> * ICS28: VSCPackets should have timeout on provider (cosmos#858) * update CreateConsumerClient for sovereign chains * update InitGenesis for sovereign chains * establish CCV on ACK and handle preCCV completion * update Channel Uniqueness Correctness Reasoning * add pre-CCV module interface with staking * add clarifications * add overview TODO * fix pendingChanges bug * refactor proposal names * add VSC timeout * refactor proposal names (cosmos#855) * Update spec/app/ics-028-cross-chain-validation/system_model_and_properties.md Co-authored-by: Daniel T <[email protected]> * enable optimistic opening handshakes * remove ConsumerAdditionProposal.initialHeight * handle proposals in BeginBlock * pass consumer unbonding period via gov proposal * update channel init overview - wip * update overview * update modified date * ICS28: Channel initialization should have a timeout (cosmos#860) * add init timeout * fix typo * add note on timed out channel init * update vsc timeout as per implementation Co-authored-by: Daniel T <[email protected]> * add angbrav as code owner (cosmos#895) Co-authored-by: Carlos Rodriguez <[email protected]> * save progress * start adding proof generation logic and update graphical_proof.jpg * rm spec/.DS_Store Signed-off-by: Jun Kimura <[email protected]> Co-authored-by: Aditya <[email protected]> Co-authored-by: Carlos Rodriguez <[email protected]> Co-authored-by: Carlos Rodriguez <[email protected]> Co-authored-by: Jun Kimura <[email protected]> Co-authored-by: Haifeng Xi <[email protected]> Co-authored-by: Web3 Philosopher <[email protected]> Co-authored-by: Marius Poke <[email protected]> Co-authored-by: Daniel T <[email protected]> Co-authored-by: Carlos Rodriguez <[email protected]>
1 parent f7f1a6c commit 1421d33

File tree

2 files changed

+138
-39
lines changed

2 files changed

+138
-39
lines changed

spec/core/ics-032-multi-hop/README.md

Lines changed: 138 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
ics: 32
2+
ics: 33
33
title: Multi-hop Channel
44
stage: draft
55
required-by: 4
@@ -40,74 +40,173 @@ Associated definitions are as defined in referenced prior standards (where the f
4040

4141
## Technical Specification
4242

43-
The bulk of the spec will be around proof generation and verification. Channel handshake and packet message types will remain the same. Round trip messaging semantics and flow will remain the same as well. There is additional work on the verifier side on the destination chain as well as the relayers who need to query for proofs.
43+
The bulk of the spec will be around proof generation and verification. IBC connections remain unchanged. Addiitonally, channel handshake and packet message types as well as general round trip messaging semantics and flow will remain the same. There is additional work on the verifier side on the destination chain as well as the relayers who need to query for proofs.
4444

45-
Messages passed over multiple hops require proof of the connection path from source chain to destination chain as well as the packet commitment on the source chain. The connection path is proven by verifying the connection state and consensus state of each connection segment in the path to the destination chain. On a high level, this can be thought of as a connection path proof chain where the destination chain can prove the each segment of the connection path by proving the state of the prior connection within the next chains state root.
45+
Messages passed over multiple hops require proof of the connection path from source chain to destination chain as well as the packet commitment on the source chain. The connection path is proven by verifying the connection state and consensus state of each connection in the path to the destination chain. On a high level, this can be thought of as a channel path proof chain where the destination chain can prove a key/value on the source chain by iteratively proving each connection and consensus state in the channel path starting with the consensus state associated with the final client on the destination chain. Each subsequent consensus state and connection is proven until the source chain's consensus state is proven which can then be used to prove the desired key/value on the source chain.
4646

4747
### Channel Handshake and Packet Messages
4848

49-
For both channel handshake and packet messages, additional connection hops are defined in the pre-existing `connectionHops` field. The connection IDs along the channel path must be pre-existing to guarantee delivery to the correct recipient. See `Path Forgery Protection` for more info.
49+
For both channel handshake and packet messages, additional connection hops are defined in the pre-existing `connectionHops` field. The connection IDs along the channel path must be pre-existing and in the `OPEN` state to guarantee delivery to the correct recipient. See `Path Forgery Protection` for more info.
5050

5151
The spec for channel handshakes and packets remains the same. See [ICS 4](https://github.com/cosmos/ibc/tree/main/spec/core/ics-004-channel-and-packet-semantics).
5252

5353
In terms of connection topology, a user would be able to determine a viable channel path from source -> destination using information from the [chain registry](https://github.com/cosmos/chain-registry). They can also independently verify this information via network queries.
5454

5555
### Multihop Relaying
5656

57-
Relayers would deliver channel handshake and IBC packets as they currently do except that they are required to provide more proof of the channel path. Relayers would scan packet events for the connectionHops field and determine if the packet is multi-hop by checking the number of hops in the field. If the number of hops is greater than one then the packet is a multi-hop packet and will need extra proof data.
57+
Relayers would deliver channel handshake and IBC packets as they currently do except that they are required to provide proof of the channel path. Relayers would scan packet events for the connectionHops field and determine if the packet is multi-hop by checking the number of hops in the field. If the number of hops is greater than one then the packet is a multi-hop packet and will need extra proof data.
5858

5959
For each multi-hop channel (detailed proof logic below):
6060

61-
- Scan source chain for IBC messages to relay.
62-
- Read the connectionHops field in from the scanned message to determine the channel path.
63-
- Query for proof of connection and consensus state for each intermediate connection in the channel path to the destination connection.
64-
- Query proof of packet commitment or handshake message commitment on source chain.
65-
- Submit proofs and data to RPC endpoint on destination chain.
61+
1. Scan source chain for IBC messages to relay.
62+
2. Read the connectionHops field in from the scanned message to determine the channel path.
63+
3. Lookup connection endpoints via chain registry configuration and ensure each connection in the channel path is updated to include the key/value to be proven on the source chain.
64+
4. Query for proof of connection and consensus state for each intermediate connection in the channel path to the destination connection.
65+
5. Query proof of packet commitment or handshake message commitment on source chain.
66+
6. Submit proofs and data to RPC endpoint on destination chain.
6667

6768
Relayers are connection topology aware with configurations sourced from the [chain registry](https://github.com/cosmos/chain-registry).
6869

6970
### Proof Generation & Verification
7071

7172
Graphical depiction of proof generation.
7273

73-
![graphical_proof.png](graphical_proof.png)
74+
![graphical_proof.jpg](graphical_proof.jpg)
7475

7576
Proof steps.
7677

7778
![proof_steps.png](proof_steps.png)
7879

79-
Pseudocode proof generation for a channel between chains `A -> B -> C`.
80+
Pseudocode proof generation for a channel between `N` chains `C[0] --> C[i] --> C[N]`
8081

81-
```typescript
82-
function queryBatchProof(client: Client, keys: []string) {
83-
stateProofs = []
84-
for key in keys {
85-
resp = client.QueryABCI(abci.RequestQuery{
86-
Path: "store/ibc/key",
87-
Height: height,
88-
Data: key,
89-
Prove: true,
90-
})
91-
proof = ConvertProofs(resp.ProofOps)
92-
stateProofs = append(stateProofs, proof.Proofs[0])
82+
```go
83+
84+
// generic proof struct
85+
type ProofData struct {
86+
Key *MerklePath
87+
Value []]byte
88+
Proof []byte
89+
}
90+
91+
// set of proofs for a multihop message
92+
type MultihopProof struct {
93+
KeyProof *ProofData // the key/value proof on the source chain
94+
ConsensusProofs []*ProofData // array of consensus proofs starting with proof of chain0 state root on chain1
95+
ConnectionProofs []*ProofData // array of connection proofs starting with proof of conn10 on chain1
96+
}
97+
98+
// Generate proof of key/value at the proofHeight on source chain, chain0.
99+
func GenerateMultihopProof(chains []*Chain, key string, value []byte, proofHeight exported.Height) *MultihopProof {
100+
101+
assert(len(chains) > 2)
102+
103+
var multihopProof MultihopProof
104+
chain0 := chains[0] // source chain
105+
chain1 := chains[1] // first hop chain
106+
107+
height01 := chain1.GetClientStateHeight(chain0) // height of chain0's client state on chain1
108+
assert(height01 >= proofHeight) // ensure that chain0's client state is update to date
109+
110+
// query the key/value proof on the source chain at the proof height
111+
keyProof, _ := chain0.QueryProofAtHeight([]byte(keyPathToProve), int64(proofHeight.GetRevisionHeight()))
112+
prefixedKey := commitmenttypes.ApplyPrefix(chain0.GetPrefix(), commitmenttypes.NewMerklePath(key))
113+
114+
// assign the key/value proof
115+
multihopProof.KeyProof = &ProofData{
116+
Key: &prefixedKey,
117+
Value: nil, // proven values are constructed during verification
118+
Proof: proof,
93119
}
94-
return CombineProofs(stateProofs)
120+
121+
// generate and assign consensus and connection proofs
122+
multihopProof.ConsensusProofs = GenerateConsensusProofs(chains)
123+
multihopProof.ConnectionProofs = GenerateConnectionProofs(chains)
124+
125+
return &multihopProof
95126
}
96127

97-
// Query B & A for connectionState and consensusState kvs
98-
keys = [
99-
"ibc/connections/{id}",
100-
"ibc/consensusStates/{height}",
101-
]
102-
batchStateProofB = queryBatchProof(clientB, keys)
103-
batchStateProofA = queryBatchProof(clientA, keys)
104-
105-
// Query A for channel handshake and/or packet messages
106-
keys = [
107-
"ibc/channelEnds/ports/{portID}/channels/{channelID}",
108-
"ibc/commitments/ports/{portID}/channels/{channelID}/packets/{sequence}"
109-
]
110-
batchMessageProofA = queryBatchProof(clientA, keys)
128+
// GenerateConsensusProofs generates consensus state proofs starting from the source chain to the N-1'th chain.
129+
// Compute proof for each chain 3-tuple starting from the source chain, C0 to the destination chain, CN
130+
// Step 1: |C0 ---> C1 ---> C2| ---> C3 ... ---> CN
131+
// (i) (i+1) (i+2)
132+
// Step 2: C0 ---> |C1 ---> C2 ---> C3| ... ---> CN
133+
// (i) (i+1) (i+2)
134+
// Step N-3: C0 ---> C1 ... ---> |CN-2 --> CN-1 ---> CN|
135+
// (i) (i+1) (i+2)
136+
func GenerateConsensusProofs(chains []*Chain, height) []*ProofData {
137+
assert(len(chains) > 2)
138+
139+
var proofs []*ProofData
140+
141+
// iterate all but the last two chains
142+
for i := 0; i < len(chains)-2; i++ {
143+
144+
previousChain := chains[i] // previous chains state root is on currentChain and is the source chain for i==0.
145+
currentChain := chains[i+1] // currentChain is where the proof is queried and generated
146+
nextChain := chains[i+2] // nextChain holds the state root of the currentChain
147+
148+
currentHeight := GetClientStateHeight(currentChain, sourceChain) // height of previous chain state on current chain
149+
nextHeight := GetClientStateHeight(nextChain, currentChain) // height of current chain state on next chain
150+
151+
// consensus state of previous chain on current chain at currentHeight which is the height of A's client state on B
152+
consensusState := GetConsensusState(currentChain, prevChain.ClientID, currentHeight)
153+
154+
// prefixed key for consensus state of previous chain
155+
consensusKey := GetPrefixedConsensusStateKey(currentChain, currentHeight)
156+
157+
// proof of previous chain's consensus state at currentHeight on currentChain at nextHeight
158+
consensusProof := GetConsensusStateProof(currentChain, nextHeight, currentHeight, currentChain.ClientID)
159+
160+
proofs = append(consStateProofs, &ProofData{
161+
Key: &consensusKey,
162+
Value: consensusState,
163+
Proof: consensusProof,
164+
})
165+
}
166+
return proofs
167+
}
168+
169+
// GenerateConnectionProofs generates connection state proofs starting with C1 --> starting from the source chain to the N-1'th chain.
170+
// Compute proof for each chain 3-tuple starting from the source chain, C0 to the destination chain, CN
171+
// Step 1: |C0 ---> C1 ---> C2| ---> C3 ... ---> CN
172+
// (i) (i+1) (i+2)
173+
// Step 2: C0 ---> |C1 ---> C2 ---> C3| ... ---> CN
174+
// (i) (i+1) (i+2)
175+
// Step N-3: C0 ---> C1 ... ---> |CN-2 --> CN-1 ---> CN|
176+
// (i) (i+1) (i+2)
177+
func GenerateConnectionProofs(chains []*Chain) []*ProofData {
178+
assert(len(chains) > 2)
179+
180+
var proofs []*ProofData
181+
182+
// iterate all but the last two chains
183+
for i := 0; i < len(chains)-2; i++ {
184+
185+
previousChain := chains[i] // previous chains state root is on currentChain and is the source chain for i==0.
186+
currentChain := chains[i+1] // currentChain is where the proof is queried and generated
187+
nextChain := chains[i+2] // nextChain holds the state root of the currentChain
188+
189+
currentHeight := currentChain.GetClientStateHeight(sourceChain) // height of previous chain state on current chain
190+
nextHeight := nextChain.GetClientStateHeight(currentChain) // height of current chain state on next chain
191+
192+
// prefixed key for the connection from currentChain to prevChain
193+
connectionKey := GetPrefixedConnectionKey(currentChain)
194+
195+
// proof of current chain's connection to previous Chain.
196+
connectionEnd := GetConnection(currentChain)
197+
198+
// Query proof of the currentChain's connection with the previousChain at nextHeight
199+
// (currentChain's state root height on nextChain)
200+
connectionProof := GetConnectionProof(currentChain, nextHeight)
201+
202+
proofs = append(proofs, &ProofData{
203+
Key: &connectionKey,
204+
Value: connectionEnd,
205+
Proof: connectionProof,
206+
})
207+
}
208+
return proofs
209+
}
111210
```
112211

113212
Pseudocode proof verification of a channel between chains `A -> B -> C` .
83.9 KB
Loading

0 commit comments

Comments
 (0)