diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index e1adf1997f3..79c65acedce 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,8 +1,8 @@ # CODEOWNERS: https://help.github.com/articles/about-codeowners/ -* @colin-axner @AdityaSripal @crodriguezvega @damiannolan @chatton @DimitrisJim @gjermundgaraba @bznein +* @colin-axner @AdityaSripal @damiannolan @chatton @DimitrisJim @gjermundgaraba @bznein -# Our appreciation and gratitude to past code owners: @fedekunze @seantking @tmsdkeys @charleenfei +# Our appreciation and gratitude to past code owners: @fedekunze @seantking @tmsdkeys @charleenfei @crodriguezvega # Order is important; the last matching pattern takes the most # precedence. When someone opens a pull request that only @@ -11,7 +11,7 @@ # CODEOWNERS for the CODEOWNER file -/.github/CODEOWNERS @colin-axner @AdityaSripal @crodriguezvega @damiannolan @chatton +/.github/CODEOWNERS @colin-axner @AdityaSripal @damiannolan @chatton # CODEOWNERS for the core IBC module @@ -25,7 +25,7 @@ # CODEOWNERS for 08-wasm light client module -/modules/light-clients/08-wasm/ @colin-axner @AdityaSripal @damiannolan @chatton @DimitrisJim @srdtrk @crodriguezvega +/modules/light-clients/08-wasm/ @colin-axner @AdityaSripal @damiannolan @chatton @DimitrisJim @srdtrk # CODEOWNERS for ICS 20 @@ -48,5 +48,5 @@ # CODEOWNERS for docs -/docs/ @colin-axner @AdityaSripal @crodriguezvega @damiannolan @chatton @DimitrisJim @srdtrk +/docs/ @colin-axner @AdityaSripal @damiannolan @chatton @DimitrisJim @srdtrk diff --git a/.github/ISSUE_TEMPLATE/release-tracker.md b/.github/ISSUE_TEMPLATE/release-tracker.md index 960946e4e5e..482951e3819 100644 --- a/.github/ISSUE_TEMPLATE/release-tracker.md +++ b/.github/ISSUE_TEMPLATE/release-tracker.md @@ -44,7 +44,7 @@ versions of ibc-go to guarantee that no regression is introduced --> - [ ] Branch off main to create release branch in the form of `release/vx.y.z` and add branch protection rules. - [ ] Add branch protection rules to new release branch. - [ ] Add backport task to [`mergify.yml`](https://github.com/cosmos/ibc-go/blob/main/.github/mergify.yml) -- [ ] Upgrade ibc-go version in [ibctest](https://github.com/strangelove-ventures/ibctest). +- [ ] Upgrade ibc-go version in [interchaintest](https://github.com/strangelove-ventures/ibctest). - [ ] Check Swagger is up-to-date. ## Post-release checklist diff --git a/.github/compatibility-test-matrices/main/ica-chain-a.json b/.github/compatibility-test-matrices/main/ica-chain-a.json index eb14648ed4d..5fb45c4db19 100644 --- a/.github/compatibility-test-matrices/main/ica-chain-a.json +++ b/.github/compatibility-test-matrices/main/ica-chain-a.json @@ -4,6 +4,7 @@ ], "chain-b": [ "main", + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/main/ica-chain-b.json b/.github/compatibility-test-matrices/main/ica-chain-b.json index 9bb0c092bff..65f22af1dbb 100644 --- a/.github/compatibility-test-matrices/main/ica-chain-b.json +++ b/.github/compatibility-test-matrices/main/ica-chain-b.json @@ -1,6 +1,7 @@ { "chain-a": [ "main", + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/main/ica-channel-upgrade-chain-a.json b/.github/compatibility-test-matrices/main/ica-channel-upgrade-chain-a.json index ba6ec1d32ef..a10d27316eb 100644 --- a/.github/compatibility-test-matrices/main/ica-channel-upgrade-chain-a.json +++ b/.github/compatibility-test-matrices/main/ica-channel-upgrade-chain-a.json @@ -4,6 +4,7 @@ ], "chain-b": [ "main", + "v9.0.0", "v8.5.0", "v8.4.0" ], diff --git a/.github/compatibility-test-matrices/main/ica-channel-upgrade-chain-b.json b/.github/compatibility-test-matrices/main/ica-channel-upgrade-chain-b.json index e10ff5fcf63..4f76422e93d 100644 --- a/.github/compatibility-test-matrices/main/ica-channel-upgrade-chain-b.json +++ b/.github/compatibility-test-matrices/main/ica-channel-upgrade-chain-b.json @@ -1,6 +1,7 @@ { "chain-a": [ "main", + "v9.0.0", "v8.5.0", "v8.4.0" ], diff --git a/.github/compatibility-test-matrices/main/ica-gov-chain-a.json b/.github/compatibility-test-matrices/main/ica-gov-chain-a.json index a82db346b9d..cc8e0e0029c 100644 --- a/.github/compatibility-test-matrices/main/ica-gov-chain-a.json +++ b/.github/compatibility-test-matrices/main/ica-gov-chain-a.json @@ -4,6 +4,7 @@ ], "chain-b": [ "main", + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/main/ica-gov-chain-b.json b/.github/compatibility-test-matrices/main/ica-gov-chain-b.json index dbbca6d0a15..a4ee95e8bae 100644 --- a/.github/compatibility-test-matrices/main/ica-gov-chain-b.json +++ b/.github/compatibility-test-matrices/main/ica-gov-chain-b.json @@ -1,6 +1,7 @@ { "chain-a": [ "main", + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/main/ica-groups-chain-a.json b/.github/compatibility-test-matrices/main/ica-groups-chain-a.json index b0e6edc047c..491b873b5f0 100644 --- a/.github/compatibility-test-matrices/main/ica-groups-chain-a.json +++ b/.github/compatibility-test-matrices/main/ica-groups-chain-a.json @@ -4,6 +4,7 @@ ], "chain-b": [ "main", + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/main/ica-groups-chain-b.json b/.github/compatibility-test-matrices/main/ica-groups-chain-b.json index 72496c89730..221e32a49fb 100644 --- a/.github/compatibility-test-matrices/main/ica-groups-chain-b.json +++ b/.github/compatibility-test-matrices/main/ica-groups-chain-b.json @@ -1,6 +1,7 @@ { "chain-a": [ "main", + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/main/ica-unordered-channel-chain-a.json b/.github/compatibility-test-matrices/main/ica-unordered-channel-chain-a.json index fec7bc211d0..c332bea90e0 100644 --- a/.github/compatibility-test-matrices/main/ica-unordered-channel-chain-a.json +++ b/.github/compatibility-test-matrices/main/ica-unordered-channel-chain-a.json @@ -4,6 +4,7 @@ ], "chain-b": [ "main", + "v9.0.0", "v8.5.0", "v8.4.0" ], diff --git a/.github/compatibility-test-matrices/main/ica-unordered-channel-chain-b.json b/.github/compatibility-test-matrices/main/ica-unordered-channel-chain-b.json index 0ecac73aef8..8a6c009f6fa 100644 --- a/.github/compatibility-test-matrices/main/ica-unordered-channel-chain-b.json +++ b/.github/compatibility-test-matrices/main/ica-unordered-channel-chain-b.json @@ -1,6 +1,7 @@ { "chain-a": [ "main", + "v9.0.0", "v8.5.0", "v8.4.0" ], diff --git a/.github/compatibility-test-matrices/main/incentivized-ica-chain-a.json b/.github/compatibility-test-matrices/main/incentivized-ica-chain-a.json index 7b1d250e4d1..0b0eab21faf 100644 --- a/.github/compatibility-test-matrices/main/incentivized-ica-chain-a.json +++ b/.github/compatibility-test-matrices/main/incentivized-ica-chain-a.json @@ -4,6 +4,7 @@ ], "chain-b": [ "main", + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/main/incentivized-ica-chain-b.json b/.github/compatibility-test-matrices/main/incentivized-ica-chain-b.json index f964fdc44a3..6d1892f1842 100644 --- a/.github/compatibility-test-matrices/main/incentivized-ica-chain-b.json +++ b/.github/compatibility-test-matrices/main/incentivized-ica-chain-b.json @@ -1,6 +1,7 @@ { "chain-a": [ "main", + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/main/incentivized-transfer-chain-a.json b/.github/compatibility-test-matrices/main/incentivized-transfer-chain-a.json index ea9c944d149..32fc4d895a1 100644 --- a/.github/compatibility-test-matrices/main/incentivized-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/main/incentivized-transfer-chain-a.json @@ -4,6 +4,7 @@ ], "chain-b": [ "main", + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/main/incentivized-transfer-chain-b.json b/.github/compatibility-test-matrices/main/incentivized-transfer-chain-b.json index c65742cf2ff..f7bfe912e1e 100644 --- a/.github/compatibility-test-matrices/main/incentivized-transfer-chain-b.json +++ b/.github/compatibility-test-matrices/main/incentivized-transfer-chain-b.json @@ -1,6 +1,7 @@ { "chain-a": [ "main", + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/main/localhost-ica-chain-a.json b/.github/compatibility-test-matrices/main/localhost-ica-chain-a.json index 22eaffb3fa3..aded3ddc4d0 100644 --- a/.github/compatibility-test-matrices/main/localhost-ica-chain-a.json +++ b/.github/compatibility-test-matrices/main/localhost-ica-chain-a.json @@ -1,6 +1,7 @@ { "chain-a": [ "main", + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/main/localhost-ica-chain-b.json b/.github/compatibility-test-matrices/main/localhost-ica-chain-b.json index 31de5da8b65..9640bd1df33 100644 --- a/.github/compatibility-test-matrices/main/localhost-ica-chain-b.json +++ b/.github/compatibility-test-matrices/main/localhost-ica-chain-b.json @@ -4,6 +4,7 @@ ], "chain-b": [ "main", + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/main/localhost-transfer-chain-a.json b/.github/compatibility-test-matrices/main/localhost-transfer-chain-a.json index 2934f7bbdf2..cb2b7cf8f42 100644 --- a/.github/compatibility-test-matrices/main/localhost-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/main/localhost-transfer-chain-a.json @@ -1,6 +1,7 @@ { "chain-a": [ "main", + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/main/localhost-transfer-chain-b.json b/.github/compatibility-test-matrices/main/localhost-transfer-chain-b.json index c6cbecb9739..eb8263603ad 100644 --- a/.github/compatibility-test-matrices/main/localhost-transfer-chain-b.json +++ b/.github/compatibility-test-matrices/main/localhost-transfer-chain-b.json @@ -4,6 +4,7 @@ ], "chain-b": [ "main", + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/main/transfer-authz-chain-a.json b/.github/compatibility-test-matrices/main/transfer-authz-chain-a.json index 1356e01328c..1b4a8930d29 100644 --- a/.github/compatibility-test-matrices/main/transfer-authz-chain-a.json +++ b/.github/compatibility-test-matrices/main/transfer-authz-chain-a.json @@ -4,6 +4,7 @@ ], "chain-b": [ "main", + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/main/transfer-authz-chain-b.json b/.github/compatibility-test-matrices/main/transfer-authz-chain-b.json index c20b93d31c2..867cac33b69 100644 --- a/.github/compatibility-test-matrices/main/transfer-authz-chain-b.json +++ b/.github/compatibility-test-matrices/main/transfer-authz-chain-b.json @@ -1,6 +1,7 @@ { "chain-a": [ "main", + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/main/transfer-chain-a.json b/.github/compatibility-test-matrices/main/transfer-chain-a.json index d67ed6f3679..b2a7ba96fd9 100644 --- a/.github/compatibility-test-matrices/main/transfer-chain-a.json +++ b/.github/compatibility-test-matrices/main/transfer-chain-a.json @@ -4,6 +4,7 @@ ], "chain-b": [ "main", + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/main/transfer-chain-b.json b/.github/compatibility-test-matrices/main/transfer-chain-b.json index a1020f0f809..528a0bd9dce 100644 --- a/.github/compatibility-test-matrices/main/transfer-chain-b.json +++ b/.github/compatibility-test-matrices/main/transfer-chain-b.json @@ -1,6 +1,7 @@ { "chain-a": [ "main", + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/main/transfer-channel-upgrade-chain-a.json b/.github/compatibility-test-matrices/main/transfer-channel-upgrade-chain-a.json index 7fb9a65276d..a5b972f8f69 100644 --- a/.github/compatibility-test-matrices/main/transfer-channel-upgrade-chain-a.json +++ b/.github/compatibility-test-matrices/main/transfer-channel-upgrade-chain-a.json @@ -4,6 +4,7 @@ ], "chain-b": [ "main", + "v9.0.0", "v8.5.0", "v8.4.0" ], diff --git a/.github/compatibility-test-matrices/main/transfer-channel-upgrade-chain-b.json b/.github/compatibility-test-matrices/main/transfer-channel-upgrade-chain-b.json index f0331a1dcea..7bf6f95825d 100644 --- a/.github/compatibility-test-matrices/main/transfer-channel-upgrade-chain-b.json +++ b/.github/compatibility-test-matrices/main/transfer-channel-upgrade-chain-b.json @@ -1,6 +1,7 @@ { "chain-a": [ "main", + "v9.0.0", "v8.5.0", "v8.4.0" ], diff --git a/.github/compatibility-test-matrices/main/transfer-v2-1-channel-upgrade-chain-a.json b/.github/compatibility-test-matrices/main/transfer-v2-1-channel-upgrade-chain-a.json index 487d66ed0fc..c436d416799 100644 --- a/.github/compatibility-test-matrices/main/transfer-v2-1-channel-upgrade-chain-a.json +++ b/.github/compatibility-test-matrices/main/transfer-v2-1-channel-upgrade-chain-a.json @@ -3,7 +3,8 @@ "main" ], "chain-b": [ - "main" + "main", + "v9.0.0" ], "entrypoint": [ "TransferChannelUpgradesV1TestSuite" diff --git a/.github/compatibility-test-matrices/main/transfer-v2-1-channel-upgrade-chain-b.json b/.github/compatibility-test-matrices/main/transfer-v2-1-channel-upgrade-chain-b.json new file mode 100644 index 00000000000..f64538e8265 --- /dev/null +++ b/.github/compatibility-test-matrices/main/transfer-v2-1-channel-upgrade-chain-b.json @@ -0,0 +1,19 @@ +{ + "chain-a": [ + "main", + "v9.0.0" + ], + "chain-b": [ + "main" + ], + "entrypoint": [ + "TransferChannelUpgradesV1TestSuite" + ], + "test": [ + "TestChannelUpgrade_WithICS20v2_Succeeds", + "TestChannelUpgrade_WithFeeMiddlewareAndICS20v2_Succeeds" + ], + "relayer-type": [ + "hermes" + ] +} \ No newline at end of file diff --git a/.github/compatibility-test-matrices/main/transfer-v2-2-channel-upgrade-chain-a.json b/.github/compatibility-test-matrices/main/transfer-v2-2-channel-upgrade-chain-a.json index d1558f9c12e..7af82416a54 100644 --- a/.github/compatibility-test-matrices/main/transfer-v2-2-channel-upgrade-chain-a.json +++ b/.github/compatibility-test-matrices/main/transfer-v2-2-channel-upgrade-chain-a.json @@ -3,7 +3,8 @@ "main" ], "chain-b": [ - "main" + "main", + "v9.0.0" ], "entrypoint": [ "TestTransferChannelUpgradesTestSuite" diff --git a/.github/compatibility-test-matrices/main/transfer-v2-2-channel-upgrade-chain-b.json b/.github/compatibility-test-matrices/main/transfer-v2-2-channel-upgrade-chain-b.json new file mode 100644 index 00000000000..8922bb14e50 --- /dev/null +++ b/.github/compatibility-test-matrices/main/transfer-v2-2-channel-upgrade-chain-b.json @@ -0,0 +1,18 @@ +{ + "chain-a": [ + "main", + "v9.0.0" + ], + "chain-b": [ + "main" + ], + "entrypoint": [ + "TestTransferChannelUpgradesTestSuite" + ], + "test": [ + "TestChannelDowngrade_WithICS20v1_Succeeds" + ], + "relayer-type": [ + "hermes" + ] +} \ No newline at end of file diff --git a/.github/compatibility-test-matrices/main/transfer-v2-forwarding-chain-a.json b/.github/compatibility-test-matrices/main/transfer-v2-forwarding-chain-a.json index 7fc9ecbaae4..81c32f47557 100644 --- a/.github/compatibility-test-matrices/main/transfer-v2-forwarding-chain-a.json +++ b/.github/compatibility-test-matrices/main/transfer-v2-forwarding-chain-a.json @@ -3,7 +3,8 @@ "main" ], "chain-b": [ - "main" + "main", + "v9.0.0" ], "entrypoint": [ "TransferForwardingTestSuite" diff --git a/.github/compatibility-test-matrices/main/transfer-v2-forwarding-chain-b.json b/.github/compatibility-test-matrices/main/transfer-v2-forwarding-chain-b.json new file mode 100644 index 00000000000..4d356778b42 --- /dev/null +++ b/.github/compatibility-test-matrices/main/transfer-v2-forwarding-chain-b.json @@ -0,0 +1,22 @@ +{ + "chain-a": [ + "main", + "v9.0.0" + ], + "chain-b": [ + "main" + ], + "entrypoint": [ + "TransferForwardingTestSuite" + ], + "test": [ + "TestForwarding_Succeeds", + "TestForwarding_WithLastChainBeingICS20v1_Succeeds", + "TestForwardingWithUnwindSucceeds", + "TestFailedForwarding", + "TestChannelUpgradeForwarding_Succeeds" + ], + "relayer-type": [ + "hermes" + ] +} \ No newline at end of file diff --git a/.github/compatibility-test-matrices/main/transfer-v2-multidenom-chain-a.json b/.github/compatibility-test-matrices/main/transfer-v2-multidenom-chain-a.json index fb04ec8ba4d..49b973c658c 100644 --- a/.github/compatibility-test-matrices/main/transfer-v2-multidenom-chain-a.json +++ b/.github/compatibility-test-matrices/main/transfer-v2-multidenom-chain-a.json @@ -3,7 +3,8 @@ "main" ], "chain-b": [ - "main" + "main", + "v9.0.0" ], "entrypoint": [ "TestTransferTestSuite" diff --git a/.github/compatibility-test-matrices/main/transfer-v2-multidenom-chain-b.json b/.github/compatibility-test-matrices/main/transfer-v2-multidenom-chain-b.json new file mode 100644 index 00000000000..b1201ce1438 --- /dev/null +++ b/.github/compatibility-test-matrices/main/transfer-v2-multidenom-chain-b.json @@ -0,0 +1,20 @@ +{ + "chain-a": [ + "main", + "v9.0.0" + ], + "chain-b": [ + "main" + ], + "entrypoint": [ + "TestTransferTestSuite" + ], + "test": [ + "TestMsgTransfer_Succeeds_Nonincentivized_MultiDenom", + "TestMsgTransfer_EntireBalance", + "TestMsgTransfer_Fails_InvalidAddress_MultiDenom" + ], + "relayer-type": [ + "hermes" + ] +} \ No newline at end of file diff --git a/.github/compatibility-test-matrices/release-v7.4.x/ica-chain-a.json b/.github/compatibility-test-matrices/release-v7.4.x/ica-chain-a.json index 2f1b3aaddfd..b4c5d650991 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/ica-chain-a.json @@ -3,6 +3,7 @@ "release-v7.4.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/ica-chain-b.json b/.github/compatibility-test-matrices/release-v7.4.x/ica-chain-b.json index 5ae111969a2..e49746163d1 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/ica-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/ica-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/ica-gov-chain-a.json b/.github/compatibility-test-matrices/release-v7.4.x/ica-gov-chain-a.json index b12e4355c5c..4b436a6e01e 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/ica-gov-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/ica-gov-chain-a.json @@ -3,6 +3,7 @@ "release-v7.4.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/ica-gov-chain-b.json b/.github/compatibility-test-matrices/release-v7.4.x/ica-gov-chain-b.json index 28b3716ab70..04bde55f367 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/ica-gov-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/ica-gov-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/ica-groups-chain-a.json b/.github/compatibility-test-matrices/release-v7.4.x/ica-groups-chain-a.json index e41b09dab64..c2393aded81 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/ica-groups-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/ica-groups-chain-a.json @@ -3,6 +3,7 @@ "release-v7.4.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/ica-groups-chain-b.json b/.github/compatibility-test-matrices/release-v7.4.x/ica-groups-chain-b.json index 8600a307e10..320e50abed8 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/ica-groups-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/ica-groups-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/incentivized-ica-chain-a.json b/.github/compatibility-test-matrices/release-v7.4.x/incentivized-ica-chain-a.json index 261d850ea14..d4540e54796 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/incentivized-ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/incentivized-ica-chain-a.json @@ -3,6 +3,7 @@ "release-v7.4.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/incentivized-ica-chain-b.json b/.github/compatibility-test-matrices/release-v7.4.x/incentivized-ica-chain-b.json index d9d794a1037..c595f13002d 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/incentivized-ica-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/incentivized-ica-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/incentivized-transfer-chain-a.json b/.github/compatibility-test-matrices/release-v7.4.x/incentivized-transfer-chain-a.json index 995efcd8904..e9b7608fefd 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/incentivized-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/incentivized-transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v7.4.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/incentivized-transfer-chain-b.json b/.github/compatibility-test-matrices/release-v7.4.x/incentivized-transfer-chain-b.json index 6bc89899008..6d0f5dd6e8d 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/incentivized-transfer-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/incentivized-transfer-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/localhost-ica-chain-a.json b/.github/compatibility-test-matrices/release-v7.4.x/localhost-ica-chain-a.json index c9883d2efaa..6cf2cb80b5d 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/localhost-ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/localhost-ica-chain-a.json @@ -3,6 +3,7 @@ "release-v7.4.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/localhost-transfer-chain-a.json b/.github/compatibility-test-matrices/release-v7.4.x/localhost-transfer-chain-a.json index 70aa2a8f0b9..c88a421c514 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/localhost-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/localhost-transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v7.4.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/transfer-authz-chain-a.json b/.github/compatibility-test-matrices/release-v7.4.x/transfer-authz-chain-a.json index 5f3764ef5df..3a0c29c2438 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/transfer-authz-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/transfer-authz-chain-a.json @@ -3,6 +3,7 @@ "release-v7.4.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/transfer-authz-chain-b.json b/.github/compatibility-test-matrices/release-v7.4.x/transfer-authz-chain-b.json index a634081fe1e..c6f321250dc 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/transfer-authz-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/transfer-authz-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/transfer-chain-a.json b/.github/compatibility-test-matrices/release-v7.4.x/transfer-chain-a.json index a7f092a8bb8..4d291f2f8f9 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v7.4.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.4.x/transfer-chain-b.json b/.github/compatibility-test-matrices/release-v7.4.x/transfer-chain-b.json index 62a2b7bb8ae..6f641f52bc5 100644 --- a/.github/compatibility-test-matrices/release-v7.4.x/transfer-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.4.x/transfer-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/ica-chain-a.json b/.github/compatibility-test-matrices/release-v7.5.x/ica-chain-a.json index df85b58ea20..a06940ca669 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/ica-chain-a.json @@ -3,6 +3,7 @@ "release-v7.5.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/ica-chain-b.json b/.github/compatibility-test-matrices/release-v7.5.x/ica-chain-b.json index 43de7428554..befc551bb2b 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/ica-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/ica-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/ica-gov-chain-a.json b/.github/compatibility-test-matrices/release-v7.5.x/ica-gov-chain-a.json index eb031b169ba..4b7adee4e50 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/ica-gov-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/ica-gov-chain-a.json @@ -3,6 +3,7 @@ "release-v7.5.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/ica-gov-chain-b.json b/.github/compatibility-test-matrices/release-v7.5.x/ica-gov-chain-b.json index 4715e7d3f46..e4227e35e1a 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/ica-gov-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/ica-gov-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/ica-groups-chain-a.json b/.github/compatibility-test-matrices/release-v7.5.x/ica-groups-chain-a.json index d3552b6c85a..e7085f95879 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/ica-groups-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/ica-groups-chain-a.json @@ -3,6 +3,7 @@ "release-v7.5.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/ica-groups-chain-b.json b/.github/compatibility-test-matrices/release-v7.5.x/ica-groups-chain-b.json index 91469f4bc74..aa740c41bf4 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/ica-groups-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/ica-groups-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/ica-unordered-channel-chain-a.json b/.github/compatibility-test-matrices/release-v7.5.x/ica-unordered-channel-chain-a.json index 7744f41ff75..3ed146622bf 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/ica-unordered-channel-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/ica-unordered-channel-chain-a.json @@ -3,6 +3,7 @@ "release-v7.5.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "release-v7.5.x" diff --git a/.github/compatibility-test-matrices/release-v7.5.x/ica-unordered-channel-chain-b.json b/.github/compatibility-test-matrices/release-v7.5.x/ica-unordered-channel-chain-b.json index e2ee04f9739..5cf6e525aae 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/ica-unordered-channel-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/ica-unordered-channel-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "release-v7.5.x" diff --git a/.github/compatibility-test-matrices/release-v7.5.x/incentivized-ica-chain-a.json b/.github/compatibility-test-matrices/release-v7.5.x/incentivized-ica-chain-a.json index e8e0a4dc71d..156e44e5eae 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/incentivized-ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/incentivized-ica-chain-a.json @@ -3,6 +3,7 @@ "release-v7.5.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/incentivized-ica-chain-b.json b/.github/compatibility-test-matrices/release-v7.5.x/incentivized-ica-chain-b.json index 6cb957c3445..7ecb5e19d79 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/incentivized-ica-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/incentivized-ica-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/incentivized-transfer-chain-a.json b/.github/compatibility-test-matrices/release-v7.5.x/incentivized-transfer-chain-a.json index 119150bf216..86b6e58d2b9 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/incentivized-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/incentivized-transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v7.5.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/incentivized-transfer-chain-b.json b/.github/compatibility-test-matrices/release-v7.5.x/incentivized-transfer-chain-b.json index 043fac58525..acd0f5fe811 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/incentivized-transfer-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/incentivized-transfer-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/localhost-ica-chain-a.json b/.github/compatibility-test-matrices/release-v7.5.x/localhost-ica-chain-a.json index 3b8625c9a4e..084352af361 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/localhost-ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/localhost-ica-chain-a.json @@ -3,6 +3,7 @@ "release-v7.5.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/localhost-transfer-chain-a.json b/.github/compatibility-test-matrices/release-v7.5.x/localhost-transfer-chain-a.json index 2e04effa1d1..975d7a5d572 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/localhost-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/localhost-transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v7.5.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/transfer-authz-chain-a.json b/.github/compatibility-test-matrices/release-v7.5.x/transfer-authz-chain-a.json index 7250610a60d..c53e07bc5b8 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/transfer-authz-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/transfer-authz-chain-a.json @@ -3,6 +3,7 @@ "release-v7.5.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/transfer-authz-chain-b.json b/.github/compatibility-test-matrices/release-v7.5.x/transfer-authz-chain-b.json index d153dd4d30d..3782db96aa0 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/transfer-authz-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/transfer-authz-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/transfer-chain-a.json b/.github/compatibility-test-matrices/release-v7.5.x/transfer-chain-a.json index 2b0e065c972..98d2ee7c518 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v7.5.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.5.x/transfer-chain-b.json b/.github/compatibility-test-matrices/release-v7.5.x/transfer-chain-b.json index e8c68b9342e..7fa72895936 100644 --- a/.github/compatibility-test-matrices/release-v7.5.x/transfer-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.5.x/transfer-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.6.x/ica-chain-a.json b/.github/compatibility-test-matrices/release-v7.6.x/ica-chain-a.json index edf38f3cded..ee3668d4deb 100644 --- a/.github/compatibility-test-matrices/release-v7.6.x/ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.6.x/ica-chain-a.json @@ -3,6 +3,7 @@ "release-v7.6.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.6.x/ica-chain-b.json b/.github/compatibility-test-matrices/release-v7.6.x/ica-chain-b.json index d5c94282d8d..1e654dd5637 100644 --- a/.github/compatibility-test-matrices/release-v7.6.x/ica-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.6.x/ica-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.6.x/ica-gov-chain-a.json b/.github/compatibility-test-matrices/release-v7.6.x/ica-gov-chain-a.json index cd55da60534..1ac4ef3e611 100644 --- a/.github/compatibility-test-matrices/release-v7.6.x/ica-gov-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.6.x/ica-gov-chain-a.json @@ -3,6 +3,7 @@ "release-v7.6.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.6.x/ica-gov-chain-b.json b/.github/compatibility-test-matrices/release-v7.6.x/ica-gov-chain-b.json index cb22e2f185e..b2d8e894c24 100644 --- a/.github/compatibility-test-matrices/release-v7.6.x/ica-gov-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.6.x/ica-gov-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.6.x/ica-groups-chain-a.json b/.github/compatibility-test-matrices/release-v7.6.x/ica-groups-chain-a.json index 763c5ee9b45..cd5cf97d58e 100644 --- a/.github/compatibility-test-matrices/release-v7.6.x/ica-groups-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.6.x/ica-groups-chain-a.json @@ -3,6 +3,7 @@ "release-v7.6.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.6.x/ica-groups-chain-b.json b/.github/compatibility-test-matrices/release-v7.6.x/ica-groups-chain-b.json index 9bb44d4ea9b..afb8059c717 100644 --- a/.github/compatibility-test-matrices/release-v7.6.x/ica-groups-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.6.x/ica-groups-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.6.x/ica-unordered-channel-chain-a.json b/.github/compatibility-test-matrices/release-v7.6.x/ica-unordered-channel-chain-a.json index cf6e450466e..7fb313f57b9 100644 --- a/.github/compatibility-test-matrices/release-v7.6.x/ica-unordered-channel-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.6.x/ica-unordered-channel-chain-a.json @@ -3,6 +3,7 @@ "release-v7.6.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "release-v7.6.x" diff --git a/.github/compatibility-test-matrices/release-v7.6.x/ica-unordered-channel-chain-b.json b/.github/compatibility-test-matrices/release-v7.6.x/ica-unordered-channel-chain-b.json index 5d1506c255f..5c33433988a 100644 --- a/.github/compatibility-test-matrices/release-v7.6.x/ica-unordered-channel-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.6.x/ica-unordered-channel-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "release-v7.6.x" diff --git a/.github/compatibility-test-matrices/release-v7.6.x/incentivized-ica-chain-a.json b/.github/compatibility-test-matrices/release-v7.6.x/incentivized-ica-chain-a.json index 0e321531563..1ef2145b837 100644 --- a/.github/compatibility-test-matrices/release-v7.6.x/incentivized-ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.6.x/incentivized-ica-chain-a.json @@ -3,6 +3,7 @@ "release-v7.6.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.6.x/incentivized-ica-chain-b.json b/.github/compatibility-test-matrices/release-v7.6.x/incentivized-ica-chain-b.json index e39e71cef1b..5c5280b8488 100644 --- a/.github/compatibility-test-matrices/release-v7.6.x/incentivized-ica-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.6.x/incentivized-ica-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.6.x/incentivized-transfer-chain-a.json b/.github/compatibility-test-matrices/release-v7.6.x/incentivized-transfer-chain-a.json index 0d8032381a5..044db930ca8 100644 --- a/.github/compatibility-test-matrices/release-v7.6.x/incentivized-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.6.x/incentivized-transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v7.6.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.6.x/incentivized-transfer-chain-b.json b/.github/compatibility-test-matrices/release-v7.6.x/incentivized-transfer-chain-b.json index 19a46ce636c..db41909a39e 100644 --- a/.github/compatibility-test-matrices/release-v7.6.x/incentivized-transfer-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.6.x/incentivized-transfer-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.6.x/localhost-ica-chain-a.json b/.github/compatibility-test-matrices/release-v7.6.x/localhost-ica-chain-a.json index 9ec9880bc87..5388cf1ac69 100644 --- a/.github/compatibility-test-matrices/release-v7.6.x/localhost-ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.6.x/localhost-ica-chain-a.json @@ -3,6 +3,7 @@ "release-v7.6.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.6.x/localhost-transfer-chain-a.json b/.github/compatibility-test-matrices/release-v7.6.x/localhost-transfer-chain-a.json index c50336a27e5..9d28c736b38 100644 --- a/.github/compatibility-test-matrices/release-v7.6.x/localhost-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.6.x/localhost-transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v7.6.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.6.x/transfer-authz-chain-a.json b/.github/compatibility-test-matrices/release-v7.6.x/transfer-authz-chain-a.json index 8dddec5339b..e42906a200d 100644 --- a/.github/compatibility-test-matrices/release-v7.6.x/transfer-authz-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.6.x/transfer-authz-chain-a.json @@ -3,6 +3,7 @@ "release-v7.6.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.6.x/transfer-authz-chain-b.json b/.github/compatibility-test-matrices/release-v7.6.x/transfer-authz-chain-b.json index 95f4adc423c..fc8956a5879 100644 --- a/.github/compatibility-test-matrices/release-v7.6.x/transfer-authz-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.6.x/transfer-authz-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.6.x/transfer-chain-a.json b/.github/compatibility-test-matrices/release-v7.6.x/transfer-chain-a.json index eea91a7afec..3cbbd928cf7 100644 --- a/.github/compatibility-test-matrices/release-v7.6.x/transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.6.x/transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v7.6.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.6.x/transfer-chain-b.json b/.github/compatibility-test-matrices/release-v7.6.x/transfer-chain-b.json index 53d146f37cf..755ab6ef82a 100644 --- a/.github/compatibility-test-matrices/release-v7.6.x/transfer-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.6.x/transfer-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.7.x/ica-chain-a.json b/.github/compatibility-test-matrices/release-v7.7.x/ica-chain-a.json index 7c2c9f448c0..fc06ae844f0 100644 --- a/.github/compatibility-test-matrices/release-v7.7.x/ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.7.x/ica-chain-a.json @@ -3,6 +3,7 @@ "release-v7.7.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.7.x/ica-chain-b.json b/.github/compatibility-test-matrices/release-v7.7.x/ica-chain-b.json index 47d82f0b0b8..03a8dfdfcdb 100644 --- a/.github/compatibility-test-matrices/release-v7.7.x/ica-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.7.x/ica-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.7.x/ica-gov-chain-a.json b/.github/compatibility-test-matrices/release-v7.7.x/ica-gov-chain-a.json index 3020ce3ebc2..21ddba9ce27 100644 --- a/.github/compatibility-test-matrices/release-v7.7.x/ica-gov-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.7.x/ica-gov-chain-a.json @@ -3,6 +3,7 @@ "release-v7.7.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.7.x/ica-gov-chain-b.json b/.github/compatibility-test-matrices/release-v7.7.x/ica-gov-chain-b.json index a1e585285c4..ee7e13ceb33 100644 --- a/.github/compatibility-test-matrices/release-v7.7.x/ica-gov-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.7.x/ica-gov-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.7.x/ica-groups-chain-a.json b/.github/compatibility-test-matrices/release-v7.7.x/ica-groups-chain-a.json index 6cf1e0c5913..b701b6ed836 100644 --- a/.github/compatibility-test-matrices/release-v7.7.x/ica-groups-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.7.x/ica-groups-chain-a.json @@ -3,6 +3,7 @@ "release-v7.7.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.7.x/ica-groups-chain-b.json b/.github/compatibility-test-matrices/release-v7.7.x/ica-groups-chain-b.json index a2d262c0076..bea4c54c778 100644 --- a/.github/compatibility-test-matrices/release-v7.7.x/ica-groups-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.7.x/ica-groups-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.7.x/ica-unordered-channel-chain-a.json b/.github/compatibility-test-matrices/release-v7.7.x/ica-unordered-channel-chain-a.json index baaf8bab6f9..58726245d8d 100644 --- a/.github/compatibility-test-matrices/release-v7.7.x/ica-unordered-channel-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.7.x/ica-unordered-channel-chain-a.json @@ -3,6 +3,7 @@ "release-v7.7.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "release-v7.7.x" diff --git a/.github/compatibility-test-matrices/release-v7.7.x/ica-unordered-channel-chain-b.json b/.github/compatibility-test-matrices/release-v7.7.x/ica-unordered-channel-chain-b.json index 3d7a2fac3cb..f8352177d9c 100644 --- a/.github/compatibility-test-matrices/release-v7.7.x/ica-unordered-channel-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.7.x/ica-unordered-channel-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "release-v7.7.x" diff --git a/.github/compatibility-test-matrices/release-v7.7.x/incentivized-ica-chain-a.json b/.github/compatibility-test-matrices/release-v7.7.x/incentivized-ica-chain-a.json index 6b11a19db50..35dda0d2251 100644 --- a/.github/compatibility-test-matrices/release-v7.7.x/incentivized-ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.7.x/incentivized-ica-chain-a.json @@ -3,6 +3,7 @@ "release-v7.7.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.7.x/incentivized-ica-chain-b.json b/.github/compatibility-test-matrices/release-v7.7.x/incentivized-ica-chain-b.json index ffc7e16b18e..11020e13ee7 100644 --- a/.github/compatibility-test-matrices/release-v7.7.x/incentivized-ica-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.7.x/incentivized-ica-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.7.x/incentivized-transfer-chain-a.json b/.github/compatibility-test-matrices/release-v7.7.x/incentivized-transfer-chain-a.json index 63ca4f86ac4..647aefbf71c 100644 --- a/.github/compatibility-test-matrices/release-v7.7.x/incentivized-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.7.x/incentivized-transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v7.7.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.7.x/incentivized-transfer-chain-b.json b/.github/compatibility-test-matrices/release-v7.7.x/incentivized-transfer-chain-b.json index 3f72a4f02a9..1779bb55d20 100644 --- a/.github/compatibility-test-matrices/release-v7.7.x/incentivized-transfer-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.7.x/incentivized-transfer-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.7.x/localhost-ica-chain-a.json b/.github/compatibility-test-matrices/release-v7.7.x/localhost-ica-chain-a.json index 12d246727ef..2ca5155c5fa 100644 --- a/.github/compatibility-test-matrices/release-v7.7.x/localhost-ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.7.x/localhost-ica-chain-a.json @@ -3,6 +3,7 @@ "release-v7.7.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.7.x/localhost-transfer-chain-a.json b/.github/compatibility-test-matrices/release-v7.7.x/localhost-transfer-chain-a.json index 397c21fb75b..b545a18d85e 100644 --- a/.github/compatibility-test-matrices/release-v7.7.x/localhost-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.7.x/localhost-transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v7.7.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.7.x/transfer-authz-chain-a.json b/.github/compatibility-test-matrices/release-v7.7.x/transfer-authz-chain-a.json index aafffefacb2..6c2bc8c8cab 100644 --- a/.github/compatibility-test-matrices/release-v7.7.x/transfer-authz-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.7.x/transfer-authz-chain-a.json @@ -3,6 +3,7 @@ "release-v7.7.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.7.x/transfer-authz-chain-b.json b/.github/compatibility-test-matrices/release-v7.7.x/transfer-authz-chain-b.json index e4bceaff361..1a8455b4785 100644 --- a/.github/compatibility-test-matrices/release-v7.7.x/transfer-authz-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.7.x/transfer-authz-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.7.x/transfer-chain-a.json b/.github/compatibility-test-matrices/release-v7.7.x/transfer-chain-a.json index f832ac61a6e..0b2916d5c73 100644 --- a/.github/compatibility-test-matrices/release-v7.7.x/transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.7.x/transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v7.7.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.7.x/transfer-chain-b.json b/.github/compatibility-test-matrices/release-v7.7.x/transfer-chain-b.json index bf1b933a646..edb0b978daf 100644 --- a/.github/compatibility-test-matrices/release-v7.7.x/transfer-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.7.x/transfer-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.8.x/ica-chain-a.json b/.github/compatibility-test-matrices/release-v7.8.x/ica-chain-a.json index ae0b3d9a90f..2d34fec1e5a 100644 --- a/.github/compatibility-test-matrices/release-v7.8.x/ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.8.x/ica-chain-a.json @@ -3,6 +3,7 @@ "release-v7.8.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.8.x/ica-chain-b.json b/.github/compatibility-test-matrices/release-v7.8.x/ica-chain-b.json index a5f69025ec0..18cbbde57f4 100644 --- a/.github/compatibility-test-matrices/release-v7.8.x/ica-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.8.x/ica-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.8.x/ica-gov-chain-a.json b/.github/compatibility-test-matrices/release-v7.8.x/ica-gov-chain-a.json index 8ace4bfe3fe..b8ce19d6ff4 100644 --- a/.github/compatibility-test-matrices/release-v7.8.x/ica-gov-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.8.x/ica-gov-chain-a.json @@ -3,6 +3,7 @@ "release-v7.8.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.8.x/ica-gov-chain-b.json b/.github/compatibility-test-matrices/release-v7.8.x/ica-gov-chain-b.json index 9793fe4b54c..268657ac163 100644 --- a/.github/compatibility-test-matrices/release-v7.8.x/ica-gov-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.8.x/ica-gov-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.8.x/ica-groups-chain-a.json b/.github/compatibility-test-matrices/release-v7.8.x/ica-groups-chain-a.json index 032ec43173d..b67ca0f56da 100644 --- a/.github/compatibility-test-matrices/release-v7.8.x/ica-groups-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.8.x/ica-groups-chain-a.json @@ -3,6 +3,7 @@ "release-v7.8.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.8.x/ica-groups-chain-b.json b/.github/compatibility-test-matrices/release-v7.8.x/ica-groups-chain-b.json index 0f8f01af088..006db55559f 100644 --- a/.github/compatibility-test-matrices/release-v7.8.x/ica-groups-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.8.x/ica-groups-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.8.x/ica-unordered-channel-chain-a.json b/.github/compatibility-test-matrices/release-v7.8.x/ica-unordered-channel-chain-a.json index ccd805c86e1..926c5b8bece 100644 --- a/.github/compatibility-test-matrices/release-v7.8.x/ica-unordered-channel-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.8.x/ica-unordered-channel-chain-a.json @@ -3,6 +3,7 @@ "release-v7.8.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "release-v7.8.x" diff --git a/.github/compatibility-test-matrices/release-v7.8.x/ica-unordered-channel-chain-b.json b/.github/compatibility-test-matrices/release-v7.8.x/ica-unordered-channel-chain-b.json index d86d0aac81f..f27be113678 100644 --- a/.github/compatibility-test-matrices/release-v7.8.x/ica-unordered-channel-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.8.x/ica-unordered-channel-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "release-v7.8.x" diff --git a/.github/compatibility-test-matrices/release-v7.8.x/incentivized-ica-chain-a.json b/.github/compatibility-test-matrices/release-v7.8.x/incentivized-ica-chain-a.json index 3471c955487..ab2027dcdd7 100644 --- a/.github/compatibility-test-matrices/release-v7.8.x/incentivized-ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.8.x/incentivized-ica-chain-a.json @@ -3,6 +3,7 @@ "release-v7.8.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.8.x/incentivized-ica-chain-b.json b/.github/compatibility-test-matrices/release-v7.8.x/incentivized-ica-chain-b.json index 9365475a499..2a60b095e48 100644 --- a/.github/compatibility-test-matrices/release-v7.8.x/incentivized-ica-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.8.x/incentivized-ica-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.8.x/incentivized-transfer-chain-a.json b/.github/compatibility-test-matrices/release-v7.8.x/incentivized-transfer-chain-a.json index c4c9ca1107e..61fa270413f 100644 --- a/.github/compatibility-test-matrices/release-v7.8.x/incentivized-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.8.x/incentivized-transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v7.8.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.8.x/incentivized-transfer-chain-b.json b/.github/compatibility-test-matrices/release-v7.8.x/incentivized-transfer-chain-b.json index 5aa8ce2345d..d48f66b5e37 100644 --- a/.github/compatibility-test-matrices/release-v7.8.x/incentivized-transfer-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.8.x/incentivized-transfer-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.8.x/localhost-ica-chain-a.json b/.github/compatibility-test-matrices/release-v7.8.x/localhost-ica-chain-a.json index fc7b1491b46..cb12f945d32 100644 --- a/.github/compatibility-test-matrices/release-v7.8.x/localhost-ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.8.x/localhost-ica-chain-a.json @@ -3,6 +3,7 @@ "release-v7.8.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.8.x/localhost-transfer-chain-a.json b/.github/compatibility-test-matrices/release-v7.8.x/localhost-transfer-chain-a.json index 6153e674a05..be320e72645 100644 --- a/.github/compatibility-test-matrices/release-v7.8.x/localhost-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.8.x/localhost-transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v7.8.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.8.x/transfer-authz-chain-a.json b/.github/compatibility-test-matrices/release-v7.8.x/transfer-authz-chain-a.json index 156f8171a27..cc2174dfc3c 100644 --- a/.github/compatibility-test-matrices/release-v7.8.x/transfer-authz-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.8.x/transfer-authz-chain-a.json @@ -3,6 +3,7 @@ "release-v7.8.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.8.x/transfer-authz-chain-b.json b/.github/compatibility-test-matrices/release-v7.8.x/transfer-authz-chain-b.json index bad34e7e0c6..21d046fa7bd 100644 --- a/.github/compatibility-test-matrices/release-v7.8.x/transfer-authz-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.8.x/transfer-authz-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.8.x/transfer-chain-a.json b/.github/compatibility-test-matrices/release-v7.8.x/transfer-chain-a.json index f31a0b07a5b..60411906f0b 100644 --- a/.github/compatibility-test-matrices/release-v7.8.x/transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v7.8.x/transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v7.8.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v7.8.x/transfer-chain-b.json b/.github/compatibility-test-matrices/release-v7.8.x/transfer-chain-b.json index 09693a9c446..2be3cfd0f8c 100644 --- a/.github/compatibility-test-matrices/release-v7.8.x/transfer-chain-b.json +++ b/.github/compatibility-test-matrices/release-v7.8.x/transfer-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.4.x/ica-chain-a.json b/.github/compatibility-test-matrices/release-v8.4.x/ica-chain-a.json index 1e6f12f6f38..b85b81ffc1c 100644 --- a/.github/compatibility-test-matrices/release-v8.4.x/ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.4.x/ica-chain-a.json @@ -3,6 +3,7 @@ "release-v8.4.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.4.x/ica-chain-b.json b/.github/compatibility-test-matrices/release-v8.4.x/ica-chain-b.json index 26c040209f9..e32c1390647 100644 --- a/.github/compatibility-test-matrices/release-v8.4.x/ica-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.4.x/ica-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.4.x/ica-channel-upgrade-chain-a.json b/.github/compatibility-test-matrices/release-v8.4.x/ica-channel-upgrade-chain-a.json index 69a3f5042e7..acebf43d0c3 100644 --- a/.github/compatibility-test-matrices/release-v8.4.x/ica-channel-upgrade-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.4.x/ica-channel-upgrade-chain-a.json @@ -3,6 +3,7 @@ "release-v8.4.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "release-v8.4.x" diff --git a/.github/compatibility-test-matrices/release-v8.4.x/ica-channel-upgrade-chain-b.json b/.github/compatibility-test-matrices/release-v8.4.x/ica-channel-upgrade-chain-b.json index fc8ddd2f346..fbe739607a1 100644 --- a/.github/compatibility-test-matrices/release-v8.4.x/ica-channel-upgrade-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.4.x/ica-channel-upgrade-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "release-v8.4.x" diff --git a/.github/compatibility-test-matrices/release-v8.4.x/ica-gov-chain-a.json b/.github/compatibility-test-matrices/release-v8.4.x/ica-gov-chain-a.json index 92a20ef45ad..79c646cfcb8 100644 --- a/.github/compatibility-test-matrices/release-v8.4.x/ica-gov-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.4.x/ica-gov-chain-a.json @@ -3,6 +3,7 @@ "release-v8.4.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.4.x/ica-gov-chain-b.json b/.github/compatibility-test-matrices/release-v8.4.x/ica-gov-chain-b.json index 8a6c409e896..45d1f56db31 100644 --- a/.github/compatibility-test-matrices/release-v8.4.x/ica-gov-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.4.x/ica-gov-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.4.x/ica-groups-chain-a.json b/.github/compatibility-test-matrices/release-v8.4.x/ica-groups-chain-a.json index ceef3795909..dc626cbd3d3 100644 --- a/.github/compatibility-test-matrices/release-v8.4.x/ica-groups-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.4.x/ica-groups-chain-a.json @@ -3,6 +3,7 @@ "release-v8.4.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.4.x/ica-groups-chain-b.json b/.github/compatibility-test-matrices/release-v8.4.x/ica-groups-chain-b.json index d92e890efed..6d911b04b70 100644 --- a/.github/compatibility-test-matrices/release-v8.4.x/ica-groups-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.4.x/ica-groups-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.4.x/ica-queries-chain-a.json b/.github/compatibility-test-matrices/release-v8.4.x/ica-queries-chain-a.json index 7664b4934e5..964c8d2f25a 100644 --- a/.github/compatibility-test-matrices/release-v8.4.x/ica-queries-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.4.x/ica-queries-chain-a.json @@ -3,6 +3,7 @@ "release-v8.4.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.4.x/ica-queries-chain-b.json b/.github/compatibility-test-matrices/release-v8.4.x/ica-queries-chain-b.json index 3f18bd9b205..f92c0099b57 100644 --- a/.github/compatibility-test-matrices/release-v8.4.x/ica-queries-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.4.x/ica-queries-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.4.x/ica-unordered-channel-chain-a.json b/.github/compatibility-test-matrices/release-v8.4.x/ica-unordered-channel-chain-a.json index 2ffb5f9e4cc..6c0dda38f64 100644 --- a/.github/compatibility-test-matrices/release-v8.4.x/ica-unordered-channel-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.4.x/ica-unordered-channel-chain-a.json @@ -3,6 +3,7 @@ "release-v8.4.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.4.x/ica-unordered-channel-chain-b.json b/.github/compatibility-test-matrices/release-v8.4.x/ica-unordered-channel-chain-b.json index 40623b97af5..322feabdf31 100644 --- a/.github/compatibility-test-matrices/release-v8.4.x/ica-unordered-channel-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.4.x/ica-unordered-channel-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.4.x/incentivized-ica-chain-a.json b/.github/compatibility-test-matrices/release-v8.4.x/incentivized-ica-chain-a.json index 6e7a1744a8d..5d4b5cf22f6 100644 --- a/.github/compatibility-test-matrices/release-v8.4.x/incentivized-ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.4.x/incentivized-ica-chain-a.json @@ -3,6 +3,7 @@ "release-v8.4.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.4.x/incentivized-ica-chain-b.json b/.github/compatibility-test-matrices/release-v8.4.x/incentivized-ica-chain-b.json index e5a15ea9f8e..2127bf39421 100644 --- a/.github/compatibility-test-matrices/release-v8.4.x/incentivized-ica-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.4.x/incentivized-ica-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.4.x/incentivized-transfer-chain-a.json b/.github/compatibility-test-matrices/release-v8.4.x/incentivized-transfer-chain-a.json index 6e6e343d420..5c58b8d8234 100644 --- a/.github/compatibility-test-matrices/release-v8.4.x/incentivized-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.4.x/incentivized-transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v8.4.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.4.x/incentivized-transfer-chain-b.json b/.github/compatibility-test-matrices/release-v8.4.x/incentivized-transfer-chain-b.json index bb7d5dfe150..075a3febbc4 100644 --- a/.github/compatibility-test-matrices/release-v8.4.x/incentivized-transfer-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.4.x/incentivized-transfer-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.4.x/localhost-ica-chain-a.json b/.github/compatibility-test-matrices/release-v8.4.x/localhost-ica-chain-a.json index 7f67b18a01b..3fe7463947a 100644 --- a/.github/compatibility-test-matrices/release-v8.4.x/localhost-ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.4.x/localhost-ica-chain-a.json @@ -3,6 +3,7 @@ "release-v8.4.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.4.x/localhost-transfer-chain-a.json b/.github/compatibility-test-matrices/release-v8.4.x/localhost-transfer-chain-a.json index 4d1ae7dcf70..30e197881d2 100644 --- a/.github/compatibility-test-matrices/release-v8.4.x/localhost-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.4.x/localhost-transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v8.4.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.4.x/transfer-authz-chain-a.json b/.github/compatibility-test-matrices/release-v8.4.x/transfer-authz-chain-a.json index 11ae7ca039c..ed12691ebc4 100644 --- a/.github/compatibility-test-matrices/release-v8.4.x/transfer-authz-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.4.x/transfer-authz-chain-a.json @@ -3,6 +3,7 @@ "release-v8.4.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.4.x/transfer-authz-chain-b.json b/.github/compatibility-test-matrices/release-v8.4.x/transfer-authz-chain-b.json index 64641ff3091..d624b90adfb 100644 --- a/.github/compatibility-test-matrices/release-v8.4.x/transfer-authz-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.4.x/transfer-authz-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.4.x/transfer-chain-a.json b/.github/compatibility-test-matrices/release-v8.4.x/transfer-chain-a.json index eaed8ad7c77..f9c76912326 100644 --- a/.github/compatibility-test-matrices/release-v8.4.x/transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.4.x/transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v8.4.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.4.x/transfer-chain-b.json b/.github/compatibility-test-matrices/release-v8.4.x/transfer-chain-b.json index 83191949c6f..9a28aad8b8c 100644 --- a/.github/compatibility-test-matrices/release-v8.4.x/transfer-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.4.x/transfer-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.4.x/transfer-channel-upgrade-chain-a.json b/.github/compatibility-test-matrices/release-v8.4.x/transfer-channel-upgrade-chain-a.json index abd255a88d1..213fe6e807d 100644 --- a/.github/compatibility-test-matrices/release-v8.4.x/transfer-channel-upgrade-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.4.x/transfer-channel-upgrade-chain-a.json @@ -3,6 +3,7 @@ "release-v8.4.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "release-v8.4.x" diff --git a/.github/compatibility-test-matrices/release-v8.4.x/transfer-channel-upgrade-chain-b.json b/.github/compatibility-test-matrices/release-v8.4.x/transfer-channel-upgrade-chain-b.json index 71d5a676d32..857370c4387 100644 --- a/.github/compatibility-test-matrices/release-v8.4.x/transfer-channel-upgrade-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.4.x/transfer-channel-upgrade-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "release-v8.4.x" diff --git a/.github/compatibility-test-matrices/release-v8.5.x/ica-chain-a.json b/.github/compatibility-test-matrices/release-v8.5.x/ica-chain-a.json index 23e31849731..9e9b4b158bb 100644 --- a/.github/compatibility-test-matrices/release-v8.5.x/ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.5.x/ica-chain-a.json @@ -3,6 +3,7 @@ "release-v8.5.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.5.x/ica-chain-b.json b/.github/compatibility-test-matrices/release-v8.5.x/ica-chain-b.json index 7fa55f1fcf4..867d9562232 100644 --- a/.github/compatibility-test-matrices/release-v8.5.x/ica-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.5.x/ica-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.5.x/ica-channel-upgrade-chain-a.json b/.github/compatibility-test-matrices/release-v8.5.x/ica-channel-upgrade-chain-a.json index 248c371e927..1e8168fc951 100644 --- a/.github/compatibility-test-matrices/release-v8.5.x/ica-channel-upgrade-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.5.x/ica-channel-upgrade-chain-a.json @@ -3,6 +3,7 @@ "release-v8.5.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "release-v8.5.x" diff --git a/.github/compatibility-test-matrices/release-v8.5.x/ica-channel-upgrade-chain-b.json b/.github/compatibility-test-matrices/release-v8.5.x/ica-channel-upgrade-chain-b.json index 612eabe143b..211d38509f2 100644 --- a/.github/compatibility-test-matrices/release-v8.5.x/ica-channel-upgrade-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.5.x/ica-channel-upgrade-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "release-v8.5.x" diff --git a/.github/compatibility-test-matrices/release-v8.5.x/ica-gov-chain-a.json b/.github/compatibility-test-matrices/release-v8.5.x/ica-gov-chain-a.json index 3454076cf71..fe59339328d 100644 --- a/.github/compatibility-test-matrices/release-v8.5.x/ica-gov-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.5.x/ica-gov-chain-a.json @@ -3,6 +3,7 @@ "release-v8.5.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.5.x/ica-gov-chain-b.json b/.github/compatibility-test-matrices/release-v8.5.x/ica-gov-chain-b.json index 93f579f43d9..dd131c1f321 100644 --- a/.github/compatibility-test-matrices/release-v8.5.x/ica-gov-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.5.x/ica-gov-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.5.x/ica-groups-chain-a.json b/.github/compatibility-test-matrices/release-v8.5.x/ica-groups-chain-a.json index 89e36bc1f30..c22d96f104d 100644 --- a/.github/compatibility-test-matrices/release-v8.5.x/ica-groups-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.5.x/ica-groups-chain-a.json @@ -3,6 +3,7 @@ "release-v8.5.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.5.x/ica-groups-chain-b.json b/.github/compatibility-test-matrices/release-v8.5.x/ica-groups-chain-b.json index 40b58ea8b8e..be17cb6295f 100644 --- a/.github/compatibility-test-matrices/release-v8.5.x/ica-groups-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.5.x/ica-groups-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.5.x/ica-queries-chain-a.json b/.github/compatibility-test-matrices/release-v8.5.x/ica-queries-chain-a.json index 9a195d9ceb7..a34d4dd4cf6 100644 --- a/.github/compatibility-test-matrices/release-v8.5.x/ica-queries-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.5.x/ica-queries-chain-a.json @@ -3,6 +3,7 @@ "release-v8.5.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.5.x/ica-queries-chain-b.json b/.github/compatibility-test-matrices/release-v8.5.x/ica-queries-chain-b.json index 21b53e65bb0..37e04cb23ef 100644 --- a/.github/compatibility-test-matrices/release-v8.5.x/ica-queries-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.5.x/ica-queries-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.5.x/ica-unordered-channel-chain-a.json b/.github/compatibility-test-matrices/release-v8.5.x/ica-unordered-channel-chain-a.json index 577dae489e5..63607ab24db 100644 --- a/.github/compatibility-test-matrices/release-v8.5.x/ica-unordered-channel-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.5.x/ica-unordered-channel-chain-a.json @@ -3,6 +3,7 @@ "release-v8.5.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.5.x/ica-unordered-channel-chain-b.json b/.github/compatibility-test-matrices/release-v8.5.x/ica-unordered-channel-chain-b.json index d9c364fd2a0..835d87749b3 100644 --- a/.github/compatibility-test-matrices/release-v8.5.x/ica-unordered-channel-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.5.x/ica-unordered-channel-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.5.x/incentivized-ica-chain-a.json b/.github/compatibility-test-matrices/release-v8.5.x/incentivized-ica-chain-a.json index 330964f3c79..a08b2ebea6a 100644 --- a/.github/compatibility-test-matrices/release-v8.5.x/incentivized-ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.5.x/incentivized-ica-chain-a.json @@ -3,6 +3,7 @@ "release-v8.5.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.5.x/incentivized-ica-chain-b.json b/.github/compatibility-test-matrices/release-v8.5.x/incentivized-ica-chain-b.json index 9d6412f10af..e9c546d478b 100644 --- a/.github/compatibility-test-matrices/release-v8.5.x/incentivized-ica-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.5.x/incentivized-ica-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.5.x/incentivized-transfer-chain-a.json b/.github/compatibility-test-matrices/release-v8.5.x/incentivized-transfer-chain-a.json index 528821135bb..a054c17f7b9 100644 --- a/.github/compatibility-test-matrices/release-v8.5.x/incentivized-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.5.x/incentivized-transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v8.5.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.5.x/incentivized-transfer-chain-b.json b/.github/compatibility-test-matrices/release-v8.5.x/incentivized-transfer-chain-b.json index 0e87e2c7808..ba6345b7e84 100644 --- a/.github/compatibility-test-matrices/release-v8.5.x/incentivized-transfer-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.5.x/incentivized-transfer-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.5.x/localhost-ica-chain-a.json b/.github/compatibility-test-matrices/release-v8.5.x/localhost-ica-chain-a.json index 2cda7657b7d..205806c2719 100644 --- a/.github/compatibility-test-matrices/release-v8.5.x/localhost-ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.5.x/localhost-ica-chain-a.json @@ -3,6 +3,7 @@ "release-v8.5.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.5.x/localhost-transfer-chain-a.json b/.github/compatibility-test-matrices/release-v8.5.x/localhost-transfer-chain-a.json index 7c36ff7d1a1..d4469d17571 100644 --- a/.github/compatibility-test-matrices/release-v8.5.x/localhost-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.5.x/localhost-transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v8.5.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.5.x/transfer-authz-chain-a.json b/.github/compatibility-test-matrices/release-v8.5.x/transfer-authz-chain-a.json index fff34cfb346..a7e286853ac 100644 --- a/.github/compatibility-test-matrices/release-v8.5.x/transfer-authz-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.5.x/transfer-authz-chain-a.json @@ -3,6 +3,7 @@ "release-v8.5.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.5.x/transfer-authz-chain-b.json b/.github/compatibility-test-matrices/release-v8.5.x/transfer-authz-chain-b.json index 2ec52ff3240..cd8a3a3f1f1 100644 --- a/.github/compatibility-test-matrices/release-v8.5.x/transfer-authz-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.5.x/transfer-authz-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.5.x/transfer-chain-a.json b/.github/compatibility-test-matrices/release-v8.5.x/transfer-chain-a.json index bb1176b3ad3..a68f1fd5a0a 100644 --- a/.github/compatibility-test-matrices/release-v8.5.x/transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.5.x/transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v8.5.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.5.x/transfer-chain-b.json b/.github/compatibility-test-matrices/release-v8.5.x/transfer-chain-b.json index 5ee0b1f0f6f..8297dce0672 100644 --- a/.github/compatibility-test-matrices/release-v8.5.x/transfer-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.5.x/transfer-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v8.5.x/transfer-channel-upgrade-chain-a.json b/.github/compatibility-test-matrices/release-v8.5.x/transfer-channel-upgrade-chain-a.json index e13a5647db4..066e0103644 100644 --- a/.github/compatibility-test-matrices/release-v8.5.x/transfer-channel-upgrade-chain-a.json +++ b/.github/compatibility-test-matrices/release-v8.5.x/transfer-channel-upgrade-chain-a.json @@ -3,6 +3,7 @@ "release-v8.5.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "release-v8.5.x" diff --git a/.github/compatibility-test-matrices/release-v8.5.x/transfer-channel-upgrade-chain-b.json b/.github/compatibility-test-matrices/release-v8.5.x/transfer-channel-upgrade-chain-b.json index 383154fe1eb..2301c429ccb 100644 --- a/.github/compatibility-test-matrices/release-v8.5.x/transfer-channel-upgrade-chain-b.json +++ b/.github/compatibility-test-matrices/release-v8.5.x/transfer-channel-upgrade-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "release-v8.5.x" diff --git a/.github/compatibility-test-matrices/release-v9.0.x/ica-chain-a.json b/.github/compatibility-test-matrices/release-v9.0.x/ica-chain-a.json index 0f1aed472ba..45471fdedbe 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/ica-chain-a.json @@ -3,6 +3,7 @@ "release-v9.0.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v9.0.x/ica-chain-b.json b/.github/compatibility-test-matrices/release-v9.0.x/ica-chain-b.json index 6fd799e238b..25cb87054d7 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/ica-chain-b.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/ica-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v9.0.x/ica-channel-upgrade-chain-a.json b/.github/compatibility-test-matrices/release-v9.0.x/ica-channel-upgrade-chain-a.json index fc9d57f1fed..aa84371ef9e 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/ica-channel-upgrade-chain-a.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/ica-channel-upgrade-chain-a.json @@ -3,6 +3,7 @@ "release-v9.0.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "release-v9.0.x" diff --git a/.github/compatibility-test-matrices/release-v9.0.x/ica-channel-upgrade-chain-b.json b/.github/compatibility-test-matrices/release-v9.0.x/ica-channel-upgrade-chain-b.json index c689a92c791..e7e3ed1e6c3 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/ica-channel-upgrade-chain-b.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/ica-channel-upgrade-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "release-v9.0.x" diff --git a/.github/compatibility-test-matrices/release-v9.0.x/ica-gov-chain-a.json b/.github/compatibility-test-matrices/release-v9.0.x/ica-gov-chain-a.json index e2f558a7e37..5a951ba05ff 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/ica-gov-chain-a.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/ica-gov-chain-a.json @@ -3,6 +3,7 @@ "release-v9.0.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v9.0.x/ica-gov-chain-b.json b/.github/compatibility-test-matrices/release-v9.0.x/ica-gov-chain-b.json index 8e8e6ed85a2..63da08a7d35 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/ica-gov-chain-b.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/ica-gov-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v9.0.x/ica-groups-chain-a.json b/.github/compatibility-test-matrices/release-v9.0.x/ica-groups-chain-a.json index a9bcb6f5bcf..551c9e5eecc 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/ica-groups-chain-a.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/ica-groups-chain-a.json @@ -3,6 +3,7 @@ "release-v9.0.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v9.0.x/ica-groups-chain-b.json b/.github/compatibility-test-matrices/release-v9.0.x/ica-groups-chain-b.json index 86709bca8b8..a80d2a4d46f 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/ica-groups-chain-b.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/ica-groups-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v9.0.x/ica-queries-chain-a.json b/.github/compatibility-test-matrices/release-v9.0.x/ica-queries-chain-a.json index 5976a12e19d..5cae3c5dbd4 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/ica-queries-chain-a.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/ica-queries-chain-a.json @@ -3,6 +3,7 @@ "release-v9.0.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v9.0.x/ica-queries-chain-b.json b/.github/compatibility-test-matrices/release-v9.0.x/ica-queries-chain-b.json index 065156d3b35..b11084f01d8 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/ica-queries-chain-b.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/ica-queries-chain-b.json @@ -7,6 +7,7 @@ "release-v9.0.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "release-v9.0.x" diff --git a/.github/compatibility-test-matrices/release-v9.0.x/ica-unordered-channel-chain-a.json b/.github/compatibility-test-matrices/release-v9.0.x/ica-unordered-channel-chain-a.json index 2b9157ce95e..2b5233ee8c7 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/ica-unordered-channel-chain-a.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/ica-unordered-channel-chain-a.json @@ -3,6 +3,7 @@ "release-v9.0.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v9.0.x/ica-unordered-channel-chain-b.json b/.github/compatibility-test-matrices/release-v9.0.x/ica-unordered-channel-chain-b.json index dd9b990c6c0..4b709bc1d2a 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/ica-unordered-channel-chain-b.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/ica-unordered-channel-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v9.0.x/incentivized-ica-chain-a.json b/.github/compatibility-test-matrices/release-v9.0.x/incentivized-ica-chain-a.json index 5720e7b3378..6a1bb76c6b4 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/incentivized-ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/incentivized-ica-chain-a.json @@ -3,6 +3,7 @@ "release-v9.0.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v9.0.x/incentivized-ica-chain-b.json b/.github/compatibility-test-matrices/release-v9.0.x/incentivized-ica-chain-b.json index d946dae389e..fa2c89d816d 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/incentivized-ica-chain-b.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/incentivized-ica-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v9.0.x/incentivized-transfer-chain-a.json b/.github/compatibility-test-matrices/release-v9.0.x/incentivized-transfer-chain-a.json index 768441d53b1..b08500750c5 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/incentivized-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/incentivized-transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v9.0.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v9.0.x/incentivized-transfer-chain-b.json b/.github/compatibility-test-matrices/release-v9.0.x/incentivized-transfer-chain-b.json index fb6ea5e68fe..86ed566f370 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/incentivized-transfer-chain-b.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/incentivized-transfer-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v9.0.x/localhost-ica-chain-a.json b/.github/compatibility-test-matrices/release-v9.0.x/localhost-ica-chain-a.json index 3e3399b0269..e15ccb82429 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/localhost-ica-chain-a.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/localhost-ica-chain-a.json @@ -3,6 +3,7 @@ "release-v9.0.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v9.0.x/localhost-transfer-chain-a.json b/.github/compatibility-test-matrices/release-v9.0.x/localhost-transfer-chain-a.json index 9e2671e0c8b..62c9c1644dd 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/localhost-transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/localhost-transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v9.0.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v9.0.x/transfer-authz-chain-a.json b/.github/compatibility-test-matrices/release-v9.0.x/transfer-authz-chain-a.json index 8f51caef846..1f04456329f 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/transfer-authz-chain-a.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/transfer-authz-chain-a.json @@ -3,6 +3,7 @@ "release-v9.0.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v9.0.x/transfer-authz-chain-b.json b/.github/compatibility-test-matrices/release-v9.0.x/transfer-authz-chain-b.json index 61100e64000..9d213e88cc8 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/transfer-authz-chain-b.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/transfer-authz-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v9.0.x/transfer-chain-a.json b/.github/compatibility-test-matrices/release-v9.0.x/transfer-chain-a.json index 9fbc18b18eb..f6484d6aa9f 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/transfer-chain-a.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/transfer-chain-a.json @@ -3,6 +3,7 @@ "release-v9.0.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v9.0.x/transfer-chain-b.json b/.github/compatibility-test-matrices/release-v9.0.x/transfer-chain-b.json index 497406e4567..fd977d6af2c 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/transfer-chain-b.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/transfer-chain-b.json @@ -1,5 +1,6 @@ { "chain-a": [ + "v9.0.0", "v8.5.0", "v8.4.0", "v7.8.0", diff --git a/.github/compatibility-test-matrices/release-v9.0.x/transfer-channel-upgrade-chain-a.json b/.github/compatibility-test-matrices/release-v9.0.x/transfer-channel-upgrade-chain-a.json index ae30c743d7a..5d7e3e59b21 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/transfer-channel-upgrade-chain-a.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/transfer-channel-upgrade-chain-a.json @@ -3,6 +3,7 @@ "release-v9.0.x" ], "chain-b": [ + "v9.0.0", "v8.5.0", "v8.4.0", "release-v9.0.x" diff --git a/.github/compatibility-test-matrices/release-v9.0.x/transfer-channel-upgrade-chain-a copy.json b/.github/compatibility-test-matrices/release-v9.0.x/transfer-channel-upgrade-chain-b.json similarity index 96% rename from .github/compatibility-test-matrices/release-v9.0.x/transfer-channel-upgrade-chain-a copy.json rename to .github/compatibility-test-matrices/release-v9.0.x/transfer-channel-upgrade-chain-b.json index ae30c743d7a..9aa61648920 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/transfer-channel-upgrade-chain-a copy.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/transfer-channel-upgrade-chain-b.json @@ -1,10 +1,11 @@ { "chain-a": [ + "v9.0.0", + "v8.5.0", + "v8.4.0", "release-v9.0.x" ], "chain-b": [ - "v8.5.0", - "v8.4.0", "release-v9.0.x" ], "entrypoint": [ diff --git a/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-1-channel-upgrade-chain-a.json b/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-1-channel-upgrade-chain-a.json index 54055b7f6a5..c652d92ea50 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-1-channel-upgrade-chain-a.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-1-channel-upgrade-chain-a.json @@ -3,6 +3,7 @@ "release-v9.0.x" ], "chain-b": [ + "v9.0.0", "release-v9.0.x" ], "entrypoint": [ diff --git a/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-1-channel-upgrade-chain-b.json b/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-1-channel-upgrade-chain-b.json new file mode 100644 index 00000000000..baa7b5671b1 --- /dev/null +++ b/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-1-channel-upgrade-chain-b.json @@ -0,0 +1,19 @@ +{ + "chain-a": [ + "v9.0.0", + "release-v9.0.x" + ], + "chain-b": [ + "release-v9.0.x" + ], + "entrypoint": [ + "TransferChannelUpgradesV1TestSuite" + ], + "test": [ + "TestChannelUpgrade_WithICS20v2_Succeeds", + "TestChannelUpgrade_WithFeeMiddlewareAndICS20v2_Succeeds" + ], + "relayer-type": [ + "hermes" + ] +} \ No newline at end of file diff --git a/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-2-channel-upgrade-chain-a.json b/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-2-channel-upgrade-chain-a.json index 6d34120aae7..1c911971e54 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-2-channel-upgrade-chain-a.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-2-channel-upgrade-chain-a.json @@ -3,6 +3,7 @@ "release-v9.0.x" ], "chain-b": [ + "v9.0.0", "release-v9.0.x" ], "entrypoint": [ diff --git a/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-2-channel-upgrade-chain-b.json b/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-2-channel-upgrade-chain-b.json new file mode 100644 index 00000000000..db049e69553 --- /dev/null +++ b/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-2-channel-upgrade-chain-b.json @@ -0,0 +1,18 @@ +{ + "chain-a": [ + "v9.0.0", + "release-v9.0.x" + ], + "chain-b": [ + "release-v9.0.x" + ], + "entrypoint": [ + "TestTransferChannelUpgradesTestSuite" + ], + "test": [ + "TestChannelDowngrade_WithICS20v1_Succeeds" + ], + "relayer-type": [ + "hermes" + ] +} \ No newline at end of file diff --git a/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-forwarding-chain-a.json b/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-forwarding-chain-a.json index e161d7ae8a1..1e0f7149632 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-forwarding-chain-a.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-forwarding-chain-a.json @@ -3,6 +3,7 @@ "release-v9.0.x" ], "chain-b": [ + "v9.0.0", "release-v9.0.x" ], "entrypoint": [ diff --git a/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-forwarding-chain-b.json b/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-forwarding-chain-b.json new file mode 100644 index 00000000000..e433e06e97d --- /dev/null +++ b/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-forwarding-chain-b.json @@ -0,0 +1,22 @@ +{ + "chain-a": [ + "v9.0.0", + "release-v9.0.x" + ], + "chain-b": [ + "release-v9.0.x" + ], + "entrypoint": [ + "TransferForwardingTestSuite" + ], + "test": [ + "TestForwarding_Succeeds", + "TestForwarding_WithLastChainBeingICS20v1_Succeeds", + "TestForwardingWithUnwindSucceeds", + "TestFailedForwarding", + "TestChannelUpgradeForwarding_Succeeds" + ], + "relayer-type": [ + "hermes" + ] +} \ No newline at end of file diff --git a/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-multidenom-chain-a.json b/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-multidenom-chain-a.json index 60de14c5609..65c840b313c 100644 --- a/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-multidenom-chain-a.json +++ b/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-multidenom-chain-a.json @@ -3,6 +3,7 @@ "release-v9.0.x" ], "chain-b": [ + "v9.0.0", "release-v9.0.x" ], "entrypoint": [ diff --git a/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-multidenom-chain-b.json b/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-multidenom-chain-b.json new file mode 100644 index 00000000000..2962f7e7d80 --- /dev/null +++ b/.github/compatibility-test-matrices/release-v9.0.x/transfer-v2-multidenom-chain-b.json @@ -0,0 +1,19 @@ +{ + "chain-a": [ + "v9.0.0", + "release-v9.0.x" + ], + "chain-b": [ + "release-v9.0.x" + ], + "entrypoint": [ + "TestTransferTestSuite" + ], + "test": [ + "TestMsgTransfer_Succeeds_Nonincentivized_MultiDenom", + "TestMsgTransfer_Fails_InvalidAddress_MultiDenom" + ], + "relayer-type": [ + "hermes" + ] +} \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 75e9fb10fae..075390e7013 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -38,14 +38,6 @@ updates: labels: - dependencies - - package-ecosystem: gomod - directory: "/modules/capability" - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - dependencies - - package-ecosystem: gomod directory: "/simapp" schedule: @@ -53,5 +45,3 @@ updates: open-pull-requests-limit: 10 labels: - dependencies - - diff --git a/.github/mergify.yml b/.github/mergify.yml index 09eb23e64b0..d8bb1105e59 100644 --- a/.github/mergify.yml +++ b/.github/mergify.yml @@ -1,6 +1,9 @@ queue_rules: - name: default - conditions: + commit_message_template: | + {{ title }} (#{{ number }}) + {{ body }} + merge_conditions: - "#approved-reviews-by>=1" - base=main - label=automerge @@ -14,18 +17,7 @@ pull_request_rules: actions: queue: name: default - method: squash - commit_message_template: | - {{ title }} (#{{ number }}) - {{ body }} - - name: backport patches to v1.0.x capability branch - conditions: - - base=main - - label=backport-capability-to-v1.0.x - actions: - backport: - branches: - - capability/release/v1.0.x + merge_method: squash - name: backport patches to v0.1.x callbacks ibc-go v7.3.x branch conditions: - base=main @@ -65,7 +57,7 @@ pull_request_rules: actions: backport: branches: - - 08-wasm/release/v0.4.x+ibc-go-v8.4.x-wasmvm-v2.0.x + - 08-wasm/release/v0.4.x+ibc-go-v8.4.x-wasmvm-v2.0.x - name: backport patches to v0.5.x wasm ibc-go v9.0.x & wasmvm 2.1.x branch conditions: - base=main @@ -73,7 +65,7 @@ pull_request_rules: actions: backport: branches: - - 08-wasm/release/v0.5.x+ibc-go-v9.0.x-wasmvm-v2.1.x + - 08-wasm/release/v0.5.x+ibc-go-v9.0.x-wasmvm-v2.1.x - name: backport patches to v7.4.x branch conditions: - base=main @@ -89,7 +81,7 @@ pull_request_rules: actions: backport: branches: - - release/v7.5.x + - release/v7.5.x - name: backport patches to v7.6.x branch conditions: - base=main diff --git a/.github/workflows/callbacks.yml b/.github/workflows/callbacks.yml index c09e14b9387..db3f56d7984 100644 --- a/.github/workflows/callbacks.yml +++ b/.github/workflows/callbacks.yml @@ -21,7 +21,7 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: golangci/golangci-lint-action@v6.1.0 + - uses: golangci/golangci-lint-action@v6.1.1 with: version: v1.57.2 only-new-issues: true @@ -62,7 +62,7 @@ jobs: steps: - name: sonarcloud if: ${{ env.GIT_DIFF && !github.event.pull_request.draft && env.SONAR_TOKEN != null }} - uses: SonarSource/sonarcloud-github-action@v3.0.0 + uses: SonarSource/sonarcloud-github-action@v3.1.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 25c05965007..24226ac5c7a 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -27,7 +27,7 @@ jobs: run: make build-docs - name: Deploy 🚀 - uses: JamesIves/github-pages-deploy-action@v4.6.4 + uses: JamesIves/github-pages-deploy-action@v4.6.8 with: branch: gh-pages folder: docs/build diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index f61ded50503..f6d30419b75 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -28,7 +28,7 @@ jobs: images: ${{ env.REGISTRY }}/cosmos/${{ env.IMAGE_NAME }} - name: Build Docker image - uses: docker/build-push-action@5cd11c3a4ced054e52742c5fd54dca954e0edd85 + uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 with: context: . tags: ${{ steps.meta.outputs.tags }} @@ -46,7 +46,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Push Docker image - uses: docker/build-push-action@5cd11c3a4ced054e52742c5fd54dca954e0edd85 + uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 with: context: . push: true diff --git a/.github/workflows/e2e-manual-simd.yaml b/.github/workflows/e2e-manual-simd.yaml index 94aa86aa425..d2ec7b5c081 100644 --- a/.github/workflows/e2e-manual-simd.yaml +++ b/.github/workflows/e2e-manual-simd.yaml @@ -35,6 +35,7 @@ on: default: main options: - main + - v9.0.0 - v8.5.0 - v8.4.0 - v7.7.0 @@ -52,6 +53,7 @@ on: type: choice options: - main + - v9.0.0 - v8.5.0 - v8.4.0 - v7.7.0 diff --git a/.github/workflows/e2e-test-workflow-call.yml b/.github/workflows/e2e-test-workflow-call.yml index 76bcadd5528..9302c82446f 100644 --- a/.github/workflows/e2e-test-workflow-call.yml +++ b/.github/workflows/e2e-test-workflow-call.yml @@ -132,7 +132,7 @@ jobs: - name: Build and push Docker image if: ${{ inputs.build-and-push-docker-image }} - uses: docker/build-push-action@5cd11c3a4ced054e52742c5fd54dca954e0edd85 + uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 with: context: . push: true @@ -179,7 +179,7 @@ jobs: - name: Build and push Docker image if: ${{ inputs.build-and-push-docker-image-wasm }} - uses: docker/build-push-action@5cd11c3a4ced054e52742c5fd54dca954e0edd85 + uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 with: context: . push: true diff --git a/.github/workflows/e2emodule.yml b/.github/workflows/e2emodule.yml index 3554d6ce99f..2cd7501c7dd 100644 --- a/.github/workflows/e2emodule.yml +++ b/.github/workflows/e2emodule.yml @@ -22,7 +22,7 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: golangci/golangci-lint-action@v6.1.0 + - uses: golangci/golangci-lint-action@v6.1.1 with: version: v1.57.2 only-new-issues: true diff --git a/.github/workflows/golangci-feature.yml b/.github/workflows/golangci-feature.yml index 9476a8a35db..3a2947a7abd 100644 --- a/.github/workflows/golangci-feature.yml +++ b/.github/workflows/golangci-feature.yml @@ -27,7 +27,7 @@ jobs: with: fetch-depth: 0 - name: golangci-lint - uses: golangci/golangci-lint-action@v6.1.0 + uses: golangci/golangci-lint-action@v6.1.1 with: version: v1.57.2 only-new-issues: true diff --git a/.github/workflows/golangci.yml b/.github/workflows/golangci.yml index 4097aa3e081..455439b7ebd 100644 --- a/.github/workflows/golangci.yml +++ b/.github/workflows/golangci.yml @@ -23,7 +23,7 @@ jobs: with: fetch-depth: 0 - name: golangci-lint - uses: golangci/golangci-lint-action@v6.1.0 + uses: golangci/golangci-lint-action@v6.1.1 with: version: v1.57.2 only-new-issues: true diff --git a/.github/workflows/proto-breaking-check.yml b/.github/workflows/proto-breaking-check.yml new file mode 100644 index 00000000000..8e675beb0f3 --- /dev/null +++ b/.github/workflows/proto-breaking-check.yml @@ -0,0 +1,16 @@ +name: proto breaking check +# proto breaking check workflow checks if Protobuf file contains breaking changes. +# This workflow runs when a PR that targets Protobuf is opened. +on: + merge_group: + pull_request: + paths: + - "proto/**/*.proto" + +jobs: + proto-breaking-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Run proto-breaking check + run: make proto-check-breaking \ No newline at end of file diff --git a/.github/workflows/proto-registry.yml b/.github/workflows/proto-registry.yml index 3b2ef58e0ed..1718d649af8 100644 --- a/.github/workflows/proto-registry.yml +++ b/.github/workflows/proto-registry.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: bufbuild/buf-setup-action@v1.41.0 + - uses: bufbuild/buf-setup-action@v1.45.0 - uses: bufbuild/buf-push-action@v1 with: input: "proto" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f6f6a875ce8..19ccf6083d6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -52,7 +52,7 @@ jobs: images: ${{ env.REGISTRY }}/cosmos/${{ env.IMAGE_NAME }} - name: Build and push Docker image - uses: docker/build-push-action@5cd11c3a4ced054e52742c5fd54dca954e0edd85 + uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 with: context: . push: true diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 356bfc291fe..0efed2df15b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -146,7 +146,7 @@ jobs: name: '${{ github.sha }}-03-coverage' - name: sonarcloud if: ${{ env.GIT_DIFF && !github.event.pull_request.draft }} - uses: SonarSource/sonarcloud-github-action@v3.0.0 + uses: SonarSource/sonarcloud-github-action@v3.1.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.github/workflows/wasm-client.yml b/.github/workflows/wasm-client.yml index 47046d33cde..187550bec23 100644 --- a/.github/workflows/wasm-client.yml +++ b/.github/workflows/wasm-client.yml @@ -20,7 +20,7 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: golangci/golangci-lint-action@v6.1.0 + - uses: golangci/golangci-lint-action@v6.1.1 with: version: v1.57.2 only-new-issues: true @@ -68,7 +68,7 @@ jobs: steps: - name: sonarcloud if: ${{ env.GIT_DIFF && !github.event.pull_request.draft && env.SONAR_TOKEN != null }} - uses: SonarSource/sonarcloud-github-action@v3.0.0 + uses: SonarSource/sonarcloud-github-action@v3.1.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.golangci.yml b/.golangci.yml index 32cd4cb67af..99a7c1eadf8 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -5,7 +5,6 @@ run: linters: disable-all: true enable: - - exportloopref - errcheck - gci - goconst diff --git a/.markdownlint-cli2.jsonc b/.markdownlint-cli2.jsonc index fa24257664c..bfa7772916f 100644 --- a/.markdownlint-cli2.jsonc +++ b/.markdownlint-cli2.jsonc @@ -6,7 +6,6 @@ ".github", "**/CHANGELOG.md", "vendor/**", - "e2e/vendor/**", - "modules/capability/vendor/**" + "e2e/vendor/**" ] -} +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dc9c417934..e68c1a222da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +### Testing + +* [\#7430](https://github.com/cosmos/ibc-go/pull/7430) Update the block proposer in test chains for each block. + ### Dependencies * [\#7247](https://github.com/cosmos/ibc-go/pull/7247) Bump CometBFT to v0.38.12. @@ -51,7 +55,8 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (core/24-host) [\#7239](https://github.com/cosmos/ibc-go/pull/7239) Removed function `ChannelCapabilityPath` * (apps/27-interchain-accounts) [\#7239](https://github.com/cosmos/ibc-go/pull/7239) The following functions have been removed: `AuthenticateCapability`, `ClaimCapability` * (apps/transfer) [\#7239](https://github.com/cosmos/ibc-go/pull/7239) The following functions have been removed: `BindPort`, `AuthenticateCapability`, `ClaimCapability` -* (capability) [\#7279](https://github.com/cosmos/ibc-go/pull/7279) The module `capability` has been removed +* (capability) [\#7279](https://github.com/cosmos/ibc-go/pull/7279) The module `capability` has been removed. +* (testing) [\#7305](https://github.com/cosmos/ibc-go/pull/7305) Added `TrustedValidators` map to `TestChain`. This removes the dependency on the `x/staking` module for retrieving trusted validator sets at a given height, and removes the `GetTrustedValidators` method from the `TestChain` struct. ### State Machine Breaking @@ -62,11 +67,14 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Bug Fixes * (apps/27-interchain-accounts) [\#7277](https://github.com/cosmos/ibc-go/pull/7277) Use `GogoResolver` when populating module query safe allow list to avoid panics from unresolvable protobuf dependencies. +* (core/04-channel) [\#7342](https://github.com/cosmos/ibc-go/pull/7342) Read Tx cmd flags including from address to avoid Address cannot be empty error when upgrade-channels via cli. +* (core/03-connection) [\#7397](https://github.com/cosmos/ibc-go/pull/7397) Skip the genesis validation connectionID for localhost client. -## v9.0.0 (unreleased) +## [v9.0.0](https://github.com/cosmos/ibc-go/releases/tag/v9.0.0) - 2024-10-01 ### Dependencies +* [\#6828](https://github.com/cosmos/ibc-go/pull/6828) Bump Cosmos SDK to v0.50.9. * [\#6193](https://github.com/cosmos/ibc-go/pull/6193) Bump `cosmossdk.io/store` to v1.1.0. * [\#7126](https://github.com/cosmos/ibc-go/pull/7126) Bump CometBFT to v0.38.11. * [\#6380](https://github.com/cosmos/ibc-go/pull/6380) Bump go to v1.22. @@ -74,16 +82,9 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### API Breaking -* (apps/27-interchain-accounts) [\#4977](https://github.com/cosmos/ibc-go/pull/4977) The `InitModule` function has been removed. -* (core/02-client) [\#5110](https://github.com/cosmos/ibc-go/pull/5110) The `header` attribute has been removed from the `update_client` event. -* (apps/27-interchain-accounts) [\#5396](https://github.com/cosmos/ibc-go/pull/5396) Remove `GetBytes` function of `CosmosTx` type. -* (core/04-channel) [\#5691](https://github.com/cosmos/ibc-go/pull/5691) Remove functions `IsOpen` and `IsClosed` of `Channel` type. -* (core/04-channel) [\#5705](https://github.com/cosmos/ibc-go/pull/5705) Remove functions `GetState`, `GetOrdering`, `GetCounterparty`, `GetConnectionHops`, `GetVersion` of the `Channel` type. -* (core/04-channel) [\#5603](https://github.com/cosmos/ibc-go/pull/5603) Rename attribute names and constants for channel upgrades events. * (core/02-client, light-clients) [\#5806](https://github.com/cosmos/ibc-go/pull/5806) Decouple light client routing from their encoding structure. * (core/04-channel) [\#5991](https://github.com/cosmos/ibc-go/pull/5991) The client CLI `QueryLatestConsensusState` has been removed. * (light-clients/06-solomachine) [\#6037](https://github.com/cosmos/ibc-go/pull/6037) Remove `Initialize` function from `ClientState` and move logic to `Initialize` function of `LightClientModule`. -- (core/04-channel) [\#6063](https://github.com/cosmos/ibc-go/pull/6063) Remove attributes `version`, `ordering` and `connection_hops` from the `channel_upgrade_init`, `channel_upgrade_try`, `channel_upgrade_ack`, `channel_upgrade_open`, `channel_upgrade_timeout` and `channel_upgrade_cancelled` events. * (light-clients/06-solomachine) [\#6230](https://github.com/cosmos/ibc-go/pull/6230) Remove `GetTimestampAtHeight`, `Status` and `UpdateStateOnMisbehaviour` functions from `ClientState` and move logic to functions of `LightClientModule`. * (core/02-client) [\#6084](https://github.com/cosmos/ibc-go/pull/6084) Removed `stakingKeeper` as an argument to `NewKeeper` and replaced with a `ConsensusHost` implementation. * (testing) [\#6070](https://github.com/cosmos/ibc-go/pull/6070) Remove `AssertEventsLegacy` function. @@ -91,7 +92,6 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (core/04-channel) [\#6023](https://github.com/cosmos/ibc-go/pull/6023) Remove emission of non-hexlified event attributes `packet_data` and `packet_ack`. * (core) [\#6320](https://github.com/cosmos/ibc-go/pull/6320) Remove unnecessary `Proof` interface from `exported` package. * (core/05-port) [\#6341](https://github.com/cosmos/ibc-go/pull/6341) Modify `UnmarshalPacketData` interface to take in the context, portID, and channelID. This allows for packet data's to be unmarshaled based on the channel version. -* (core/05-port) [\#6341](https://github.com/cosmos/ibc-go/pull/6988) Modify `UnmarshalPacketData` interface to return the underlying application version. * (apps/27-interchain-accounts) [\#6433](https://github.com/cosmos/ibc-go/pull/6433) Use UNORDERED as the default ordering for new ICA channels. * (apps/transfer) [\#6440](https://github.com/cosmos/ibc-go/pull/6440) Remove `GetPrefixedDenom`. * (apps/transfer) [\#6508](https://github.com/cosmos/ibc-go/pull/6508) Remove the `DenomTrace` type. @@ -106,12 +106,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (light-clients/06-solomachine, light-clients/07-tendermint) [\#6891](https://github.com/cosmos/ibc-go/pull/6891) The `VerifyMembership` and `VerifyNonMembership` functions of solomachine's `ClientState` have been made private. The `VerifyMembership`, `VerifyNonMembership`, `GetTimestampAtHeight`, `Status` and `Initialize` functions of tendermint's `ClientState` have been made private. * (core/04-channel) [\#6902](https://github.com/cosmos/ibc-go/pull/6902) Add channel version to core application callbacks. * (core/03-connection, core/02-client) [\#6937](https://github.com/cosmos/ibc-go/pull/6937) Remove 'ConsensusHost' interface, also removing self client and consensus state validation in the connection handshake. -* (core/24-host) [\#6882](https://github.com/cosmos/ibc-go/issues/6882) All functions ending in `Path` have been removed from 24-host in favour of their sibling functions ending in `Key`. -* (apps/27-interchain-accounts) [\#7053](https://github.com/cosmos/ibc-go/pull/7053) Remove ICS27 channel capability migration introduced in v6. +* (core/24-host) [\#6882](https://github.com/cosmos/ibc-go/issues/6882) All functions ending in `Path` have been removed from 24-host in favour of their sybling functions ending in `Key`. ### State Machine Breaking -* (light-clients/07-tendermint) [\#6276](https://github.com/cosmos/ibc-go/pull/6276) Fix: No-op to avoid panicking on `UpdateState` for invalid misbehaviour submissions. * (light-clients/06-solomachine) [\#6313](https://github.com/cosmos/ibc-go/pull/6313) Fix: No-op to avoid panicking on `UpdateState` for invalid misbehaviour submissions. ### Improvements diff --git a/README.md b/README.md index 6e9121191a6..0aa4762a1b1 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ For the latest expected release timelines, please check [here](https://github.co ## Releases -The release lines currently supported are v7 and v8. +The release lines currently supported are v7, v8 and v9. Please refer to the [Stable Release Policy section of RELEASES.md](https://github.com/cosmos/ibc-go/blob/main/RELEASES.md#stable-release-policy) for more details. @@ -93,6 +93,7 @@ To report a security vulnerability, see our [Coordinated Vulnerability Disclosur The following audits have been performed on the `ibc-go` source code: - [ICS20 Fungible Token Transfer](https://github.com/informalsystems/audits/tree/dc8b503727adcbb8e29c3d3a25a9070e0bf1ec87/IBC-GO) by Informal Systems. +- [ICS20 Fungible Token Transfer V2](https://github.com/cosmos/ibc-go/blob/main/docs/audits/20-token-transfer/Atredis%20Partners%20-%20Interchain%20ICS20%20v2%20New%20Features%20Assessment%20-%20Report%20v1.0.pdf) by Atredis Partners. - ICS27 Interchain Accounts by [Trail of Bits](https://github.com/cosmos/ibc-go/blob/main/docs/audits/27-interchain-accounts/Trail%20of%20Bits%20audit%20-%20Final%20Report.pdf) and [Informal Systems](https://github.com/cosmos/ibc-go/issues/631). - [ICS08 Wasm Clients](https://github.com/cosmos/ibc-go/blob/main/docs/audits/08-wasm/Ethan%20Frey%20-%20Wasm%20Client%20Review.pdf) by Ethan Frey/Confio. - [ICS04 Channel upgradability](https://github.com/cosmos/ibc-go/blob/main/docs/audits/04-channel-upgrades/Atredis%20Partners%20-%20Interchain%20Foundation%20IBC-Go%20Channel%20Upgrade%20Feature%20Assessment%20-%20Report%20v1.1.pdf) by Atredis Partners. diff --git a/RELEASES.md b/RELEASES.md index 61db2b75376..287d9994c52 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -78,19 +78,20 @@ We reserve the right to drop support for releases if they are deemed unused (for |`v7.8.x`|March 17, 2025| |`v8.4.x`|May 10, 2025| |`v8.5.x`|May 10, 2025| +|`v9.0.x`|October 1, 2025| ### Callbacks middleware |Release|End of Life Date| |-------|----------------| -|`v0.1.x+ibc-go-v7.3.x`|September 17, 2024| +|`v0.1.x+ibc-go-v7.3.x`|March 17, 2025| |`v0.1.x+ibc-go-v8.0.x`|May 10, 2025| ### `08-wasm` light client proxy module |Release|End of Life Date| |-------|----------------| -|`v0.3.x+ibc-go-v7.4.x-wasmvm-v1.5.x`|September 17, 2024| +|`v0.3.x+ibc-go-v7.4.x-wasmvm-v1.5.x`|March 17, 2025| |`v0.4.x+ibc-go-v8.4.x-wasmvm-v2.0.x`|May 10, 2025| ### What pull requests will be included in stable patch-releases? @@ -133,6 +134,7 @@ Versions of Golang, Cosmos SDK and CometBFT used by ibc-go in the currently acti | 1.19 | v7.8.0 | v0.47.13 | v0.37.5 | | 1.21 | v8.4.0 | v0.50.7 | v0.38.7 | | 1.21 | v8.5.0 | v0.50.9 | v0.38.11 | +| 1.22 | v9.0.0 | v0.50.9 | v0.38.11 | ### Callbacks middleware diff --git a/docs/audits/20-token-transfer/Atredis Partners - Interchain ICS20 v2 New Features Assessment - Report v1.0.pdf b/docs/audits/20-token-transfer/Atredis Partners - Interchain ICS20 v2 New Features Assessment - Report v1.0.pdf new file mode 100644 index 00000000000..6776c46c57b Binary files /dev/null and b/docs/audits/20-token-transfer/Atredis Partners - Interchain ICS20 v2 New Features Assessment - Report v1.0.pdf differ diff --git a/docs/dev/project-structure.md b/docs/dev/project-structure.md index b3e7dce1914..7138d65c7fb 100644 --- a/docs/dev/project-structure.md +++ b/docs/dev/project-structure.md @@ -8,10 +8,6 @@ Every Interchain Standard (ICS) has been developed in its own package. The devel This folder contains implementations for the IBC TAO (`core`), IBC applications (`apps`) and light clients (`light-clients`). -### `capability` - -This module is an implementation of [Cosmos SDK's ADR 003](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-003-dynamic-capability-store.md) that allows for provisioning, tracking, and authenticating multi-owner capabilities at runtime. - ### `core` - `02-client`: This package is an implementation for Cosmos SDK-based chains of [ICS 02](https://github.com/cosmos/ibc/tree/main/spec/core/ics-002-client-semantics). This implementation defines the types and methods needed to operate light clients tracking other chain's consensus state. diff --git a/docs/dev/release-management.md b/docs/dev/release-management.md index 3b3ebc36953..246f1bd3ea3 100644 --- a/docs/dev/release-management.md +++ b/docs/dev/release-management.md @@ -1,5 +1,7 @@ # Tagging a release +Before tagging a new release, please run the [compatibility e2e test suite](https://github.com/cosmos/ibc-go/actions/workflows/e2e-compatibility.yaml) for the corresponding release line. + ## New major release branch Pre-requisites for creating a release branch for a new major version: @@ -70,17 +72,15 @@ Additionally, for the first point release of a new major or minor release branch - Update the [list of supported release lines in README.md](../../RELEASES.md#releases), if necessary. - Update the [e2e compatibility test matrices](https://github.com/cosmos/ibc-go/tree/main/.github/compatibility-test-matrices): add the tag for the new release and remove any tags that might not be recommended anymore. - Update the manual [e2e `simd`](https://github.com/cosmos/ibc-go/blob/main/.github/workflows/e2e-manual-simd.yaml) test workflow: - - Remove any tags that might not be recommended anymore. - -- Bump ibc-go version in [cosmos/interchain-accounts-demo repository](https://github.com/cosmos/interchain-accounts-demo) and create a tag. -- [ ] Update docs site: - - [ ] If the release is occurring on the main branch, on the latest version, then run `npm run docusaurus docs:version vX.Y.Z` in the `docs/` directory. (where `X.Y.Z` is the new version number) - - [ ] If the release is occurring on an older release branch, then make a PR to the main branch called `docs: new release vX.Y.Z` doing the following: - - [ ] Update the content of the docs found in `docs/versioned_docs/version-vx.y.z` if needed. (where `x.y.z` is the previous version number) - - [ ] Update the version number of the older release branch by changing the version number of the older release branch in: - - [ ] In `docs/versions.json`. - - [ ] Rename `docs/versioned_sidebars/version-vx.y.z-sidebars.json` - - [ ] Rename `docs/versioned_docs/version-vx.y.z` + - Remove any tags that might not be recommended anymore. +- Update docs site: + - If the release is occurring on the main branch, on the latest version, then run `npm run docusaurus docs:version vX.Y.Z` in the `docs/` directory. (where `X.Y.Z` is the new version number) + - If the release is occurring on an older release branch, then make a PR to the main branch called `docs: new release vX.Y.Z` doing the following: + - Update the content of the docs found in `docs/versioned_docs/version-vx.y.z` if needed. (where `x.y.z` is the previous version number) + - Update the version number of the older release branch by changing the version number of the older release branch in: + - In `docs/versions.json`. + - Rename `docs/versioned_sidebars/version-vx.y.z-sidebars.json` + - Rename `docs/versioned_docs/version-vx.y.z` - After changes to docs site are deployed, check [ibc.cosmos.network](https://ibc.cosmos.network) is updated. - Open issue in [SDK tutorials repo](https://github.com/cosmos/sdk-tutorials) to update tutorials to the released version of ibc-go. diff --git a/docs/docs/01-ibc/01-overview.md b/docs/docs/01-ibc/01-overview.md index 3342ec6a581..d2918a09519 100644 --- a/docs/docs/01-ibc/01-overview.md +++ b/docs/docs/01-ibc/01-overview.md @@ -160,34 +160,6 @@ Proofs are passed from core IBC to light clients as bytes. It is up to light cli [ICS-24 Host State Machine Requirements](https://github.com/cosmos/ics/tree/master/spec/core/ics-024-host-requirements). - The proof format that all implementations must be able to produce and verify is defined in [ICS-23 Proofs](https://github.com/cosmos/ics23) implementation. -### [Capabilities](https://github.com/cosmos/cosmos-sdk/blob/main/docs/learn/advanced/10-ocap.md) - -IBC is intended to work in execution environments where modules do not necessarily trust each -other. Thus, IBC must authenticate module actions on ports and channels so that only modules with the -appropriate permissions can use them. - -This module authentication is accomplished using a [dynamic -capability store](https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-003-dynamic-capability-store.md). Upon binding to a port or -creating a channel for a module, IBC returns a dynamic capability that the module must claim in -order to use that port or channel. The dynamic capability module prevents other modules from using that port or channel since -they do not own the appropriate capability. - -While this background information is useful, IBC modules do not need to interact at all with -these lower-level abstractions. The relevant abstraction layer for IBC application developers is -that of channels and ports. IBC applications must be written as self-contained **modules**. - -A module on one blockchain can communicate with other modules on other blockchains by sending, -receiving, and acknowledging packets through channels that are uniquely identified by the -`(channelID, portID)` tuple. - -A useful analogy is to consider IBC modules as internet applications on -a computer. A channel can then be conceptualized as an IP connection, with the IBC port ID being -analogous to an IP port and the IBC channel ID being analogous to an IP address. Thus, a single -instance of an IBC module can communicate on the same port with any number of other modules and -IBC correctly routes all packets to the relevant module using the (channel ID, port ID) tuple. An -IBC module can also communicate with another IBC module over multiple ports, with each -`(portID<->portID)` packet stream being sent on a different unique channel. - ### [Ports](https://github.com/cosmos/ibc-go/blob/main/modules/core/05-port) An IBC module can bind to any number of ports. Each port must be identified by a unique `portID`. @@ -229,11 +201,6 @@ on `ChanOpenInit`, the module on chain A executes its callback `OnChanOpenInit`. The channel identifier is auto derived in the format: `channel-{N}` where `N` is the next sequence to be used. -Just as ports came with dynamic capabilities, channel initialization returns a dynamic capability -that the module **must** claim so that they can pass in a capability to authenticate channel actions -like sending packets. The channel capability is passed into the callback on the first parts of the -handshake; either `OnChanOpenInit` on the initializing chain or `OnChanOpenTry` on the other chain. - #### Closing channels Closing a channel occurs in 2 handshake steps as defined in [ICS 04](https://github.com/cosmos/ibc/tree/master/spec/core/ics-004-channel-and-packet-semantics). diff --git a/docs/docs/01-ibc/02-integration.md b/docs/docs/01-ibc/02-integration.md index 5af103bdf6e..def03102de0 100644 --- a/docs/docs/01-ibc/02-integration.md +++ b/docs/docs/01-ibc/02-integration.md @@ -36,7 +36,6 @@ We need to register the core `ibc` and `transfer` `Keeper`s as follows: import ( // other imports // ... - capabilitykeeper "github.com/cosmos/ibc-go/modules/capability/keeper" ibckeeper "github.com/cosmos/ibc-go/v9/modules/core/keeper" ibctransferkeeper "github.com/cosmos/ibc-go/v9/modules/apps/transfer/keeper" ) @@ -49,10 +48,6 @@ type App struct { IBCKeeper *ibckeeper.Keeper // IBC Keeper must be a pointer in the app, so we can SetRouter on it correctly TransferKeeper ibctransferkeeper.Keeper // for cross-chain fungible token transfers - // make scoped keepers public for test purposes - ScopedIBCKeeper capabilitykeeper.ScopedKeeper - ScopedTransferKeeper capabilitykeeper.ScopedKeeper - // ... // module and simulation manager definitions } @@ -169,7 +164,6 @@ import ( "github.com/cosmos/cosmos-sdk/types/module" ibc "github.com/cosmos/ibc-go/v9/modules/core" - "github.com/cosmos/ibc-go/modules/capability" "github.com/cosmos/ibc-go/v9/modules/apps/transfer" ) @@ -180,7 +174,6 @@ func NewApp(...args) *App { // other modules // ... // highlight-start -+ capability.NewAppModule(appCodec, *app.CapabilityKeeper, false), + ibc.NewAppModule(app.IBCKeeper), + transfer.NewAppModule(app.TransferKeeper), // highlight-end @@ -251,7 +244,6 @@ tmLightClientModule := ibctm.NewLightClientModule(appCodec, storeProvider) app.IBCKeeper.ClientKeeper.AddRoute(ibctm.ModuleName, &tmLightClientModule) app.ModuleManager = module.NewManager( // ... - capability.NewAppModule(appCodec, *app.CapabilityKeeper, false), ibc.NewAppModule(app.IBCKeeper), transfer.NewAppModule(app.TransferKeeper), // i.e ibc-transfer module @@ -273,7 +265,6 @@ import ( // other imports // ... stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - capabilitytypes "github.com/cosmos/ibc-go/modules/capability/types" ibcexported "github.com/cosmos/ibc-go/v9/modules/core/exported" ibckeeper "github.com/cosmos/ibc-go/v9/modules/core/keeper" ibctransfertypes "github.com/cosmos/ibc-go/v9/modules/apps/transfer/types" @@ -283,11 +274,8 @@ func NewApp(...args) *App { // ... continuation from above // add x/staking, ibc and transfer modules to BeginBlockers - // capability module's Beginblocker must come before any - // modules using capabilities (e.g. IBC) app.ModuleManager.SetOrderBeginBlockers( // other modules ... - capabilitytypes.ModuleName, stakingtypes.ModuleName, ibcexported.ModuleName, ibctransfertypes.ModuleName, @@ -297,16 +285,11 @@ func NewApp(...args) *App { stakingtypes.ModuleName, ibcexported.ModuleName, ibctransfertypes.ModuleName, - capabilitytypes.ModuleName, ) // ... - // NOTE: Capability module must occur first so that it can initialize any capabilities - // so that other modules that want to create or claim capabilities afterwards in InitChain - // can do so safely. genesisModuleOrder := []string{ - capabilitytypes.ModuleName, // other modules // ... ibcexported.ModuleName, @@ -317,10 +300,6 @@ func NewApp(...args) *App { // ... continues ``` -:::warning -**IMPORTANT**: The capability module **must** be declared first in `SetOrderBeginBlockers` and `SetOrderInitGenesis`. -::: - That's it! You have now wired up the IBC module and the `transfer` module, and are now able to send fungible tokens across different chains. If you want to have a broader view of the changes take a look into the SDK's [`SimApp`](https://github.com/cosmos/ibc-go/blob/main/testing/simapp/app.go). diff --git a/docs/docs/01-ibc/03-apps/01-apps.md b/docs/docs/01-ibc/03-apps/01-apps.md index eacd37d24cc..dba8f1e903f 100644 --- a/docs/docs/01-ibc/03-apps/01-apps.md +++ b/docs/docs/01-ibc/03-apps/01-apps.md @@ -51,14 +51,9 @@ func (k Keeper) OnChanOpenInit(ctx sdk.Context, connectionHops []string, portID string, channelID string, - channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, version string, ) error { - // OpenInit must claim the channelCapability that IBC passes into the callback - if err := k.ClaimCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)); err != nil { - return err - } // ... do custom initialization logic @@ -76,15 +71,9 @@ OnChanOpenTry( connectionHops []string, portID, channelID string, - channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, counterpartyVersion string, ) (string, error) { - // OpenTry must claim the channelCapability that IBC passes into the callback - if err := k.scopedKeeper.ClaimCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)); err != nil { - return err - } - // ... do custom initialization logic // Use above arguments to determine if we want to abort handshake @@ -187,34 +176,6 @@ encoded version into each handhshake call as necessary. ICS20 currently implements basic string matching with a single supported version. -### Bind Ports - -Currently, ports must be bound on app initialization. A module may bind to ports in `InitGenesis` -like so: - -```go -func InitGenesis(ctx sdk.Context, keeper keeper.Keeper, state types.GenesisState) { - // ... other initialization logic - - // Only try to bind to port if it is not already bound, since we may already own - // port capability from capability InitGenesis - if !hasCapability(ctx, state.PortID) { - // module binds to desired ports on InitChain - // and claims returned capabilities - cap1 := keeper.IBCPortKeeper.BindPort(ctx, port1) - cap2 := keeper.IBCPortKeeper.BindPort(ctx, port2) - cap3 := keeper.IBCPortKeeper.BindPort(ctx, port3) - - // NOTE: The module's scoped capability keeper must be private - keeper.scopedKeeper.ClaimCapability(cap1) - keeper.scopedKeeper.ClaimCapability(cap2) - keeper.scopedKeeper.ClaimCapability(cap3) - } - - // ... more initialization logic -} -``` - ### Custom Packets Modules connected by a channel must agree on what application data they are sending over the @@ -245,15 +206,12 @@ DecodePacketData(encoded []byte) (CustomPacketData) { Then a module must encode its packet data before sending it through IBC. ```go -// retrieve the dynamic capability for this channel -channelCap := scopedKeeper.GetCapability(ctx, channelCapName) // Sending custom application packet data data := EncodePacketData(customPacketData) packet.Data = data // Send packet to IBC, authenticating with channelCap sequence, err := IBCChannelKeeper.SendPacket( ctx, - channelCap, sourcePort, sourceChannel, timeoutHeight, @@ -298,14 +256,11 @@ module must trigger execution on the port-bound module through the use of callba packet a module simply needs to call `SendPacket` on the `IBCChannelKeeper`. ```go -// retrieve the dynamic capability for this channel -channelCap := scopedKeeper.GetCapability(ctx, channelCapName) // Sending custom application packet data data := EncodePacketData(customPacketData) // Send packet to IBC, authenticating with channelCap sequence, err := IBCChannelKeeper.SendPacket( ctx, - channelCap, sourcePort, sourceChannel, timeoutHeight, @@ -314,11 +269,6 @@ sequence, err := IBCChannelKeeper.SendPacket( ) ``` -:::warning -In order to prevent modules from sending packets on channels they do not own, IBC expects -modules to pass in the correct channel capability for the packet's source channel. -::: - ##### Receiving Packets To handle receiving packets, the module must implement the `OnRecvPacket` callback. This gets diff --git a/docs/docs/01-ibc/03-apps/02-ibcmodule.md b/docs/docs/01-ibc/03-apps/02-ibcmodule.md index 0f1b4d1ae21..4d8a6019bbd 100644 --- a/docs/docs/01-ibc/03-apps/02-ibcmodule.md +++ b/docs/docs/01-ibc/03-apps/02-ibcmodule.md @@ -45,7 +45,7 @@ var ( ## Channel handshake callbacks -This section will describe the callbacks that are called during channel handshake execution. Among other things, it will claim channel capabilities passed on from core IBC. For a refresher on capabilities, check [the Overview section](../01-overview.md#capabilities). +This section will describe the callbacks that are called during channel handshake execution. Here are the channel handshake callbacks that modules are expected to implement: @@ -58,7 +58,6 @@ func (im IBCModule) OnChanOpenInit(ctx sdk.Context, connectionHops []string, portID string, channelID string, - channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, version string, ) (string, error) { @@ -72,10 +71,6 @@ func (im IBCModule) OnChanOpenInit(ctx sdk.Context, return "", err } - // OpenInit must claim the channelCapability that IBC passes into the callback - if err := im.keeper.ClaimCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)); err != nil { - return "", err - } return version, nil } @@ -87,7 +82,6 @@ func (im IBCModule) OnChanOpenTry( connectionHops []string, portID, channelID string, - channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, counterpartyVersion string, ) (string, error) { @@ -98,11 +92,6 @@ func (im IBCModule) OnChanOpenTry( return "", err } - // OpenTry must claim the channelCapability that IBC passes into the callback - if err := im.keeper.scopedKeeper.ClaimCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)); err != nil { - return err - } - // Construct application version // IBC applications must return the appropriate application version // This can be a simple string or it can be a complex version constructed @@ -239,14 +228,11 @@ module must trigger execution on the port-bound module through the use of callba > Note that some of the code below is *pseudo code*, indicating what actions need to happen but leaving it up to the developer to implement a custom implementation. E.g. the `EncodePacketData(customPacketData)` function. ```go -// retrieve the dynamic capability for this channel -channelCap := scopedKeeper.GetCapability(ctx, channelCapName) // Sending custom application packet data data := EncodePacketData(customPacketData) // Send packet to IBC, authenticating with channelCap sequence, err := IBCChannelKeeper.SendPacket( ctx, - channelCap, sourcePort, sourceChannel, timeoutHeight, @@ -255,11 +241,6 @@ sequence, err := IBCChannelKeeper.SendPacket( ) ``` -:::warning -In order to prevent modules from sending packets on channels they do not own, IBC expects -modules to pass in the correct channel capability for the packet's source channel. -::: - ### Receiving packets To handle receiving packets, the module must implement the `OnRecvPacket` callback. This gets diff --git a/docs/docs/01-ibc/03-apps/04-keeper.md b/docs/docs/01-ibc/03-apps/04-keeper.md index 8e0040e09fc..a1bb8fe838d 100644 --- a/docs/docs/01-ibc/03-apps/04-keeper.md +++ b/docs/docs/01-ibc/03-apps/04-keeper.md @@ -32,7 +32,6 @@ type Keeper struct { channelKeeper types.ChannelKeeper portKeeper types.PortKeeper - scopedKeeper capabilitykeeper.ScopedKeeper // ... additional according to custom logic } @@ -56,19 +55,6 @@ func NewKeeper( } } -// hasCapability checks if the IBC app module owns the port capability for the desired port -func (k Keeper) hasCapability(ctx sdk.Context, portID string) bool { - _, ok := k.scopedKeeper.GetCapability(ctx, host.PortPath(portID)) - return ok -} - -// BindPort defines a wrapper function for the port Keeper's function in -// order to expose it to module's InitGenesis function -func (k Keeper) BindPort(ctx sdk.Context, portID string) error { - cap := k.portKeeper.BindPort(ctx, portID) - return k.ClaimCapability(ctx, cap, host.PortPath(portID)) -} - // GetPort returns the portID for the IBC app module. Used in ExportGenesis func (k Keeper) GetPort(ctx sdk.Context) string { store := ctx.KVStore(k.storeKey) @@ -81,16 +67,5 @@ func (k Keeper) SetPort(ctx sdk.Context, portID string) { store.Set(types.PortKey, []byte(portID)) } -// AuthenticateCapability wraps the scopedKeeper's AuthenticateCapability function -func (k Keeper) AuthenticateCapability(ctx sdk.Context, cap *capabilitytypes.Capability, name string) bool { - return k.scopedKeeper.AuthenticateCapability(ctx, cap, name) -} - -// ClaimCapability allows the IBC app module to claim a capability that core IBC -// passes to it -func (k Keeper) ClaimCapability(ctx sdk.Context, cap *capabilitytypes.Capability, name string) error { - return k.scopedKeeper.ClaimCapability(ctx, cap, name) -} - // ... additional according to custom logic ``` diff --git a/docs/docs/01-ibc/03-apps/05-packets_acks.md b/docs/docs/01-ibc/03-apps/05-packets_acks.md index 66a1710ecbc..18d34cdeaad 100644 --- a/docs/docs/01-ibc/03-apps/05-packets_acks.md +++ b/docs/docs/01-ibc/03-apps/05-packets_acks.md @@ -52,14 +52,11 @@ DecodePacketData(encoded []byte) (CustomPacketData) { Then a module must encode its packet data before sending it through IBC. ```go -// retrieve the dynamic capability for this channel -channelCap := scopedKeeper.GetCapability(ctx, channelCapName) // Sending custom application packet data data := EncodePacketData(customPacketData) // Send packet to IBC, authenticating with channelCap sequence, err := IBCChannelKeeper.SendPacket( ctx, - channelCap, sourcePort, sourceChannel, timeoutHeight, diff --git a/docs/docs/01-ibc/04-middleware/02-develop.md b/docs/docs/01-ibc/04-middleware/02-develop.md index 9ae53985af7..2f5742ede31 100644 --- a/docs/docs/01-ibc/04-middleware/02-develop.md +++ b/docs/docs/01-ibc/04-middleware/02-develop.md @@ -53,7 +53,7 @@ The middleware must have access to the underlying application, and be called bef > Middleware **may** choose not to call the underlying application's callback at all. Though these should generally be limited to error cases. -The `IBCModule` interface consists of the channel handshake callbacks and packet callbacks. Most of the custom logic will be performed in the packet callbacks, in the case of the channel handshake callbacks, introducing the middleware requires consideration to the version negotiation and passing of capabilities. +The `IBCModule` interface consists of the channel handshake callbacks and packet callbacks. Most of the custom logic will be performed in the packet callbacks, in the case of the channel handshake callbacks, introducing the middleware requires consideration to the version negotiation. ### Channel handshake callbacks @@ -85,7 +85,6 @@ func (im IBCMiddleware) OnChanOpenInit( connectionHops []string, portID string, channelID string, - channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, version string, ) (string, error) { @@ -104,7 +103,6 @@ func (im IBCMiddleware) OnChanOpenInit( connectionHops, portID, channelID, - channelCap, counterparty, version, ) @@ -129,7 +127,6 @@ func (im IBCMiddleware) OnChanOpenInit( connectionHops, portID, channelID, - channelCap, counterparty, metadata.AppVersion, // note we only pass app version here ) @@ -154,7 +151,6 @@ func (im IBCMiddleware) OnChanOpenTry( connectionHops []string, portID, channelID string, - channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, counterpartyVersion string, ) (string, error) { @@ -169,7 +165,6 @@ func (im IBCMiddleware) OnChanOpenTry( connectionHops, portID, channelID, - channelCap, counterparty, counterpartyVersion, ) @@ -185,7 +180,6 @@ func (im IBCMiddleware) OnChanOpenTry( connectionHops, portID, channelID, - channelCap, counterparty, cpMetadata.AppVersion, // note we only pass counterparty app version here ) @@ -281,12 +275,6 @@ func OnChanCloseConfirm( See [here](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/apps/29-fee/ibc_middleware.go#L191-L213) an example implementation of this callback for the ICS-29 Fee Middleware module. -#### Capabilities - -The middleware should simply pass the capability in the callback arguments along to the underlying application so that it may be claimed by the base application. The base application will then pass the capability up the stack in order to authenticate an outgoing packet/acknowledgement, which you can check in the [`ICS4Wrapper` section](#ics-04-wrappers). - -In the case where the middleware wishes to send a packet or acknowledgment without the involvement of the underlying application, it should be given access to the same `scopedKeeper` as the base application so that it can retrieve the capabilities by itself. - ### Packet callbacks The packet callbacks just like the handshake callbacks wrap the application's packet callbacks. The packet callbacks are where the middleware performs most of its custom logic. The middleware may read the packet flow data and perform some additional packet handling, or it may modify the incoming data before it reaches the underlying application. This enables a wide degree of usecases, as a simple base application like token-transfer can be transformed for a variety of usecases by combining it with custom middleware. @@ -375,7 +363,6 @@ For stateless middleware, the `ics4Wrapper` can be passed on directly without ha type ICS4Wrapper interface { SendPacket( ctx sdk.Context, - chanCap *capabilitytypes.Capability, sourcePort string, sourceChannel string, timeoutHeight clienttypes.Height, @@ -385,7 +372,6 @@ type ICS4Wrapper interface { WriteAcknowledgement( ctx sdk.Context, - chanCap *capabilitytypes.Capability, packet exported.PacketI, ack exported.Acknowledgement, ) error @@ -407,7 +393,6 @@ Check out the references provided for an actual implementation to clarify, where ```go func SendPacket( ctx sdk.Context, - chanCap *capabilitytypes.Capability, sourcePort string, sourceChannel string, timeoutHeight clienttypes.Height, @@ -419,7 +404,6 @@ func SendPacket( return ics4Wrapper.SendPacket( ctx, - chanCap, sourcePort, sourceChannel, timeoutHeight, @@ -437,7 +421,6 @@ See [here](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/apps/29-fee/keep // only called for async acks func WriteAcknowledgement( ctx sdk.Context, - chanCap *capabilitytypes.Capability, packet exported.PacketI, ack exported.Acknowledgement, ) error { diff --git a/docs/docs/01-ibc/12-capability-module.md b/docs/docs/01-ibc/12-capability-module.md deleted file mode 100644 index 05db8a887eb..00000000000 --- a/docs/docs/01-ibc/12-capability-module.md +++ /dev/null @@ -1,139 +0,0 @@ ---- -title: Capability Module -sidebar_label: Capability Module -sidebar_position: 12 -slug: /ibc/capability-module ---- - -# Capability Module - -## Overview - -`modules/capability` is an implementation of a Cosmos SDK module, per [ADR 003](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-003-dynamic-capability-store.md), that allows for provisioning, tracking, and authenticating multi-owner capabilities at runtime. - -The keeper maintains two states: persistent and ephemeral in-memory. The persistent -store maintains a globally unique auto-incrementing index and a mapping from -capability index to a set of capability owners that are defined as a module and -capability name tuple. The in-memory ephemeral state keeps track of the actual -capabilities, represented as addresses in local memory, with both forward and reverse indexes. -The forward index maps module name and capability tuples to the capability name. The -reverse index maps between the module and capability name and the capability itself. - -The keeper allows the creation of "scoped" sub-keepers which are tied to a particular -module by name. Scoped keepers must be created at application initialization and -passed to modules, which can then use them to claim capabilities they receive and -retrieve capabilities which they own by name, in addition to creating new capabilities -& authenticating capabilities passed by other modules. A scoped keeper cannot escape its scope, -so a module cannot interfere with or inspect capabilities owned by other modules. - -The keeper provides no other core functionality that can be found in other modules -like queriers, REST and CLI handlers, and genesis state. - -## Initialization - -During application initialization, the keeper must be instantiated with a persistent -store key and an in-memory store key. - -```go -type App struct { - // ... - - capabilityKeeper *capability.Keeper -} - -func NewApp(...) *App { - // ... - - app.capabilityKeeper = capabilitykeeper.NewKeeper(codec, persistentStoreKey, memStoreKey) -} -``` - -After the keeper is created, it can be used to create scoped sub-keepers which -are passed to other modules that can create, authenticate, and claim capabilities. -After all the necessary scoped keepers are created and the state is loaded, the -main capability keeper must be sealed to prevent further scoped keepers from -being created. - -```go -func NewApp(...) *App { - // ... - - // Creating a scoped keeper - scopedIBCKeeper := app.CapabilityKeeper.ScopeToModule(ibchost.ModuleName) - - // Seal the capability keeper to prevent any further modules from creating scoped - // sub-keepers. - app.capabilityKeeper.Seal() - - return app -} -``` - -## Contents - -- [`modules/capability`](#capability-module) - - [Overview](#overview) - - [Initialization](#initialization) - - [Contents](#contents) - - [Concepts](#concepts) - - [Capabilities](#capabilities) - - [Stores](#stores) - - [State](#state) - - [Persisted KV store](#persisted-kv-store) - - [In-memory KV store](#in-memory-kv-store) - -## Concepts - -### Capabilities - -Capabilities are multi-owner. A scoped keeper can create a capability via `NewCapability` -which creates a new unique, unforgeable object-capability reference. The newly -created capability is automatically persisted; the calling module need not call -`ClaimCapability`. Calling `NewCapability` will create the capability with the -calling module and name as a tuple to be treated the capabilities first owner. - -Capabilities can be claimed by other modules which add them as owners. `ClaimCapability` -allows a module to claim a capability key which it has received from another -module so that future `GetCapability` calls will succeed. `ClaimCapability` MUST -be called if a module which receives a capability wishes to access it by name in -the future. Again, capabilities are multi-owner, so if multiple modules have a -single Capability reference, they will all own it. If a module receives a capability -from another module but does not call `ClaimCapability`, it may use it in the executing -transaction but will not be able to access it afterwards. - -`AuthenticateCapability` can be called by any module to check that a capability -does in fact correspond to a particular name (the name can be un-trusted user input) -with which the calling module previously associated it. - -`GetCapability` allows a module to fetch a capability which it has previously -claimed by name. The module is not allowed to retrieve capabilities which it does -not own. - -### Stores - -- MemStore -- KeyStore - -## State - -### Persisted KV store - -1. Global unique capability index -2. Capability owners - -Indexes: - -- Unique index: `[]byte("index") -> []byte(currentGlobalIndex)` -- Capability Index: `[]byte("capability_index") | []byte(index) -> ProtocolBuffer(CapabilityOwners)` - -### In-memory KV store - -1. Initialized flag -2. Mapping between the module and capability tuple and the capability name -3. Mapping between the module and capability name and its index - -Indexes: - -- Initialized flag: `[]byte("mem_initialized")` -- RevCapabilityKey: `[]byte(moduleName + "/rev/" + capabilityName) -> []byte(index)` -- FwdCapabilityKey: `[]byte(moduleName + "/fwd/" + capabilityPointerAddress) -> []byte(capabilityName)` diff --git a/docs/docs/02-apps/01-transfer/01-overview.md b/docs/docs/02-apps/01-transfer/01-overview.md index 31433d34f0f..d61ac19dbfb 100644 --- a/docs/docs/02-apps/01-transfer/01-overview.md +++ b/docs/docs/02-apps/01-transfer/01-overview.md @@ -138,7 +138,7 @@ a multi-denom collections of tokens is also allowed (i.e. forwarding of tokens o ### Unwind tokens Taking again as an example the topology from the previous section, we assume that native tokens on chain `A` -have been transfered to chain `C`. The IBC vouchers on chain `C` have the denomination trace +have been transferred to chain `C`. The IBC vouchers on chain `C` have the denomination trace `transfer/channelCtoB/transfer/channelBtoA`, and with forwarding it is possible to submit a transfer message on chain `C` and automatically unwind the vouchers through chain `B` to chain `A`, so that the tokens recovered on the origin chain regain their native denomination. In order to execute automatic unwinding, the transfer diff --git a/docs/docs/02-apps/01-transfer/09-client.md b/docs/docs/02-apps/01-transfer/09-client.md index 2a5940f4631..3ba88e6dfc1 100644 --- a/docs/docs/02-apps/01-transfer/09-client.md +++ b/docs/docs/02-apps/01-transfer/09-client.md @@ -42,7 +42,7 @@ The additional flags that can be used with the command are: - `--packet-timeout-height` to specify the timeout block height in the format `{revision}-{height}`. The default value is `0-0`, which effectively disables the timeout. Timeout height can only be absolute, therefore this option must be used in combination with `--absolute-timeouts` set to true. - `--packet-timeout-timestamp` to specify the timeout timestamp in nanoseconds. The timeout can be either relative (fromthe current UTC time) or absolute. The default value is 10 minutes (and thus relative). The timeout is disabled when set to 0. -- `--absolute-timeouts` to interpret the timeout timestamp as an aboslute value (when set to true). The default value is false (and thus the timeout timeout is considered relative to current UTC time). +- `--absolute-timeouts` to interpret the timeout timestamp as an absolute value (when set to true). The default value is false (and thus the timeout timeout is considered relative to current UTC time). - `--memo` to specify the memo string to be sent along with the transfer packet. If forwarding is used, then the memo string will be carried through the intermediary chains to the final destination. - `--forwarding` to specify forwarding information in the form of a comma separated list of source port ID/channel ID pairs at each intermediary chain (e.g. `transfer/channel-0,transfer/channel-1`). - `--unwind` to specify if the tokens must be automatically unwound to there origin chain. This option can be used in combination with `--forwarding` to forward the tokens to the final destination after unwinding. When this flag is true, the tokens specified in the `coins` option must all have the same denomination trace path (i.e. all tokens must be IBC vouchers sharing exactly the same set of destination port/channel IDs in their denomination trace path). Arguments `[src-port]` and `[src-channel]` must not be passed if the `--unwind` flag is specified. diff --git a/docs/docs/02-apps/01-transfer/10-ICS20-v1/09-client.md b/docs/docs/02-apps/01-transfer/10-ICS20-v1/09-client.md index d55b8531271..20d8c2f10a0 100644 --- a/docs/docs/02-apps/01-transfer/10-ICS20-v1/09-client.md +++ b/docs/docs/02-apps/01-transfer/10-ICS20-v1/09-client.md @@ -45,7 +45,7 @@ The additional flags that can be used with the command are: - `--packet-timeout-height` to specify the timeout block height in the format `{revision}-{height}`. The default value is `0-0`, which effectively disables the timeout. Timeout height can only be absolute, therefore this option must be used in combination with `--absolute-timeouts` set to true. - `--packet-timeout-timestamp` to specify the timeout timestamp in nanoseconds. The timeout can be either relative (fromthe current UTC time) or absolute. The default value is 10 minutes (and thus relative). The timeout is disabled when set to 0. -- `--absolute-timeouts` to interpret the timeout timestamp as an aboslute value (when set to true). The default value is false (and thus the timeout timeout is considered relative to current UTC time). +- `--absolute-timeouts` to interpret the timeout timestamp as an absolute value (when set to true). The default value is false (and thus the timeout timeout is considered relative to current UTC time). - `--memo` to specify the memo string to be sent along with the transfer packet. If forwarding is used, then the memo string will be carried through the intermediary chains to the final destination. #### `total-escrow` diff --git a/docs/docs/02-apps/02-interchain-accounts/04-integration.md b/docs/docs/02-apps/02-interchain-accounts/04-integration.md index 3c5cb2e62aa..14117661086 100644 --- a/docs/docs/02-apps/02-interchain-accounts/04-integration.md +++ b/docs/docs/02-apps/02-interchain-accounts/04-integration.md @@ -71,26 +71,20 @@ keys := sdk.NewKVStoreKeys( ... -// Create the scoped keepers for each submodule keeper and authentication keeper -scopedICAControllerKeeper := app.CapabilityKeeper.ScopeToModule(icacontrollertypes.SubModuleName) -scopedICAHostKeeper := app.CapabilityKeeper.ScopeToModule(icahosttypes.SubModuleName) -scopedICAAuthKeeper := app.CapabilityKeeper.ScopeToModule(icaauthtypes.ModuleName) - -... // Create the Keeper for each submodule app.ICAControllerKeeper = icacontrollerkeeper.NewKeeper( appCodec, keys[icacontrollertypes.StoreKey], app.GetSubspace(icacontrollertypes.SubModuleName), app.IBCKeeper.ChannelKeeper, // may be replaced with middleware such as ics29 fee app.IBCKeeper.ChannelKeeper, app.IBCKeeper.PortKeeper, - scopedICAControllerKeeper, app.MsgServiceRouter(), + app.MsgServiceRouter(), authtypes.NewModuleAddress(govtypes.ModuleName).String(), ) app.ICAHostKeeper = icahostkeeper.NewKeeper( appCodec, keys[icahosttypes.StoreKey], app.GetSubspace(icahosttypes.SubModuleName), app.IBCKeeper.ChannelKeeper, // may be replaced with middleware such as ics29 fee app.IBCKeeper.ChannelKeeper, app.IBCKeeper.PortKeeper, app.AccountKeeper, - scopedICAHostKeeper, app.MsgServiceRouter(), app.GRPCQueryRouter(), + app.MsgServiceRouter(), app.GRPCQueryRouter(), authtypes.NewModuleAddress(govtypes.ModuleName).String(), ) diff --git a/docs/docs/02-apps/02-interchain-accounts/05-messages.md b/docs/docs/02-apps/02-interchain-accounts/05-messages.md index fa5833bd976..eb671ab5e5e 100644 --- a/docs/docs/02-apps/02-interchain-accounts/05-messages.md +++ b/docs/docs/02-apps/02-interchain-accounts/05-messages.md @@ -28,7 +28,7 @@ This message is expected to fail if: This message will construct a new `MsgChannelOpenInit` on chain and route it to the core IBC message server to initiate the opening step of the channel handshake. -The controller submodule will generate a new port identifier and claim the associated port capability. The caller is expected to provide an appropriate application version string. For example, this may be an ICS-27 JSON encoded [`Metadata`](https://github.com/cosmos/ibc-go/blob/v6.0.0/proto/ibc/applications/interchain_accounts/v1/metadata.proto#L11) type or an ICS-29 JSON encoded [`Metadata`](https://github.com/cosmos/ibc-go/blob/v6.0.0/proto/ibc/applications/fee/v1/metadata.proto#L11) type with a nested application version. +The controller submodule will generate a new port identifier. The caller is expected to provide an appropriate application version string. For example, this may be an ICS-27 JSON encoded [`Metadata`](https://github.com/cosmos/ibc-go/blob/v6.0.0/proto/ibc/applications/interchain_accounts/v1/metadata.proto#L11) type or an ICS-29 JSON encoded [`Metadata`](https://github.com/cosmos/ibc-go/blob/v6.0.0/proto/ibc/applications/fee/v1/metadata.proto#L11) type with a nested application version. If the `Version` string is omitted, the controller submodule will construct a default version string in the `OnChanOpenInit` handshake callback. ```go diff --git a/docs/docs/02-apps/02-interchain-accounts/10-legacy/01-auth-modules.md b/docs/docs/02-apps/02-interchain-accounts/10-legacy/01-auth-modules.md index e9bf7038647..38b0b753c10 100644 --- a/docs/docs/02-apps/02-interchain-accounts/10-legacy/01-auth-modules.md +++ b/docs/docs/02-apps/02-interchain-accounts/10-legacy/01-auth-modules.md @@ -26,8 +26,6 @@ The authentication module must: - Track the associated interchain account address for an owner. - Send packets on behalf of an owner (after authentication). -> Please note that since ibc-go v6 the channel capability is claimed by the controller submodule and therefore it is not required for authentication modules to claim the capability in the `OnChanOpenInit` callback. When the authentication module sends packets on the channel created for the associated interchain account it can pass a `nil` capability to the legacy function `SendTx` of the controller keeper (see section [`SendTx`](03-keeper-api.md#sendtx) for more information). - ## `IBCModule` implementation The following `IBCModule` callbacks must be implemented with appropriate custom logic: @@ -40,12 +38,9 @@ func (im IBCModule) OnChanOpenInit( connectionHops []string, portID string, channelID string, - chanCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, version string, ) (string, error) { - // since ibc-go v6 the authentication module *must not* claim the channel capability on OnChanOpenInit - // perform custom logic return version, nil @@ -108,7 +103,6 @@ func (im IBCModule) OnChanOpenTry( connectionHops []string, portID, channelID string, - chanCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, counterpartyVersion string, ) (string, error) { diff --git a/docs/docs/02-apps/02-interchain-accounts/10-legacy/02-integration.md b/docs/docs/02-apps/02-interchain-accounts/10-legacy/02-integration.md index 1999223c02f..ae15c0ae197 100644 --- a/docs/docs/02-apps/02-interchain-accounts/10-legacy/02-integration.md +++ b/docs/docs/02-apps/02-interchain-accounts/10-legacy/02-integration.md @@ -24,8 +24,6 @@ Interchain Account authentication modules are the base application of a middlewa ![ica-pre-v6.png](./images/ica-pre-v6.png) -> Please note that since ibc-go v6 the channel capability is claimed by the controller submodule and therefore it is not required for authentication modules to claim the capability in the `OnChanOpenInit` callback. Therefore the custom authentication module does not need a scoped keeper anymore. - ## Example integration ```go @@ -77,9 +75,6 @@ keys := sdk.NewKVStoreKeys( ... -// Create the scoped keepers for each submodule keeper and authentication keeper -scopedICAControllerKeeper := app.CapabilityKeeper.ScopeToModule(icacontrollertypes.SubModuleName) -scopedICAHostKeeper := app.CapabilityKeeper.ScopeToModule(icahosttypes.SubModuleName) ... @@ -88,13 +83,13 @@ app.ICAControllerKeeper = icacontrollerkeeper.NewKeeper( appCodec, keys[icacontrollertypes.StoreKey], app.GetSubspace(icacontrollertypes.SubModuleName), app.IBCKeeper.ChannelKeeper, // may be replaced with middleware such as ics29 fee app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, - scopedICAControllerKeeper, app.MsgServiceRouter(), + app.MsgServiceRouter(), ) app.ICAHostKeeper = icahostkeeper.NewKeeper( appCodec, keys[icahosttypes.StoreKey], app.GetSubspace(icahosttypes.SubModuleName), app.IBCKeeper.ChannelKeeper, // may be replaced with middleware such as ics29 fee app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, - app.AccountKeeper, scopedICAHostKeeper, app.MsgServiceRouter(), + app.AccountKeeper, app.MsgServiceRouter(), ) // Create Interchain Accounts AppModule diff --git a/docs/docs/02-apps/02-interchain-accounts/10-legacy/03-keeper-api.md b/docs/docs/02-apps/02-interchain-accounts/10-legacy/03-keeper-api.md index 120bdcd6365..337ad1f71df 100644 --- a/docs/docs/02-apps/02-interchain-accounts/10-legacy/03-keeper-api.md +++ b/docs/docs/02-apps/02-interchain-accounts/10-legacy/03-keeper-api.md @@ -116,9 +116,7 @@ packetData := icatypes.InterchainAccountPacketData{ timeoutTimestamp := obtainTimeoutTimestamp() // Send the interchain accounts packet, returning the packet sequence -// A nil channel capability can be passed, since the controller submodule (and not the authentication module) -// claims the channel capability since ibc-go v6. -seq, err = keeper.icaControllerKeeper.SendTx(ctx, nil, portID, packetData, timeoutTimestamp) +seq, err = keeper.icaControllerKeeper.SendTx(ctx, portID, packetData, timeoutTimestamp) ``` The data within an `InterchainAccountPacketData` must be serialized using a format supported by the host chain. diff --git a/docs/docs/03-light-clients/05-tendermint/01-overview.md b/docs/docs/03-light-clients/05-tendermint/01-overview.md index 9f94d77980a..1a09c64e79f 100644 --- a/docs/docs/03-light-clients/05-tendermint/01-overview.md +++ b/docs/docs/03-light-clients/05-tendermint/01-overview.md @@ -23,7 +23,7 @@ The Tendermint client consists of two important structs that keep track of the s Each Tendermint Client is composed of a single `ClientState` keyed on the client ID, and multiple consensus states which are keyed on both the clientID and header height. Relayers can use the consensus states to verify merkle proofs of packet commitments, acknowledgements, and receipts against the `AppHash` of the counterparty chain in order to enable verified packet flow. -If a counterparty chain violates the CometBFT protocol in a way that is detectable to off-chain light clients, this misbehaviour can also be submitted to an IBC client by any off-chain actor. Upon verification of this misbehaviour, the Tendermint IBC Client will freeze, preventing any further packet flow from this malicious chain from occuring. Governance or some other out-of-band protocol may then be used to unwind any damage that has already occurred. +If a counterparty chain violates the CometBFT protocol in a way that is detectable to off-chain light clients, this misbehaviour can also be submitted to an IBC client by any off-chain actor. Upon verification of this misbehaviour, the Tendermint IBC Client will freeze, preventing any further packet flow from this malicious chain from occurring. Governance or some other out-of-band protocol may then be used to unwind any damage that has already occurred. ## Initialization diff --git a/docs/requirements/path-unwinding-forwarding-requirements.md b/docs/requirements/path-unwinding-forwarding-requirements.md index 1c0c7a447a7..973cd4f25f9 100644 --- a/docs/requirements/path-unwinding-forwarding-requirements.md +++ b/docs/requirements/path-unwinding-forwarding-requirements.md @@ -6,7 +6,7 @@ The implementation of fungible token path unwinding vastly simplifies token tran Path unwinding reduces the complexity of token transfer for the end user; a user simply needs to choose the final destination for their tokens and the complexity of determining the optimal route is abstracted away. This is a huge user experience improvement. -In addition to unwinding, when a user recieves their token on a destination chain, they then want to use the token in some way. By enabling token forwarding, a user can recieve a token, perform some action with that token, for example a swap, and then send the token onto another chain. We observe that the complexity of IBC is increasingly being abstracted away from end users and automating workflows such as transfer, swap and forward with a single signed transaction significantly enhances usability. +In addition to unwinding, when a user receives their token on a destination chain, they then want to use the token in some way. By enabling token forwarding, a user can receive a token, perform some action with that token, for example a swap, and then send the token onto another chain. We observe that the complexity of IBC is increasingly being abstracted away from end users and automating workflows such as transfer, swap and forward with a single signed transaction significantly enhances usability. ## Problem diff --git a/docs/tutorials/02-channel-upgrades/05-upgrade-channel.md b/docs/tutorials/02-channel-upgrades/05-upgrade-channel.md index 421c9fafb6e..d9addbacc10 100644 --- a/docs/tutorials/02-channel-upgrades/05-upgrade-channel.md +++ b/docs/tutorials/02-channel-upgrades/05-upgrade-channel.md @@ -122,7 +122,7 @@ proposals: Now we wait for the relayer to complete the upgrade handshake. -## Check ugprade completed +## Check upgrade completed Once the handshake has completed we verify that the channel has successfully upgraded: diff --git a/docs/tutorials/02-channel-upgrades/06-incentivize-packet.md b/docs/tutorials/02-channel-upgrades/06-incentivize-packet.md index f6b14a5b87b..49139fde97f 100644 --- a/docs/tutorials/02-channel-upgrades/06-incentivize-packet.md +++ b/docs/tutorials/02-channel-upgrades/06-incentivize-packet.md @@ -102,4 +102,4 @@ pagination: total: "2" ``` -An amount of `1075samoleans` has been deducted, which is what we expected: `1000samoleans` have been transfered to `VALIDATOR_CHAIN2` and `75stake` have been paid for the receive and acknowledgment fees. The timeout fee has been refunded to `VALIDATOR_CHAIN1` and the relayer address `RLY_CHAIN1` should have gained `75samoleans` for submitting the `MsgRecvPacket` and the `MsgAcknowledgement` messages. +An amount of `1075samoleans` has been deducted, which is what we expected: `1000samoleans` have been transferred to `VALIDATOR_CHAIN2` and `75stake` have been paid for the receive and acknowledgment fees. The timeout fee has been refunded to `VALIDATOR_CHAIN1` and the relayer address `RLY_CHAIN1` should have gained `75samoleans` for submitting the `MsgRecvPacket` and the `MsgAcknowledgement` messages. diff --git a/docs/versioned_docs/version-v9.0.x/00-intro.md b/docs/versioned_docs/version-v9.0.x/00-intro.md new file mode 100644 index 00000000000..a21bdf40058 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/00-intro.md @@ -0,0 +1,36 @@ +--- +slug: / +sidebar_position: 0 +--- + +# IBC-Go Documentation + +Welcome to the documentation for IBC-Go, the Golang implementation of the Inter-Blockchain Communication Protocol! Looking for information on ibc-rs? [Click here to go to the ibc-rs github repo](https://github.com/cosmos/ibc-rs). + +The Inter-Blockchain Communication Protocol (IBC) is an end-to-end, connection-oriented, stateful protocol for reliable, ordered, and authenticated communication between heterogeneous blockchains arranged in an unknown and dynamic topology. + +IBC is a protocol that allows blockchains to talk to each other. Chains that speak IBC can share any type of data as long as it's encoded in bytes, enabling the industry’s most feature-rich cross-chain interactions. IBC is secure and permissionless. + +The protocol realizes this interoperability by specifying a set of data structures, abstractions, and semantics that can be implemented by any distributed ledger that satisfies a small set of requirements. + +IBC can be used to build a wide range of cross-chain applications that include token transfers, atomic swaps, multi-chain smart contracts (with or without mutually comprehensible VMs), cross-chain account control, and data and code sharding of various kinds. + +## High-level overview of IBC + +The following diagram shows how IBC works at a high level: + +![Light Mode IBC Overview](./images/ibcoverview-light.svg#gh-light-mode-only)![Dark Mode IBC Overview](./images/ibcoverview-dark.svg#gh-dark-mode-only) + +The transport layer (TAO) provides the necessary infrastructure to establish secure connections and authenticate data packets between chains. The application layer builds on top of the transport layer and defines exactly how data packets should be packaged and interpreted by the sending and receiving chains. + +IBC provides a reliable, permissionless, and generic base layer (allowing for the secure relaying of data packets), while allowing for composability and modularity with separation of concerns by moving application designs (interpreting and acting upon the packet data) to a higher-level layer. This separation is reflected in the categories: + +- **IBC/TAO** comprises the Transport, Authentication, and Ordering of packets, i.e. the infrastructure layer. +- **IBC/APP** consists of the application handlers for the data packets being passed over the transport layer. These include but are not limited to fungible token transfers (ICS-20), NFT transfers (ICS-721), and interchain accounts (ICS-27). +- **Application module:** groups any application, middleware or smart contract that may wrap downstream application handlers to provide enhanced functionality. + +Note three crucial elements in the diagram: + +- The chains depend on relayers to communicate. [Relayers](https://github.com/cosmos/ibc/blob/main/spec/relayer/ics-018-relayer-algorithms/README.md) are the "physical" connection layer of IBC: off-chain processes responsible for relaying data between two chains running the IBC protocol by scanning the state of each chain, constructing appropriate datagrams, and executing them on the opposite chain as is allowed by the protocol. +- Many relayers can serve one or more channels to send messages between the chains. +- Each side of the connection uses the light client of the other chain to quickly verify incoming messages. diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/01-overview.md b/docs/versioned_docs/version-v9.0.x/01-ibc/01-overview.md new file mode 100644 index 00000000000..d2918a09519 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/01-overview.md @@ -0,0 +1,293 @@ +--- +title: Overview +sidebar_label: Overview +sidebar_position: 1 +slug: /ibc/overview +--- + +# Overview + +:::note Synopsis +Learn about IBC, its components, and its use cases. +::: + +## What is the Inter-Blockchain Communication Protocol (IBC)? + +This document serves as a guide for developers who want to write their own Inter-Blockchain +Communication Protocol (IBC) applications for custom use cases. + +> IBC applications must be written as self-contained modules. + +Due to the modular design of the IBC Protocol, IBC +application developers do not need to be concerned with the low-level details of clients, +connections, and proof verification. + +This brief explanation of the lower levels of the +stack gives application developers a broad understanding of the IBC +Protocol. Abstraction layer details for channels and ports are most relevant for application developers and describe how to define custom packets and `IBCModule` callbacks. + +The requirements to have your module interact over IBC are: + +- Bind to a port or ports. +- Define your packet data. +- Use the default acknowledgment struct provided by core IBC or optionally define a custom acknowledgment struct. +- Standardize an encoding of the packet data. +- Implement the `IBCModule` interface. +- Implement the `UpgradableModule` interface (optional). + +Read on for a detailed explanation of how to write a self-contained IBC application module. + +## Components overview + +### [Clients](https://github.com/cosmos/ibc-go/blob/main/modules/core/02-client) + +IBC clients are on-chain light clients. Each light client is identified by a unique client ID. +IBC clients track the consensus states of other blockchains, along with the proof spec necessary to +properly verify proofs against the client's consensus state. A client can be associated with any number +of connections to the counterparty chain. The client identifier is auto generated using the client type +and the global client counter appended in the format: `{client-type}-{N}`. + +A `ClientState` should contain chain specific and light client specific information necessary for verifying updates +and upgrades to the IBC client. The `ClientState` may contain information such as chain ID, latest height, proof specs, +unbonding periods or the status of the light client. The `ClientState` should not contain information that +is specific to a given block at a certain height, this is the function of the `ConsensusState`. Each `ConsensusState` +should be associated with a unique block and should be referenced using a height. IBC clients are given a +client identifier prefixed store to store their associated client state and consensus states along with +any metadata associated with the consensus states. Consensus states are stored using their associated height. + +The supported IBC clients are: + +- [Solo Machine light client](https://github.com/cosmos/ibc-go/blob/main/modules/light-clients/06-solomachine): Devices such as phones, browsers, or laptops. +- [Tendermint light client](https://github.com/cosmos/ibc-go/blob/main/modules/light-clients/07-tendermint): The default for Cosmos SDK-based chains. +- [Wasm client](https://github.com/cosmos/ibc-go/blob/main/modules/light-clients/08-wasm): Proxy client useful for running light clients written in a Wasm-compilable language. +- [Localhost (loopback) client](https://github.com/cosmos/ibc-go/blob/main/modules/light-clients/09-localhost): Useful for testing, simulation, and relaying packets to modules on the same application. + +### IBC client heights + +IBC Client Heights are represented by the struct: + +```go +type Height struct { + RevisionNumber uint64 + RevisionHeight uint64 +} +``` + +The `RevisionNumber` represents the revision of the chain that the height is representing. +A revision typically represents a continuous, monotonically increasing range of block-heights. +The `RevisionHeight` represents the height of the chain within the given revision. + +On any reset of the `RevisionHeight`—for example, when hard-forking a Tendermint chain, +the `RevisionNumber` will get incremented. This allows IBC clients to distinguish between a +block height `n` of a previous revision of the chain (at revision `p`) and block-height `n` of the current +revision of the chain (at revision `e`). + +`Height`s that share the same revision number can be compared by simply comparing their respective `RevisionHeight`s. +`Height`s that do not share the same revision number will only be compared using their respective `RevisionNumber`s. +Thus a height `h` with revision number `e+1` will always be greater than a height `g` with revision number `e`, +**REGARDLESS** of the difference in revision heights. + +For example: + +```go +Height{RevisionNumber: 3, RevisionHeight: 0} > Height{RevisionNumber: 2, RevisionHeight: 100000000000} +``` + +When a Tendermint chain is running a particular revision, relayers can simply submit headers and proofs with the revision number +given by the chain's `chainID`, and the revision height given by the Tendermint block height. When a chain updates using a hard-fork +and resets its block-height, it is responsible for updating its `chainID` to increment the revision number. +IBC Tendermint clients then verifies the revision number against their `chainID` and treat the `RevisionHeight` as the Tendermint block-height. + +Tendermint chains wishing to use revisions to maintain persistent IBC connections even across height-resetting upgrades must format their `chainID`s +in the following manner: `{chainID}-{revision_number}`. On any height-resetting upgrade, the `chainID` **MUST** be updated with a higher revision number +than the previous value. + +For example: + +- Before upgrade `chainID`: `gaiamainnet-3` +- After upgrade `chainID`: `gaiamainnet-4` + +Clients that do not require revisions, such as the `06-solomachine` client, can simply hardcode `0` into the revision number whenever they +need to return an IBC height when implementing IBC interfaces and use the `RevisionHeight` exclusively. + +Other client types can implement their own logic to verify the IBC heights that relayers provide in their `Update`, `Misbehavior`, and +`Verify` functions respectively. + +The IBC interfaces expect an `ibcexported.Height` interface, however all clients must use the concrete implementation provided in +`02-client/types` and reproduced above. + +### [Connections](https://github.com/cosmos/ibc-go/blob/main/modules/core/03-connection) + +Connections encapsulate two [`ConnectionEnd`](https://github.com/cosmos/ibc-go/blob/v8.0.0/proto/ibc/core/connection/v1/connection.proto#L17) +objects on two separate blockchains. Each `ConnectionEnd` is associated with a client of the +other blockchain (for example, the counterparty blockchain). The connection handshake is responsible +for verifying that the light clients on each chain are correct for their respective counterparties. +Connections, once established, are responsible for facilitating all cross-chain verifications of IBC state. +A connection can be associated with any number of channels. + +The connection handshake is a 4-step handshake. Briefly, if a given chain A wants to open a connection with +chain B using already established light clients on both chains: + +1. chain A sends a `ConnectionOpenInit` message to signal a connection initialization attempt with chain B. +2. chain B sends a `ConnectionOpenTry` message to try opening the connection on chain A. +3. chain A sends a `ConnectionOpenAck` message to mark its connection end state as open. +4. chain B sends a `ConnectionOpenConfirm` message to mark its connection end state as open. + +#### Time delayed connections + +Connections can be opened with a time delay by setting the `delay_period` field (in nanoseconds) in the [`MsgConnectionOpenInit`](https://github.com/cosmos/ibc-go/blob/v8.0.0/proto/ibc/core/connection/v1/tx.proto#L45). +The time delay is used to require that the underlying light clients have been updated to a certain height before commitment verification can be performed. + +`delayPeriod` is used in conjunction with the [`max_expected_time_per_block`](https://github.com/cosmos/ibc-go/blob/v8.0.0/proto/ibc/core/connection/v1/connection.proto#L113) parameter of the connection submodule to determine the `blockDelay`, which is number of blocks that the connection must be delayed by. + +When commitment verification is performed, the connection submodule will pass `delayPeriod` and `blockDelay` to the light client. It is up to the light client to determine whether the light client has been updated to the required height. Only the following light clients in `ibc-go` support time delayed connections: + +- `07-tendermint` +- `08-wasm` (passed to the contact) + +### [Proofs](https://github.com/cosmos/ibc-go/blob/main/modules/core/23-commitment) and [paths](https://github.com/cosmos/ibc-go/blob/main/modules/core/24-host) + +In IBC, blockchains do not directly pass messages to each other over the network. Instead, to +communicate, a blockchain commits some state to a specifically defined path that is reserved for a +specific message type and a specific counterparty. For example, for storing a specific connectionEnd as part +of a handshake or a packet intended to be relayed to a module on the counterparty chain. A relayer +process monitors for updates to these paths and relays messages by submitting the data stored +under the path and a proof to the counterparty chain. + +Proofs are passed from core IBC to light clients as bytes. It is up to light client implementations to interpret these bytes appropriately. + +- The paths that all IBC implementations must use for committing IBC messages is defined in +[ICS-24 Host State Machine Requirements](https://github.com/cosmos/ics/tree/master/spec/core/ics-024-host-requirements). +- The proof format that all implementations must be able to produce and verify is defined in [ICS-23 Proofs](https://github.com/cosmos/ics23) implementation. + +### [Ports](https://github.com/cosmos/ibc-go/blob/main/modules/core/05-port) + +An IBC module can bind to any number of ports. Each port must be identified by a unique `portID`. +Since IBC is designed to be secure with mutually distrusted modules operating on the same ledger, +binding a port returns a dynamic object capability. In order to take action on a particular port +(for example, an open channel with its port ID), a module must provide the dynamic object capability to the IBC +handler. This requirement prevents a malicious module from opening channels with ports it does not own. Thus, +IBC modules are responsible for claiming the capability that is returned on `BindPort`. + +### [Channels](https://github.com/cosmos/ibc-go/blob/main/modules/core/04-channel) + +An IBC channel can be established between two IBC ports. Currently, a port is exclusively owned by a +single module. IBC packets are sent over channels. Just as IP packets contain the destination IP +address and IP port, and the source IP address and source IP port, IBC packets contain +the destination port ID and channel ID, and the source port ID and channel ID. This packet structure enables IBC to +correctly route packets to the destination module while allowing modules receiving packets to +know the sender module. + +A channel can be `ORDERED`, where packets from a sending module must be processed by the +receiving module in the order they were sent. Or a channel can be `UNORDERED`, where packets +from a sending module are processed in the order they arrive (might be in a different order than they were sent). + +Modules can choose which channels they wish to communicate over with, thus IBC expects modules to +implement callbacks that are called during the channel handshake. These callbacks can do custom +channel initialization logic. If any callback returns an error, the channel handshake fails. Thus, by +returning errors on callbacks, modules can programmatically reject and accept channels. + +The channel handshake is a 4-step handshake. Briefly, if a given chain A wants to open a channel with +chain B using an already established connection: + +1. chain A sends a `ChanOpenInit` message to signal a channel initialization attempt with chain B. +2. chain B sends a `ChanOpenTry` message to try opening the channel on chain A. +3. chain A sends a `ChanOpenAck` message to mark its channel end status as open. +4. chain B sends a `ChanOpenConfirm` message to mark its channel end status as open. + +If all handshake steps are successful, the channel is opened on both sides. At each step in the handshake, the module +associated with the `ChannelEnd` executes its callback. So +on `ChanOpenInit`, the module on chain A executes its callback `OnChanOpenInit`. + +The channel identifier is auto derived in the format: `channel-{N}` where `N` is the next sequence to be used. + +#### Closing channels + +Closing a channel occurs in 2 handshake steps as defined in [ICS 04](https://github.com/cosmos/ibc/tree/master/spec/core/ics-004-channel-and-packet-semantics). +Once a channel is closed, it cannot be reopened. The channel handshake steps are: + +**`ChanCloseInit`** closes a channel on the executing chain if + +- the channel exists and it is not already closed, +- the connection it exists upon is `OPEN`, +- the [IBC module callback `OnChanCloseInit`](./03-apps/02-ibcmodule.md#channel-closing-callbacks) returns `nil`. + +`ChanCloseInit` can be initiated by any user by submitting a `MsgChannelCloseInit` transaction. +Note that channels are automatically closed when a packet times out on an `ORDERED` channel. +A timeout on an `ORDERED` channel skips the `ChanCloseInit` step and immediately closes the channel. + +**`ChanCloseConfirm`** is a response to a counterparty channel executing `ChanCloseInit`. The channel +on the executing chain closes if + +- the channel exists and is not already closed, +- the connection the channel exists upon is `OPEN`, +- the executing chain successfully verifies that the counterparty channel has been closed +- the [IBC module callback `OnChanCloseConfirm`](./03-apps/02-ibcmodule.md#channel-closing-callbacks) returns `nil`. + +Currently, none of the IBC applications provided in ibc-go support `ChanCloseInit`. + +### [Packets](https://github.com/cosmos/ibc-go/blob/main/modules/core/04-channel) + +Modules communicate with each other by sending packets over IBC channels. All +IBC packets contain the destination `portID` and `channelID` along with the source `portID` and +`channelID`. This packet structure allows modules to know the sender module of a given packet. IBC packets +contain a sequence to optionally enforce ordering. + +IBC packets also contain a `TimeoutHeight` and a `TimeoutTimestamp` that determine the deadline before the receiving module must process a packet. + +Modules send custom application data to each other inside the `Data` `[]byte` field of the IBC packet. +Thus, packet data is opaque to IBC handlers. It is incumbent on a sender module to encode +their application-specific packet information into the `Data` field of packets. The receiver +module must decode that `Data` back to the original application data. + +### [Receipts and timeouts](https://github.com/cosmos/ibc-go/blob/main/modules/core/04-channel) + +Since IBC works over a distributed network and relies on potentially faulty relayers to relay messages between ledgers, +IBC must handle the case where a packet does not get sent to its destination in a timely manner or at all. Packets must +specify a non-zero value for timeout height (`TimeoutHeight`) or timeout timestamp (`TimeoutTimestamp` ) after which a packet can no longer be successfully received on the destination chain. + +- The `timeoutHeight` indicates a consensus height on the destination chain after which the packet is no longer to be processed, and instead counts as having timed-out. +- The `timeoutTimestamp` indicates a timestamp on the destination chain after which the packet is no longer to be processed, and instead counts as having timed-out. + +If the timeout passes without the packet being successfully received, the packet can no longer be +received on the destination chain. The sending module can timeout the packet and take appropriate actions. + +If the timeout is reached, then a proof of packet timeout can be submitted to the original chain. The original chain can then perform +application-specific logic to timeout the packet, perhaps by rolling back the packet send changes (refunding senders any locked funds, etc). + +- In `ORDERED` channels, a timeout of a single packet in the channel causes the channel to close. + + - If packet sequence `n` times out, then a packet at sequence `k > n` cannot be received without violating the contract of `ORDERED` channels that packets are processed in the order that they are sent. + - Since `ORDERED` channels enforce this invariant, a proof that sequence `n` has not been received on the destination chain by the specified timeout of packet `n` is sufficient to timeout packet `n` and close the channel. + +- In `UNORDERED` channels, the application-specific timeout logic for that packet is applied and the channel is not closed. + + - Packets can be received in any order. + - IBC writes a packet receipt for each sequence received in the `UNORDERED` channel. This receipt does not contain information; it is simply a marker intended to signify that the `UNORDERED` channel has received a packet at the specified sequence. + - To timeout a packet on an `UNORDERED` channel, a proof is required that a packet receipt **does not exist** for the packet's sequence by the specified timeout. + +For this reason, most modules should use `UNORDERED` channels as they require fewer liveness guarantees to function effectively for users of that channel. + +### [Acknowledgments](https://github.com/cosmos/ibc-go/blob/main/modules/core/04-channel) + +Modules can also choose to write application-specific acknowledgments upon processing a packet. Acknowledgments can be done: + +- Synchronously on `OnRecvPacket` if the module processes packets as soon as they are received from IBC module. +- Asynchronously if module processes packets at some later point after receiving the packet. + +This acknowledgment data is opaque to IBC much like the packet `Data` and is treated by IBC as a simple byte string `[]byte`. Receiver modules must encode their acknowledgment so that the sender module can decode it correctly. The encoding must be negotiated between the two parties during version negotiation in the channel handshake. + +The acknowledgment can encode whether the packet processing succeeded or failed, along with additional information that allows the sender module to take appropriate action. + +After the acknowledgment has been written by the receiving chain, a relayer relays the acknowledgment back to the original sender module. + +The original sender module then executes application-specific acknowledgment logic using the contents of the acknowledgment. + +- After an acknowledgement fails, packet-send changes can be rolled back (for example, refunding senders in ICS 20). +- After an acknowledgment is received successfully on the original sender on the chain, the corresponding packet commitment is deleted since it is no longer needed. + +## Further readings and specs + +If you want to learn more about IBC, check the following specifications: + +- [IBC specification overview](https://github.com/cosmos/ibc/blob/master/README.md) diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/02-integration.md b/docs/versioned_docs/version-v9.0.x/01-ibc/02-integration.md new file mode 100644 index 00000000000..def03102de0 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/02-integration.md @@ -0,0 +1,305 @@ +--- +title: Integration +sidebar_label: Integration +sidebar_position: 2 +slug: /ibc/integration +--- + +# Integration + +:::note Synopsis +Learn how to integrate IBC to your application and send data packets to other chains. +::: + +This document outlines the required steps to integrate and configure the [IBC +module](https://github.com/cosmos/ibc-go/tree/main/modules/core) to your Cosmos SDK application and +send fungible token transfers to other chains. + +## Integrating the IBC module + +Integrating the IBC module to your SDK-based application is straightforward. The general changes can be summarized in the following steps: + +- [Define additional `Keeper` fields for the new modules on the `App` type](#add-application-fields-to-app). +- [Add the module's `StoreKey`s and initialize their `Keeper`s](#configure-the-keepers). +- [Set up IBC router and add route for the `transfer` module](#register-module-routes-in-the-ibc-router). +- [Grant permissions to `transfer`'s `ModuleAccount`](#module-account-permissions). +- [Add the modules to the module `Manager`](#module-manager-and-simulationmanager). +- [Update the module `SimulationManager` to enable simulations](#module-manager-and-simulationmanager). +- [Integrate light client modules (e.g. `07-tendermint`)](#integrating-light-clients). +- [Add modules to `Begin/EndBlockers` and `InitGenesis`](#application-abci-ordering). + +### Add application fields to `App` + +We need to register the core `ibc` and `transfer` `Keeper`s as follows: + +```go title="app.go" +import ( + // other imports + // ... + ibckeeper "github.com/cosmos/ibc-go/v9/modules/core/keeper" + ibctransferkeeper "github.com/cosmos/ibc-go/v9/modules/apps/transfer/keeper" +) + +type App struct { + // baseapp, keys and subspaces definitions + + // other keepers + // ... + IBCKeeper *ibckeeper.Keeper // IBC Keeper must be a pointer in the app, so we can SetRouter on it correctly + TransferKeeper ibctransferkeeper.Keeper // for cross-chain fungible token transfers + + // ... + // module and simulation manager definitions +} +``` + +### Configure the `Keeper`s + +During initialization, besides initializing the IBC `Keeper`s (for core `ibc` and `transfer` modules), we need to grant specific capabilities through the capability module `ScopedKeeper`s so that we can authenticate the object-capability permissions for each of the IBC channels. + +```go +import ( + // other imports + // ... + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + + capabilitykeeper "github.com/cosmos/ibc-go/modules/capability/keeper" + capabilitytypes "github.com/cosmos/ibc-go/modules/capability/types" + ibcexported "github.com/cosmos/ibc-go/v9/modules/core/exported" + ibckeeper "github.com/cosmos/ibc-go/v9/modules/core/keeper" + "github.com/cosmos/ibc-go/v9/modules/apps/transfer" + ibctransfertypes "github.com/cosmos/ibc-go/v9/modules/apps/transfer/types" + ibctm "github.com/cosmos/ibc-go/v9/modules/light-clients/07-tendermint" +) + +func NewApp(...args) *App { + // define codecs and baseapp + + // add capability keeper and ScopeToModule for ibc module + app.CapabilityKeeper = capabilitykeeper.NewKeeper( + appCodec, + keys[capabilitytypes.StoreKey], + memKeys[capabilitytypes.MemStoreKey], + ) + + // grant capabilities for the ibc and transfer modules + scopedIBCKeeper := app.CapabilityKeeper.ScopeToModule(ibcexported.ModuleName) + scopedTransferKeeper := app.CapabilityKeeper.ScopeToModule(ibctransfertypes.ModuleName) + + // ... other module keepers + + // Create IBC Keeper + app.IBCKeeper = ibckeeper.NewKeeper( + appCodec, + keys[ibcexported.StoreKey], + app.GetSubspace(ibcexported.ModuleName), + app.UpgradeKeeper, + scopedIBCKeeper, + authtypes.NewModuleAddress(govtypes.ModuleName).String(), + ) + + // Create Transfer Keeper + app.TransferKeeper = ibctransferkeeper.NewKeeper( + appCodec, + keys[ibctransfertypes.StoreKey], + app.GetSubspace(ibctransfertypes.ModuleName), + app.IBCKeeper.ChannelKeeper, + app.IBCKeeper.ChannelKeeper, + app.IBCKeeper.PortKeeper, + app.AccountKeeper, + app.BankKeeper, + scopedTransferKeeper, + authtypes.NewModuleAddress(govtypes.ModuleName).String(), + ) + transferModule := transfer.NewIBCModule(app.TransferKeeper) + + // ... continues +} +``` + +### Register module routes in the IBC `Router` + +IBC needs to know which module is bound to which port so that it can route packets to the +appropriate module and call the appropriate callbacks. The port to module name mapping is handled by +IBC's port `Keeper`. However, the mapping from module name to the relevant callbacks is accomplished +by the port +[`Router`](https://github.com/cosmos/ibc-go/blob/main/modules/core/05-port/types/router.go) on the +`ibc` module. + +Adding the module routes allows the IBC handler to call the appropriate callback when processing a +channel handshake or a packet. + +Currently, a `Router` is static so it must be initialized and set correctly on app initialization. +Once the `Router` has been set, no new routes can be added. + +```go title="app.go" +import ( + // other imports + // ... + porttypes "github.com/cosmos/ibc-go/v9/modules/core/05-port/types" + ibctransfertypes "github.com/cosmos/ibc-go/v9/modules/apps/transfer/types" +) + +func NewApp(...args) *App { + // .. continuation from above + + // Create static IBC router, add transfer module route, then set and seal it + ibcRouter := porttypes.NewRouter() + ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferModule) + // Setting Router will finalize all routes by sealing router + // No more routes can be added + app.IBCKeeper.SetRouter(ibcRouter) + + // ... continues +``` + +### Module `Manager` and `SimulationManager` + +In order to use IBC, we need to add the new modules to the module `Manager` and to the `SimulationManager`, in case your application supports [simulations](https://github.com/cosmos/cosmos-sdk/blob/main/docs/build/building-modules/14-simulator.md). + +```go title="app.go" +import ( + // other imports + // ... + "github.com/cosmos/cosmos-sdk/types/module" + + ibc "github.com/cosmos/ibc-go/v9/modules/core" + "github.com/cosmos/ibc-go/v9/modules/apps/transfer" +) + +func NewApp(...args) *App { + // ... continuation from above + + app.ModuleManager = module.NewManager( + // other modules + // ... + // highlight-start ++ ibc.NewAppModule(app.IBCKeeper), ++ transfer.NewAppModule(app.TransferKeeper), + // highlight-end + ) + + // ... + + app.simulationManager = module.NewSimulationManagerFromAppModules( + // other modules + // ... + app.ModuleManager.Modules, + map[string]module.AppModuleSimulation{}, + ) + + // ... continues +``` + +### Module account permissions + +After that, we need to grant `Minter` and `Burner` permissions to +the `transfer` `ModuleAccount` to mint and burn relayed tokens. + +```go title="app.go" +import ( + // other imports + // ... + "github.com/cosmos/cosmos-sdk/types/module" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + + // highlight-next-line ++ ibctransfertypes "github.com/cosmos/ibc-go/v9/modules/apps/transfer/types" +) + +// app.go +var ( + // module account permissions + maccPerms = map[string][]string{ + // other module accounts permissions + // ... + ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, + } +) +``` + +#### Integrating light clients + +> Note that from v9 onwards, all light clients are expected to implement the [`LightClientInterface` interface](../03-light-clients/01-developer-guide/02-light-client-module.md#implementing-the-lightclientmodule-interface) defined by core IBC, and have to be explicitly registered in a chain's app.go. This is in contrast to earlier versions of ibc-go when `07-tendermint` and `06-solomachine` were added out of the box. Follow the steps below to integrate the `07-tendermint` light client. + +All light clients must be registered with `module.Manager` in a chain's app.go file. + +The following code example shows how to instantiate `07-tendermint` light client module and register its `ibctm.AppModule`. + +```go title="app.go" +import ( + // other imports + // ... + "github.com/cosmos/cosmos-sdk/types/module" + // highlight-next-line ++ ibctm "github.com/cosmos/ibc-go/v9/modules/light-clients/07-tendermint" +) + +// app.go +// after sealing the IBC router + +storeProvider := app.IBCKeeper.ClientKeeper.GetStoreProvider() + +tmLightClientModule := ibctm.NewLightClientModule(appCodec, storeProvider) +app.IBCKeeper.ClientKeeper.AddRoute(ibctm.ModuleName, &tmLightClientModule) +app.ModuleManager = module.NewManager( + // ... + ibc.NewAppModule(app.IBCKeeper), + transfer.NewAppModule(app.TransferKeeper), // i.e ibc-transfer module + + // register light clients on IBC + // highlight-next-line ++ ibctm.NewAppModule(tmLightClientModule), +) +``` + +### Application ABCI ordering + +One addition from IBC is the concept of `HistoricalInfo` which is stored in the Cosmos SDK `x/staking` module. The number of records stored by `x/staking` is controlled by the `HistoricalEntries` parameter which stores `HistoricalInfo` on a per height basis. +Each entry contains the historical information for the `Header` and `ValidatorSet` of this chain which is stored +at each height during the `BeginBlock` call. The `HistoricalInfo` is required to introspect a blockchain's prior state at a given height in order to verify the light client `ConsensusState` during the +connection handshake. + +```go title="app.go" +import ( + // other imports + // ... + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + ibcexported "github.com/cosmos/ibc-go/v9/modules/core/exported" + ibckeeper "github.com/cosmos/ibc-go/v9/modules/core/keeper" + ibctransfertypes "github.com/cosmos/ibc-go/v9/modules/apps/transfer/types" +) + +func NewApp(...args) *App { + // ... continuation from above + + // add x/staking, ibc and transfer modules to BeginBlockers + app.ModuleManager.SetOrderBeginBlockers( + // other modules ... + stakingtypes.ModuleName, + ibcexported.ModuleName, + ibctransfertypes.ModuleName, + ) + app.ModuleManager.SetOrderEndBlockers( + // other modules ... + stakingtypes.ModuleName, + ibcexported.ModuleName, + ibctransfertypes.ModuleName, + ) + + // ... + + genesisModuleOrder := []string{ + // other modules + // ... + ibcexported.ModuleName, + ibctransfertypes.ModuleName, + } + app.ModuleManager.SetOrderInitGenesis(genesisModuleOrder...) + + // ... continues +``` + +That's it! You have now wired up the IBC module and the `transfer` module, and are now able to send fungible tokens across +different chains. If you want to have a broader view of the changes take a look into the SDK's +[`SimApp`](https://github.com/cosmos/ibc-go/blob/main/testing/simapp/app.go). diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/03-apps/01-apps.md b/docs/versioned_docs/version-v9.0.x/01-ibc/03-apps/01-apps.md new file mode 100644 index 00000000000..dba8f1e903f --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/03-apps/01-apps.md @@ -0,0 +1,444 @@ +--- +title: IBC Applications +sidebar_label: IBC Applications +sidebar_position: 1 +slug: /ibc/apps/apps +--- + +# IBC Applications + +Learn how to configure your application to use IBC and send data packets to other chains. + +This document serves as a guide for developers who want to write their own Inter-blockchain +Communication Protocol (IBC) applications for custom use cases. + +Due to the modular design of the IBC protocol, IBC +application developers do not need to concern themselves with the low-level details of clients, +connections, and proof verification. Nevertheless a brief explanation of the lower levels of the +stack is given so that application developers may have a high-level understanding of the IBC +protocol. Then the document goes into detail on the abstraction layer most relevant for application +developers (channels and ports), and describes how to define your own custom packets, and +`IBCModule` callbacks. + +To have your module interact over IBC you must: bind to a port(s), define your own packet data and acknowledgement structs as well as how to encode/decode them, and implement the +`IBCModule` interface. Below is a more detailed explanation of how to write an IBC application +module correctly. + +:::note + +## Pre-requisites Readings + +- [IBC Overview](../01-overview.md) +- [IBC default integration](../02-integration.md) + +::: + +## Create a custom IBC application module + +### Implement `IBCModule` Interface and callbacks + +The Cosmos SDK expects all IBC modules to implement the [`IBCModule` +interface](https://github.com/cosmos/ibc-go/tree/main/modules/core/05-port/types/module.go). This +interface contains all of the callbacks IBC expects modules to implement. This section will describe +the callbacks that are called during channel handshake execution. + +Here are the channel handshake callbacks that modules are expected to implement: + +```go +// Called by IBC Handler on MsgOpenInit +func (k Keeper) OnChanOpenInit(ctx sdk.Context, + order channeltypes.Order, + connectionHops []string, + portID string, + channelID string, + counterparty channeltypes.Counterparty, + version string, +) error { + + // ... do custom initialization logic + + // Use above arguments to determine if we want to abort handshake + // Examples: Abort if order == UNORDERED, + // Abort if version is unsupported + err := checkArguments(args) + return err +} + +// Called by IBC Handler on MsgOpenTry +OnChanOpenTry( + ctx sdk.Context, + order channeltypes.Order, + connectionHops []string, + portID, + channelID string, + counterparty channeltypes.Counterparty, + counterpartyVersion string, +) (string, error) { + // ... do custom initialization logic + + // Use above arguments to determine if we want to abort handshake + if err := checkArguments(args); err != nil { + return err + } + + // Construct application version + // IBC applications must return the appropriate application version + // This can be a simple string or it can be a complex version constructed + // from the counterpartyVersion and other arguments. + // The version returned will be the channel version used for both channel ends. + appVersion := negotiateAppVersion(counterpartyVersion, args) + + return appVersion, nil +} + +// Called by IBC Handler on MsgOpenAck +OnChanOpenAck( + ctx sdk.Context, + portID, + channelID string, + counterpartyVersion string, +) error { + // ... do custom initialization logic + + // Use above arguments to determine if we want to abort handshake + err := checkArguments(args) + return err +} + +// Called by IBC Handler on MsgOpenConfirm +OnChanOpenConfirm( + ctx sdk.Context, + portID, + channelID string, +) error { + // ... do custom initialization logic + + // Use above arguments to determine if we want to abort handshake + err := checkArguments(args) + return err +} +``` + +The channel closing handshake will also invoke module callbacks that can return errors to abort the +closing handshake. Closing a channel is a 2-step handshake, the initiating chain calls +`ChanCloseInit` and the finalizing chain calls `ChanCloseConfirm`. + +```go +// Called by IBC Handler on MsgCloseInit +OnChanCloseInit( + ctx sdk.Context, + portID, + channelID string, +) error { + // ... do custom finalization logic + + // Use above arguments to determine if we want to abort handshake + err := checkArguments(args) + return err +} + +// Called by IBC Handler on MsgCloseConfirm +OnChanCloseConfirm( + ctx sdk.Context, + portID, + channelID string, +) error { + // ... do custom finalization logic + + // Use above arguments to determine if we want to abort handshake + err := checkArguments(args) + return err +} +``` + +#### Channel Handshake Version Negotiation + +Application modules are expected to verify versioning used during the channel handshake procedure. + +- `ChanOpenInit` callback should verify that the `MsgChanOpenInit.Version` is valid +- `ChanOpenTry` callback should construct the application version used for both channel ends. If no application version can be constructed, it must return an error. +- `ChanOpenAck` callback should verify that the `MsgChanOpenAck.CounterpartyVersion` is valid and supported. + +IBC expects application modules to perform application version negotiation in `OnChanOpenTry`. The negotiated version +must be returned to core IBC. If the version cannot be negotiated, an error should be returned. + +Versions must be strings but can implement any versioning structure. If your application plans to +have linear releases then semantic versioning is recommended. If your application plans to release +various features in between major releases then it is advised to use the same versioning scheme +as IBC. This versioning scheme specifies a version identifier and compatible feature set with +that identifier. Valid version selection includes selecting a compatible version identifier with +a subset of features supported by your application for that version. The struct is used for this +scheme can be found in `03-connection/types`. + +Since the version type is a string, applications have the ability to do simple version verification +via string matching or they can use the already implemented versioning system and pass the proto +encoded version into each handhshake call as necessary. + +ICS20 currently implements basic string matching with a single supported version. + +### Custom Packets + +Modules connected by a channel must agree on what application data they are sending over the +channel, as well as how they will encode/decode it. This process is not specified by IBC as it is up +to each application module to determine how to implement this agreement. However, for most +applications this will happen as a version negotiation during the channel handshake. While more +complex version negotiation is possible to implement inside the channel opening handshake, a very +simple version negotiation is implemented in the [ibc-transfer module](https://github.com/cosmos/ibc-go/tree/main/modules/apps/transfer/module.go). + +Thus, a module must define its custom packet data structure, along with a well-defined way to +encode and decode it to and from `[]byte`. + +```go +// Custom packet data defined in application module +type CustomPacketData struct { + // Custom fields ... +} + +EncodePacketData(packetData CustomPacketData) []byte { + // encode packetData to bytes +} + +DecodePacketData(encoded []byte) (CustomPacketData) { + // decode from bytes to packet data +} +``` + +Then a module must encode its packet data before sending it through IBC. + +```go +// Sending custom application packet data +data := EncodePacketData(customPacketData) +packet.Data = data +// Send packet to IBC, authenticating with channelCap +sequence, err := IBCChannelKeeper.SendPacket( + ctx, + sourcePort, + sourceChannel, + timeoutHeight, + timeoutTimestamp, + data, +) +``` + +A module receiving a packet must decode the `PacketData` into a structure it expects so that it can +act on it. + +```go +// Receiving custom application packet data (in OnRecvPacket) +packetData := DecodePacketData(packet.Data) +// handle received custom packet data +``` + +#### Packet Flow Handling + +Just as IBC expected modules to implement callbacks for channel handshakes, IBC also expects modules +to implement callbacks for handling the packet flow through a channel. + +Once a module A and module B are connected to each other, relayers can start relaying packets and +acknowledgements back and forth on the channel. + +![IBC packet flow diagram](https://media.githubusercontent.com/media/cosmos/ibc/old/spec/ics-004-channel-and-packet-semantics/channel-state-machine.png) + +Briefly, a successful packet flow works as follows: + +1. module A sends a packet through the IBC module +2. the packet is received by module B +3. if module B writes an acknowledgement of the packet then module A will process the + acknowledgement +4. if the packet is not successfully received before the timeout, then module A processes the + packet's timeout. + +##### Sending Packets + +Modules do not send packets through callbacks, since the modules initiate the action of sending +packets to the IBC module, as opposed to other parts of the packet flow where msgs sent to the IBC +module must trigger execution on the port-bound module through the use of callbacks. Thus, to send a +packet a module simply needs to call `SendPacket` on the `IBCChannelKeeper`. + +```go +// Sending custom application packet data +data := EncodePacketData(customPacketData) +// Send packet to IBC, authenticating with channelCap +sequence, err := IBCChannelKeeper.SendPacket( + ctx, + sourcePort, + sourceChannel, + timeoutHeight, + timeoutTimestamp, + data, +) +``` + +##### Receiving Packets + +To handle receiving packets, the module must implement the `OnRecvPacket` callback. This gets +invoked by the IBC module after the packet has been proved valid and correctly processed by the IBC +keepers. Thus, the `OnRecvPacket` callback only needs to worry about making the appropriate state +changes given the packet data without worrying about whether the packet is valid or not. + +Modules may return to the IBC handler an acknowledgement which implements the Acknowledgement interface. +The IBC handler will then commit this acknowledgement of the packet so that a relayer may relay the +acknowledgement back to the sender module. + +The state changes that occurred during this callback will only be written if: + +- the acknowledgement was successful as indicated by the `Success()` function of the acknowledgement +- if the acknowledgement returned is nil indicating that an asynchronous process is occurring + +NOTE: Applications which process asynchronous acknowledgements must handle reverting state changes +when appropriate. Any state changes that occurred during the `OnRecvPacket` callback will be written +for asynchronous acknowledgements. + +```go +OnRecvPacket( + ctx sdk.Context, + packet channeltypes.Packet, +) ibcexported.Acknowledgement { + // Decode the packet data + packetData := DecodePacketData(packet.Data) + + // do application state changes based on packet data and return the acknowledgement + // NOTE: The acknowledgement will indicate to the IBC handler if the application + // state changes should be written via the `Success()` function. Application state + // changes are only written if the acknowledgement is successful or the acknowledgement + // returned is nil indicating that an asynchronous acknowledgement will occur. + ack := processPacket(ctx, packet, packetData) + + return ack +} +``` + +The Acknowledgement interface: + +```go +// Acknowledgement defines the interface used to return +// acknowledgements in the OnRecvPacket callback. +type Acknowledgement interface { + Success() bool + Acknowledgement() []byte +} +``` + +### Acknowledgements + +Modules may commit an acknowledgement upon receiving and processing a packet in the case of synchronous packet processing. +In the case where a packet is processed at some later point after the packet has been received (asynchronous execution), the acknowledgement +will be written once the packet has been processed by the application which may be well after the packet receipt. + +NOTE: Most blockchain modules will want to use the synchronous execution model in which the module processes and writes the acknowledgement +for a packet as soon as it has been received from the IBC module. + +This acknowledgement can then be relayed back to the original sender chain, which can take action +depending on the contents of the acknowledgement. + +Just as packet data was opaque to IBC, acknowledgements are similarly opaque. Modules must pass and +receive acknowledegments with the IBC modules as byte strings. + +Thus, modules must agree on how to encode/decode acknowledgements. The process of creating an +acknowledgement struct along with encoding and decoding it, is very similar to the packet data +example above. [ICS 04](https://github.com/cosmos/ibc/blob/master/spec/core/ics-004-channel-and-packet-semantics#acknowledgement-envelope) +specifies a recommended format for acknowledgements. This acknowledgement type can be imported from +[channel types](https://github.com/cosmos/ibc-go/tree/main/modules/core/04-channel/types). + +While modules may choose arbitrary acknowledgement structs, a default acknowledgement types is provided by IBC [here](https://github.com/cosmos/ibc-go/blob/main/proto/ibc/core/channel/v1/channel.proto): + +```proto +// Acknowledgement is the recommended acknowledgement format to be used by +// app-specific protocols. +// NOTE: The field numbers 21 and 22 were explicitly chosen to avoid accidental +// conflicts with other protobuf message formats used for acknowledgements. +// The first byte of any message with this format will be the non-ASCII values +// `0xaa` (result) or `0xb2` (error). Implemented as defined by ICS: +// https://github.com/cosmos/ibc/tree/master/spec/core/ics-004-channel-and-packet-semantics#acknowledgement-envelope +message Acknowledgement { + // response contains either a result or an error and must be non-empty + oneof response { + bytes result = 21; + string error = 22; + } +} +``` + +#### Acknowledging Packets + +After a module writes an acknowledgement, a relayer can relay back the acknowledgement to the sender module. The sender module can +then process the acknowledgement using the `OnAcknowledgementPacket` callback. The contents of the +acknowledgement is entirely up to the modules on the channel (just like the packet data); however, it +may often contain information on whether the packet was successfully processed along +with some additional data that could be useful for remediation if the packet processing failed. + +Since the modules are responsible for agreeing on an encoding/decoding standard for packet data and +acknowledgements, IBC will pass in the acknowledgements as `[]byte` to this callback. The callback +is responsible for decoding the acknowledgement and processing it. + +```go +OnAcknowledgementPacket( + ctx sdk.Context, + packet channeltypes.Packet, + acknowledgement []byte, +) (*sdk.Result, error) { + // Decode acknowledgement + ack := DecodeAcknowledgement(acknowledgement) + + // process ack + res, err := processAck(ack) + return res, err +} +``` + +#### Timeout Packets + +If the timeout for a packet is reached before the packet is successfully received or the +counterparty channel end is closed before the packet is successfully received, then the receiving +chain can no longer process it. Thus, the sending chain must process the timeout using +`OnTimeoutPacket` to handle this situation. Again the IBC module will verify that the timeout is +indeed valid, so our module only needs to implement the state machine logic for what to do once a +timeout is reached and the packet can no longer be received. + +```go +OnTimeoutPacket( + ctx sdk.Context, + packet channeltypes.Packet, +) (*sdk.Result, error) { + // do custom timeout logic +} +``` + +### Routing + +As mentioned above, modules must implement the IBC module interface (which contains both channel +handshake callbacks and packet handling callbacks). The concrete implementation of this interface +must be registered with the module name as a route on the IBC `Router`. + +```go +// app.go +func NewApp(...args) *App { +// ... + +// Create static IBC router, add module routes, then set and seal it +ibcRouter := port.NewRouter() + +ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferModule) +// Note: moduleCallbacks must implement IBCModule interface +ibcRouter.AddRoute(moduleName, moduleCallbacks) + +// Setting Router will finalize all routes by sealing router +// No more routes can be added +app.IBCKeeper.SetRouter(ibcRouter) +``` + +## Working Example + +For a real working example of an IBC application, you can look through the `ibc-transfer` module +which implements everything discussed above. + +Here are the useful parts of the module to look at: + +[Binding to transfer +port](https://github.com/cosmos/ibc-go/blob/main/modules/apps/transfer/keeper/genesis.go) + +[Sending transfer +packets](https://github.com/cosmos/ibc-go/blob/main/modules/apps/transfer/keeper/relay.go) + +[Implementing IBC +callbacks](https://github.com/cosmos/ibc-go/blob/main/modules/apps/transfer/ibc_module.go) diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/03-apps/02-ibcmodule.md b/docs/versioned_docs/version-v9.0.x/01-ibc/03-apps/02-ibcmodule.md new file mode 100644 index 00000000000..4d8a6019bbd --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/03-apps/02-ibcmodule.md @@ -0,0 +1,367 @@ +--- +title: Implement IBCModule interface and callbacks +sidebar_label: Implement IBCModule interface and callbacks +sidebar_position: 2 +slug: /ibc/apps/ibcmodule +--- + +# Implement `IBCModule` interface and callbacks + +:::note Synopsis +Learn how to implement the `IBCModule` interface and all of the callbacks it requires. +::: + +The Cosmos SDK expects all IBC modules to implement the [`IBCModule` +interface](https://github.com/cosmos/ibc-go/tree/main/modules/core/05-port/types/module.go). This interface contains all of the callbacks IBC expects modules to implement. They include callbacks related to channel handshake, closing and packet callbacks (`OnRecvPacket`, `OnAcknowledgementPacket` and `OnTimeoutPacket`). + +```go +// IBCModule implements the ICS26 interface for given the keeper. +// The implementation of the IBCModule interface could for example be in a file called ibc_module.go, +// but ultimately file structure is up to the developer +type IBCModule struct { + keeper keeper.Keeper +} +``` + +Additionally, in the `module.go` file, add the following line: + +```go +var ( + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} + // Add this line + _ porttypes.IBCModule = IBCModule{} +) +``` + +:::note + +## Pre-requisite readings + +- [IBC Overview](../01-overview.md) +- [IBC default integration](../02-integration.md) + +::: + +## Channel handshake callbacks + +This section will describe the callbacks that are called during channel handshake execution. + +Here are the channel handshake callbacks that modules are expected to implement: + +> Note that some of the code below is *pseudo code*, indicating what actions need to happen but leaving it up to the developer to implement a custom implementation. E.g. the `checkArguments` and `negotiateAppVersion` functions. + +```go +// Called by IBC Handler on MsgOpenInit +func (im IBCModule) OnChanOpenInit(ctx sdk.Context, + order channeltypes.Order, + connectionHops []string, + portID string, + channelID string, + counterparty channeltypes.Counterparty, + version string, +) (string, error) { + // ... do custom initialization logic + + // Use above arguments to determine if we want to abort handshake + // Examples: + // - Abort if order == UNORDERED, + // - Abort if version is unsupported + if err := checkArguments(args); err != nil { + return "", err + } + + + return version, nil +} + +// Called by IBC Handler on MsgOpenTry +func (im IBCModule) OnChanOpenTry( + ctx sdk.Context, + order channeltypes.Order, + connectionHops []string, + portID, + channelID string, + counterparty channeltypes.Counterparty, + counterpartyVersion string, +) (string, error) { + // ... do custom initialization logic + + // Use above arguments to determine if we want to abort handshake + if err := checkArguments(args); err != nil { + return "", err + } + + // Construct application version + // IBC applications must return the appropriate application version + // This can be a simple string or it can be a complex version constructed + // from the counterpartyVersion and other arguments. + // The version returned will be the channel version used for both channel ends. + appVersion := negotiateAppVersion(counterpartyVersion, args) + + return appVersion, nil +} + +// Called by IBC Handler on MsgOpenAck +func (im IBCModule) OnChanOpenAck( + ctx sdk.Context, + portID, + channelID string, + counterpartyVersion string, +) error { + if counterpartyVersion != types.Version { + return sdkerrors.Wrapf(types.ErrInvalidVersion, "invalid counterparty version: %s, expected %s", counterpartyVersion, types.Version) + } + + // do custom logic + + return nil +} + +// Called by IBC Handler on MsgOpenConfirm +func (im IBCModule) OnChanOpenConfirm( + ctx sdk.Context, + portID, + channelID string, +) error { + // do custom logic + + return nil +} +``` + +### Channel closing callbacks + +The channel closing handshake will also invoke module callbacks that can return errors to abort the closing handshake. Closing a channel is a 2-step handshake, the initiating chain calls `ChanCloseInit` and the finalizing chain calls `ChanCloseConfirm`. + +Currently, all IBC modules in this repository return an error for `OnChanCloseInit` to prevent the channels from closing. This is because any user can call `ChanCloseInit` by submitting a `MsgChannelCloseInit` transaction. + +```go +// Called by IBC Handler on MsgCloseInit +func (im IBCModule) OnChanCloseInit( + ctx sdk.Context, + portID, + channelID string, +) error { + // ... do custom finalization logic + + // Use above arguments to determine if we want to abort handshake + err := checkArguments(args) + return err +} + +// Called by IBC Handler on MsgCloseConfirm +func (im IBCModule) OnChanCloseConfirm( + ctx sdk.Context, + portID, + channelID string, +) error { + // ... do custom finalization logic + + // Use above arguments to determine if we want to abort handshake + err := checkArguments(args) + return err +} +``` + +### Channel handshake version negotiation + +Application modules are expected to verify versioning used during the channel handshake procedure. + +- `OnChanOpenInit` will verify that the relayer-chosen parameters + are valid and perform any custom `INIT` logic. + It may return an error if the chosen parameters are invalid + in which case the handshake is aborted. + If the provided version string is non-empty, `OnChanOpenInit` should return + the version string if valid or an error if the provided version is invalid. + **If the version string is empty, `OnChanOpenInit` is expected to + return a default version string representing the version(s) + it supports.** + If there is no default version string for the application, + it should return an error if the provided version is an empty string. +- `OnChanOpenTry` will verify the relayer-chosen parameters along with the + counterparty-chosen version string and perform custom `TRY` logic. + If the relayer-chosen parameters + are invalid, the callback must return an error to abort the handshake. + If the counterparty-chosen version is not compatible with this module's + supported versions, the callback must return an error to abort the handshake. + If the versions are compatible, the try callback must select the final version + string and return it to core IBC. + `OnChanOpenTry` may also perform custom initialization logic. +- `OnChanOpenAck` will error if the counterparty selected version string + is invalid and abort the handshake. It may also perform custom ACK logic. + +Versions must be strings but can implement any versioning structure. If your application plans to +have linear releases then semantic versioning is recommended. If your application plans to release +various features in between major releases then it is advised to use the same versioning scheme +as IBC. This versioning scheme specifies a version identifier and compatible feature set with +that identifier. Valid version selection includes selecting a compatible version identifier with +a subset of features supported by your application for that version. The struct used for this +scheme can be found in [03-connection/types](https://github.com/cosmos/ibc-go/blob/main/modules/core/03-connection/types/version.go#L16). + +Since the version type is a string, applications have the ability to do simple version verification +via string matching or they can use the already implemented versioning system and pass the proto +encoded version into each handhshake call as necessary. + +ICS20 currently implements basic string matching with a single supported version. + +## Packet callbacks + +Just as IBC expects modules to implement callbacks for channel handshakes, it also expects modules to implement callbacks for handling the packet flow through a channel, as defined in the `IBCModule` interface. + +Once a module A and module B are connected to each other, relayers can start relaying packets and acknowledgements back and forth on the channel. + +![IBC packet flow diagram](./images/packet_flow.png) + +Briefly, a successful packet flow works as follows: + +1. Module A sends a packet through the IBC module +2. The packet is received by module B +3. If module B writes an acknowledgement of the packet then module A will process the acknowledgement +4. If the packet is not successfully received before the timeout, then module A processes the packet's timeout. + +### Sending packets + +Modules **do not send packets through callbacks**, since the modules initiate the action of sending packets to the IBC module, as opposed to other parts of the packet flow where messages sent to the IBC +module must trigger execution on the port-bound module through the use of callbacks. Thus, to send a packet a module simply needs to call `SendPacket` on the `IBCChannelKeeper`. + +> Note that some of the code below is *pseudo code*, indicating what actions need to happen but leaving it up to the developer to implement a custom implementation. E.g. the `EncodePacketData(customPacketData)` function. + +```go +// Sending custom application packet data +data := EncodePacketData(customPacketData) +// Send packet to IBC, authenticating with channelCap +sequence, err := IBCChannelKeeper.SendPacket( + ctx, + sourcePort, + sourceChannel, + timeoutHeight, + timeoutTimestamp, + data, +) +``` + +### Receiving packets + +To handle receiving packets, the module must implement the `OnRecvPacket` callback. This gets +invoked by the IBC module after the packet has been proved valid and correctly processed by the IBC +keepers. Thus, the `OnRecvPacket` callback only needs to worry about making the appropriate state +changes given the packet data without worrying about whether the packet is valid or not. + +Modules may return to the IBC handler an acknowledgement which implements the `Acknowledgement` interface. +The IBC handler will then commit this acknowledgement of the packet so that a relayer may relay the +acknowledgement back to the sender module. + +The state changes that occurred during this callback will only be written if: + +- the acknowledgement was successful as indicated by the `Success()` function of the acknowledgement +- if the acknowledgement returned is nil indicating that an asynchronous process is occurring + +NOTE: Applications which process asynchronous acknowledgements must handle reverting state changes +when appropriate. Any state changes that occurred during the `OnRecvPacket` callback will be written +for asynchronous acknowledgements. + +> Note that some of the code below is *pseudo code*, indicating what actions need to happen but leaving it up to the developer to implement a custom implementation. E.g. the `DecodePacketData(packet.Data)` function. + +```go +func (im IBCModule) OnRecvPacket( + ctx sdk.Context, + packet channeltypes.Packet, +) ibcexported.Acknowledgement { + // Decode the packet data + packetData := DecodePacketData(packet.Data) + + // do application state changes based on packet data and return the acknowledgement + // NOTE: The acknowledgement will indicate to the IBC handler if the application + // state changes should be written via the `Success()` function. Application state + // changes are only written if the acknowledgement is successful or the acknowledgement + // returned is nil indicating that an asynchronous acknowledgement will occur. + ack := processPacket(ctx, packet, packetData) + + return ack +} +``` + +Reminder, the `Acknowledgement` interface: + +```go +// Acknowledgement defines the interface used to return +// acknowledgements in the OnRecvPacket callback. +type Acknowledgement interface { + Success() bool + Acknowledgement() []byte +} +``` + +### Acknowledging packets + +After a module writes an acknowledgement, a relayer can relay back the acknowledgement to the sender module. The sender module can +then process the acknowledgement using the `OnAcknowledgementPacket` callback. The contents of the +acknowledgement is entirely up to the modules on the channel (just like the packet data); however, it +may often contain information on whether the packet was successfully processed along +with some additional data that could be useful for remediation if the packet processing failed. + +Since the modules are responsible for agreeing on an encoding/decoding standard for packet data and +acknowledgements, IBC will pass in the acknowledgements as `[]byte` to this callback. The callback +is responsible for decoding the acknowledgement and processing it. + +> Note that some of the code below is *pseudo code*, indicating what actions need to happen but leaving it up to the developer to implement a custom implementation. E.g. the `DecodeAcknowledgement(acknowledgments)` and `processAck(ack)` functions. + +```go +func (im IBCModule) OnAcknowledgementPacket( + ctx sdk.Context, + packet channeltypes.Packet, + acknowledgement []byte, +) (*sdk.Result, error) { + // Decode acknowledgement + ack := DecodeAcknowledgement(acknowledgement) + + // process ack + res, err := processAck(ack) + return res, err +} +``` + +### Timeout packets + +If the timeout for a packet is reached before the packet is successfully received or the +counterparty channel end is closed before the packet is successfully received, then the receiving +chain can no longer process it. Thus, the sending chain must process the timeout using +`OnTimeoutPacket` to handle this situation. Again the IBC module will verify that the timeout is +indeed valid, so our module only needs to implement the state machine logic for what to do once a +timeout is reached and the packet can no longer be received. + +```go +func (im IBCModule) OnTimeoutPacket( + ctx sdk.Context, + packet channeltypes.Packet, +) (*sdk.Result, error) { + // do custom timeout logic +} +``` + +### Optional interfaces + +The following interface are optional and MAY be implemented by an IBCModule. + +#### PacketDataUnmarshaler + +The `PacketDataUnmarshaler` interface is defined as follows: + +```go +// PacketDataUnmarshaler defines an optional interface which allows a middleware to +// request the packet data to be unmarshaled by the base application. +type PacketDataUnmarshaler interface { + // UnmarshalPacketData unmarshals the packet data into a concrete type + // ctx, portID, channelID are provided as arguments, so that (if needed) + // the packet data can be unmarshaled based on the channel version. + // The version of the underlying app is also returned. + UnmarshalPacketData(ctx sdk.Context, portID, channelID string, bz []byte) (interface{}, string, error) +} +``` + +The implementation of `UnmarshalPacketData` should unmarshal the bytes into the packet data type defined for an IBC stack. +The base application of an IBC stack should unmarshal the bytes into its packet data type, while a middleware may simply defer the call to the underlying application. + +This interface allows middlewares to unmarshal a packet data in order to make use of interfaces the packet data type implements. +For example, the callbacks middleware makes use of this function to access packet data types which implement the `PacketData` and `PacketDataProvider` interfaces. diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/03-apps/03-bindports.md b/docs/versioned_docs/version-v9.0.x/01-ibc/03-apps/03-bindports.md new file mode 100644 index 00000000000..6a3cc27a924 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/03-apps/03-bindports.md @@ -0,0 +1,122 @@ +--- +title: Bind ports +sidebar_label: Bind ports +sidebar_position: 3 +slug: /ibc/apps/bindports +--- + +# Bind ports + +:::note Synopsis +Learn what changes to make to bind modules to their ports on initialization. +::: + +:::note + +## Pre-requisite readings + +- [IBC Overview](../01-overview.md) +- [IBC default integration](../02-integration.md) + +::: +Currently, ports must be bound on app initialization. In order to bind modules to their respective ports on initialization, the following needs to be implemented: + +> Note that `portID` does not refer to a certain numerical ID, like `localhost:8080` with a `portID` 8080. Rather it refers to the application module the port binds. For IBC Modules built with the Cosmos SDK, it defaults to the module's name and for Cosmwasm contracts it defaults to the contract address. + +1. Add port ID to the `GenesisState` proto definition: + +```protobuf +message GenesisState { + string port_id = 1; + // other fields +} +``` + +1. Add port ID as a key to the module store: + +```go +// x//types/keys.go +const ( + // ModuleName defines the IBC Module name + ModuleName = "moduleName" + + // Version defines the current version the IBC + // module supports + Version = "moduleVersion-1" + + // PortID is the default port id that module binds to + PortID = "portID" + + // ... +) +``` + +1. Add port ID to `x//types/genesis.go`: + +```go +// in x//types/genesis.go + +// DefaultGenesisState returns a GenesisState with "transfer" as the default PortID. +func DefaultGenesisState() *GenesisState { + return &GenesisState{ + PortId: PortID, + // additional k-v fields + } +} + +// Validate performs basic genesis state validation returning an error upon any +// failure. +func (gs GenesisState) Validate() error { + if err := host.PortIdentifierValidator(gs.PortId); err != nil { + return err + } + //additional validations + + return gs.Params.Validate() +} +``` + +1. Bind to port(s) in the module keeper's `InitGenesis`: + +```go +// InitGenesis initializes the ibc-module state and binds to PortID. +func (k Keeper) InitGenesis(ctx sdk.Context, state types.GenesisState) { + k.SetPort(ctx, state.PortId) + + // ... + + // Only try to bind to port if it is not already bound, since we may already own + // port capability from capability InitGenesis + if !k.hasCapability(ctx, state.PortId) { + // transfer module binds to the transfer port on InitChain + // and claims the returned capability + err := k.BindPort(ctx, state.PortId) + if err != nil { + panic(fmt.Sprintf("could not claim port capability: %v", err)) + } + } + + // ... +} +``` + +With: + +```go +// IsBound checks if the module is already bound to the desired port +func (k Keeper) IsBound(ctx sdk.Context, portID string) bool { + _, ok := k.scopedKeeper.GetCapability(ctx, host.PortPath(portID)) + return ok +} + +// BindPort defines a wrapper function for the port Keeper's function in +// order to expose it to module's InitGenesis function +func (k Keeper) BindPort(ctx sdk.Context, portID string) error { + cap := k.portKeeper.BindPort(ctx, portID) + return k.ClaimCapability(ctx, cap, host.PortPath(portID)) +} +``` + +The module binds to the desired port(s) and returns the capabilities. + +In the above we find reference to keeper methods that wrap other keeper functionality, in the next section the keeper methods that need to be implemented will be defined. diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/03-apps/04-keeper.md b/docs/versioned_docs/version-v9.0.x/01-ibc/03-apps/04-keeper.md new file mode 100644 index 00000000000..a1bb8fe838d --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/03-apps/04-keeper.md @@ -0,0 +1,71 @@ +--- +title: Keeper +sidebar_label: Keeper +sidebar_position: 4 +slug: /ibc/apps/keeper +--- + +# Keeper + +:::note Synopsis +Learn how to implement the IBC Module keeper. +::: + +:::note + +## Pre-requisite readings + +- [IBC Overview](../01-overview.md) +- [IBC default integration](../02-integration.md) + +::: +In the previous sections, on channel handshake callbacks and port binding in `InitGenesis`, a reference was made to keeper methods that need to be implemented when creating a custom IBC module. Below is an overview of how to define an IBC module's keeper. + +> Note that some code has been left out for clarity, to get a full code overview, please refer to [the transfer module's keeper in the ibc-go repo](https://github.com/cosmos/ibc-go/blob/main/modules/apps/transfer/keeper/keeper.go). + +```go +// Keeper defines the IBC app module keeper +type Keeper struct { + storeKey sdk.StoreKey + cdc codec.BinaryCodec + paramSpace paramtypes.Subspace + + channelKeeper types.ChannelKeeper + portKeeper types.PortKeeper + + // ... additional according to custom logic +} + +// NewKeeper creates a new IBC app module Keeper instance +func NewKeeper( + // args +) Keeper { + // ... + + return Keeper{ + cdc: cdc, + storeKey: key, + paramSpace: paramSpace, + + channelKeeper: channelKeeper, + portKeeper: portKeeper, + scopedKeeper: scopedKeeper, + + // ... additional according to custom logic + } +} + +// GetPort returns the portID for the IBC app module. Used in ExportGenesis +func (k Keeper) GetPort(ctx sdk.Context) string { + store := ctx.KVStore(k.storeKey) + return string(store.Get(types.PortKey)) +} + +// SetPort sets the portID for the IBC app module. Used in InitGenesis +func (k Keeper) SetPort(ctx sdk.Context, portID string) { + store := ctx.KVStore(k.storeKey) + store.Set(types.PortKey, []byte(portID)) +} + +// ... additional according to custom logic +``` diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/03-apps/05-packets_acks.md b/docs/versioned_docs/version-v9.0.x/01-ibc/03-apps/05-packets_acks.md new file mode 100644 index 00000000000..18d34cdeaad --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/03-apps/05-packets_acks.md @@ -0,0 +1,163 @@ +--- +title: Define packets and acks +sidebar_label: Define packets and acks +sidebar_position: 5 +slug: /ibc/apps/packets_acks +--- + +# Define packets and acks + +:::note Synopsis +Learn how to define custom packet and acknowledgement structs and how to encode and decode them. +::: + +:::note + +## Pre-requisite readings + +- [IBC Overview](../01-overview.md) +- [IBC default integration](../02-integration.md) + +::: + +## Custom packets + +Modules connected by a channel must agree on what application data they are sending over the +channel, as well as how they will encode/decode it. This process is not specified by IBC as it is up +to each application module to determine how to implement this agreement. However, for most +applications this will happen as a version negotiation during the channel handshake. While more +complex version negotiation is possible to implement inside the channel opening handshake, a very +simple version negotiation is implemented in the [ibc-transfer module](https://github.com/cosmos/ibc-go/tree/main/modules/apps/transfer/module.go). + +Thus, a module must define its custom packet data structure, along with a well-defined way to +encode and decode it to and from `[]byte`. + +```go +// Custom packet data defined in application module +type CustomPacketData struct { + // Custom fields ... +} + +EncodePacketData(packetData CustomPacketData) []byte { + // encode packetData to bytes +} + +DecodePacketData(encoded []byte) (CustomPacketData) { + // decode from bytes to packet data +} +``` + +> Note that the `CustomPacketData` struct is defined in the proto definition and then compiled by the protobuf compiler. + +Then a module must encode its packet data before sending it through IBC. + +```go +// Sending custom application packet data +data := EncodePacketData(customPacketData) +// Send packet to IBC, authenticating with channelCap +sequence, err := IBCChannelKeeper.SendPacket( + ctx, + sourcePort, + sourceChannel, + timeoutHeight, + timeoutTimestamp, + data, +) +``` + +A module receiving a packet must decode the `PacketData` into a structure it expects so that it can +act on it. + +```go +// Receiving custom application packet data (in OnRecvPacket) +packetData := DecodePacketData(packet.Data) +// handle received custom packet data +``` + +### Optional interfaces + +The following interfaces are optional and MAY be implemented by a custom packet type. +They allow middlewares such as callbacks to access information stored within the packet data. + +#### PacketData interface + +The `PacketData` interface is defined as follows: + +```go +// PacketData defines an optional interface which an application's packet data structure may implement. +type PacketData interface { + // GetPacketSender returns the sender address of the packet data. + // If the packet sender is unknown or undefined, an empty string should be returned. + GetPacketSender(sourcePortID string) string +} +``` + +The implementation of `GetPacketSender` should return the sender of the packet data. +If the packet sender is unknown or undefined, an empty string should be returned. + +This interface is intended to give IBC middlewares access to the packet sender of a packet data type. + +#### PacketDataProvider interface + +The `PacketDataProvider` interface is defined as follows: + +```go +// PacketDataProvider defines an optional interfaces for retrieving custom packet data stored on behalf of another application. +// An existing problem in the IBC middleware design is the inability for a middleware to define its own packet data type and insert packet sender provided information. +// A short term solution was introduced into several application's packet data to utilize a memo field to carry this information on behalf of another application. +// This interfaces standardizes that behaviour. Upon realization of the ability for middleware's to define their own packet data types, this interface will be deprecated and removed with time. +type PacketDataProvider interface { + // GetCustomPacketData returns the packet data held on behalf of another application. + // The name the information is stored under should be provided as the key. + // If no custom packet data exists for the key, nil should be returned. + GetCustomPacketData(key string) interface{} +} +``` + +The implementation of `GetCustomPacketData` should return packet data held on behalf of another application (if present and supported). +If this functionality is not supported, it should return nil. Otherwise it should return the packet data associated with the provided key. + +This interface gives IBC applications access to the packet data information embedded into the base packet data type. +Within transfer and interchain accounts, the embedded packet data is stored within the Memo field. + +Once all IBC applications within an IBC stack are capable of creating/maintaining their own packet data type's, this interface function will be deprecated and removed. + +## Acknowledgements + +Modules may commit an acknowledgement upon receiving and processing a packet in the case of synchronous packet processing. +In the case where a packet is processed at some later point after the packet has been received (asynchronous execution), the acknowledgement +will be written once the packet has been processed by the application which may be well after the packet receipt. + +NOTE: Most blockchain modules will want to use the synchronous execution model in which the module processes and writes the acknowledgement +for a packet as soon as it has been received from the IBC module. + +This acknowledgement can then be relayed back to the original sender chain, which can take action +depending on the contents of the acknowledgement. + +Just as packet data was opaque to IBC, acknowledgements are similarly opaque. Modules must pass and +receive acknowledegments with the IBC modules as byte strings. + +Thus, modules must agree on how to encode/decode acknowledgements. The process of creating an +acknowledgement struct along with encoding and decoding it, is very similar to the packet data +example above. [ICS 04](https://github.com/cosmos/ibc/blob/master/spec/core/ics-004-channel-and-packet-semantics#acknowledgement-envelope) +specifies a recommended format for acknowledgements. This acknowledgement type can be imported from +[channel types](https://github.com/cosmos/ibc-go/tree/main/modules/core/04-channel/types). + +While modules may choose arbitrary acknowledgement structs, a default acknowledgement types is provided by IBC [here](https://github.com/cosmos/ibc-go/blob/main/proto/ibc/core/channel/v1/channel.proto): + +```protobuf +// Acknowledgement is the recommended acknowledgement format to be used by +// app-specific protocols. +// NOTE: The field numbers 21 and 22 were explicitly chosen to avoid accidental +// conflicts with other protobuf message formats used for acknowledgements. +// The first byte of any message with this format will be the non-ASCII values +// `0xaa` (result) or `0xb2` (error). Implemented as defined by ICS: +// https://github.com/cosmos/ibc/tree/master/spec/core/ics-004-channel-and-packet-semantics#acknowledgement-envelope +message Acknowledgement { + // response contains either a result or an error and must be non-empty + oneof response { + bytes result = 21; + string error = 22; + } +} +``` diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/03-apps/06-routing.md b/docs/versioned_docs/version-v9.0.x/01-ibc/03-apps/06-routing.md new file mode 100644 index 00000000000..666fb1af11b --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/03-apps/06-routing.md @@ -0,0 +1,44 @@ +--- +title: Routing +sidebar_label: Routing +sidebar_position: 6 +slug: /ibc/apps/routing +--- + +# Routing + +:::note + +## Pre-requisite readings + +- [IBC Overview](../01-overview.md) +- [IBC default integration](../02-integration.md) + +::: +:::note Synopsis +Learn how to hook a route to the IBC router for the custom IBC module. +::: + +As mentioned above, modules must implement the `IBCModule` interface (which contains both channel +handshake callbacks and packet handling callbacks). The concrete implementation of this interface +must be registered with the module name as a route on the IBC `Router`. + +```go +// app.go +func NewApp(...args) *App { + // ... + + // Create static IBC router, add module routes, then set and seal it + ibcRouter := port.NewRouter() + + ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferModule) + // Note: moduleCallbacks must implement IBCModule interface + ibcRouter.AddRoute(moduleName, moduleCallbacks) + + // Setting Router will finalize all routes by sealing router + // No more routes can be added + app.IBCKeeper.SetRouter(ibcRouter) + + // ... +} +``` diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/03-apps/_category_.json b/docs/versioned_docs/version-v9.0.x/01-ibc/03-apps/_category_.json new file mode 100644 index 00000000000..4561a95b84c --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/03-apps/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Applications", + "position": 3, + "link": null +} \ No newline at end of file diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/03-apps/images/packet_flow.png b/docs/versioned_docs/version-v9.0.x/01-ibc/03-apps/images/packet_flow.png new file mode 100644 index 00000000000..db2d1d314b8 Binary files /dev/null and b/docs/versioned_docs/version-v9.0.x/01-ibc/03-apps/images/packet_flow.png differ diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/04-middleware/01-overview.md b/docs/versioned_docs/version-v9.0.x/01-ibc/04-middleware/01-overview.md new file mode 100644 index 00000000000..24a27689755 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/04-middleware/01-overview.md @@ -0,0 +1,55 @@ +--- +title: IBC middleware +sidebar_label: IBC middleware +sidebar_position: 1 +slug: /ibc/middleware/overview +--- + +# IBC middleware + +:::note Synopsis +Learn how to write your own custom middleware to wrap an IBC application, and understand how to hook different middleware to IBC base applications to form different IBC application stacks +::: + +This documentation serves as a guide for middleware developers who want to write their own middleware and for chain developers who want to use IBC middleware on their chains. + +After going through the overview they can consult respectively: + +- [documentation on developing custom middleware](02-develop.md) +- [documentation on integrating middleware into a stack on a chain](03-integration.md) + +:::note + +## Pre-requisite readings + +- [IBC Overview](../01-overview.md) +- [IBC Integration](../02-integration.md) +- [IBC Application Developer Guide](../03-apps/01-apps.md) + +::: + +## Why middleware? + +IBC applications are designed to be self-contained modules that implement their own application-specific logic through a set of interfaces with the core IBC handlers. These core IBC handlers, in turn, are designed to enforce the correctness properties of IBC (transport, authentication, ordering) while delegating all application-specific handling to the IBC application modules. **However, there are cases where some functionality may be desired by many applications, yet not appropriate to place in core IBC.** + +Middleware allows developers to define the extensions as separate modules that can wrap over the base application. This middleware can thus perform its own custom logic, and pass data into the application so that it may run its logic without being aware of the middleware's existence. This allows both the application and the middleware to implement its own isolated logic while still being able to run as part of a single packet flow. + +## Definitions + +`Middleware`: A self-contained module that sits between core IBC and an underlying IBC application during packet execution. All messages between core IBC and underlying application must flow through middleware, which may perform its own custom logic. + +`Underlying Application`: An underlying application is the application that is directly connected to the middleware in question. This underlying application may itself be middleware that is chained to a base application. + +`Base Application`: A base application is an IBC application that does not contain any middleware. It may be nested by 0 or multiple middleware to form an application stack. + +`Application Stack (or stack)`: A stack is the complete set of application logic (middleware(s) + base application) that gets connected to core IBC. A stack may be just a base application, or it may be a series of middlewares that nest a base application. + +The diagram below gives an overview of a middleware stack consisting of two middleware (one stateless, the other stateful). + +![middleware-stack.png](./images/middleware-stack.png) + +Keep in mind that: + +- **The order of the middleware matters** (more on how to correctly define your stack in the code will follow in the [integration section](03-integration.md)). +- Depending on the type of message, it will either be passed on from the base application up the middleware stack to core IBC or down the stack in the reverse situation (handshake and packet callbacks). +- IBC middleware will wrap over an underlying IBC application and sits between core IBC and the application. It has complete control in modifying any message coming from IBC to the application, and any message coming from the application to core IBC. **Middleware must be completely trusted by chain developers who wish to integrate them**, as this gives them complete flexibility in modifying the application(s) they wrap. diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/04-middleware/02-develop.md b/docs/versioned_docs/version-v9.0.x/01-ibc/04-middleware/02-develop.md new file mode 100644 index 00000000000..2f5742ede31 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/04-middleware/02-develop.md @@ -0,0 +1,464 @@ +--- +title: Create a custom IBC middleware +sidebar_label: Create a custom IBC middleware +sidebar_position: 2 +slug: /ibc/middleware/develop +--- + + +# Create a custom IBC middleware + +IBC middleware will wrap over an underlying IBC application (a base application or downstream middleware) and sits between core IBC and the base application. + +The interfaces a middleware must implement are found [here](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/05-port/types/module.go). + +```go +// Middleware implements the ICS26 Module interface +type Middleware interface { + IBCModule // middleware has access to an underlying application which may be wrapped by more middleware + ICS4Wrapper // middleware has access to ICS4Wrapper which may be core IBC Channel Handler or a higher-level middleware that wraps this middleware. +} +``` + +An `IBCMiddleware` struct implementing the `Middleware` interface, can be defined with its constructor as follows: + +```go +// @ x/module_name/ibc_middleware.go + +// IBCMiddleware implements the ICS26 callbacks and ICS4Wrapper for the fee middleware given the +// fee keeper and the underlying application. +type IBCMiddleware struct { + app porttypes.IBCModule + keeper keeper.Keeper +} + +// NewIBCMiddleware creates a new IBCMiddleware given the keeper and underlying application +func NewIBCMiddleware(app porttypes.IBCModule, k keeper.Keeper) IBCMiddleware { + return IBCMiddleware{ + app: app, + keeper: k, + } +} +``` + +## Implement `IBCModule` interface + +`IBCMiddleware` is a struct that implements the [ICS-26 `IBCModule` interface (`porttypes.IBCModule`)](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/05-port/types/module.go#L14-L107). It is recommended to separate these callbacks into a separate file `ibc_middleware.go`. + +> Note how this is analogous to implementing the same interfaces for IBC applications that act as base applications. + +As will be mentioned in the [integration section](03-integration.md), this struct should be different than the struct that implements `AppModule` in case the middleware maintains its own internal state and processes separate SDK messages. + +The middleware must have access to the underlying application, and be called before it during all ICS-26 callbacks. It may execute custom logic during these callbacks, and then call the underlying application's callback. + +> Middleware **may** choose not to call the underlying application's callback at all. Though these should generally be limited to error cases. + +The `IBCModule` interface consists of the channel handshake callbacks and packet callbacks. Most of the custom logic will be performed in the packet callbacks, in the case of the channel handshake callbacks, introducing the middleware requires consideration to the version negotiation. + +### Channel handshake callbacks + +#### Version negotiation + +In the case where the IBC middleware expects to speak to a compatible IBC middleware on the counterparty chain, they must use the channel handshake to negotiate the middleware version without interfering in the version negotiation of the underlying application. + +Middleware accomplishes this by formatting the version in a JSON-encoded string containing the middleware version and the application version. The application version may as well be a JSON-encoded string, possibly including further middleware and app versions, if the application stack consists of multiple milddlewares wrapping a base application. The format of the version is specified in ICS-30 as the following: + +```json +{ + "": "", + "app_version": "" +} +``` + +The `` key in the JSON struct should be replaced by the actual name of the key for the corresponding middleware (e.g. `fee_version`). + +During the handshake callbacks, the middleware can unmarshal the version string and retrieve the middleware and application versions. It can do its negotiation logic on ``, and pass the `` to the underlying application. + +> **NOTE**: Middleware that does not need to negotiate with a counterparty middleware on the remote stack will not implement the version unmarshalling and negotiation, and will simply perform its own custom logic on the callbacks without relying on the counterparty behaving similarly. + +#### `OnChanOpenInit` + +```go +func (im IBCMiddleware) OnChanOpenInit( + ctx sdk.Context, + order channeltypes.Order, + connectionHops []string, + portID string, + channelID string, + counterparty channeltypes.Counterparty, + version string, +) (string, error) { + if version != "" { + // try to unmarshal JSON-encoded version string and pass + // the app-specific version to app callback. + // otherwise, pass version directly to app callback. + metadata, err := Unmarshal(version) + if err != nil { + // Since it is valid for fee version to not be specified, + // the above middleware version may be for another middleware. + // Pass the entire version string onto the underlying application. + return im.app.OnChanOpenInit( + ctx, + order, + connectionHops, + portID, + channelID, + counterparty, + version, + ) + } + else { + metadata = { + // set middleware version to default value + MiddlewareVersion: defaultMiddlewareVersion, + // allow application to return its default version + AppVersion: "", + } + } + } + + doCustomLogic() + + // if the version string is empty, OnChanOpenInit is expected to return + // a default version string representing the version(s) it supports + appVersion, err := im.app.OnChanOpenInit( + ctx, + order, + connectionHops, + portID, + channelID, + counterparty, + metadata.AppVersion, // note we only pass app version here + ) + if err != nil { + return "", err + } + + version := constructVersion(metadata.MiddlewareVersion, appVersion) + + return version, nil +} +``` + +See [here](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/apps/29-fee/ibc_middleware.go#L36-L83) an example implementation of this callback for the ICS-29 Fee Middleware module. + +#### `OnChanOpenTry` + +```go +func (im IBCMiddleware) OnChanOpenTry( + ctx sdk.Context, + order channeltypes.Order, + connectionHops []string, + portID, + channelID string, + counterparty channeltypes.Counterparty, + counterpartyVersion string, +) (string, error) { + // try to unmarshal JSON-encoded version string and pass + // the app-specific version to app callback. + // otherwise, pass version directly to app callback. + cpMetadata, err := Unmarshal(counterpartyVersion) + if err != nil { + return app.OnChanOpenTry( + ctx, + order, + connectionHops, + portID, + channelID, + counterparty, + counterpartyVersion, + ) + } + + doCustomLogic() + + // Call the underlying application's OnChanOpenTry callback. + // The try callback must select the final app-specific version string and return it. + appVersion, err := app.OnChanOpenTry( + ctx, + order, + connectionHops, + portID, + channelID, + counterparty, + cpMetadata.AppVersion, // note we only pass counterparty app version here + ) + if err != nil { + return "", err + } + + // negotiate final middleware version + middlewareVersion := negotiateMiddlewareVersion(cpMetadata.MiddlewareVersion) + version := constructVersion(middlewareVersion, appVersion) + + return version, nil +} +``` + +See [here](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/apps/29-fee/ibc_middleware.go#L88-L125) an example implementation of this callback for the ICS-29 Fee Middleware module. + +#### `OnChanOpenAck` + +```go +func (im IBCMiddleware) OnChanOpenAck( + ctx sdk.Context, + portID, + channelID string, + counterpartyChannelID string, + counterpartyVersion string, +) error { + // try to unmarshal JSON-encoded version string and pass + // the app-specific version to app callback. + // otherwise, pass version directly to app callback. + cpMetadata, err = UnmarshalJSON(counterpartyVersion) + if err != nil { + return app.OnChanOpenAck(ctx, portID, channelID, counterpartyChannelID, counterpartyVersion) + } + + if !isCompatible(cpMetadata.MiddlewareVersion) { + return error + } + doCustomLogic() + + // call the underlying application's OnChanOpenTry callback + return app.OnChanOpenAck(ctx, portID, channelID, counterpartyChannelID, cpMetadata.AppVersion) +} +``` + +See [here](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/apps/29-fee/ibc_middleware.go#L128-L153)) an example implementation of this callback for the ICS-29 Fee Middleware module. + +#### `OnChanOpenConfirm` + +```go +func OnChanOpenConfirm( + ctx sdk.Context, + portID, + channelID string, +) error { + doCustomLogic() + + return app.OnChanOpenConfirm(ctx, portID, channelID) +} +``` + +See [here](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/apps/29-fee/ibc_middleware.go#L156-L163) an example implementation of this callback for the ICS-29 Fee Middleware module. + +#### `OnChanCloseInit` + +```go +func OnChanCloseInit( + ctx sdk.Context, + portID, + channelID string, +) error { + doCustomLogic() + + return app.OnChanCloseInit(ctx, portID, channelID) +} +``` + +See [here](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/apps/29-fee/ibc_middleware.go#L166-L188) an example implementation of this callback for the ICS-29 Fee Middleware module. + +#### `OnChanCloseConfirm` + +```go +func OnChanCloseConfirm( + ctx sdk.Context, + portID, + channelID string, +) error { + doCustomLogic() + + return app.OnChanCloseConfirm(ctx, portID, channelID) +} +``` + +See [here](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/apps/29-fee/ibc_middleware.go#L191-L213) an example implementation of this callback for the ICS-29 Fee Middleware module. + +### Packet callbacks + +The packet callbacks just like the handshake callbacks wrap the application's packet callbacks. The packet callbacks are where the middleware performs most of its custom logic. The middleware may read the packet flow data and perform some additional packet handling, or it may modify the incoming data before it reaches the underlying application. This enables a wide degree of usecases, as a simple base application like token-transfer can be transformed for a variety of usecases by combining it with custom middleware. + +#### `OnRecvPacket` + +```go +func (im IBCMiddleware) OnRecvPacket( + ctx sdk.Context, + packet channeltypes.Packet, + relayer sdk.AccAddress, +) ibcexported.Acknowledgement { + doCustomLogic(packet) + + ack := app.OnRecvPacket(ctx, packet, relayer) + + doCustomLogic(ack) // middleware may modify outgoing ack + + return ack +} +``` + +See [here](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/apps/29-fee/ibc_middleware.go#L217-L238) an example implementation of this callback for the ICS-29 Fee Middleware module. + +#### `OnAcknowledgementPacket` + +```go +func (im IBCMiddleware) OnAcknowledgementPacket( + ctx sdk.Context, + packet channeltypes.Packet, + acknowledgement []byte, + relayer sdk.AccAddress, +) error { + doCustomLogic(packet, ack) + + return app.OnAcknowledgementPacket(ctx, packet, ack, relayer) +} +``` + +See [here](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/apps/29-fee/ibc_middleware.go#L242-L293) an example implementation of this callback for the ICS-29 Fee Middleware module. + +#### `OnTimeoutPacket` + +```go +func (im IBCMiddleware) OnTimeoutPacket( + ctx sdk.Context, + packet channeltypes.Packet, + relayer sdk.AccAddress, +) error { + doCustomLogic(packet) + + return app.OnTimeoutPacket(ctx, packet, relayer) +} +``` + +See [here](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/apps/29-fee/ibc_middleware.go#L297-L335) an example implementation of this callback for the ICS-29 Fee Middleware module. + +## ICS-04 wrappers + +Middleware must also wrap ICS-04 so that any communication from the application to the `channelKeeper` goes through the middleware first. Similar to the packet callbacks, the middleware may modify outgoing acknowledgements and packets in any way it wishes. + +To ensure optimal generalisability, the `ICS4Wrapper` abstraction serves to abstract away whether a middleware is the topmost middleware (and thus directly calling into the ICS-04 `channelKeeper`) or itself being wrapped by another middleware. + +Remember that middleware can be stateful or stateless. When defining the stateful middleware's keeper, the `ics4Wrapper` field is included. Then the appropriate keeper can be passed when instantiating the middleware's keeper in `app.go` + +```go +type Keeper struct { + storeKey storetypes.StoreKey + cdc codec.BinaryCodec + + ics4Wrapper porttypes.ICS4Wrapper + channelKeeper types.ChannelKeeper + portKeeper types.PortKeeper + ... +} +``` + +For stateless middleware, the `ics4Wrapper` can be passed on directly without having to instantiate a keeper struct for the middleware. + +[The interface](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/05-port/types/module.go#L110-L133) looks as follows: + +```go +// This is implemented by ICS4 and all middleware that are wrapping base application. +// The base application will call `sendPacket` or `writeAcknowledgement` of the middleware directly above them +// which will call the next middleware until it reaches the core IBC handler. +type ICS4Wrapper interface { + SendPacket( + ctx sdk.Context, + sourcePort string, + sourceChannel string, + timeoutHeight clienttypes.Height, + timeoutTimestamp uint64, + data []byte, + ) (sequence uint64, err error) + + WriteAcknowledgement( + ctx sdk.Context, + packet exported.PacketI, + ack exported.Acknowledgement, + ) error + + GetAppVersion( + ctx sdk.Context, + portID, + channelID string, + ) (string, bool) +} +``` + +:warning: In the following paragraphs, the methods are presented in pseudo code which has been kept general, not stating whether the middleware is stateful or stateless. Remember that when the middleware is stateful, `ics4Wrapper` can be accessed through the keeper. + +Check out the references provided for an actual implementation to clarify, where the `ics4Wrapper` methods in `ibc_middleware.go` simply call the equivalent keeper methods where the actual logic resides. + +### `SendPacket` + +```go +func SendPacket( + ctx sdk.Context, + sourcePort string, + sourceChannel string, + timeoutHeight clienttypes.Height, + timeoutTimestamp uint64, + appData []byte, +) (uint64, error) { + // middleware may modify data + data = doCustomLogic(appData) + + return ics4Wrapper.SendPacket( + ctx, + sourcePort, + sourceChannel, + timeoutHeight, + timeoutTimestamp, + data, + ) +} +``` + +See [here](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/apps/29-fee/keeper/relay.go#L17-L27) an example implementation of this function for the ICS-29 Fee Middleware module. + +### `WriteAcknowledgement` + +```go +// only called for async acks +func WriteAcknowledgement( + ctx sdk.Context, + packet exported.PacketI, + ack exported.Acknowledgement, +) error { + // middleware may modify acknowledgement + ack_bytes = doCustomLogic(ack) + + return ics4Wrapper.WriteAcknowledgement(packet, ack_bytes) +} +``` + +See [here](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/apps/29-fee/keeper/relay.go#L31-L55) an example implementation of this function for the ICS-29 Fee Middleware module. + +### `GetAppVersion` + +```go +// middleware must return the underlying application version +func GetAppVersion( + ctx sdk.Context, + portID, + channelID string, +) (string, bool) { + version, found := ics4Wrapper.GetAppVersion(ctx, portID, channelID) + if !found { + return "", false + } + + if !MiddlewareEnabled { + return version, true + } + + // unwrap channel version + metadata, err := Unmarshal(version) + if err != nil { + panic(fmt.Errof("unable to unmarshal version: %w", err)) + } + + return metadata.AppVersion, true +} +``` + +See [here](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/apps/29-fee/keeper/relay.go#L58-L74) an example implementation of this function for the ICS-29 Fee Middleware module. diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/04-middleware/03-integration.md b/docs/versioned_docs/version-v9.0.x/01-ibc/04-middleware/03-integration.md new file mode 100644 index 00000000000..f049555e544 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/04-middleware/03-integration.md @@ -0,0 +1,74 @@ +--- +title: Integrating IBC middleware into a chain +sidebar_label: Integrating IBC middleware into a chain +sidebar_position: 3 +slug: /ibc/middleware/integration +--- + + +# Integrating IBC middleware into a chain + +Learn how to integrate IBC middleware(s) with a base application to your chain. The following document only applies for Cosmos SDK chains. + +If the middleware is maintaining its own state and/or processing SDK messages, then it should create and register its SDK module with the module manager in `app.go`. + +All middleware must be connected to the IBC router and wrap over an underlying base IBC application. An IBC application may be wrapped by many layers of middleware, only the top layer middleware should be hooked to the IBC router, with all underlying middlewares and application getting wrapped by it. + +The order of middleware **matters**, function calls from IBC to the application travel from top-level middleware to the bottom middleware and then to the application. Function calls from the application to IBC goes through the bottom middleware in order to the top middleware and then to core IBC handlers. Thus the same set of middleware put in different orders may produce different effects. + +## Example integration + +```go +// app.go pseudocode + +// middleware 1 and middleware 3 are stateful middleware, +// perhaps implementing separate sdk.Msg and Handlers +mw1Keeper := mw1.NewKeeper(storeKey1, ..., ics4Wrapper: channelKeeper, ...) // in stack 1 & 3 +// middleware 2 is stateless +mw3Keeper1 := mw3.NewKeeper(storeKey3,..., ics4Wrapper: mw1Keeper, ...) // in stack 1 +mw3Keeper2 := mw3.NewKeeper(storeKey3,..., ics4Wrapper: channelKeeper, ...) // in stack 2 + +// Only create App Module **once** and register in app module +// if the module maintains independent state and/or processes sdk.Msgs +app.moduleManager = module.NewManager( + ... + mw1.NewAppModule(mw1Keeper), + mw3.NewAppModule(mw3Keeper1), + mw3.NewAppModule(mw3Keeper2), + transfer.NewAppModule(transferKeeper), + custom.NewAppModule(customKeeper) +) + +scopedKeeperTransfer := capabilityKeeper.NewScopedKeeper("transfer") +scopedKeeperCustom1 := capabilityKeeper.NewScopedKeeper("custom1") +scopedKeeperCustom2 := capabilityKeeper.NewScopedKeeper("custom2") + +// NOTE: IBC Modules may be initialized any number of times provided they use a separate +// scopedKeeper and underlying port. + +customKeeper1 := custom.NewKeeper(..., scopedKeeperCustom1, ...) +customKeeper2 := custom.NewKeeper(..., scopedKeeperCustom2, ...) + +// initialize base IBC applications +// if you want to create two different stacks with the same base application, +// they must be given different scopedKeepers and assigned different ports. +transferIBCModule := transfer.NewIBCModule(transferKeeper) +customIBCModule1 := custom.NewIBCModule(customKeeper1, "portCustom1") +customIBCModule2 := custom.NewIBCModule(customKeeper2, "portCustom2") + +// create IBC stacks by combining middleware with base application +// NOTE: since middleware2 is stateless it does not require a Keeper +// stack 1 contains mw1 -> mw3 -> transfer +stack1 := mw1.NewIBCMiddleware(mw3.NewIBCMiddleware(transferIBCModule, mw3Keeper1), mw1Keeper) +// stack 2 contains mw3 -> mw2 -> custom1 +stack2 := mw3.NewIBCMiddleware(mw2.NewIBCMiddleware(customIBCModule1), mw3Keeper2) +// stack 3 contains mw2 -> mw1 -> custom2 +stack3 := mw2.NewIBCMiddleware(mw1.NewIBCMiddleware(customIBCModule2, mw1Keeper)) + +// associate each stack with the moduleName provided by the underlying scopedKeeper +ibcRouter := porttypes.NewRouter() +ibcRouter.AddRoute("transfer", stack1) +ibcRouter.AddRoute("custom1", stack2) +ibcRouter.AddRoute("custom2", stack3) +app.IBCKeeper.SetRouter(ibcRouter) +``` diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/04-middleware/_category_.json b/docs/versioned_docs/version-v9.0.x/01-ibc/04-middleware/_category_.json new file mode 100644 index 00000000000..6596fe16c13 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/04-middleware/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Middleware", + "position": 4, + "link": null +} \ No newline at end of file diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/04-middleware/images/middleware-stack.png b/docs/versioned_docs/version-v9.0.x/01-ibc/04-middleware/images/middleware-stack.png new file mode 100644 index 00000000000..1d54f808170 Binary files /dev/null and b/docs/versioned_docs/version-v9.0.x/01-ibc/04-middleware/images/middleware-stack.png differ diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/05-upgrades/00-intro.md b/docs/versioned_docs/version-v9.0.x/01-ibc/05-upgrades/00-intro.md new file mode 100644 index 00000000000..61711d35f01 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/05-upgrades/00-intro.md @@ -0,0 +1,15 @@ +--- +title: Upgrading IBC Chains Overview +sidebar_label: Overview +sidebar_position: 0 +slug: /ibc/upgrades/intro +--- + +# Upgrading IBC Chains Overview + +This directory contains information on how to upgrade an IBC chain without breaking counterparty clients and connections. + +IBC-connected chains must be able to upgrade without breaking connections to other chains. Otherwise there would be a massive disincentive towards upgrading and disrupting high-value IBC connections, thus preventing chains in the IBC ecosystem from evolving and improving. Many chain upgrades may be irrelevant to IBC, however some upgrades could potentially break counterparty clients if not handled correctly. Thus, any IBC chain that wishes to perform a IBC-client-breaking upgrade must perform an IBC upgrade in order to allow counterparty clients to securely upgrade to the new light client. + +1. The [quick-guide](./01-quick-guide.md) describes how IBC-connected chains can perform client-breaking upgrades and how relayers can securely upgrade counterparty clients using the SDK. +2. The [developer-guide](./02-developer-guide.md) is a guide for developers intending to develop IBC client implementations with upgrade functionality. diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/05-upgrades/01-quick-guide.md b/docs/versioned_docs/version-v9.0.x/01-ibc/05-upgrades/01-quick-guide.md new file mode 100644 index 00000000000..a1a0b766e60 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/05-upgrades/01-quick-guide.md @@ -0,0 +1,60 @@ +--- +title: How to Upgrade IBC Chains and their Clients +sidebar_label: How to Upgrade IBC Chains and their Clients +sidebar_position: 1 +slug: /ibc/upgrades/quick-guide +--- + + +# How to Upgrade IBC Chains and their Clients + +:::note Synopsis +Learn how to upgrade your chain and counterparty clients. +::: + +The information in this doc for upgrading chains is relevant to SDK chains. However, the guide for counterparty clients is relevant to any Tendermint client that enables upgrades. + +## IBC Client Breaking Upgrades + +IBC-connected chains must perform an IBC upgrade if their upgrade will break counterparty IBC clients. The current IBC protocol supports upgrading tendermint chains for a specific subset of IBC-client-breaking upgrades. Here is the exhaustive list of IBC client-breaking upgrades and whether the IBC protocol currently supports such upgrades. + +IBC currently does **NOT** support unplanned upgrades. All of the following upgrades must be planned and committed to in advance by the upgrading chain, in order for counterparty clients to maintain their connections securely. + +Note: Since upgrades are only implemented for Tendermint clients, this doc only discusses upgrades on Tendermint chains that would break counterparty IBC Tendermint Clients. + +1. Changing the Chain-ID: **Supported** +2. Changing the UnbondingPeriod: **Partially Supported**, chains may increase the unbonding period with no issues. However, decreasing the unbonding period may irreversibly break some counterparty clients. Thus, it is **not recommended** that chains reduce the unbonding period. +3. Changing the height (resetting to 0): **Supported**, so long as chains remember to increment the revision number in their chain-id. +4. Changing the ProofSpecs: **Supported**, this should be changed if the proof structure needed to verify IBC proofs is changed across the upgrade. Ex: Switching from an IAVL store, to a SimpleTree Store +5. Changing the UpgradePath: **Supported**, this might involve changing the key under which upgraded clients and consensus states are stored in the upgrade store, or even migrating the upgrade store itself. +6. Migrating the IBC store: **Unsupported**, as the IBC store location is negotiated by the connection. +7. Upgrading to a backwards compatible version of IBC: Supported +8. Upgrading to a non-backwards compatible version of IBC: **Unsupported**, as IBC version is negotiated on connection handshake. +9. Changing the Tendermint LightClient algorithm: **Partially Supported**. Changes to the light client algorithm that do not change the ClientState or ConsensusState struct may be supported, provided that the counterparty is also upgraded to support the new light client algorithm. Changes that require updating the ClientState and ConsensusState structs themselves are theoretically possible by providing a path to translate an older ClientState struct into the new ClientState struct; however this is not currently implemented. + +## Step-by-Step Upgrade Process for SDK chains + +If the IBC-connected chain is conducting an upgrade that will break counterparty clients, it must ensure that the upgrade is first supported by IBC using the list above and then execute the upgrade process described below in order to prevent counterparty clients from breaking. + +1. Create a governance proposal with the [`MsgIBCSoftwareUpgrade`](https://buf.build/cosmos/ibc/docs/main:ibc.core.client.v1#ibc.core.client.v1.MsgIBCSoftwareUpgrade) message which contains an `UpgradePlan` and a new IBC `ClientState` in the `UpgradedClientState` field. Note that the `UpgradePlan` must specify an upgrade height **only** (no upgrade time), and the `ClientState` should only include the fields common to all valid clients (chain-specified parameters) and zero out any client-customizable fields (such as `TrustingPeriod`). +2. Vote on and pass the governance proposal. + +Upon passing the governance proposal, the upgrade module will commit the `UpgradedClient` under the key: `upgrade/UpgradedIBCState/{upgradeHeight}/upgradedClient`. On the block right before the upgrade height, the upgrade module will also commit an initial consensus state for the next chain under the key: `upgrade/UpgradedIBCState/{upgradeHeight}/upgradedConsState`. + +Once the chain reaches the upgrade height and halts, a relayer can upgrade the counterparty clients to the last block of the old chain. They can then submit the proofs of the `UpgradedClient` and `UpgradedConsensusState` against this last block and upgrade the counterparty client. + +## Step-by-Step Upgrade Process for Relayers Upgrading Counterparty Clients + +Once the upgrading chain has committed to upgrading, relayers must wait till the chain halts at the upgrade height before upgrading counterparty clients. This is because chains may reschedule or cancel upgrade plans before they occur. Thus, relayers must wait till the chain reaches the upgrade height and halts before they can be sure the upgrade will take place. + +Thus, the upgrade process for relayers trying to upgrade the counterparty clients is as follows: + +1. Wait for the upgrading chain to reach the upgrade height and halt +2. Query a full node for the proofs of `UpgradedClient` and `UpgradedConsensusState` at the last height of the old chain. +3. Update the counterparty client to the last height of the old chain using the `UpdateClient` msg. +4. Submit an `UpgradeClient` msg to the counterparty chain with the `UpgradedClient`, `UpgradedConsensusState` and their respective proofs. +5. Submit an `UpdateClient` msg to the counterparty chain with a header from the new upgraded chain. + +The Tendermint client on the counterparty chain will verify that the upgrading chain did indeed commit to the upgraded client and upgraded consensus state at the upgrade height (since the upgrade height is included in the key). If the proofs are verified against the upgrade height, then the client will upgrade to the new client while retaining all of its client-customized fields. Thus, it will retain its old TrustingPeriod, TrustLevel, MaxClockDrift, etc; while adopting the new chain-specified fields such as UnbondingPeriod, ChainId, UpgradePath, etc. Note, this can lead to an invalid client since the old client-chosen fields may no longer be valid given the new chain-chosen fields. Upgrading chains should try to avoid these situations by not altering parameters that can break old clients. For an example, see the UnbondingPeriod example in the supported upgrades section. + +The upgraded consensus state will serve purely as a basis of trust for future `UpdateClientMsgs` and will not contain a consensus root to perform proof verification against. Thus, relayers must submit an `UpdateClientMsg` with a header from the new chain so that the connection can be used for proof verification again. diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/05-upgrades/02-developer-guide.md b/docs/versioned_docs/version-v9.0.x/01-ibc/05-upgrades/02-developer-guide.md new file mode 100644 index 00000000000..c21b23e03e3 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/05-upgrades/02-developer-guide.md @@ -0,0 +1,14 @@ +--- +title: IBC Client Developer Guide to Upgrades +sidebar_label: IBC Client Developer Guide to Upgrades +sidebar_position: 2 +slug: /ibc/upgrades/developer-guide +--- + +# IBC Client Developer Guide to Upgrades + +:::note Synopsis +Learn how to implement upgrade functionality for your custom IBC client. +::: + +Please see the section [Handling upgrades](../../03-light-clients/01-developer-guide/06-upgrades.md) from the light client developer guide for more information. diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/05-upgrades/03-genesis-restart.md b/docs/versioned_docs/version-v9.0.x/01-ibc/05-upgrades/03-genesis-restart.md new file mode 100644 index 00000000000..3a15141d41d --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/05-upgrades/03-genesis-restart.md @@ -0,0 +1,52 @@ +--- +title: Genesis Restart Upgrades +sidebar_label: Genesis Restart Upgrades +sidebar_position: 3 +slug: /ibc/upgrades/genesis-restart +--- + + +# Genesis Restart Upgrades + +:::note Synopsis +Learn how to upgrade your chain and counterparty clients using genesis restarts. +::: + +**NOTE**: Regular genesis restarts are currently unsupported by relayers! + +## IBC Client Breaking Upgrades + +IBC client breaking upgrades are possible using genesis restarts. +It is highly recommended to use the in-place migrations instead of a genesis restart. +Genesis restarts should be used sparingly and as backup plans. + +Genesis restarts still require the usage of an IBC upgrade proposal in order to correctly upgrade counterparty clients. + +### Step-by-Step Upgrade Process for SDK Chains + +If the IBC-connected chain is conducting an upgrade that will break counterparty clients, it must ensure that the upgrade is first supported by IBC using the [IBC Client Breaking Upgrade List](./01-quick-guide.md#ibc-client-breaking-upgrades) and then execute the upgrade process described below in order to prevent counterparty clients from breaking. + +1. Create a governance proposal with the [`MsgIBCSoftwareUpgrade`](https://buf.build/cosmos/ibc/docs/main:ibc.core.client.v1#ibc.core.client.v1.MsgIBCSoftwareUpgrade) which contains an `UpgradePlan` and a new IBC `ClientState` in the `UpgradedClientState` field. Note that the `UpgradePlan` must specify an upgrade height **only** (no upgrade time), and the `ClientState` should only include the fields common to all valid clients and zero out any client-customizable fields (such as `TrustingPeriod`). +2. Vote on and pass the governance proposal. +3. Halt the node after successful upgrade. +4. Export the genesis file. +5. Swap to the new binary. +6. Run migrations on the genesis file. +7. Remove the upgrade plan set by the governance proposal from the genesis file. This may be done by migrations. +8. Change desired chain-specific fields (chain id, unbonding period, etc). This may be done by migrations. +8. Reset the node's data. +9. Start the chain. + +Upon passing the governance proposal, the upgrade module will commit the `UpgradedClient` under the key: `upgrade/UpgradedIBCState/{upgradeHeight}/upgradedClient`. On the block right before the upgrade height, the upgrade module will also commit an initial consensus state for the next chain under the key: `upgrade/UpgradedIBCState/{upgradeHeight}/upgradedConsState`. + +Once the chain reaches the upgrade height and halts, a relayer can upgrade the counterparty clients to the last block of the old chain. They can then submit the proofs of the `UpgradedClient` and `UpgradedConsensusState` against this last block and upgrade the counterparty client. + +### Step-by-Step Upgrade Process for Relayers Upgrading Counterparty Clients + +These steps are identical to the regular [IBC client breaking upgrade process](./01-quick-guide.md#step-by-step-upgrade-process-for-relayers-upgrading-counterparty-clients). + +## Non-IBC Client Breaking Upgrades + +While ibc-go supports genesis restarts which do not break IBC clients, relayers do not support this upgrade path. +Here is a tracking issue on [Hermes](https://github.com/informalsystems/ibc-rs/issues/1152). +Please do not attempt a regular genesis restarts unless you have a tool to update counterparty clients correctly. diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/05-upgrades/_category_.json b/docs/versioned_docs/version-v9.0.x/01-ibc/05-upgrades/_category_.json new file mode 100644 index 00000000000..46eea8924ec --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/05-upgrades/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Upgrades", + "position": 5, + "link": { "type": "doc", "id": "intro" } +} diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/06-channel-upgrades.md b/docs/versioned_docs/version-v9.0.x/01-ibc/06-channel-upgrades.md new file mode 100644 index 00000000000..05e640c4214 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/06-channel-upgrades.md @@ -0,0 +1,413 @@ +--- +title: Channel Upgrades +sidebar_label: Channel Upgrades +sidebar_position: 6 +slug: /ibc/channel-upgrades +--- + +# Channel Upgrades + +:::note Synopsis +Learn how to upgrade existing IBC channels. +::: + +Channel upgradability is an IBC-level protocol that allows chains to leverage new application and channel features without having to create new channels or perform a network-wide upgrade. + +Prior to this feature, developers who wanted to update an application module or add a middleware to their application flow would need to create a new channel in order to use the updated application feature/middleware, resulting in a loss of the accumulated state/liquidity, token fungibility (as the channel ID is encoded in the IBC denom), and any other larger network effects of losing usage of the existing channel from relayers monitoring, etc. + +With channel upgradability, applications will be able to implement features such as but not limited to: potentially adding [denom metadata to tokens](https://github.com/cosmos/ibc/discussions/719), or utilizing the [fee middleware](https://github.com/cosmos/ibc/tree/main/spec/app/ics-029-fee-payment), all while maintaining the channels on which they currently operate. + +This document outlines the channel upgrade feature, and the multiple steps used in the upgrade process. + +## Channel Upgrade Handshake + +Channel upgrades will be achieved using a handshake process that is designed to be similar to the standard connection/channel opening handshake. + +```go +type Channel struct { + // current state of the channel end + State State `protobuf:"varint,1,opt,name=state,proto3,enum=ibc.core.channel.v1.State" json:"state,omitempty"` + // whether the channel is ordered or unordered + Ordering Order `protobuf:"varint,2,opt,name=ordering,proto3,enum=ibc.core.channel.v1.Order" json:"ordering,omitempty"` + // counterparty channel end + Counterparty Counterparty `protobuf:"bytes,3,opt,name=counterparty,proto3" json:"counterparty"` + // list of connection identifiers, in order, along which packets sent on + // this channel will travel + ConnectionHops []string `protobuf:"bytes,4,rep,name=connection_hops,json=connectionHops,proto3" json:"connection_hops,omitempty"` + // opaque channel version, which is agreed upon during the handshake + Version string `protobuf:"bytes,5,opt,name=version,proto3" json:"version,omitempty"` + // upgrade sequence indicates the latest upgrade attempt performed by this channel + // the value of 0 indicates the channel has never been upgraded + UpgradeSequence uint64 `protobuf:"varint,6,opt,name=upgrade_sequence,json=upgradeSequence,proto3" json:"upgrade_sequence,omitempty"` +} +``` + +The version, connection hops, and channel ordering are fields in this channel struct which can be changed. For example, the fee middleware can be added to an application module by updating the version string [shown here](https://github.com/cosmos/ibc-go/blob/v8.1.0/modules/apps/29-fee/types/metadata.pb.go#L29). However, although connection hops can change in a channel upgrade, both sides must still be each other's counterparty. This is enforced by the upgrade protocol and upgrade attempts which try to alter an expected counterparty will fail. + +On a high level, successful handshake process for channel upgrades works as follows: + +1. The chain initiating the upgrade process will propose an upgrade. +2. If the counterparty agrees with the proposal, it will block sends and begin flushing any in-flight packets on its channel end. This flushing process will be covered in more detail below. +3. Upon successful completion of the previous step, the initiating chain will also block packet sends and begin flushing any in-flight packets on its channel end. +4. Once both channel ends have completed flushing packets within the upgrade timeout window, both channel ends can be opened and upgraded to the new channel fields. + +Each handshake step will be documented below in greater detail. + +## Initializing a Channel Upgrade + +A channel upgrade is initialised by submitting the `MsgChannelUpgradeInit` message, which can be submitted only by the chain itself upon governance authorization. It is possible to upgrade the channel ordering, the channel connection hops, and the channel version, which can be found in the `UpgradeFields`. + +```go +type MsgChannelUpgradeInit struct { + PortId string + ChannelId string + Fields UpgradeFields + Signer string +} +``` + +As part of the handling of the `MsgChannelUpgradeInit` message, the application's `OnChanUpgradeInit` callback will be triggered as well. + +After this message is handled successfully, the channel's upgrade sequence will be incremented. This upgrade sequence will serve as a nonce for the upgrade process to provide replay protection. + +:::warning +Initiating an upgrade in the same block as opening a channel may potentially prevent the counterparty channel from also opening. +::: + +### Governance gating on `ChanUpgradeInit` + +The message signer for `MsgChannelUpgradeInit` must be the address which has been designated as the `authority` of the `IBCKeeper`. If this proposal passes, the counterparty's channel will upgrade by default. + +If chains want to initiate the upgrade of many channels, they will need to submit a governance proposal with multiple `MsgChannelUpgradeInit` messages, one for each channel they would like to upgrade, again with message signer as the designated `authority` of the `IBCKeeper`. The `upgrade-channels` CLI command can be used to submit a proposal that initiates the upgrade of multiple channels; see section [Upgrading channels with the CLI](#upgrading-channels-with-the-cli) below for more information. + +## Channel State and Packet Flushing + +`FLUSHING` and `FLUSHCOMPLETE` are additional channel states which have been added to enable the upgrade feature. + +These states may consist of: + +```go +const ( + // Default State + UNINITIALIZED State = 0 + // A channel has just started the opening handshake. + INIT State = 1 + // A channel has acknowledged the handshake step on the counterparty chain. + TRYOPEN State = 2 + // A channel has completed the handshake. Open channels are + // ready to send and receive packets. + OPEN State = 3 + // A channel has been closed and can no longer be used to send or receive + // packets. + CLOSED State = 4 + // A channel has just accepted the upgrade handshake attempt and is flushing in-flight packets. + FLUSHING State = 5 + // A channel has just completed flushing any in-flight packets. + FLUSHCOMPLETE State = 6 +) +``` + +These are found in `State` on the `Channel` struct: + +```go +type Channel struct { + // current state of the channel end + State State `protobuf:"varint,1,opt,name=state,proto3,enum=ibc.core.channel.v1.State" json:"state,omitempty"` + // whether the channel is ordered or unordered + Ordering Order `protobuf:"varint,2,opt,name=ordering,proto3,enum=ibc.core.channel.v1.Order" json:"ordering,omitempty"` + // counterparty channel end + Counterparty Counterparty `protobuf:"bytes,3,opt,name=counterparty,proto3" json:"counterparty"` + // list of connection identifiers, in order, along which packets sent on + // this channel will travel + ConnectionHops []string `protobuf:"bytes,4,rep,name=connection_hops,json=connectionHops,proto3" json:"connection_hops,omitempty"` + // opaque channel version, which is agreed upon during the handshake + Version string `protobuf:"bytes,5,opt,name=version,proto3" json:"version,omitempty"` + // upgrade sequence indicates the latest upgrade attempt performed by this channel + // the value of 0 indicates the channel has never been upgraded + UpgradeSequence uint64 `protobuf:"varint,6,opt,name=upgrade_sequence,json=upgradeSequence,proto3" json:"upgrade_sequence,omitempty"` +} +``` + +`startFlushing` is the specific method which is called in `ChanUpgradeTry` and `ChanUpgradeAck` to update the state on the channel end. This will set the timeout on the upgrade and update the channel state to `FLUSHING` which will block the upgrade from continuing until all in-flight packets have been flushed. + +This will also set the upgrade timeout for the counterparty (i.e. the timeout before which the counterparty chain must move from `FLUSHING` to `FLUSHCOMPLETE`; if it doesn't then the chain will cancel the upgrade and write an error receipt). The timeout is a relative time duration in nanoseconds that can be changed with `MsgUpdateParams` and by default is 10 minutes. + +The state will change to `FLUSHCOMPLETE` once there are no in-flight packets left and the channel end is ready to move to `OPEN`. This flush state will also have an impact on how a channel upgrade can be cancelled, as detailed below. + +All other parameters will remain the same during the upgrade handshake until the upgrade handshake completes. When the channel is reset to `OPEN` on a successful upgrade handshake, the relevant fields on the channel end will be switched over to the `UpgradeFields` specified in the upgrade. + +:::note + +When transitioning a channel from UNORDERED to ORDERED, new packet sends from the channel end which upgrades first will be incapable of being timed out until the counterparty has finished upgrading. + +::: + +:::warning + +Due to the addition of new channel states, packets can still be received and processed in both `FLUSHING` and `FLUSHCOMPLETE` states. +Packets can also be acknowledged in the `FLUSHING` state. Acknowledging will **not** be possible when the channel is in the `FLUSHCOMPLETE` state, since all packets sent from that channel end have been flushed. +Application developers should consider these new states when implementing application logic that relies on the channel state. +It is still only possible to send packets when the channel is in the `OPEN` state, but sending is disallowed when the channel enters `FLUSHING` and `FLUSHCOMPLETE`. When the channel reopens, sending will be possible again. + +::: + +## Cancelling a Channel Upgrade + +Channel upgrade cancellation is performed by submitting a `MsgChannelUpgradeCancel` message. + +It is possible for the authority to cancel an in-progress channel upgrade if the following are true: + +- The signer is the authority +- The channel state has not reached FLUSHCOMPLETE +- If the channel state has reached FLUSHCOMPLETE, an existence proof of an `ErrorReceipt` on the counterparty chain is provided at our upgrade sequence or greater + +It is possible for a relayer to cancel an in-progress channel upgrade if the following are true: + +- An existence proof of an `ErrorReceipt` on the counterparty chain is provided at our upgrade sequence or greater + +> Note: if the signer is the authority, e.g. the `gov` address, no `ErrorReceipt` or proof is required if the current channel state is not in FLUSHCOMPLETE. +> These can be left empty in the `MsgChannelUpgradeCancel` message in that case. + +Upon cancelling a channel upgrade, an `ErrorReceipt` will be written with the channel's current upgrade sequence, and +the channel will move back to `OPEN` state keeping its original parameters. + +It will then be possible to re-initiate an upgrade by sending a `MsgChannelOpenInit` message. + +:::warning + +Performing sequentially an upgrade cancellation, upgrade initialization, and another upgrade cancellation in a single block while the counterparty is in `FLUSHCOMPLETE` will lead to corrupted state. +The counterparty will be unable to cancel its upgrade attempt and will require a manual migration. +When the counterparty is in `FLUSHCOMPLETE`, it requires a proof that the counterparty cancelled its current upgrade attempt. +When this cancellation is succeeded by an initialization and cancellation in the same block, it results in the proof of cancellation existing only for the next upgrade attempt, not the current. + +::: + +## Timing Out a Channel Upgrade + +Timing out an outstanding channel upgrade may be necessary during the flushing packet stage of the channel upgrade process. As stated above, with `ChanUpgradeTry` or `ChanUpgradeAck`, the channel state has been changed from `OPEN` to `FLUSHING`, so no new packets will be allowed to be sent over this channel while flushing. If upgrades cannot be performed in a timely manner (due to unforeseen flushing issues), upgrade timeouts allow the channel to avoid blocking packet sends indefinitely. If flushing exceeds the time limit set in the `UpgradeTimeout` channel `Params`, the upgrade process will need to be timed out to abort the upgrade attempt and resume normal channel processing. + +Channel upgrades require setting a valid timeout value in the channel `Params` before submitting a `MsgChannelUpgradeTry` or `MsgChannelUpgradeAck` message (by default, 10 minutes): + +```go +type Params struct { + UpgradeTimeout Timeout +} +``` + +A valid Timeout contains either one or both of a timestamp and block height (sequence). + +```go +type Timeout struct { + // block height after which the packet or upgrade times out + Height types.Height + // block timestamp (in nanoseconds) after which the packet or upgrade times out + Timestamp uint64 +} +``` + +This timeout will then be set as a field on the `Upgrade` struct itself when flushing is started. + +```go +type Upgrade struct { + Fields UpgradeFields + Timeout Timeout + NextSequenceSend uint64 +} +``` + +If the timeout has been exceeded during flushing, a chain can then submit the `MsgChannelUpgradeTimeout` to timeout the channel upgrade process: + +```go +type MsgChannelUpgradeTimeout struct { + PortId string + ChannelId string + CounterpartyChannel Channel + ProofChannel []byte + ProofHeight types.Height + Signer string +} +``` + +An `ErrorReceipt` will be written with the channel's current upgrade sequence, and the channel will move back to `OPEN` state keeping its original parameters. + +Note that timing out a channel upgrade will end the upgrade process, and a new `MsgChannelUpgradeInit` will have to be submitted via governance in order to restart the upgrade process. + +## Pruning Acknowledgements + +Acknowledgements can be pruned by broadcasting the `MsgPruneAcknowledgements` message. + +> Note: It is only possible to prune acknowledgements after a channel has been upgraded, so pruning will fail +> if the channel has not yet been upgraded. + +```protobuf +// MsgPruneAcknowledgements defines the request type for the PruneAcknowledgements rpc. +message MsgPruneAcknowledgements { + option (cosmos.msg.v1.signer) = "signer"; + option (gogoproto.goproto_getters) = false; + + string port_id = 1; + string channel_id = 2; + uint64 limit = 3; + string signer = 4; +} +``` + +The `port_id` and `channel_id` specify the port and channel to act on, and the `limit` specifies the upper bound for the number +of acknowledgements and packet receipts to prune. + +### CLI Usage + +Acknowledgements can be pruned via the cli with the `prune-acknowledgements` command. + +```bash +simd tx ibc channel prune-acknowledgements [port] [channel] [limit] +``` + +## IBC App Recommendations + +IBC application callbacks should be primarily used to validate data fields and do compatibility checks. Application developers +should be aware that callbacks will be invoked before any core ibc state changes are written. + +`OnChanUpgradeInit` should validate the proposed version, order, and connection hops, and should return the application version to upgrade to. + +`OnChanUpgradeTry` should validate the proposed version (provided by the counterparty), order, and connection hops. The desired upgrade version should be returned. + +`OnChanUpgradeAck` should validate the version proposed by the counterparty. + +`OnChanUpgradeOpen` should perform any logic associated with changing of the channel fields. + +> IBC applications should not attempt to process any packet data under the new conditions until after `OnChanUpgradeOpen` +> has been executed, as up until this point it is still possible for the upgrade handshake to fail and for the channel +> to remain in the pre-upgraded state. + +## Upgrade an existing transfer application stack to use 29-fee middleware + +### Wire up the transfer stack and middleware in app.go + +In app.go, the existing transfer stack must be wrapped with the fee middleware. + +```golang + +import ( + // ... + ibcfee "github.com/cosmos/ibc-go/v9/modules/apps/29-fee" + ibctransferkeeper "github.com/cosmos/ibc-go/v9/modules/apps/transfer/keeper" + transfer "github.com/cosmos/ibc-go/v9/modules/apps/transfer" + porttypes "github.com/cosmos/ibc-go/v9/modules/core/05-port/types" + // ... +) + +type App struct { + // ... + TransferKeeper ibctransferkeeper.Keeper + IBCFeeKeeper ibcfeekeeper.Keeper + // .. +} + +// ... + +app.IBCFeeKeeper = ibcfeekeeper.NewKeeper( + appCodec, keys[ibcfeetypes.StoreKey], + app.IBCKeeper.ChannelKeeper, // may be replaced with IBC middleware + app.IBCKeeper.ChannelKeeper, + app.IBCKeeper.PortKeeper, app.AccountKeeper, app.BankKeeper, +) + +// Create Transfer Keeper and pass IBCFeeKeeper as expected Channel and PortKeeper +// since fee middleware will wrap the IBCKeeper for underlying application. +app.TransferKeeper = ibctransferkeeper.NewKeeper( + appCodec, keys[ibctransfertypes.StoreKey], app.GetSubspace(ibctransfertypes.ModuleName), + app.IBCFeeKeeper, // ISC4 Wrapper: fee IBC middleware + app.IBCKeeper.ChannelKeeper, app.IBCKeeper.PortKeeper, + app.AccountKeeper, app.BankKeeper, scopedTransferKeeper, + authtypes.NewModuleAddress(govtypes.ModuleName).String(), +) + + +ibcRouter := porttypes.NewRouter() + +// create IBC module from bottom to top of stack +var transferStack porttypes.IBCModule +transferStack = transfer.NewIBCModule(app.TransferKeeper) +transferStack = ibcfee.NewIBCMiddleware(transferStack, app.IBCFeeKeeper) + +// Add transfer stack to IBC Router +ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferStack) +``` + +### Submit a governance proposal to execute a MsgChannelUpgradeInit message + +> This process can be performed with the new CLI that has been added +> outlined [here](#upgrading-channels-with-the-cli). + +Only the configured authority for the ibc module is able to initiate a channel upgrade by submitting a `MsgChannelUpgradeInit` message. + +Execute a governance proposal specifying the relevant fields to perform a channel upgrade. + +Update the following json sample, and copy the contents into `proposal.json`. + +```json +{ + "title": "Channel upgrade init", + "summary": "Channel upgrade init", + "messages": [ + { + "@type": "/ibc.core.channel.v1.MsgChannelUpgradeInit", + "signer": "", + "port_id": "transfer", + "channel_id": "channel-...", + "fields": { + "ordering": "ORDER_UNORDERED", + "connection_hops": ["connection-0"], + "version": "{\"fee_version\":\"ics29-1\",\"app_version\":\"ics20-1\"}" + } + } + ], + "metadata": "", + "deposit": "10stake" +} +``` + +> Note: ensure the correct fields.version is specified. This is the new version that the channels will be upgraded to. + +### Submit the proposal + +```shell +simd tx submit-proposal proposal.json --from +``` + +## Upgrading channels with the CLI + +A new cli has been added which enables either + - submitting a governance proposal which contains a `MsgChannelUpgradeInit` for every channel to be upgraded. + - generating a `proposal.json` file which contains the proposal contents to be edited/submitted at a later date. + +The following example, would submit a governance proposal with the specified deposit, title and summary which would +contain a `MsgChannelUpgradeInit` for all `OPEN` channels whose port matches the regular expression `transfer`. + +> Note: by adding the `--json` flag, the command would instead output the contents of the proposal which could be +> stored in a `proposal.json` file to be edited and submitted at a later date. + +```bash +simd tx ibc channel upgrade-channels "{\"fee_version\":\"ics29-1\",\"app_version\":\"ics20-1\"}" \ + --deposit "10stake" \ + --title "Channel Upgrades Governance Proposal" \ + --summary "Upgrade all transfer channels to be fee enabled" \ + --port-pattern "transfer" +``` + +It is also possible to explicitly list a comma separated string of channel IDs. It is important to note that the +regular expression matching specified by `--port-pattern` (which defaults to `transfer`) still applies. + +For example the following command would generate the contents of a `proposal.json` file which would attempt to upgrade +channels with a port ID of `transfer` and a channelID of `channel-0`, `channel-1` or `channel-2`. + +```bash +simd tx ibc channel upgrade-channels "{\"fee_version\":\"ics29-1\",\"app_version\":\"ics20-1\"}" \ + --deposit "10stake" \ + --title "Channel Upgrades Governance Proposal" \ + --summary "Upgrade all transfer channels to be fee enabled" \ + --port-pattern "transfer" \ + --channel-ids "channel-0,channel-1,channel-2" \ + --json +``` diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/07-proposals.md b/docs/versioned_docs/version-v9.0.x/01-ibc/07-proposals.md new file mode 100644 index 00000000000..9a78f0b2aec --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/07-proposals.md @@ -0,0 +1,118 @@ +--- +title: Governance Proposals +sidebar_label: Governance Proposals +sidebar_position: 7 +slug: /ibc/proposals +--- + +# Governance Proposals + +In uncommon situations, a highly valued client may become frozen due to uncontrollable +circumstances. A highly valued client might have hundreds of channels being actively used. +Some of those channels might have a significant amount of locked tokens used for ICS 20. + +If the one third of the validator set of the chain the client represents decides to collude, +they can sign off on two valid but conflicting headers each signed by the other one third +of the honest validator set. The light client can now be updated with two valid, but conflicting +headers at the same height. The light client cannot know which header is trustworthy and therefore +evidence of such misbehaviour is likely to be submitted resulting in a frozen light client. + +Frozen light clients cannot be updated under any circumstance except via a governance proposal. +Since a quorum of validators can sign arbitrary state roots which may not be valid executions +of the state machine, a governance proposal has been added to ease the complexity of unfreezing +or updating clients which have become "stuck". Without this mechanism, validator sets would need +to construct a state root to unfreeze the client. Unfreezing clients, re-enables all of the channels +built upon that client. This may result in recovery of otherwise lost funds. + +Tendermint light clients may become expired if the trusting period has passed since their +last update. This may occur if relayers stop submitting headers to update the clients. + +An unplanned upgrade by the counterparty chain may also result in expired clients. If the counterparty +chain undergoes an unplanned upgrade, there may be no commitment to that upgrade signed by the validator +set before the chain ID changes. In this situation, the validator set of the last valid update for the +light client is never expected to produce another valid header since the chain ID has changed, which will +ultimately lead the on-chain light client to become expired. + +In the case that a highly valued light client is frozen, expired, or rendered non-updateable, a +governance proposal may be submitted to update this client, known as the subject client. The +proposal includes the client identifier for the subject and the client identifier for a substitute +client. Light client implementations may implement custom updating logic, but in most cases, +the subject will be updated to the latest consensus state of the substitute client, if the proposal passes. +The substitute client is used as a "stand in" while the subject is on trial. It is best practice to create +a substitute client *after* the subject has become frozen to avoid the substitute from also becoming frozen. +An active substitute client allows headers to be submitted during the voting period to prevent accidental expiry +once the proposal passes. + +*note* two of these parameters: `AllowUpdateAfterExpiry` and `AllowUpdateAfterMisbehavior` have been deprecated, and will both be set to `false` upon upgrades even if they were previously set to `true`. These parameters will no longer play a role in restricting a client upgrade. Please see ADR026 for more details. + +# How to recover an expired client with a governance proposal + +See also the relevant documentation: [ADR-026, IBC client recovery mechanisms](/architecture/adr-026-ibc-client-recovery-mechanisms) + +> **Who is this information for?** +> Although technically anyone can submit the governance proposal to recover an expired client, often it will be **relayer operators** (at least coordinating the submission). + +## Preconditions + +- There exists an active client (with a known client identifier) for the same counterparty chain as the expired client. +- The governance deposit. + +## Steps + +### Step 1 + +Check if the client is attached to the expected `chain_id`. For example, for an expired Tendermint client representing the Akash chain the client state looks like this on querying the client state: + +```text +{ + client_id: 07-tendermint-146 + client_state: + '@type': /ibc.lightclients.tendermint.v1.ClientState + allow_update_after_expiry: true + allow_update_after_misbehaviour: true + chain_id: akashnet-2 +} +``` + +The client is attached to the expected Akash `chain_id`. Note that although the parameters (`allow_update_after_expiry` and `allow_update_after_misbehaviour`) exist to signal intent, these parameters have been deprecated and will not enforce any checks on the revival of client. See ADR-026 for more context on this deprecation. + +### Step 2 + +Anyone can submit the governance proposal to recover the client by executing the following via CLI. +If the chain is on an ibc-go version older than v8, please see the [relevant documentation](https://ibc.cosmos.network/v7/ibc/proposals). + +- From ibc-go v8 onwards + + ```shell + tx gov submit-proposal [path-to-proposal-json] + ``` + + where `proposal.json` contains: + + ```json + { + "messages": [ + { + "@type": "/ibc.core.client.v1.MsgRecoverClient", + "subject_client_id": "", + "substitute_client_id": "", + "signer": "" + } + ], + "metadata": "", + "deposit": "10stake" + "title": "My proposal", + "summary": "A short summary of my proposal", + "expedited": false + } + ``` + +The `` identifier is the proposed client to be updated. This client must be either frozen or expired. + +The `` represents a substitute client. It carries all the state for the client which may be updated. It must have identical client and chain parameters to the client which may be updated (except for latest height, frozen height, and chain ID). It should be continually updated during the voting period. + +After this, all that remains is deciding who funds the governance deposit and ensuring the governance proposal passes. If it does, the client on trial will be updated to the latest state of the substitute. + +## Important considerations + +Please note that if the counterparty client is also expired, that client will also need to update. This process updates only one client. diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/08-relayer.md b/docs/versioned_docs/version-v9.0.x/01-ibc/08-relayer.md new file mode 100644 index 00000000000..100d68fc77a --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/08-relayer.md @@ -0,0 +1,53 @@ +--- +title: Relayer +sidebar_label: Relayer +sidebar_position: 8 +slug: /ibc/relayer +--- + +# Relayer + +:::note + +## Pre-requisite readings + +- [IBC Overview](01-overview.md) +- [Events](https://github.com/cosmos/cosmos-sdk/blob/main/docs/learn/advanced/08-events.md) + +::: + +## Events + +Events are emitted for every transaction processed by the base application to indicate the execution +of some logic clients may want to be aware of. This is extremely useful when relaying IBC packets. +Any message that uses IBC will emit events for the corresponding TAO logic executed as defined in +the [IBC events document](/events/events). + +In the SDK, it can be assumed that for every message there is an event emitted with the type `message`, +attribute key `action`, and an attribute value representing the type of message sent +(`channel_open_init` would be the attribute value for `MsgChannelOpenInit`). If a relayer queries +for transaction events, it can split message events using this event Type/Attribute Key pair. + +The Event Type `message` with the Attribute Key `module` may be emitted multiple times for a single +message due to application callbacks. It can be assumed that any TAO logic executed will result in +a module event emission with the attribute value `ibc_` (02-client emits `ibc_client`). + +### Subscribing with Tendermint + +Calling the Tendermint RPC method `Subscribe` via [Tendermint's Websocket](https://docs.tendermint.com/main/rpc/) will return events using +Tendermint's internal representation of them. Instead of receiving back a list of events as they +were emitted, Tendermint will return the type `map[string][]string` which maps a string in the +form `.` to `attribute_value`. This causes extraction of the event +ordering to be non-trivial, but still possible. + +A relayer should use the `message.action` key to extract the number of messages in the transaction +and the type of IBC transactions sent. For every IBC transaction within the string array for +`message.action`, the necessary information should be extracted from the other event fields. If +`send_packet` appears at index 2 in the value for `message.action`, a relayer will need to use the +value at index 2 of the key `send_packet.packet_sequence`. This process should be repeated for each +piece of information needed to relay a packet. + +## Example Implementations + +- [Golang Relayer](https://github.com/cosmos/relayer) +- [Hermes](https://github.com/informalsystems/ibc-rs/tree/master/crates/relayer) diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/09-proto-docs.md b/docs/versioned_docs/version-v9.0.x/01-ibc/09-proto-docs.md new file mode 100644 index 00000000000..1666d3b7dd2 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/09-proto-docs.md @@ -0,0 +1,11 @@ +--- +title: Protobuf Documentation +sidebar_label: Protobuf Documentation +sidebar_position: 9 +slug: /ibc/proto-docs +--- + + +# Protobuf documentation + +See [ibc-go Buf Protobuf documentation](https://buf.build/cosmos/ibc/docs/main). diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/10-roadmap.md b/docs/versioned_docs/version-v9.0.x/01-ibc/10-roadmap.md new file mode 100644 index 00000000000..88651908455 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/10-roadmap.md @@ -0,0 +1,50 @@ +--- +title: Roadmap +sidebar_label: Roadmap +sidebar_position: 10 +slug: /ibc/roadmap +--- + +# Roadmap ibc-go + +*Latest update: June 7th, 2024* + +This document endeavours to inform the wider IBC community about plans and priorities for work on ibc-go by the team at Interchain GmbH. It is intended to broadly inform all users of ibc-go, including developers and operators of IBC, relayer, chain and wallet applications. + +This roadmap should be read as a high-level guide, rather than a commitment to schedules and deliverables. The degree of specificity is inversely proportional to the timeline. We will update this document periodically to reflect the status and plans. For the latest expected release timelines, please check [here](https://github.com/cosmos/ibc-go/wiki/Release-timeline). + +## v9.0.0 + +### ICS20 v2 + +The transfer application will be updated to add support for [transferring multiple tokens in the same packet](https://github.com/cosmos/ibc/pull/1020) and support for [atomically route tokens series of paths with a single packet](https://github.com/cosmos/ibc/pull/1090). + +## v10.0.0 + +### ICA v2 + +This new version of ICS27 will address many of [the pain points with the current design](https://github.com/cosmos/ibc-go/pull/6281), including multiplexing all communication between controller and host through a single channel (instead of each interchain account on the host being associated to a different channel, as it is now). + +### Multipacket atomicity + +We will refactor the 05-port router to enable atomic sending of multiple packets belonging to different applications. + +--- + +And potentially later on... + +#### Multihop channels + +Multihop channels specify a way to route messages across a path of IBC enabled blockchains utilizing multiple pre-existing IBC connections. The current IBC protocol defines messaging in a point-to-point paradigm which allows message passing between two directly connected IBC chains, but as more IBC enabled chains come into existence there becomes a need to relay IBC packets across chains because IBC connections may not exist between the two chains wishing to exchange messages. IBC connections may not exist for a variety of reasons which could include economic inviability since connections require client state to be continuously exchanged between connection ends which carries a cost. Please see the [ICS 33 spec](https://github.com/cosmos/ibc/blob/main/spec/core/ics-033-multi-hop/README.md) for more information. + +--- + +This roadmap is also available as a [project board](https://github.com/orgs/cosmos/projects/7/views/25). + +For the latest expected release timelines, please check [here](https://github.com/cosmos/ibc-go/wiki/Release-timeline). + +For the latest information on the progress of the work or the decisions made that might influence the roadmap, please follow the [Announcements](https://github.com/cosmos/ibc-go/discussions/categories/announcements) category in the Discussions tab of the repository. + +--- + +**Note**: release version numbers may be subject to change. diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/11-troubleshooting.md b/docs/versioned_docs/version-v9.0.x/01-ibc/11-troubleshooting.md new file mode 100644 index 00000000000..4080f3b449b --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/11-troubleshooting.md @@ -0,0 +1,15 @@ +--- +title: Troubleshooting +sidebar_label: Troubleshooting +sidebar_position: 11 +slug: /ibc/troubleshooting +--- + +# Troubleshooting + +## Unauthorized client states + +If it is being reported that a client state is unauthorized, this is due to the client type not being present +in the [`AllowedClients`](https://github.com/cosmos/ibc-go/blob/v6.0.0/modules/core/02-client/types/client.pb.go#L345) array. + +Unless the client type is present in this array or the `AllowAllClients` wildcard (`"*"`) is used, all usage of clients of this type will be prevented. diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/13-best-practices.md b/docs/versioned_docs/version-v9.0.x/01-ibc/13-best-practices.md new file mode 100644 index 00000000000..47e10d36ac2 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/13-best-practices.md @@ -0,0 +1,25 @@ +--- +title: Best Practices +sidebar_label: Best Practices +sidebar_position: 13 +slug: /ibc/best-practices +--- + +# Best practices + +## Identifying legitimate channels + +Identifying which channel to use can be difficult as it requires verifying information about the chains you want to connect to. +Channels are based on a light client. A chain can be uniquely identified by its chain ID, validator set pairing. It is unsafe to rely only on the chain ID. +Any user can create a client with any chain ID, but only the chain with correct validator set and chain ID can produce headers which would update that client. + +Which channel to use is based on social consensus. The desired channel should have the following properties: + +- based on a valid client (can only be updated by the chain it connects to) +- has sizable activity +- the underlying client is active + +To verify if a client is valid. You will need to obtain a header from the chain you want to connect to. This can be done by running a full node for that chain or relying on a trusted rpc address. +Then you should query the light client you want to verify and obtain its latest consensus state. All consensus state fields must match the header queried for at same height as the consensus state (root, timestamp, next validator set hash). + +Explorers and wallets are highly encouraged to follow this practice. It is unsafe to algorithmically add new channels without following this process. diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/14-permissioning.md b/docs/versioned_docs/version-v9.0.x/01-ibc/14-permissioning.md new file mode 100644 index 00000000000..c96ecf3cc26 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/14-permissioning.md @@ -0,0 +1,32 @@ +--- +title: Permissioning +sidebar_label: Permissioning +sidebar_position: 14 +slug: /ibc/permissioning +--- + +# Permissioning + +IBC is designed at its base level to be a permissionless protocol. This does not mean that chains cannot add in permissioning on top of IBC. In ibc-go this can be accomplished by implementing and wiring an ante-decorator that checks if the IBC message is signed by a permissioned authority. If the signer address check passes, the tx can go through; otherwise it is rejected from the mempool. + +The antehandler runs before message-processing so it acts as a customizable filter that can reject messages before they get included in the block. The Cosmos SDK allows developers to write ante-decorators that can be stacked with others to add multiple independent customizable filters that run in sequence. Thus, chain developers that want to permission IBC messages are advised to implement their own custom permissioned IBC ante-decorator to add to the standard ante-decorator stack. + +## Best practices + +`MsgCreateClient`: permissioning the client creation is the most important for permissioned IBC. This will prevent malicious relayers from creating clients to fake chains. If a chain wants to control which chains are connected to it directly over IBC, the best way to do this is by controlling which clients get created. The permissioned authority can create clients only of counterparties that the chain approves of. The permissioned authority can be the governance account, however `MsgCreateClient` contains a consensus state that can be expired by the time governance passes the proposal to execute the message. Thus, if the voting period is longer than the unbonding period of the counterparty, it is advised to use a permissioned authority that can immediately execute the transaction (e.g. a trusted multisig). + +`MsgConnectionOpenInit`: permissioning this message will give the chain control over the connections that are opened and also will control which connection identifier is associated with which counterparty. + +`MsgConnectionOpenTry`: permissioning this message through a permissioned address check is ill-advised because it will prevent relayers from easily completing the handshake that was initialized on the counterparty. However, if the chain does want strict control of exactly which connections are opened, it can permission this message. Be aware, if two chains with strict permissions try to open a connection it may take much longer than expected. + +`MsgChannelOpenInit`: permissioning this message will give the chain control over the channels that are opened and also will control which channel identifier is associated with which counterparty. + +`MsgChannelOpenTry`: permissioning this message through a permissioned address check is ill-advised because it will prevent relayers from easily completing the handshake that was initialized on the counterparty. However, if the chain does want strict control of exactly which channels are opened, it can permission this message. Be aware, if two chains with strict permissions try to open a channel it may take much longer than expected. + +It is not advised to permission any other message from ibc-go. Permissionless relayers should still be allowed to complete handshakes that were authorized by permissioned parties, and to relay user packets on channels that were also authorized by permissioned parties. This provides the maximum liveness provided by a permissionless relayer network with the safety guarantees provided by permissioned client, connection, and channel creation. + +## Genesis setup + +Chains that are starting up from genesis have the option of initializing authorized clients, connections and channels from genesis. This allows chains to automatically connect to desired chains with a desired identifier. + +Note: The chain must be launched soon after the genesis file is created so that the client creation does not occur with an expired consensus state. The connections and channels must also simply have their `INIT` messages executed so that relayers can complete the rest of the handshake. diff --git a/docs/versioned_docs/version-v9.0.x/01-ibc/_category_.json b/docs/versioned_docs/version-v9.0.x/01-ibc/_category_.json new file mode 100644 index 00000000000..066f3af93b1 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/01-ibc/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Using IBC-Go", + "position": 1, + "link": null +} \ No newline at end of file diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/01-overview.md b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/01-overview.md new file mode 100644 index 00000000000..d61ac19dbfb --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/01-overview.md @@ -0,0 +1,181 @@ +--- +title: Overview +sidebar_label: Overview +sidebar_position: 1 +slug: /apps/transfer/overview +--- + +# Overview + +:::note Synopsis +Learn about what the token Transfer module is +::: + +## What is the Transfer module? + +Transfer is the Cosmos SDK implementation of the [ICS-20](https://github.com/cosmos/ibc/tree/master/spec/app/ics-020-fungible-token-transfer) protocol, which enables cross-chain fungible token transfers. + +## Concepts + +### Acknowledgements + +ICS20 uses the recommended acknowledgement format as specified by [ICS 04](https://github.com/cosmos/ibc/tree/master/spec/core/ics-004-channel-and-packet-semantics#acknowledgement-envelope). + +A successful receive of a transfer packet will result in a Result Acknowledgement being written +with the value `[]byte{byte(1)}` in the `Response` field. + +An unsuccessful receive of a transfer packet will result in an Error Acknowledgement being written +with the error message in the `Response` field. + +### Denomination trace + +The denomination trace corresponds to the information that allows a token to be traced back to its +origin chain. It contains a sequence of port and channel identifiers ordered from the most recent to +the oldest in the timeline of transfers. + +This information is included on the token's base denomination field in the form of a hash to prevent an +unbounded denomination length. For example, the token `transfer/channelToA/uatom` will be displayed +as `ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2`. The human readable denomination +is stored using `x/bank` module's [denom metadata](https://docs.cosmos.network/main/build/modules/bank#denom-metadata) +feature. You may display the human readable denominations by querying balances with the `--resolve-denom` flag, as in: + +```shell +simd query bank balances [address] --resolve-denom +``` + +Each send to any chain other than the one it was previously received from is a movement forwards in +the token's timeline. This causes trace to be added to the token's history and the destination port +and destination channel to be prefixed to the denomination. In these instances the sender chain is +acting as the "source zone". When the token is sent back to the chain it previously received from, the +prefix is removed. This is a backwards movement in the token's timeline and the sender chain is +acting as the "sink zone". + +It is strongly recommended to read the full details of [ADR 001: Coin Source Tracing](/architecture/adr-001-coin-source-tracing) to understand the implications and context of the IBC token representations. + +## UX suggestions for clients + +For clients (wallets, exchanges, applications, block explorers, etc) that want to display the source of the token, it is recommended to use the following alternatives for each of the cases below: + +### Direct connection + +If the denomination trace contains a single identifier prefix pair (as in the example above), then +the easiest way to retrieve the chain and light client identifier is to map the trace information +directly. In summary, this requires querying the channel from the denomination trace identifiers, +and then the counterparty client state using the counterparty port and channel identifiers from the +retrieved channel. + +A general pseudo algorithm would look like the following: + +1. Query the full denomination trace. +2. Query the channel with the `portID/channelID` pair, which corresponds to the first destination of the + token. +3. Query the client state using the identifiers pair. Note that this query will return a `"Not +Found"` response if the current chain is not connected to this channel. +4. Retrieve the client identifier or chain identifier from the client state (eg: on + Tendermint clients) and store it locally. + +Using the gRPC gateway client service the steps above would be, with a given IBC token `ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2` stored on `chainB`: + +1. `GET /ibc/apps/transfer/v1/denom_traces/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2` -> `{"path": "transfer/channelToA", "base_denom": "uatom"}` +2. `GET /ibc/apps/transfer/v1/channels/channelToA/ports/transfer/client_state"` -> `{"client_id": "clientA", "chain-id": "chainA", ...}` +3. `GET /ibc/apps/transfer/v1/channels/channelToA/ports/transfer"` -> `{"channel_id": "channelToA", port_id": "transfer", counterparty: {"channel_id": "channelToB", port_id": "transfer"}, ...}` +4. `GET /ibc/apps/transfer/v1/channels/channelToB/ports/transfer/client_state" -> {"client_id": "clientB", "chain-id": "chainB", ...}` + +Then, the token transfer chain path for the `uatom` denomination would be: `chainA` -> `chainB`. + +### Multiple hops + +The multiple channel hops case applies when the token has passed through multiple chains between the original source and final destination chains. + +The IBC protocol doesn't know the topology of the overall network (i.e connections between chains and identifier names between them). For this reason, in the multiple hops case, a particular chain in the timeline of the individual transfers can't query the chain and client identifiers of the other chains. + +Take for example the following sequence of transfers `A -> B -> C` for an IBC token, with a final prefix path (trace info) of `transfer/channelChainC/transfer/channelChainB`. What the paragraph above means is that even in the case that chain `C` is directly connected to chain `A`, querying the port and channel identifiers that chain `B` uses to connect to chain `A` (eg: `transfer/channelChainA`) can be completely different from the one that chain `C` uses to connect to chain `A` (eg: `transfer/channelToChainA`). + +Thus the proposed solution for clients that the IBC team recommends are the following: + +- **Connect to all chains**: Connecting to all the chains in the timeline would allow clients to + perform the queries outlined in the [direct connection](#direct-connection) section to each + relevant chain. By repeatedly following the port and channel denomination trace transfer timeline, + clients should always be able to find all the relevant identifiers. This comes at the tradeoff + that the client must connect to nodes on each of the chains in order to perform the queries. +- **Relayer as a Service (RaaS)**: A longer term solution is to use/create a relayer service that + could map the denomination trace to the chain path timeline for each token (i.e `origin chain -> +chain #1 -> ... -> chain #(n-1) -> final chain`). These services could provide merkle proofs in + order to allow clients to optionally verify the path timeline correctness for themselves by + running light clients. If the proofs are not verified, they should be considered as trusted third + parties services. Additionally, client would be advised in the future to use RaaS that support the + largest number of connections between chains in the ecosystem. Unfortunately, none of the existing + public relayers (in [Golang](https://github.com/cosmos/relayer) and + [Rust](https://github.com/informalsystems/ibc-rs)), provide this service to clients. + +:::tip +The only viable alternative for clients (at the time of writing) to tokens with multiple connection hops, is to connect to all chains directly and perform relevant queries to each of them in the sequence. +::: + +## Forwarding + +:::info +Token forwarding and unwinding is supported only on ICS20 v2 transfer channels. +::: + +Forwarding allows tokens to be routed to a final destination through multiple (up to 8) intermediary +chains. With forwarding, it's also possible to unwind IBC vouchers to their native chain, and forward +them afterwards to another destination, all with just a single transfer transaction on the sending chain. + +### Forward tokens + +Native tokens or IBC vouchers on any chain can be forwarded through intermediary chains to reach their +final destination. For example, given the topology below, with 3 chains and a transfer channel between +chains A and B and between chains B and C: + +![Light Mode Forwarding](./images/forwarding-3-chains-light.png#gh-light-mode-only)![Dark Mode Forwarding](./images/forwarding-3-chains-dark.png#gh-dark-mode-only) + +Native tokens on chain `A` can be sent to chain `C` through chain `B`. The routing is specified by the +source port ID and channel ID of choice on every intermediary chain. In this example, there is only one +forwarding hop on chain `B` and the port ID, channel ID pair is `transfer`, `channelBToC`. Forwarding of +a multi-denom collections of tokens is also allowed (i.e. forwarding of tokens of different denominations). + +### Unwind tokens + +Taking again as an example the topology from the previous section, we assume that native tokens on chain `A` +have been transferred to chain `C`. The IBC vouchers on chain `C` have the denomination trace +`transfer/channelCtoB/transfer/channelBtoA`, and with forwarding it is possible to submit a transfer message +on chain `C` and automatically unwind the vouchers through chain `B` to chain `A`, so that the tokens recovered +on the origin chain regain their native denomination. In order to execute automatic unwinding, the transfer +module does not require extra user input: the unwind route is encoded in the denomination trace with the +pairs of destination port ID, channel ID that are added on every chain where the tokens are received. + +Please note that unwinding of vouchers is only allowed when vouchers transferred all share the same denomination +trace (signifying coins that all originate from the same source). It is not possible to unwind vouchers of two different +IBC denominations, since they come from different source chains. + +### Unwind tokens and then forward + +Unwinding and forwarding can be used in combination, so that vouchers are first unwound to their origin chain +and then forwarded to a final destination. The same restriction as in the unwinding case applies: only vouchers +of a single IBC denomination can be used. + +## Locked funds + +In some [exceptional cases](/architecture/adr-026-ibc-client-recovery-mechanisms#exceptional-cases), a client state associated with a given channel cannot be updated. This causes that funds from fungible tokens in that channel will be permanently locked and thus can no longer be transferred. + +To mitigate this, a client update governance proposal can be submitted to update the frozen client +with a new valid header. Once the proposal passes the client state will be unfrozen and the funds +from the associated channels will then be unlocked. This mechanism only applies to clients that +allow updates via governance, such as Tendermint clients. + +In addition to this, it's important to mention that a token must be sent back along the exact route +that it took originally in order to return it to its original form on the source chain (eg: the +Cosmos Hub for the `uatom`). Sending a token back to the same chain across a different channel will +**not** move the token back across its timeline. If a channel in the chain history closes before the +token can be sent back across that channel, then the token will not be returnable to its original +form. + +## Security considerations + +For safety, no other module must be capable of minting tokens with the `ibc/` prefix. The IBC +transfer module needs a subset of the denomination space that only it can create tokens in. + +## Channel Closure + +The IBC transfer module does not support channel closure. diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/02-state.md b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/02-state.md new file mode 100644 index 00000000000..916e99b46c3 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/02-state.md @@ -0,0 +1,13 @@ +--- +title: State +sidebar_label: State +sidebar_position: 2 +slug: /apps/transfer/state +--- + +# State + +The IBC transfer application module keeps state of the port to which the module is binded and the denomination trace information as outlined in [ADR 001](/architecture/adr-001-coin-source-tracing). + +- `Port`: `0x01 -> ProtocolBuffer(string)` +- `DenomTrace`: `0x02 | []bytes(traceHash) -> ProtocolBuffer(DenomTrace)` diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/03-state-transitions.md b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/03-state-transitions.md new file mode 100644 index 00000000000..7c73b8da21c --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/03-state-transitions.md @@ -0,0 +1,37 @@ +--- +title: State Transitions +sidebar_label: State Transitions +sidebar_position: 3 +slug: /apps/transfer/state-transitions +--- + +# State transitions + +## Send fungible tokens + +A successful fungible token send has two state transitions depending if the transfer is a movement forward or backwards in the token's timeline: + +1. Sender chain is the source chain, *i.e* a transfer to any chain other than the one it was previously received from is a movement forwards in the token's timeline. This results in the following state transitions: + + - The coins are transferred to an escrow address (i.e locked) on the sender chain. + - The coins are transferred to the receiving chain through IBC TAO logic. + +2. Sender chain is the sink chain, *i.e* the token is sent back to the chain it previously received from. This is a backwards movement in the token's timeline. This results in the following state transitions: + + - The coins (vouchers) are burned on the sender chain. + - The coins are transferred to the receiving chain through IBC TAO logic. + +## Receive fungible tokens + +A successful fungible token receive has two state transitions depending if the transfer is a movement forward or backwards in the token's timeline: + +1. Receiver chain is the source chain. This is a backwards movement in the token's timeline. This results in the following state transitions: + + - The leftmost port and channel identifier pair is removed from the token denomination prefix. + - The tokens are unescrowed and sent to the receiving address. + +2. Receiver chain is the sink chain. This is a movement forwards in the token's timeline. This results in the following state transitions: + + - Token vouchers are minted by prefixing the destination port and channel identifiers to the trace information. + - The receiving chain stores the new trace information in the store (if not set already). + - The vouchers are sent to the receiving address. diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/04-messages.md b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/04-messages.md new file mode 100644 index 00000000000..0118b3e8166 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/04-messages.md @@ -0,0 +1,86 @@ +--- +title: Messages +sidebar_label: Messages +sidebar_position: 4 +slug: /apps/transfer/messages +--- + +# Messages + +## `MsgTransfer` + +A fungible token cross chain transfer is achieved by using the `MsgTransfer`: + +```go +type MsgTransfer struct { + SourcePort string + SourceChannel string + // Deprecated: Use Tokens instead. + Token sdk.Coin + Sender string + Receiver string + TimeoutHeight ibcexported.Height + TimeoutTimestamp uint64 + Memo string + Tokens []sdk.Coin + Forwarding *Forwarding +} + +type Forwarding struct { + Unwind bool + Hops []Hop +} + +type Hop struct { + PortId string + ChannelId string +} +``` + +:::info +Multi-denom token transfers and token forwarding are features supported only on ICS20 v2 transfer channels. +::: + +If `Forwarding` is `nil`, this message is expected to fail if: + +- `SourcePort` is invalid (see [24-host naming requirements](https://github.com/cosmos/ibc/blob/master/spec/core/ics-024-host-requirements/README.md#paths-identifiers-separators). +- `SourceChannel` is invalid (see [24-host naming requirements](https://github.com/cosmos/ibc/blob/master/spec/core/ics-024-host-requirements/README.md#paths-identifiers-separators)). +- `Tokens` must not be empty. +- Each `Coin` in `Tokens` must satisfy the following: + - `Amount` must be positive. + - `Denom` must be a valid IBC denomination, as defined in [ADR 001 - Coin Source Tracing](/architecture/adr-001-coin-source-tracing). +- `Sender` is empty. +- `Receiver` is empty or contains more than 2048 bytes. +- `Memo` contains more than 32768 bytes. +- `TimeoutHeight` and `TimeoutTimestamp` are both zero. + +If `Forwarding` is not `nil`, then to use forwarding you must either set `Unwind` to true or provide a non-empty list of `Hops`. Setting both `Unwind` to true and providing a non-empty list of `Hops` is allowed, but the total number of hops that is formed as a combination of the hops needed to unwind the tokens and the hops to forward them afterwards to the final destination must not exceed 8. When using forwarding, timeout must be specified using only `TimeoutTimestamp` (i.e. `TimeoutHeight` must be zero). Please note that the timeout timestamp must take into account the time that it may take tokens to be forwarded through the intermediary chains. Additionally, please note that the `MsgTransfer` will fail if: + +- `Hops` is not empty, and the number of elements of `Hops` is greater than 8, or either the `PortId` or `ChannelId` of any of the `Hops` is not a valid identifier. +- `Unwind` is true, and either the coins to be transferred have different denomination traces, or `SourcePort` and `SourceChannel` are not empty strings (they must be empty because they are set by the transfer module, since it has access to the denomination trace information and is thus able to know the source port ID, channel ID to use in order to unwind the tokens). If `Unwind` is true, the transfer module expects the tokens in `MsgTransfer` to not be native to the sending chain (i.e. they must be IBC vouchers). + +Please note that the `Token` field is deprecated and users should now use `Tokens` instead. If `Token` is used then `Tokens` must be empty. Similarly, if `Tokens` is used then `Token` should be left empty. This message will send a fungible token to the counterparty chain represented by the counterparty Channel End connected to the Channel End with the identifiers `SourcePort` and `SourceChannel`. + +The denomination provided for transfer should correspond to the same denomination represented on this chain. The prefixes will be added as necessary upon by the receiving chain. + +If the `Amount` is set to the maximum value for a 256-bit unsigned integer (i.e. 2^256 - 1), then the whole balance of the corresponding denomination will be transferred. The helper function `UnboundedSpendLimit` in the `types` package of the `transfer` module provides the sentinel value that can be used. + +### Memo + +The memo field was added to allow applications and users to attach metadata to transfer packets. The field is optional and may be left empty. When it is used to attach metadata for a particular middleware, the memo field should be represented as a json object where different middlewares use different json keys. + +For example, the following memo field is used by the [callbacks middleware](../../04-middleware/02-callbacks/01-overview.md) to attach a source callback to a transfer packet: + +```jsonc +{ + "src_callback": { + "address": "callbackAddressString", + // optional + "gas_limit": "userDefinedGasLimitString", + } +} +``` + +You can find more information about other applications that use the memo field in the [chain registry](https://github.com/cosmos/chain-registry/blob/master/_memo_keys/ICS20_memo_keys.json). + +Please note that the memo field is always meant to be consumed only on the final destination chain. This means that the transfer module will guarantee that the memo field in the intermediary chains is empty. diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/05-events.md b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/05-events.md new file mode 100644 index 00000000000..3c5cf3782ec --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/05-events.md @@ -0,0 +1,57 @@ +--- +title: Events +sidebar_label: Events +sidebar_position: 5 +slug: /apps/transfer/events +--- + +# Events + +## `MsgTransfer` + +| Type | Attribute Key | Attribute Value | +|--------------|-----------------|------------------------| +| ibc_transfer | sender | \{sender\} | +| ibc_transfer | receiver | \{receiver\} | +| ibc_transfer | tokens | \{jsonTokens\} | +| ibc_transfer | memo | \{memo\} | +| ibc_transfer | forwarding_hops | \{jsonForwardingHops\} | +| message | module | transfer | + +## `OnRecvPacket` callback + +| Type | Attribute Key | Attribute Value | +|-----------------------|-----------------|------------------------| +| fungible_token_packet | sender | \{sender\} | +| fungible_token_packet | receiver | \{receiver\} | +| fungible_token_packet | tokens | \{jsonTokens\} | +| fungible_token_packet | memo | \{memo\} | +| fungible_token_packet | forwarding_hops | \{jsonForwardingHops\} | +| fungible_token_packet | success | \{ackSuccess\} | +| fungible_token_packet | error | \{ackError\} | +| denomination | trace_hash | \{hex_hash\} | +| denomination | denom | \{jsonDenom\} | +| message | module | transfer | + +## `OnAcknowledgePacket` callback + +| Type | Attribute Key | Attribute Value | +|-----------------------|-----------------|------------------------| +| fungible_token_packet | sender | \{sender\} | +| fungible_token_packet | receiver | \{receiver\} | +| fungible_token_packet | tokens | \{jsonTokens\} | +| fungible_token_packet | memo | \{memo\} | +| fungible_token_packet | forwarding_hops | \{jsonForwardingHops\} | +| fungible_token_packet | acknowledgement | \{ack.String()\} | +| fungible_token_packet | success / error | \{ack.Response\} | +| message | module | transfer | + +## `OnTimeoutPacket` callback + +| Type | Attribute Key | Attribute Value | +|---------|-----------------|------------------------| +| timeout | refund_receiver | \{receiver\} | +| timeout | refund_tokens | \{jsonTokens\} | +| timeout | memo | \{memo\} | +| timeout | forwarding_hops | \{jsonForwardingHops\} | +| message | module | transfer | diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/06-metrics.md b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/06-metrics.md new file mode 100644 index 00000000000..104e5b4d3bc --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/06-metrics.md @@ -0,0 +1,18 @@ +--- +title: Metrics +sidebar_label: Metrics +sidebar_position: 6 +slug: /apps/transfer/metrics +--- + + +# Metrics + +The IBC transfer application module exposes the following set of [metrics](https://github.com/cosmos/cosmos-sdk/blob/main/docs/learn/advanced/09-telemetry.md). + +| Metric | Description | Unit | Type | +|:--------------------------------|:------------------------------------------------------------------------------------------|:----------------|:--------| +| `tx_msg_ibc_transfer` | The total amount of tokens transferred via IBC in a `MsgTransfer` (source or sink chain) | token | gauge | +| `ibc_transfer_packet_receive` | The total amount of tokens received in a `FungibleTokenPacketData` (source or sink chain) | token | gauge | +| `ibc_transfer_send` | Total number of IBC transfers sent from a chain (source or sink) | transfer | counter | +| `ibc_transfer_receive` | Total number of IBC transfers received to a chain (source or sink) | transfer | counter | diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/07-params.md b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/07-params.md new file mode 100644 index 00000000000..f3aeee45d48 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/07-params.md @@ -0,0 +1,94 @@ +--- +title: Params +sidebar_label: Params +sidebar_position: 7 +slug: /apps/transfer/params +--- + + +# Parameters + +The IBC transfer application module contains the following parameters: + +| Name | Type | Default Value | +| ---------------- | ---- | ------------- | +| `SendEnabled` | bool | `true` | +| `ReceiveEnabled` | bool | `true` | + +The IBC transfer module stores its parameters in its keeper with the prefix of `0x03`. + +## `SendEnabled` + +The `SendEnabled` parameter controls send cross-chain transfer capabilities for all fungible tokens. + +To prevent a single token from being transferred from the chain, set the `SendEnabled` parameter to `true` and then, depending on the Cosmos SDK version, do one of the following: + +- For Cosmos SDK v0.46.x or earlier, set the bank module's [`SendEnabled` parameter](https://github.com/cosmos/cosmos-sdk/blob/release/v0.46.x/x/bank/spec/05_params.md#sendenabled) for the denomination to `false`. +- For Cosmos SDK versions above v0.46.x, set the bank module's `SendEnabled` entry for the denomination to `false` using `MsgSetSendEnabled` as a governance proposal. + +:::warning +Doing so will prevent the token from being transferred between any accounts in the blockchain. +::: + +## `ReceiveEnabled` + +The transfers enabled parameter controls receive cross-chain transfer capabilities for all fungible tokens. + +To prevent a single token from being transferred to the chain, set the `ReceiveEnabled` parameter to `true` and then, depending on the Cosmos SDK version, do one of the following: + +- For Cosmos SDK v0.46.x or earlier, set the bank module's [`SendEnabled` parameter](https://github.com/cosmos/cosmos-sdk/blob/release/v0.46.x/x/bank/spec/05_params.md#sendenabled) for the denomination to `false`. +- For Cosmos SDK versions above v0.46.x, set the bank module's `SendEnabled` entry for the denomination to `false` using `MsgSetSendEnabled` as a governance proposal. + +:::warning +Doing so will prevent the token from being transferred between any accounts in the blockchain. +::: + +## Queries + +Current parameter values can be queried via a query message. + + + +```protobuf +// proto/ibc/applications/transfer/v1/query.proto + +// QueryParamsRequest is the request type for the Query/Params RPC method. +message QueryParamsRequest {} + +// QueryParamsResponse is the response type for the Query/Params RPC method. +message QueryParamsResponse { + // params defines the parameters of the module. + Params params = 1; +} +``` + +To execute the query in `simd`, you use the following command: + +```bash +simd query ibc-transfer params +``` + +## Changing Parameters + +To change the parameter values, you must make a governance proposal that executes the `MsgUpdateParams` message. + + + +```protobuf +// proto/ibc/applications/transfer/v1/tx.proto + +// MsgUpdateParams is the Msg/UpdateParams request type. +message MsgUpdateParams { + // signer address (it may be the address that controls the module, which defaults to x/gov unless overwritten). + string signer = 1; + + // params defines the transfer parameters to update. + // + // NOTE: All parameters must be supplied. + Params params = 2 [(gogoproto.nullable) = false]; +} + +// MsgUpdateParamsResponse defines the response structure for executing a +// MsgUpdateParams message. +message MsgUpdateParamsResponse {} +``` diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/08-authorizations.md b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/08-authorizations.md new file mode 100644 index 00000000000..d9e71fac46f --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/08-authorizations.md @@ -0,0 +1,66 @@ +--- +title: Authorizations +sidebar_label: Authorizations +sidebar_position: 8 +slug: /apps/transfer/authorizations +--- + +# `TransferAuthorization` + +`TransferAuthorization` implements the `Authorization` interface for `ibc.applications.transfer.v1.MsgTransfer`. It allows a granter to grant a grantee the privilege to submit `MsgTransfer` on its behalf. Please see the [Cosmos SDK docs](https://docs.cosmos.network/v0.47/modules/authz) for more details on granting privileges via the `x/authz` module. + +More specifically, the granter allows the grantee to transfer funds that belong to the granter over a specified channel. + +For the specified channel, the granter must be able to specify a spend limit of a specific denomination they wish to allow the grantee to be able to transfer. + +The granter may be able to specify the list of addresses that they allow to receive funds. If empty, then all addresses are allowed. + +It takes: + +- a `SourcePort` and a `SourceChannel` which together comprise the unique transfer channel identifier over which authorized funds can be transferred. +- a `SpendLimit` that specifies the maximum amount of tokens the grantee can transfer. The `SpendLimit` is updated as the tokens are transferred, unless the sentinel value of the maximum value for a 256-bit unsigned integer (i.e. 2^256 - 1) is used for the amount, in which case the `SpendLimit` will not be updated (please be aware that using this sentinel value will grant the grantee the privilege to transfer **all** the tokens of a given denomination available at the granter's account). The helper function `UnboundedSpendLimit` in the `types` package of the `transfer` module provides the sentinel value that can be used. This `SpendLimit` may also be updated to increase or decrease the limit as the granter wishes. +- an `AllowList` list that specifies the list of addresses that are allowed to receive funds. If this list is empty, then all addresses are allowed to receive funds from the `TransferAuthorization`. +- an `AllowedPacketData` list that specifies the list of memo strings that are allowed to be included in the memo field of the packet. If this list is empty, then only an empty memo is allowed (a `memo` field with non-empty content will be denied). If this list includes a single element equal to `"*"`, then any content in `memo` field will be allowed. +- an `AllowedForwarding` list that specifies the combinations of source port ID/channel ID pairs through which the tokens are allowed to be forwarded until final destination. Please note that granters are expected to specify the unwinding route of IBC vouchers if they wish to allow grantees to unwind the vouchers to their native chain (i.e. grantees cannot make use of the `Unwind` flag and must also set the source port ID, channel ID pairs required to unwind the vouchers in the forwarding `Hops` field). + +Setting a `TransferAuthorization` is expected to fail if: + +- the spend limit is nil +- the denomination of the spend limit is an invalid coin type +- the source port ID is invalid +- the source channel ID is invalid +- there are duplicate entries in the `AllowList` +- the `memo` field is not allowed by `AllowedPacketData` +- the forwarding hops do not match any of the combinations specified in `AllowedForwarding` + +Below is the `TransferAuthorization` message: + +```go +func NewTransferAuthorization(allocations ...Allocation) *TransferAuthorization { + return &TransferAuthorization{ + Allocations: allocations, + } +} + +type Allocation struct { + // the port on which the packet will be sent + SourcePort string + // the channel by which the packet will be sent + SourceChannel string + // spend limitation on the channel + SpendLimit sdk.Coins + // allow list of receivers, an empty allow list permits any receiver address + AllowList []string + // allow list of memo strings, an empty list prohibits all memo strings; + // a list only with "*" permits any memo string + AllowedPacketData []string + // Optional list of allowed combinations of source port ID/channel ID pairs + // through which the tokens are allowed to be forwarded until final + // destination + AllowedForwarding []AllowedForwarding +} + +type AllowedForwarding struct { + Hops []Hop +} +``` diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/09-client.md b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/09-client.md new file mode 100644 index 00000000000..3ba88e6dfc1 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/09-client.md @@ -0,0 +1,97 @@ +--- +title: Client +sidebar_label: Client +sidebar_position: 9 +slug: /apps/transfer/client +--- + +# Client + +## CLI + +A user can query and interact with the `transfer` module using the CLI. Use the `--help` flag to discover the available commands: + +### Query + +The `query` commands allow users to query `transfer` state. + +```shell +simd query ibc-transfer --help +``` + +#### Transactions + +The `tx` commands allow users to interact with the controller submodule. + +```shell +simd tx ibc-transfer --help +``` + +#### `transfer` + +The `transfer` command allows users to execute cross-chain token transfers from the source port ID and channel ID on the sending chain. + +```shell +simd tx ibc-transfer transfer [src-port] [src-channel] [receiver] [coins] [flags] +``` + +Multiple tokens can be transferred on the same transaction by specifying a comma-separated list +of amount and denomination (e.g. `100uatom,100uosmo`) in the `coins` option. + +The additional flags that can be used with the command are: + +- `--packet-timeout-height` to specify the timeout block height in the format `{revision}-{height}`. The default value is `0-0`, which effectively disables the timeout. Timeout height can only be absolute, therefore this option must be used in combination with `--absolute-timeouts` set to true. +- `--packet-timeout-timestamp` to specify the timeout timestamp in nanoseconds. The timeout can be either relative (fromthe current UTC time) or absolute. The default value is 10 minutes (and thus relative). The timeout is disabled when set to 0. +- `--absolute-timeouts` to interpret the timeout timestamp as an absolute value (when set to true). The default value is false (and thus the timeout timeout is considered relative to current UTC time). +- `--memo` to specify the memo string to be sent along with the transfer packet. If forwarding is used, then the memo string will be carried through the intermediary chains to the final destination. +- `--forwarding` to specify forwarding information in the form of a comma separated list of source port ID/channel ID pairs at each intermediary chain (e.g. `transfer/channel-0,transfer/channel-1`). +- `--unwind` to specify if the tokens must be automatically unwound to there origin chain. This option can be used in combination with `--forwarding` to forward the tokens to the final destination after unwinding. When this flag is true, the tokens specified in the `coins` option must all have the same denomination trace path (i.e. all tokens must be IBC vouchers sharing exactly the same set of destination port/channel IDs in their denomination trace path). Arguments `[src-port]` and `[src-channel]` must not be passed if the `--unwind` flag is specified. + +#### `total-escrow` + +The `total-escrow` command allows users to query the total amount in escrow for a particular coin denomination regardless of the transfer channel from where the coins were sent out. + +```shell +simd query ibc-transfer total-escrow [denom] [flags] +``` + +Example: + +```shell +simd query ibc-transfer total-escrow samoleans +``` + +Example Output: + +```shell +amount: "100" +``` + +## gRPC + +A user can query the `transfer` module using gRPC endpoints. + +### `TotalEscrowForDenom` + +The `TotalEscrowForDenom` endpoint allows users to query the total amount in escrow for a particular coin denomination regardless of the transfer channel from where the coins were sent out. + +```shell +ibc.applications.transfer.v1.Query/TotalEscrowForDenom +``` + +Example: + +```shell +grpcurl -plaintext \ + -d '{"denom":"samoleans"}' \ + localhost:9090 \ + ibc.applications.transfer.v1.Query/TotalEscrowForDenom +``` + +Example output: + +```shell +{ + "amount": "100" +} +``` diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/01-overview.md b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/01-overview.md new file mode 100644 index 00000000000..fa98a8683bf --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/01-overview.md @@ -0,0 +1,142 @@ +--- +title: Overview +sidebar_label: Overview +sidebar_position: 1 +slug: /apps/transfer/ics20-v1/overview +--- + +:::warning +This document is relevant only for fungible token transfers over channels on v1 of the ICS-20 protocol. +::: + +# Overview + +:::note Synopsis +Learn about what the token Transfer module is +::: + +## What is the Transfer module? + +Transfer is the Cosmos SDK implementation of the [ICS-20](https://github.com/cosmos/ibc/tree/master/spec/app/ics-020-fungible-token-transfer) protocol, which enables cross-chain fungible token transfers. + +## Concepts + +### Acknowledgements + +ICS20 uses the recommended acknowledgement format as specified by [ICS 04](https://github.com/cosmos/ibc/tree/master/spec/core/ics-004-channel-and-packet-semantics#acknowledgement-envelope). + +A successful receive of a transfer packet will result in a Result Acknowledgement being written +with the value `[]byte{byte(1)}` in the `Response` field. + +An unsuccessful receive of a transfer packet will result in an Error Acknowledgement being written +with the error message in the `Response` field. + +### Denomination trace + +The denomination trace corresponds to the information that allows a token to be traced back to its +origin chain. It contains a sequence of port and channel identifiers ordered from the most recent to +the oldest in the timeline of transfers. + +This information is included on the token's base denomination field in the form of a hash to prevent an +unbounded denomination length. For example, the token `transfer/channelToA/uatom` will be displayed +as `ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2`. The human readable denomination +is stored using `x/bank` module's [denom metadata](https://docs.cosmos.network/main/build/modules/bank#denom-metadata) +feature. You may display the human readable denominations by querying balances with the `--resolve-denom` flag, as in: + +```shell +simd query bank balances [address] --resolve-denom +``` + +Each send to any chain other than the one it was previously received from is a movement forwards in +the token's timeline. This causes trace to be added to the token's history and the destination port +and destination channel to be prefixed to the denomination. In these instances the sender chain is +acting as the "source zone". When the token is sent back to the chain it previously received from, the +prefix is removed. This is a backwards movement in the token's timeline and the sender chain is +acting as the "sink zone". + +It is strongly recommended to read the full details of [ADR 001: Coin Source Tracing](/architecture/adr-001-coin-source-tracing) to understand the implications and context of the IBC token representations. + +## UX suggestions for clients + +For clients (wallets, exchanges, applications, block explorers, etc) that want to display the source of the token, it is recommended to use the following alternatives for each of the cases below: + +### Direct connection + +If the denomination trace contains a single identifier prefix pair (as in the example above), then +the easiest way to retrieve the chain and light client identifier is to map the trace information +directly. In summary, this requires querying the channel from the denomination trace identifiers, +and then the counterparty client state using the counterparty port and channel identifiers from the +retrieved channel. + +A general pseudo algorithm would look like the following: + +1. Query the full denomination trace. +2. Query the channel with the `portID/channelID` pair, which corresponds to the first destination of the + token. +3. Query the client state using the identifiers pair. Note that this query will return a `"Not +Found"` response if the current chain is not connected to this channel. +4. Retrieve the client identifier or chain identifier from the client state (eg: on + Tendermint clients) and store it locally. + +Using the gRPC gateway client service the steps above would be, with a given IBC token `ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2` stored on `chainB`: + +1. `GET /ibc/apps/transfer/v1/denom_traces/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2` -> `{"path": "transfer/channelToA", "base_denom": "uatom"}` +2. `GET /ibc/apps/transfer/v1/channels/channelToA/ports/transfer/client_state"` -> `{"client_id": "clientA", "chain-id": "chainA", ...}` +3. `GET /ibc/apps/transfer/v1/channels/channelToA/ports/transfer"` -> `{"channel_id": "channelToA", port_id": "transfer", counterparty: {"channel_id": "channelToB", port_id": "transfer"}, ...}` +4. `GET /ibc/apps/transfer/v1/channels/channelToB/ports/transfer/client_state" -> {"client_id": "clientB", "chain-id": "chainB", ...}` + +Then, the token transfer chain path for the `uatom` denomination would be: `chainA` -> `chainB`. + +### Multiple hops + +The multiple channel hops case applies when the token has passed through multiple chains between the original source and final destination chains. + +The IBC protocol doesn't know the topology of the overall network (i.e connections between chains and identifier names between them). For this reason, in the multiple hops case, a particular chain in the timeline of the individual transfers can't query the chain and client identifiers of the other chains. + +Take for example the following sequence of transfers `A -> B -> C` for an IBC token, with a final prefix path (trace info) of `transfer/channelChainC/transfer/channelChainB`. What the paragraph above means is that even in the case that chain `C` is directly connected to chain `A`, querying the port and channel identifiers that chain `B` uses to connect to chain `A` (eg: `transfer/channelChainA`) can be completely different from the one that chain `C` uses to connect to chain `A` (eg: `transfer/channelToChainA`). + +Thus the proposed solution for clients that the IBC team recommends are the following: + +- **Connect to all chains**: Connecting to all the chains in the timeline would allow clients to + perform the queries outlined in the [direct connection](#direct-connection) section to each + relevant chain. By repeatedly following the port and channel denomination trace transfer timeline, + clients should always be able to find all the relevant identifiers. This comes at the tradeoff + that the client must connect to nodes on each of the chains in order to perform the queries. +- **Relayer as a Service (RaaS)**: A longer term solution is to use/create a relayer service that + could map the denomination trace to the chain path timeline for each token (i.e `origin chain -> +chain #1 -> ... -> chain #(n-1) -> final chain`). These services could provide merkle proofs in + order to allow clients to optionally verify the path timeline correctness for themselves by + running light clients. If the proofs are not verified, they should be considered as trusted third + parties services. Additionally, client would be advised in the future to use RaaS that support the + largest number of connections between chains in the ecosystem. Unfortunately, none of the existing + public relayers (in [Golang](https://github.com/cosmos/relayer) and + [Rust](https://github.com/informalsystems/ibc-rs)), provide this service to clients. + +:::tip +The only viable alternative for clients (at the time of writing) to tokens with multiple connection hops, is to connect to all chains directly and perform relevant queries to each of them in the sequence. +::: + +## Locked funds + +In some [exceptional cases](/architecture/adr-026-ibc-client-recovery-mechanisms#exceptional-cases), a client state associated with a given channel cannot be updated. This causes that funds from fungible tokens in that channel will be permanently locked and thus can no longer be transferred. + +To mitigate this, a client update governance proposal can be submitted to update the frozen client +with a new valid header. Once the proposal passes the client state will be unfrozen and the funds +from the associated channels will then be unlocked. This mechanism only applies to clients that +allow updates via governance, such as Tendermint clients. + +In addition to this, it's important to mention that a token must be sent back along the exact route +that it took originally in order to return it to its original form on the source chain (eg: the +Cosmos Hub for the `uatom`). Sending a token back to the same chain across a different channel will +**not** move the token back across its timeline. If a channel in the chain history closes before the +token can be sent back across that channel, then the token will not be returnable to its original +form. + +## Security considerations + +For safety, no other module must be capable of minting tokens with the `ibc/` prefix. The IBC +transfer module needs a subset of the denomination space that only it can create tokens in. + +## Channel Closure + +The IBC transfer module does not support channel closure. diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/02-state.md b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/02-state.md new file mode 100644 index 00000000000..1d8207b58ef --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/02-state.md @@ -0,0 +1,17 @@ +--- +title: State +sidebar_label: State +sidebar_position: 2 +slug: /apps/transfer/ics20-v1/state +--- + +:::warning +This document is relevant only for fungible token transfers over channels on v1 of the ICS-20 protocol. +::: + +# State + +The IBC transfer application module keeps state of the port to which the module is binded and the denomination trace information as outlined in [ADR 001](/architecture/adr-001-coin-source-tracing). + +- `Port`: `0x01 -> ProtocolBuffer(string)` +- `DenomTrace`: `0x02 | []bytes(traceHash) -> ProtocolBuffer(DenomTrace)` diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/03-state-transitions.md b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/03-state-transitions.md new file mode 100644 index 00000000000..6e31bd5c298 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/03-state-transitions.md @@ -0,0 +1,41 @@ +--- +title: State Transitions +sidebar_label: State Transitions +sidebar_position: 3 +slug: /apps/transfer/ics20-v1/state-transitions +--- + +:::warning +This document is relevant only for fungible token transfers over channels on v1 of the ICS-20 protocol. +::: + +# State transitions + +## Send fungible tokens + +A successful fungible token send has two state transitions depending if the transfer is a movement forward or backwards in the token's timeline: + +1. Sender chain is the source chain, *i.e* a transfer to any chain other than the one it was previously received from is a movement forwards in the token's timeline. This results in the following state transitions: + + - The coins are transferred to an escrow address (i.e locked) on the sender chain. + - The coins are transferred to the receiving chain through IBC TAO logic. + +2. Sender chain is the sink chain, *i.e* the token is sent back to the chain it previously received from. This is a backwards movement in the token's timeline. This results in the following state transitions: + + - The coins (vouchers) are burned on the sender chain. + - The coins are transferred to the receiving chain through IBC TAO logic. + +## Receive fungible tokens + +A successful fungible token receive has two state transitions depending if the transfer is a movement forward or backwards in the token's timeline: + +1. Receiver chain is the source chain. This is a backwards movement in the token's timeline. This results in the following state transitions: + + - The leftmost port and channel identifier pair is removed from the token denomination prefix. + - The tokens are unescrowed and sent to the receiving address. + +2. Receiver chain is the sink chain. This is a movement forwards in the token's timeline. This results in the following state transitions: + + - Token vouchers are minted by prefixing the destination port and channel identifiers to the trace information. + - The receiving chain stores the new trace information in the store (if not set already). + - The vouchers are sent to the receiving address. diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/04-messages.md b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/04-messages.md new file mode 100644 index 00000000000..c2826f54426 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/04-messages.md @@ -0,0 +1,65 @@ +--- +title: Messages +sidebar_label: Messages +sidebar_position: 4 +slug: /apps/transfer/ics20-v1/messages +--- + +:::warning +This document is relevant only for fungible token transfers over channels on v1 of the ICS-20 protocol. +::: + +# Messages + +## `MsgTransfer` + +A fungible token cross chain transfer is achieved by using the `MsgTransfer`: + +```go +type MsgTransfer struct { + SourcePort string + SourceChannel string + Token sdk.Coin + Sender string + Receiver string + TimeoutHeight ibcexported.Height + TimeoutTimestamp uint64 + Memo string +} +``` + +This message is expected to fail if: + +- `SourcePort` is invalid (see [24-host naming requirements](https://github.com/cosmos/ibc/blob/master/spec/core/ics-024-host-requirements/README.md#paths-identifiers-separators). +- `SourceChannel` is invalid (see [24-host naming requirements](https://github.com/cosmos/ibc/blob/master/spec/core/ics-024-host-requirements/README.md#paths-identifiers-separators)). +- `Token` is invalid: + - `Amount` is not positive. + - `Denom` is not a valid IBC denomination as per [ADR 001 - Coin Source Tracing](/architecture/adr-001-coin-source-tracing). +- `Sender` is empty. +- `Receiver` is empty or contains more than 2048 bytes. +- `Memo` contains more than 32768 bytes. +- `TimeoutHeight` and `TimeoutTimestamp` are both zero. + +This message will send a fungible token to the counterparty chain represented by the counterparty Channel End connected to the Channel End with the identifiers `SourcePort` and `SourceChannel`. + +The denomination provided for transfer should correspond to the same denomination represented on this chain. The prefixes will be added as necessary upon by the receiving chain. + +If the `Amount` is set to the maximum value for a 256-bit unsigned integer (i.e. 2^256 - 1), then the whole balance of the corresponding denomination will be transferred. The helper function `UnboundedSpendLimit` in the `types` package of the `transfer` module provides the sentinel value that can be used. + +### Memo + +The memo field was added to allow applications and users to attach metadata to transfer packets. The field is optional and may be left empty. When it is used to attach metadata for a particular middleware, the memo field should be represented as a json object where different middlewares use different json keys. + +For example, the following memo field is used by the [callbacks middleware](../../../04-middleware/02-callbacks/01-overview.md) to attach a source callback to a transfer packet: + +```jsonc +{ + "src_callback": { + "address": "callbackAddressString", + // optional + "gas_limit": "userDefinedGasLimitString", + } +} +``` + +You can find more information about other applications that use the memo field in the [chain registry](https://github.com/cosmos/chain-registry/blob/master/_memo_keys/ICS20_memo_keys.json). diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/05-events.md b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/05-events.md new file mode 100644 index 00000000000..cea5b596cf1 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/05-events.md @@ -0,0 +1,61 @@ +--- +title: Events +sidebar_label: Events +sidebar_position: 5 +slug: /apps/transfer/ics20-v1/events +--- + +:::warning +This document is relevant only for fungible token transfers over channels on v1 of the ICS-20 protocol. +::: + +# Events + +## `MsgTransfer` + +| Type | Attribute Key | Attribute Value | +|--------------|-----------------|-----------------| +| ibc_transfer | sender | \{sender\} | +| ibc_transfer | receiver | \{receiver\} | +| ibc_transfer | tokens | \{jsonTokens\} | +| ibc_transfer | memo | \{memo\} | +| ibc_transfer | forwarding_hops | `nil` | +| message | module | transfer | + +## `OnRecvPacket` callback + +| Type | Attribute Key | Attribute Value | +|-----------------------|-----------------|-----------------| +| fungible_token_packet | sender | \{sender\} | +| fungible_token_packet | receiver | \{receiver\} | +| fungible_token_packet | tokens | \{jsonTokens\} | +| fungible_token_packet | memo | \{memo\} | +| fungible_token_packet | forwarding_hops | `nil` | +| fungible_token_packet | success | \{ackSuccess\} | +| fungible_token_packet | error | \{ackError\} | +| denomination | trace_hash | \{hex_hash\} | +| denomination | denom | \{jsonDenom\} | +| message | module | transfer | + +## `OnAcknowledgePacket` callback + +| Type | Attribute Key | Attribute Value | +|-----------------------|-----------------|------------------| +| fungible_token_packet | sender | \{sender\} | +| fungible_token_packet | receiver | \{receiver\} | +| fungible_token_packet | tokens | \{jsonTokens\} | +| fungible_token_packet | memo | \{memo\} | +| fungible_token_packet | forwarding_hops | `nil` | +| fungible_token_packet | acknowledgement | \{ack.String()\} | +| fungible_token_packet | success / error | \{ack.Response\} | +| message | module | transfer | + +## `OnTimeoutPacket` callback + +| Type | Attribute Key | Attribute Value | +|---------|-----------------|-----------------| +| timeout | refund_receiver | \{receiver\} | +| timeout | refund_tokens | \{jsonTokens\} | +| timeout | memo | \{memo\} | +| timeout | forwarding_hops | `nil` | +| message | module | transfer | diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/06-metrics.md b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/06-metrics.md new file mode 100644 index 00000000000..f788429fd10 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/06-metrics.md @@ -0,0 +1,21 @@ +--- +title: Metrics +sidebar_label: Metrics +sidebar_position: 6 +slug: /apps/transfer/ics20-v1/metrics +--- + +:::warning +This document is relevant only for fungible token transfers over channels on v1 of the ICS-20 protocol. +::: + +# Metrics + +The IBC transfer application module exposes the following set of [metrics](https://github.com/cosmos/cosmos-sdk/blob/main/docs/learn/advanced/09-telemetry.md). + +| Metric | Description | Unit | Type | +|:--------------------------------|:------------------------------------------------------------------------------------------|:----------------|:--------| +| `tx_msg_ibc_transfer` | The total amount of tokens transferred via IBC in a `MsgTransfer` (source or sink chain) | token | gauge | +| `ibc_transfer_packet_receive` | The total amount of tokens received in a `FungibleTokenPacketData` (source or sink chain) | token | gauge | +| `ibc_transfer_send` | Total number of IBC transfers sent from a chain (source or sink) | transfer | counter | +| `ibc_transfer_receive` | Total number of IBC transfers received to a chain (source or sink) | transfer | counter | diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/07-params.md b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/07-params.md new file mode 100644 index 00000000000..ca3b20a5acd --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/07-params.md @@ -0,0 +1,97 @@ +--- +title: Params +sidebar_label: Params +sidebar_position: 7 +slug: /apps/transfer/ics20-v1/params +--- + +:::warning +This document is relevant only for fungible token transfers over channels on v1 of the ICS-20 protocol. +::: + +# Parameters + +The IBC transfer application module contains the following parameters: + +| Name | Type | Default Value | +| ---------------- | ---- | ------------- | +| `SendEnabled` | bool | `true` | +| `ReceiveEnabled` | bool | `true` | + +The IBC transfer module stores its parameters in its keeper with the prefix of `0x03`. + +## `SendEnabled` + +The `SendEnabled` parameter controls send cross-chain transfer capabilities for all fungible tokens. + +To prevent a single token from being transferred from the chain, set the `SendEnabled` parameter to `true` and then, depending on the Cosmos SDK version, do one of the following: + +- For Cosmos SDK v0.46.x or earlier, set the bank module's [`SendEnabled` parameter](https://github.com/cosmos/cosmos-sdk/blob/release/v0.46.x/x/bank/spec/05_params.md#sendenabled) for the denomination to `false`. +- For Cosmos SDK versions above v0.46.x, set the bank module's `SendEnabled` entry for the denomination to `false` using `MsgSetSendEnabled` as a governance proposal. + +:::warning +Doing so will prevent the token from being transferred between any accounts in the blockchain. +::: + +## `ReceiveEnabled` + +The transfers enabled parameter controls receive cross-chain transfer capabilities for all fungible tokens. + +To prevent a single token from being transferred to the chain, set the `ReceiveEnabled` parameter to `true` and then, depending on the Cosmos SDK version, do one of the following: + +- For Cosmos SDK v0.46.x or earlier, set the bank module's [`SendEnabled` parameter](https://github.com/cosmos/cosmos-sdk/blob/release/v0.46.x/x/bank/spec/05_params.md#sendenabled) for the denomination to `false`. +- For Cosmos SDK versions above v0.46.x, set the bank module's `SendEnabled` entry for the denomination to `false` using `MsgSetSendEnabled` as a governance proposal. + +:::warning +Doing so will prevent the token from being transferred between any accounts in the blockchain. +::: + +## Queries + +Current parameter values can be queried via a query message. + + + +```protobuf +// proto/ibc/applications/transfer/v1/query.proto + +// QueryParamsRequest is the request type for the Query/Params RPC method. +message QueryParamsRequest {} + +// QueryParamsResponse is the response type for the Query/Params RPC method. +message QueryParamsResponse { + // params defines the parameters of the module. + Params params = 1; +} +``` + +To execute the query in `simd`, you use the following command: + +```bash +simd query ibc-transfer params +``` + +## Changing Parameters + +To change the parameter values, you must make a governance proposal that executes the `MsgUpdateParams` message. + + + +```protobuf +// proto/ibc/applications/transfer/v1/tx.proto + +// MsgUpdateParams is the Msg/UpdateParams request type. +message MsgUpdateParams { + // signer address (it may be the address that controls the module, which defaults to x/gov unless overwritten). + string signer = 1; + + // params defines the transfer parameters to update. + // + // NOTE: All parameters must be supplied. + Params params = 2 [(gogoproto.nullable) = false]; +} + +// MsgUpdateParamsResponse defines the response structure for executing a +// MsgUpdateParams message. +message MsgUpdateParamsResponse {} +``` diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/08-authorizations.md b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/08-authorizations.md new file mode 100644 index 00000000000..6ba1de76ac4 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/08-authorizations.md @@ -0,0 +1,60 @@ +--- +title: Authorizations +sidebar_label: Authorizations +sidebar_position: 8 +slug: /apps/transfer/ics20-v1/authorizations +--- + +:::warning +This document is relevant only for fungible token transfers over channels on v1 of the ICS-20 protocol. +::: + +# `TransferAuthorization` + +`TransferAuthorization` implements the `Authorization` interface for `ibc.applications.transfer.v1.MsgTransfer`. It allows a granter to grant a grantee the privilege to submit `MsgTransfer` on its behalf. Please see the [Cosmos SDK docs](https://docs.cosmos.network/v0.47/modules/authz) for more details on granting privileges via the `x/authz` module. + +More specifically, the granter allows the grantee to transfer funds that belong to the granter over a specified channel. + +For the specified channel, the granter must be able to specify a spend limit of a specific denomination they wish to allow the grantee to be able to transfer. + +The granter may be able to specify the list of addresses that they allow to receive funds. If empty, then all addresses are allowed. + +It takes: + +- a `SourcePort` and a `SourceChannel` which together comprise the unique transfer channel identifier over which authorized funds can be transferred. +- a `SpendLimit` that specifies the maximum amount of tokens the grantee can transfer. The `SpendLimit` is updated as the tokens are transferred, unless the sentinel value of the maximum value for a 256-bit unsigned integer (i.e. 2^256 - 1) is used for the amount, in which case the `SpendLimit` will not be updated (please be aware that using this sentinel value will grant the grantee the privilege to transfer **all** the tokens of a given denomination available at the granter's account). The helper function `UnboundedSpendLimit` in the `types` package of the `transfer` module provides the sentinel value that can be used. This `SpendLimit` may also be updated to increase or decrease the limit as the granter wishes. +- an `AllowList` list that specifies the list of addresses that are allowed to receive funds. If this list is empty, then all addresses are allowed to receive funds from the `TransferAuthorization`. +- an `AllowedPacketData` list that specifies the list of memo strings that are allowed to be included in the memo field of the packet. If this list is empty, then only an empty memo is allowed (a `memo` field with non-empty content will be denied). If this list includes a single element equal to `"*"`, then any content in `memo` field will be allowed. + +Setting a `TransferAuthorization` is expected to fail if: + +- the spend limit is nil +- the denomination of the spend limit is an invalid coin type +- the source port ID is invalid +- the source channel ID is invalid +- there are duplicate entries in the `AllowList` +- the `memo` field is not allowed by `AllowedPacketData` + +Below is the `TransferAuthorization` message: + +```go +func NewTransferAuthorization(allocations ...Allocation) *TransferAuthorization { + return &TransferAuthorization{ + Allocations: allocations, + } +} + +type Allocation struct { + // the port on which the packet will be sent + SourcePort string + // the channel by which the packet will be sent + SourceChannel string + // spend limitation on the channel + SpendLimit sdk.Coins + // allow list of receivers, an empty allow list permits any receiver address + AllowList []string + // allow list of memo strings, an empty list prohibits all memo strings; + // a list only with "*" permits any memo string + AllowedPacketData []string +} +``` diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/09-client.md b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/09-client.md new file mode 100644 index 00000000000..20d8c2f10a0 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/09-client.md @@ -0,0 +1,98 @@ +--- +title: Client +sidebar_label: Client +sidebar_position: 9 +slug: /apps/transfer/ics20-v1/client +--- + +:::warning +This document is relevant only for fungible token transfers over channels on v1 of the ICS-20 protocol. +::: + +# Client + +## CLI + +A user can query and interact with the `transfer` module using the CLI. Use the `--help` flag to discover the available commands: + +### Query + +The `query` commands allow users to query `transfer` state. + +```shell +simd query ibc-transfer --help +``` + +#### Transactions + +The `tx` commands allow users to interact with the controller submodule. + +```shell +simd tx ibc-transfer --help +``` + +#### `transfer` + +The `transfer` command allows users to execute cross-chain token transfers from the source port ID and channel ID on the sending chain. + +```shell +simd tx ibc-transfer transfer [src-port] [src-channel] [receiver] [coins] [flags] +``` + +The `coins` parameter accepts the amount and denomination (e.g. `100uatom`) of the tokens to be transferred. + +The additional flags that can be used with the command are: + +- `--packet-timeout-height` to specify the timeout block height in the format `{revision}-{height}`. The default value is `0-0`, which effectively disables the timeout. Timeout height can only be absolute, therefore this option must be used in combination with `--absolute-timeouts` set to true. +- `--packet-timeout-timestamp` to specify the timeout timestamp in nanoseconds. The timeout can be either relative (fromthe current UTC time) or absolute. The default value is 10 minutes (and thus relative). The timeout is disabled when set to 0. +- `--absolute-timeouts` to interpret the timeout timestamp as an absolute value (when set to true). The default value is false (and thus the timeout timeout is considered relative to current UTC time). +- `--memo` to specify the memo string to be sent along with the transfer packet. If forwarding is used, then the memo string will be carried through the intermediary chains to the final destination. + +#### `total-escrow` + +The `total-escrow` command allows users to query the total amount in escrow for a particular coin denomination regardless of the transfer channel from where the coins were sent out. + +```shell +simd query ibc-transfer total-escrow [denom] [flags] +``` + +Example: + +```shell +simd query ibc-transfer total-escrow samoleans +``` + +Example Output: + +```shell +amount: "100" +``` + +## gRPC + +A user can query the `transfer` module using gRPC endpoints. + +### `TotalEscrowForDenom` + +The `TotalEscrowForDenom` endpoint allows users to query the total amount in escrow for a particular coin denomination regardless of the transfer channel from where the coins were sent out. + +```shell +ibc.applications.transfer.v1.Query/TotalEscrowForDenom +``` + +Example: + +```shell +grpcurl -plaintext \ + -d '{"denom":"samoleans"}' \ + localhost:9090 \ + ibc.applications.transfer.v1.Query/TotalEscrowForDenom +``` + +Example output: + +```shell +{ + "amount": "100" +} +``` diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/_category_.json b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/_category_.json new file mode 100644 index 00000000000..3ea1fff9668 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/10-ICS20-v1/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "ICS20 v1", + "position": 10, + "link": null +} diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/_category_.json b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/_category_.json new file mode 100644 index 00000000000..d643a498cdf --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Transfer", + "position": 1, + "link": null +} \ No newline at end of file diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/images/forwarding-3-chains-dark.png b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/images/forwarding-3-chains-dark.png new file mode 100644 index 00000000000..3da5c63f6ec Binary files /dev/null and b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/images/forwarding-3-chains-dark.png differ diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/images/forwarding-3-chains-light.png b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/images/forwarding-3-chains-light.png new file mode 100644 index 00000000000..032919e8177 Binary files /dev/null and b/docs/versioned_docs/version-v9.0.x/02-apps/01-transfer/images/forwarding-3-chains-light.png differ diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/01-overview.md b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/01-overview.md new file mode 100644 index 00000000000..d09654230b9 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/01-overview.md @@ -0,0 +1,48 @@ +--- +title: Overview +sidebar_label: Overview +sidebar_position: 1 +slug: /apps/interchain-accounts/overview +--- + + +# Overview + +:::note Synopsis +Learn about what the Interchain Accounts module is +::: + +## What is the Interchain Accounts module? + +Interchain Accounts is the Cosmos SDK implementation of the ICS-27 protocol, which enables cross-chain account management built upon IBC. + +- How does an interchain account differ from a regular account? + +Regular accounts use a private key to sign transactions. Interchain Accounts are instead controlled programmatically by counterparty chains via IBC packets. + +## Concepts + +`Host Chain`: The chain where the interchain account is registered. The host chain listens for IBC packets from a controller chain which should contain instructions (e.g. Cosmos SDK messages) for which the interchain account will execute. + +`Controller Chain`: The chain registering and controlling an account on a host chain. The controller chain sends IBC packets to the host chain to control the account. + +`Interchain Account`: An account on a host chain created using the ICS-27 protocol. An interchain account has all the capabilities of a normal account. However, rather than signing transactions with a private key, a controller chain will send IBC packets to the host chain which signals what transactions the interchain account should execute. + +`Authentication Module`: A custom application module on the controller chain that uses the Interchain Accounts module to build custom logic for the creation & management of interchain accounts. It can be either an IBC application module using the [legacy API](10-legacy/03-keeper-api.md), or a regular Cosmos SDK application module sending messages to the controller submodule's `MsgServer` (this is the recommended approach from ibc-go v6 if access to packet callbacks is not needed). Please note that the legacy API will eventually be removed and IBC applications will not be able to use them in later releases. + +## SDK security model + +SDK modules on a chain are assumed to be trustworthy. For example, there are no checks to prevent an untrustworthy module from accessing the bank keeper. + +The implementation of ICS-27 in ibc-go uses this assumption in its security considerations. + +The implementation assumes other IBC application modules will not bind to ports within the ICS-27 namespace. + +## Channel Closure + +The provided interchain account host and controller implementations do not support `ChanCloseInit`. However, they do support `ChanCloseConfirm`. +This means that the host and controller modules cannot close channels, but they will confirm channel closures initiated by other implementations of ICS-27. + +In the event of a channel closing (due to a packet timeout in an ordered channel, for example), the interchain account associated with that channel can become accessible again if a new channel is created with a (JSON-formatted) version string that encodes the exact same `Metadata` information of the previous channel. The channel can be reopened using either [`MsgRegisterInterchainAccount`](./05-messages.md#msgregisterinterchainaccount) or `MsgChannelOpenInit`. If `MsgRegisterInterchainAccount` is used, then it is possible to leave the `version` field of the message empty, since it will be filled in by the controller submodule. If `MsgChannelOpenInit` is used, then the `version` field must be provided with the correct JSON-encoded `Metadata` string. See section [Understanding Active Channels](./09-active-channels.md#understanding-active-channels) for more information. + +When reopening a channel with the default controller submodule, the ordering of the channel cannot be changed. In order to change the ordering of the channel, the channel has to go through a [channel upgrade handshake](../../01-ibc/06-channel-upgrades.md) or reopen the channel with a custom controller implementation. diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/02-development.md b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/02-development.md new file mode 100644 index 00000000000..0440de5255b --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/02-development.md @@ -0,0 +1,40 @@ +--- +title: Development Use Cases +sidebar_label: Development Use Cases +sidebar_position: 2 +slug: /apps/interchain-accounts/development +--- + + +# Development use cases + +The initial version of Interchain Accounts allowed for the controller submodule to be extended by providing it with an underlying application which would handle all packet callbacks. +That functionality is now being deprecated in favor of alternative approaches. +This document will outline potential use cases and redirect each use case to the appropriate documentation. + +## Custom authentication + +Interchain accounts may be associated with alternative types of authentication relative to the traditional public/private key signing. +If you wish to develop or use Interchain Accounts with a custom authentication module and do not need to execute custom logic on the packet callbacks, we recommend you use ibc-go v6 or greater and that your custom authentication module interacts with the controller submodule via the [`MsgServer`](./05-messages.md). + +If you wish to consume and execute custom logic in the packet callbacks, then please read the section [Packet callbacks](#packet-callbacks) below. + +## Redirection to a smart contract + +It may be desirable to allow smart contracts to control an interchain account. +To facilitate such an action, the controller submodule may be provided an underlying application which redirects to smart contract callers. +An improved design has been suggested in [ADR 008](https://github.com/cosmos/ibc-go/pull/1976) which performs this action via middleware. + +Implementers of this use case are recommended to follow the ADR 008 approach. +The underlying application may continue to be used as a short term solution for ADR 008 and the [legacy API](./10-legacy/01-auth-modules.md) should continue to be utilized in such situations. + +## Packet callbacks + +If a developer requires access to packet callbacks for their use case, then they have the following options: + +1. Write a smart contract which is connected via an ADR 008 or equivalent IBC application (recommended). +2. Use the controller's underlying application to implement packet callback logic. + +In the first case, the smart contract should use the [`MsgServer`](./05-messages.md). + +In the second case, the underlying application should use the [legacy API](./10-legacy/03-keeper-api.md). diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/03-auth-modules.md b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/03-auth-modules.md new file mode 100644 index 00000000000..31231952208 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/03-auth-modules.md @@ -0,0 +1,27 @@ +--- +title: Authentication Modules +sidebar_label: Authentication Modules +sidebar_position: 3 +slug: /apps/interchain-accounts/auth-modules +--- + + +# Building an authentication module + +:::note Synopsis +Authentication modules enable application developers to perform custom logic when interacting with the Interchain Accounts controller sumbmodule's `MsgServer`. +::: + +The controller submodule is used for account registration and packet sending. It executes only logic required of all controllers of interchain accounts. The type of authentication used to manage the interchain accounts remains unspecified. There may exist many different types of authentication which are desirable for different use cases. Thus the purpose of the authentication module is to wrap the controller submodule with custom authentication logic. + +In ibc-go, authentication modules can communicate with the controller submodule by passing messages through `baseapp`'s `MsgServiceRouter`. To implement an authentication module, the `IBCModule` interface need not be fulfilled; it is only required to fulfill Cosmos SDK's `AppModuleBasic` interface, just like any regular Cosmos SDK application module. + +The authentication module must: + +- Authenticate interchain account owners. +- Track the associated interchain account address for an owner. +- Send packets on behalf of an owner (after authentication). + +## Integration into `app.go` file + +To integrate the authentication module into your chain, please follow the steps outlined in [`app.go` integration](04-integration.md#example-integration). diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/04-integration.md b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/04-integration.md new file mode 100644 index 00000000000..14117661086 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/04-integration.md @@ -0,0 +1,195 @@ +--- +title: Integration +sidebar_label: Integration +sidebar_position: 4 +slug: /apps/interchain-accounts/integration +--- + + +# Integration + +:::note Synopsis +Learn how to integrate Interchain Accounts host and controller functionality to your chain. The following document only applies for Cosmos SDK chains. +::: + +The Interchain Accounts module contains two submodules. Each submodule has its own IBC application. The Interchain Accounts module should be registered as an `AppModule` in the same way all SDK modules are registered on a chain, but each submodule should create its own `IBCModule` as necessary. A route should be added to the IBC router for each submodule which will be used. + +Chains who wish to support ICS-27 may elect to act as a host chain, a controller chain or both. Disabling host or controller functionality may be done statically by excluding the host or controller submodule entirely from the `app.go` file or it may be done dynamically by taking advantage of the on-chain parameters which enable or disable the host or controller submodules. + +Interchain Account authentication modules (both custom or generic, such as the `x/gov`, `x/group` or `x/auth` Cosmos SDK modules) can send messages to the controller submodule's [`MsgServer`](05-messages.md) to register interchain accounts and send packets to the interchain account. To accomplish this, the authentication module needs to be composed with `baseapp`'s `MsgServiceRouter`. + +![ica-v6.png](./images/ica-v6.png) + +## Example integration + +```go +// app.go + +// Register the AppModule for the Interchain Accounts module and the authentication module +// Note: No `icaauth` exists, this must be substituted with an actual Interchain Accounts authentication module +ModuleBasics = module.NewBasicManager( + ... + ica.AppModuleBasic{}, + icaauth.AppModuleBasic{}, + ... +) + +... + +// Add module account permissions for the Interchain Accounts module +// Only necessary for host chain functionality +// Each Interchain Account created on the host chain is derived from the module account created +maccPerms = map[string][]string{ + ... + icatypes.ModuleName: nil, +} + +... + +// Add Interchain Accounts Keepers for each submodule used and the authentication module +// If a submodule is being statically disabled, the associated Keeper does not need to be added. +type App struct { + ... + + ICAControllerKeeper icacontrollerkeeper.Keeper + ICAHostKeeper icahostkeeper.Keeper + ICAAuthKeeper icaauthkeeper.Keeper + + ... +} + +... + +// Create store keys for each submodule Keeper and the authentication module +keys := sdk.NewKVStoreKeys( + ... + icacontrollertypes.StoreKey, + icahosttypes.StoreKey, + icaauthtypes.StoreKey, + ... +) + +... + + +// Create the Keeper for each submodule +app.ICAControllerKeeper = icacontrollerkeeper.NewKeeper( + appCodec, keys[icacontrollertypes.StoreKey], app.GetSubspace(icacontrollertypes.SubModuleName), + app.IBCKeeper.ChannelKeeper, // may be replaced with middleware such as ics29 fee + app.IBCKeeper.ChannelKeeper, app.IBCKeeper.PortKeeper, + app.MsgServiceRouter(), + authtypes.NewModuleAddress(govtypes.ModuleName).String(), +) +app.ICAHostKeeper = icahostkeeper.NewKeeper( + appCodec, keys[icahosttypes.StoreKey], app.GetSubspace(icahosttypes.SubModuleName), + app.IBCKeeper.ChannelKeeper, // may be replaced with middleware such as ics29 fee + app.IBCKeeper.ChannelKeeper, app.IBCKeeper.PortKeeper, app.AccountKeeper, + app.MsgServiceRouter(), app.GRPCQueryRouter(), + authtypes.NewModuleAddress(govtypes.ModuleName).String(), +) + +// Create Interchain Accounts AppModule +icaModule := ica.NewAppModule(&app.ICAControllerKeeper, &app.ICAHostKeeper) + +// Create your Interchain Accounts authentication module +app.ICAAuthKeeper = icaauthkeeper.NewKeeper(appCodec, keys[icaauthtypes.StoreKey], app.MsgServiceRouter()) + +// ICA auth AppModule +icaAuthModule := icaauth.NewAppModule(appCodec, app.ICAAuthKeeper) + +// Create controller IBC application stack and host IBC module as desired +icaControllerStack := icacontroller.NewIBCMiddleware(app.ICAControllerKeeper) +icaHostIBCModule := icahost.NewIBCModule(app.ICAHostKeeper) + +// Register host and authentication routes +ibcRouter. + AddRoute(icacontrollertypes.SubModuleName, icaControllerStack). + AddRoute(icahosttypes.SubModuleName, icaHostIBCModule) +... + +// Register Interchain Accounts and authentication module AppModule's +app.moduleManager = module.NewManager( + ... + icaModule, + icaAuthModule, +) + +... + +// Add Interchain Accounts to begin blocker logic +app.moduleManager.SetOrderBeginBlockers( + ... + icatypes.ModuleName, + ... +) + +// Add Interchain Accounts to end blocker logic +app.moduleManager.SetOrderEndBlockers( + ... + icatypes.ModuleName, + ... +) + +// Add Interchain Accounts module InitGenesis logic +app.moduleManager.SetOrderInitGenesis( + ... + icatypes.ModuleName, + ... +) + +// initParamsKeeper init params keeper and its subspaces +func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino, key, tkey sdk.StoreKey) paramskeeper.Keeper { + ... + paramsKeeper.Subspace(icahosttypes.SubModuleName) + paramsKeeper.Subspace(icacontrollertypes.SubModuleName) + ... +} +``` + +If no custom athentication module is needed and a generic Cosmos SDK authentication module can be used, then from the sample integration code above all references to `ICAAuthKeeper` and `icaAuthModule` can be removed. That's it, the following code would not be needed: + +```go +// Create your Interchain Accounts authentication module +app.ICAAuthKeeper = icaauthkeeper.NewKeeper(appCodec, keys[icaauthtypes.StoreKey], app.MsgServiceRouter()) + +// ICA auth AppModule +icaAuthModule := icaauth.NewAppModule(appCodec, app.ICAAuthKeeper) +``` + +### Using submodules exclusively + +As described above, the Interchain Accounts application module is structured to support the ability of exclusively enabling controller or host functionality. +This can be achieved by simply omitting either controller or host `Keeper` from the Interchain Accounts `NewAppModule` constructor function, and mounting only the desired submodule via the `IBCRouter`. +Alternatively, submodules can be enabled and disabled dynamically using [on-chain parameters](06-parameters.md). + +The following snippets show basic examples of statically disabling submodules using `app.go`. + +#### Disabling controller chain functionality + +```go +// Create Interchain Accounts AppModule omitting the controller keeper +icaModule := ica.NewAppModule(nil, &app.ICAHostKeeper) + +// Create host IBC Module +icaHostIBCModule := icahost.NewIBCModule(app.ICAHostKeeper) + +// Register host route +ibcRouter.AddRoute(icahosttypes.SubModuleName, icaHostIBCModule) +``` + +#### Disabling host chain functionality + +```go +// Create Interchain Accounts AppModule omitting the host keeper +icaModule := ica.NewAppModule(&app.ICAControllerKeeper, nil) + + +// Optionally instantiate your custom authentication module if needed, or not otherwise +... + +// Create controller IBC application stack +icaControllerStack := icacontroller.NewIBCMiddleware(app.ICAControllerKeeper) + +// Register controller route +ibcRouter.AddRoute(icacontrollertypes.SubModuleName, icaControllerStack) +``` diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/05-messages.md b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/05-messages.md new file mode 100644 index 00000000000..eb671ab5e5e --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/05-messages.md @@ -0,0 +1,153 @@ +--- +title: Messages +sidebar_label: Messages +sidebar_position: 5 +slug: /apps/interchain-accounts/messages +--- + + +# Messages + +## `MsgRegisterInterchainAccount` + +An Interchain Accounts channel handshake can be initiated using `MsgRegisterInterchainAccount`: + +```go +type MsgRegisterInterchainAccount struct { + Owner string + ConnectionID string + Version string + Ordering channeltypes.Order +} +``` + +This message is expected to fail if: + +- `Owner` is an empty string or contains more than 2048 bytes. +- `ConnectionID` is invalid (see [24-host naming requirements](https://github.com/cosmos/ibc/blob/master/spec/core/ics-024-host-requirements/README.md#paths-identifiers-separators)). + +This message will construct a new `MsgChannelOpenInit` on chain and route it to the core IBC message server to initiate the opening step of the channel handshake. + +The controller submodule will generate a new port identifier. The caller is expected to provide an appropriate application version string. For example, this may be an ICS-27 JSON encoded [`Metadata`](https://github.com/cosmos/ibc-go/blob/v6.0.0/proto/ibc/applications/interchain_accounts/v1/metadata.proto#L11) type or an ICS-29 JSON encoded [`Metadata`](https://github.com/cosmos/ibc-go/blob/v6.0.0/proto/ibc/applications/fee/v1/metadata.proto#L11) type with a nested application version. +If the `Version` string is omitted, the controller submodule will construct a default version string in the `OnChanOpenInit` handshake callback. + +```go +type MsgRegisterInterchainAccountResponse struct { + ChannelID string + PortId string +} +``` + +The `ChannelID` and `PortID` are returned in the message response. + +## `MsgSendTx` + +An Interchain Accounts transaction can be executed on a remote host chain by sending a `MsgSendTx` from the corresponding controller chain: + +```go +type MsgSendTx struct { + Owner string + ConnectionID string + PacketData InterchainAccountPacketData + RelativeTimeout uint64 +} +``` + +This message is expected to fail if: + +- `Owner` is an empty string or contains more than 2048 bytes. +- `ConnectionID` is invalid (see [24-host naming requirements](https://github.com/cosmos/ibc/blob/master/spec/core/ics-024-host-requirements/README.md#paths-identifiers-separators)). +- `PacketData` contains an `UNSPECIFIED` type enum, the length of `Data` bytes is zero or the `Memo` field exceeds 256 characters in length. +- `RelativeTimeout` is zero. + +This message will create a new IBC packet with the provided `PacketData` and send it via the channel associated with the `Owner` and `ConnectionID`. +The `PacketData` is expected to contain a list of serialized `[]sdk.Msg` in the form of `CosmosTx`. Please note the signer field of each `sdk.Msg` must be the interchain account address. +When the packet is relayed to the host chain, the `PacketData` is unmarshalled and the messages are authenticated and executed. + +```go +type MsgSendTxResponse struct { + Sequence uint64 +} +``` + +The packet `Sequence` is returned in the message response. + +### Queries + +It is possible to use [`MsgModuleQuerySafe`](https://github.com/cosmos/ibc-go/blob/eecfa5c09a4c38a5c9f2cc2a322d2286f45911da/proto/ibc/applications/interchain_accounts/host/v1/tx.proto#L41-L51) to execute a list of queries on the host chain. This message can be included in the list of encoded `sdk.Msg`s of `InterchainPacketData`. The host chain will return on the acknowledgment the responses for all the queries. Please note that only module safe queries can be executed ([deterministic queries that are safe to be called from within the state machine](https://docs.cosmos.network/main/build/building-modules/query-services#calling-queries-from-the-state-machine)). + +The queries available from Cosmos SDK are: + +```plaintext +/cosmos.auth.v1beta1.Query/Accounts +/cosmos.auth.v1beta1.Query/Account +/cosmos.auth.v1beta1.Query/AccountAddressByID +/cosmos.auth.v1beta1.Query/Params +/cosmos.auth.v1beta1.Query/ModuleAccounts +/cosmos.auth.v1beta1.Query/ModuleAccountByName +/cosmos.auth.v1beta1.Query/AccountInfo +/cosmos.bank.v1beta1.Query/Balance +/cosmos.bank.v1beta1.Query/AllBalances +/cosmos.bank.v1beta1.Query/SpendableBalances +/cosmos.bank.v1beta1.Query/SpendableBalanceByDenom +/cosmos.bank.v1beta1.Query/TotalSupply +/cosmos.bank.v1beta1.Query/SupplyOf +/cosmos.bank.v1beta1.Query/Params +/cosmos.bank.v1beta1.Query/DenomMetadata +/cosmos.bank.v1beta1.Query/DenomMetadataByQueryString +/cosmos.bank.v1beta1.Query/DenomsMetadata +/cosmos.bank.v1beta1.Query/DenomOwners +/cosmos.bank.v1beta1.Query/SendEnabled +/cosmos.circuit.v1.Query/Account +/cosmos.circuit.v1.Query/Accounts +/cosmos.circuit.v1.Query/DisabledList +/cosmos.staking.v1beta1.Query/Validators +/cosmos.staking.v1beta1.Query/Validator +/cosmos.staking.v1beta1.Query/ValidatorDelegations +/cosmos.staking.v1beta1.Query/ValidatorUnbondingDelegations +/cosmos.staking.v1beta1.Query/Delegation +/cosmos.staking.v1beta1.Query/UnbondingDelegation +/cosmos.staking.v1beta1.Query/DelegatorDelegations +/cosmos.staking.v1beta1.Query/DelegatorUnbondingDelegations +/cosmos.staking.v1beta1.Query/Redelegations +/cosmos.staking.v1beta1.Query/DelegatorValidators +/cosmos.staking.v1beta1.Query/DelegatorValidator +/cosmos.staking.v1beta1.Query/HistoricalInfo +/cosmos.staking.v1beta1.Query/Pool +/cosmos.staking.v1beta1.Query/Params +``` + +And the query available from ibc-go is: + +```plaintext +/ibc.core.client.v1.Query/VerifyMembership +``` + +The following code block shows an example of how `MsgModuleQuerySafe` can be used to query the account balance of an account on the host chain. The resulting packet data variable is used to set the `PacketData` of `MsgSendTx`. + +```go +balanceQuery := banktypes.NewQueryBalanceRequest("cosmos1...", "uatom") +queryBz, err := balanceQuery.Marshal() + +// signer of message must be the interchain account on the host +queryMsg := icahosttypes.NewMsgModuleQuerySafe("cosmos2...", []icahosttypes.QueryRequest{ + { + Path: "/cosmos.bank.v1beta1.Query/Balance", + Data: queryBz, + }, +}) + +bz, err := icatypes.SerializeCosmosTx(cdc, []proto.Message{queryMsg}, icatypes.EncodingProtobuf) + +packetData := icatypes.InterchainAccountPacketData{ + Type: icatypes.EXECUTE_TX, + Data: bz, + Memo: "", +} +``` + +## Atomicity + +As the Interchain Accounts module supports the execution of multiple transactions using the Cosmos SDK `Msg` interface, it provides the same atomicity guarantees as Cosmos SDK-based applications, leveraging the [`CacheMultiStore`](https://docs.cosmos.network/main/learn/advanced/store#cachemultistore) architecture provided by the [`Context`](https://docs.cosmos.network/main/learn/advanced/context.html) type. + +This provides atomic execution of transactions when using Interchain Accounts, where state changes are only committed if all `Msg`s succeed. diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/06-parameters.md b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/06-parameters.md new file mode 100644 index 00000000000..5ab4fdd8478 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/06-parameters.md @@ -0,0 +1,65 @@ +--- +title: Parameters +sidebar_label: Parameters +sidebar_position: 6 +slug: /apps/interchain-accounts/parameters +--- + + +# Parameters + +The Interchain Accounts module contains the following on-chain parameters, logically separated for each distinct submodule: + +## Controller Submodule Parameters + +| Name | Type | Default Value | +|------------------------|------|---------------| +| `ControllerEnabled` | bool | `true` | + +### ControllerEnabled + +The `ControllerEnabled` parameter controls a chains ability to service ICS-27 controller specific logic. This includes the sending of Interchain Accounts packet data as well as the following ICS-26 callback handlers: + +- `OnChanOpenInit` +- `OnChanOpenAck` +- `OnChanCloseConfirm` +- `OnAcknowledgementPacket` +- `OnTimeoutPacket` + +## Host Submodule Parameters + +| Name | Type | Default Value | +|------------------------|----------|---------------| +| `HostEnabled` | bool | `true` | +| `AllowMessages` | []string | `["*"]` | + +### HostEnabled + +The `HostEnabled` parameter controls a chains ability to service ICS-27 host specific logic. This includes the following ICS-26 callback handlers: + +- `OnChanOpenTry` +- `OnChanOpenConfirm` +- `OnChanCloseConfirm` +- `OnRecvPacket` + +### AllowMessages + +The `AllowMessages` parameter provides the ability for a chain to limit the types of messages or transactions that hosted interchain accounts are authorized to execute by defining an allowlist using the Protobuf message type URL format. + +For example, a Cosmos SDK-based chain that elects to provide hosted Interchain Accounts with the ability of governance voting and staking delegations will define its parameters as follows: + +```json +"params": { + "host_enabled": true, + "allow_messages": ["/cosmos.staking.v1beta1.MsgDelegate", "/cosmos.gov.v1beta1.MsgVote"] +} +``` + +There is also a special wildcard `"*"` value which allows any type of message to be executed by the interchain account. This must be the only value in the `allow_messages` array. + +```json +"params": { + "host_enabled": true, + "allow_messages": ["*"] +} +``` diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/07-tx-encoding.md b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/07-tx-encoding.md new file mode 100644 index 00000000000..5be03af2f8e --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/07-tx-encoding.md @@ -0,0 +1,58 @@ +--- +title: Transaction Encoding +sidebar_label: Transaction Encoding +sidebar_position: 7 +slug: /apps/interchain-accounts/tx-encoding +--- + +# Transaction Encoding + +When orchestrating an interchain account transaction, which comprises multiple `sdk.Msg` objects represented as `Any` types, the transactions must be encoded as bytes within [`InterchainAccountPacketData`](https://github.com/cosmos/ibc-go/blob/v7.2.0/proto/ibc/applications/interchain_accounts/v1/packet.proto#L21-L26). + +```protobuf +// InterchainAccountPacketData is comprised of a raw transaction, type of transaction and optional memo field. +message InterchainAccountPacketData { + Type type = 1; + bytes data = 2; + string memo = 3; +} +``` + +The `data` field must be encoded as a [`CosmosTx`](https://github.com/cosmos/ibc-go/blob/v7.2.0/proto/ibc/applications/interchain_accounts/v1/packet.proto#L28-L31). + +```protobuf +// CosmosTx contains a list of sdk.Msg's. It should be used when sending transactions to an SDK host chain. +message CosmosTx { + repeated google.protobuf.Any messages = 1; +} +``` + +The encoding method for `CosmosTx` is determined during the channel handshake process. If the channel version [metadata's `encoding` field](https://github.com/cosmos/ibc-go/blob/v7.2.0/proto/ibc/applications/interchain_accounts/v1/metadata.proto#L22) is marked as `proto3`, then `CosmosTx` undergoes protobuf encoding. Conversely, if the field is set to `proto3json`, then [proto3 json](https://protobuf.dev/programming-guides/proto3/#json) encoding takes place, which generates a JSON representation of the protobuf message. + +## Protobuf Encoding + +Protobuf encoding serves as the standard encoding process for `CosmosTx`. This occurs if the channel handshake initiates with an empty channel version metadata or if the `encoding` field explicitly denotes `proto3`. In Golang, the protobuf encoding procedure utilizes the `proto.Marshal` function. Every protobuf autogenerated Golang type comes equipped with a `Marshal` method that can be employed to encode the message. + +## (Protobuf) JSON Encoding + +The proto3 JSON encoding presents an alternative encoding technique for `CosmosTx`. It is selected if the channel handshake begins with the channel version metadata `encoding` field labeled as `proto3json`. In Golang, the Proto3 canonical encoding in JSON is implemented by the `"github.com/cosmos/gogoproto/jsonpb"` package. Within Cosmos SDK, the `ProtoCodec` structure implements the `JSONCodec` interface, leveraging the `jsonpb` package. This method generates a JSON format as follows: + +```json +{ + "messages": [ + { + "@type": "/cosmos.bank.v1beta1.MsgSend", + "from_address": "cosmos1...", + "to_address": "cosmos1...", + "amount": [ + { + "denom": "uatom", + "amount": "1000000" + } + ] + } + ] +} +``` + +Here, the `"messages"` array is populated with transactions. Each transaction is represented as a JSON object with the `@type` field denoting the transaction type and the remaining fields representing the transaction's attributes. diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/08-client.md b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/08-client.md new file mode 100644 index 00000000000..82f00816285 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/08-client.md @@ -0,0 +1,202 @@ +--- +title: Client +sidebar_label: Client +sidebar_position: 8 +slug: /apps/interchain-accounts/client +--- + +# Client + +## CLI + +A user can query and interact with the Interchain Accounts module using the CLI. Use the `--help` flag to discover the available commands: + +```shell +simd query interchain-accounts --help +``` + +> Please not that this section does not document all the available commands, but only the ones that deserved extra documentation that was not possible to fit in the command line documentation. + +### Controller + +A user can query and interact with the controller submodule. + +#### Query + +The `query` commands allow users to query the controller submodule. + +```shell +simd query interchain-accounts controller --help +``` + +#### Transactions + +The `tx` commands allow users to interact with the controller submodule. + +```shell +simd tx interchain-accounts controller --help +``` + +#### `register` + +The `register` command allows users to register an interchain account on a host chain on the provided connection. + +```shell +simd tx interchain-accounts controller register [connection-id] [flags] +``` + +During registration a new channel is set up between controller and host. There are two flags available that influence the channel that is created: + +- `--version` to specify the (JSON-formatted) version string of the channel. For example: `{\"version\":\"ics27-1\",\"encoding\":\"proto3\",\"tx_type\":\"sdk_multi_msg\",\"controller_connection_id\":\"connection-0\",\"host_connection_id\":\"connection-0\"}`. Passing a custom version string is useful if you want to specify, for example, the encoding format of the interchain accounts packet data (either `proto3` or `proto3json`). If not specified the controller submodule will generate a default version string. +- `--ordering` to specify the ordering of the channel. Available options are `order_ordered` and `order_unordered` (default if not specified). + +Example: + +```shell +simd tx interchain-accounts controller register connection-0 --ordering order_ordered --from cosmos1.. +``` + +#### `send-tx` + +The `send-tx` command allows users to send a transaction on the provided connection to be executed using an interchain account on the host chain. + +```shell +simd tx interchain-accounts controller send-tx [connection-id] [path/to/packet_msg.json] +``` + +Example: + +```shell +simd tx interchain-accounts controller send-tx connection-0 packet-data.json --from cosmos1.. +``` + +See below for example contents of `packet-data.json`. The CLI handler will unmarshal the following into `InterchainAccountPacketData` appropriately. + +```json +{ + "type":"TYPE_EXECUTE_TX", + "data":"CqIBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEoEBCkFjb3Ntb3MxNWNjc2hobXAwZ3N4MjlxcHFxNmc0em1sdG5udmdteXU5dWV1YWRoOXkybmM1emowc3psczVndGRkehItY29zbW9zMTBoOXN0YzV2Nm50Z2V5Z2Y1eGY5NDVuanFxNWgzMnI1M3VxdXZ3Gg0KBXN0YWtlEgQxMDAw", + "memo":"" +} +``` + +Note the `data` field is a base64 encoded byte string as per the tx encoding agreed upon during the channel handshake. + +A helper CLI is provided in the host submodule which can be used to generate the packet data JSON using the counterparty chain's binary. See the [`generate-packet-data` command](#generate-packet-data) for an example. + +### Host + +A user can query and interact with the host submodule. + +#### Query + +The `query` commands allow users to query the host submodule. + +```shell +simd query interchain-accounts host --help +``` + +#### Transactions + +The `tx` commands allow users to interact with the controller submodule. + +```shell +simd tx interchain-accounts host --help +``` + +##### `generate-packet-data` + +The `generate-packet-data` command allows users to generate protobuf or proto3 JSON encoded interchain accounts packet data for input message(s). The packet data can then be used with the controller submodule's [`send-tx` command](#send-tx). The `--encoding` flag can be used to specify the encoding format (value must be either `proto3` or `proto3json`); if not specified, the default will be `proto3`. The `--memo` flag can be used to include a memo string in the interchain accounts packet data. + +```shell +simd tx interchain-accounts host generate-packet-data [message] +``` + +Example: + +```shell +simd tx interchain-accounts host generate-packet-data '[{ + "@type":"/cosmos.bank.v1beta1.MsgSend", + "from_address":"cosmos15ccshhmp0gsx29qpqq6g4zmltnnvgmyu9ueuadh9y2nc5zj0szls5gtddz", + "to_address":"cosmos10h9stc5v6ntgeygf5xf945njqq5h32r53uquvw", + "amount": [ + { + "denom": "stake", + "amount": "1000" + } + ] +}]' --memo memo +``` + +The command accepts a single `sdk.Msg` or a list of `sdk.Msg`s that will be encoded into the outputs `data` field. + +Example output: + +```json +{ + "type":"TYPE_EXECUTE_TX", + "data":"CqIBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEoEBCkFjb3Ntb3MxNWNjc2hobXAwZ3N4MjlxcHFxNmc0em1sdG5udmdteXU5dWV1YWRoOXkybmM1emowc3psczVndGRkehItY29zbW9zMTBoOXN0YzV2Nm50Z2V5Z2Y1eGY5NDVuanFxNWgzMnI1M3VxdXZ3Gg0KBXN0YWtlEgQxMDAw", + "memo":"memo" +} +``` + +## gRPC + +A user can query the interchain account module using gRPC endpoints. + +### Controller + +A user can query the controller submodule using gRPC endpoints. + +#### `InterchainAccount` + +The `InterchainAccount` endpoint allows users to query the controller submodule for the interchain account address for a given owner on a particular connection. + +```shell +ibc.applications.interchain_accounts.controller.v1.Query/InterchainAccount +``` + +Example: + +```shell +grpcurl -plaintext \ + -d '{"owner":"cosmos1..","connection_id":"connection-0"}' \ + localhost:9090 \ + ibc.applications.interchain_accounts.controller.v1.Query/InterchainAccount +``` + +#### `Params` + +The `Params` endpoint users to query the current controller submodule parameters. + +```shell +ibc.applications.interchain_accounts.controller.v1.Query/Params +``` + +Example: + +```shell +grpcurl -plaintext \ + localhost:9090 \ + ibc.applications.interchain_accounts.controller.v1.Query/Params +``` + +### Host + +A user can query the host submodule using gRPC endpoints. + +#### `Params` + +The `Params` endpoint users to query the current host submodule parameters. + +```shell +ibc.applications.interchain_accounts.host.v1.Query/Params +``` + +Example: + +```shell +grpcurl -plaintext \ + localhost:9090 \ + ibc.applications.interchain_accounts.host.v1.Query/Params +``` diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/09-active-channels.md b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/09-active-channels.md new file mode 100644 index 00000000000..0845c20ebe6 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/09-active-channels.md @@ -0,0 +1,45 @@ +--- +title: Active Channels +sidebar_label: Active Channels +sidebar_position: 9 +slug: /apps/interchain-accounts/active-channels +--- + +# Understanding Active Channels + +The Interchain Accounts module uses either [ORDERED or UNORDERED](https://github.com/cosmos/ibc/tree/master/spec/core/ics-004-channel-and-packet-semantics#ordering) channels. + +When using `ORDERED` channels, the order of transactions when sending packets from a controller to a host chain is maintained. + +When using `UNORDERED` channels, there is no guarantee that the order of transactions when sending packets from the controller to the host chain is maintained. If no ordering is specified in `MsgRegisterInterchainAccount`, then the default ordering for new ICA channels is `UNORDERED`. + +> A limitation when using ORDERED channels is that when a packet times out the channel will be closed. + +In the case of a channel closing, a controller chain needs to be able to regain access to the interchain account registered on this channel. `Active Channels` enable this functionality. + +When an Interchain Account is registered using `MsgRegisterInterchainAccount`, a new channel is created on a particular port. During the `OnChanOpenAck` and `OnChanOpenConfirm` steps (on controller & host chain respectively) the `Active Channel` for this interchain account is stored in state. + +It is possible to create a new channel using the same controller chain portID if the previously set `Active Channel` is now in a `CLOSED` state. This channel creation can be initialized programmatically by sending a new `MsgChannelOpenInit` message like so: + +```go +msg := channeltypes.NewMsgChannelOpenInit(portID, string(versionBytes), channeltypes.ORDERED, []string{connectionID}, icatypes.HostPortID, authtypes.NewModuleAddress(icatypes.ModuleName).String()) +handler := keeper.msgRouter.Handler(msg) +res, err := handler(ctx, msg) +if err != nil { + return err +} +``` + +Alternatively, any relayer operator may initiate a new channel handshake for this interchain account once the previously set `Active Channel` is in a `CLOSED` state. This is done by initiating the channel handshake on the controller chain using the same portID associated with the interchain account in question. + +It is important to note that once a channel has been opened for a given interchain account, new channels can not be opened for this account until the currently set `Active Channel` is set to `CLOSED`. + +## Future improvements + +Future versions of the ICS-27 protocol and the Interchain Accounts module will likely use a new channel type that provides ordering of packets without the channel closing in the event of a packet timing out, thus removing the need for `Active Channels` entirely. +The following is a list of issues which will provide the infrastructure to make this possible: + +- [IBC Channel Upgrades](https://github.com/cosmos/ibc-go/issues/1599) +- [Implement ORDERED_ALLOW_TIMEOUT logic in 04-channel](https://github.com/cosmos/ibc-go/issues/1661) +- [Add ORDERED_ALLOW_TIMEOUT as supported ordering in 03-connection](https://github.com/cosmos/ibc-go/issues/1662) +- [Allow ICA channels to be opened as ORDERED_ALLOW_TIMEOUT](https://github.com/cosmos/ibc-go/issues/1663) diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/10-legacy/01-auth-modules.md b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/10-legacy/01-auth-modules.md new file mode 100644 index 00000000000..38b0b753c10 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/10-legacy/01-auth-modules.md @@ -0,0 +1,268 @@ +--- +title: Authentication Modules +sidebar_label: Authentication Modules +sidebar_position: 1 +slug: /apps/interchain-accounts/legacy/auth-modules +--- + + +# Building an authentication module + +## Deprecation Notice + +**This document is deprecated and will be removed in future releases**. + +:::note Synopsis +Authentication modules play the role of the `Base Application` as described in [ICS-30 IBC Middleware](https://github.com/cosmos/ibc/tree/master/spec/app/ics-030-middleware), and enable application developers to perform custom logic when working with the Interchain Accounts controller API. +::: + +The controller submodule is used for account registration and packet sending. It executes only logic required of all controllers of interchain accounts. The type of authentication used to manage the interchain accounts remains unspecified. There may exist many different types of authentication which are desirable for different use cases. Thus the purpose of the authentication module is to wrap the controller submodule with custom authentication logic. + +In ibc-go, authentication modules are connected to the controller chain via a middleware stack. The controller submodule is implemented as [middleware](https://github.com/cosmos/ibc/tree/master/spec/app/ics-030-middleware) and the authentication module is connected to the controller submodule as the base application of the middleware stack. To implement an authentication module, the `IBCModule` interface must be fulfilled. By implementing the controller submodule as middleware, any amount of authentication modules can be created and connected to the controller submodule without writing redundant code. + +The authentication module must: + +- Authenticate interchain account owners. +- Track the associated interchain account address for an owner. +- Send packets on behalf of an owner (after authentication). + +## `IBCModule` implementation + +The following `IBCModule` callbacks must be implemented with appropriate custom logic: + +```go +// OnChanOpenInit implements the IBCModule interface +func (im IBCModule) OnChanOpenInit( + ctx sdk.Context, + order channeltypes.Order, + connectionHops []string, + portID string, + channelID string, + counterparty channeltypes.Counterparty, + version string, +) (string, error) { + // perform custom logic + + return version, nil +} + +// OnChanOpenAck implements the IBCModule interface +func (im IBCModule) OnChanOpenAck( + ctx sdk.Context, + portID, + channelID string, + counterpartyVersion string, +) error { + // perform custom logic + + return nil +} + +// OnChanCloseConfirm implements the IBCModule interface +func (im IBCModule) OnChanCloseConfirm( + ctx sdk.Context, + portID, + channelID string, +) error { + // perform custom logic + + return nil +} + +// OnAcknowledgementPacket implements the IBCModule interface +func (im IBCModule) OnAcknowledgementPacket( + ctx sdk.Context, + packet channeltypes.Packet, + acknowledgement []byte, + relayer sdk.AccAddress, +) error { + // perform custom logic + + return nil +} + +// OnTimeoutPacket implements the IBCModule interface. +func (im IBCModule) OnTimeoutPacket( + ctx sdk.Context, + packet channeltypes.Packet, + relayer sdk.AccAddress, +) error { + // perform custom logic + + return nil +} +``` + +The following functions must be defined to fulfill the `IBCModule` interface, but they will never be called by the controller submodule so they may error or panic. That is because in Interchain Accounts, the channel handshake is always initiated on the controller chain and packets are always sent to the host chain and never to the controller chain. + +```go +// OnChanOpenTry implements the IBCModule interface +func (im IBCModule) OnChanOpenTry( + ctx sdk.Context, + order channeltypes.Order, + connectionHops []string, + portID, + channelID string, + counterparty channeltypes.Counterparty, + counterpartyVersion string, +) (string, error) { + panic("UNIMPLEMENTED") +} + +// OnChanOpenConfirm implements the IBCModule interface +func (im IBCModule) OnChanOpenConfirm( + ctx sdk.Context, + portID, + channelID string, +) error { + panic("UNIMPLEMENTED") +} + +// OnChanCloseInit implements the IBCModule interface +func (im IBCModule) OnChanCloseInit( + ctx sdk.Context, + portID, + channelID string, +) error { + panic("UNIMPLEMENTED") +} + +// OnRecvPacket implements the IBCModule interface. A successful acknowledgement +// is returned if the packet data is successfully decoded and the receive application +// logic returns without error. +func (im IBCModule) OnRecvPacket( + ctx sdk.Context, + packet channeltypes.Packet, + relayer sdk.AccAddress, +) ibcexported.Acknowledgement { + panic("UNIMPLEMENTED") +} +``` + +## `OnAcknowledgementPacket` + +Controller chains will be able to access the acknowledgement written into the host chain state once a relayer relays the acknowledgement. +The acknowledgement bytes contain either the response of the execution of the message(s) on the host chain or an error. They will be passed to the auth module via the `OnAcknowledgementPacket` callback. Auth modules are expected to know how to decode the acknowledgement. + +If the controller chain is connected to a host chain using the host module on ibc-go, it may interpret the acknowledgement bytes as follows: + +Begin by unmarshaling the acknowledgement into `sdk.TxMsgData`: + +```go +var ack channeltypes.Acknowledgement +if err := channeltypes.SubModuleCdc.UnmarshalJSON(acknowledgement, &ack); err != nil { + return err +} + +txMsgData := &sdk.TxMsgData{} +if err := proto.Unmarshal(ack.GetResult(), txMsgData); err != nil { + return err +} +``` + +If the `txMsgData.Data` field is non nil, the host chain is using SDK version \<\= v0.45. +The auth module should interpret the `txMsgData.Data` as follows: + +```go +switch len(txMsgData.Data) { +case 0: + // see documentation below for SDK 0.46.x or greater +default: + for _, msgData := range txMsgData.Data { + if err := handler(msgData); err != nil { + return err + } + } +... +} +``` + +A handler will be needed to interpret what actions to perform based on the message type sent. +A router could be used, or more simply a switch statement. + +```go +func handler(msgData sdk.MsgData) error { +switch msgData.MsgType { +case sdk.MsgTypeURL(&banktypes.MsgSend{}): + msgResponse := &banktypes.MsgSendResponse{} + if err := proto.Unmarshal(msgData.Data, msgResponse}; err != nil { + return err + } + + handleBankSendMsg(msgResponse) + +case sdk.MsgTypeURL(&stakingtypes.MsgDelegate{}): + msgResponse := &stakingtypes.MsgDelegateResponse{} + if err := proto.Unmarshal(msgData.Data, msgResponse}; err != nil { + return err + } + + handleStakingDelegateMsg(msgResponse) + +case sdk.MsgTypeURL(&transfertypes.MsgTransfer{}): + msgResponse := &transfertypes.MsgTransferResponse{} + if err := proto.Unmarshal(msgData.Data, msgResponse}; err != nil { + return err + } + + handleIBCTransferMsg(msgResponse) + +default: + return +} +``` + +If the `txMsgData.Data` is empty, the host chain is using SDK version > v0.45. +The auth module should interpret the `txMsgData.Responses` as follows: + +```go +... +// switch statement from above +case 0: + for _, any := range txMsgData.MsgResponses { + if err := handleAny(any); err != nil { + return err + } + } +} +``` + +A handler will be needed to interpret what actions to perform based on the type URL of the Any. +A router could be used, or more simply a switch statement. +It may be possible to deduplicate logic between `handler` and `handleAny`. + +```go +func handleAny(any *codectypes.Any) error { +switch any.TypeURL { +case banktypes.MsgSend: + msgResponse, err := unpackBankMsgSendResponse(any) + if err != nil { + return err + } + + handleBankSendMsg(msgResponse) + +case stakingtypes.MsgDelegate: + msgResponse, err := unpackStakingDelegateResponse(any) + if err != nil { + return err + } + + handleStakingDelegateMsg(msgResponse) + + case transfertypes.MsgTransfer: + msgResponse, err := unpackIBCTransferMsgResponse(any) + if err != nil { + return err + } + + handleIBCTransferMsg(msgResponse) + +default: + return +} +``` + +## Integration into `app.go` file + +To integrate the authentication module into your chain, please follow the steps outlined in [`app.go` integration](02-integration.md#example-integration). diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/10-legacy/02-integration.md b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/10-legacy/02-integration.md new file mode 100644 index 00000000000..ae15c0ae197 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/10-legacy/02-integration.md @@ -0,0 +1,196 @@ +--- +title: Integration +sidebar_label: Integration +sidebar_position: 2 +slug: /apps/interchain-accounts/legacy/integration +--- + + +# Integration + +## Deprecation Notice + +**This document is deprecated and will be removed in future releases**. + +:::note Synopsis +Learn how to integrate Interchain Accounts host and controller functionality to your chain. The following document only applies for Cosmos SDK chains. +::: + +The Interchain Accounts module contains two submodules. Each submodule has its own IBC application. The Interchain Accounts module should be registered as an `AppModule` in the same way all SDK modules are registered on a chain, but each submodule should create its own `IBCModule` as necessary. A route should be added to the IBC router for each submodule which will be used. + +Chains who wish to support ICS-27 may elect to act as a host chain, a controller chain or both. Disabling host or controller functionality may be done statically by excluding the host or controller module entirely from the `app.go` file or it may be done dynamically by taking advantage of the on-chain parameters which enable or disable the host or controller submodules. + +Interchain Account authentication modules are the base application of a middleware stack. The controller submodule is the middleware in this stack. + +![ica-pre-v6.png](./images/ica-pre-v6.png) + +## Example integration + +```go +// app.go + +// Register the AppModule for the Interchain Accounts module and the authentication module +// Note: No `icaauth` exists, this must be substituted with an actual Interchain Accounts authentication module +ModuleBasics = module.NewBasicManager( + ... + ica.AppModuleBasic{}, + icaauth.AppModuleBasic{}, + ... +) + +... + +// Add module account permissions for the Interchain Accounts module +// Only necessary for host chain functionality +// Each Interchain Account created on the host chain is derived from the module account created +maccPerms = map[string][]string{ + ... + icatypes.ModuleName: nil, +} + +... + +// Add Interchain Accounts Keepers for each submodule used and the authentication module +// If a submodule is being statically disabled, the associated Keeper does not need to be added. +type App struct { + ... + + ICAControllerKeeper icacontrollerkeeper.Keeper + ICAHostKeeper icahostkeeper.Keeper + ICAAuthKeeper icaauthkeeper.Keeper + + ... +} + +... + +// Create store keys for each submodule Keeper and the authentication module +keys := sdk.NewKVStoreKeys( + ... + icacontrollertypes.StoreKey, + icahosttypes.StoreKey, + icaauthtypes.StoreKey, + ... +) + +... + + +... + +// Create the Keeper for each submodule +app.ICAControllerKeeper = icacontrollerkeeper.NewKeeper( + appCodec, keys[icacontrollertypes.StoreKey], app.GetSubspace(icacontrollertypes.SubModuleName), + app.IBCKeeper.ChannelKeeper, // may be replaced with middleware such as ics29 fee + app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, + app.MsgServiceRouter(), +) +app.ICAHostKeeper = icahostkeeper.NewKeeper( + appCodec, keys[icahosttypes.StoreKey], app.GetSubspace(icahosttypes.SubModuleName), + app.IBCKeeper.ChannelKeeper, // may be replaced with middleware such as ics29 fee + app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, + app.AccountKeeper, app.MsgServiceRouter(), +) + +// Create Interchain Accounts AppModule +icaModule := ica.NewAppModule(&app.ICAControllerKeeper, &app.ICAHostKeeper) + +// Create your Interchain Accounts authentication module +app.ICAAuthKeeper = icaauthkeeper.NewKeeper(appCodec, keys[icaauthtypes.StoreKey], app.ICAControllerKeeper) + +// ICA auth AppModule +icaAuthModule := icaauth.NewAppModule(appCodec, app.ICAAuthKeeper) + +// ICA auth IBC Module +icaAuthIBCModule := icaauth.NewIBCModule(app.ICAAuthKeeper) + +// Create controller IBC application stack and host IBC module as desired +icaControllerStack := icacontroller.NewIBCMiddlewareWithAuth(icaAuthIBCModule, app.ICAControllerKeeper) +icaHostIBCModule := icahost.NewIBCModule(app.ICAHostKeeper) + +// Register host and authentication routes +ibcRouter. + AddRoute(icacontrollertypes.SubModuleName, icaControllerStack). + AddRoute(icahosttypes.SubModuleName, icaHostIBCModule). + AddRoute(icaauthtypes.ModuleName, icaControllerStack) // Note, the authentication module is routed to the top level of the middleware stack + +... + +// Register Interchain Accounts and authentication module AppModule's +app.moduleManager = module.NewManager( + ... + icaModule, + icaAuthModule, +) + +... + +// Add fee middleware to begin blocker logic +app.moduleManager.SetOrderBeginBlockers( + ... + icatypes.ModuleName, + ... +) + +// Add fee middleware to end blocker logic +app.moduleManager.SetOrderEndBlockers( + ... + icatypes.ModuleName, + ... +) + +// Add Interchain Accounts module InitGenesis logic +app.moduleManager.SetOrderInitGenesis( + ... + icatypes.ModuleName, + ... +) + +// initParamsKeeper init params keeper and its subspaces +func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino, key, tkey sdk.StoreKey) paramskeeper.Keeper { + ... + paramsKeeper.Subspace(icahosttypes.SubModuleName) + paramsKeeper.Subspace(icacontrollertypes.SubModuleName) + ... +``` + +## Using submodules exclusively + +As described above, the Interchain Accounts application module is structured to support the ability of exclusively enabling controller or host functionality. +This can be achieved by simply omitting either controller or host `Keeper` from the Interchain Accounts `NewAppModule` constructor function, and mounting only the desired submodule via the `IBCRouter`. +Alternatively, submodules can be enabled and disabled dynamically using [on-chain parameters](../06-parameters.md). + +The following snippets show basic examples of statically disabling submodules using `app.go`. + +### Disabling controller chain functionality + +```go +// Create Interchain Accounts AppModule omitting the controller keeper +icaModule := ica.NewAppModule(nil, &app.ICAHostKeeper) + +// Create host IBC Module +icaHostIBCModule := icahost.NewIBCModule(app.ICAHostKeeper) + +// Register host route +ibcRouter.AddRoute(icahosttypes.SubModuleName, icaHostIBCModule) +``` + +### Disabling host chain functionality + +```go +// Create Interchain Accounts AppModule omitting the host keeper +icaModule := ica.NewAppModule(&app.ICAControllerKeeper, nil) + +// Create your Interchain Accounts authentication module, setting up the Keeper, AppModule and IBCModule appropriately +app.ICAAuthKeeper = icaauthkeeper.NewKeeper(appCodec, keys[icaauthtypes.StoreKey], app.ICAControllerKeeper) +icaAuthModule := icaauth.NewAppModule(appCodec, app.ICAAuthKeeper) +icaAuthIBCModule := icaauth.NewIBCModule(app.ICAAuthKeeper) + +// Create controller IBC application stack +icaControllerStack := icacontroller.NewIBCMiddlewareWithAuth(icaAuthIBCModule, app.ICAControllerKeeper) + +// Register controller and authentication routes +ibcRouter. + AddRoute(icacontrollertypes.SubModuleName, icaControllerStack). + AddRoute(icaauthtypes.ModuleName, icaControllerStack) // Note, the authentication module is routed to the top level of the middleware stack +``` diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/10-legacy/03-keeper-api.md b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/10-legacy/03-keeper-api.md new file mode 100644 index 00000000000..337ad1f71df --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/10-legacy/03-keeper-api.md @@ -0,0 +1,123 @@ +--- +title: Keeper API +sidebar_label: Keeper API +sidebar_position: 3 +slug: /apps/interchain-accounts/legacy/keeper-api +--- + + +# Keeper API + +## Deprecation Notice + +**This document is deprecated and will be removed in future releases**. + +The controller submodule keeper exposes two legacy functions that allow respectively for custom authentication modules to register interchain accounts and send packets to the interchain account. + +## `RegisterInterchainAccount` + +The authentication module can begin registering interchain accounts by calling `RegisterInterchainAccount`: + +```go +if err := keeper.icaControllerKeeper.RegisterInterchainAccount(ctx, connectionID, owner.String(), version, channeltypes.UNORDERED); err != nil { + return err +} + +return nil +``` + +The `version` argument is used to support ICS-29 fee middleware for relayer incentivization of ICS-27 packets. The `ordering` argument allows to specify the ordering of the channel that is created; if `NONE` is passed, then the default ordering will be `UNORDERED`. Consumers of the `RegisterInterchainAccount` are expected to build the appropriate JSON encoded version string themselves and pass it accordingly. If an empty string is passed in the `version` argument, then the version will be initialized to a default value in the `OnChanOpenInit` callback of the controller's handler, so that channel handshake can proceed. + +The following code snippet illustrates how to construct an appropriate interchain accounts `Metadata` and encode it as a JSON bytestring: + +```go +icaMetadata := icatypes.Metadata{ + Version: icatypes.Version, + ControllerConnectionId: controllerConnectionID, + HostConnectionId: hostConnectionID, + Encoding: icatypes.EncodingProtobuf, + TxType: icatypes.TxTypeSDKMultiMsg, +} + +appVersion, err := icatypes.ModuleCdc.MarshalJSON(&icaMetadata) +if err != nil { + return err +} + +if err := keeper.icaControllerKeeper.RegisterInterchainAccount(ctx, controllerConnectionID, owner.String(), string(appVersion), channeltypes.UNORDERED); err != nil { + return err +} +``` + +Similarly, if the application stack is configured to route through ICS-29 fee middleware and a fee enabled channel is desired, construct the appropriate ICS-29 `Metadata` type: + +```go +icaMetadata := icatypes.Metadata{ + Version: icatypes.Version, + ControllerConnectionId: controllerConnectionID, + HostConnectionId: hostConnectionID, + Encoding: icatypes.EncodingProtobuf, + TxType: icatypes.TxTypeSDKMultiMsg, +} + +appVersion, err := icatypes.ModuleCdc.MarshalJSON(&icaMetadata) +if err != nil { + return err +} + +feeMetadata := feetypes.Metadata{ + AppVersion: string(appVersion), + FeeVersion: feetypes.Version, +} + +feeEnabledVersion, err := feetypes.ModuleCdc.MarshalJSON(&feeMetadata) +if err != nil { + return err +} + +if err := keeper.icaControllerKeeper.RegisterInterchainAccount(ctx, controllerConnectionID, owner.String(), string(feeEnabledVersion), channeltypes.UNORDERED); err != nil { + return err +} +``` + +## `SendTx` + +The authentication module can attempt to send a packet by calling `SendTx`: + +```go +// Authenticate owner +// perform custom logic + +// Construct controller portID based on interchain account owner address +portID, err := icatypes.NewControllerPortID(owner.String()) +if err != nil { + return err +} + +// Obtain data to be sent to the host chain. +// In this example, the owner of the interchain account would like to send a bank MsgSend to the host chain. +// The appropriate serialization function should be called. The host chain must be able to deserialize the transaction. +// If the host chain is using the ibc-go host module, `SerializeCosmosTx` should be used. +msg := &banktypes.MsgSend{FromAddress: fromAddr, ToAddress: toAddr, Amount: amt} +data, err := icatypes.SerializeCosmosTx(keeper.cdc, []proto.Message{msg}) +if err != nil { + return err +} + +// Construct packet data +packetData := icatypes.InterchainAccountPacketData{ + Type: icatypes.EXECUTE_TX, + Data: data, +} + +// Obtain timeout timestamp +// An appropriate timeout timestamp must be determined based on the usage of the interchain account. +// If the packet times out, the channel will be closed requiring a new channel to be created. +timeoutTimestamp := obtainTimeoutTimestamp() + +// Send the interchain accounts packet, returning the packet sequence +seq, err = keeper.icaControllerKeeper.SendTx(ctx, portID, packetData, timeoutTimestamp) +``` + +The data within an `InterchainAccountPacketData` must be serialized using a format supported by the host chain. +If the host chain is using the ibc-go host chain submodule, `SerializeCosmosTx` should be used. If the `InterchainAccountPacketData.Data` is serialized using a format not supported by the host chain, the packet will not be successfully received. diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/10-legacy/_category_.json b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/10-legacy/_category_.json new file mode 100644 index 00000000000..70500795bf8 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/10-legacy/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Legacy", + "position": 10, + "link": null +} diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/10-legacy/images/ica-pre-v6.png b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/10-legacy/images/ica-pre-v6.png new file mode 100644 index 00000000000..acd00d1294b Binary files /dev/null and b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/10-legacy/images/ica-pre-v6.png differ diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/_category_.json b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/_category_.json new file mode 100644 index 00000000000..5ac86ce8ff6 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Interchain Accounts", + "position": 2, + "link": null +} \ No newline at end of file diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/images/ica-v6.png b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/images/ica-v6.png new file mode 100644 index 00000000000..0ffa707c981 Binary files /dev/null and b/docs/versioned_docs/version-v9.0.x/02-apps/02-interchain-accounts/images/ica-v6.png differ diff --git a/docs/versioned_docs/version-v9.0.x/02-apps/_category_.json b/docs/versioned_docs/version-v9.0.x/02-apps/_category_.json new file mode 100644 index 00000000000..fa5fbf0ac9a --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/02-apps/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "IBC Application Modules", + "position": 2, + "link": null +} \ No newline at end of file diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/01-overview.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/01-overview.md new file mode 100644 index 00000000000..e4abc31574e --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/01-overview.md @@ -0,0 +1,95 @@ +--- +title: Overview +sidebar_label: Overview +sidebar_position: 1 +slug: /ibc/light-clients/overview +--- + +# Overview + +:::note Synopsis +Learn how to build IBC light client modules and fulfill the interfaces required to integrate with core IBC. +::: + +:::note + +## Pre-requisite readings + +- [IBC Overview](../../01-ibc/01-overview.md) +- [IBC Transport, Authentication, and Ordering Layer - Clients](https://tutorials.cosmos.network/academy/3-ibc/4-clients.html) +- [ICS-002 Client Semantics](https://github.com/cosmos/ibc/tree/main/spec/core/ics-002-client-semantics) + +::: + +IBC uses light clients in order to provide trust-minimized interoperability between sovereign blockchains. Light clients operate under a strict set of rules which provide security guarantees for state updates and facilitate the ability to verify the state of a remote blockchain using merkle proofs. + +The following aims to provide a high level IBC light client module developer guide. Access to IBC light clients are gated by the core IBC `MsgServer` which utilizes the abstractions set by the `02-client` submodule to call into a light client module. A light client module developer is only required to implement a set of interfaces as defined in the `modules/core/exported` package of ibc-go. + +A light client module developer should be concerned with three main interfaces: + +- [`LightClientModule`](#lightclientmodule) a module which manages many light client instances of a certain type. +- [`ClientState`](#clientstate) encapsulates the light client implementation and its semantics. +- [`ConsensusState`](#consensusstate) tracks consensus data used for verification of client updates, misbehaviour detection and proof verification of counterparty state. +- [`ClientMessage`](#clientmessage) used for submitting block headers for client updates and submission of misbehaviour evidence using conflicting headers. + +Throughout this guide the `07-tendermint` light client module may be referred to as a reference example. + +## Concepts and vocabulary + +### `LightClientModule` + +`LightClientModule` is an interface defined by core IBC which allows for modular light client implementations. All light client implementations *must* implement the [`LightClientModule` interface](https://github.com/cosmos/ibc-go/blob/501a8462345da099144efe91d495bfcfa18d760d/modules/core/exported/client.go#L51) so that core IBC may redirect calls to the light client module. + +For example a light client module may need to: + +- create clients +- update clients +- recover and upgrade clients +- verify membership and non-membership + +The methods which make up this interface are detailed at a more granular level in the [`LightClientModule` section of this guide](02-light-client-module.md). + +Please refer to the `07-tendermint`'s [`LightClientModule` definition](https://github.com/cosmos/ibc-go/blob/501a8462345da099144efe91d495bfcfa18d760d/modules/light-clients/07-tendermint/light_client_module.go#L17) for more information. + +### `ClientState` + +`ClientState` is a term used to define the data structure which encapsulates opaque light client state. The `ClientState` contains all the information needed to verify a `ClientMessage` and perform membership and non-membership proof verification of counterparty state. This includes properties that refer to the remote state machine, the light client type and the specific light client instance. + +For example: + +- Constraints used for client updates. +- Constraints used for misbehaviour detection. +- Constraints used for state verification. +- Constraints used for client upgrades. + +The `ClientState` type maintained within the light client module *must* implement the [`ClientState`](https://github.com/cosmos/ibc-go/tree/02-client-refactor-beta1/modules/core/exported/client.go#L36) interface defined in `core/modules/exported/client.go`. +The methods which make up this interface are detailed at a more granular level in the [`ClientState` section of this guide](03-client-state.md). + +Please refer to the `07-tendermint` light client module's [`ClientState` definition](https://github.com/cosmos/ibc-go/tree/02-client-refactor-beta1/proto/ibc/lightclients/tendermint/v1/tendermint.proto#L18) containing information such as chain ID, status, latest height, unbonding period and proof specifications. + +### `ConsensusState` + +`ConsensusState` is a term used to define the data structure which encapsulates consensus data at a particular point in time, i.e. a unique height or sequence number of a state machine. There must exist a single trusted `ConsensusState` for each height. `ConsensusState` generally contains a trusted root, validator set information and timestamp. + +For example, the `ConsensusState` of the `07-tendermint` light client module defines a trusted root which is used by the `ClientState` to perform verification of membership and non-membership commitment proofs, as well as the next validator set hash used for verifying headers can be trusted in client updates. + +The `ConsensusState` type maintained within the light client module *must* implement the [`ConsensusState`](https://github.com/cosmos/ibc-go/tree/02-client-refactor-beta1/modules/core/exported/client.go#L134) interface defined in `modules/core/exported/client.go`. +The methods which make up this interface are detailed at a more granular level in the [`ConsensusState` section of this guide](04-consensus-state.md). + +### `Height` + +`Height` defines a monotonically increasing sequence number which provides ordering of consensus state data persisted through client updates. +IBC light client module developers are expected to use the [concrete type](https://github.com/cosmos/ibc-go/tree/02-client-refactor-beta1/proto/ibc/core/client/v1/client.proto#L89) provided by the `02-client` submodule. This implements the expectations required by the [`Height`](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/exported/client.go#L156) interface defined in `modules/core/exported/client.go`. + +### `ClientMessage` + +`ClientMessage` refers to the interface type [`ClientMessage`](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/exported/client.go#L147) used for performing updates to a `ClientState` stored on chain. +This may be any concrete type which produces a change in state to the IBC client when verified. + +The following are considered as valid update scenarios: + +- A block header which when verified inserts a new `ConsensusState` at a unique height. +- A batch of block headers which when verified inserts `N` `ConsensusState` instances for `N` unique heights. +- Evidence of misbehaviour provided by two conflicting block headers. + +Learn more in the [Handling update and misbehaviour](05-updates-and-misbehaviour.md) section. diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/02-light-client-module.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/02-light-client-module.md new file mode 100644 index 00000000000..f2025813580 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/02-light-client-module.md @@ -0,0 +1,76 @@ +--- +title: Light Client Module interface +sidebar_label: Light Client Module interface +sidebar_position: 2 +slug: /ibc/light-clients/light-client-module +--- + + +# Implementing the `LightClientModule` interface + +## `Status` method + +`Status` must return the status of the client. + +- An `Active` status indicates that clients are allowed to process packets. +- A `Frozen` status indicates that misbehaviour was detected in the counterparty chain and the client is not allowed to be used. +- An `Expired` status indicates that a client is not allowed to be used because it was not updated for longer than the trusting period. +- An `Unknown` status indicates that there was an error in determining the status of a client. + +All possible `Status` types can be found [here](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/exported/client.go#L22-L32). + +This field is returned in the response of the gRPC [`ibc.core.client.v1.Query/ClientStatus`](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/02-client/types/query.pb.go#L665) endpoint. + +## `TimestampAtHeight` method + +`TimestampAtHeight` must return the timestamp for the consensus state associated with the provided height. +This value is used to facilitate timeouts by checking the packet timeout timestamp against the returned value. + +## `LatestHeight` method + +`LatestHeight` should return the latest block height that the client state represents. + +## `Initialize` method + +Clients must validate the initial consensus state, and set the initial client state and consensus state in the provided client store. +Clients may also store any necessary client-specific metadata. + +`Initialize` is called when a [client is created](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/02-client/keeper/client.go#L30). + +## `UpdateState` method + +`UpdateState` updates and stores as necessary any associated information for an IBC client, such as the `ClientState` and corresponding `ConsensusState`. See section [`UpdateState`](05-updates-and-misbehaviour.md#updatestate) for more information. + +## `UpdateStateOnMisbehaviour` method + +`UpdateStateOnMisbehaviour` should perform appropriate state changes on a client state given that misbehaviour has been detected and verified. See section [`UpdateStateOnMisbehaviour`](05-updates-and-misbehaviour.md#updatestateonmisbehaviour) for more information. + +## `VerifyMembership` method + +`VerifyMembership` must verify the existence of a value at a given commitment path at the specified height. For more information about membership proofs +see the [Existence and non-existence proofs section](07-proofs.md). + +## `VerifyNonMembership` method + +`VerifyNonMembership` must verify the absence of a value at a given commitment path at a specified height. For more information about non-membership proofs +see the [Existence and non-existence proofs section](07-proofs.md). + +## `VerifyClientMessage` method + +`VerifyClientMessage` must verify a `ClientMessage`. A `ClientMessage` could be a `Header`, `Misbehaviour`, or batch update. +It must handle each type of `ClientMessage` appropriately. Calls to `CheckForMisbehaviour`, `UpdateState`, and `UpdateStateOnMisbehaviour` +will assume that the content of the `ClientMessage` has been verified and can be trusted. An error should be returned +if the ClientMessage fails to verify. See section [`VerifyClientMessage`](05-updates-and-misbehaviour.md#verifyclientmessage) for more information. + +## `CheckForMisbehaviour` method + +Checks for evidence of a misbehaviour in `Header` or `Misbehaviour` type. It assumes the `ClientMessage` +has already been verified. See section [`CheckForMisbehaviour`](05-updates-and-misbehaviour.md#checkformisbehaviour) for more information. + +## `RecoverClient` method + +`RecoverClient` is used to recover an expired or frozen client by updating the client with the state of a substitute client. The method must verify that the provided substitute may be used to update the subject client. See section [Implementing `RecoverClient`](./08-proposals.md#implementing-recoverclient) for more information. + +## `VerifyUpgradeAndUpdateState` method + +`VerifyUpgradeAndUpdateState` provides a path to upgrading clients given an upgraded `ClientState`, upgraded `ConsensusState` and proofs for each. See section [Implementing `VerifyUpgradeAndUpdateState`](./06-upgrades.md#implementing-verifyupgradeandupdatestate) for more information. diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/03-client-state.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/03-client-state.md new file mode 100644 index 00000000000..f4545c46fd0 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/03-client-state.md @@ -0,0 +1,21 @@ +--- +title: Client State interface +sidebar_label: Client State interface +sidebar_position: 3 +slug: /ibc/light-clients/client-state +--- + + +# Implementing the `ClientState` interface + +Learn how to implement the [`ClientState`](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/exported/client.go#L36) interface. + +## `ClientType` method + +`ClientType` should return a unique string identifier of the light client. This will be used when generating a client identifier. +The format is created as follows: `{client-type}-{N}` where `{N}` is the unique global nonce associated with a specific client (e.g `07-tendermint-0`). + +## `Validate` method + +`Validate` should validate every client state field and should return an error if any value is invalid. The light client +implementer is in charge of determining which checks are required. See the [Tendermint light client implementation](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/light-clients/07-tendermint/client_state.go#L111) as a reference. diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/04-consensus-state.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/04-consensus-state.md new file mode 100644 index 00000000000..4edc43cb8fa --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/04-consensus-state.md @@ -0,0 +1,27 @@ +--- +title: Consensus State interface +sidebar_label: Consensus State interface +sidebar_position: 4 +slug: /ibc/light-clients/consensus-state +--- + + +# Implementing the `ConsensusState` interface + +A `ConsensusState` is the snapshot of the counterparty chain, that an IBC client uses to verify proofs (e.g. a block). + +The further development of multiple types of IBC light clients and the difficulties presented by this generalization problem (see [ADR-006](https://github.com/cosmos/ibc-go/blob/main/docs/architecture/adr-006-02-client-refactor.md) for more information about this historical context) led to the design decision of each client keeping track of and set its own `ClientState` and `ConsensusState`, as well as the simplification of client `ConsensusState` updates through the generalized `ClientMessage` interface. + +The below [`ConsensusState`](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/exported/client.go#L133) interface is a generalized interface for the types of information a `ConsensusState` could contain. For a reference `ConsensusState` implementation, please see the [Tendermint light client `ConsensusState`](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/light-clients/07-tendermint/consensus_state.go). + +## `ClientType` method + +This is the type of client consensus. It should be the same as the `ClientType` return value for the [corresponding `ClientState` implementation](03-client-state.md). + +## `GetTimestamp` method + +`GetTimestamp` should return the timestamp (in nanoseconds) of the consensus state snapshot. This function has been deprecated and will be removed in a future release. + +## `ValidateBasic` method + +`ValidateBasic` should validate every consensus state field and should return an error if any value is invalid. The light client implementer is in charge of determining which checks are required. diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/05-updates-and-misbehaviour.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/05-updates-and-misbehaviour.md new file mode 100644 index 00000000000..57b92a0fcc1 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/05-updates-and-misbehaviour.md @@ -0,0 +1,104 @@ +--- +title: Handling Updates and Misbehaviour +sidebar_label: Handling Updates and Misbehaviour +sidebar_position: 5 +slug: /ibc/light-clients/updates-and-misbehaviour +--- + + +# Handling `ClientMessage`s: updates and misbehaviour + +As mentioned before in the documentation about [implementing the `ConsensusState` interface](04-consensus-state.md), [`ClientMessage`](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/exported/client.go#L147) is an interface used to update an IBC client. This update may be performed by: + +- a single header, +- a batch of headers, +- evidence of misbehaviour, +- or any type which when verified produces a change to the consensus state of the IBC client. + +This interface has been purposefully kept generic in order to give the maximum amount of flexibility to the light client implementer. + +## Implementing the `ClientMessage` interface + +Find the `ClientMessage` interface in `modules/core/exported`: + +```go +type ClientMessage interface { + proto.Message + + ClientType() string + ValidateBasic() error +} +``` + +The `ClientMessage` will be passed to the client to be used in [`UpdateClient`](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/02-client/keeper/client.go#L48), which retrieves the `LightClientModule` by client type (parsed from the client ID available in `MsgUpdateClient`). This `LightClientModule` implements the [`LightClientModule` interface](02-light-client-module.md) for its specific consenus type (e.g. Tendermint). + +`UpdateClient` will then handle a number of cases including misbehaviour and/or updating the consensus state, utilizing the specific methods defined in the relevant `LightClientModule`. + +```go +VerifyClientMessage(ctx sdk.Context, clientID string, clientMsg ClientMessage) error +CheckForMisbehaviour(ctx sdk.Context, clientID string, clientMsg ClientMessage) bool +UpdateStateOnMisbehaviour(ctx sdk.Context, clientID string, clientMsg ClientMessage) +UpdateState(ctx sdk.Context, clientID string, clientMsg ClientMessage) []Height +``` + +## Handling updates and misbehaviour + +The functions for handling updates to a light client and evidence of misbehaviour are all found in the [`LightClientModule`](https://github.com/cosmos/ibc-go/blob/501a8462345da099144efe91d495bfcfa18d760d/modules/core/exported/client.go#L51) interface, and will be discussed below. + +> It is important to note that `Misbehaviour` in this particular context is referring to misbehaviour on the chain level intended to fool the light client. This will be defined by each light client. + +## `VerifyClientMessage` + +`VerifyClientMessage` must verify a `ClientMessage`. A `ClientMessage` could be a `Header`, `Misbehaviour`, or batch update. To understand how to implement a `ClientMessage`, please refer to the [Implementing the `ClientMessage` interface](#implementing-the-clientmessage-interface) section. + +It must handle each type of `ClientMessage` appropriately. Calls to `CheckForMisbehaviour`, `UpdateState`, and `UpdateStateOnMisbehaviour` will assume that the content of the `ClientMessage` has been verified and can be trusted. An error should be returned if the `ClientMessage` fails to verify. + +For an example of a `VerifyClientMessage` implementation, please check the [Tendermint light client](https://github.com/cosmos/ibc-go/blob/76730ff030b52a351096ee941b7e4da44af9f059/modules/light-clients/07-tendermint/update.go#L23). + +## `CheckForMisbehaviour` + +Checks for evidence of a misbehaviour in `Header` or `Misbehaviour` type. It assumes the `ClientMessage` has already been verified. + +For an example of a `CheckForMisbehaviour` implementation, please check the [Tendermint light client](https://github.com/cosmos/ibc-go/blob/76730ff030b52a351096ee941b7e4da44af9f059/modules/light-clients/07-tendermint/misbehaviour_handle.go#L22). + +> The Tendermint light client [defines `Misbehaviour`](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/light-clients/07-tendermint/misbehaviour.go) as two different types of situations: a situation where two conflicting `Header`s with the same height have been submitted to update a client's `ConsensusState` within the same trusting period, or that the two conflicting `Header`s have been submitted at different heights but the consensus states are not in the correct monotonic time ordering (BFT time violation). More explicitly, updating to a new height must have a timestamp greater than the previous consensus state, or, if inserting a consensus at a past height, then time must be less than those heights which come after and greater than heights which come before. + +## `UpdateStateOnMisbehaviour` + +`UpdateStateOnMisbehaviour` should perform appropriate state changes on a client state given that misbehaviour has been detected and verified. This method should only be called when misbehaviour is detected, as it does not perform any misbehaviour checks. Notably, it should freeze the client so that calling the `Status` function on the associated client state no longer returns `Active`. + +For an example of a `UpdateStateOnMisbehaviour` implementation, please check the [Tendermint light client](https://github.com/cosmos/ibc-go/blob/76730ff030b52a351096ee941b7e4da44af9f059/modules/light-clients/07-tendermint/update.go#L202). + +## `UpdateState` + +`UpdateState` updates and stores as necessary any associated information for an IBC client, such as the `ClientState` and corresponding `ConsensusState`. It should perform a no-op on duplicate updates. + +It assumes the `ClientMessage` has already been verified. + +For an example of a `UpdateState` implementation, please check the [Tendermint light client](https://github.com/cosmos/ibc-go/blob/76730ff030b52a351096ee941b7e4da44af9f059/modules/light-clients/07-tendermint/update.go#L134). + +## Putting it all together + +The `02-client` `Keeper` module in ibc-go offers a reference as to how these functions will be used to [update the client](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/02-client/keeper/client.go#L48). + +```go +clientModule, found := k.router.GetRoute(clientID) +if !found { + return errorsmod.Wrap(types.ErrRouteNotFound, clientID) +} + +if err := clientModule.VerifyClientMessage(ctx, clientID, clientMsg); err != nil { + return err +} + +foundMisbehaviour := clientModule.CheckForMisbehaviour(ctx, clientID, clientMsg) +if foundMisbehaviour { + clientModule.UpdateStateOnMisbehaviour(ctx, clientID, clientMsg) + // emit misbehaviour event + return +} + +clientModule.UpdateState(ctx, clientID, clientMsg) // expects no-op on duplicate header +// emit update event +return +``` diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/06-upgrades.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/06-upgrades.md new file mode 100644 index 00000000000..b0be176ac5a --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/06-upgrades.md @@ -0,0 +1,62 @@ +--- +title: Handling Upgrades +sidebar_label: Handling Upgrades +sidebar_position: 6 +slug: /ibc/light-clients/upgrades +--- + + +# Handling upgrades + +It is vital that high-value IBC clients can upgrade along with their underlying chains to avoid disruption to the IBC ecosystem. Thus, IBC client developers will want to implement upgrade functionality to enable clients to maintain connections and channels even across chain upgrades. + +## Implementing `VerifyUpgradeAndUpdateState` + +The IBC protocol allows client implementations to provide a path to upgrading clients given the upgraded `ClientState`, upgraded `ConsensusState` and proofs for each. This path is provided in the `VerifyUpgradeAndUpdateState` method: + +```go +// NOTE: proof heights are not included as upgrade to a new revision is expected to pass only on the last +// height committed by the current revision. Clients are responsible for ensuring that the planned last +// height of the current revision is somehow encoded in the proof verification process. +// This is to ensure that no premature upgrades occur, since upgrade plans committed to by the counterparty +// may be cancelled or modified before the last planned height. +// If the upgrade is verified, the upgraded client and consensus states must be set in the client store. +func (l LightClientModule) VerifyUpgradeAndUpdateState( + ctx sdk.Context, + clientID string, + newClient []byte, + newConsState []byte, + upgradeClientProof, + upgradeConsensusStateProof []byte, +) error +``` + +> Please refer to the [Tendermint light client implementation](https://github.com/cosmos/ibc-go/blob/47162061bcbfe74df791161059715a635e31c604/modules/light-clients/07-tendermint/light_client_module.go#L257) as an example for implementation. + +It is important to note that light clients **must** handle all management of client and consensus states including the setting of updated `ClientState` and `ConsensusState` in the client store. This can include verifying that the submitted upgraded `ClientState` is of a valid `ClientState` type, that the height of the upgraded client is not greater than the height of the current client (in order to preserve BFT monotonic time), or that certain parameters which should not be changed have not been altered in the upgraded `ClientState`. + +Developers must ensure that the `MsgUpgradeClient` does not pass until the last height of the old chain has been committed, and after the chain upgrades, the `MsgUpgradeClient` should pass once and only once on all counterparty clients. + +### Upgrade path + +Clients should have **prior knowledge of the merkle path** that the upgraded client and upgraded consensus states will use. The height at which the upgrade has occurred should also be encoded in the proof. + +> The Tendermint client implementation accomplishes this by including an `UpgradePath` in the `ClientState` itself, which is used along with the upgrade height to construct the merkle path under which the client state and consensus state are committed. + +## Chain specific vs client specific client parameters + +Developers should maintain the distinction between client parameters that are uniform across every valid light client of a chain (chain-chosen parameters), and client parameters that are customizable by each individual client (client-chosen parameters). + +When upgrading a client, developers must ensure that the new client adopts all of the new client parameters that must be uniform across every valid light client of a chain (chain-chosen parameters), while maintaining the client parameters that are customizable by each individual client (client-chosen parameters) from the previous version of the client. + +## Security + +Upgrades must adhere to the IBC Security Model. IBC does not rely on the assumption of honest relayers for correctness. Thus users should not have to rely on relayers to maintain client correctness and security (though honest relayers must exist to maintain relayer liveness). While relayers may choose any set of client parameters while creating a new `ClientState`, this still holds under the security model since users can always choose a relayer-created client that suits their security and correctness needs or create a client with their desired parameters if no such client exists. + +However, when upgrading an existing client, one must keep in mind that there are already many users who depend on this client's particular parameters. **We cannot give the upgrading relayer free choice over these parameters once they have already been chosen. This would violate the security model** since users who rely on the client would have to rely on the upgrading relayer to maintain the same level of security. + +Thus, developers must make sure that their upgrade mechanism allows clients to upgrade the chain-specified parameters whenever a chain upgrade changes these parameters (examples in the Tendermint client include `UnbondingPeriod`, `TrustingPeriod`, `ChainID`, `UpgradePath`, etc), while ensuring that the relayer submitting the `MsgUpgradeClient` cannot alter the client-chosen parameters that the users are relying upon (examples in Tendermint client include `TrustLevel`, `MaxClockDrift`, etc). + +### Document potential client parameter conflicts during upgrades + +Counterparty clients can upgrade securely by using all of the chain-chosen parameters from the chain-committed `UpgradedClient` and preserving all of the old client-chosen parameters. This enables chains to securely upgrade without relying on an honest relayer, however it can in some cases lead to an invalid final `ClientState` if the new chain-chosen parameters clash with the old client-chosen parameter. This can happen in the Tendermint client case if the upgrading chain lowers the `UnbondingPeriod` (chain-chosen) to a duration below that of a counterparty client's `TrustingPeriod` (client-chosen). Such cases should be clearly documented by developers, so that chains know which upgrades should be avoided to prevent this problem. The final upgraded client should also be validated in `VerifyUpgradeAndUpdateState` before returning to ensure that the client does not upgrade to an invalid `ClientState`. diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/07-proofs.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/07-proofs.md new file mode 100644 index 00000000000..67663baff32 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/07-proofs.md @@ -0,0 +1,71 @@ +--- +title: Existence/Non-Existence Proofs +sidebar_label: Existence/Non-Existence Proofs +sidebar_position: 7 +slug: /ibc/light-clients/proofs +--- + + +# Existence and non-existence proofs + +IBC uses merkle proofs in order to verify the state of a remote counterparty state machine given a trusted root, and [ICS-23](https://github.com/cosmos/ics23/tree/master/go) is a general approach for verifying merkle trees which is used in ibc-go. + +Currently, all Cosmos SDK modules contain their own stores, which maintain the state of the application module in an IAVL (immutable AVL) binary merkle tree format. Specifically with regard to IBC, core IBC maintains its own IAVL store, and IBC apps (e.g. transfer) maintain their own dedicated stores. The Cosmos SDK multistore therefore creates a simple merkle tree of all of these IAVL trees, and from each of these individual IAVL tree root hashes it derives a root hash for the application state tree as a whole (the `AppHash`). + +For the purposes of ibc-go, there are two types of proofs which are important: existence and non-existence proofs, terms which have been used interchangeably with membership and non-membership proofs. For the purposes of this guide, we will stick with "existence" and "non-existence". + +## Existence proofs + +Existence proofs are used in IBC transactions which involve verification of counterparty state for transactions which will result in the writing of provable state. For example, this includes verification of IBC store state for handshakes and packets. + +Put simply, existence proofs prove that a particular key and value exists in the tree. Under the hood, an IBC existence proof is comprised of two proofs: an IAVL proof that the key exists in IBC store/IBC root hash, and a proof that the IBC root hash exists in the multistore root hash. + +## Non-existence proofs + +Non-existence proofs verify the absence of data stored within counterparty state and are used to prove that a key does NOT exist in state. As stated above, these types of proofs can be used to timeout packets by proving that the counterparty has not written a packet receipt into the store, meaning that a token transfer has NOT successfully occurred. + +Some trees (e.g. SMT) may have a sentinel empty child for non-existent keys. In this case, the ICS-23 proof spec should include this `EmptyChild` so that ICS-23 handles the non-existence proof correctly. + +In some cases, there is a necessity to "mock" non-existence proofs if the counterparty does not have ability to prove absence. Since the verification method is designed to give complete control to client implementations, clients can support chains that do not provide absence proofs by verifying the existence of a non-empty sentinel `ABSENCE` value. In these special cases, the proof provided will be an ICS-23 `Existence` proof, and the client will verify that the `ABSENCE` value is stored under the given path for the given height. + +## State verification methods: `VerifyMembership` and `VerifyNonMembership` + +The state verification functions for all IBC data types have been consolidated into two generic methods, `VerifyMembership` and `VerifyNonMembership`. + +From the [`LightClientModule` interface definition](https://github.com/cosmos/ibc-go/blob/main/modules/core/exported/client.go#L56), we find: + +```go +// VerifyMembership is a generic proof verification method which verifies +// a proof of the existence of a value at a given CommitmentPath at the +// specified height. The caller is expected to construct the full CommitmentPath +// from a CommitmentPrefix and a standardized path (as defined in ICS 24). +VerifyMembership( + ctx sdk.Context, + clientID string, + height Height, + delayTimePeriod uint64, + delayBlockPeriod uint64, + proof []byte, + path Path, + value []byte, +) error + +// VerifyNonMembership is a generic proof verification method which verifies +// the absence of a given CommitmentPath at a specified height. The caller is +// expected to construct the full CommitmentPath from a CommitmentPrefix and +// a standardized path (as defined in ICS 24). +VerifyNonMembership( + ctx sdk.Context, + clientStore sdk.KVStore, + cdc codec.BinaryCodec, + height Height, + delayTimePeriod uint64, + delayBlockPeriod uint64, + proof []byte, + path Path, +) error +``` + +Both are expected to be provided with a standardised key path, `exported.Path`, as defined in [ICS-24 host requirements](https://github.com/cosmos/ibc/tree/main/spec/core/ics-024-host-requirements). Membership verification requires callers to provide the value marshalled as `[]byte`. Delay period values should be zero for non-packet processing verification. A zero proof height is now allowed by core IBC and may be passed into `VerifyMembership` and `VerifyNonMembership`. Light clients are responsible for returning an error if a zero proof height is invalid behaviour. + +Please refer to the [ICS-23 implementation](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/23-commitment/types/merkle.go#L131-L205) for a concrete example. diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/08-proposals.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/08-proposals.md new file mode 100644 index 00000000000..1015901ba73 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/08-proposals.md @@ -0,0 +1,36 @@ +--- +title: Handling Proposals +sidebar_label: Handling Proposals +sidebar_position: 8 +slug: /ibc/light-clients/proposals +--- + + +# Handling proposals + +It is possible to update the client with the state of the substitute client through a governance proposal. [This type of governance proposal](../../01-ibc/07-proposals.md) is typically used to recover an expired or frozen client, as it can recover the entire state and therefore all existing channels built on top of the client. `RecoverClient` should be implemented to handle the proposal. + +## Implementing `RecoverClient` + +In the [`LightClientModule` interface](https://github.com/cosmos/ibc-go/blob/501a8462345da099144efe91d495bfcfa18d760d/modules/core/exported/client.go#L51), we find: + +```go +// RecoverClient must verify that the provided substitute +// may be used to update the subject client. The light client +// must set the updated client and consensus states within +// the clientStore for the subject client. +RecoverClient( + ctx sdk.Context, + clientID, + substituteClientID string, +) error +``` + +Prior to updating, this function must verify that: + +- the substitute client is the same type as the subject client. For a reference implementation, please see the [Tendermint light client](https://github.com/cosmos/ibc-go/blob/47162061bcbfe74df791161059715a635e31c604/modules/light-clients/07-tendermint/proposal_handle.go#L34). +- the provided substitute may be used to update the subject client. This may mean that certain parameters must remain unaltered. For example, a [valid substitute Tendermint light client](https://github.com/cosmos/ibc-go/blob/47162061bcbfe74df791161059715a635e31c604/modules/light-clients/07-tendermint/proposal_handle.go#L86) must NOT change the chain ID, trust level, max clock drift, unbonding period, proof specs or upgrade path. Please note that `AllowUpdateAfterMisbehaviour` and `AllowUpdateAfterExpiry` have been deprecated (see ADR 026 for more information). + +After these checks are performed, the function must [set the updated client and consensus states](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/light-clients/07-tendermint/proposal_handle.go#L77) within the client store for the subject client. + +Please refer to the [Tendermint light client implementation](https://github.com/cosmos/ibc-go/blob/47162061bcbfe74df791161059715a635e31c604/modules/light-clients/07-tendermint/proposal_handle.go#L79) for reference. diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/09-setup.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/09-setup.md new file mode 100644 index 00000000000..23ced3cf80a --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/09-setup.md @@ -0,0 +1,135 @@ +--- +title: Setup +sidebar_label: Setup +sidebar_position: 9 +slug: /ibc/light-clients/setup +--- + + +# Setup + +:::note Synopsis +Learn how to configure light client modules and create clients using core IBC and the `02-client` submodule. +::: + +A last step to finish the development of the light client, is to implement the `AppModuleBasic` interface to allow it to be added to the chain's `app.go` alongside other light client types the chain enables. + +Finally, a succinct rundown is given of the remaining steps to make the light client operational, getting the light client type passed through governance and creating the clients. + +## Configuring a light client module + +An IBC light client module must implement the [`AppModuleBasic`](https://github.com/cosmos/cosmos-sdk/blob/main/types/module/module.go#L50) interface in order to register its concrete types against the core IBC interfaces defined in `modules/core/exported`. This is accomplished via the `RegisterInterfaces` method which provides the light client module with the opportunity to register codec types using the chain's `InterfaceRegistry`. Please refer to the [`07-tendermint` codec registration](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/light-clients/07-tendermint/codec.go#L11). + +The `AppModuleBasic` interface may also be leveraged to install custom CLI handlers for light client module users. Light client modules can safely no-op for interface methods which it does not wish to implement. + +Please refer to the [core IBC documentation](../../01-ibc/02-integration.md#integrating-light-clients) for how to configure additional light client modules alongside `07-tendermint` in `app.go`. + +See below for an example of the `07-tendermint` implementation of `AppModuleBasic`. + +```go +var _ module.AppModuleBasic = AppModuleBasic{} + +// AppModuleBasic defines the basic application module used by the tendermint light client. +// Only the RegisterInterfaces function needs to be implemented. All other function perform +// a no-op. +type AppModuleBasic struct{} + +// Name returns the tendermint module name. +func (AppModuleBasic) Name() string { + return ModuleName +} + +// RegisterLegacyAminoCodec performs a no-op. The Tendermint client does not support amino. +func (AppModuleBasic) RegisterLegacyAminoCodec(*codec.LegacyAmino) {} + +// RegisterInterfaces registers module concrete types into protobuf Any. This allows core IBC +// to unmarshal tendermint light client types. +func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) { + RegisterInterfaces(registry) +} + +// DefaultGenesis performs a no-op. Genesis is not supported for the tendermint light client. +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + return nil +} + +// ValidateGenesis performs a no-op. Genesis is not supported for the tendermint light client. +func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error { + return nil +} + +// RegisterGRPCGatewayRoutes performs a no-op. +func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {} + +// GetTxCmd performs a no-op. Please see the 02-client cli commands. +func (AppModuleBasic) GetTxCmd() *cobra.Command { + return nil +} + +// GetQueryCmd performs a no-op. Please see the 02-client cli commands. +func (AppModuleBasic) GetQueryCmd() *cobra.Command { + return nil +} +``` + +## Creating clients + +A client is created by executing a new `MsgCreateClient` transaction composed with a valid `ClientState` and initial `ConsensusState` encoded as protobuf `Any`s. +Generally, this is performed by an off-chain process known as an [IBC relayer](https://github.com/cosmos/ibc/tree/main/spec/relayer/ics-018-relayer-algorithms) however, this is not a strict requirement. + +See below for a list of IBC relayer implementations: + +- [cosmos/relayer](https://github.com/cosmos/relayer) +- [informalsystems/hermes](https://github.com/informalsystems/hermes) +- [confio/ts-relayer](https://github.com/confio/ts-relayer) + +Stateless checks are performed within the [`ValidateBasic`](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/02-client/types/msgs.go#L48) method of `MsgCreateClient`. + +```protobuf +// MsgCreateClient defines a message to create an IBC client +message MsgCreateClient { + option (gogoproto.goproto_getters) = false; + + // light client state + google.protobuf.Any client_state = 1 [(gogoproto.moretags) = "yaml:\"client_state\""]; + // consensus state associated with the client that corresponds to a given + // height. + google.protobuf.Any consensus_state = 2 [(gogoproto.moretags) = "yaml:\"consensus_state\""]; + // signer address + string signer = 3; +} +``` + +Leveraging protobuf `Any` encoding allows core IBC to [unpack](https://github.com/cosmos/ibc-go/blob/47162061bcbfe74df791161059715a635e31c604/modules/core/keeper/msg_server.go#L38) the `ClientState` into its respective interface type registered previously using the light client module's `RegisterInterfaces` method. + +Within the `02-client` submodule, the [`ClientState` is then initialized](https://github.com/cosmos/ibc-go/blob/47162061bcbfe74df791161059715a635e31c604/modules/core/02-client/keeper/client.go#L40-L42) with its own isolated key-value store, namespaced using a unique client identifier. + +In order to successfully create an IBC client using a new client type, it [must be supported](https://github.com/cosmos/ibc-go/blob/v7.0.0/modules/core/02-client/keeper/client.go#L19-L25). Light client support in IBC is gated by on-chain governance. The allow list may be updated by submitting a new governance proposal to update the `02-client` parameter `AllowedClients`. + +See below for example: + +```shell +%s tx gov submit-proposal --from +``` + +where `proposal.json` contains: + +```json +{ + "title": "IBC Clients Param Change", + "summary": "Update allowed clients", + "messages": [ + { + "@type": "/ibc.core.client.v1.MsgUpdateParams", + "signer": "cosmos1...", // The gov module account address + "params": { + "allowed_clients": ["06-solomachine", "07-tendermint", "0x-new-client"] + } + } + ], + "metadata": "AQ==", + "deposit": "100stake" +} +``` + +If the `AllowedClients` list contains a single element that is equal to the wildcard `"*"`, then all client types are allowed and it is thus not necessary to submit a governance proposal to update the parameter. diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/_category_.json b/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/_category_.json new file mode 100644 index 00000000000..9be9c3c3a08 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/01-developer-guide/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Developer Guide", + "position": 1, + "link": null +} \ No newline at end of file diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/02-localhost/01-overview.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/02-localhost/01-overview.md new file mode 100644 index 00000000000..c6754004097 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/02-localhost/01-overview.md @@ -0,0 +1,56 @@ +--- +title: Overview +sidebar_label: Overview +sidebar_position: 1 +slug: /ibc/light-clients/localhost/overview +--- + + +# `09-localhost` + +## Overview + +:::note Synopsis +Learn about the 09-localhost light client module. +::: + +The 09-localhost light client module implements a stateless localhost loopback client with the ability to send and +receive IBC packets to and from the same state machine. + +### Context + +In a multichain environment, application developers will be used to developing cross-chain applications through IBC. +From their point of view, whether or not they are interacting with multiple modules on the same chain or on different +chains should not matter. The localhost client module enables a unified interface to interact with different +applications on a single chain, using the familiar IBC application layer semantics. + +### Implementation + +There exists a localhost light client module which can be invoked with the client identifier `09-localhost`. The light +client is stateless, so the `ClientState` is constructed on demand when required. + +To supplement this, a [sentinel `ConnectionEnd` is stored in core IBC](04-connection.md) state with the connection +identifier `connection-localhost`. This enables IBC applications to create channels directly on top of the sentinel +connection which leverage the 09-localhost loopback functionality. + +[State verification](05-state-verification.md) for channel state in handshakes or processing packets is reduced in +complexity, the `09-localhost` client can simply compare bytes stored under the standardized key paths. + +### Localhost vs *regular* client + +The localhost client aims to provide a unified approach to interacting with applications on a single chain, as the IBC +application layer provides for cross-chain interactions. To achieve this unified interface though, there are a number of +differences under the hood compared to a 'regular' IBC client (excluding `06-solomachine` and `09-localhost` itself). + +The table below lists some important differences: + +| | Regular client | Localhost | +|----------------------------------------------|-----------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------| +| Number of clients | Many instances of a client *type* corresponding to different counterparties | A single sentinel client with the client identifier `09-localhost` | +| Client creation | Relayer (permissionless) | Implicitly made available by the 02-client submodule in core IBC | +| Client updates | Relayer submits headers using `MsgUpdateClient` | No client updates are required as the localhost implementation is stateless | +| Number of connections | Many connections, 1 (or more) per client | A single sentinel connection with the connection identifier `connection-localhost` | +| Connection creation | Connection handshake, provided underlying client | Sentinel `ConnectionEnd` is created and set in store in the `InitGenesis` handler of the 03-connection submodule in core IBC | +| Counterparty | Underlying client, representing another chain | Client with identifier `09-localhost` in same chain | +| `VerifyMembership` and `VerifyNonMembership` | Performs proof verification using consensus state roots | Performs state verification using key-value lookups in the core IBC store | +| `ClientState` storage | `ClientState` stored and directly provable with `VerifyMembership` | Stateless, so `ClientState` is not provable directly with `VerifyMembership` | diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/02-localhost/02-integration.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/02-localhost/02-integration.md new file mode 100644 index 00000000000..e1fc491a332 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/02-localhost/02-integration.md @@ -0,0 +1,19 @@ +--- +title: Integration +sidebar_label: Integration +sidebar_position: 2 +slug: /ibc/light-clients/localhost/integration +--- + + +# Integration + +The 09-localhost light client module registers codec types within the core IBC module. This differs from other light client module implementations which are expected to register codec types using the `AppModuleBasic` interface. + +The localhost client is implicitly enabled by using the `AllowAllClients` wildcard (`"*"`) in the 02-client submodule default value for param [`allowed_clients`](https://github.com/cosmos/ibc-go/blob/v7.0.0/proto/ibc/core/client/v1/client.proto#L102). + +```go +// DefaultAllowedClients are the default clients for the AllowedClients parameter. +// By default it allows all client types. +var DefaultAllowedClients = []string{AllowAllClients} +``` diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/02-localhost/03-client-state.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/02-localhost/03-client-state.md new file mode 100644 index 00000000000..3cbdf05442a --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/02-localhost/03-client-state.md @@ -0,0 +1,10 @@ +--- +title: ClientState +sidebar_label: ClientState +sidebar_position: 3 +slug: /ibc/light-clients/localhost/client-state +--- + +# `ClientState` + +The 09-localhost client is stateless and has no types. diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/02-localhost/04-connection.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/02-localhost/04-connection.md new file mode 100644 index 00000000000..160c814d229 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/02-localhost/04-connection.md @@ -0,0 +1,29 @@ +--- +title: Connection +sidebar_label: Connection +sidebar_position: 4 +slug: /ibc/light-clients/localhost/connection +--- + + +# Localhost connections + +The 09-localhost light client module integrates with core IBC through a single sentinel localhost connection. +The sentinel `ConnectionEnd` is stored by default in the core IBC store. + +This enables channel handshakes to be initiated out of the box by supplying the localhost connection identifier (`connection-localhost`) in the `connectionHops` parameter of `MsgChannelOpenInit`. + +The `ConnectionEnd` is created and set in store via the `InitGenesis` handler of the 03-connection submodule in core IBC. +The `ConnectionEnd` and its `Counterparty` both reference the `09-localhost` client identifier, and share the localhost connection identifier `connection-localhost`. + +```go +// CreateSentinelLocalhostConnection creates and sets the sentinel localhost connection end in the IBC store. +func (k Keeper) CreateSentinelLocalhostConnection(ctx sdk.Context) { + counterparty := types.NewCounterparty(exported.LocalhostClientID, exported.LocalhostConnectionID, commitmenttypes.NewMerklePrefix(k.GetCommitmentPrefix().Bytes())) + connectionEnd := types.NewConnectionEnd(types.OPEN, exported.LocalhostClientID, counterparty, types.GetCompatibleVersions(), 0) + + k.SetConnection(ctx, exported.LocalhostConnectionID, connectionEnd) +} +``` + +Note that connection handshakes are disallowed when using the `09-localhost` client type. diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/02-localhost/05-state-verification.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/02-localhost/05-state-verification.md new file mode 100644 index 00000000000..82d10d6ff40 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/02-localhost/05-state-verification.md @@ -0,0 +1,23 @@ +--- +title: State Verification +sidebar_label: State Verification +sidebar_position: 5 +slug: /ibc/light-clients/localhost/state-verification +--- + +# State verification + +The localhost client handles state verification through the `LightClientModule` interface methods `VerifyMembership` and `VerifyNonMembership` by performing read-only operations directly on the core IBC store. + +When verifying channel state in handshakes or processing packets the `09-localhost` client can simply compare bytes stored under the standardized key paths defined by [ICS-24](https://github.com/cosmos/ibc/tree/main/spec/core/ics-024-host-requirements). + +For existence proofs via `VerifyMembership` the 09-localhost client will retrieve the value stored under the provided key path and compare it against the value provided by the caller. In contrast, non-existence proofs via `VerifyNonMembership` assert the absence of a value at the provided key path. + +Relayers are expected to provide a sentinel proof when sending IBC messages. Submission of nil or empty proofs is disallowed in core IBC messaging. +The 09-localhost light client module defines a `SentinelProof` as a single byte. Localhost client state verification will fail if the sentinel proof value is not provided. + +```go +var SentinelProof = []byte{0x01} +``` + +The `ClientState` of `09-localhost` is stateless, so it is not directly provable with `VerifyMembership` or `VerifyNonMembership`. diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/02-localhost/_category_.json b/docs/versioned_docs/version-v9.0.x/03-light-clients/02-localhost/_category_.json new file mode 100644 index 00000000000..0dc062d29e6 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/02-localhost/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Localhost", + "position": 2, + "link": null +} \ No newline at end of file diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/03-solomachine/01-solomachine.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/03-solomachine/01-solomachine.md new file mode 100644 index 00000000000..394e5ec6efb --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/03-solomachine/01-solomachine.md @@ -0,0 +1,26 @@ +--- +title: Solomachine +sidebar_label: Solomachine +sidebar_position: 1 +slug: /ibc/light-clients/solomachine/solomachine +--- + + +# `solomachine` + +## Abstract + +This paper defines the implementation of the ICS06 protocol on the Cosmos SDK. For the general +specification please refer to the [ICS06 Specification](https://github.com/cosmos/ibc/tree/master/spec/client/ics-006-solo-machine-client). + +This implementation of a solo machine light client supports single and multi-signature public +keys. The client is capable of handling public key updates by header and governance proposals. +The light client is capable of processing client misbehaviour. Proofs of the counterparty state +are generated by the solo machine client by signing over the desired state with a certain sequence, +diversifier, and timestamp. + +## Contents + +1. **[Concepts](02-concepts.md)** +2. **[State](03-state.md)** +3. **[State Transitions](04-state_transitions.md)** diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/03-solomachine/02-concepts.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/03-solomachine/02-concepts.md new file mode 100644 index 00000000000..270dab232a6 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/03-solomachine/02-concepts.md @@ -0,0 +1,168 @@ +--- +title: Concepts +sidebar_label: Concepts +sidebar_position: 2 +slug: /ibc/light-clients/solomachine/concepts +--- + + +# Concepts + +## Client State + +The `ClientState` for a solo machine light client stores the latest sequence, the frozen sequence, +the latest consensus state, and client flag indicating if the client should be allowed to be updated +after a governance proposal. + +If the client is not frozen then the frozen sequence is 0. + +## Consensus State + +The consensus states stores the public key, diversifier, and timestamp of the solo machine light client. + +The diversifier is used to prevent accidental misbehaviour if the same public key is used across +different chains with the same client identifier. It should be unique to the chain the light client +is used on. + +## Public Key + +The public key can be a single public key or a multi-signature public key. The public key type used +must fulfill the tendermint public key interface (this will become the SDK public key interface in the +near future). The public key must be registered on the application codec otherwise encoding/decoding +errors will arise. The public key stored in the consensus state is represented as a protobuf `Any`. +This allows for flexibility in what other public key types can be supported in the future. + +## Counterparty Verification + +The solo machine light client can verify counterparty client state, consensus state, connection state, +channel state, packet commitments, packet acknowledgements, packet receipt absence, +and the next sequence receive. At the end of each successful verification call the light +client sequence number will be incremented. + +Successful verification requires the current public key to sign over the proof. + +## Proofs + +A solo machine proof should verify that the solomachine public key signed +over some specified data. The format for generating marshaled proofs for +the SDK's implementation of solo machine is as follows: + +1. Construct the data using the associated protobuf definition and marshal it. + +For example: + +```go +data := &ClientStateData{ + Path: []byte(path.String()), + ClientState: protoAny, +} + +dataBz, err := cdc.Marshal(data) +``` + +The helper functions `...DataBytes()` in [proof.go](https://github.com/cosmos/ibc-go/blob/main/modules/light-clients/06-solomachine/proof.go) handle this +functionality. + +2. Construct the `SignBytes` and marshal it. + +For example: + +```go +signBytes := &SignBytes{ + Sequence: sequence, + Timestamp: timestamp, + Diversifier: diversifier, + DataType: CLIENT, + Data: dataBz, +} + +signBz, err := cdc.Marshal(signBytes) +``` + +The helper functions `...SignBytes()` in [proof.go](https://github.com/cosmos/ibc-go/blob/main/modules/light-clients/06-solomachine/proof.go) handle this functionality. +The `DataType` field is used to disambiguate what type of data was signed to prevent potential +proto encoding overlap. + +3. Sign the sign bytes. Embed the signatures into either `SingleSignatureData` or `MultiSignatureData`. +Convert the `SignatureData` to proto and marshal it. + +For example: + +```go +sig, err := key.Sign(signBz) +sigData := &signing.SingleSignatureData{ + Signature: sig, +} + +protoSigData := signing.SignatureDataToProto(sigData) +bz, err := cdc.Marshal(protoSigData) +``` + +4. Construct a `TimestampedSignatureData` and marshal it. The marshaled result can be passed in +as the proof parameter to the verification functions. + +For example: + +```go +timestampedSignatureData := &solomachine.TimestampedSignatureData{ + SignatureData: sigData, + Timestamp: solomachine.Time, +} + +proof, err := cdc.Marshal(timestampedSignatureData) +``` + +NOTE: At the end of this process, the sequence associated with the key needs to be updated. +The sequence must be incremented each time proof is generated. + +## Updates By Header + +An update by a header will only succeed if: + +- the header provided is parseable to solo machine header +- the header sequence matches the current sequence +- the header timestamp is greater than or equal to the consensus state timestamp +- the currently registered public key generated the proof + +If the update is successful: + +- the public key is updated +- the diversifier is updated +- the timestamp is updated +- the sequence is incremented by 1 +- the new consensus state is set in the client state + +## Updates By Proposal + +An update by a governance proposal will only succeed if: + +- the substitute provided is parseable to solo machine client state +- the new consensus state public key does not equal the current consensus state public key + +If the update is successful: + +- the subject client state is updated to the substitute client state +- the subject consensus state is updated to the substitute consensus state +- the client is unfrozen (if it was previously frozen) + +NOTE: Previously, `AllowUpdateAfterProposal` was used to signal the update/recovery options for the solo machine client. However, this has now been deprecated because a code migration can overwrite the client and consensus states regardless of the value of this parameter. If governance would vote to overwrite a client or consensus state, it is likely that governance would also be willing to perform a code migration to do the same. + +## Misbehaviour + +Misbehaviour handling will only succeed if: + +- the misbehaviour provided is parseable to solo machine misbehaviour +- the client is not already frozen +- the current public key signed over two unique data messages at the same sequence and diversifier. + +If the misbehaviour is successfully processed: + +- the client is frozen by setting the frozen sequence to the misbehaviour sequence + +NOTE: Misbehaviour processing is data processing order dependent. A misbehaving solo machine +could update to a new public key to prevent being frozen before misbehaviour is submitted. + +## Upgrades + +Upgrades to solo machine light clients are not supported since an entirely different type of +public key can be set using normal client updates. diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/03-solomachine/03-state.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/03-solomachine/03-state.md new file mode 100644 index 00000000000..90d017473c3 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/03-solomachine/03-state.md @@ -0,0 +1,12 @@ +--- +title: State +sidebar_label: State +sidebar_position: 3 +slug: /ibc/light-clients/solomachine/state +--- + + +# State + +The solo machine light client will only store consensus states for each update by a header +or a governance proposal. The latest client state is also maintained in the store. diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/03-solomachine/04-state_transitions.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/03-solomachine/04-state_transitions.md new file mode 100644 index 00000000000..22a456fcc0e --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/03-solomachine/04-state_transitions.md @@ -0,0 +1,43 @@ +--- +title: State Transitions +sidebar_label: State Transitions +sidebar_position: 4 +slug: /ibc/light-clients/solomachine/state_transitions +--- + + +# State Transitions + +## Client State Verification Functions + +Successful state verification by a solo machine light client will result in: + +- the sequence being incremented by 1. + +## Update By Header + +A successful update of a solo machine light client by a header will result in: + +- the public key being updated to the new public key provided by the header. +- the diversifier being updated to the new diviersifier provided by the header. +- the timestamp being updated to the new timestamp provided by the header. +- the sequence being incremented by 1 +- the consensus state being updated (consensus state stores the public key, diversifier, and timestamp) + +## Update By Governance Proposal + +A successful update of a solo machine light client by a governance proposal will result in: + +- the client state being updated to the substitute client state +- the consensus state being updated to the substitute consensus state (consensus state stores the public key, diversifier, and timestamp) +- the frozen sequence being set to zero (client is unfrozen if it was previously frozen). + +## Upgrade + +Client udgrades are not supported for the solo machine light client. No state transition occurs. + +## Misbehaviour + +Successful misbehaviour processing of a solo machine light client will result in: + +- the frozen sequence being set to the sequence the misbehaviour occurred at diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/03-solomachine/_category_.json b/docs/versioned_docs/version-v9.0.x/03-light-clients/03-solomachine/_category_.json new file mode 100644 index 00000000000..de0a6927408 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/03-solomachine/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Solomachine", + "position": 3, + "link": null +} \ No newline at end of file diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/01-overview.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/01-overview.md new file mode 100644 index 00000000000..a41f15e6793 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/01-overview.md @@ -0,0 +1,26 @@ +--- +title: Overview +sidebar_label: Overview +sidebar_position: 1 +slug: /ibc/light-clients/wasm/overview +--- + +# `08-wasm` + +## Overview + +Learn about the `08-wasm` light client proxy module. + +### Context + +Traditionally, light clients used by ibc-go have been implemented only in Go, and since ibc-go v7 (with the release of the 02-client refactor), they are [first-class Cosmos SDK modules](/architecture/adr-010-light-clients-as-sdk-modules). This means that updating existing light client implementations or adding support for new light clients is a multi-step, time-consuming process involving on-chain governance: it is necessary to modify the codebase of ibc-go (if the light client is part of its codebase), re-build chains' binaries, pass a governance proposal and have validators upgrade their nodes. + +### Motivation + +To break the limitation of being able to write light client implementations only in Go, the `08-wasm` adds support to run light clients written in a Wasm-compilable language. The light client byte code implements the entry points of a [CosmWasm](https://docs.cosmwasm.com/docs/) smart contract, and runs inside a Wasm VM. The `08-wasm` module exposes a proxy light client interface that routes incoming messages to the appropriate handler function, inside the Wasm VM, for execution. + +Adding a new light client to a chain is just as simple as submitting a governance proposal with the message that stores the byte code of the light client contract. No coordinated upgrade is needed. When the governance proposal passes and the message is executed, the contract is ready to be instantiated upon receiving a relayer-submitted `MsgCreateClient`. The process of creating a Wasm light client is the same as with a regular light client implemented in Go. + +### Use cases + +- Development of light clients for non-Cosmos ecosystem chains: state machines in other ecosystems are, in many cases, implemented in Rust, and thus there are probably libraries used in their light client implementations for which there is no equivalent in Go. This makes the development of a light client in Go very difficult, but relatively simple to do it in Rust. Therefore, writing a CosmWasm smart contract in Rust that implements the light client algorithm becomes a lower effort. diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/02-concepts.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/02-concepts.md new file mode 100644 index 00000000000..978b77d3c73 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/02-concepts.md @@ -0,0 +1,90 @@ +--- +title: Concepts +sidebar_label: Concepts +sidebar_position: 2 +slug: /ibc/light-clients/wasm/concepts +--- + +# Concepts + +Learn about the differences between a proxy light client and a Wasm light client. + +## Proxy light client + +The `08-wasm` module is not a regular light client in the same sense as, for example, the 07-tendermint light client. `08-wasm` is instead a *proxy* light client module, and this means that the module acts a proxy to the actual implementations of light clients. The module will act as a wrapper for the actual light clients uploaded as Wasm byte code and will delegate all operations to them (i.e. `08-wasm` just passes through the requests to the Wasm light clients). Still, the `08-wasm` module implements all the required interfaces necessary to integrate with core IBC, so that 02-client can call into it as it would for any other light client module. These interfaces are `LightClientModule`, `ClientState`, `ConsensusState` and `ClientMessage`, and we will describe them in the context of `08-wasm` in the following sections. For more information about this set of interfaces, please read section [Overview of the light client module developer guide](../01-developer-guide/01-overview.md#overview). + +### `LightClientModule` + +The `08-wasm`'s `LightClientModule` data structure contains two fields: + +- `keeper` is the `08-wasm` module keeper. +- `storeProvider` encapsulates the IBC core store key and provides access to isolated prefix stores for each client so they can read/write in separate namespaces. + +```go +type LightClientModule struct { + keeper wasmkeeper.Keeper + storeProvider exported.ClientStoreProvider +} +``` + +See section [`LightClientModule` of the light client module developer guide](../01-developer-guide/01-overview.md#lightclientmodule) for more information about the `LightClientModule` interface. + +### `ClientState` + +The `08-wasm`'s `ClientState` data structure contains three fields: + +- `Data` contains the bytes of the Protobuf-encoded client state of the underlying light client implemented as a Wasm contract. For example, if the Wasm light client contract implements the GRANDPA light client algorithm, then `Data` will contain the bytes for a [GRANDPA client state](https://github.com/ComposableFi/composable-ibc/blob/02ce69e2843e7986febdcf795f69a757ce569272/light-clients/ics10-grandpa/src/proto/grandpa.proto#L35-L60). +- `Checksum` is the sha256 hash of the Wasm contract's byte code. This hash is used as an identifier to call the right contract. +- `LatestHeight` is the latest height of the counterparty state machine (i.e. the height of the blockchain), whose consensus state the light client tracks. + +```go +type ClientState struct { + // bytes encoding the client state of the underlying + // light client implemented as a Wasm contract + Data []byte + // sha256 hash of Wasm contract byte code + Checksum []byte + // latest height of the counterparty ledger + LatestHeight types.Height +} +``` + +See section [`ClientState` of the light client module developer guide](../01-developer-guide/01-overview.md#clientstate) for more information about the `ClientState` interface. + +### `ConsensusState` + +The `08-wasm`'s `ConsensusState` data structure maintains one field: + +- `Data` contains the bytes of the Protobuf-encoded consensus state of the underlying light client implemented as a Wasm contract. For example, if the Wasm light client contract implements the GRANDPA light client algorithm, then `Data` will contain the bytes for a [GRANDPA consensus state](https://github.com/ComposableFi/composable-ibc/blob/02ce69e2843e7986febdcf795f69a757ce569272/light-clients/ics10-grandpa/src/proto/grandpa.proto#L87-L94). + +```go +type ConsensusState struct { + // bytes encoding the consensus state of the underlying light client + // implemented as a Wasm contract. + Data []byte +} +``` + +See section [`ConsensusState` of the light client module developer guide](../01-developer-guide/01-overview.md#consensusstate) for more information about the `ConsensusState` interface. + +### `ClientMessage` + +`ClientMessage` is used for performing updates to a `ClientState` stored on chain. The `08-wasm`'s `ClientMessage` data structure maintains one field: + +- `Data` contains the bytes of the Protobuf-encoded header(s) or misbehaviour for the underlying light client implemented as a Wasm contract. For example, if the Wasm light client contract implements the GRANDPA light client algorithm, then `Data` will contain the bytes of either [header](https://github.com/ComposableFi/composable-ibc/blob/02ce69e2843e7986febdcf795f69a757ce569272/light-clients/ics10-grandpa/src/proto/grandpa.proto#L96-L104) or [misbehaviour](https://github.com/ComposableFi/composable-ibc/blob/02ce69e2843e7986febdcf795f69a757ce569272/light-clients/ics10-grandpa/src/proto/grandpa.proto#L106-L112) for a GRANDPA light client. + +```go +type ClientMessage struct { + // bytes encoding the header(s) or misbehaviour for the underlying light client + // implemented as a Wasm contract. + Data []byte +} +``` + +See section [`ClientMessage` of the light client module developer guide](../01-developer-guide/01-overview.md#clientmessage) for more information about the `ClientMessage` interface. + +## Wasm light client + +The actual light client can be implemented in any language that compiles to Wasm and implements the interfaces of a [CosmWasm](https://docs.cosmwasm.com/docs/) contract. Even though in theory other languages could be used, in practice (at least for the time being) the most suitable language to use would be Rust, since there is already good support for it for developing CosmWasm smart contracts. + +At the moment of writing there are two contracts available: one for [Tendermint](https://github.com/ComposableFi/composable-ibc/tree/master/light-clients/ics07-tendermint-cw) and one [GRANDPA](https://github.com/ComposableFi/composable-ibc/tree/master/light-clients/ics10-grandpa-cw) (which is being used in production in [Composable Finance's Centauri bridge](https://github.com/ComposableFi/composable-ibc)). And there are others in development (e.g. for Near). diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/03-integration.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/03-integration.md new file mode 100644 index 00000000000..e005cd5ae4c --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/03-integration.md @@ -0,0 +1,405 @@ +--- +title: Integration +sidebar_label: Integration +sidebar_position: 3 +slug: /ibc/light-clients/wasm/integration +--- + +# Integration + +Learn how to integrate the `08-wasm` module in a chain binary and about the recommended approaches depending on whether the [`x/wasm` module](https://github.com/CosmWasm/wasmd/tree/main/x/wasm) is already used in the chain. The following document only applies for Cosmos SDK chains. + +## Importing the `08-wasm` module + +`08-wasm` has no stable releases yet. To use it, you need to import the git commit that contains the module with the compatible versions of `ibc-go` and `wasmvm`. To do so, run the following command with the desired git commit in your project: + +```sh +go get github.com/cosmos/ibc-go/modules/light-clients/08-wasm@7ee2a2452b79d0bc8316dc622a1243afa058e8cb +``` + +The following table shows the compatibility matrix between the `08-wasm` module, `ibc-go`, and `wasmvm`. + +| **Version** | **Git commit to import** | +|:--------------------------------:|:----------------------------------------:| +| `v0.4.1+ibc-go-v8.4-wasmvm-v2.0` | ccd4dc278e720be87418028026ebd93a80fa5ac0 | +| `v0.3.1+ibc-go-v7.4-wasmvm-v1.5` | 13c071f0b34d67342f0b7a8874d84d2e68b887e1 | + +## `app.go` setup + +The sample code below shows the relevant integration points in `app.go` required to set up the `08-wasm` module in a chain binary. Since `08-wasm` is a light client module itself, please check out as well the section [Integrating light clients](../../01-ibc/02-integration.md#integrating-light-clients) for more information: + +```go +// app.go +import ( + ... + "github.com/cosmos/cosmos-sdk/runtime" + + cmtos "github.com/cometbft/cometbft/libs/os" + + ibcwasm "github.com/cosmos/ibc-go/modules/light-clients/08-wasm" + ibcwasmkeeper "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/keeper" + ibcwasmtypes "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/types" + ... +) + +... + +// Register the AppModule for the 08-wasm module +ModuleBasics = module.NewBasicManager( + ... + ibcwasm.AppModuleBasic{}, + ... +) + +// Add 08-wasm Keeper +type SimApp struct { + ... + WasmClientKeeper ibcwasmkeeper.Keeper + ... +} + +func NewSimApp( + logger log.Logger, + db dbm.DB, + traceStore io.Writer, + loadLatest bool, + appOpts servertypes.AppOptions, + baseAppOptions ...func(*baseapp.BaseApp), +) *SimApp { + ... + keys := sdk.NewKVStoreKeys( + ... + ibcwasmtypes.StoreKey, + ) + + // Instantiate 08-wasm's keeper + // This sample code uses a constructor function that + // accepts a pointer to an existing instance of Wasm VM. + // This is the recommended approach when the chain + // also uses `x/wasm`, and then the Wasm VM instance + // can be shared. + app.WasmClientKeeper = ibcwasmkeeper.NewKeeperWithVM( + appCodec, + runtime.NewKVStoreService(keys[ibcwasmtypes.StoreKey]), + app.IBCKeeper.ClientKeeper, + authtypes.NewModuleAddress(govtypes.ModuleName).String(), + wasmVM, + app.GRPCQueryRouter(), + ) + + wasmLightClientModule := wasm.NewLightClientModule(app.WasmClientKeeper) + app.IBCKeeper.ClientKeeper.AddRoute(ibcwasmtypes.ModuleName, &wasmLightClientModule) + + app.ModuleManager = module.NewManager( + // SDK app modules + ... + ibcwasm.NewAppModule(app.WasmClientKeeper), + ) + app.ModuleManager.SetOrderBeginBlockers( + ... + ibcwasmtypes.ModuleName, + ... + ) + app.ModuleManager.SetOrderEndBlockers( + ... + ibcwasmtypes.ModuleName, + ... + ) + genesisModuleOrder := []string{ + ... + ibcwasmtypes.ModuleName, + ... + } + app.ModuleManager.SetOrderInitGenesis(genesisModuleOrder...) + app.ModuleManager.SetOrderExportGenesis(genesisModuleOrder...) + ... + + // initialize BaseApp + app.SetInitChainer(app.InitChainer) + ... + + // must be before Loading version + if manager := app.SnapshotManager(); manager != nil { + err := manager.RegisterExtensions( + ibcwasmkeeper.NewWasmSnapshotter(app.CommitMultiStore(), &app.WasmClientKeeper), + ) + if err != nil { + panic(fmt.Errorf("failed to register snapshot extension: %s", err)) + } + } + ... + + if loadLatest { + ... + + ctx := app.BaseApp.NewUncachedContext(true, cmtproto.Header{}) + + // Initialize pinned codes in wasmvm as they are not persisted there + if err := app.WasmClientKeeper.InitializePinnedCodes(ctx); err != nil { + cmtos.Exit(fmt.Sprintf("failed initialize pinned codes %s", err)) + } + } +} +``` + +## Keeper instantiation + +When it comes to instantiating `08-wasm`'s keeper, there are two recommended ways of doing it. Choosing one or the other will depend on whether the chain already integrates [`x/wasm`](https://github.com/CosmWasm/wasmd/tree/main/x/wasm) or not. + +### If `x/wasm` is present + +If the chain where the module is integrated uses `x/wasm` then we recommend that both `08-wasm` and `x/wasm` share the same Wasm VM instance. Having two separate Wasm VM instances is still possible, but care should be taken to make sure that both instances do not share the directory when the VM stores blobs and various caches, otherwise unexpected behaviour is likely to happen (from `x/wasm` v0.51 and `08-wasm` v0.2.0+ibc-go-v8.3-wasmvm-v2.0 this will be forbidden anyway, since wasmvm v2.0.0 and above will not allow two different Wasm VM instances to shared the same data folder). + +In order to share the Wasm VM instance, please follow the guideline below. Please note that this requires `x/wasm` v0.41 or above. + +- Instantiate the Wasm VM in `app.go` with the parameters of your choice. +- [Create an `Option` with this Wasm VM instance](https://github.com/CosmWasm/wasmd/blob/db93d7b6c7bb6f4a340d74b96a02cec885729b59/x/wasm/keeper/options.go#L21-L25). +- Add the option created in the previous step to a slice and [pass it to the `x/wasm NewKeeper` constructor function](https://github.com/CosmWasm/wasmd/blob/db93d7b6c7bb6f4a340d74b96a02cec885729b59/x/wasm/keeper/keeper_cgo.go#L36). +- Pass the pointer to the Wasm VM instance to `08-wasm` [`NewKeeperWithVM` constructor function](https://github.com/cosmos/ibc-go/blob/57fcdb9a9a9db9b206f7df2f955866dc4e10fef4/modules/light-clients/08-wasm/keeper/keeper.go#L39-L47). + +The code to set this up would look something like this: + +```go +// app.go +import ( + ... + "github.com/cosmos/cosmos-sdk/runtime" + + wasmvm "github.com/CosmWasm/wasmvm/v2" + wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" + wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" + + ibcwasmkeeper "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/keeper" + ibcwasmtypes "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/types" + ... +) + +... + +// instantiate the Wasm VM with the chosen parameters +wasmer, err := wasmvm.NewVM( + dataDir, + availableCapabilities, + contractMemoryLimit, // default of 32 + contractDebugMode, + memoryCacheSize, +) +if err != nil { + panic(err) +} + +// create an Option slice (or append to an existing one) +// with the option to use a custom Wasm VM instance +wasmOpts = []wasmkeeper.Option{ + wasmkeeper.WithWasmEngine(wasmer), +} + +// the keeper will use the provided Wasm VM instance, +// instead of instantiating a new one +app.WasmKeeper = wasmkeeper.NewKeeper( + appCodec, + keys[wasmtypes.StoreKey], + app.AccountKeeper, + app.BankKeeper, + app.StakingKeeper, + distrkeeper.NewQuerier(app.DistrKeeper), + app.IBCFeeKeeper, // ISC4 Wrapper: fee IBC middleware + app.IBCKeeper.ChannelKeeper, + &app.IBCKeeper.PortKeeper, + scopedWasmKeeper, + app.TransferKeeper, + app.MsgServiceRouter(), + app.GRPCQueryRouter(), + wasmDir, + wasmConfig, + availableCapabilities, + authtypes.NewModuleAddress(govtypes.ModuleName).String(), + wasmOpts..., +) + +app.WasmClientKeeper = ibcwasmkeeper.NewKeeperWithVM( + appCodec, + runtime.NewKVStoreService(keys[ibcwasmtypes.StoreKey]), + app.IBCKeeper.ClientKeeper, + authtypes.NewModuleAddress(govtypes.ModuleName).String(), + wasmer, // pass the Wasm VM instance to `08-wasm` keeper constructor + app.GRPCQueryRouter(), +) +... +``` + +### If `x/wasm` is not present + +If the chain does not use [`x/wasm`](https://github.com/CosmWasm/wasmd/tree/main/x/wasm), even though it is still possible to use the method above from the previous section +(e.g. instantiating a Wasm VM in app.go an pass it to 08-wasm's [`NewKeeperWithVM` constructor function](https://github.com/cosmos/ibc-go/blob/57fcdb9a9a9db9b206f7df2f955866dc4e10fef4/modules/light-clients/08-wasm/keeper/keeper.go#L39-L47), since there would be no need in this case to share the Wasm VM instance with another module, you can use the [`NewKeeperWithConfig` constructor function](https://github.com/cosmos/ibc-go/blob/57fcdb9a9a9db9b206f7df2f955866dc4e10fef4/modules/light-clients/08-wasm/keeper/keeper.go#L88-L96) and provide the Wasm VM configuration parameters of your choice instead. A Wasm VM instance will be created in `NewKeeperWithConfig`. The parameters that can set are: + +- `DataDir` is the [directory for Wasm blobs and various caches](https://github.com/CosmWasm/wasmvm/blob/v2.0.0/lib.go#L25). As an example, in `wasmd` this is set to the [`wasm` folder under the home directory](https://github.com/CosmWasm/wasmd/blob/36416def20effe47fb77f29f5ba35a003970fdba/app/app.go#L578). In the code snippet below we set this field to the `ibc_08-wasm_client_data` folder under the home directory. +- `SupportedCapabilities` is a [list of capabilities supported by the chain](https://github.com/CosmWasm/wasmvm/blob/v2.0.0/lib.go#L26). [`wasmd` sets this to all the available capabilities](https://github.com/CosmWasm/wasmd/blob/36416def20effe47fb77f29f5ba35a003970fdba/app/app.go#L586), but 08-wasm only requires `iterator`. +- `MemoryCacheSize` sets [the size in MiB of an in-memory cache for e.g. module caching](https://github.com/CosmWasm/wasmvm/blob/v2.0.0/lib.go#L29C16-L29C104). It is not consensus-critical and should be defined on a per-node basis, often in the range 100 to 1000 MB. [`wasmd` reads this value of](https://github.com/CosmWasm/wasmd/blob/36416def20effe47fb77f29f5ba35a003970fdba/app/app.go#L579). Default value is 256. +- `ContractDebugMode` is a [flag to enable/disable printing debug logs from the contract to STDOUT](https://github.com/CosmWasm/wasmvm/blob/v2.0.0/lib.go#L28). This should be false in production environments. Default value is false. + +Another configuration parameter of the Wasm VM is the contract memory limit (in MiB), which is [set to 32](https://github.com/cosmos/ibc-go/blob/57fcdb9a9a9db9b206f7df2f955866dc4e10fef4/modules/light-clients/08-wasm/types/config.go#L8), [following the example of `wasmd`](https://github.com/CosmWasm/wasmd/blob/36416def20effe47fb77f29f5ba35a003970fdba/x/wasm/keeper/keeper.go#L32-L34). This parameter is not configurable by users of `08-wasm`. + +The following sample code shows how the keeper would be constructed using this method: + +```go +// app.go +import ( + ... + "github.com/cosmos/cosmos-sdk/runtime" + + ibcwasmkeeper "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/keeper" + ibcwasmtypes "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/types" + ... +) + +... + +// homePath is the path to the directory where the data +// directory for Wasm blobs and caches will be created +wasmConfig := ibcwasmtypes.WasmConfig{ + DataDir: filepath.Join(homePath, "ibc_08-wasm_client_data"), + SupportedCapabilities: []string{"iterator"}, + ContractDebugMode: false, +} +app.WasmClientKeeper = ibcwasmkeeper.NewKeeperWithConfig( + appCodec, + runtime.NewKVStoreService(keys[ibcwasmtypes.StoreKey]), + app.IBCKeeper.ClientKeeper, + authtypes.NewModuleAddress(govtypes.ModuleName).String(), + wasmConfig, + app.GRPCQueryRouter(), +) +``` + +Check out also the [`WasmConfig` type definition](https://github.com/cosmos/ibc-go/blob/57fcdb9a9a9db9b206f7df2f955866dc4e10fef4/modules/light-clients/08-wasm/types/config.go#L21-L31) for more information on each of the configurable parameters. Some parameters allow node-level configurations. There is additionally the function [`DefaultWasmConfig`](https://github.com/cosmos/ibc-go/blob/57fcdb9a9a9db9b206f7df2f955866dc4e10fef4/modules/light-clients/08-wasm/types/config.go#L36-L42) available that returns a configuration with the default values. + +### Options + +The `08-wasm` module comes with an options API inspired by the one in `x/wasm`. +Currently the only option available is the `WithQueryPlugins` option, which allows registration of custom query plugins for the `08-wasm` module. The use of this API is optional and it is only required if the chain wants to register custom query plugins for the `08-wasm` module. + +#### `WithQueryPlugins` + +By default, the `08-wasm` module does not configure any querier options for light client contracts. However, it is possible to register custom query plugins for [`QueryRequest::Custom`](https://github.com/CosmWasm/cosmwasm/blob/v2.0.1/packages/std/src/query/mod.rs#L48) and [`QueryRequest::Stargate`](https://github.com/CosmWasm/cosmwasm/blob/v2.0.1/packages/std/src/query/mod.rs#L57-L65). + +Assuming that the keeper is not yet instantiated, the following sample code shows how to register query plugins for the `08-wasm` module. + +We first construct a [`QueryPlugins`](https://github.com/cosmos/ibc-go/blob/57fcdb9a9a9db9b206f7df2f955866dc4e10fef4/modules/light-clients/08-wasm/types/querier.go#L78-L87) object with the desired query plugins: + +```go +queryPlugins := ibcwasmtypes.QueryPlugins { + Custom: MyCustomQueryPlugin(), + // `myAcceptList` is a `[]string` containing the list of gRPC query paths that the chain wants to allow for the `08-wasm` module to query. + // These queries must be registered in the chain's gRPC query router, be deterministic, and track their gas usage. + // The `AcceptListStargateQuerier` function will return a query plugin that will only allow queries for the paths in the `myAcceptList`. + // The query responses are encoded in protobuf unlike the implementation in `x/wasm`. + Stargate: ibcwasmtypes.AcceptListStargateQuerier(myAcceptList), +} +``` + +Note that the `Stargate` querier appends the user defined accept list of query routes to a default list defined by the `08-wasm` module. +The `defaultAcceptList` defines a single query route: `"/ibc.core.client.v1.Query/VerifyMembership"`. This allows for light client smart contracts to delegate parts of their workflow to other light clients for auxiliary proof verification. For example, proof of inclusion of block and tx data by a data availability provider. + +```go +// defaultAcceptList defines a set of default allowed queries made available to the Querier. +var defaultAcceptList = []string{ + "/ibc.core.client.v1.Query/VerifyMembership", +} +``` + +You may leave any of the fields in the `QueryPlugins` object as `nil` if you do not want to register a query plugin for that query type. + +Then, we pass the `QueryPlugins` object to the `WithQueryPlugins` option: + +```go +querierOption := ibcwasmkeeper.WithQueryPlugins(&queryPlugins) +``` + +Finally, we pass the option to the `NewKeeperWithConfig` or `NewKeeperWithVM` constructor function during [Keeper instantiation](#keeper-instantiation): + +```diff +app.WasmClientKeeper = ibcwasmkeeper.NewKeeperWithConfig( + appCodec, + runtime.NewKVStoreService(keys[ibcwasmtypes.StoreKey]), + app.IBCKeeper.ClientKeeper, + authtypes.NewModuleAddress(govtypes.ModuleName).String(), + wasmConfig, + app.GRPCQueryRouter(), ++ querierOption, +) +``` + +```diff +app.WasmClientKeeper = ibcwasmkeeper.NewKeeperWithVM( + appCodec, + runtime.NewKVStoreService(keys[ibcwasmtypes.StoreKey]), + app.IBCKeeper.ClientKeeper, + authtypes.NewModuleAddress(govtypes.ModuleName).String(), + wasmer, // pass the Wasm VM instance to `08-wasm` keeper constructor + app.GRPCQueryRouter(), ++ querierOption, +) +``` + +## Updating `AllowedClients` + +If the chain's 02-client submodule parameter `AllowedClients` contains the single wildcard `"*"` element, then it is not necessary to do anything in order to allow the creation of `08-wasm` clients. However, if the parameter contains a list of client types (e.g. `["06-solomachine", "07-tendermint"]`), then in order to use the `08-wasm` module chains must update the [`AllowedClients` parameter](https://github.com/cosmos/ibc-go/blob/v8.0.0/proto/ibc/core/client/v1/client.proto#L64) of core IBC. This can be configured directly in the application upgrade handler with the sample code below: + +```go +import ( + ... + ibcwasmtypes "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/types" + ... +) + +... + +func CreateWasmUpgradeHandler( + mm *module.Manager, + configurator module.Configurator, + clientKeeper clientkeeper.Keeper, +) upgradetypes.UpgradeHandler { + return func(ctx context.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { + sdkCtx := sdk.UnwrapSDKContext(ctx) + // explicitly update the IBC 02-client params, adding the wasm client type + params := clientKeeper.GetParams(ctx) + params.AllowedClients = append(params.AllowedClients, ibcwasmtypes.Wasm) + clientKeeper.SetParams(ctx, params) + + return mm.RunMigrations(ctx, configurator, vm) + } +} +``` + +Or alternatively the parameter can be updated via a governance proposal (see at the bottom of section [`Creating clients`](../01-developer-guide/09-setup.md#creating-clients) for an example of how to do this). + +## Adding the module to the store + +As part of the upgrade migration you must also add the module to the upgrades store. + +```go +func (app SimApp) RegisterUpgradeHandlers() { + + ... + + if upgradeInfo.Name == UpgradeName && !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) { + storeUpgrades := storetypes.StoreUpgrades{ + Added: []string{ + ibcwasmtypes.ModuleName, + }, + } + + // configure store loader that checks if version == upgradeHeight and applies store upgrades + app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &storeUpgrades)) + } +} +``` + +## Adding snapshot support + +In order to use the `08-wasm` module chains are required to register the `WasmSnapshotter` extension in the snapshot manager. This snapshotter takes care of persisting the external state, in the form of contract code, of the Wasm VM instance to disk when the chain is snapshotted. [This code](https://github.com/cosmos/ibc-go/blob/57fcdb9a9a9db9b206f7df2f955866dc4e10fef4/modules/light-clients/08-wasm/testing/simapp/app.go#L775-L782) should be placed in `NewSimApp` function in `app.go`. + +## Pin byte codes at start + +Wasm byte codes should be pinned to the WasmVM cache on every application start, therefore [this code](https://github.com/cosmos/ibc-go/blob/57fcdb9a9a9db9b206f7df2f955866dc4e10fef4/modules/light-clients/08-wasm/testing/simapp/app.go#L825-L830) should be placed in `NewSimApp` function in `app.go`. diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/04-messages.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/04-messages.md new file mode 100644 index 00000000000..cbb9571616b --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/04-messages.md @@ -0,0 +1,75 @@ +--- +title: Messages +sidebar_label: Messages +sidebar_position: 4 +slug: /ibc/light-clients/wasm/messages +--- + +# Messages + +## `MsgStoreCode` + +Uploading the Wasm light client contract to the Wasm VM storage is achieved by means of `MsgStoreCode`: + +```go +type MsgStoreCode struct { + // signer address + Signer string + // wasm byte code of light client contract. It can be raw or gzip compressed + WasmByteCode []byte +} +``` + +This message is expected to fail if: + +- `Signer` is an invalid Bech32 address, or it does not match the designated authority address. +- `WasmByteCode` is empty or it exceeds the maximum size, currently set to 3MB. + +Only light client contracts stored using `MsgStoreCode` are allowed to be instantiated. An attempt to create a light client from contracts uploaded via other means (e.g. through `x/wasm` if the module shares the same Wasm VM instance with 08-wasm) will fail. Due to the idempotent nature of the Wasm VM's `StoreCode` function, it is possible to store the same byte code multiple times. + +When execution of `MsgStoreCode` succeeds, the checksum of the contract (i.e. the sha256 hash of the contract's byte code) is stored in an allow list. When a relayer submits [`MsgCreateClient`](https://github.com/cosmos/ibc-go/blob/v8.0.0/proto/ibc/core/client/v1/tx.proto#L25-L37) with 08-wasm's `ClientState`, the client state includes the checksum of the Wasm byte code that should be called. Then 02-client calls [08-wasm's implementation of `Initialize` function](https://github.com/cosmos/ibc-go/blob/06fd8eb5ee1697e3b43be7528a6e42f5e4a4613c/modules/core/02-client/keeper/client.go#L40) (which is an interface function part of `LightClientModule`), and it will check that the checksum in the client state matches one of the checksums in the allow list. If a match is found, the light client is initialized; otherwise, the transaction is aborted. + +## `MsgMigrateContract` + +Migrating a contract to a new Wasm byte code is achieved by means of `MsgMigrateContract`: + +```go +type MsgMigrateContract struct { + // signer address + Signer string + // the client id of the contract + ClientId string + // the SHA-256 hash of the new wasm byte code for the contract + Checksum []byte + // the json-encoded migrate msg to be passed to the contract on migration + Msg []byte +} +``` + +This message is expected to fail if: + +- `Signer` is an invalid Bech32 address, or it does not match the designated authority address. +- `ClientId` is not a valid identifier prefixed by `08-wasm`. +- `Checksum` is not exactly 32 bytes long or it is not found in the list of allowed checksums (a new checksum is added to the list when executing `MsgStoreCode`), or it matches the current checksum of the contract. + +When a Wasm light client contract is migrated to a new Wasm byte code the checksum for the contract will be updated with the new checksum. + +## `MsgRemoveChecksum` + +Removing a checksum from the list of allowed checksums is achieved by means of `MsgRemoveChecksum`: + +```go +type MsgRemoveChecksum struct { + // signer address + Signer string + // Wasm byte code checksum to be removed from the store + Checksum []byte +} +``` + +This message is expected to fail if: + +- `Signer` is an invalid Bech32 address, or it does not match the designated authority address. +- `Checksum` is not exactly 32 bytes long or it is not found in the list of allowed checksums (a new checksum is added to the list when executing `MsgStoreCode`). + +When a checksum is removed from the list of allowed checksums, then the corresponding Wasm byte code will not be available for instantiation in [08-wasm's implementation of `Initialize` function](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/core/02-client/keeper/client.go#L36). diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/05-governance.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/05-governance.md new file mode 100644 index 00000000000..19a0df5d6fb --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/05-governance.md @@ -0,0 +1,126 @@ +--- +title: Governance +sidebar_label: Governance +sidebar_position: 5 +slug: /ibc/light-clients/wasm/governance +--- + +# Governance + +Learn how to upload Wasm light client byte code on a chain, and how to migrate an existing Wasm light client contract. + +## Setting an authority + +Both the storage of Wasm light client byte code as well as the migration of an existing Wasm light client contract are permissioned (i.e. only allowed to an authority such as governance). The designated authority is specified when instantiating `08-wasm`'s keeper: both [`NewKeeperWithVM`](https://github.com/cosmos/ibc-go/blob/57fcdb9a9a9db9b206f7df2f955866dc4e10fef4/modules/light-clients/08-wasm/keeper/keeper.go#L39-L47) and [`NewKeeperWithConfig`](https://github.com/cosmos/ibc-go/blob/57fcdb9a9a9db9b206f7df2f955866dc4e10fef4/modules/light-clients/08-wasm/keeper/keeper.go#L88-L96) constructor functions accept an `authority` argument that must be the address of the authorized actor. For example, in `app.go`, when instantiating the keeper, you can pass the address of the governance module: + +```go +// app.go +import ( + ... + "github.com/cosmos/cosmos-sdk/runtime" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + + ibcwasmkeeper "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/keeper" + ibcwasmtypes "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/types" + ... +) + +// app.go +app.WasmClientKeeper = ibcwasmkeeper.NewKeeperWithVM( + appCodec, + runtime.NewKVStoreService(keys[ibcwasmtypes.StoreKey]), + app.IBCKeeper.ClientKeeper, + authtypes.NewModuleAddress(govtypes.ModuleName).String(), // authority + wasmVM, + app.GRPCQueryRouter(), +) +``` + +## Storing new Wasm light client byte code + + If governance is the allowed authority, the governance v1 proposal that needs to be submitted to upload a new light client contract should contain the message [`MsgStoreCode`](https://github.com/cosmos/ibc-go/blob/57fcdb9a9a9db9b206f7df2f955866dc4e10fef4/proto/ibc/lightclients/wasm/v1/tx.proto#L23-L30) with the base64-encoded byte code of the Wasm contract. Use the following CLI command and JSON as an example: + +```shell +simd tx gov submit-proposal --from +``` + +where `proposal.json` contains: + +```json +{ + "title": "Upload IBC Wasm light client", + "summary": "Upload wasm client", + "messages": [ + { + "@type": "/ibc.lightclients.wasm.v1.MsgStoreCode", + "signer": "cosmos1...", // the authority address (e.g. the gov module account address) + "wasm_byte_code": "YWJ...PUB+" // standard base64 encoding of the Wasm contract byte code + } + ], + "metadata": "AQ==", + "deposit": "100stake" +} +``` + +To learn more about the `submit-proposal` CLI command, please check out [the relevant section in Cosmos SDK documentation](https://docs.cosmos.network/main/modules/gov#submit-proposal). + +Alternatively, the process of submitting the proposal may be simpler if you use the CLI command `store-code`. This CLI command accepts as argument the file of the Wasm light client contract and takes care of constructing the proposal message with `MsgStoreCode` and broadcasting it. See section [`store-code`](./08-client.md#store-code) for more information. + +## Migrating an existing Wasm light client contract + +If governance is the allowed authority, the governance v1 proposal that needs to be submitted to migrate an existing new Wasm light client contract should contain the message [`MsgMigrateContract`](https://github.com/cosmos/ibc-go/blob/57fcdb9a9a9db9b206f7df2f955866dc4e10fef4/proto/ibc/lightclients/wasm/v1/tx.proto#L52-L63) with the checksum of the Wasm byte code to migrate to. Use the following CLI command and JSON as an example: + +```shell +simd tx gov submit-proposal --from +``` + +where `proposal.json` contains: + +```json +{ + "title": "Migrate IBC Wasm light client", + "summary": "Migrate wasm client", + "messages": [ + { + "@type": "/ibc.lightclients.wasm.v1.MsgMigrateContract", + "signer": "cosmos1...", // the authority address (e.g. the gov module account address) + "client_id": "08-wasm-1", // client identifier of the Wasm light client contract that will be migrated + "checksum": "a8ad...4dc0", // SHA-256 hash of the Wasm byte code to migrate to, previously stored with MsgStoreCode + "msg": "{}" // JSON-encoded message to be passed to the contract on migration + } + ], + "metadata": "AQ==", + "deposit": "100stake" +} +``` + +To learn more about the `submit-proposal` CLI command, please check out [the relevant section in Cosmos SDK documentation](https://docs.cosmos.network/main/modules/gov#submit-proposal). + +## Removing an existing checksum + +If governance is the allowed authority, the governance v1 proposal that needs to be submitted to remove a specific checksum from the list of allowed checksums should contain the message [`MsgRemoveChecksum`](https://github.com/cosmos/ibc-go/blob/57fcdb9a9a9db9b206f7df2f955866dc4e10fef4/proto/ibc/lightclients/wasm/v1/tx.proto#L39-L46) with the checksum (of a corresponding Wasm byte code). Use the following CLI command and JSON as an example: + +```shell +simd tx gov submit-proposal --from +``` + +where `proposal.json` contains: + +```json +{ + "title": "Remove checksum of Wasm light client byte code", + "summary": "Remove checksum", + "messages": [ + { + "@type": "/ibc.lightclients.wasm.v1.MsgRemoveChecksum", + "signer": "cosmos1...", // the authority address (e.g. the gov module account address) + "checksum": "a8ad...4dc0", // SHA-256 hash of the Wasm byte code that should be removed from the list of allowed checksums + } + ], + "metadata": "AQ==", + "deposit": "100stake" +} +``` + +To learn more about the `submit-proposal` CLI command, please check out [the relevant section in Cosmos SDK documentation](https://docs.cosmos.network/main/modules/gov#submit-proposal). diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/06-events.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/06-events.md new file mode 100644 index 00000000000..518a3a94c02 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/06-events.md @@ -0,0 +1,26 @@ +--- +title: Events +sidebar_label: Events +sidebar_position: 6 +slug: /ibc/light-clients/wasm/events +--- + +# Events + +The `08-wasm` module emits the following events: + +## `MsgStoreCode` + +| Type | Attribute Key | Attribute Value | +|------------------|----------------|--------------------------| +| store_wasm_code | wasm_checksum | \{hex.Encode(checksum)\} | +| message | module | 08-wasm | + +## `MsgMigrateContract` + +| Type | Attribute Key | Attribute Value | +|------------------|----------------|-----------------------------| +| migrate_contract | client_id | \{clientId\} | +| migrate_contract | wasm_checksum | \{hex.Encode(checksum)\} | +| migrate_contract | new_checksum | \{hex.Encode(newChecksum)\} | +| message | module | 08-wasm | diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/07-contracts.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/07-contracts.md new file mode 100644 index 00000000000..7e88309124b --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/07-contracts.md @@ -0,0 +1,110 @@ +--- +title: Contracts +sidebar_label: Contracts +sidebar_position: 7 +slug: /ibc/light-clients/wasm/contracts +--- + +# Contracts + +Learn about the expected behaviour of Wasm light client contracts and the between with `08-wasm`. + +## API + +The `08-wasm` light client proxy performs calls to the Wasm light client via the Wasm VM. The calls require as input JSON-encoded payload messages that fall in the three categories described in the next sections. + +## `InstantiateMessage` + +This is the message sent to the contract's `instantiate` entry point. It contains the bytes of the protobuf-encoded client and consensus states of the underlying light client, both provided in [`MsgCreateClient`](https://github.com/cosmos/ibc-go/blob/v8.0.0/proto/ibc/core/client/v1/tx.proto#L40-L52). Please note that the bytes contained within the JSON message are represented as base64-encoded strings. + +```go +type InstantiateMessage struct { + ClientState []byte `json:"client_state"` + ConsensusState []byte `json:"consensus_state"` + Checksum []byte `json:"checksum" +} +``` + +The Wasm light client contract is expected to store the client and consensus state in the corresponding keys of the client-prefixed store. + +## `QueryMsg` + +`QueryMsg` acts as a discriminated union type that is used to encode the messages that are sent to the contract's `query` entry point. Only one of the fields of the type should be set at a time, so that the other fields are omitted in the encoded JSON and the payload can be correctly translated to the corresponding element of the enumeration in Rust. + +```go +type QueryMsg struct { + Status *StatusMsg `json:"status,omitempty"` + TimestampAtHeight *TimestampAtHeightMsg `json:"timestamp_at_height,omitempty"` + VerifyClientMessage *VerifyClientMessageMsg `json:"verify_client_message,omitempty"` + CheckForMisbehaviour *CheckForMisbehaviourMsg `json:"check_for_misbehaviour,omitempty"` +} +``` + +```rust +#[cw_serde] +pub enum QueryMsg { + Status(StatusMsg), + TimestampAtHeight(TimestampAtHeightMsg), + VerifyClientMessage(VerifyClientMessageRaw), + CheckForMisbehaviour(CheckForMisbehaviourMsgRaw), +} +``` + +To learn what it is expected from the Wasm light client contract when processing each message, please read the corresponding section of the [Light client developer guide](../01-developer-guide/01-overview.md): + +- For `StatusMsg`, see the section [`Status` method](../01-developer-guide/03-client-state.md#status-method). +- For `TimestampAtHeightMsg`, see the section [`GetTimestampAtHeight` method](../01-developer-guide/03-client-state.md#gettimestampatheight-method). +- For `VerifyClientMessageMsg`, see the section [`VerifyClientMessage`](../01-developer-guide/05-updates-and-misbehaviour.md#verifyclientmessage). +- For `CheckForMisbehaviourMsg`, see the section [`CheckForMisbehaviour` method](../01-developer-guide/03-client-state.md#checkformisbehaviour-method). + +## `SudoMsg` + +`SudoMsg` acts as a discriminated union type that is used to encode the messages that are sent to the contract's `sudo` entry point. Only one of the fields of the type should be set at a time, so that the other fields are omitted in the encoded JSON and the payload can be correctly translated to the corresponding element of the enumeration in Rust. + +The `sudo` entry point is able to perform state-changing writes in the client-prefixed store. + +```go +type SudoMsg struct { + UpdateState *UpdateStateMsg `json:"update_state,omitempty"` + UpdateStateOnMisbehaviour *UpdateStateOnMisbehaviourMsg `json:"update_state_on_misbehaviour,omitempty"` + VerifyUpgradeAndUpdateState *VerifyUpgradeAndUpdateStateMsg `json:"verify_upgrade_and_update_state,omitempty"` + VerifyMembership *VerifyMembershipMsg `json:"verify_membership,omitempty"` + VerifyNonMembership *VerifyNonMembershipMsg `json:"verify_non_membership,omitempty"` + MigrateClientStore *MigrateClientStoreMsg `json:"migrate_client_store,omitempty"` +} +``` + +```rust +#[cw_serde] +pub enum SudoMsg { + UpdateState(UpdateStateMsgRaw), + UpdateStateOnMisbehaviour(UpdateStateOnMisbehaviourMsgRaw), + VerifyUpgradeAndUpdateState(VerifyUpgradeAndUpdateStateMsgRaw), + VerifyMembership(VerifyMembershipMsgRaw), + VerifyNonMembership(VerifyNonMembershipMsgRaw), + MigrateClientStore(MigrateClientStoreMsgRaw), +} +``` + +To learn what it is expected from the Wasm light client contract when processing each message, please read the corresponding section of the [Light client developer guide](../01-developer-guide/01-overview.md): + +- For `UpdateStateMsg`, see the section [`UpdateState`](../01-developer-guide/05-updates-and-misbehaviour.md#updatestate). +- For `UpdateStateOnMisbehaviourMsg`, see the section [`UpdateStateOnMisbehaviour`](../01-developer-guide/05-updates-and-misbehaviour.md#updatestateonmisbehaviour). +- For `VerifyUpgradeAndUpdateStateMsg`, see the section [`GetTimestampAtHeight` method](../01-developer-guide/06-upgrades.md#implementing-verifyupgradeandupdatestate). +- For `VerifyMembershipMsg`, see the section [`VerifyMembership` method](../01-developer-guide/03-client-state.md#verifymembership-method). +- For `VerifyNonMembershipMsg`, see the section [`VerifyNonMembership` method](../01-developer-guide/03-client-state.md#verifynonmembership-method). +- For `MigrateClientStoreMsg`, see the section [Implementing `CheckSubstituteAndUpdateState`](../01-developer-guide/08-proposals.md#implementing-checksubstituteandupdatestate). + +### Migration + +The `08-wasm` proxy light client exposes the `MigrateContract` RPC endpoint that can be used to migrate a given Wasm light client contract (specified by the client identifier) to a new Wasm byte code (specified by the hash of the byte code). The expected use case for this RPC endpoint is to enable contracts to migrate to new byte code in case the current byte code is found to have a bug or vulnerability. The Wasm byte code that contracts are migrated have to be uploaded beforehand using `MsgStoreCode` and must implement the `migrate` entry point. See section[`MsgMigrateContract`](./04-messages.md#msgmigratecontract) for information about the request message for this RPC endpoint. + +## Expected behaviour + +The `08-wasm` proxy light client modules expects the following behaviour from the Wasm light client contracts when executing messages that perform state-changing writes: + +- The contract must not delete the client state from the store. +- The contract must not change the client state to a client state of another type. +- The contract must not change the checksum in the client state. + +Any violation of these rules will result in an error returned from `08-wasm` that will abort the transaction. diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/08-client.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/08-client.md new file mode 100644 index 00000000000..1139d4e2510 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/08-client.md @@ -0,0 +1,151 @@ +--- +title: Client +sidebar_label: Client +sidebar_position: 7 +slug: /ibc/light-clients/wasm/client +--- + +# Client + +## CLI + +A user can query and interact with the `08-wasm` module using the CLI. Use the `--help` flag to discover the available commands: + +### Transactions + +The `tx` commands allow users to interact with the `08-wasm` submodule. + +```shell +simd tx ibc-wasm --help +``` + +#### `store-code` + +The `store-code` command allows users to submit a governance proposal with a `MsgStoreCode` to store the byte code of a Wasm light client contract. + +```shell +simd tx ibc-wasm store-code [path/to/wasm-file] [flags] +``` + +`path/to/wasm-file` is the path to the `.wasm` or `.wasm.gz` file. + +#### `migrate-contract` + +The `migrate-contract` command allows users to broadcast a transaction with a `MsgMigrateContract` to migrate the contract for a given light client to a new byte code denoted by the given checksum. + +```shell +simd tx ibc-wasm migrate-contract [client-id] [checksum] [migrate-msg] +``` + +The migrate message must not be emptied and is expected to be a JSON-encoded string. + +### Query + +The `query` commands allow users to query `08-wasm` state. + +```shell +simd query ibc-wasm --help +``` + +#### `checksums` + +The `checksums` command allows users to query the list of checksums of Wasm light client contracts stored in the Wasm VM via the `MsgStoreCode`. The checksums are hex-encoded. + +```shell +simd query ibc-wasm checksums [flags] +``` + +Example: + +```shell +simd query ibc-wasm checksums +``` + +Example Output: + +```shell +checksums: +- c64f75091a6195b036f472cd8c9f19a56780b9eac3c3de7ced0ec2e29e985b64 +pagination: + next_key: null + total: "1" +``` + +#### `code` + +The `code` command allows users to query the Wasm byte code of a light client contract given the provided input checksum. + +```shell +./simd q ibc-wasm code +``` + +Example: + +```shell +simd query ibc-wasm code c64f75091a6195b036f472cd8c9f19a56780b9eac3c3de7ced0ec2e29e985b64 +``` + +Example Output: + +```shell +code: AGFzb...AqBBE= +``` + +## gRPC + +A user can query the `08-wasm` module using gRPC endpoints. + +### `Checksums` + +The `Checksums` endpoint allows users to query the list of checksums of Wasm light client contracts stored in the Wasm VM via the `MsgStoreCode`. + +```shell +ibc.lightclients.wasm.v1.Query/Checksums +``` + +Example: + +```shell +grpcurl -plaintext \ + -d '{}' \ + localhost:9090 \ + ibc.lightclients.wasm.v1.Query/Checksums +``` + +Example output: + +```shell +{ + "checksums": [ + "c64f75091a6195b036f472cd8c9f19a56780b9eac3c3de7ced0ec2e29e985b64" + ], + "pagination": { + "total": "1" + } +} +``` + +### `Code` + +The `Code` endpoint allows users to query the Wasm byte code of a light client contract given the provided input checksum. + +```shell +ibc.lightclients.wasm.v1.Query/Code +``` + +Example: + +```shell +grpcurl -plaintext \ + -d '{"checksum":"c64f75091a6195b036f472cd8c9f19a56780b9eac3c3de7ced0ec2e29e985b64"}' \ + localhost:9090 \ + ibc.lightclients.wasm.v1.Query/Code +``` + +Example output: + +```shell +{ + "code": AGFzb...AqBBE= +} +``` diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/09-migrations.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/09-migrations.md new file mode 100644 index 00000000000..35c43bd6721 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/09-migrations.md @@ -0,0 +1,239 @@ +--- +title: Migrations +sidebar_label: Migrations +sidebar_position: 9 +slug: /ibc/light-clients/wasm/migrations +--- + +# Migrations + +This guide provides instructions for migrating 08-wasm versions. + +Please note that the following releases are retracted. Please refer to the appropriate migrations section for upgrading. + +```bash +v0.3.1-0.20240717085919-bb71eef0f3bf => v0.3.0+ibc-go-v8.3-wasmvm-v2.0 +v0.2.1-0.20240717085554-570d057959e3 => v0.2.0+ibc-go-v7.6-wasmvm-v1.5 +v0.2.1-0.20240523101951-4b45d1822fb6 => v0.2.0+ibc-go-v8.3-wasmvm-v2.0 +v0.1.2-0.20240412103620-7ee2a2452b79 => v0.1.1+ibc-go-v7.3-wasmvm-v1.5 +v0.1.1-0.20231213092650-57fcdb9a9a9d => v0.1.0+ibc-go-v8.0-wasmvm-v1.5 +v0.1.1-0.20231213092633-b306e7a706e1 => v0.1.0+ibc-go-v7.3-wasmvm-v1.5 +``` + +## From ibc-go v8.4.x to ibc-go v9.0.x + +### Chains + +- The `Initialize`, `Status`, `GetTimestampAtHeight`, `GetLatestHeight`, `VerifyMembership`, `VerifyNonMembership`, `VerifyClientMessage`, `UpdateState` and `UpdateStateOnMisbehaviour` functions in `ClientState` have been removed and all their logic has been moved to functions of the `LightClientModule`. +- The `MigrateContract` function has been removed from `ClientState`. +- The `VerifyMembershipMsg` and `VerifyNonMembershipMsg` payloads for `SudoMsg` have been modified. The `Path` field of both structs has been updated from `v1.MerklePath` to `v2.MerklePath`. The new `v2.MerklePath` field contains a `KeyPath` of `[][]byte` as opposed to `[]string`, see [23-commitment](../../05-migrations/13-v8-to-v9.md#23-commitment). This supports proving values stored under keys which contain non-utf8 encoded symbols. As a result, the JSON field `path` containing `key_path` of both messages will marshal elements as a base64 encoded bytestrings. This is a breaking change for 08-wasm client contracts and they should be migrated to correctly support deserialisation of the `v2.MerklePath` field. +- The `ExportMetadataMsg` struct has been removed and is no longer required for contracts to implement. Core IBC will handle exporting all key/value's written to the store by a light client contract. +- The `ZeroCustomFields` interface function has been removed from the `ClientState` interface. Core IBC only used this function to set tendermint client states when scheduling an IBC software upgrade. The interface function has been replaced by a type assertion. +- The `MaxWasmByteSize` function has been removed in favor of the `MaxWasmSize` constant. +- The `HasChecksum`, `GetAllChecksums` and `Logger` functions have been moved from the `types` package to a method on the `Keeper` type in the `keeper` package. +- The `InitializePinnedCodes` function has been moved to a method on the `Keeper` type in the `keeper` package. +- The `CustomQuerier`, `StargateQuerier` and `QueryPlugins` types have been moved from the `types` package to the `keeper` package. +- The `NewDefaultQueryPlugins`, `AcceptListStargateQuerier` and `RejectCustomQuerier` functions has been moved from the `types` package to the `keeper` package. +- The `NewDefaultQueryPlugins` function signature has changed to take an argument: `queryRouter ibcwasm.QueryRouter`. +- The `AcceptListStargateQuerier` function signature has changed to take an additional argument: `queryRouter ibcwasm.QueryRouter`. +- The `WithQueryPlugins` function signature has changed to take in the `QueryPlugins` type from the `keeper` package (previously from the `types` package). +- The `VMGasRegister` variable has been moved from the `types` package to the `keeper` package. + +## From v0.3.0+ibc-go-v8.3-wasmvm-v2.0 to v0.4.1-ibc-go-v8.4-wasmvm-v2.0 + +### Contract developers + +Contract developers are required to update their JSON API message structure for the `SudoMsg` payloads `VerifyMembershipMsg` and `VerifyNonMembershipMsg`. +The `path` field on both JSON API messages has been renamed to `merkle_path`. + +A migration is required for existing 08-wasm client contracts in order to correctly handle the deserialisation of these fields. + +## From v0.2.0+ibc-go-v7.3-wasmvm-v1.5 to v0.3.1-ibc-go-v7.4-wasmvm-v1.5 + +### Contract developers + +Contract developers are required to update their JSON API message structure for the `SudoMsg` payloads `VerifyMembershipMsg` and `VerifyNonMembershipMsg`. +The `path` field on both JSON API messages has been renamed to `merkle_path`. + +A migration is required for existing 08-wasm client contracts in order to correctly handle the deserialisation of these fields. + +## From v0.2.0+ibc-go-v8.3-wasmvm-v2.0 to v0.3.0-ibc-go-v8.3-wasmvm-v2.0 + +### Contract developers + +The `v0.3.0` release of 08-wasm for ibc-go `v8.3.x` and above introduces a breaking change for client contract developers. + +The contract API `SudoMsg` payloads `VerifyMembershipMsg` and `VerifyNonMembershipMsg` have been modified. +The encoding of the `Path` field of both structs has been updated from `v1.MerklePath` to `v2.MerklePath` to support proving values stored under keys which contain non-utf8 encoded symbols. + +As a result, the `Path` field now contains a `MerklePath` composed of `key_path` of `[][]byte` as opposed to `[]string`. The JSON field `path` containing `key_path` of both `VerifyMembershipMsg` and `VerifyNonMembershipMsg` structs will now marshal elements as base64 encoded bytestrings. See below for example JSON diff. + +```diff +{ + "verify_membership": { + "height": { + "revision_height": 1 + }, + "delay_time_period": 0, + "delay_block_period": 0, + "proof":"dmFsaWQgcHJvb2Y=", + "path": { ++ "key_path":["L2liYw==","L2tleS9wYXRo"] +- "key_path":["/ibc","/key/path"] + }, + "value":"dmFsdWU=" + } +} +``` + +A migration is required for existing 08-wasm client contracts in order to correctly handle the deserialisation of `key_path` from `[]string` to `[][]byte`. +Contract developers should familiarise themselves with the migration path offered by 08-wasm [here](./05-governance.md#migrating-an-existing-wasm-light-client-contract). + +An example of the required changes in a client contract may look like: + +```diff +#[cw_serde] +pub struct MerklePath { ++ pub key_path: Vec, +- pub key_path: Vec, +} +``` + +Please refer to the [`cosmwasm_std`](https://docs.rs/cosmwasm-std/2.0.4/cosmwasm_std/struct.Binary.html) documentation for more information. + +## From v0.1.1+ibc-go-v7.3-wasmvm-v1.5 to v0.2.0-ibc-go-v7.3-wasmvm-v1.5 + +### Contract developers + +The `v0.2.0` release of 08-wasm for ibc-go `v7.6.x` and above introduces a breaking change for client contract developers. + +The contract API `SudoMsg` payloads `VerifyMembershipMsg` and `VerifyNonMembershipMsg` have been modified. +The encoding of the `Path` field of both structs has been updated from `v1.MerklePath` to `v2.MerklePath` to support proving values stored under keys which contain non-utf8 encoded symbols. + +As a result, the `Path` field now contains a `MerklePath` composed of `key_path` of `[][]byte` as opposed to `[]string`. The JSON field `path` containing `key_path` of both `VerifyMembershipMsg` and `VerifyNonMembershipMsg` structs will now marshal elements as base64 encoded bytestrings. See below for example JSON diff. + +```diff +{ + "verify_membership": { + "height": { + "revision_height": 1 + }, + "delay_time_period": 0, + "delay_block_period": 0, + "proof":"dmFsaWQgcHJvb2Y=", + "path": { ++ "key_path":["L2liYw==","L2tleS9wYXRo"] +- "key_path":["/ibc","/key/path"] + }, + "value":"dmFsdWU=" + } +} +``` + +A migration is required for existing 08-wasm client contracts in order to correctly handle the deserialisation of `key_path` from `[]string` to `[][]byte`. +Contract developers should familiarise themselves with the migration path offered by 08-wasm [here](./05-governance.md#migrating-an-existing-wasm-light-client-contract). + +An example of the required changes in a client contract may look like: + +```diff +#[cw_serde] +pub struct MerklePath { ++ pub key_path: Vec, +- pub key_path: Vec, +} +``` + +Please refer to the [`cosmwasm_std`](https://docs.rs/cosmwasm-std/2.0.4/cosmwasm_std/struct.Binary.html) documentation for more information. + +## From ibc-go v7.3.x to ibc-go v8.0.x + +### Chains + +In the 08-wasm versions compatible with ibc-go v7.3.x and above from the v7 release line, the checksums of the uploaded Wasm bytecodes are all stored under a single key. From ibc-go v8.0.x the checksums are stored using [`collections.KeySet`](https://docs.cosmos.network/v0.50/build/packages/collections#keyset), whose full functionality became available in Cosmos SDK v0.50. There is therefore an [automatic migration handler](https://github.com/cosmos/ibc-go/blob/57fcdb9a9a9db9b206f7df2f955866dc4e10fef4/modules/light-clients/08-wasm/module.go#L115-L118) configured in the 08-wasm module to migrate the stored checksums to `collections.KeySet`. + +## From v0.1.0+ibc-go-v8.0-wasmvm-v1.5 to v0.2.0-ibc-go-v8.3-wasmvm-v2.0 + +The `WasmEngine` interface has been updated to reflect changes in the function signatures of Wasm VM: + +```diff +type WasmEngine interface { +- StoreCode(code wasmvm.WasmCode) (wasmvm.Checksum, error) ++ StoreCode(code wasmvm.WasmCode, gasLimit uint64) (wasmvmtypes.Checksum, uint64, error) + + StoreCodeUnchecked(code wasmvm.WasmCode) (wasmvm.Checksum, error) + + Instantiate( + checksum wasmvm.Checksum, + env wasmvmtypes.Env, + info wasmvmtypes.MessageInfo, + initMsg []byte, + store wasmvm.KVStore, + goapi wasmvm.GoAPI, + querier wasmvm.Querier, + gasMeter wasmvm.GasMeter, + gasLimit uint64, + deserCost wasmvmtypes.UFraction, +- ) (*wasmvmtypes.Response, uint64, error) ++ ) (*wasmvmtypes.ContractResult, uint64, error) + + Query( + checksum wasmvm.Checksum, + env wasmvmtypes.Env, + queryMsg []byte, + store wasmvm.KVStore, + goapi wasmvm.GoAPI, + querier wasmvm.Querier, + gasMeter wasmvm.GasMeter, + gasLimit uint64, + deserCost wasmvmtypes.UFraction, +- ) ([]byte, uint64, error) ++ ) (*wasmvmtypes.QueryResult, uint64, error) + + Migrate( + checksum wasmvm.Checksum, + env wasmvmtypes.Env, + migrateMsg []byte, + store wasmvm.KVStore, + goapi wasmvm.GoAPI, + querier wasmvm.Querier, + gasMeter wasmvm.GasMeter, + gasLimit uint64, + deserCost wasmvmtypes.UFraction, +- ) (*wasmvmtypes.Response, uint64, error) ++ ) (*wasmvmtypes.ContractResult, uint64, error) + + Sudo( + checksum wasmvm.Checksum, + env wasmvmtypes.Env, + sudoMsg []byte, + store wasmvm.KVStore, + goapi wasmvm.GoAPI, + querier wasmvm.Querier, + gasMeter wasmvm.GasMeter, + gasLimit uint64, + deserCost wasmvmtypes.UFraction, +- ) (*wasmvmtypes.Response, uint64, error) ++ ) (*wasmvmtypes.ContractResult, uint64, error) + + GetCode(checksum wasmvm.Checksum) (wasmvm.WasmCode, error) + + Pin(checksum wasmvm.Checksum) error + + Unpin(checksum wasmvm.Checksum) error +} +``` + +Similar changes were required in the functions of `MockWasmEngine` interface. + +### Chains + +The `SupportedCapabilities` field of `WasmConfig` is now of type `[]string`: + +```diff +type WasmConfig struct { + DataDir string +- SupportedCapabilities string ++ SupportedCapabilities []string + ContractDebugMode bool +} +``` diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/_category_.json b/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/_category_.json new file mode 100644 index 00000000000..6dc3d24d11a --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/04-wasm/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Wasm", + "position": 4, + "link": null +} \ No newline at end of file diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/05-tendermint/01-overview.md b/docs/versioned_docs/version-v9.0.x/03-light-clients/05-tendermint/01-overview.md new file mode 100644 index 00000000000..1a09c64e79f --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/05-tendermint/01-overview.md @@ -0,0 +1,167 @@ +--- +title: Overview +sidebar_label: Overview +sidebar_position: 1 +slug: /ibc/light-clients/tendermint/overview +--- + +# `07-tendermint` + +## Overview + +:::note Synopsis +Learn about the 07-tendermint light client module. +::: + +The Tendermint client is the first and most deployed light client in IBC. It implements the IBC [light client module interface](https://github.com/cosmos/ibc-go/blob/v9.0.0-beta.1/modules/core/exported/client.go#L41-L123) to track a counterparty running [CometBFT](https://github.com/cometbft/cometbft) consensus. + +:::note +Tendermint is the old name of CometBFT which has been retained in IBC to avoid expensive migration costs. +::: + +The Tendermint client consists of two important structs that keep track of the state of the counterparty chain and allow for future updates. The `ClientState` struct contains all the parameters necessary for CometBFT header verification. The `ConsensusState`, on the other hand, is a compressed view of a particular header of the counterparty chain. Unlike off chain light clients, IBC does not store full header. Instead it stores only the information it needs to prove verification of key/value pairs in the counterparty state (i.e. the header `AppHash`), and the information necessary to use the consensus state as the next root of trust to add a new consensus state to the client (i.e. the header `NextValidatorsHash` and `Timestamp`). The relayer provides the full trusted header on `UpdateClient`, which will get checked against the compressed root-of-trust consensus state. If the trusted header matches a previous consensus state, and the trusted header and new header pass the CometBFT light client update algorithm, then the new header is compressed into a consensus state and added to the IBC client. + +Each Tendermint Client is composed of a single `ClientState` keyed on the client ID, and multiple consensus states which are keyed on both the clientID and header height. Relayers can use the consensus states to verify merkle proofs of packet commitments, acknowledgements, and receipts against the `AppHash` of the counterparty chain in order to enable verified packet flow. + +If a counterparty chain violates the CometBFT protocol in a way that is detectable to off-chain light clients, this misbehaviour can also be submitted to an IBC client by any off-chain actor. Upon verification of this misbehaviour, the Tendermint IBC Client will freeze, preventing any further packet flow from this malicious chain from occurring. Governance or some other out-of-band protocol may then be used to unwind any damage that has already occurred. + +## Initialization + +The Tendermint light client is initialized with a `ClientState` that contains parameters necessary for CometBFT header verification along with a latest height and `ConsensusState` that encapsulates the application state root of a trusted header that will serve to verify future incoming headers from the counterparty. + +```proto +message ClientState { + // human readable chain-id that will be included in header + // and signed over by the validator set + string chain_id = 1; + // trust level is the fraction of the trusted validator set + // that must sign over a new untrusted header before it is accepted + // it can be a minimum of 1/3 and a maximum of 2/3 + // Note these are the bounds of liveness. 1/3 is the minimum + // honest stake needed to maintain liveness on a chain, + // requiring more than 2/3 to sign over the new header would + // break the BFT threshold of allowing 1/3 malicious validators + Fraction trust_level = 2; + // duration of the period since the LatestTimestamp during which the + // submitted headers are valid for update + google.protobuf.Duration trusting_period = 3; + // duration of the staking unbonding period + google.protobuf.Duration unbonding_period = 4; + // defines how much new (untrusted) header's Time can drift + // into the future relative to our local clock. + google.protobuf.Duration max_clock_drift = 5; + + // Block height when the client was frozen due to a misbehaviour + ibc.core.client.v1.Height frozen_height = 6; + // Latest height the client was updated to + ibc.core.client.v1.Height latest_height = 7; + + // Proof specifications used in verifying counterparty state + repeated cosmos.ics23.v1.ProofSpec proof_specs = 8; + + // Path at which next upgraded client will be committed. + // Each element corresponds to the key for a single CommitmentProof in the + // chained proof. NOTE: ClientState must stored under + // `{upgradePath}/{upgradeHeight}/clientState` ConsensusState must be stored + // under `{upgradepath}/{upgradeHeight}/consensusState` For SDK chains using + // the default upgrade module, upgrade_path should be []string{"upgrade", + // "upgradedIBCState"}` + repeated string upgrade_path = 9; +} +``` + +```proto +message ConsensusState { + // timestamp that corresponds to the block height in which the ConsensusState + // was stored. + google.protobuf.Timestamp timestamp = 1; + // commitment root (i.e app hash) that will be used + // to verify proofs of packet flow messages + ibc.core.commitment.v1.MerkleRoot root = 2; + // hash of the next validator set that will be used as + // a new updated source of trust to verify future updates + bytes next_validators_hash = 3; +} +``` + +## Updates + +Once the initial client state and consensus state are submitted, future consensus states can be added to the client by submitting IBC [headers](https://github.com/cosmos/ibc-go/blob/v9.0.0-beta.1/proto/ibc/lightclients/tendermint/v1/tendermint.proto#L76-L94). These headers contain all necessary information to run the CometBFT light client protocol. + +```proto +message Header { + // this is the new signed header that we want to add + // as a new consensus state to the ibc client. + // the signed header contains the commit signatures of the `validator_set` below + .tendermint.types.SignedHeader signed_header = 1; + + // the validator set which signed the new header + .tendermint.types.ValidatorSet validator_set = 2; + // the trusted height of the consensus state which we are updating from + ibc.core.client.v1.Height trusted_height = 3; + // the trusted validator set, the hash of the trusted validators must be equal to + // `next_validators_hash` of the current consensus state + .tendermint.types.ValidatorSet trusted_validators = 4; +} +``` + +For detailed information on the CometBFT light client protocol and its safety properties please refer to the [original Tendermint whitepaper](https://arxiv.org/abs/1807.04938). + +## Proofs + +As consensus states are added to the client, they can be used for proof verification by relayers wishing to prove packet flow messages against a particular height on the counterparty. This uses the `VerifyMembership` and `VerifyNonMembership` methods on the Tendermint client. + +```go +// VerifyMembership is a generic proof verification method +//which verifies a proof of the existence of a value at a +// given CommitmentPath at the specified height. The caller +// is expected to construct the full CommitmentPath from a +// CommitmentPrefix and a standardized path (as defined in ICS 24). +VerifyMembership( + ctx sdk.Context, + clientID string, + height Height, + delayTimePeriod uint64, + delayBlockPeriod uint64, + proof []byte, + path Path, + value []byte, +) error + +// VerifyNonMembership is a generic proof verification method +// which verifies the absence of a given CommitmentPath at a +// specified height. The caller is expected to construct the +// full CommitmentPath from a CommitmentPrefix and a standardized +// path (as defined in ICS 24). +VerifyNonMembership( + ctx sdk.Context, + clientID string, + height Height, + delayTimePeriod uint64, + delayBlockPeriod uint64, + proof []byte, + path Path, +) error +``` + +The Tendermint client is initialized with an ICS23 proof spec. This allows the Tendermint implementation to support many different merkle tree structures so long as they can be represented in an [`ics23.ProofSpec`](https://github.com/cosmos/ics23/blob/go/v0.10.0/proto/cosmos/ics23/v1/proofs.proto#L145-L170). + +## Misbehaviour + +The Tendermint light client directly tracks consensus of a CometBFT counterparty chain. So long as the counterparty is Byzantine Fault Tolerant, that is to say, the malicious subset of the bonded validators does not exceed the trust level of the client, then the client is secure. + +In case the malicious subset of the validators exceeds the trust level of the client, then the client can be deceived into accepting invalid blocks and the connection is no longer secure. + +The Tendermint client has some mitigations in place to prevent this. If there are two valid blocks signed by the counterparty validator set at the same height [e.g. a valid block signed by an honest subset and an invalid block signed by a malicious one], then these conflicting headers can be submitted to the client as [misbehaviour](https://github.com/cosmos/ibc-go/blob/v9.0.0-beta.1/proto/ibc/lightclients/tendermint/v1/tendermint.proto#L65-L74). The client will verify the headers and freeze the client; preventing any future updates and proof verification from succeeding. This effectively halts communication with the compromised counterparty while out-of-band social consensus can unwind any damage done. + +Similarly, if the timestamps of the headers are not monotonically increasing, this can also be evidence of malicious behaviour and cause the client to freeze. + +Thus, any consensus faults that are detectable by a light client are part of the misbehaviour protocol and can be used to minimize the damage caused by a compromised counterparty chain. + +### Security model + +It is important to note that IBC is not a completely trustless protocol; it is **trust-minimized**. This means that the safety property of bilateral IBC communication between two chains is dependent on the safety properties of the two chains in question. If one of the chains is compromised completely, then the IBC connection to the other chain is liable to receive invalid packets from the malicious chain. For example, if a malicious validator set has taken over more than 2/3 of the validator power on a chain; that malicious validator set can create a single chain of blocks with arbitrary commitment roots and arbitrary commitments to the next validator set. This would seize complete control of the chain and prevent the honest subset from even being able to create a competing honest block. + +In this case, there is no ability for the IBC Tendermint client solely tracking CometBFT consensus to detect the misbehaviour and freeze the client. The IBC protocol would require out-of-band mechanisms to detect and fix such an egregious safety fault on the counterparty chain. Since the Tendermint light client is only tracking consensus and not also verifying the validity of state transitions, malicious behaviour from a validator set that is beyond the BFT fault threshold is an accepted risk of this light client implementation. + +The IBC protocol has principles of fault isolation (e.g. all tokens are prefixed by their channel, so tokens from different chains are not mutually fungible) and fault mitigation (e.g. ability to freeze the client if misbehaviour can be detected before complete malicious takeover) that make this risk as minimal as possible. diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/05-tendermint/_category_.json b/docs/versioned_docs/version-v9.0.x/03-light-clients/05-tendermint/_category_.json new file mode 100644 index 00000000000..e7c0c00613c --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/05-tendermint/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Tendermint", + "position": 5, + "link": null + } diff --git a/docs/versioned_docs/version-v9.0.x/03-light-clients/_category_.json b/docs/versioned_docs/version-v9.0.x/03-light-clients/_category_.json new file mode 100644 index 00000000000..8e1f221f353 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/03-light-clients/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "IBC Light Clients", + "position": 3, + "link": null +} \ No newline at end of file diff --git a/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/01-overview.md b/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/01-overview.md new file mode 100644 index 00000000000..c4b4a3e80e7 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/01-overview.md @@ -0,0 +1,55 @@ +--- +title: Overview +sidebar_label: Overview +sidebar_position: 1 +slug: /middleware/ics29-fee/overview +--- + +# Overview + +:::note Synopsis +Learn about what the Fee Middleware module is, and how to build custom modules that utilize the Fee Middleware functionality +::: + +## What is the Fee Middleware module? + +IBC does not depend on relayer operators for transaction verification. However, the relayer infrastructure ensures liveness of the Interchain network — operators listen for packets sent through channels opened between chains, and perform the vital service of ferrying these packets (and proof of the transaction on the sending chain/receipt on the receiving chain) to the clients on each side of the channel. + +Though relaying is permissionless and completely decentralized and accessible, it does come with operational costs. Running full nodes to query transaction proofs and paying for transaction fees associated with IBC packets are two of the primary cost burdens which have driven the overall discussion on **a general, in-protocol incentivization mechanism for relayers**. + +Initially, a [simple proposal](https://github.com/cosmos/ibc/pull/577/files) was created to incentivize relaying on ICS20 token transfers on the destination chain. However, the proposal was specific to ICS20 token transfers and would have to be reimplemented in this format on every other IBC application module. + +After much discussion, the proposal was expanded to a [general incentivisation design](https://github.com/cosmos/ibc/tree/master/spec/app/ics-029-fee-payment) that can be adopted by any ICS application protocol as [middleware](../../01-ibc/04-middleware/02-develop.md). + +## Concepts + +ICS29 fee payments in this middleware design are built on the assumption that sender chains are the source of incentives — the chain on which packets are incentivized is the chain that distributes fees to relayer operators. However, as part of the IBC packet flow, messages have to be submitted on both sender and destination chains. This introduces the requirement of a mapping of relayer operator's addresses on both chains. + +To achieve the stated requirements, the **fee middleware module has two main groups of functionality**: + +- Registering of relayer addresses associated with each party involved in relaying the packet on the source chain. This registration process can be automated on start up of relayer infrastructure and happens only once, not every packet flow. + + This is described in the [Fee distribution section](04-fee-distribution.md). + +- Escrowing fees by any party which will be paid out to each rightful party on completion of the packet lifecycle. + + This is described in the [Fee messages section](03-msgs.md). + +We complete the introduction by giving a list of definitions of relevant terminology. + +`Forward relayer`: The relayer that submits the `MsgRecvPacket` message for a given packet (on the destination chain). + +`Reverse relayer`: The relayer that submits the `MsgAcknowledgement` message for a given packet (on the source chain). + +`Timeout relayer`: The relayer that submits the `MsgTimeout` or `MsgTimeoutOnClose` messages for a given packet (on the source chain). + +`Payee`: The account address on the source chain to be paid on completion of the packet lifecycle. The packet lifecycle on the source chain completes with the receipt of a `MsgTimeout`/`MsgTimeoutOnClose` or a `MsgAcknowledgement`. + +`Counterparty payee`: The account address to be paid on completion of the packet lifecycle on the destination chain. The package lifecycle on the destination chain completes with a successful `MsgRecvPacket`. + +`Refund address`: The address of the account paying for the incentivization of packet relaying. The account is refunded timeout fees upon successful acknowledgement. In the event of a packet timeout, both acknowledgement and receive fees are refunded. + +## Known Limitations + +- At the time of the release of the feature (ibc-go v4) fee payments middleware only supported incentivisation of new channels; however, with the release of channel upgradeability (ibc-go v8.1) it is possible to enable incentivisation of all existing channels. +- Even though unlikely, there exists a DoS attack vector on a fee-enabled channel if 1) there exists a relayer software implementation that is incentivised to timeout packets if the timeout fee is greater than the sum of the fees to receive and acknowledge the packet, and 2) only this type of implementation is used by operators relaying on the channel. In this situation, an attacker could continuously incentivise the relayers to never deliver the packets by incrementing the timeout fee of the packets above the sum of the receive and acknowledge fees. However, this situation is unlikely to occur because 1) another relayer behaving honestly could relay the packets before they timeout, and 2) the attack would be costly because the attacker would need to incentivise the timeout fee of the packets with their own funds. Given the low impact and unlikelihood of the attack we have decided to accept this risk and not implement any mitigation mesaures. diff --git a/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/02-integration.md b/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/02-integration.md new file mode 100644 index 00000000000..343e09fb11e --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/02-integration.md @@ -0,0 +1,177 @@ +--- +title: Integration +sidebar_label: Integration +sidebar_position: 2 +slug: /middleware/ics29-fee/integration +--- + +# Integration + +:::note Synopsis +Learn how to configure the Fee Middleware module with IBC applications. The following document is intended for developers building on top of the Cosmos SDK and only applies for Cosmos SDK chains. +::: + +:::note + +## Pre-requisite Readings + +- [IBC middleware development](../../01-ibc/04-middleware/02-develop.md) +- [IBC middleware integration](../../01-ibc/04-middleware/03-integration.md) + +::: + +The Fee Middleware module, as the name suggests, plays the role of an IBC middleware and as such must be configured by chain developers to route and handle IBC messages correctly. +For Cosmos SDK chains this setup is done via the `app/app.go` file, where modules are constructed and configured in order to bootstrap the blockchain application. + +## Example integration of the Fee Middleware module + +```go +// app.go + +// Register the AppModule for the fee middleware module +ModuleBasics = module.NewBasicManager( + ... + ibcfee.AppModuleBasic{}, + ... +) + +... + +// Add module account permissions for the fee middleware module +maccPerms = map[string][]string{ + ... + ibcfeetypes.ModuleName: nil, +} + +... + +// Add fee middleware Keeper +type App struct { + ... + + IBCFeeKeeper ibcfeekeeper.Keeper + + ... +} + +... + +// Create store keys +keys := sdk.NewKVStoreKeys( + ... + ibcfeetypes.StoreKey, + ... +) + +... + +app.IBCFeeKeeper = ibcfeekeeper.NewKeeper( + appCodec, keys[ibcfeetypes.StoreKey], + app.IBCKeeper.ChannelKeeper, // may be replaced with IBC middleware + app.IBCKeeper.ChannelKeeper, + &app.IBCKeeper.PortKeeper, app.AccountKeeper, app.BankKeeper, +) + + +// See the section below for configuring an application stack with the fee middleware module + +... + +// Register fee middleware AppModule +app.moduleManager = module.NewManager( + ... + ibcfee.NewAppModule(app.IBCFeeKeeper), +) + +... + +// Add fee middleware to begin blocker logic +app.moduleManager.SetOrderBeginBlockers( + ... + ibcfeetypes.ModuleName, + ... +) + +// Add fee middleware to end blocker logic +app.moduleManager.SetOrderEndBlockers( + ... + ibcfeetypes.ModuleName, + ... +) + +// Add fee middleware to init genesis logic +app.moduleManager.SetOrderInitGenesis( + ... + ibcfeetypes.ModuleName, + ... +) +``` + +## Configuring an application stack with Fee Middleware + +As mentioned in [IBC middleware development](../../01-ibc/04-middleware/02-develop.md) an application stack may be composed of many or no middlewares that nest a base application. +These layers form the complete set of application logic that enable developers to build composable and flexible IBC application stacks. +For example, an application stack may be just a single base application like `transfer`, however, the same application stack composed with `29-fee` will nest the `transfer` base application +by wrapping it with the Fee Middleware module. + +### Transfer + +See below for an example of how to create an application stack using `transfer` and `29-fee`. +The following `transferStack` is configured in `app/app.go` and added to the IBC `Router`. +The in-line comments describe the execution flow of packets between the application stack and IBC core. + +```go +// Create Transfer Stack +// SendPacket, since it is originating from the application to core IBC: +// transferKeeper.SendPacket -> fee.SendPacket -> channel.SendPacket + +// RecvPacket, message that originates from core IBC and goes down to app, the flow is the other way +// channel.RecvPacket -> fee.OnRecvPacket -> transfer.OnRecvPacket + +// transfer stack contains (from top to bottom): +// - IBC Fee Middleware +// - Transfer + +// create IBC module from bottom to top of stack +var transferStack porttypes.IBCModule +transferStack = transfer.NewIBCModule(app.TransferKeeper) +transferStack = ibcfee.NewIBCMiddleware(transferStack, app.IBCFeeKeeper) + +// Add transfer stack to IBC Router +ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferStack) +``` + +### Interchain Accounts + +See below for an example of how to create an application stack using `27-interchain-accounts` and `29-fee`. +The following `icaControllerStack` and `icaHostStack` are configured in `app/app.go` and added to the IBC `Router` with the associated authentication module. +The in-line comments describe the execution flow of packets between the application stack and IBC core. + +```go +// Create Interchain Accounts Stack +// SendPacket, since it is originating from the application to core IBC: +// icaAuthModuleKeeper.SendTx -> icaController.SendPacket -> fee.SendPacket -> channel.SendPacket + +// initialize ICA module with mock module as the authentication module on the controller side +var icaControllerStack porttypes.IBCModule +icaControllerStack = ibcmock.NewIBCModule(&mockModule, ibcmock.NewMockIBCApp("", scopedICAMockKeeper)) +app.ICAAuthModule = icaControllerStack.(ibcmock.IBCModule) +icaControllerStack = icacontroller.NewIBCMiddleware(icaControllerStack, app.ICAControllerKeeper) +icaControllerStack = ibcfee.NewIBCMiddleware(icaControllerStack, app.IBCFeeKeeper) + +// RecvPacket, message that originates from core IBC and goes down to app, the flow is: +// channel.RecvPacket -> fee.OnRecvPacket -> icaHost.OnRecvPacket + +var icaHostStack porttypes.IBCModule +icaHostStack = icahost.NewIBCModule(app.ICAHostKeeper) +icaHostStack = ibcfee.NewIBCMiddleware(icaHostStack, app.IBCFeeKeeper) + +// Add authentication module, controller and host to IBC router +ibcRouter. + // the ICA Controller middleware needs to be explicitly added to the IBC Router because the + // ICA controller module owns the port capability for ICA. The ICA authentication module + // owns the channel capability. + AddRoute(ibcmock.ModuleName+icacontrollertypes.SubModuleName, icaControllerStack) // ica with mock auth module stack route to ica (top level of middleware stack) + AddRoute(icacontrollertypes.SubModuleName, icaControllerStack). + AddRoute(icahosttypes.SubModuleName, icaHostStack). +``` diff --git a/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/03-msgs.md b/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/03-msgs.md new file mode 100644 index 00000000000..c9fe1df563b --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/03-msgs.md @@ -0,0 +1,97 @@ +--- +title: Fee Messages +sidebar_label: Fee Messages +sidebar_position: 3 +slug: /middleware/ics29-fee/msgs +--- + +# Fee messages + +:::note Synopsis +Learn about the different ways to pay for fees, how the fees are paid out and what happens when not enough escrowed fees are available for payout +::: + +## Escrowing fees + +The fee middleware module exposes two different ways to pay fees for relaying IBC packets: + +### `MsgPayPacketFee` + +`MsgPayPacketFee` enables the escrowing of fees for a packet at the next sequence send and should be combined into one `MultiMsgTx` with the message that will be paid for. Note that the `Relayers` field has been set up to allow for an optional whitelist of relayers permitted to receive this fee, however, this feature has not yet been enabled at this time. + +```go +type MsgPayPacketFee struct{ + // fee encapsulates the recv, ack and timeout fees associated with an IBC packet + Fee Fee + // the source port unique identifier + SourcePortId string + // the source channel unique identifier + SourceChannelId string + // account address to refund fee if necessary + Signer string + // optional list of relayers permitted to the receive packet fee + Relayers []string +} +``` + +The `Fee` message contained in this synchronous fee payment method configures different fees which will be paid out for `MsgRecvPacket`, `MsgAcknowledgement`, and `MsgTimeout`/`MsgTimeoutOnClose`. +The amount of fees escrowed in total is the denomwise maximum of `RecvFee + AckFee` and `TimeoutFee`. This is because we do not know whether the packet will be successfully received and acknowledged or whether it will timeout. + +```go +type Fee struct { + RecvFee types.Coins + AckFee types.Coins + TimeoutFee types.Coins +} +``` + +The diagram below shows the `MultiMsgTx` with the `MsgTransfer` coming from a token transfer message, along with `MsgPayPacketFee`. + +![msgpaypacket.png](./images/msgpaypacket.png) + +### `MsgPayPacketFeeAsync` + +`MsgPayPacketFeeAsync` enables the asynchronous escrowing of fees for a specified packet. Note that a packet can be 'topped up' multiple times with additional fees of any coin denomination by broadcasting multiple `MsgPayPacketFeeAsync` messages. + +```go +type MsgPayPacketFeeAsync struct { + // unique packet identifier comprised of the channel ID, port ID and sequence + PacketId channeltypes.PacketId + // the packet fee associated with a particular IBC packet + PacketFee PacketFee +} +``` + +where the `PacketFee` also specifies the `Fee` to be paid as well as the refund address for fees which are not paid out + +```go +type PacketFee struct { + Fee Fee + RefundAddress string + Relayers []string +} +``` + +The diagram below shows how multiple `MsgPayPacketFeeAsync` can be broadcasted asynchronously. Escrowing of the fee associated with a packet can be carried out by any party because ICS-29 does not dictate a particular fee payer. In fact, chains can choose to simply not expose this fee payment to end users at all and rely on a different module account or even the community pool as the source of relayer incentives. + +![paypacketfeeasync.png](./images/paypacketfeeasync.png) + +Please see our [wiki](https://github.com/cosmos/ibc-go/wiki/Fee-enabled-fungible-token-transfers) for example flows on how to use these messages to incentivise a token transfer channel using a CLI. + +## Paying out the escrowed fees + +Following diagram takes a look at the packet flow for an incentivized token transfer and investigates the several scenario's for paying out the escrowed fees. We assume that the relayers have registered their counterparty address, detailed in the [Fee distribution section](04-fee-distribution.md). + +![feeflow.png](./images/feeflow.png) + +- In the case of a successful transaction, `RecvFee` will be paid out to the designated counterparty payee address which has been registered on the receiver chain and sent back with the `MsgAcknowledgement`, `AckFee` will be paid out to the relayer address which has submitted the `MsgAcknowledgement` on the sending chain (or the registered payee in case one has been registered for the relayer address), and the remaining fees (if any) will be reimbursed to the account which escrowed the fee. (The reimbursed amount equals `EscrowedAmount - (RecvFee + AckFee)`). + +- In case of a timeout transaction, the `TimeoutFee` will be paid to the `Timeout Relayer` (who submits the timeout message to the source chain), and the remaining fees (if any) will be reimbursed to the account which escrowed the fee. (The reimbursed amount equals `EscrowedAmount - (TimeoutFee)`). + +> Please note that fee payments are built on the assumption that sender chains are the source of incentives — the chain that sends the packets is the same chain where fee payments will occur -- please see the [Fee distribution section](04-fee-distribution.md) to understand the flow for registering payee and counterparty payee (fee receiving) addresses. + +## A locked fee middleware module + +The fee middleware module can become locked if the situation arises that the escrow account for the fees does not have sufficient funds to pay out the fees which have been escrowed for each packet. *This situation indicates a severe bug.* In this case, the fee module will be locked until manual intervention fixes the issue. + +> A locked fee module will simply skip fee logic and continue on to the underlying packet flow. A channel with a locked fee module will temporarily function as a fee disabled channel, and the locking of a fee module will not affect the continued flow of packets over the channel. diff --git a/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/04-fee-distribution.md b/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/04-fee-distribution.md new file mode 100644 index 00000000000..a2f4c286276 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/04-fee-distribution.md @@ -0,0 +1,117 @@ +--- +title: Fee Distribution +sidebar_label: Fee Distribution +sidebar_position: 4 +slug: /middleware/ics29-fee/fee-distribution +--- + +# Fee distribution + +:::note Synopsis +Learn about payee registration for the distribution of packet fees. The following document is intended for relayer operators. +::: + +:::note + +## Pre-requisite readings + +- [Fee Middleware](01-overview.md) + +::: + +Packet fees are divided into 3 distinct amounts in order to compensate relayer operators for packet relaying on fee enabled IBC channels. + +- `RecvFee`: The sum of all packet receive fees distributed to a payee for successful execution of `MsgRecvPacket`. +- `AckFee`: The sum of all packet acknowledgement fees distributed to a payee for successful execution of `MsgAcknowledgement`. +- `TimeoutFee`: The sum of all packet timeout fees distributed to a payee for successful execution of `MsgTimeout`. + +## Register a counterparty payee address for forward relaying + +As mentioned in [ICS29 Concepts](01-overview.md#concepts), the forward relayer describes the actor who performs the submission of `MsgRecvPacket` on the destination chain. +Fee distribution for incentivized packet relays takes place on the packet source chain. + +> Relayer operators are expected to register a counterparty payee address, in order to be compensated accordingly with `RecvFee`s upon completion of a packet lifecycle. + +The counterparty payee address registered on the destination chain is encoded into the packet acknowledgement and communicated as such to the source chain for fee distribution. +**If a counterparty payee is not registered for the forward relayer on the destination chain, the escrowed fees will be refunded upon fee distribution.** + +### Relayer operator actions + +A transaction must be submitted **to the destination chain** including a `CounterpartyPayee` address of an account on the source chain. +The transaction must be signed by the `Relayer`. + +Note: If a module account address is used as the `CounterpartyPayee` but the module has been set as a blocked address in the `BankKeeper`, the refunding to the module account will fail. This is because many modules use invariants to compare internal tracking of module account balances against the actual balance of the account stored in the `BankKeeper`. If a token transfer to the module account occurs without going through this module and updating the account balance of the module on the `BankKeeper`, then invariants may break and unknown behaviour could occur depending on the module implementation. Therefore, if it is desirable to use a module account that is currently blocked, the module developers should be consulted to gauge to possibility of removing the module account from the blocked list. + +```go +type MsgRegisterCounterpartyPayee struct { + // unique port identifier + PortId string + // unique channel identifier + ChannelId string + // the relayer address + Relayer string + // the counterparty payee address + CounterpartyPayee string +} +``` + +> This message is expected to fail if: +> +> - `PortId` is invalid (see [24-host naming requirements](https://github.com/cosmos/ibc/blob/master/spec/core/ics-024-host-requirements/README.md#paths-identifiers-separators). +> - `ChannelId` is invalid (see [24-host naming requirements](https://github.com/cosmos/ibc/blob/master/spec/core/ics-024-host-requirements/README.md#paths-identifiers-separators)). +> - `Relayer` is an invalid address (see [Cosmos SDK Addresses](https://github.com/cosmos/cosmos-sdk/blob/main/docs/learn/beginner/03-accounts.md#addresses)). +> - `CounterpartyPayee` is empty or contains more than 2048 bytes. + +See below for an example CLI command: + +```bash +simd tx ibc-fee register-counterparty-payee transfer channel-0 \ + cosmos1rsp837a4kvtgp2m4uqzdge0zzu6efqgucm0qdh \ + osmo1v5y0tz01llxzf4c2afml8s3awue0ymju22wxx2 \ + --from cosmos1rsp837a4kvtgp2m4uqzdge0zzu6efqgucm0qdh +``` + +## Register an alternative payee address for reverse and timeout relaying + +As mentioned in [ICS29 Concepts](01-overview.md#concepts), the reverse relayer describes the actor who performs the submission of `MsgAcknowledgement` on the source chain. +Similarly the timeout relayer describes the actor who performs the submission of `MsgTimeout` (or `MsgTimeoutOnClose`) on the source chain. + +> Relayer operators **may choose** to register an optional payee address, in order to be compensated accordingly with `AckFee`s and `TimeoutFee`s upon completion of a packet life cycle. + +If a payee is not registered for the reverse or timeout relayer on the source chain, then fee distribution assumes the default behaviour, where fees are paid out to the relayer account which delivers `MsgAcknowledgement` or `MsgTimeout`/`MsgTimeoutOnClose`. + +### Relayer operator actions + +A transaction must be submitted **to the source chain** including a `Payee` address of an account on the source chain. +The transaction must be signed by the `Relayer`. + +Note: If a module account address is used as the `Payee` it is recommended to [turn off invariant checks](https://github.com/cosmos/ibc-go/blob/v7.0.0/testing/simapp/app.go#L727) for that module. + +```go +type MsgRegisterPayee struct { + // unique port identifier + PortId string + // unique channel identifier + ChannelId string + // the relayer address + Relayer string + // the payee address + Payee string +} +``` + +> This message is expected to fail if: +> +> - `PortId` is invalid (see [24-host naming requirements](https://github.com/cosmos/ibc/blob/master/spec/core/ics-024-host-requirements/README.md#paths-identifiers-separators). +> - `ChannelId` is invalid (see [24-host naming requirements](https://github.com/cosmos/ibc/blob/master/spec/core/ics-024-host-requirements/README.md#paths-identifiers-separators)). +> - `Relayer` is an invalid address (see [Cosmos SDK Addresses](https://github.com/cosmos/cosmos-sdk/blob/main/docs/learn/beginner/03-accounts.md#addresses)). +> - `Payee` is an invalid address (see [Cosmos SDK Addresses](https://github.com/cosmos/cosmos-sdk/blob/main/docs/learn/beginner/03-accounts.md#addresses)). + +See below for an example CLI command: + +```bash +simd tx ibc-fee register-payee transfer channel-0 \ + cosmos1rsp837a4kvtgp2m4uqzdge0zzu6efqgucm0qdh \ + cosmos153lf4zntqt33a4v0sm5cytrxyqn78q7kz8j8x5 \ + --from cosmos1rsp837a4kvtgp2m4uqzdge0zzu6efqgucm0qdh +``` diff --git a/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/05-events.md b/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/05-events.md new file mode 100644 index 00000000000..adb814143a9 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/05-events.md @@ -0,0 +1,43 @@ +--- +title: Events +sidebar_label: Events +sidebar_position: 5 +slug: /middleware/ics29-fee/events +--- + + +# Events + +:::note Synopsis +An overview of all events related to ICS-29 +::: + +## `MsgPayPacketFee`, `MsgPayPacketFeeAsync` + +| Type | Attribute Key | Attribute Value | +| ----------------------- | --------------- | --------------- | +| incentivized_ibc_packet | port_id | \{portID\} | +| incentivized_ibc_packet | channel_id | \{channelID\} | +| incentivized_ibc_packet | packet_sequence | \{sequence\} | +| incentivized_ibc_packet | recv_fee | \{recvFee\} | +| incentivized_ibc_packet | ack_fee | \{ackFee\} | +| incentivized_ibc_packet | timeout_fee | \{timeoutFee\} | +| message | module | fee-ibc | + +## `RegisterPayee` + +| Type | Attribute Key | Attribute Value | +| -------------- | ------------- | --------------- | +| register_payee | relayer | \{relayer\} | +| register_payee | payee | \{payee\} | +| register_payee | channel_id | \{channelID\} | +| message | module | fee-ibc | + +## `RegisterCounterpartyPayee` + +| Type | Attribute Key | Attribute Value | +| --------------------------- | ------------------ | --------------------- | +| register_counterparty_payee | relayer | \{relayer\} | +| register_counterparty_payee | counterparty_payee | \{counterpartyPayee\} | +| register_counterparty_payee | channel_id | \{channelID\} | +| message | module | fee-ibc | diff --git a/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/06-end-users.md b/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/06-end-users.md new file mode 100644 index 00000000000..f3985cc0358 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/06-end-users.md @@ -0,0 +1,39 @@ +--- +title: End Users +sidebar_label: End Users +sidebar_position: 6 +slug: /middleware/ics29-fee/end-users +--- + +# For end users + +:::note Synopsis +Learn how to incentivize IBC packets using the ICS29 Fee Middleware module. +::: + +:::note + +## Pre-requisite readings + +- [Fee Middleware](01-overview.md) + +::: + +## Summary + +Different types of end users: + +- CLI users who want to manually incentivize IBC packets +- Client developers + +The Fee Middleware module allows end users to add a 'tip' to each IBC packet which will incentivize relayer operators to relay packets between chains. gRPC endpoints are exposed for client developers as well as a simple CLI for manually incentivizing IBC packets. + +## CLI Users + +For an in depth guide on how to use the ICS29 Fee Middleware module using the CLI please take a look at the [wiki](https://github.com/cosmos/ibc-go/wiki/Fee-enabled-fungible-token-transfers#asynchronous-incentivization-of-a-fungible-token-transfer) on the `ibc-go` repo. + +## Client developers + +Client developers can read more about the relevant ICS29 message types in the [Fee messages section](03-msgs.md). + +[CosmJS](https://github.com/cosmos/cosmjs) is a useful client library for signing and broadcasting Cosmos SDK messages. diff --git a/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/_category_.json b/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/_category_.json new file mode 100644 index 00000000000..ddca8d29da6 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Fee Middleware", + "position": 1, + "link": null +} \ No newline at end of file diff --git a/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/images/feeflow.png b/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/images/feeflow.png new file mode 100644 index 00000000000..ba02071f4d8 Binary files /dev/null and b/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/images/feeflow.png differ diff --git a/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/images/msgpaypacket.png b/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/images/msgpaypacket.png new file mode 100644 index 00000000000..1bd5deb01fd Binary files /dev/null and b/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/images/msgpaypacket.png differ diff --git a/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/images/paypacketfeeasync.png b/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/images/paypacketfeeasync.png new file mode 100644 index 00000000000..27c486a6f82 Binary files /dev/null and b/docs/versioned_docs/version-v9.0.x/04-middleware/01-ics29-fee/images/paypacketfeeasync.png differ diff --git a/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/01-overview.md b/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/01-overview.md new file mode 100644 index 00000000000..eae194b2b96 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/01-overview.md @@ -0,0 +1,55 @@ +--- +title: Overview +sidebar_label: Overview +sidebar_position: 1 +slug: /middleware/callbacks/overview +--- + +# Overview + +Learn about what the Callbacks Middleware is, and how to build custom modules that utilize the Callbacks Middleware functionality + +## What is the Callbacks Middleware? + +IBC was designed with callbacks between core IBC and IBC applications. IBC apps would send a packet to core IBC, and receive a callback on every step of that packet's lifecycle. This allows IBC applications to be built on top of core IBC, and to be able to execute custom logic on packet lifecycle events (e.g. unescrow tokens for ICS-20). + +This setup worked well for off-chain users interacting with IBC applications. However, we are now seeing the desire for secondary applications (e.g. smart contracts, modules) to call into IBC apps as part of their state machine logic and then do some actions on packet lifecycle events. + +The Callbacks Middleware allows for this functionality by allowing the packets of the underlying IBC applications to register callbacks to secondary applications for lifecycle events. These callbacks are then executed by the Callbacks Middleware when the corresponding packet lifecycle event occurs. + +After much discussion, the design was expanded to [an ADR](/architecture/adr-008-app-caller-cbs), and the Callbacks Middleware is an implementation of that ADR. + +## Concepts + +Callbacks Middleware was built with smart contracts in mind, but can be used by any secondary application that wants to allow IBC packets to call into it. Think of the Callbacks Middleware as a bridge between core IBC and a secondary application. + +We have the following definitions: + +- `Underlying IBC application`: The IBC application that is wrapped by the Callbacks Middleware. This is the IBC application that is actually sending and receiving packet lifecycle events from core IBC. For example, the transfer module, or the ICA controller submodule. +- `IBC Actor`: IBC Actor is an on-chain or off-chain entity that can initiate a packet on the underlying IBC application. For example, a smart contract, an off-chain user, or a module that sends a transfer packet are all IBC Actors. +- `Secondary application`: The application that is being called into by the Callbacks Middleware for packet lifecycle events. This is the application that is receiving the callback directly from the Callbacks Middleware module. For example, the `x/wasm` module. +- `Callback Actor`: The on-chain smart contract or module that is registered to receive callbacks from the secondary application. For example, a Wasm smart contract (gatekeeped by the `x/wasm` module). Note that the Callback Actor is not necessarily the same as the IBC Actor. For example, an off-chain user can initiate a packet on the underlying IBC application, but the Callback Actor could be a smart contract. The secondary application may want to check that the IBC Actor is allowed to call into the Callback Actor, for example, by checking that the IBC Actor is the same as the Callback Actor. +- `Callback Address`: Address of the Callback Actor. This is the address that the secondary application will call into when a packet lifecycle event occurs. For example, the address of the Wasm smart contract. +- `Maximum gas limit`: The maximum amount of gas that the Callbacks Middleware will allow the secondary application to use when it executes its custom logic. +- `User defined gas limit`: The amount of gas that the IBC Actor wants to allow the secondary application to use when it executes its custom logic. This is the gas limit that the IBC Actor specifies when it sends a packet to the underlying IBC application. This cannot be greater than the maximum gas limit. + +Think of the secondary application as a bridge between the Callbacks Middleware and the Callback Actor. The secondary application is responsible for executing the custom logic of the Callback Actor when a packet lifecycle event occurs. The secondary application is also responsible for checking that the IBC Actor is allowed to call into the Callback Actor. + +Note that it is possible that the IBC Actor, Secondary Application, and Callback Actor are all the same entity. In which case, the Callback Address should be the secondary application's module address. + +The following diagram shows how a typical `RecvPacket`, `AcknowledgementPacket`, and `TimeoutPacket` execution flow would look like: +![callbacks-middleware](./images/callbackflow.svg) + +And the following diagram shows how a typical `SendPacket` and `WriteAcknowledgement` execution flow would look like: +![callbacks-middleware](./images/ics4-callbackflow.svg) + +## Known Limitations + +- Callbacks are always executed after the underlying IBC application has executed its logic. +- Maximum gas limit is hardcoded manually during wiring. It requires a coordinated upgrade to change the maximum gas limit. +- The receive packet callback does not pass the relayer address to the secondary application. This is so that we can use the same callback for both synchronous and asynchronous acknowledgements. +- The receive packet callback does not pass IBC Actor's address, this is because the IBC Actor lives in the counterparty chain and cannot be trusted. + +:::warning +If the callbacks middleware wraps the transfer application, we strongly discourage the usage of source callbacks if [`MsgTransfer` includes forwarding information](https://github.com/cosmos/ibc-go/blob/v9.0.0-rc.0/proto/ibc/applications/transfer/v1/tx.proto#L54-L55) (which is only supported from ICS20 v2). Source callback information will be executed on the last hop before the destination chain, not on the sending chain. The explanation for this behaviour is that, if the tokens are routed through intermediary chains, then the transfer application on the sending chain will construct a packet data where the [`memo` field](https://github.com/cosmos/ibc-go/blob/v9.0.0-rc.0/proto/ibc/applications/transfer/v2/packet.proto#L38) is empty, and any [memo string](https://github.com/cosmos/ibc-go/blob/v9.0.0-rc.0/proto/ibc/applications/transfer/v1/tx.proto#L51) included in `MsgTransfer` is placed in the [`destination_memo` field](https://github.com/cosmos/ibc-go/blob/v9.0.0-rc.0/proto/ibc/applications/transfer/v2/packet.proto#L48). This makes it impossible to trigger the source callbacks on the sending chain, since the memo string is not available in the `memo` field. Then, on the chain before the final destination chain, the transfer application will construct the packet data with the memo string back in the `memo` field, so that it can be consumed by the callbacks middleware on the destination chain. However, if the `memo` field of `FungibleTokenPacketDataV2` is not empty on the chain before the final destination and the transfer application on that chain is wrapped by callbacks middleware, then the source callbacks would be triggered. Therefore, in order to prevent this unexpected behaviour (i.e. source callbacks triggered not on sending chain, but on the intermediary chain before the final destination) we are strongly recommeding to not include source callbacks information in the `memo` field of `MsgTransfer`. +::: diff --git a/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/02-integration.md b/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/02-integration.md new file mode 100644 index 00000000000..189848c6963 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/02-integration.md @@ -0,0 +1,113 @@ +--- +title: Integration +sidebar_label: Integration +sidebar_position: 2 +slug: /middleware/callbacks/integration +--- + +# Integration + +Learn how to integrate the callbacks middleware with IBC applications. The following document is intended for developers building on top of the Cosmos SDK and only applies for Cosmos SDK chains. + +The callbacks middleware is a minimal and stateless implementation of the IBC middleware interface. It does not have a keeper, nor does it store any state. It simply routes IBC middleware messages to the appropriate callback function, which is implemented by the secondary application. Therefore, it doesn't need to be registered as a module, nor does it need to be added to the module manager. It only needs to be added to the IBC application stack. + +## Pre-requisite Readings + +- [IBC middleware development](../../01-ibc/04-middleware/02-develop.md) +- [IBC middleware integration](../../01-ibc/04-middleware/03-integration.md) + +The callbacks middleware, as the name suggests, plays the role of an IBC middleware and as such must be configured by chain developers to route and handle IBC messages correctly. +For Cosmos SDK chains this setup is done via the `app/app.go` file, where modules are constructed and configured in order to bootstrap the blockchain application. + +## Importing the callbacks middleware + +The callbacks middleware has no stable releases yet. To use it, you need to import the git commit that contains the module with the compatible version of `ibc-go`. To do so, run the following command with the desired git commit in your project: + +```sh +go get github.com/cosmos/ibc-go/modules/apps/callbacks@342c00b0f8bd7feeebf0780f208a820b0faf90d1 +``` + +The following table shows the compatibility matrix between the callbacks middleware, `ibc-go`. + +| **Version** | **Git commit to import** | +|:--------------------:|:----------------------------------------:| +| `v0.2.0+ibc-go-v8.0` | 342c00b0f8bd7feeebf0780f208a820b0faf90d1 | +| `v0.1.0+ibc-go-v7.3` | 17cf1260a9cdc5292512acc9bcf6336ef0d917f4 | + +## Configuring an application stack with the callbacks middleware + +As mentioned in [IBC middleware development](../../01-ibc/04-middleware/02-develop.md) an application stack may be composed of many or no middlewares that nest a base application. +These layers form the complete set of application logic that enable developers to build composable and flexible IBC application stacks. +For example, an application stack may just be a single base application like `transfer`, however, the same application stack composed with `29-fee` and `callbacks` will nest the `transfer` base application twice by wrapping it with the Fee Middleware module and then callbacks middleware. + +The callbacks middleware also **requires** a secondary application that will receive the callbacks to implement the [`ContractKeeper`](https://github.com/cosmos/ibc-go/blob/v7.3.0/modules/apps/callbacks/types/expected_keepers.go#L11-L83). Since the wasm module does not yet support the callbacks middleware, we will use the `mockContractKeeper` module in the examples below. You should replace this with a module that implements `ContractKeeper`. + +### Transfer + +See below for an example of how to create an application stack using `transfer`, `29-fee`, and `callbacks`. Feel free to omit the `29-fee` middleware if you do not want to use it. +The following `transferStack` is configured in `app/app.go` and added to the IBC `Router`. +The in-line comments describe the execution flow of packets between the application stack and IBC core. + +```go +// Create Transfer Stack +// SendPacket, since it is originating from the application to core IBC: +// transferKeeper.SendPacket -> callbacks.SendPacket -> feeKeeper.SendPacket -> channel.SendPacket + +// RecvPacket, message that originates from core IBC and goes down to app, the flow is the other way +// channel.RecvPacket -> fee.OnRecvPacket -> callbacks.OnRecvPacket -> transfer.OnRecvPacket + +// transfer stack contains (from top to bottom): +// - IBC Fee Middleware +// - IBC Callbacks Middleware +// - Transfer + +// create IBC module from bottom to top of stack +var transferStack porttypes.IBCModule +transferStack = transfer.NewIBCModule(app.TransferKeeper) +transferStack = ibccallbacks.NewIBCMiddleware(transferStack, app.IBCFeeKeeper, app.MockContractKeeper, maxCallbackGas) +transferICS4Wrapper := transferStack.(porttypes.ICS4Wrapper) +transferStack = ibcfee.NewIBCMiddleware(transferStack, app.IBCFeeKeeper) +// Since the callbacks middleware itself is an ics4wrapper, it needs to be passed to the transfer keeper +app.TransferKeeper.WithICS4Wrapper(transferICS4Wrapper) + +// Add transfer stack to IBC Router +ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferStack) +``` + +:::warning +The usage of `WithICS4Wrapper` after `transferStack`'s configuration is critical! It allows the callbacks middleware to do `SendPacket` callbacks and asynchronous `ReceivePacket` callbacks. You must do this regardless of whether you are using the `29-fee` middleware or not. +::: + +### Interchain Accounts Controller + +```go +// Create Interchain Accounts Stack +// SendPacket, since it is originating from the application to core IBC: +// icaControllerKeeper.SendTx -> callbacks.SendPacket -> fee.SendPacket -> channel.SendPacket + +// initialize ICA module with mock module as the authentication module on the controller side +var icaControllerStack porttypes.IBCModule +icaControllerStack = ibcmock.NewIBCModule(&mockModule, ibcmock.NewIBCApp("", scopedICAMockKeeper)) +app.ICAAuthModule = icaControllerStack.(ibcmock.IBCModule) +icaControllerStack = icacontroller.NewIBCMiddleware(icaControllerStack, app.ICAControllerKeeper) +icaControllerStack = ibccallbacks.NewIBCMiddleware(icaControllerStack, app.IBCFeeKeeper, app.MockContractKeeper, maxCallbackGas) +icaICS4Wrapper := icaControllerStack.(porttypes.ICS4Wrapper) +icaControllerStack = ibcfee.NewIBCMiddleware(icaControllerStack, app.IBCFeeKeeper) +// Since the callbacks middleware itself is an ics4wrapper, it needs to be passed to the ica controller keeper +app.ICAControllerKeeper.WithICS4Wrapper(icaICS4Wrapper) + +// RecvPacket, message that originates from core IBC and goes down to app, the flow is: +// channel.RecvPacket -> fee.OnRecvPacket -> icaHost.OnRecvPacket + +var icaHostStack porttypes.IBCModule +icaHostStack = icahost.NewIBCModule(app.ICAHostKeeper) +icaHostStack = ibcfee.NewIBCMiddleware(icaHostStack, app.IBCFeeKeeper) + +// Add ICA host and controller to IBC router ibcRouter. +AddRoute(icacontrollertypes.SubModuleName, icaControllerStack). +AddRoute(icahosttypes.SubModuleName, icaHostStack). +``` + +:::warning +The usage of `WithICS4Wrapper` here is also critical! +::: diff --git a/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/03-interfaces.md b/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/03-interfaces.md new file mode 100644 index 00000000000..9b7991d2cfd --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/03-interfaces.md @@ -0,0 +1,170 @@ +--- +title: Interfaces +sidebar_label: Interfaces +sidebar_position: 3 +slug: /middleware/callbacks/interfaces +--- + +# Interfaces + +The callbacks middleware requires certain interfaces to be implemented by the underlying IBC applications and the secondary application. If you're simply wiring up the callbacks middleware to an existing IBC application stack and a secondary application such as `icacontroller` and `x/wasm`, you can skip this section. + +## Interfaces for developing the Underlying IBC Application + +### `PacketDataUnmarshaler` + +```go +// PacketDataUnmarshaler defines an optional interface which allows a middleware to +// request the packet data to be unmarshaled by the base application. +type PacketDataUnmarshaler interface { + // UnmarshalPacketData unmarshals the packet data into a concrete type + // ctx, portID, channelID are provided as arguments, so that (if needed) + // the packet data can be unmarshaled based on the channel version. + // The version of the underlying app is also returned. + UnmarshalPacketData(ctx sdk.Context, portID, channelID string, bz []byte) (interface{}, string, error) +} +``` + +The callbacks middleware **requires** the underlying ibc application to implement the [`PacketDataUnmarshaler`](https://github.com/cosmos/ibc-go/blob/v7.3.0/modules/core/05-port/types/module.go#L142-L147) interface so that it can unmarshal the packet data bytes into the appropriate packet data type. This allows usage of interface functions implemented by the packet data type. The packet data type is expected to implement the `PacketDataProvider` interface (see section below), which is used to parse the callback data that is currently stored in the packet memo field for `transfer` and `ica` packets as a JSON string. See its implementation in the [`transfer`](https://github.com/cosmos/ibc-go/blob/v7.3.0/modules/apps/transfer/ibc_module.go#L303-L313) and [`icacontroller`](https://github.com/cosmos/ibc-go/blob/v7.3.0/modules/apps/27-interchain-accounts/controller/ibc_middleware.go#L258-L268) modules for reference. + +If the underlying application is a middleware itself, then it can implement this interface by simply passing the function call to its underlying application. See its implementation in the [`fee middleware`](https://github.com/cosmos/ibc-go/blob/v7.3.0/modules/apps/29-fee/ibc_middleware.go#L368-L378) for reference. + +### `PacketDataProvider` + +```go +// PacketDataProvider defines an optional interfaces for retrieving custom packet data stored on behalf of another application. +// An existing problem in the IBC middleware design is the inability for a middleware to define its own packet data type and insert packet sender provided information. +// A short term solution was introduced into several application's packet data to utilize a memo field to carry this information on behalf of another application. +// This interfaces standardizes that behaviour. Upon realization of the ability for middleware's to define their own packet data types, this interface will be deprecated and removed with time. +type PacketDataProvider interface { + // GetCustomPacketData returns the packet data held on behalf of another application. + // The name the information is stored under should be provided as the key. + // If no custom packet data exists for the key, nil should be returned. + GetCustomPacketData(key string) interface{} +} +``` + +The callbacks middleware also **requires** the underlying ibc application's packet data type to implement the [`PacketDataProvider`](https://github.com/cosmos/ibc-go/blob/v7.3.0/modules/core/exported/packet.go#L43-L52) interface. This interface is used to retrieve the callback data from the packet data (using the memo field in the case of `transfer` and `ica`). For example, see its implementation in the [`transfer`](https://github.com/cosmos/ibc-go/blob/v7.3.0/modules/apps/transfer/types/packet.go#L85-L105) module. + +Since middlewares do not have packet types, they do not need to implement this interface. + +### `PacketData` + +```go +// PacketData defines an optional interface which an application's packet data structure may implement. +type PacketData interface { + // GetPacketSender returns the sender address of the packet data. + // If the packet sender is unknown or undefined, an empty string should be returned. + GetPacketSender(sourcePortID string) string +} +``` + +[`PacketData`](https://github.com/cosmos/ibc-go/blob/v7.3.0/modules/core/exported/packet.go#L36-L41) is an optional interface that can be implemented by the underlying ibc application's packet data type. It is used to retrieve the packet sender address from the packet data. The callbacks middleware uses this interface to retrieve the packet sender address and pass it to the callback function during a source callback. If this interface is not implemented, then the callbacks middleware passes and empty string as the sender address. For example, see its implementation in the [`transfer`](https://github.com/cosmos/ibc-go/blob/v7.3.0/modules/apps/transfer/types/packet.go#L74-L83) and [`ica`](https://github.com/cosmos/ibc-go/blob/v7.3.0/modules/apps/27-interchain-accounts/types/packet.go#L78-L92) module. + +This interface was added so that secondary applications can retrieve the packet sender address to perform custom authorization logic if needed. + +Since middlewares do not have packet types, they do not need to implement this interface. + +## Interfaces for developing the Secondary Application + +### `ContractKeeper` + +The callbacks middleware requires the secondary application to implement the [`ContractKeeper`](https://github.com/cosmos/ibc-go/blob/v7.3.0/modules/apps/callbacks/types/expected_keepers.go#L11-L83) interface. The contract keeper will be invoked at each step of the packet lifecycle. When a packet is sent, if callback information is provided, the contract keeper will be invoked via the `IBCSendPacketCallback`. This allows the contract keeper to prevent packet sends when callback information is provided, for example if the sender is unauthorized to perform callbacks on the given information. If the packet send is successful, the contract keeper on the destination (if present) will be invoked when a packet has been received and the acknowledgement is written, this will occur via `IBCReceivePacketCallback`. At the end of the packet lifecycle, when processing acknowledgements or timeouts, the source contract keeper will be invoked either via `IBCOnAcknowledgementPacket` or `IBCOnTimeoutPacket`. Once a packet has been sent, each step of the packet lifecycle can be processed given that a relayer sets the gas limit to be more than or equal to the required `CommitGasLimit`. State changes performed in the callback will only be committed upon successful execution. + +```go +// ContractKeeper defines the entry points exposed to the VM module which invokes a smart contract +type ContractKeeper interface { + // IBCSendPacketCallback is called in the source chain when a PacketSend is executed. The + // packetSenderAddress is determined by the underlying module, and may be empty if the sender is + // unknown or undefined. The contract is expected to handle the callback within the user defined + // gas limit, and handle any errors, or panics gracefully. + // This entry point is called with a cached context. If an error is returned, then the changes in + // this context will not be persisted, and the error will be propagated to the underlying IBC + // application, resulting in a packet send failure. + // + // Implementations are provided with the packetSenderAddress and MAY choose to use this to perform + // validation on the origin of a given packet. It is recommended to perform the same validation + // on all source chain callbacks (SendPacket, AcknowledgementPacket, TimeoutPacket). This + // defensively guards against exploits due to incorrectly wired SendPacket ordering in IBC stacks. + // + // The version provided is the base application version for the given packet send. This allows + // contracts to determine how to unmarshal the packetData. + IBCSendPacketCallback( + cachedCtx sdk.Context, + sourcePort string, + sourceChannel string, + timeoutHeight clienttypes.Height, + timeoutTimestamp uint64, + packetData []byte, + contractAddress, + packetSenderAddress string, + version string, + ) error + // IBCOnAcknowledgementPacketCallback is called in the source chain when a packet acknowledgement + // is received. The packetSenderAddress is determined by the underlying module, and may be empty if + // the sender is unknown or undefined. The contract is expected to handle the callback within the + // user defined gas limit, and handle any errors, or panics gracefully. + // This entry point is called with a cached context. If an error is returned, then the changes in + // this context will not be persisted, but the packet lifecycle will not be blocked. + // + // Implementations are provided with the packetSenderAddress and MAY choose to use this to perform + // validation on the origin of a given packet. It is recommended to perform the same validation + // on all source chain callbacks (SendPacket, AcknowledgementPacket, TimeoutPacket). This + // defensively guards against exploits due to incorrectly wired SendPacket ordering in IBC stacks. + // + // The version provided is the base application version for the given packet send. This allows + // contracts to determine how to unmarshal the packetData. + IBCOnAcknowledgementPacketCallback( + cachedCtx sdk.Context, + packet channeltypes.Packet, + acknowledgement []byte, + relayer sdk.AccAddress, + contractAddress, + packetSenderAddress string, + version string, + ) error + // IBCOnTimeoutPacketCallback is called in the source chain when a packet is not received before + // the timeout height. The packetSenderAddress is determined by the underlying module, and may be + // empty if the sender is unknown or undefined. The contract is expected to handle the callback + // within the user defined gas limit, and handle any error, out of gas, or panics gracefully. + // This entry point is called with a cached context. If an error is returned, then the changes in + // this context will not be persisted, but the packet lifecycle will not be blocked. + // + // Implementations are provided with the packetSenderAddress and MAY choose to use this to perform + // validation on the origin of a given packet. It is recommended to perform the same validation + // on all source chain callbacks (SendPacket, AcknowledgementPacket, TimeoutPacket). This + // defensively guards against exploits due to incorrectly wired SendPacket ordering in IBC stacks. + // + // The version provided is the base application version for the given packet send. This allows + // contracts to determine how to unmarshal the packetData. + IBCOnTimeoutPacketCallback( + cachedCtx sdk.Context, + packet channeltypes.Packet, + relayer sdk.AccAddress, + contractAddress, + packetSenderAddress string, + version string, + ) error + // IBCReceivePacketCallback is called in the destination chain when a packet acknowledgement is written. + // The contract is expected to handle the callback within the user defined gas limit, and handle any errors, + // out of gas, or panics gracefully. + // This entry point is called with a cached context. If an error is returned, then the changes in + // this context will not be persisted, but the packet lifecycle will not be blocked. + // + // The version provided is the base application version for the given packet send. This allows + // contracts to determine how to unmarshal the packetData. + IBCReceivePacketCallback( + cachedCtx sdk.Context, + packet ibcexported.PacketI, + ack ibcexported.Acknowledgement, + contractAddress string, + version string, + ) error +} +``` + +These are the callback entry points exposed to the secondary application. The secondary application is expected to execute its custom logic within these entry points. The callbacks middleware will handle the execution of these callbacks and revert the state if needed. + +:::tip +Note that the source callback entry points are provided with the `packetSenderAddress` and MAY choose to use this to perform validation on the origin of a given packet. It is recommended to perform the same validation on all source chain callbacks (SendPacket, AcknowledgePacket, TimeoutPacket). This defensively guards against exploits due to incorrectly wired SendPacket ordering in IBC stacks. +::: diff --git a/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/04-events.md b/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/04-events.md new file mode 100644 index 00000000000..c7711100fb7 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/04-events.md @@ -0,0 +1,39 @@ +--- +title: Events +sidebar_label: Events +sidebar_position: 4 +slug: /middleware/callbacks/events +--- + +# Events + +An overview of all events related to the callbacks middleware. There are two types of events, `"ibc_src_callback"` and `"ibc_dest_callback"`. + +## Shared Attributes + +Both of these event types share the following attributes: + +| **Attribute Key** | **Attribute Values** | **Optional** | +|:-------------------------:|:---------------------------------------------------------------------------------------:|:------------------:| +| module | "ibccallbacks" | | +| callback_type | **One of**: "send_packet", "acknowledgement_packet", "timeout_packet", "receive_packet" | | +| callback_address | string | | +| callback_exec_gas_limit | string (parsed from uint64) | | +| callback_commit_gas_limit | string (parsed from uint64) | | +| packet_sequence | string (parsed from uint64) | | +| callback_result | **One of**: "success", "failure" | | +| callback_error | string (parsed from callback err) | Yes, if err != nil | + +## `ibc_src_callback` Attributes + +| **Attribute Key** | **Attribute Values** | +|:------------------:|:------------------------:| +| packet_src_port | string (sourcePortID) | +| packet_src_channel | string (sourceChannelID) | + +## `ibc_dest_callback` Attributes + +| **Attribute Key** | **Attribute Values** | +|:-------------------:|:------------------------:| +| packet_dest_port | string (destPortID) | +| packet_dest_channel | string (destChannelID) | diff --git a/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/05-end-users.md b/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/05-end-users.md new file mode 100644 index 00000000000..fe74a6a747e --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/05-end-users.md @@ -0,0 +1,96 @@ +--- +title: End Users +sidebar_label: End Users +sidebar_position: 5 +slug: /middleware/callbacks/end-users +--- + +# Usage + +This section explains how to use the callbacks middleware from the perspective of an IBC Actor. Callbacks middleware provides two types of callbacks: + +- Source callbacks: + - `SendPacket` callback + - `OnAcknowledgementPacket` callback + - `OnTimeoutPacket` callback +- Destination callbacks: + - `ReceivePacket` callback + +For a given channel, the source callbacks are supported if the source chain has the callbacks middleware wired up in the channel's IBC stack. Similarly, the destination callbacks are supported if the destination chain has the callbacks middleware wired up in the channel's IBC stack. + +:::tip +Callbacks are always executed after the packet has been processed by the underlying IBC module. +::: + +:::warning +If the underlying application module is doing an asynchronous acknowledgement on packet receive (for example, if the [packet forward middleware](https://github.com/cosmos/ibc-apps/tree/main/middleware/packet-forward-middleware) is in the stack, and is being used by this packet), then the callbacks middleware will execute the `ReceivePacket` callback after the acknowledgement has been received. +::: + +## Source Callbacks + +Source callbacks are natively supported in the following ibc modules (if they are wrapped by the callbacks middleware): + +- `transfer` +- `icacontroller` + +To have your source callbacks be processed by the callbacks middleware, you must set the memo in the application's packet data to the following format: + +```jsonc +{ + "src_callback": { + "address": "callbackAddressString", + // optional + "gas_limit": "userDefinedGasLimitString", + } +} +``` + +## Destination Callbacks + +Destination callbacks are natively only supported in the transfer module. Note that wrapping icahost is not supported. This is because icahost should be able to execute an arbitrary transaction anyway, and can call contracts or modules directly. + +To have your destination callbacks processed by the callbacks middleware, you must set the memo in the application's packet data to the following format: + +```jsonc +{ + "dest_callback": { + "address": "callbackAddressString", + // optional + "gas_limit": "userDefinedGasLimitString", + } +} +``` + +Note that a packet can have both a source and destination callback. + +```jsonc +{ + "src_callback": { + "address": "callbackAddressString", + // optional + "gas_limit": "userDefinedGasLimitString", + }, + "dest_callback": { + "address": "callbackAddressString", + // optional + "gas_limit": "userDefinedGasLimitString", + } +} +``` + +# User Defined Gas Limit + +User defined gas limit was added for the following reasons: + +- To prevent callbacks from blocking packet lifecycle. +- To prevent relayers from being able to DOS the callback execution by sending a packet with a low amount of gas. + +:::tip +There is a chain wide parameter that sets the maximum gas limit that a user can set for a callback. This is to prevent a user from setting a gas limit that is too high for relayers. If the `"gas_limit"` is not set in the packet memo, then the maximum gas limit is used. +::: + +These goals are achieved by creating a minimum gas amount required for callback execution. If the relayer provides at least the minimum gas limit for the callback execution, then the packet lifecycle will not be blocked if the callback runs out of gas during execution, and the callback cannot be retried. If the relayer does not provided the minimum amount of gas and the callback executions runs out of gas, the entire tx is reverted and it may be executed again. + +:::tip +`SendPacket` callback is always reverted if the callback execution fails or returns an error for any reason. This is so that the packet is not sent if the callback execution fails. +::: diff --git a/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/06-gas.md b/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/06-gas.md new file mode 100644 index 00000000000..d9637c58344 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/06-gas.md @@ -0,0 +1,77 @@ +--- +title: Gas Management +sidebar_label: Gas Management +sidebar_position: 6 +slug: /middleware/callbacks/gas +--- + +# Gas Management + +## Overview + +Executing arbitrary code on a chain can be arbitrarily expensive. In general, a callback may consume infinite gas (think of a callback that loops forever). This is problematic for a few reasons: + +- It can block the packet lifecycle. +- It can be used to consume all of the relayer's funds and gas. +- A relayer can DOS the callback execution by sending a packet with a low amount of gas. + +To prevent these, the callbacks middleware introduces two gas limits: a chain wide gas limit (`maxCallbackGas`) and a user defined gas limit. + +### Chain Wide Gas Limit + +Since the callbacks middleware does not have a keeper, it does not use a governance parameter to set the chain wide gas limit. Instead, the chain wide gas limit is passed in as a parameter to the callbacks middleware during initialization. + +```go +// app.go + +maxCallbackGas := uint64(1_000_000) + +var transferStack porttypes.IBCModule +transferStack = transfer.NewIBCModule(app.TransferKeeper) +transferStack = ibcfee.NewIBCMiddleware(transferStack, app.IBCFeeKeeper) +transferStack = ibccallbacks.NewIBCMiddleware(transferStack, app.IBCFeeKeeper, app.MockContractKeeper, maxCallbackGas) +// Since the callbacks middleware itself is an ics4wrapper, it needs to be passed to the transfer keeper +app.TransferKeeper.WithICS4Wrapper(transferStack.(porttypes.ICS4Wrapper)) + +// Add transfer stack to IBC Router +ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferStack) +``` + +### User Defined Gas Limit + +The user defined gas limit is set by the IBC Actor during packet creation. The user defined gas limit is set in the packet memo. If the user defined gas limit is not set or if the user defined gas limit is greater than the chain wide gas limit, then the chain wide gas limit is used as the user defined gas limit. + +```jsonc +{ + "src_callback": { + "address": "callbackAddressString", + // optional + "gas_limit": "userDefinedGasLimitString", + }, + "dest_callback": { + "address": "callbackAddressString", + // optional + "gas_limit": "userDefinedGasLimitString", + } +} +``` + +## Gas Limit Enforcement + +During a callback execution, there are three types of gas limits that are enforced: + +- User defined gas limit +- Chain wide gas limit +- Context gas limit (amount of gas that the relayer has left for this execution) + +Chain wide gas limit is used as a maximum to the user defined gas limit as explained in the [previous section](#user-defined-gas-limit). It may also be used as a default value if no user gas limit is provided. Therefore, we can ignore the chain wide gas limit for the rest of this section and work with the minimum of the chain wide gas limit and user defined gas limit. This minimum is called the commit gas limit. + +The gas limit enforcement is done by executing the callback inside a cached context with a new gas meter. The gas meter is initialized with the minimum of the commit gas limit and the context gas limit. This minimum is called the execution gas limit. We say that retries are allowed if `context gas limit < commit gas limit`. Otherwise, we say that retries are not allowed. + +If the callback execution fails due to an out of gas error, then the middleware checks if retries are allowed. If retries are not allowed, then it recovers from the out of gas error, consumes execution gas limit from the original context, and continues with the packet life cycle. If retries are allowed, then it panics with an out of gas error to revert the entire tx. The packet can then be submitted again with a higher gas limit. The out of gas panic descriptor is shown below. + +```go +fmt.Sprintf("ibc %s callback out of gas; commitGasLimit: %d", callbackType, callbackData.CommitGasLimit)} +``` + +If the callback execution does not fail due to an out of gas error then the callbacks middleware does not block the packet life cycle regardless of whether retries are allowed or not. diff --git a/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/_category_.json b/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/_category_.json new file mode 100644 index 00000000000..06ae30acec9 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Callbacks Middleware", + "position": 2, + "link": null +} diff --git a/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/images/callbackflow.svg b/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/images/callbackflow.svg new file mode 100644 index 00000000000..2323889b7c9 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/images/callbackflow.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/images/ics4-callbackflow.svg b/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/images/ics4-callbackflow.svg new file mode 100644 index 00000000000..032a83f7662 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/04-middleware/02-callbacks/images/ics4-callbackflow.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/versioned_docs/version-v9.0.x/04-middleware/_category_.json b/docs/versioned_docs/version-v9.0.x/04-middleware/_category_.json new file mode 100644 index 00000000000..72f60663bf3 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/04-middleware/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "IBC Middleware Modules", + "position": 4, + "link": null +} \ No newline at end of file diff --git a/docs/versioned_docs/version-v9.0.x/05-migrations/01-support-denoms-with-slashes.md b/docs/versioned_docs/version-v9.0.x/05-migrations/01-support-denoms-with-slashes.md new file mode 100644 index 00000000000..99d08040903 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/05-migrations/01-support-denoms-with-slashes.md @@ -0,0 +1,87 @@ +--- +title: Support transfer of coins whose base denom contains slashes +sidebar_label: Support transfer of coins whose base denom contains slashes +sidebar_position: 1 +slug: /migrations/support-denoms-with-slashes +--- +# Migrating from not supporting base denoms with slashes to supporting base denoms with slashes + +This document is intended to highlight significant changes which may require more information than presented in the CHANGELOG. +Any changes that must be done by a user of ibc-go should be documented here. + +There are four sections based on the four potential user groups of this document: + +- Chains +- IBC Apps +- Relayers +- IBC Light Clients + +This document is necessary when chains are upgrading from a version that does not support base denoms with slashes (e.g. v3.0.0) to a version that does (e.g. v3.2.0). All versions of ibc-go smaller than v1.5.0 for the v1.x release line, v2.3.0 for the v2.x release line, and v3.1.0 for the v3.x release line do **NOT** support IBC token transfers of coins whose base denoms contain slashes. Therefore the in-place of genesis migration described in this document are required when upgrading. + +If a chain receives coins of a base denom with slashes before it upgrades to supporting it, the receive may pass however the trace information will be incorrect. + +E.g. If a base denom of `testcoin/testcoin/testcoin` is sent to a chain that does not support slashes in the base denom, the receive will be successful. However, the trace information stored on the receiving chain will be: `Trace: "transfer/{channel-id}/testcoin/testcoin", BaseDenom: "testcoin"`. + +This incorrect trace information must be corrected when the chain does upgrade to fully supporting denominations with slashes. + +To do so, chain binaries should include a migration script that will run when the chain upgrades from not supporting base denominations with slashes to supporting base denominations with slashes. + +## Chains + +### ICS20 - Transfer + +The transfer module will now support slashes in base denoms, so we must iterate over current traces to check if any of them are incorrectly formed and correct the trace information. + +### Upgrade Proposal + +```go +app.UpgradeKeeper.SetUpgradeHandler("MigrateTraces", + func(ctx sdk.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { + // transfer module consensus version has been bumped to 2 + return app.mm.RunMigrations(ctx, app.configurator, fromVM) + }) +``` + +This is only necessary if there are denom traces in the store with incorrect trace information from previously received coins that had a slash in the base denom. However, it is recommended that any chain upgrading to support base denominations with slashes runs this code for safety. + +For a more detailed sample, please check out the code changes in [this pull request](https://github.com/cosmos/ibc-go/pull/1680). + +### Genesis Migration + +If the chain chooses to add support for slashes in base denoms via genesis export, then the trace information must be corrected during genesis migration. + +The migration code required may look like: + +```go +func migrateGenesisSlashedDenomsUpgrade(appState genutiltypes.AppMap, clientCtx client.Context, genDoc *tmtypes.GenesisDoc) (genutiltypes.AppMap, error) { + if appState[ibctransfertypes.ModuleName] != nil { + transferGenState := &ibctransfertypes.GenesisState{} + clientCtx.Codec.MustUnmarshalJSON(appState[ibctransfertypes.ModuleName], transferGenState) + + substituteTraces := make([]ibctransfertypes.DenomTrace, len(transferGenState.DenomTraces)) + for i, dt := range transferGenState.DenomTraces { + // replace all previous traces with the latest trace if validation passes + // note most traces will have same value + newTrace := ibctransfertypes.ParseDenomTrace(dt.GetFullDenomPath()) + + if err := newTrace.Validate(); err != nil { + substituteTraces[i] = dt + } else { + substituteTraces[i] = newTrace + } + } + + transferGenState.DenomTraces = substituteTraces + + // delete old genesis state + delete(appState, ibctransfertypes.ModuleName) + + // set new ibc transfer genesis state + appState[ibctransfertypes.ModuleName] = clientCtx.Codec.MustMarshalJSON(transferGenState) + } + + return appState, nil +} +``` + +For a more detailed sample, please check out the code changes in [this pull request](https://github.com/cosmos/ibc-go/pull/1528). diff --git a/docs/versioned_docs/version-v9.0.x/05-migrations/02-sdk-to-v1.md b/docs/versioned_docs/version-v9.0.x/05-migrations/02-sdk-to-v1.md new file mode 100644 index 00000000000..88022435f64 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/05-migrations/02-sdk-to-v1.md @@ -0,0 +1,195 @@ +--- +title: SDK v0.43 to IBC-Go v1 +sidebar_label: SDK v0.43 to IBC-Go v1 +sidebar_position: 2 +slug: /migrations/sdk-to-v1 +--- + +# Migrating to ibc-go + +This file contains information on how to migrate from the IBC module contained in the SDK 0.41.x and 0.42.x lines to the IBC module in the ibc-go repository based on the 0.44 SDK version. + +## Import Changes + +The most obvious changes is import name changes. We need to change: + +- applications -> apps +- cosmos-sdk/x/ibc -> ibc-go + +On my GNU/Linux based machine I used the following commands, executed in order: + +```shell +grep -RiIl 'cosmos-sdk\/x\/ibc\/applications' | xargs sed -i 's/cosmos-sdk\/x\/ibc\/applications/ibc-go\/modules\/apps/g' +``` + +```shell +grep -RiIl 'cosmos-sdk\/x\/ibc' | xargs sed -i 's/cosmos-sdk\/x\/ibc/ibc-go\/modules/g' +``` + +ref: [explanation of the above commands](https://www.internalpointers.com/post/linux-find-and-replace-text-multiple-files) + +Executing these commands out of order will cause issues. + +Feel free to use your own method for modifying import names. + +NOTE: Updating to the `v0.44.0` SDK release and then running `go mod tidy` will cause a downgrade to `v0.42.0` in order to support the old IBC import paths. +Update the import paths before running `go mod tidy`. + +## Chain Upgrades + +Chains may choose to upgrade via an upgrade proposal or genesis upgrades. Both in-place store migrations and genesis migrations are supported. + +**WARNING**: Please read at least the quick guide for [IBC client upgrades](../01-ibc/05-upgrades/01-quick-guide.md) before upgrading your chain. It is highly recommended you do not change the chain-ID during an upgrade, otherwise you must follow the IBC client upgrade instructions. + +Both in-place store migrations and genesis migrations will: + +- migrate the solo machine client state from v1 to v2 protobuf definitions +- prune all solo machine consensus states +- prune all expired tendermint consensus states + +Chains must set a new connection parameter during either in place store migrations or genesis migration. The new parameter, max expected block time, is used to enforce packet processing delays on the receiving end of an IBC packet flow. Checkout the [docs](https://github.com/cosmos/ibc-go/blob/release/v1.0.x/docs/ibc/proto-docs.md#params-2) for more information. + +### In-Place Store Migrations + +The new chain binary will need to run migrations in the upgrade handler. The fromVM (previous module version) for the IBC module should be 1. This will allow migrations to be run for IBC updating the version from 1 to 2. + +Ex: + +```go +app.UpgradeKeeper.SetUpgradeHandler("my-upgrade-proposal", + func(ctx sdk.Context, _ upgradetypes.Plan, _ module.VersionMap) (module.VersionMap, error) { + // set max expected block time parameter. Replace the default with your expected value + // https://github.com/cosmos/ibc-go/blob/release/v1.0.x/docs/ibc/proto-docs.md#params-2 + app.IBCKeeper.ConnectionKeeper.SetParams(ctx, ibcconnectiontypes.DefaultParams()) + + fromVM := map[string]uint64{ + ... // other modules + "ibc": 1, + ... + } + return app.mm.RunMigrations(ctx, app.configurator, fromVM) + }) + +``` + +### Genesis Migrations + +To perform genesis migrations, the following code must be added to your existing migration code. + +```go +// add imports as necessary +import ( + ibcv100 "github.com/cosmos/ibc-go/modules/core/legacy/v100" + ibchost "github.com/cosmos/ibc-go/modules/core/24-host" +) + +... + +// add in migrate cmd function +// expectedTimePerBlock is a new connection parameter +// https://github.com/cosmos/ibc-go/blob/release/v1.0.x/docs/ibc/proto-docs.md#params-2 +newGenState, err = ibcv100.MigrateGenesis(newGenState, clientCtx, *genDoc, expectedTimePerBlock) +if err != nil { + return err +} +``` + +**NOTE:** The genesis chain-id, time and height MUST be updated before migrating IBC, otherwise the tendermint consensus state will not be pruned. + +## IBC Keeper Changes + +The IBC Keeper now takes in the Upgrade Keeper. Please add the chains' Upgrade Keeper after the Staking Keeper: + +```diff +// Create IBC Keeper +app.IBCKeeper = ibckeeper.NewKeeper( +- appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, scopedIBCKeeper, ++ appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, app.UpgradeKeeper, scopedIBCKeeper, +) +``` + +## Proposals + +### UpdateClientProposal + +The `UpdateClient` has been modified to take in two client-identifiers and one initial height. Please see the [documentation](../01-ibc/07-proposals.md) for more information. + +### UpgradeProposal + +A new IBC proposal type has been added, `UpgradeProposal`. This handles an IBC (breaking) Upgrade. +The previous `UpgradedClientState` field in an Upgrade `Plan` has been deprecated in favor of this new proposal type. + +### Proposal Handler Registration + +The `ClientUpdateProposalHandler` has been renamed to `ClientProposalHandler`. +It handles both `UpdateClientProposal`s and `UpgradeProposal`s. + +Add this import: + +```diff ++ ibcclienttypes "github.com/cosmos/ibc-go/modules/core/02-client/types" +``` + +Please ensure the governance module adds the correct route: + +```diff +- AddRoute(ibchost.RouterKey, ibcclient.NewClientUpdateProposalHandler(app.IBCKeeper.ClientKeeper)) ++ AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper)) +``` + +NOTE: Simapp registration was incorrect in the 0.41.x releases. The `UpdateClient` proposal handler should be registered with the router key belonging to `ibc-go/core/02-client/types` +as shown in the diffs above. + +### Proposal CLI Registration + +Please ensure both proposal type CLI commands are registered on the governance module by adding the following arguments to `gov.NewAppModuleBasic()`: + +Add the following import: + +```diff ++ ibcclientclient "github.com/cosmos/ibc-go/modules/core/02-client/client" +``` + +Register the cli commands: + +```diff +gov.NewAppModuleBasic( + paramsclient.ProposalHandler, distrclient.ProposalHandler, upgradeclient.ProposalHandler, upgradeclient.CancelProposalHandler, ++ ibcclientclient.UpdateClientProposalHandler, ibcclientclient.UpgradeProposalHandler, +), +``` + +REST routes are not supported for these proposals. + +## Proto file changes + +The gRPC querier service endpoints have changed slightly. The previous files used `v1beta1` gRPC route, this has been updated to `v1`. + +The solo machine has replaced the FrozenSequence uint64 field with a IsFrozen boolean field. The package has been bumped from `v1` to `v2` + +## IBC callback changes + +### OnRecvPacket + +Application developers need to update their `OnRecvPacket` callback logic. + +The `OnRecvPacket` callback has been modified to only return the acknowledgement. The acknowledgement returned must implement the `Acknowledgement` interface. The acknowledgement should indicate if it represents a successful processing of a packet by returning true on `Success()` and false in all other cases. A return value of false on `Success()` will result in all state changes which occurred in the callback being discarded. More information can be found in the [documentation](../01-ibc/03-apps/01-apps.md#receiving-packets). + +The `OnRecvPacket`, `OnAcknowledgementPacket`, and `OnTimeoutPacket` callbacks are now passed the `sdk.AccAddress` of the relayer who relayed the IBC packet. Applications may use or ignore this information. + +## IBC Event changes + +The `packet_data` attribute has been deprecated in favor of `packet_data_hex`, in order to provide standardized encoding/decoding of packet data in events. While the `packet_data` event still exists, all relayers and IBC Event consumers are strongly encouraged to switch over to using `packet_data_hex` as soon as possible. + +The `packet_ack` attribute has also been deprecated in favor of `packet_ack_hex` for the same reason stated above. All relayers and IBC Event consumers are strongly encouraged to switch over to using `packet_ack_hex` as soon as possible. + +The `consensus_height` attribute has been removed in the Misbehaviour event emitted. IBC clients no longer have a frozen height and misbehaviour does not necessarily have an associated height. + +## Relevant SDK changes + +- (codec) [\#9226](https://github.com/cosmos/cosmos-sdk/pull/9226) Rename codec interfaces and methods, to follow a general Go interfaces: + - `codec.Marshaler` → `codec.Codec` (this defines objects which serialize other objects) + - `codec.BinaryMarshaler` → `codec.BinaryCodec` + - `codec.JSONMarshaler` → `codec.JSONCodec` + - Removed `BinaryBare` suffix from `BinaryCodec` methods (`MarshalBinaryBare`, `UnmarshalBinaryBare`, ...) + - Removed `Binary` infix from `BinaryCodec` methods (`MarshalBinaryLengthPrefixed`, `UnmarshalBinaryLengthPrefixed`, ...) diff --git a/docs/versioned_docs/version-v9.0.x/05-migrations/03-v1-to-v2.md b/docs/versioned_docs/version-v9.0.x/05-migrations/03-v1-to-v2.md new file mode 100644 index 00000000000..77d3de4e87f --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/05-migrations/03-v1-to-v2.md @@ -0,0 +1,59 @@ +--- +title: IBC-Go v1 to v2 +sidebar_label: IBC-Go v1 to v2 +sidebar_position: 3 +slug: /migrations/v1-to-v2 +--- +# Migrating from ibc-go v1 to v2 + +This document is intended to highlight significant changes which may require more information than presented in the CHANGELOG. +Any changes that must be done by a user of ibc-go should be documented here. + +There are four sections based on the four potential user groups of this document: + +- Chains +- IBC Apps +- Relayers +- IBC Light Clients + +**Note:** ibc-go supports golang semantic versioning and therefore all imports must be updated to bump the version number on major releases. + +```go +github.com/cosmos/ibc-go -> github.com/cosmos/ibc-go/v2 +``` + +## Chains + +- No relevant changes were made in this release. + +## IBC Apps + +A new function has been added to the app module interface: + +```go +// NegotiateAppVersion performs application version negotiation given the provided channel ordering, connectionID, portID, counterparty and proposed version. +// An error is returned if version negotiation cannot be performed. For example, an application module implementing this interface +// may decide to return an error in the event of the proposed version being incompatible with it's own +NegotiateAppVersion( + ctx sdk.Context, + order channeltypes.Order, + connectionID string, + portID string, + counterparty channeltypes.Counterparty, + proposedVersion string, +) (version string, err error) +``` + +This function should perform application version negotiation and return the negotiated version. If the version cannot be negotiated, an error should be returned. This function is only used on the client side. + +### `sdk.Result` removed + +`sdk.Result` has been removed as a return value in the application callbacks. Previously it was being discarded by core IBC and was thus unused. + +## Relayers + +A new gRPC has been added to 05-port, `AppVersion`. It returns the negotiated app version. This function should be used for the `ChanOpenTry` channel handshake step to decide upon the application version which should be set in the channel. + +## IBC Light Clients + +- No relevant changes were made in this release. diff --git a/docs/versioned_docs/version-v9.0.x/05-migrations/04-v2-to-v3.md b/docs/versioned_docs/version-v9.0.x/05-migrations/04-v2-to-v3.md new file mode 100644 index 00000000000..280f5340fbe --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/05-migrations/04-v2-to-v3.md @@ -0,0 +1,186 @@ +--- +title: IBC-Go v2 to v3 +sidebar_label: IBC-Go v2 to v3 +sidebar_position: 4 +slug: /migrations/v2-to-v3 +--- + +# Migrating from ibc-go v2 to v3 + +This document is intended to highlight significant changes which may require more information than presented in the CHANGELOG. +Any changes that must be done by a user of ibc-go should be documented here. + +There are four sections based on the four potential user groups of this document: + +- Chains +- IBC Apps +- Relayers +- IBC Light Clients + +**Note:** ibc-go supports golang semantic versioning and therefore all imports must be updated to bump the version number on major releases. + +```go +github.com/cosmos/ibc-go/v2 -> github.com/cosmos/ibc-go/v3 +``` + +No genesis or in-place migrations are required when upgrading from v1 or v2 of ibc-go. + +## Chains + +### ICS20 + +The `transferkeeper.NewKeeper(...)` now takes in an ICS4Wrapper. +The ICS4Wrapper should be the IBC Channel Keeper unless ICS 20 is being connected to a middleware application. + +### ICS27 + +ICS27 Interchain Accounts has been added as a supported IBC application of ibc-go. +Please see the [ICS27 documentation](../02-apps/02-interchain-accounts/01-overview.md) for more information. + +### Upgrade Proposal + +If the chain will adopt ICS27, it must set the appropriate params during the execution of the upgrade handler in `app.go`: + +```go +app.UpgradeKeeper.SetUpgradeHandler("v3", + func(ctx sdk.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { + // set the ICS27 consensus version so InitGenesis is not run + fromVM[icatypes.ModuleName] = icamodule.ConsensusVersion() + + // create ICS27 Controller submodule params + controllerParams := icacontrollertypes.Params{ + ControllerEnabled: true, + } + + // create ICS27 Host submodule params + hostParams := icahosttypes.Params{ + HostEnabled: true, + AllowMessages: []string{"/cosmos.bank.v1beta1.MsgSend", ...}, + } + + // initialize ICS27 module + icamodule.InitModule(ctx, controllerParams, hostParams) + + ... + + return app.mm.RunMigrations(ctx, app.configurator, fromVM) + }) +``` + +The host and controller submodule params only need to be set if the chain integrates those submodules. +For example, if a chain chooses not to integrate a controller submodule, it may pass empty params into `InitModule`. + +#### Add `StoreUpgrades` for ICS27 module + +For ICS27 it is also necessary to [manually add store upgrades](https://docs.cosmos.network/main/learn/advanced/upgrade#add-storeupgrades-for-new-modules) for the new ICS27 module and then configure the store loader to apply those upgrades in `app.go`: + +```go +if upgradeInfo.Name == "v3" && !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) { + storeUpgrades := store.StoreUpgrades{ + Added: []string{icacontrollertypes.StoreKey, icahosttypes.StoreKey}, + } + + app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &storeUpgrades)) +} +``` + +This ensures that the new module's stores are added to the multistore before the migrations begin. +The host and controller submodule keys only need to be added if the chain integrates those submodules. +For example, if a chain chooses not to integrate a controller submodule, it does not need to add the controller key to the `Added` field. + +### Genesis migrations + +If the chain will adopt ICS27 and chooses to upgrade via a genesis export, then the ICS27 parameters must be set during genesis migration. + +The migration code required may look like: + +```go + controllerGenesisState := icatypes.DefaultControllerGenesis() + // overwrite parameters as desired + controllerGenesisState.Params = icacontrollertypes.Params{ + ControllerEnabled: true, + } + + hostGenesisState := icatypes.DefaultHostGenesis() + // overwrite parameters as desired + hostGenesisState.Params = icahosttypes.Params{ + HostEnabled: true, + AllowMessages: []string{"/cosmos.bank.v1beta1.MsgSend", ...}, + } + + icaGenesisState := icatypes.NewGenesisState(controllerGenesisState, hostGenesisState) + + // set new ics27 genesis state + appState[icatypes.ModuleName] = clientCtx.Codec.MustMarshalJSON(icaGenesisState) +``` + +### Ante decorator + +The field of type `channelkeeper.Keeper` in the `AnteDecorator` structure has been replaced with a field of type `*keeper.Keeper`: + +```diff +type AnteDecorator struct { +- k channelkeeper.Keeper ++ k *keeper.Keeper +} + +- func NewAnteDecorator(k channelkeeper.Keeper) AnteDecorator { ++ func NewAnteDecorator(k *keeper.Keeper) AnteDecorator { + return AnteDecorator{k: k} +} +``` + +## IBC Apps + +### `OnChanOpenTry` must return negotiated application version + +The `OnChanOpenTry` application callback has been modified. +The return signature now includes the application version. +IBC applications must perform application version negotiation in `OnChanOpenTry` using the counterparty version. +The negotiated application version then must be returned in `OnChanOpenTry` to core IBC. +Core IBC will set this version in the TRYOPEN channel. + +### `OnChanOpenAck` will take additional `counterpartyChannelID` argument + +The `OnChanOpenAck` application callback has been modified. +The arguments now include the counterparty channel id. + +### `NegotiateAppVersion` removed from `IBCModule` interface + +Previously this logic was handled by the `NegotiateAppVersion` function. +Relayers would query this function before calling `ChanOpenTry`. +Applications would then need to verify that the passed in version was correct. +Now applications will perform this version negotiation during the channel handshake, thus removing the need for `NegotiateAppVersion`. + +### Channel state will not be set before application callback + +The channel handshake logic has been reorganized within core IBC. +Channel state will not be set in state after the application callback is performed. +Applications must rely only on the passed in channel parameters instead of querying the channel keeper for channel state. + +### IBC application callbacks moved from `AppModule` to `IBCModule` + +Previously, IBC module callbacks were apart of the `AppModule` type. +The recommended approach is to create an `IBCModule` type and move the IBC module callbacks from `AppModule` to `IBCModule` in a separate file `ibc_module.go`. + +The mock module go API has been broken in this release by applying the above format. +The IBC module callbacks have been moved from the mock modules `AppModule` into a new type `IBCModule`. + +As apart of this release, the mock module now supports middleware testing. Please see the [README](https://github.com/cosmos/ibc-go/blob/v3.0.0/testing/README.md#middleware-testing) for more information. + +Please review the [mock](https://github.com/cosmos/ibc-go/blob/v3.0.0/testing/mock/ibc_module.go) and [transfer](https://github.com/cosmos/ibc-go/blob/v3.0.0/modules/apps/transfer/ibc_module.go) modules as examples. Additionally, [simapp](https://github.com/cosmos/ibc-go/blob/v3.0.0/testing/simapp/app.go) provides an example of how `IBCModule` types should now be added to the IBC router in favour of `AppModule`. + +### IBC testing package + +`TestChain`s are now created with chainID's beginning from an index of 1. Any calls to `GetChainID(0)` will now fail. Please increment all calls to `GetChainID` by 1. + +## Relayers + +`AppVersion` gRPC has been removed. +The `version` string in `MsgChanOpenTry` has been deprecated and will be ignored by core IBC. +Relayers no longer need to determine the version to use on the `ChanOpenTry` step. +IBC applications will determine the correct version using the counterparty version. + +## IBC Light Clients + +The `GetProofSpecs` function has been removed from the `ClientState` interface. This function was previously unused by core IBC. Light clients which don't use this function may remove it. diff --git a/docs/versioned_docs/version-v9.0.x/05-migrations/05-v3-to-v4.md b/docs/versioned_docs/version-v9.0.x/05-migrations/05-v3-to-v4.md new file mode 100644 index 00000000000..091e11375ef --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/05-migrations/05-v3-to-v4.md @@ -0,0 +1,159 @@ +--- +title: IBC-Go v3 to v4 +sidebar_label: IBC-Go v3 to v4 +sidebar_position: 5 +slug: /migrations/v3-to-v4 +--- +# Migrating from ibc-go v3 to v4 + +This document is intended to highlight significant changes which may require more information than presented in the CHANGELOG. +Any changes that must be done by a user of ibc-go should be documented here. + +There are four sections based on the four potential user groups of this document: + +- Chains +- IBC Apps +- Relayers +- IBC Light Clients + +**Note:** ibc-go supports golang semantic versioning and therefore all imports must be updated to bump the version number on major releases. + +```go +github.com/cosmos/ibc-go/v3 -> github.com/cosmos/ibc-go/v4 +``` + +No genesis or in-place migrations required when upgrading from v1 or v2 of ibc-go. + +## Chains + +### ICS27 - Interchain Accounts + +The controller submodule implements now the 05-port `Middleware` interface instead of the 05-port `IBCModule` interface. Chains that integrate the controller submodule, need to create it with the `NewIBCMiddleware` constructor function. For example: + +```diff +- icacontroller.NewIBCModule(app.ICAControllerKeeper, icaAuthIBCModule) ++ icacontroller.NewIBCMiddleware(icaAuthIBCModule, app.ICAControllerKeeper) +``` + +where `icaAuthIBCModule` is the Interchain Accounts authentication IBC Module. + +### ICS29 - Fee Middleware + +The Fee Middleware module, as the name suggests, plays the role of an IBC middleware and as such must be configured by chain developers to route and handle IBC messages correctly. + +Please read the Fee Middleware [integration documentation](../04-middleware/01-ics29-fee/02-integration.md) for an in depth guide on how to configure the module correctly in order to incentivize IBC packets. + +Take a look at the following diff for an [example setup](https://github.com/cosmos/ibc-go/pull/1432/files#diff-d18972debee5e64f16e40807b2ae112ddbe609504a93ea5e1c80a5d489c3a08aL366) of how to incentivize ics27 channels. + +### Migration to fix support for base denoms with slashes + +As part of [v1.5.0](https://github.com/cosmos/ibc-go/releases/tag/v1.5.0), [v2.3.0](https://github.com/cosmos/ibc-go/releases/tag/v2.3.0) and [v3.1.0](https://github.com/cosmos/ibc-go/releases/tag/v3.1.0) some [migration handler code sample was documented](./01-support-denoms-with-slashes.md#upgrade-proposal) that needs to run in order to correct the trace information of coins transferred using ICS20 whose base denom contains slashes. + +Based on feedback from the community we add now an improved solution to run the same migration that does not require copying a large piece of code over from the migration document, but instead requires only adding a one-line upgrade handler. + +If the chain will migrate to supporting base denoms with slashes, it must set the appropriate params during the execution of the upgrade handler in `app.go`: + +```go +app.UpgradeKeeper.SetUpgradeHandler("MigrateTraces", + func(ctx sdk.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { + // transfer module consensus version has been bumped to 2 + return app.mm.RunMigrations(ctx, app.configurator, fromVM) + }) +``` + +If a chain receives coins of a base denom with slashes before it upgrades to supporting it, the receive may pass however the trace information will be incorrect. + +E.g. If a base denom of `testcoin/testcoin/testcoin` is sent to a chain that does not support slashes in the base denom, the receive will be successful. However, the trace information stored on the receiving chain will be: `Trace: "transfer/{channel-id}/testcoin/testcoin", BaseDenom: "testcoin"`. + +This incorrect trace information must be corrected when the chain does upgrade to fully supporting denominations with slashes. + +## IBC Apps + +### ICS03 - Connection + +Crossing hellos have been removed from 03-connection handshake negotiation. +`PreviousConnectionId` in `MsgConnectionOpenTry` has been deprecated and is no longer used by core IBC. + +`NewMsgConnectionOpenTry` no longer takes in the `PreviousConnectionId` as crossing hellos are no longer supported. A non-empty `PreviousConnectionId` will fail basic validation for this message. + +### ICS04 - Channel + +The `WriteAcknowledgement` API now takes the `exported.Acknowledgement` type instead of passing in the acknowledgement byte array directly. +This is an API breaking change and as such IBC application developers will have to update any calls to `WriteAcknowledgement`. + +The `OnChanOpenInit` application callback has been modified. +The return signature now includes the application version as detailed in the latest IBC [spec changes](https://github.com/cosmos/ibc/pull/629). + +The `NewErrorAcknowledgement` method signature has changed. +It now accepts an `error` rather than a `string`. This was done in order to prevent accidental state changes. +All error acknowledgements now contain a deterministic ABCI code and error message. It is the responsibility of the application developer to emit error details in events. + +Crossing hellos have been removed from 04-channel handshake negotiation. +IBC Applications no longer need to account from already claimed capabilities in the `OnChanOpenTry` callback. The capability provided by core IBC must be able to be claimed with error. +`PreviousChannelId` in `MsgChannelOpenTry` has been deprecated and is no longer used by core IBC. + +`NewMsgChannelOpenTry` no longer takes in the `PreviousChannelId` as crossing hellos are no longer supported. A non-empty `PreviousChannelId` will fail basic validation for this message. + +### ICS27 - Interchain Accounts + +The `RegisterInterchainAccount` API has been modified to include an additional `version` argument. This change has been made in order to support ICS29 fee middleware, for relayer incentivization of ICS27 packets. +Consumers of the `RegisterInterchainAccount` are now expected to build the appropriate JSON encoded version string themselves and pass it accordingly. +This should be constructed within the interchain accounts authentication module which leverages the APIs exposed via the interchain accounts `controllerKeeper`. If an empty string is passed in the `version` argument, then the version will be initialized to a default value in the `OnChanOpenInit` callback of the controller's handler, so that channel handshake can proceed. + +The following code snippet illustrates how to construct an appropriate interchain accounts `Metadata` and encode it as a JSON bytestring: + +```go +icaMetadata := icatypes.Metadata{ + Version: icatypes.Version, + ControllerConnectionId: controllerConnectionID, + HostConnectionId: hostConnectionID, + Encoding: icatypes.EncodingProtobuf, + TxType: icatypes.TxTypeSDKMultiMsg, +} + +appVersion, err := icatypes.ModuleCdc.MarshalJSON(&icaMetadata) +if err != nil { + return err +} + +if err := k.icaControllerKeeper.RegisterInterchainAccount(ctx, msg.ConnectionId, msg.Owner, string(appVersion)); err != nil { + return err +} +``` + +Similarly, if the application stack is configured to route through ICS29 fee middleware and a fee enabled channel is desired, construct the appropriate ICS29 `Metadata` type: + +```go +icaMetadata := icatypes.Metadata{ + Version: icatypes.Version, + ControllerConnectionId: controllerConnectionID, + HostConnectionId: hostConnectionID, + Encoding: icatypes.EncodingProtobuf, + TxType: icatypes.TxTypeSDKMultiMsg, +} + +appVersion, err := icatypes.ModuleCdc.MarshalJSON(&icaMetadata) +if err != nil { + return err +} + +feeMetadata := feetypes.Metadata{ + AppVersion: string(appVersion), + FeeVersion: feetypes.Version, +} + +feeEnabledVersion, err := feetypes.ModuleCdc.MarshalJSON(&feeMetadata) +if err != nil { + return err +} + +if err := k.icaControllerKeeper.RegisterInterchainAccount(ctx, msg.ConnectionId, msg.Owner, string(feeEnabledVersion)); err != nil { + return err +} +``` + +## Relayers + +When using the `DenomTrace` gRPC, the full IBC denomination with the `ibc/` prefix may now be passed in. + +Crossing hellos are no longer supported by core IBC for 03-connection and 04-channel. The handshake should be completed in the logical 4 step process (INIT, TRY, ACK, CONFIRM). diff --git a/docs/versioned_docs/version-v9.0.x/05-migrations/06-v4-to-v5.md b/docs/versioned_docs/version-v9.0.x/05-migrations/06-v4-to-v5.md new file mode 100644 index 00000000000..c5e8c84db1c --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/05-migrations/06-v4-to-v5.md @@ -0,0 +1,441 @@ +--- +title: IBC-Go v4 to v5 +sidebar_label: IBC-Go v4 to v5 +sidebar_position: 6 +slug: /migrations/v4-to-v5 +--- + +# Migrating from v4 to v5 + +This document is intended to highlight significant changes which may require more information than presented in the CHANGELOG. +Any changes that must be done by a user of ibc-go should be documented here. + +There are four sections based on the four potential user groups of this document: + +- [Chains](#chains) +- [IBC Apps](#ibc-apps) +- [Relayers](#relayers) +- [IBC Light Clients](#ibc-light-clients) + +**Note:** ibc-go supports golang semantic versioning and therefore all imports must be updated to bump the version number on major releases. + +```go +github.com/cosmos/ibc-go/v4 -> github.com/cosmos/ibc-go/v5 +``` + +## Chains + +### Ante decorator + +The `AnteDecorator` type in `core/ante` has been renamed to `RedundantRelayDecorator` (and the corresponding constructor function to `NewRedundantRelayDecorator`). Therefore in the function that creates the instance of the `sdk.AnteHandler` type (e.g. `NewAnteHandler`) the change would be like this: + +```diff +func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) { + // parameter validation + + anteDecorators := []sdk.AnteDecorator{ + // other ante decorators +- ibcante.NewAnteDecorator(opts.IBCkeeper), ++ ibcante.NewRedundantRelayDecorator(options.IBCKeeper), + } + + return sdk.ChainAnteDecorators(anteDecorators...), nil +} +``` + +The `AnteDecorator` was actually renamed twice, but in [this PR](https://github.com/cosmos/ibc-go/pull/1820) you can see the changes made for the final rename. + +## IBC Apps + +### Core + +The `key` parameter of the `NewKeeper` function in `modules/core/keeper` is now of type `storetypes.StoreKey` (where `storetypes` is an import alias for `"github.com/cosmos/cosmos-sdk/store/types"`): + +```diff +func NewKeeper( + cdc codec.BinaryCodec, +- key sdk.StoreKey, ++ key storetypes.StoreKey, + paramSpace paramtypes.Subspace, + stakingKeeper clienttypes.StakingKeeper, + upgradeKeeper clienttypes.UpgradeKeeper, + scopedKeeper capabilitykeeper.ScopedKeeper, +) *Keeper +``` + +The `RegisterRESTRoutes` function in `modules/core` has been removed. + +### ICS03 - Connection + +The `key` parameter of the `NewKeeper` function in `modules/core/03-connection/keeper` is now of type `storetypes.StoreKey` (where `storetypes` is an import alias for `"github.com/cosmos/cosmos-sdk/store/types"`): + +```diff +func NewKeeper( + cdc codec.BinaryCodec, +- key sdk.StoreKey, ++ key storetypes.StoreKey, + paramSpace paramtypes.Subspace, + ck types.ClientKeeper +) Keeper +``` + +### ICS04 - Channel + +The function `NewPacketId` in `modules/core/04-channel/types` has been renamed to `NewPacketID`: + +```diff +- func NewPacketId( ++ func NewPacketID( + portID, + channelID string, + seq uint64 +) PacketId +``` + +The `key` parameter of the `NewKeeper` function in `modules/core/04-channel/keeper` is now of type `storetypes.StoreKey` (where `storetypes` is an import alias for `"github.com/cosmos/cosmos-sdk/store/types"`): + +```diff +func NewKeeper( + cdc codec.BinaryCodec, +- key sdk.StoreKey, ++ key storetypes.StoreKey, + clientKeeper types.ClientKeeper, + connectionKeeper types.ConnectionKeeper, + portKeeper types.PortKeeper, + scopedKeeper capabilitykeeper.ScopedKeeper, +) Keeper +``` + +### ICS20 - Transfer + +The `key` parameter of the `NewKeeper` function in `modules/apps/transfer/keeper` is now of type `storetypes.StoreKey` (where `storetypes` is an import alias for `"github.com/cosmos/cosmos-sdk/store/types"`): + +```diff +func NewKeeper( + cdc codec.BinaryCodec, +- key sdk.StoreKey, ++ key storetypes.StoreKey, + paramSpace paramtypes.Subspace, + ics4Wrapper types.ICS4Wrapper, + channelKeeper types.ChannelKeeper, + portKeeper types.PortKeeper, + authKeeper types.AccountKeeper, + bankKeeper types.BankKeeper, + scopedKeeper capabilitykeeper.ScopedKeeper, +) Keeper +``` + +The `amount` parameter of function `GetTransferCoin` in `modules/apps/transfer/types` is now of type `math.Int` (`"cosmossdk.io/math"`): + +```diff +func GetTransferCoin( + portID, channelID, baseDenom string, +- amount sdk.Int ++ amount math.Int +) sdk.Coin +``` + +The `RegisterRESTRoutes` function in `modules/apps/transfer` has been removed. + +### ICS27 - Interchain Accounts + +The `key` and `msgRouter` parameters of the `NewKeeper` functions in + +- `modules/apps/27-interchain-accounts/controller/keeper` +- and `modules/apps/27-interchain-accounts/host/keeper` + +have changed type. The `key` parameter is now of type `storetypes.StoreKey` (where `storetypes` is an import alias for `"github.com/cosmos/cosmos-sdk/store/types"`), and the `msgRouter` parameter is now of type `*icatypes.MessageRouter` (where `icatypes` is an import alias for `"github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/types"`): + +```diff +// NewKeeper creates a new interchain accounts controller Keeper instance +func NewKeeper( + cdc codec.BinaryCodec, +- key sdk.StoreKey, ++ key storetypes.StoreKey, + paramSpace paramtypes.Subspace, + ics4Wrapper icatypes.ICS4Wrapper, + channelKeeper icatypes.ChannelKeeper, + portKeeper icatypes.PortKeeper, + scopedKeeper capabilitykeeper.ScopedKeeper, +- msgRouter *baseapp.MsgServiceRouter, ++ msgRouter *icatypes.MessageRouter, +) Keeper +``` + +```diff +// NewKeeper creates a new interchain accounts host Keeper instance +func NewKeeper( + cdc codec.BinaryCodec, +- key sdk.StoreKey, ++ key storetypes.StoreKey, + paramSpace paramtypes.Subspace, + channelKeeper icatypes.ChannelKeeper, + portKeeper icatypes.PortKeeper, + accountKeeper icatypes.AccountKeeper, + scopedKeeper capabilitykeeper.ScopedKeeper, +- msgRouter *baseapp.MsgServiceRouter, ++ msgRouter *icatypes.MessageRouter, +) Keeper +``` + +The new `MessageRouter` interface is defined as: + +```go +type MessageRouter interface { + Handler(msg sdk.Msg) baseapp.MsgServiceHandler +} +``` + +The `RegisterRESTRoutes` function in `modules/apps/27-interchain-accounts` has been removed. + +An additional parameter, `ics4Wrapper` has been added to the `host` submodule `NewKeeper` function in `modules/apps/27-interchain-accounts/host/keeper`. +This allows the `host` submodule to correctly unwrap the channel version for channel reopening handshakes in the `OnChanOpenTry` callback. + +```diff +func NewKeeper( + cdc codec.BinaryCodec, + key storetypes.StoreKey, + paramSpace paramtypes.Subspace, ++ ics4Wrapper icatypes.ICS4Wrapper, + channelKeeper icatypes.ChannelKeeper, + portKeeper icatypes.PortKeeper, + accountKeeper icatypes.AccountKeeper, + scopedKeeper icatypes.ScopedKeeper, + msgRouter icatypes.MessageRouter, +) Keeper +``` + +#### Cosmos SDK message handler responses in packet acknowledgement + +The construction of the transaction response of a message execution on the host chain has changed. The `Data` field in the `sdk.TxMsgData` has been deprecated and since Cosmos SDK 0.46 the `MsgResponses` field contains the message handler responses packed into `Any`s. + +For chains on Cosmos SDK 0.45 and below, the message response was constructed like this: + +```go +txMsgData := &sdk.TxMsgData{ + Data: make([]*sdk.MsgData, len(msgs)), +} + +for i, msg := range msgs { + // message validation + + msgResponse, err := k.executeMsg(cacheCtx, msg) + // return if err != nil + + txMsgData.Data[i] = &sdk.MsgData{ + MsgType: sdk.MsgTypeURL(msg), + Data: msgResponse, + } +} + +// emit events + +txResponse, err := proto.Marshal(txMsgData) +// return if err != nil + +return txResponse, nil +``` + +And for chains on Cosmos SDK 0.46 and above, it is now done like this: + +```go +txMsgData := &sdk.TxMsgData{ + MsgResponses: make([]*codectypes.Any, len(msgs)), +} + +for i, msg := range msgs { + // message validation + + protoAny, err := k.executeMsg(cacheCtx, msg) + // return if err != nil + + txMsgData.MsgResponses[i] = protoAny +} + +// emit events + +txResponse, err := proto.Marshal(txMsgData) +// return if err != nil + +return txResponse, nil +``` + +When handling the acknowledgement in the `OnAcknowledgementPacket` callback of a custom ICA controller module, then depending on whether `txMsgData.Data` is empty or not, the logic to handle the message handler response will be different. **Only controller chains on Cosmos SDK 0.46 or above will be able to write the logic needed to handle the response from a host chain on Cosmos SDK 0.46 or above.** + +```go +var ack channeltypes.Acknowledgement +if err := channeltypes.SubModuleCdc.UnmarshalJSON(acknowledgement, &ack); err != nil { + return err +} + +var txMsgData sdk.TxMsgData +if err := proto.Unmarshal(ack.GetResult(), txMsgData); err != nil { + return err +} + +switch len(txMsgData.Data) { +case 0: // for SDK 0.46 and above + for _, msgResponse := range txMsgData.MsgResponses { + // unmarshall msgResponse and execute logic based on the response + } + return nil +default: // for SDK 0.45 and below + for _, msgData := range txMsgData.Data { + // unmarshall msgData and execute logic based on the response + } +} +``` + +See [ADR-03](/architecture/adr-003-ics27-acknowledgement#next-major-version-format) for more information or the [corresponding documentation about authentication modules](../02-apps/02-interchain-accounts/03-auth-modules.md#onacknowledgementpacket). + +### ICS29 - Fee Middleware + +The `key` parameter of the `NewKeeper` function in `modules/apps/29-fee` is now of type `storetypes.StoreKey` (where `storetypes` is an import alias for `"github.com/cosmos/cosmos-sdk/store/types"`): + +```diff +func NewKeeper( + cdc codec.BinaryCodec, +- key sdk.StoreKey, ++ key storetypes.StoreKey, + paramSpace paramtypes.Subspace, + ics4Wrapper types.ICS4Wrapper, + channelKeeper types.ChannelKeeper, + portKeeper types.PortKeeper, + authKeeper types.AccountKeeper, + bankKeeper types.BankKeeper, +) Keeper +``` + +The `RegisterRESTRoutes` function in `modules/apps/29-fee` has been removed. + +### IBC testing package + +The `MockIBCApp` type has been renamed to `IBCApp` (and the corresponding constructor function to `NewIBCApp`). This has resulted therefore in: + +- The `IBCApp` field of the `*IBCModule` in `testing/mock` to change its type as well to `*IBCApp`: + +```diff +type IBCModule struct { + appModule *AppModule +- IBCApp *MockIBCApp // base application of an IBC middleware stack ++ IBCApp *IBCApp // base application of an IBC middleware stack +} +``` + +- The `app` parameter to `*NewIBCModule` in `testing/mock` to change its type as well to `*IBCApp`: + +```diff +func NewIBCModule( + appModule *AppModule, +- app *MockIBCApp ++ app *IBCApp +) IBCModule +``` + +The `MockEmptyAcknowledgement` type has been renamed to `EmptyAcknowledgement` (and the corresponding constructor function to `NewEmptyAcknowledgement`). + +The `TestingApp` interface in `testing` has gone through some modifications: + +- The return type of the function `GetStakingKeeper` is not the concrete type `stakingkeeper.Keeper` anymore (where `stakingkeeper` is an import alias for `"github.com/cosmos/cosmos-sdk/x/staking/keeper"`), but it has been changed to the interface `ibctestingtypes.StakingKeeper` (where `ibctestingtypes` is an import alias for `""github.com/cosmos/ibc-go/v5/testing/types"`). See this [PR](https://github.com/cosmos/ibc-go/pull/2028) for more details. The `StakingKeeper` interface is defined as: + +```go +type StakingKeeper interface { + GetHistoricalInfo(ctx sdk.Context, height int64) (stakingtypes.HistoricalInfo, bool) +} +``` + +- The return type of the function `LastCommitID` has changed to `storetypes.CommitID` (where `storetypes` is an import alias for `"github.com/cosmos/cosmos-sdk/store/types"`). + +See the following `git diff` for more details: + +```diff +type TestingApp interface { + abci.Application + + // ibc-go additions + GetBaseApp() *baseapp.BaseApp +- GetStakingKeeper() stakingkeeper.Keeper ++ GetStakingKeeper() ibctestingtypes.StakingKeeper + GetIBCKeeper() *keeper.Keeper + GetScopedIBCKeeper() capabilitykeeper.ScopedKeeper + GetTxConfig() client.TxConfig + + // Implemented by SimApp + AppCodec() codec.Codec + + // Implemented by BaseApp +- LastCommitID() sdk.CommitID ++ LastCommitID() storetypes.CommitID + LastBlockHeight() int64 +} +``` + +The `powerReduction` parameter of the function `SetupWithGenesisValSet` in `testing` is now of type `math.Int` (`"cosmossdk.io/math"`): + +```diff +func SetupWithGenesisValSet( + t *testing.T, + valSet *tmtypes.ValidatorSet, + genAccs []authtypes.GenesisAccount, + chainID string, +- powerReduction sdk.Int, ++ powerReduction math.Int, + balances ...banktypes.Balance +) TestingApp +``` + +The `accAmt` parameter of the functions + +- `AddTestAddrsFromPubKeys` , +- `AddTestAddrs` +- and `AddTestAddrsIncremental` + +in `testing/simapp` are now of type `math.Int` (`"cosmossdk.io/math"`): + +```diff +func AddTestAddrsFromPubKeys( + app *SimApp, + ctx sdk.Context, + pubKeys []cryptotypes.PubKey, +- accAmt sdk.Int, ++ accAmt math.Int +) +func addTestAddrs( + app *SimApp, + ctx sdk.Context, + accNum int, +- accAmt sdk.Int, ++ accAmt math.Int, + strategy GenerateAccountStrategy +) []sdk.AccAddress +func AddTestAddrsIncremental( + app *SimApp, + ctx sdk.Context, + accNum int, +- accAmt sdk.Int, ++ accAmt math.Int +) []sdk.AccAddress +``` + +The `RegisterRESTRoutes` function in `testing/mock` has been removed. + +## Relayers + +- No relevant changes were made in this release. + +## IBC Light Clients + +### ICS02 - Client + +The `key` parameter of the `NewKeeper` function in `modules/core/02-client/keeper` is now of type `storetypes.StoreKey` (where `storetypes` is an import alias for `"github.com/cosmos/cosmos-sdk/store/types"`): + +```diff +func NewKeeper( + cdc codec.BinaryCodec, +- key sdk.StoreKey, ++ key storetypes.StoreKey, + paramSpace paramtypes.Subspace, + sk types.StakingKeeper, + uk types.UpgradeKeeper +) Keeper +``` diff --git a/docs/versioned_docs/version-v9.0.x/05-migrations/07-v5-to-v6.md b/docs/versioned_docs/version-v9.0.x/05-migrations/07-v5-to-v6.md new file mode 100644 index 00000000000..4fc777e6cd9 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/05-migrations/07-v5-to-v6.md @@ -0,0 +1,299 @@ +--- +title: IBC-Go v5 to v6 +sidebar_label: IBC-Go v5 to v6 +sidebar_position: 7 +slug: /migrations/v5-to-v6 +--- + +# Migrating from ibc-go v5 to v6 + +This document is intended to highlight significant changes which may require more information than presented in the CHANGELOG. +Any changes that must be done by a user of ibc-go should be documented here. + +There are four sections based on the four potential user groups of this document: + +- Chains +- IBC Apps +- Relayers +- IBC Light Clients + +**Note:** ibc-go supports golang semantic versioning and therefore all imports must be updated to bump the version number on major releases. + +## Chains + +The `ibc-go/v6` release introduces a new set of migrations for `27-interchain-accounts`. Ownership of ICS27 channel capabilities is transferred from ICS27 authentication modules and will now reside with the ICS27 controller submodule moving forward. + +For chains which contain a custom authentication module using the ICS27 controller submodule this requires a migration function to be included in the chain upgrade handler. A subsequent migration handler is run automatically, asserting the ownership of ICS27 channel capabilities has been transferred successfully. + +This migration is not required for chains which *do not* contain a custom authentication module using the ICS27 controller submodule. + +This migration facilitates the addition of the ICS27 controller submodule `MsgServer` which provides a standardised approach to integrating existing forms of authentication such as `x/gov` and `x/group` provided by the Cosmos SDK. + +For more information please refer to [ADR 009](/architecture/adr-009-v6-ics27-msgserver). + +### Upgrade proposal + +Please refer to [PR #2383](https://github.com/cosmos/ibc-go/pull/2383) for integrating the ICS27 channel capability migration logic or follow the steps outlined below: + +1. Add the upgrade migration logic to chain distribution. This may be, for example, maintained under a package `app/upgrades/v6`. + +```go +package v6 + +import ( + "github.com/cosmos/cosmos-sdk/codec" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + + v6 "github.com/cosmos/ibc-go/v6/modules/apps/27-interchain-accounts/controller/migrations/v6" +) + +const ( + UpgradeName = "v6" +) + +func CreateUpgradeHandler( + mm *module.Manager, + configurator module.Configurator, + cdc codec.BinaryCodec, + capabilityStoreKey *storetypes.KVStoreKey, + capabilityKeeper *capabilitykeeper.Keeper, + moduleName string, +) upgradetypes.UpgradeHandler { + return func(ctx sdk.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { + if err := v6.MigrateICS27ChannelCapability(ctx, cdc, capabilityStoreKey, capabilityKeeper, moduleName); err != nil { + return nil, err + } + + return mm.RunMigrations(ctx, configurator, vm) + } +} +``` + +2. Set the upgrade handler in `app.go`. The `moduleName` parameter refers to the authentication module's `ScopedKeeper` name. This is the name provided upon instantiation in `app.go` via the [`x/capability` keeper `ScopeToModule(moduleName string)`](https://github.com/cosmos/cosmos-sdk/blob/v0.46.1/x/capability/keeper/keeper.go#L70) method. [See here for an example in `simapp`](https://github.com/cosmos/ibc-go/blob/v5.0.0/testing/simapp/app.go#L304). + +```go +app.UpgradeKeeper.SetUpgradeHandler( + v6.UpgradeName, + v6.CreateUpgradeHandler( + app.mm, + app.configurator, + app.appCodec, + app.keys[capabilitytypes.ModuleName], + app.CapabilityKeeper, + >>>> moduleName <<<<, + ), +) +``` + +## IBC Apps + +### ICS27 - Interchain Accounts + +#### Controller APIs + +In previous releases of ibc-go, chain developers integrating the ICS27 interchain accounts controller functionality were expected to create a custom `Base Application` referred to as an authentication module, see the section [Building an authentication module](../02-apps/02-interchain-accounts/03-auth-modules.md) from the documentation. + +The `Base Application` was intended to be composed with the ICS27 controller submodule `Keeper` and facilitate many forms of message authentication depending on a chain's particular use case. + +Prior to ibc-go v6 the controller submodule exposed only these two functions (to which we will refer as the legacy APIs): + +- [`RegisterInterchainAccount`](https://github.com/cosmos/ibc-go/blob/v5.0.0/modules/apps/27-interchain-accounts/controller/keeper/account.go#L19) +- [`SendTx`](https://github.com/cosmos/ibc-go/blob/v5.0.0/modules/apps/27-interchain-accounts/controller/keeper/relay.go#L18) + +However, these functions have now been deprecated in favour of the new controller submodule `MsgServer` and will be removed in later releases. + +Both APIs remain functional and maintain backwards compatibility in ibc-go v6, however consumers of these APIs are now recommended to follow the message passing paradigm outlined in Cosmos SDK [ADR 031](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-031-msg-service.md) and [ADR 033](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-033-protobuf-inter-module-comm.md). This is facilitated by the Cosmos SDK [`MsgServiceRouter`](https://github.com/cosmos/cosmos-sdk/blob/main/baseapp/msg_service_router.go#L17) and chain developers creating custom application logic can now omit the ICS27 controller submodule `Keeper` from their module and instead depend on message routing. + +Depending on the use case, developers of custom authentication modules face one of three scenarios: + +![auth-module-decision-tree.png](./images/auth-module-decision-tree.png) + +**My authentication module needs to access IBC packet callbacks** + +Application developers that wish to consume IBC packet callbacks and react upon packet acknowledgements **must** continue using the controller submodule's legacy APIs. The authentication modules will not need a `ScopedKeeper` anymore, though, because the channel capability will be claimed by the controller submodule. For example, given an Interchain Accounts authentication module keeper `ICAAuthKeeper`, the authentication module's `ScopedKeeper` (`scopedICAAuthKeeper`) is not needed anymore and can be removed for the argument list of the keeper constructor function, as shown here: + +```diff +app.ICAAuthKeeper = icaauthkeeper.NewKeeper( + appCodec, + keys[icaauthtypes.StoreKey], + app.ICAControllerKeeper, +- scopedICAAuthKeeper, +) +``` + +Please note that the authentication module's `ScopedKeeper` name is still needed as part of the channel capability migration described in section [Upgrade proposal](#upgrade-proposal) above. Therefore the authentication module's `ScopedKeeper` cannot be completely removed from the chain code until the migration has run. + +In the future, the use of the legacy APIs for accessing packet callbacks will be replaced by IBC Actor Callbacks (see [ADR 008](https://github.com/cosmos/ibc-go/pull/1976) for more details) and it will also be possible to access them with the `MsgServiceRouter`. + +**My authentication module does not need access to IBC packet callbacks** + +The authentication module can migrate from using the legacy APIs and it can be composed instead with the `MsgServiceRouter`, so that the authentication module is able to pass messages to the controller submodule's `MsgServer` to register interchain accounts and send packets to the interchain account. For example, given an Interchain Accounts authentication module keeper `ICAAuthKeeper`, the ICS27 controller submodule keeper (`ICAControllerKeeper`) and authentication module scoped keeper (`scopedICAAuthKeeper`) are not needed anymore and can be replaced with the `MsgServiceRouter`, as shown here: + +```diff +app.ICAAuthKeeper = icaauthkeeper.NewKeeper( + appCodec, + keys[icaauthtypes.StoreKey], +- app.ICAControllerKeeper, +- scopedICAAuthKeeper, ++ app.MsgServiceRouter(), +) +``` + +In your authentication module you can route messages to the controller submodule's `MsgServer` instead of using the legacy APIs. For example, for registering an interchain account: + +```diff +- if err := keeper.icaControllerKeeper.RegisterInterchainAccount( +- ctx, +- connectionID, +- owner.String(), +- version, +- ); err != nil { +- return err +- } ++ msg := controllertypes.NewMsgRegisterInterchainAccount( ++ connectionID, ++ owner.String(), ++ version, ++ ) ++ handler := keeper.msgRouter.Handler(msg) ++ res, err := handler(ctx, msg) ++ if err != nil { ++ return err ++ } +``` + +where `controllertypes` is an import alias for `"github.com/cosmos/ibc-go/v6/modules/apps/27-interchain-accounts/controller/types"`. + +In addition, in this use case the authentication module does not need to implement the `IBCModule` interface anymore. + +**I do not need a custom authentication module anymore** + +If your authentication module does not have any extra functionality compared to the default authentication module added in ibc-go v6 (the `MsgServer`), or if you can use a generic authentication module, such as the `x/auth`, `x/gov` or `x/group` modules from the Cosmos SDK (v0.46 and later), then you can remove your authentication module completely and use instead the gRPC endpoints of the `MsgServer` or the CLI added in ibc-go v6. + +Please remember that the authentication module's `ScopedKeeper` name is still needed as part of the channel capability migration described in section [Upgrade proposal](#upgrade-proposal) above. + +#### Host params + +The ICS27 host submodule default params have been updated to include the `AllowAllHostMsgs` wildcard `*`. +This enables execution of any `sdk.Msg` type for ICS27 registered on the host chain `InterfaceRegistry`. + +```diff +// AllowAllHostMsgs holds the string key that allows all message types on interchain accounts host module +const AllowAllHostMsgs = "*" + +... + +// DefaultParams is the default parameter configuration for the host submodule +func DefaultParams() Params { +- return NewParams(DefaultHostEnabled, nil) ++ return NewParams(DefaultHostEnabled, []string{AllowAllHostMsgs}) +} +``` + +#### API breaking changes + +`SerializeCosmosTx` takes in a `[]proto.Message` instead of `[]sdk.Message`. This allows for the serialization of proto messages without requiring the fulfillment of the `sdk.Msg` interface. + +The `27-interchain-accounts` genesis types have been moved to their own package: `modules/apps/27-interchain-acccounts/genesis/types`. +This change facilitates the addition of the ICS27 controller submodule `MsgServer` and avoids cyclic imports. This should have minimal disruption to chain developers integrating `27-interchain-accounts`. + +The ICS27 host submodule `NewKeeper` function in `modules/apps/27-interchain-acccounts/host/keeper` now includes an additional parameter of type `ICS4Wrapper`. +This provides the host submodule with the ability to correctly unwrap channel versions in the event of a channel reopening handshake. + +```diff +func NewKeeper( + cdc codec.BinaryCodec, key storetypes.StoreKey, paramSpace paramtypes.Subspace, +- channelKeeper icatypes.ChannelKeeper, portKeeper icatypes.PortKeeper, ++ ics4Wrapper icatypes.ICS4Wrapper, channelKeeper icatypes.ChannelKeeper, portKeeper icatypes.PortKeeper, + accountKeeper icatypes.AccountKeeper, scopedKeeper icatypes.ScopedKeeper, msgRouter icatypes.MessageRouter, +) Keeper +``` + +### ICS29 - `NewKeeper` API change + +The `NewKeeper` function of ICS29 has been updated to remove the `paramSpace` parameter as it was unused. + +```diff +func NewKeeper( +- cdc codec.BinaryCodec, key storetypes.StoreKey, paramSpace paramtypes.Subspace, +- ics4Wrapper types.ICS4Wrapper, channelKeeper types.ChannelKeeper, portKeeper types.PortKeeper, authKeeper types.AccountKeeper, bankKeeper types.BankKeeper, ++ cdc codec.BinaryCodec, key storetypes.StoreKey, ++ ics4Wrapper types.ICS4Wrapper, channelKeeper types.ChannelKeeper, ++ portKeeper types.PortKeeper, authKeeper types.AccountKeeper, bankKeeper types.BankKeeper, +) Keeper { +``` + +### ICS20 - `SendTransfer` is no longer exported + +The `SendTransfer` function of ICS20 has been removed. IBC transfers should now be initiated with `MsgTransfer` and routed to the ICS20 `MsgServer`. + +See below for example: + +```go +if handler := msgRouter.Handler(msgTransfer); handler != nil { + if err := msgTransfer.ValidateBasic(); err != nil { + return nil, err + } + + res, err := handler(ctx, msgTransfer) + if err != nil { + return nil, err + } +} +``` + +### ICS04 - `SendPacket` API change + +The `SendPacket` API has been simplified: + +```diff +// SendPacket is called by a module in order to send an IBC packet on a channel +func (k Keeper) SendPacket( + ctx sdk.Context, + channelCap *capabilitytypes.Capability, +- packet exported.PacketI, +-) error { ++ sourcePort string, ++ sourceChannel string, ++ timeoutHeight clienttypes.Height, ++ timeoutTimestamp uint64, ++ data []byte, ++) (uint64, error) { +``` + +Callers no longer need to pass in a pre-constructed packet. +The destination port/channel identifiers and the packet sequence will be determined by core IBC. +`SendPacket` will return the packet sequence. + +### IBC testing package + +The `SendPacket` API has been simplified: + +```diff +// SendPacket is called by a module in order to send an IBC packet on a channel +func (k Keeper) SendPacket( + ctx sdk.Context, + channelCap *capabilitytypes.Capability, +- packet exported.PacketI, +-) error { ++ sourcePort string, ++ sourceChannel string, ++ timeoutHeight clienttypes.Height, ++ timeoutTimestamp uint64, ++ data []byte, ++) (uint64, error) { +``` + +Callers no longer need to pass in a pre-constructed packet. `SendPacket` will return the packet sequence. + +## Relayers + +- No relevant changes were made in this release. + +## IBC Light Clients + +- No relevant changes were made in this release. diff --git a/docs/versioned_docs/version-v9.0.x/05-migrations/08-v6-to-v7.md b/docs/versioned_docs/version-v9.0.x/05-migrations/08-v6-to-v7.md new file mode 100644 index 00000000000..da47b395021 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/05-migrations/08-v6-to-v7.md @@ -0,0 +1,357 @@ +--- +title: IBC-Go v6 to v7 +sidebar_label: IBC-Go v6 to v7 +sidebar_position: 8 +slug: /migrations/v6-to-v7 +--- +# Migrating from ibc-go v6 to v7 + +This document is intended to highlight significant changes which may require more information than presented in the CHANGELOG. +Any changes that must be done by a user of ibc-go should be documented here. + +There are four sections based on the four potential user groups of this document: + +- Chains +- IBC Apps +- Relayers +- IBC Light Clients + +**Note:** ibc-go supports golang semantic versioning and therefore all imports must be updated to bump the version number on major releases. + +## Chains + +Chains will perform automatic migrations to remove existing localhost clients and to migrate the solomachine to v3 of the protobuf definition. + +An optional upgrade handler has been added to prune expired tendermint consensus states. It may be used during any upgrade (from v7 onwards). +Add the following to the function call to the upgrade handler in `app/app.go`, to perform the optional state pruning. + +```go +import ( + // ... + ibctmmigrations "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint/migrations" +) + +// ... + +app.UpgradeKeeper.SetUpgradeHandler( + upgradeName, + func(ctx sdk.Context, _ upgradetypes.Plan, _ module.VersionMap) (module.VersionMap, error) { + // prune expired tendermint consensus states to save storage space + _, err := ibctmmigrations.PruneExpiredConsensusStates(ctx, app.Codec, app.IBCKeeper.ClientKeeper) + if err != nil { + return nil, err + } + + return app.mm.RunMigrations(ctx, app.configurator, fromVM) + }, +) +``` + +Checkout the logs to see how many consensus states are pruned. + +### Light client registration + +Chains must explicitly register the types of any light client modules it wishes to integrate. + +#### Tendermint registration + +To register the tendermint client, modify the `app.go` file to include the tendermint `AppModuleBasic`: + +```diff +import ( + // ... ++ ibctm "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" +) + +// ... + +ModuleBasics = module.NewBasicManager( + ... + ibc.AppModuleBasic{}, ++ ibctm.AppModuleBasic{}, + ... +) +``` + +It may be useful to reference the [PR](https://github.com/cosmos/ibc-go/pull/2825) which added the `AppModuleBasic` for the tendermint client. + +#### Solo machine registration + +To register the solo machine client, modify the `app.go` file to include the solo machine `AppModuleBasic`: + +```diff +import ( + // ... ++ solomachine "github.com/cosmos/ibc-go/v7/modules/light-clients/06-solomachine" +) + +// ... + +ModuleBasics = module.NewBasicManager( + ... + ibc.AppModuleBasic{}, ++ solomachine.AppModuleBasic{}, + ... +) +``` + +It may be useful to reference the [PR](https://github.com/cosmos/ibc-go/pull/2826) which added the `AppModuleBasic` for the solo machine client. + +### Testing package API + +The `SetChannelClosed` utility method in `testing/endpoint.go` has been updated to `SetChannelState`, which will take a `channeltypes.State` argument so that the `ChannelState` can be set to any of the possible channel states. + +## IBC Apps + +- No relevant changes were made in this release. + +## Relayers + +- No relevant changes were made in this release. + +## IBC Light Clients + +### `ClientState` interface changes + +The `VerifyUpgradeAndUpdateState` function has been modified. The client state and consensus state return values have been removed. + +Light clients **must** handle all management of client and consensus states including the setting of updated client state and consensus state in the client store. + +The `Initialize` method is now expected to set the initial client state, consensus state and any client-specific metadata in the provided store upon client creation. + +The `CheckHeaderAndUpdateState` method has been split into 4 new methods: + +- `VerifyClientMessage` verifies a `ClientMessage`. A `ClientMessage` could be a `Header`, `Misbehaviour`, or batch update. Calls to `CheckForMisbehaviour`, `UpdateState`, and `UpdateStateOnMisbehaviour` will assume that the content of the `ClientMessage` has been verified and can be trusted. An error should be returned if the `ClientMessage` fails to verify. + +- `CheckForMisbehaviour` checks for evidence of a misbehaviour in `Header` or `Misbehaviour` types. + +- `UpdateStateOnMisbehaviour` performs appropriate state changes on a `ClientState` given that misbehaviour has been detected and verified. + +- `UpdateState` updates and stores as necessary any associated information for an IBC client, such as the `ClientState` and corresponding `ConsensusState`. An error is returned if `ClientMessage` is of type `Misbehaviour`. Upon successful update, a list containing the updated consensus state height is returned. + +The `CheckMisbehaviourAndUpdateState` function has been removed from `ClientState` interface. This functionality is now encapsulated by the usage of `VerifyClientMessage`, `CheckForMisbehaviour`, `UpdateStateOnMisbehaviour`. + +The function `GetTimestampAtHeight` has been added to the `ClientState` interface. It should return the timestamp for a consensus state associated with the provided height. + +Prior to ibc-go/v7 the `ClientState` interface defined a method for each data type which was being verified in the counterparty state store. +The state verification functions for all IBC data types have been consolidated into two generic methods, `VerifyMembership` and `VerifyNonMembership`. +Both are expected to be provided with a standardised key path, `exported.Path`, as defined in [ICS 24 host requirements](https://github.com/cosmos/ibc/tree/main/spec/core/ics-024-host-requirements). Membership verification requires callers to provide the marshalled value `[]byte`. Delay period values should be zero for non-packet processing verification. A zero proof height is now allowed by core IBC and may be passed into `VerifyMembership` and `VerifyNonMembership`. Light clients are responsible for returning an error if a zero proof height is invalid behaviour. + +See below for an example of how ibc-go now performs channel state verification. + +```go +merklePath := commitmenttypes.NewMerklePath(host.ChannelPath(portID, channelID)) +merklePath, err := commitmenttypes.ApplyPrefix(connection.GetCounterparty().GetPrefix(), merklePath) +if err != nil { + return err +} + +channelEnd, ok := channel.(channeltypes.Channel) +if !ok { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "invalid channel type %T", channel) +} + +bz, err := k.cdc.Marshal(&channelEnd) +if err != nil { + return err +} + +if err := clientState.VerifyMembership( + ctx, clientStore, k.cdc, height, + 0, 0, // skip delay period checks for non-packet processing verification + proof, merklePath, bz, +); err != nil { + return sdkerrors.Wrapf(err, "failed channel state verification for client (%s)", clientID) +} +``` + +### `Header` and `Misbehaviour` + +`exported.Header` and `exported.Misbehaviour` interface types have been merged and renamed to `ClientMessage` interface. + +`GetHeight` function has been removed from `exported.Header` and thus is not included in the `ClientMessage` interface + +### `ConsensusState` + +The `GetRoot` function has been removed from consensus state interface since it was not used by core IBC. + +### Client keeper + +Keeper function `CheckMisbehaviourAndUpdateState` has been removed since function `UpdateClient` can now handle updating `ClientState` on `ClientMessage` type which can be any `Misbehaviour` implementations. + +### SDK message + +`MsgSubmitMisbehaviour` is deprecated since `MsgUpdateClient` can now submit a `ClientMessage` type which can be any `Misbehaviour` implementations. + +The field `header` in `MsgUpdateClient` has been renamed to `client_message`. + +## Solomachine + +The `06-solomachine` client implementation has been simplified in ibc-go/v7. In-place store migrations have been added to migrate solomachine clients from `v2` to `v3`. + +### `ClientState` + +The `ClientState` protobuf message definition has been updated to remove the deprecated `bool` field `allow_update_after_proposal`. + +```diff +message ClientState { + option (gogoproto.goproto_getters) = false; + + uint64 sequence = 1; + bool is_frozen = 2 [(gogoproto.moretags) = "yaml:\"is_frozen\""]; + ConsensusState consensus_state = 3 [(gogoproto.moretags) = "yaml:\"consensus_state\""]; +- bool allow_update_after_proposal = 4 [(gogoproto.moretags) = "yaml:\"allow_update_after_proposal\""]; +} +``` + +### `Header` and `Misbehaviour` + +The `06-solomachine` protobuf message `Header` has been updated to remove the `sequence` field. This field was seen as redundant as the implementation can safely rely on the `sequence` value maintained within the `ClientState`. + +```diff +message Header { + option (gogoproto.goproto_getters) = false; + +- uint64 sequence = 1; +- uint64 timestamp = 2; +- bytes signature = 3; +- google.protobuf.Any new_public_key = 4 [(gogoproto.moretags) = "yaml:\"new_public_key\""]; +- string new_diversifier = 5 [(gogoproto.moretags) = "yaml:\"new_diversifier\""]; ++ uint64 timestamp = 1; ++ bytes signature = 2; ++ google.protobuf.Any new_public_key = 3 [(gogoproto.moretags) = "yaml:\"new_public_key\""]; ++ string new_diversifier = 4 [(gogoproto.moretags) = "yaml:\"new_diversifier\""]; +} +``` + +Similarly, the `Misbehaviour` protobuf message has been updated to remove the `client_id` field. + +```diff +message Misbehaviour { + option (gogoproto.goproto_getters) = false; + +- string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""]; +- uint64 sequence = 2; +- SignatureAndData signature_one = 3 [(gogoproto.moretags) = "yaml:\"signature_one\""]; +- SignatureAndData signature_two = 4 [(gogoproto.moretags) = "yaml:\"signature_two\""]; ++ uint64 sequence = 1; ++ SignatureAndData signature_one = 2 [(gogoproto.moretags) = "yaml:\"signature_one\""]; ++ SignatureAndData signature_two = 3 [(gogoproto.moretags) = "yaml:\"signature_two\""]; +} +``` + +### `SignBytes` + +Most notably, the `SignBytes` protobuf definition has been modified to replace the `data_type` field with a new field, `path`. The `path` field is defined as `bytes` and represents a serialized [ICS-24](https://github.com/cosmos/ibc/tree/main/spec/core/ics-024-host-requirements) standardized key path under which the `data` is stored. + +```diff +message SignBytes { + option (gogoproto.goproto_getters) = false; + + uint64 sequence = 1; + uint64 timestamp = 2; + string diversifier = 3; +- DataType data_type = 4 [(gogoproto.moretags) = "yaml:\"data_type\""]; ++ bytes path = 4; + bytes data = 5; +} +``` + +The `DataType` enum and all associated data types have been removed, greatly reducing the number of message definitions and complexity in constructing the `SignBytes` message type. Likewise, solomachine implementations must now use the serialized `path` value when constructing `SignatureAndData` for signature verification of `SignBytes` data. + +```diff +message SignatureAndData { + option (gogoproto.goproto_getters) = false; + + bytes signature = 1; +- DataType data_type = 2 [(gogoproto.moretags) = "yaml:\"data_type\""]; ++ bytes path = 2; + bytes data = 3; + uint64 timestamp = 4; +} +``` + +For more information, please refer to [ADR-007](https://github.com/cosmos/ibc-go/blob/02-client-refactor-beta1/docs/architecture/adr-007-solomachine-signbytes.md). + +### IBC module constants + +IBC module constants have been moved from the `host` package to the `exported` package. Any usages will need to be updated. + +```diff +import ( + // ... +- host "github.com/cosmos/ibc-go/v7/modules/core/24-host" ++ ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" + // ... +) + +- host.ModuleName ++ ibcexported.ModuleName + +- host.StoreKey ++ ibcexported.StoreKey + +- host.QuerierRoute ++ ibcexported.QuerierRoute + +- host.RouterKey ++ ibcexported.RouterKey +``` + +## Upgrading to Cosmos SDK 0.47 + +The following should be considered as complementary to [Cosmos SDK v0.47 UPGRADING.md](https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc2/UPGRADING.md). + +### Protobuf + +Protobuf code generation, linting and formatting have been updated to leverage the `ghcr.io/cosmos/proto-builder:0.11.5` docker container. IBC protobuf definitions are now packaged and published to [buf.build/cosmos/ibc](https://buf.build/cosmos/ibc) via CI workflows. The `third_party/proto` directory has been removed in favour of dependency management using [buf.build](https://docs.buf.build/introduction). + +### App modules + +Legacy APIs of the `AppModule` interface have been removed from ibc-go modules. For example, for + +```diff +- // Route implements the AppModule interface +- func (am AppModule) Route() sdk.Route { +- return sdk.Route{} +- } +- +- // QuerierRoute implements the AppModule interface +- func (AppModule) QuerierRoute() string { +- return types.QuerierRoute +- } +- +- // LegacyQuerierHandler implements the AppModule interface +- func (am AppModule) LegacyQuerierHandler(*codec.LegacyAmino) sdk.Querier { +- return nil +- } +- +- // ProposalContents doesn't return any content functions for governance proposals. +- func (AppModule) ProposalContents(_ module.SimulationState) []simtypes.WeightedProposalContent { +- return nil +- } +``` + +### Imports + +Imports for ics23 have been updated as the repository have been migrated from confio to cosmos. + +```diff +import ( + // ... +- ics23 "github.com/confio/ics23/go" ++ ics23 "github.com/cosmos/ics23/go" + // ... +) +``` + +Imports for gogoproto have been updated. + +```diff +import ( + // ... +- "github.com/gogo/protobuf/proto" ++ "github.com/cosmos/gogoproto/proto" + // ... +) +``` diff --git a/docs/versioned_docs/version-v9.0.x/05-migrations/09-v7-to-v7_1.md b/docs/versioned_docs/version-v9.0.x/05-migrations/09-v7-to-v7_1.md new file mode 100644 index 00000000000..30d9578dbc2 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/05-migrations/09-v7-to-v7_1.md @@ -0,0 +1,66 @@ +--- +title: IBC-Go v7 to v7.1 +sidebar_label: IBC-Go v7 to v7.1 +sidebar_position: 9 +slug: /migrations/v7-to-v7_1 +--- + +# Migrating from v7 to v7.1 + +This guide provides instructions for migrating to version `v7.1.0` of ibc-go. + +There are four sections based on the four potential user groups of this document: + +- [Migrating from v7 to v7.1](#migrating-from-v7-to-v71) + - [Chains](#chains) + - [IBC Apps](#ibc-apps) + - [Relayers](#relayers) + - [IBC Light Clients](#ibc-light-clients) + +**Note:** ibc-go supports golang semantic versioning and therefore all imports must be updated on major version releases. + +## Chains + +In the previous release of ibc-go, the localhost `v1` light client module was deprecated and removed. The ibc-go `v7.1.0` release introduces `v2` of the 09-localhost light client module. + +An [automatic migration handler](https://github.com/cosmos/ibc-go/blob/v7.2.0/modules/core/module.go#L127-L145) is configured in the core IBC module to set the localhost `ClientState` and sentinel `ConnectionEnd` in state. + +In order to use the 09-localhost client chains must update the `AllowedClients` parameter in the 02-client submodule of core IBC. This can be configured directly in the application upgrade handler or alternatively updated via the legacy governance parameter change proposal. +We **strongly** recommend chains to perform this action so that intra-ledger communication can be carried out using the familiar IBC interfaces. + +See the upgrade handler code sample provided below or [follow this link](https://github.com/cosmos/ibc-go/blob/v7.2.0/testing/simapp/upgrades/upgrades.go#L85) for the upgrade handler used by the ibc-go simapp. + +```go +func CreateV7LocalhostUpgradeHandler( + mm *module.Manager, + configurator module.Configurator, + clientKeeper clientkeeper.Keeper, +) upgradetypes.UpgradeHandler { + return func(ctx sdk.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { + // explicitly update the IBC 02-client params, adding the localhost client type + params := clientKeeper.GetParams(ctx) + params.AllowedClients = append(params.AllowedClients, exported.Localhost) + clientKeeper.SetParams(ctx, params) + + return mm.RunMigrations(ctx, configurator, vm) + } +} +``` + +### Transfer migration + +An [automatic migration handler](https://github.com/cosmos/ibc-go/blob/v7.2.0/modules/apps/transfer/module.go#L111-L113) is configured in the transfer module to set the total amount in escrow for all denominations of coins that have been sent out. For each denomination a state entry is added with the total amount of coins in escrow regardless of the channel from which they were transferred. + +## IBC Apps + +- No relevant changes were made in this release. + +## Relayers + +The event attribute `packet_connection` (`connectiontypes.AttributeKeyConnection`) has been deprecated. +Please use the `connection_id` attribute (`connectiontypes.AttributeKeyConnectionID`) which is emitted by all channel events. +Only send packet, receive packet, write acknowledgement, and acknowledge packet events used `packet_connection` previously. + +## IBC Light Clients + +- No relevant changes were made in this release. diff --git a/docs/versioned_docs/version-v9.0.x/05-migrations/10-v7_2-to-v7_3.md b/docs/versioned_docs/version-v9.0.x/05-migrations/10-v7_2-to-v7_3.md new file mode 100644 index 00000000000..8fc76f67c27 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/05-migrations/10-v7_2-to-v7_3.md @@ -0,0 +1,50 @@ +--- +title: IBC-Go v7.2 to v7.3 +sidebar_label: IBC-Go v7.2 to v7.3 +sidebar_position: 10 +slug: /migrations/v7_2-to-v7_3 +--- + +# Migrating from v7.2 to v7.3 + +This guide provides instructions for migrating to version `v7.3.0` of ibc-go. + +There are four sections based on the four potential user groups of this document: + +- [Migrating from v7.2 to v7.3](#migrating-from-v72-to-v73) + - [Chains](#chains) + - [IBC Apps](#ibc-apps) + - [Relayers](#relayers) + - [IBC Light Clients](#ibc-light-clients) + +**Note:** ibc-go supports golang semantic versioning and therefore all imports must be updated on major version releases. + +## Chains + +- No relevant changes were made in this release. + +## IBC Apps + +A set of interfaces have been added that IBC applications may optionally implement. Developers interested in integrating their applications with the [callbacks middleware](../04-middleware/02-callbacks/01-overview.md) should implement these interfaces so that the callbacks middleware can retrieve the desired callback addresses on the source and destination chains and execute actions on packet lifecycle events. The interfaces are [`PacketDataUnmarshaler`](https://github.com/cosmos/ibc-go/blob/v7.3.0-rc1/modules/core/05-port/types/module.go#L142-L147), [`PacketDataProvider`](https://github.com/cosmos/ibc-go/blob/v7.3.0-rc1/modules/core/exported/packet.go#L43-L52) and [`PacketData`](https://github.com/cosmos/ibc-go/blob/v7.3.0-rc1/modules/core/exported/packet.go#L36-L41). + +Sample implementations are available for reference. For `transfer`: + +- [`PacketDataUnmarshaler`](https://github.com/cosmos/ibc-go/blob/v7.3.0-rc1/modules/apps/transfer/ibc_module.go#L303-L313), +- [`PacketDataProvider`](https://github.com/cosmos/ibc-go/blob/v7.3.0-rc1/modules/apps/transfer/types/packet.go#L85-L105) +- and [`PacketData`](https://github.com/cosmos/ibc-go/blob/v7.3.0-rc1/modules/apps/transfer/types/packet.go#L74-L83). + +For `27-interchain-accounts`: + +- [`PacketDataUnmarshaler`](https://github.com/cosmos/ibc-go/blob/v7.3.0-rc1/modules/apps/27-interchain-accounts/controller/ibc_middleware.go#L258-L268), +- [`PacketDataProvider`](https://github.com/cosmos/ibc-go/blob/v7.3.0-rc1/modules/apps/27-interchain-accounts/types/packet.go#L94-L114) +- and [`PacketData`](https://github.com/cosmos/ibc-go/blob/v7.3.0-rc1/modules/apps/27-interchain-accounts/types/packet.go#L78-L92). + +## Relayers + +- No relevant changes were made in this release. + +## IBC Light Clients + +### 06-solomachine + +Solo machines are now expected to sign data on a path that 1) does not include a connection prefix (e.g `ibc`) and 2) does not escape any characters. See PR [#4429](https://github.com/cosmos/ibc-go/pull/4429) for more details. We recommend **NOT** using the solo machine light client of versions lower than v7.3.0. diff --git a/docs/versioned_docs/version-v9.0.x/05-migrations/11-v7-to-v8.md b/docs/versioned_docs/version-v9.0.x/05-migrations/11-v7-to-v8.md new file mode 100644 index 00000000000..e8d106de361 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/05-migrations/11-v7-to-v8.md @@ -0,0 +1,221 @@ +--- +title: IBC-Go v7 to v8 +sidebar_label: IBC-Go v7 to v8 +sidebar_position: 11 +slug: /migrations/v7-to-v8 +--- + +# Migrating from v7 to v8 + +This guide provides instructions for migrating to version `v8.0.0` of ibc-go. + +There are four sections based on the four potential user groups of this document: + +- [Migrating from v7 to v8](#migrating-from-v7-to-v8) + - [Chains](#chains) + - [Cosmos SDK v0.50 upgrade](#cosmos-sdk-v050-upgrade) + - [Authority](#authority) + - [Testing package](#testing-package) + - [Params migration](#params-migration) + - [Governance V1 migration](#governance-v1-migration) + - [Transfer migration](#transfer-migration) + - [IBC Apps](#ibc-apps) + - [ICS20 - Transfer](#ics20---transfer) + - [ICS27 - Interchain Accounts](#ics27---interchain-accounts) + - [Relayers](#relayers) + - [IBC Light Clients](#ibc-light-clients) + +**Note:** ibc-go supports golang semantic versioning and therefore all imports must be updated on major version releases. + +## Chains + +The type of the `PortKeeper` field of the IBC keeper have been changed to `*portkeeper.Keeper`: + +```diff +// Keeper defines each ICS keeper for IBC +type Keeper struct { + // implements gRPC QueryServer interface + types.QueryServer + + cdc codec.BinaryCodec + + ClientKeeper clientkeeper.Keeper + ConnectionKeeper connectionkeeper.Keeper + ChannelKeeper channelkeeper.Keeper +- PortKeeper portkeeper.Keeper ++ PortKeeper *portkeeper.Keeper + Router *porttypes.Router + + authority string +} +``` + +See [this PR](https://github.com/cosmos/ibc-go/pull/4703/files#diff-d18972debee5e64f16e40807b2ae112ddbe609504a93ea5e1c80a5d489c3a08a) for the changes required in `app.go`. + +An extra parameter `totalEscrowed` of type `sdk.Coins` has been added to transfer module's [`NewGenesisState` function](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/apps/transfer/types/genesis.go#L10). This parameter specifies the total amount of tokens that are in the module's escrow accounts. + +### Cosmos SDK v0.50 upgrade + +Version `v8.0.0` of ibc-go upgrades to Cosmos SDK v0.50. Please follow the [Cosmos SDK v0.50 upgrading guide](https://github.com/cosmos/cosmos-sdk/blob/v0.50.1/UPGRADING.md) to account for its API breaking changes. + +### Authority + +An authority identifier (e.g. an address) needs to be passed in the `NewKeeper` functions of the following keepers: + +- You must pass the `authority` to the ica/host keeper (implemented in [#3520](https://github.com/cosmos/ibc-go/pull/3520)). See [diff](https://github.com/cosmos/ibc-go/pull/3520/files#diff-d18972debee5e64f16e40807b2ae112ddbe609504a93ea5e1c80a5d489c3a08a): + +```diff +// app.go + +// ICA Host keeper +app.ICAHostKeeper = icahostkeeper.NewKeeper( + appCodec, keys[icahosttypes.StoreKey], app.GetSubspace(icahosttypes.SubModuleName), + app.IBCFeeKeeper, // use ics29 fee as ics4Wrapper in middleware stack + app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, + app.AccountKeeper, scopedICAHostKeeper, app.MsgServiceRouter(), ++ authtypes.NewModuleAddress(govtypes.ModuleName).String(), +) +``` + +- You must pass the `authority` to the ica/controller keeper (implemented in [#3590](https://github.com/cosmos/ibc-go/pull/3590)). See [diff](https://github.com/cosmos/ibc-go/pull/3590/files#diff-d18972debee5e64f16e40807b2ae112ddbe609504a93ea5e1c80a5d489c3a08a): + +```diff +// app.go + +// ICA Controller keeper +app.ICAControllerKeeper = icacontrollerkeeper.NewKeeper( + appCodec, keys[icacontrollertypes.StoreKey], app.GetSubspace(icacontrollertypes.SubModuleName), + app.IBCFeeKeeper, // use ics29 fee as ics4Wrapper in middleware stack + app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, + scopedICAControllerKeeper, app.MsgServiceRouter(), ++ authtypes.NewModuleAddress(govtypes.ModuleName).String(), +) +``` + +- You must pass the `authority` to the ibctransfer keeper (implemented in [#3553](https://github.com/cosmos/ibc-go/pull/3553)). See [diff](https://github.com/cosmos/ibc-go/pull/3553/files#diff-d18972debee5e64f16e40807b2ae112ddbe609504a93ea5e1c80a5d489c3a08a): + +```diff +// app.go + +// Create Transfer Keeper and pass IBCFeeKeeper as expected Channel and PortKeeper +// since fee middleware will wrap the IBCKeeper for underlying application. +app.TransferKeeper = ibctransferkeeper.NewKeeper( + appCodec, keys[ibctransfertypes.StoreKey], app.GetSubspace(ibctransfertypes.ModuleName), + app.IBCFeeKeeper, // ISC4 Wrapper: fee IBC middleware + app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, + app.AccountKeeper, app.BankKeeper, scopedTransferKeeper, ++ authtypes.NewModuleAddress(govtypes.ModuleName).String(), +) +``` + +- You should pass the `authority` to the IBC keeper (implemented in [#3640](https://github.com/cosmos/ibc-go/pull/3640) and [#3650](https://github.com/cosmos/ibc-go/pull/3650)). See [diff](https://github.com/cosmos/ibc-go/pull/3640/files#diff-d18972debee5e64f16e40807b2ae112ddbe609504a93ea5e1c80a5d489c3a08a): + +```diff +// app.go + +// IBC Keepers +app.IBCKeeper = ibckeeper.NewKeeper( + appCodec, + keys[ibcexported.StoreKey], + app.GetSubspace(ibcexported.ModuleName), + app.StakingKeeper, + app.UpgradeKeeper, + scopedIBCKeeper, ++ authtypes.NewModuleAddress(govtypes.ModuleName).String(), +) +``` + +The authority determines the transaction signer allowed to execute certain messages (e.g. `MsgUpdateParams`). + +### Testing package + +- The function `SetupWithGenesisAccounts` has been removed. +- The function [`RelayPacketWithResults`](https://github.com/cosmos/ibc-go/blob/v8.0.0/testing/path.go#L66) has been added. This function returns the result of the packet receive transaction, the acknowledgement written on the receiving chain, an error if a relay step fails or the packet commitment does not exist on either chain. + +### Params migration + +Params are now self managed in the following submodules: + +- ica/controller [#3590](https://github.com/cosmos/ibc-go/pull/3590) +- ica/host [#3520](https://github.com/cosmos/ibc-go/pull/3520) +- ibc/connection [#3650](https://github.com/cosmos/ibc-go/pull/3650) +- ibc/client [#3640](https://github.com/cosmos/ibc-go/pull/3640) +- ibc/transfer [#3553](https://github.com/cosmos/ibc-go/pull/3553) + +Each module has a corresponding `MsgUpdateParams` message with a `Params` which can be specified in full to update the modules' `Params`. + +Legacy params subspaces must still be initialised in app.go in order to successfully migrate from `x/params`` to the new self-contained approach. See reference [this](https://github.com/cosmos/ibc-go/blob/v8.0.0/testing/simapp/app.go#L1007-L1012) for reference. + +For new chains which do not rely on migration of parameters from `x/params`, an expected interface has been added for each module. This allows chain developers to provide `nil` as the `legacySubspace` argument to `NewKeeper` functions. + +### Governance V1 migration + +Proposals have been migrated to [gov v1 messages](https://docs.cosmos.network/v0.50/modules/gov#messages) (see [#4620](https://github.com/cosmos/ibc-go/pull/4620)). The proposal `ClientUpdateProposal` has been deprecated and [`MsgRecoverClient`](https://github.com/cosmos/ibc-go/blob/v8.0.0/proto/ibc/core/client/v1/tx.proto#L121-L134) should be used instead. Likewise, the proposal `UpgradeProposal` has been deprecated and [`MsgIBCSoftwareUpgrade`](https://github.com/cosmos/ibc-go/blob/v8.0.0/proto/ibc/core/client/v1/tx.proto#L139-L154) should be used instead. Both proposals will be removed in the next major release. + +`MsgRecoverClient` and `MsgIBCSoftwareUpgrade` will only be allowed to be executed if the signer is the authority designated at the time of instantiating the IBC keeper. So please make sure that the correct authority is provided to the IBC keeper. + +Remove the `UpgradeProposalHandler` and `UpdateClientProposalHandler` from the `BasicModuleManager`: + +```diff +app.BasicModuleManager = module.NewBasicManagerFromManager( + app.ModuleManager, + map[string]module.AppModuleBasic{ + genutiltypes.ModuleName: genutil.NewAppModuleBasic(genutiltypes.DefaultMessageValidator), + govtypes.ModuleName: gov.NewAppModuleBasic( + []govclient.ProposalHandler{ + paramsclient.ProposalHandler, +- ibcclientclient.UpdateClientProposalHandler, +- ibcclientclient.UpgradeProposalHandler, + }, + ), +}) +``` + +Support for in-flight legacy recover client proposals (i.e. `ClientUpdateProposal`) will be made for v8, but chains should use `MsgRecoverClient` only afterwards to avoid in-flight client recovery failing when upgrading to v9. See [this issue](https://github.com/cosmos/ibc-go/issues/4721) for more information. + +Please note that ibc-go offers facilities to test an ibc-go upgrade: + +- All e2e tests of the repository can be [run with custom Docker chain images](https://github.com/cosmos/ibc-go/blob/c5bac5e03a0eae449b9efe0d312258115c1a1e85/e2e/README.md#running-tests-with-custom-images). +- An [importable workflow](https://github.com/cosmos/ibc-go/blob/c5bac5e03a0eae449b9efe0d312258115c1a1e85/e2e/README.md#importable-workflow) that can be used from any other repository to test chain upgrades. + +### Transfer migration + +An [automatic migration handler](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/apps/transfer/module.go#L136) is configured in the transfer module to set the [denomination metadata](https://github.com/cosmos/cosmos-sdk/blob/v0.50.1/proto/cosmos/bank/v1beta1/bank.proto#L96-L125) for the IBC denominations of all vouchers minted by the transfer module. + +## IBC Apps + +### ICS20 - Transfer + +- The function `IsBound` has been renamed to [`hasCapability`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/apps/transfer/keeper/keeper.go#L98) and made unexported. + +### ICS27 - Interchain Accounts + +- Functions [`SerializeCosmosTx`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/apps/27-interchain-accounts/types/codec.go#L32) and [`DeserializeCosmosTx`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/apps/27-interchain-accounts/types/codec.go#L76) now accept an extra parameter `encoding` of type `string` that specifies the format in which the transaction messages are marshaled. Both [protobuf and proto3 JSON formats](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/apps/27-interchain-accounts/types/metadata.go#L14-L17) are supported. +- The function `IsBound` of controller submodule has been renamed to [`hasCapability`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/apps/27-interchain-accounts/controller/keeper/keeper.go#L111) and made unexported. +- The function `IsBound` of host submodule has been renamed to [`hasCapability`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/apps/27-interchain-accounts/host/keeper/keeper.go#L94) and made unexported. + +## Relayers + +- Getter functions in `MsgChannelOpenInitResponse`, `MsgChannelOpenTryResponse`, `MsgTransferResponse`, `MsgRegisterInterchainAccountResponse` and `MsgSendTxResponse` have been removed. The fields can be accessed directly. +- `channeltypes.EventTypeTimeoutPacketOnClose` (where `channeltypes` is an import alias for `"github.com/cosmos/ibc-go/v8/modules/core/04-channel"`) has been removed, since core IBC does not emit any event with this key. +- Attribute with key `counterparty_connection_id` has been removed from event with key `connectiontypes.EventTypeConnectionOpenInit` (where `connectiontypes` is an import alias for `"github.com/cosmos/ibc-go/v8/modules/core/03-connection/types"`) and attribute with key `counterparty_channel_id` has been removed from event with key `channeltypes.EventTypeChannelOpenInit` (where `channeltypes` is an import alias for `"github.com/cosmos/ibc-go/v8/modules/core/04-channel"`) since both (counterparty connection ID and counterparty channel ID) are empty on `ConnectionOpenInit` and `ChannelOpenInit` respectively. +- As part of the migration to [governance V1 messages](#governance-v1-migration) the following changes in events have been made: + +```diff +// IBC client events vars +var ( + EventTypeCreateClient = "create_client" + EventTypeUpdateClient = "update_client" + EventTypeUpgradeClient = "upgrade_client" + EventTypeSubmitMisbehaviour = "client_misbehaviour" +- EventTypeUpdateClientProposal = "update_client_proposal" +- EventTypeUpgradeClientProposal = "upgrade_client_proposal" ++ EventTypeRecoverClient = "recover_client" ++ EventTypeScheduleIBCSoftwareUpgrade = "schedule_ibc_software_upgrade" + EventTypeUpgradeChain = "upgrade_chain" +) +``` + +## IBC Light Clients + +- Functions `Pretty` and `String` of type `MerklePath` have been [removed](https://github.com/cosmos/ibc-go/pull/4459/files#diff-dd94ec1dde9b047c0cdfba204e30dad74a81de202e3b09ac5b42f493153811af). diff --git a/docs/versioned_docs/version-v9.0.x/05-migrations/12-v8-to-v8_1.md b/docs/versioned_docs/version-v9.0.x/05-migrations/12-v8-to-v8_1.md new file mode 100644 index 00000000000..17ddfbe295f --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/05-migrations/12-v8-to-v8_1.md @@ -0,0 +1,42 @@ +--- +title: IBC-Go v8 to v8.1 +sidebar_label: IBC-Go v8 to v8.1 +sidebar_position: 12 +slug: /migrations/v8-to-v8_1 +--- + +# Migrating from v8 to v8.1 + +This guide provides instructions for migrating to version `v8.1.0` of ibc-go. + +There are four sections based on the four potential user groups of this document: + +- [Migrating from v8 to v8.1](#migrating-from-v8-to-v81) + - [Chains](#chains) + - [IBC apps](#ibc-apps) + - [Relayers](#relayers) + - [IBC light clients](#ibc-light-clients) + +**Note:** ibc-go supports golang semantic versioning and therefore all imports must be updated on major version releases. + +## Chains + +### `04-channel` params migration + +Self-managed [params](https://github.com/cosmos/ibc-go/blob/v8.1.0/proto/ibc/core/channel/v1/channel.proto#L183-L187) have been added for `04-channel` module. The params include the `upgrade_timeout` that is used in channel upgradability to specify the interval of time during which the counterparty chain must flush all in-flight packets on its end and move to `FLUSH_COMPLETE` state (see [Channel Upgrades](../01-ibc/06-channel-upgrades.md#) for more information). An [automatic migration handler](https://github.com/cosmos/ibc-go/blob/v8.1.0/modules/core/module.go#L162-L166) is configured in the `04-channel` module that sets the default params (with a default upgrade timeout of 10 minutes). The module has a corresponding [`MsgUpdateParams` message](https://github.com/cosmos/ibc-go/blob/v8.1.0/proto/ibc/core/channel/v1/tx.proto#L435-L447) with a `Params` field which can be specified in full to update the module's `Params`. + +### Fee migration + +In ibc-go v8.1.0 an improved, more efficient escrow calculation of fees for packet incentivisation has been introduced (see [this issue](https://github.com/cosmos/ibc-go/issues/5509) for more information). Before v8.1.0 the amount escrowed was `(ReckFee + AckFee + TimeoutFee)`; from ibc-go v8.1.0, the calculation is changed to `Max(RecvFee + AckFee, TimeoutFee)`. In order to guarantee that the correct amount of fees are refunded for packets that are in-flight during the upgrade to ibc-go v8.1.0, an [automatic migration handler](https://github.com/cosmos/ibc-go/blob/v8.1.0/modules/apps/29-fee/module.go#L113-L115) is configured in the `29-fee` module to refund the leftover fees (i.e `(ReckFee + AckFee + TimeoutFee) - Max(RecvFee + AckFee, TimeoutFee)`) that otherwise would not be refunded when the packet lifecycle completes and the new calculation is used. + +## IBC apps + +- No relevant changes were made in this release. + +## Relayers + +- No relevant changes were made in this release. + +## IBC light clients + +- No relevant changes were made in this release. diff --git a/docs/versioned_docs/version-v9.0.x/05-migrations/13-v8-to-v9.md b/docs/versioned_docs/version-v9.0.x/05-migrations/13-v8-to-v9.md new file mode 100644 index 00000000000..7b1dc0399db --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/05-migrations/13-v8-to-v9.md @@ -0,0 +1,552 @@ +--- +title: IBC-Go v8 to v9 +sidebar_label: IBC-Go v8 to v9 +sidebar_position: 13 +slug: /migrations/v8-to-v9 +--- + +# Migrating from v8 to v9 + +This guide provides instructions for migrating to a new version of ibc-go. + +There are four sections based on the four potential user groups of this document: + +- [Migrating from v8 to v9](#migrating-from-v8-to-v9) + - [Chains](#chains) + - [IBC core](#ibc-core) + - [API removals](#api-removals) + - [02-client](#02-client) + - [03-connection](#03-connection) + - [Removal of self client and consensus state from connection handshake](#removal-of-self-client-and-consensus-state-from-connection-handshake) + - [04-channel](#04-channel) + - [05-port](#05-port) + - [23-commitment](#23-commitment) + - [24-host](#24-host) + - [IBC Apps](#ibc-apps) + - [ICS20 - Transfer](#ics20---transfer) + - [ICS20 v2](#ics20-v2) + - [`DenomTrace` type refactoring](#denomtrace-type-refactoring) + - [ICS27 - Interchain Accounts](#ics27---interchain-accounts) + - [Callbacks](#callbacks) + - [IBC testing package](#ibc-testing-package) + - [API deprecation notice](#api-deprecation-notice) + - [Relayers](#relayers) + - [Events](#events) + - [02-client](#02-client-1) + - [04-channel](#04-channel-1) + - [Channel upgrades](#channel-upgrades) + - [IBC Light Clients](#ibc-light-clients) + - [API removals](#api-removals-1) + - [06-solomachine](#06-solomachine) + - [07-tendermint](#07-tendermint) + - [08-wasm](#08-wasm) + - [09-localhost](#09-localhost) + +**Note:** ibc-go supports golang semantic versioning and therefore all imports must be updated on major version releases. + +## Chains + +Chains will need to remove the route for the legacy proposal handler for 02-client from their `app/app.go`: + +```diff +// app.go +govRouter.AddRoute(govtypes.RouterKey, govv1beta1.ProposalHandler). +- AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)). +- AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper)) ++ AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)) +``` + +## IBC core + +- Because the self client and consensus state validation has been removed from the connection handshake (see section [Removal of self client and consensus state from connection handshake](#removal-of-self-client-and-consensus-state-from-connection-handshake) for more details), the IBC core keeper does not need the staking keeper anymore to introspect the (self) past historical info at a given height and construct the expected consensus state at that height. Thus, the signature of IBC core keeper constructor function `NewKeeper` has been updated: + +```diff +func NewKeeper( + cdc codec.BinaryCodec, key storetypes.StoreKey, paramSpace types.ParamSubspace, +- stakingKeeper clienttypes.StakingKeeper, + upgradeKeeper clienttypes.UpgradeKeeper, + scopedKeeper capabilitykeeper.ScopedKeeper, authority string, +) *Keeper +``` + +### API removals + +- The [`exported.ChannelI`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/core/exported/channel.go#L3-L11) and [`exported.CounterpartyChannelI`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/core/exported/channel.go#L13-L19) interfaces have been removed. Please use the concrete types. +- The [`exported.ConnectionI`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/core/exported/connection.go#L6-L13) and [`exported.CounterpartyConnectionI`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/core/exported/connection.go#L15-L21) interfaces have been removed. Please use the concrete types. +- The [`Router` reference](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/core/keeper/keeper.go#L35) has been removed from the IBC core keeper in [#6138](https://github.com/cosmos/ibc-go/pull/6138). Please use `PortKeeper.Router` instead. +- The [composite interface `QueryServer`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/core/types/query.go#L14-L19) has been removed from package `core/types`. Please use the granular `QueryServer` interfaces for IBC submodules directly. +- The [`TypeClientMisbehaviour` constant](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/core/exported/client.go#L17) has been removed. +- The function [`SetConsensusHost`](https://github.com/cosmos/ibc-go/blob/v8.3.0/modules/core/keeper/keeper.go#L88-L96) has been removed because the self client and consensus state validation has been removed from the connection handshake. See section [Removal of self client and consensus state from connection handshake](#removal-of-self-client-and-consensus-state-from-connection-handshake) for more details. + +### 02-client + +- The `QueryVerifyMembershipRequest` protobuf message has been modified to include `commitment.v2.MerklePath`. The deprecated `commitment.v1.MerklePath` field has been `reserved`. [See 23-commitment](#23-commitment). +- The function [`CreateLocalhostClient`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/core/02-client/keeper/keeper.go#L56) has been removed. The localhost client is now stateless. +- The function [`NewClientProposalHandler`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/core/02-client/proposal_handler.go#L18) has been removed in [#6777](https://github.com/cosmos/ibc-go/pull/6777). +- The deprecated [`ClientUpdateProposal` and `UpgradeProposal` messages](https://github.com/cosmos/ibc-go/blob/v8.0.0/proto/ibc/core/client/v1/client.proto#L67-L113) have been removed in [\#6782](https://github.com/cosmos/ibc-go/pull/6782). Please use [`MsgRecoverClient`](https://github.com/cosmos/ibc-go/blob/release/v9.0.x/proto/ibc/core/client/v1/tx.proto#L125-L138) and [`MsgIBCSoftwareUpgrade`](https://github.com/cosmos/ibc-go/blob/release/v9.0.x/proto/ibc/core/client/v1/tx.proto#L143-L158) respectively instead. +- Because the self client and consensus state validation has been removed from the connection handshake (see section [Removal of self client and consensus state from connection handshake](#removal-of-self-client-and-consensus-state-from-connection-handshake) for more details): + - The [ConsensusHost interface](https://github.com/cosmos/ibc-go/blob/v8.3.0/modules/core/02-client/types/client.go#L25-L29) has been removed. + - The function [`SetConsensusHost`](https://github.com/cosmos/ibc-go/blob/v8.3.0/modules/core/02-client/keeper/keeper.go#L61-L68) has been removed. + - The functions [`GetSelfConsensusState` and `ValidateSelfClient`](https://github.com/cosmos/ibc-go/blob/v8.3.0/modules/core/02-client/keeper/keeper.go#L256-L269) have been removed. + +### 03-connection + +- The [functions `GetState()`, `GetClientID()`, `GetCounterparty()`, `GetVersions()`, and `GetDelayPeriod()`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/core/03-connection/types/connection.go#L25-L48) of the `Connection` type have been removed. Please access the fields directly. +- The [functions `GetClientID()`, `GetConnectionID()`, and `GetPrefix()`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/core/03-connection/types/connection.go#L79-L92) of the `Counterparty` type have been removed. Please access the fields directly. + +#### Removal of self client and consensus state from connection handshake + +The `ConnectionOpenTry` and `ConnectionOpenAck` handlers no longer validate that the light client on counterparty chain has a valid representation of the executing chain's consensus protocol (please see [#1128](https://github.com/cosmos/ibc/pull/1128) in cosmos/ibc repository for an exhaustive explanation of the reasoning). + +- The fields `client_state`, `proof_client`, `proof_consensus`, `consensus_height` and `host_consensus_state_proof` of `MsgConnectionOpenTry` and `MsgConnectionOpenAck` have been deprecated, and the signature of the constructor functions [`NewMsgConnectionOpenTry`](https://github.com/cosmos/ibc-go/blob/release/v9.0.x/modules/core/03-connection/types/msgs.go#L78) and [`NewMsgConnectionOpenTry`](https://github.com/cosmos/ibc-go/blob/release/v9.0.x/modules/core/03-connection/types/msgs.go#L165) has been accordingly updated: + +```diff +func NewMsgConnectionOpenTry( + clientID, counterpartyConnectionID, counterpartyClientID string, +- counterpartyClient exported.ClientState, + counterpartyPrefix commitmenttypes.MerklePrefix, + counterpartyVersions []*Version, delayPeriod uint64, + initProof []byte, +- clientProof []byte, +- consensusProof []byte, + proofHeight lienttypes.Height, +- consensusHeight clienttypes.Height, + signer string, +) *MsgConnectionOpenTry + +func NewMsgConnectionOpenAck( + connectionID, counterpartyConnectionID string, +- counterpartyClient exported.ClientState, + tryProof []byte, +- clientProof []byte, +- consensusProof []byte, + proofHeight clienttypes.Height, +- consensusHeight clienttypes.Height, + version *Version, + signer string, +) *MsgConnectionOpenAck +``` + +- The functions [`VerifyClientState` and `VerifyClientConsensusState`](https://github.com/cosmos/ibc-go/blob/v8.3.0/modules/core/03-connection/keeper/verify.go#L20-L101) have been removed. +- The function [`UnpackInterfaces`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/core/03-connection/types/msgs.go#L166) has been removed. + +### 04-channel + +- The utility function [`QueryLatestConsensusState`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/core/04-channel/client/utils/utils.go#L130) of the CLI has been removed. +- The [functions `GetState()`, `GetOrdering()`, `GetCounterparty()`, `GetConnectionHops()`, `GetVersion()`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/core/04-channel/types/channel.go#L29-L52) of the `Channel` type have been removed. Please access the fields directly. +- The [functions `IsOpen()` and `IsClosed()`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/core/04-channel/types/channel.go#L54-L62) of the `Channel` type have been removed. +- The [functions `GetPortID()`, `GetChannelID()`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/core/04-channel/types/channel.go#L92-L100) of the `CounterpartyChannel` type have been removed. +- Functions [`ChanCloseConfirmWithCounterpartyUpgradeSequence`](https://github.com/cosmos/ibc-go/blob/v8.1.0/modules/core/04-channel/keeper/handshake.go#L446) and [`TimeoutOnCloseWithCounterpartyUpgradeSequence`](https://github.com/cosmos/ibc-go/blob/v8.1.0/modules/core/04-channel/keeper/timeout.go#L226) have been removed. Please use `ChanCloseConfirm` and `TimeoutOnClose` with the updated signature that takes the counterparty upgrade sequence as extra argument: + +```diff +func (k *Keeper) ChanCloseConfirm( + ctx sdk.Context, + portID, + channelID string, + chanCap *capabilitytypes.Capability, + initProof []byte, + proofHeight exported.Height, ++ counterpartyUpgradeSequence uint64, +) + +func (k *Keeper) TimeoutOnClose( + ctx sdk.Context, + chanCap *capabilitytypes.Capability, + packet types.Packet, + proof, + closedProof []byte, + proofHeight exported.Height, + nextSequenceRecv uint64, ++ counterpartyUpgradeSequence uint64, +) +``` + +- The keeper handlers `RecvPacket`, `AcknowledgePacket`, `TimeoutPacket` and `TimeoutOnClose` now return the channel version, which the message server passes to the packet lifecycle application callbacks (`OnRecvPacket`, `OnAcknowledgementPacket` and `OnTimeoutPacket`). The channel version is useful when adding backwards compatible features to an existing application implementation (for example: in the context of ICS20 v2, middleware and the transfer application may use the channel version to unmarshal the packet differently depending on the channel version). + +```diff +func (k *Keeper) RecvPacket( + ctx sdk.Context, + chanCap *capabilitytypes.Capability, + packet types.Packet, + proof []byte, + proofHeight exported.Height, +- ) error { ++ ) (string, error) { + +func (k *Keeper) AcknowledgePacket( + ctx sdk.Context, + chanCap *capabilitytypes.Capability, + packet types.Packet, + acknowledgement []byte, + proof []byte, + proofHeight exported.Height, +- ) error { ++ ) (string, error) { + +func (k *Keeper) TimeoutPacket( + ctx sdk.Context, + packet types.Packet, + proof []byte, + proofHeight exported.Height, + nextSequenceRecv uint64, +- ) error { ++ ) (string, error) { + +func (k *Keeper) TimeoutOnClose( + ctx sdk.Context, + chanCap *capabilitytypes.Capability, + packet types.Packet, + proof, + closedProof []byte, + proofHeight exported.Height, + nextSequenceRecv uint64, + counterpartyUpgradeSequence uint64, +- ) error { ++ ) (string, error) { +``` + +```diff +OnRecvPacket func( + ctx sdk.Context, ++ channelVersion string, + packet channeltypes.Packet, + relayer sdk.AccAddress, +) exported.Acknowledgement + +OnAcknowledgementPacket func( + ctx sdk.Context, ++ channelVersion string, + packet channeltypes.Packet, + acknowledgement []byte, + relayer sdk.AccAddress, +) error + +OnTimeoutPacket func( + ctx sdk.Context, ++ channelVersion string, + packet channeltypes.Packet, + relayer sdk.AccAddress, +) error +``` + +### 05-port + +- The signature of the `UnmarshalPacketData` function of the `PacketDataUnmarshaler` interface takes now extra arguments for the context and the port and channel identifiers. These parameters have been added so that implementations of the interface function can retrieve the channel version, which allows the provided packet data to be unmarshaled based on the channel version. In addition to these, `UnmarshalPacketData` now also returns the underlying application's version: + +```diff +type PacketDataUnmarshaler interface { + UnmarshalPacketData( ++ ctx sdk.Context, ++ portID, ++ channelID string, + bz []byte, ++ ) (interface{}, string, error) +} +``` + +### 23-commitment + +- The [`exported.Proof`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/core/exported/commitment.go#L34-L44) interface has been removed. Please use the [`MerkleProof`](https://github.com/cosmos/ibc-go/blob/release/v9.0.x/modules/core/23-commitment/types/commitment.pb.go#L161-L168) concrete type. +- The [`MerklePath` type](https://github.com/cosmos/ibc-go/blob/release/v9.0.x/modules/core/23-commitment/types/commitment.pb.go#L113-L119) has been deprecated and a new [`commitment.v2.MerklePath` type](https://github.com/cosmos/ibc-go/blob/release/v9.0.x/modules/core/23-commitment/types/v2/commitment.pb.go#L25-L30) has been introduced in [#6644](https://github.com/cosmos/ibc-go/pull/6644). The new `commitment.v2.MerklePath` contains `repeated bytes` in favour of `repeated string`. This allows users to prove values stored under keys which contain non-utf8 encoded symbols. As a result, changes have been made to the 02-client `Query` service and 08-wasm contract API messages for JSON blobs. See [02-client](#02-client) and [08-wasm](#08-wasm), respectively. +- The `commitment.v1.MerklePath` type has been removed and a new `commitment.v2.MerklePath` type has been introduced in [#6644](https://github.com/cosmos/ibc-go/pull/6644). The new `commitment.v2.MerklePath` contains `repeated bytes` in favour of `repeated string`. This allows users to prove values stored under keys which contain non-utf8 encoded symbols. As a result, changes have been made to the 02-client `Query` service and 08-wasm contract API messages for JSON blobs. See [02-client](#02-client) and [08-wasm](#08-wasm), respectively. + +### 24-host + +All functions ending with `Path` naming have been removed in favour of their sibling function which ends in `Key`. + +## IBC Apps + +### ICS20 - Transfer + +#### ICS20 v2 + +- With support for multidenom transfer packets and path forwarding, the `NewMsgTransfer` constructor function to create a new `MsgTransfer` instance now accepts multiple coins instead of just one, and an argument with forwarding information: + +```diff +func NewMsgTransfer( + sourcePort, sourceChannel string, +- token sdk.Coin, ++ tokens sdk.Coins, + sender, receiver string, + timeoutHeight clienttypes.Height, timeoutTimestamp uint64, + memo string, ++ forwarding *Forwarding, +) +``` + +- The `ibc_transfer` and `fungible_token_packet` events do not include the attributes `denom` and `amount` anymore; instead they include the attribute `tokens` with the list of coins transferred in the packet. +- A new type for the packet payload has been introduced: [`FungibleTokenPacketDataV2`](https://github.com/cosmos/ibc-go/blob/release/v9.0.x/proto/ibc/applications/transfer/v2/packet.proto#L27-L41). Transfer channels with version `ics20-2` will use this new type for the payload and it will be encoded using Protobuf (instead of JSON). Middleware that wraps the transfer application and unmarshals the packet data MUST take this into account when upgrading: depending on the channel version, packet data should unmarshal either as JSON (v1) or Protobuf (v2). The helper function [`UnmarshalPacketData`](https://github.com/cosmos/ibc-go/blob/release/v9.0.x/modules/apps/transfer/types/packet.go#L212) encapsulates this logic and can be used by middleware or other applications to correctly unmarshal the packet data: + +```go +packetData, err := transfertypes.UnmarshalPacketData(packet.Data, version) +if err != nil { + return err +} +``` + +#### `DenomTrace` type refactoring + +- The [`DenomTrace`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/apps/transfer/types/transfer.pb.go#L25-L33) type has been made private and will be completely removed in a later release. Please use the [`Denom` type](https://github.com/cosmos/ibc-go/blob/release/v9.0.x/modules/apps/transfer/types/token.pb.go#L81-L87) instead. +- The [`DenomTrace` and `DenomTraces` gRPCs](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/apps/transfer/keeper/grpc_query.go#L22-L75) have been removed as well (together with the and `QueryDenomTraceResponse` and `QueryDenomTracesResponse` types). Please use the [`Denom` and `Denoms` gRPCs](https://github.com/cosmos/ibc-go/blob/release/v9.0.x/modules/apps/transfer/keeper/grpc_query.go#L27-L80) instead. +- An [automatic migration handler](https://github.com/cosmos/ibc-go/blob/release/v9.0.x/modules/apps/transfer/keeper/migrations.go#L75-L113) is also configured to migrate the storage from using `DenomTrace` to `Denom`. +- The [`denomination_trace` event emitted in the `OnRecvPacket` callback](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/apps/transfer/keeper/relay.go#L268-L274) has been replaced with the [`denom` event](https://github.com/cosmos/ibc-go/blob/release/v9.0.x/modules/apps/transfer/keeper/relay.go#L230). +- The functions [`SenderChainIsSource` and `ReceiverChainIsSource`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/apps/transfer/types/coin.go#L12-L32) have been replaced with the function `HasPrefix` of the newly added `Denom` type. +- The helper function [`GetTransferCoin`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/apps/transfer/types/coin.go#L46) has been removed. +- The helper function [`GetDenomPrefix`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/apps/transfer/types/coin.go#L35) has been removed. +- The helper function [`GetPrefixedDenom`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/apps/transfer/types/coin.go#L40) has been removed. Please construct the denom using the new [`Denom` type](https://github.com/cosmos/ibc-go/blob/release/v9.0.x/modules/apps/transfer/types/token.pb.go#L82). + +### ICS27 - Interchain Accounts + +- In [#5785](https://github.com/cosmos/ibc-go/pull/5785) the list of arguments of the `NewKeeper` constructor function of the host submodule was extended with an extra argument for the gRPC query router that the submodule uses when executing a [`MsgModuleQuerySafe`](https://github.com/cosmos/ibc-go/blob/release/v9.0.x/proto/ibc/applications/interchain_accounts/host/v1/tx.proto#L40-L51) to perform queries that are module safe: + +```diff +func NewKeeper( + cdc codec.Codec, key storetypes.StoreKey, legacySubspace icatypes.ParamSubspace, + ics4Wrapper porttypes.ICS4Wrapper, channelKeeper icatypes.ChannelKeeper, + portKeeper icatypes.PortKeeper, accountKeeper icatypes.AccountKeeper, + scopedKeeper exported.ScopedKeeper, msgRouter icatypes.MessageRouter, ++ queryRouter icatypes.QueryRouter, + authority string, +) Keeper +``` + +- The function [`RegisterInterchainAccountWithOrdering`](https://github.com/cosmos/ibc-go/blob/v8.3.0/modules/apps/27-interchain-accounts/controller/keeper/account.go#L68) has been removed. The legacy function `RegisterInterchainAccount` now takes an extra parameter to specify the ordering of new ICA channels: + +```diff +func (k Keeper) RegisterInterchainAccount( + ctx sdk.Context, + connectionID, owner, + version string, ++ ordering channeltypes.Order +) error { +``` + +- The `requests` repeated field of `MsgModuleQuerySafe` has been marked non-nullable, and therefore the signature of the constructor function `NewMsgModuleQuerySafe` has been updated: + +```diff +func NewMsgModuleQuerySafe( + signer string, +- requests []*QueryRequest, ++ requests []QueryRequest, +) *MsgModuleQuerySafe { +``` + +- The signature of the [`NewIBCMiddleware` constructor function](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/apps/27-interchain-accounts/controller/ibc_middleware.go#L35) in the controller submodule now only takes the controller keeper as an argument. The base application is then set by default to nil and thus authentication is assumed to be done by a Cosmos SDK module, such as the `x/gov`, `x/group` or `x/auth`, that sends messages to the controller submodule's message server. An authentication module can be set using the newly added [`NewIBCMiddlewareWithAuth` constructor function](https://github.com/cosmos/ibc-go/blob/release/v9.0.x/modules/apps/27-interchain-accounts/controller/ibc_middleware.go#L46). + +```diff +func NewIBCMiddleware( +- app porttypes.IBCModule, + k keeper.Keeper, +) IBCMiddleware { +``` + +- The [`InitModule` function](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/apps/27-interchain-accounts/module.go#L124-L143) has been removed. When adding the interchain accounts module to the chain, please set the desired params for controller and host submodules directly after calling `RunMigrations` in the upgrade handler. +- The [`GetBytes()` function](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/apps/27-interchain-accounts/types/packet.go#L65-L68) of the `CosmosTx` type has been removed. + +### Callbacks + +The `ContractKeeper` interface has been extended with the base application version. The base application version will be required by contracts to unmarshal the packet data. An example of this is unmarshaling ICS20 v2 packets which requires knowing the base version of a transfer stack (either v1 or v2). + +```diff +type ContractKeeper interface { + IBCSendPacketCallback( + cachedCtx sdk.Context, + sourcePort string, + sourceChannel string, + timeoutHeight clienttypes.Height, + timeoutTimestamp uint64, + packetData []byte, + contractAddress, + packetSenderAddress string, ++ version string, + ) error + + IBCOnAcknowledgementPacketCallback( + cachedCtx sdk.Context, + packet channeltypes.Packet, + acknowledgement []byte, + relayer sdk.AccAddress, + contractAddress, + packetSenderAddress string, ++ version string, + ) error + + IBCOnTimeoutPacketCallback( + cachedCtx sdk.Context, + packet channeltypes.Packet, + relayer sdk.AccAddress, + contractAddress, + packetSenderAddress string, ++ version string, + ) error + + IBCReceivePacketCallback( + cachedCtx sdk.Context, + packet ibcexported.PacketI, + ack ibcexported.Acknowledgement, + contractAddress string, ++ version string, + ) error +} +``` + +### IBC testing package + +- In the `TestChain` struct the field [`LastHeader`](https://github.com/cosmos/ibc-go/blob/v8.0.0/testing/chain.go#L59) has been renamed to `LatestCommittedHeader`, the field [`CurrentHeader`](https://github.com/cosmos/ibc-go/blob/v8.0.0/testing/chain.go#L60) has been renamed to `ProposedHeader` and the [`QueryServer` interface](https://github.com/cosmos/ibc-go/blob/v8.0.0/testing/chain.go#L61) has been removed. + +```diff +type TestChain struct { + testing.TB + + Coordinator *Coordinator + App TestingApp + ChainID string +- LastHeader *ibctm.Header // header for last block height committed ++ LatestCommittedHeader *ibctm.Header // header for last block height committed +- CurrentHeader cmtproto.Header // header for current block height ++ ProposedHeader cmtproto.Header // proposed (uncommitted) header for current block height +- QueryServer types.QueryServer + TxConfig client.TxConfig + Codec codec.Codec + + Vals *cmttypes.ValidatorSet + NextVals *cmttypes.ValidatorSet + + // Signers is a map from validator address to the PrivValidator + // The map is converted into an array that is the same order as the validators right before signing commit + // This ensures that signers will always be in correct order even as validator powers change. + // If a test adds a new validator after chain creation, then the signer map must be updated to include + // the new PrivValidator entry. + Signers map[string]cmttypes.PrivValidator + + // autogenerated sender private key + SenderPrivKey cryptotypes.PrivKey + SenderAccount sdk.AccountI + + SenderAccounts []SenderAccount + + // Short-term solution to override the logic of the standard SendMsgs function. + // See issue https://github.com/cosmos/ibc-go/issues/3123 for more information. + SendMsgsOverride func(msgs ...sdk.Msg) (*abci.ExecTxResult, error) +} +``` + +Submodule query servers can be constructed directly by passing their associated keeper to the appropriate constructor function. For example: + +```golang +clientQueryServer := clientkeeper.NewQueryServer(app.IBCKeeper.ClientKeeper) +``` + +- The `mock.PV` type has been removed in favour of [`cmttypes.MockPV`](https://github.com/cometbft/cometbft/blob/v0.38.5/types/priv_validator.go#L50) in [#5709](https://github.com/cosmos/ibc-go/pull/5709). +- [Functions `ConstructUpdateTMClientHeader` and `ConstructUpdateTMClientHeaderWithTrustedHeight`](https://github.com/cosmos/ibc-go/blob/v8.0.0/testing/chain.go#L446-L481) of `TestChain` type have been replaced with `IBCClientHeader` function. This function will construct a 07-tendermint header to update the light client on the counterparty chain. The trusted height must be passed in as a non-zero height. +- [`GetValsAtHeight`](https://github.com/cosmos/ibc-go/blob/v8.0.0/testing/chain.go#L401) has been renamed to [`GetTrustedValidators`](https://github.com/cosmos/ibc-go/blob/release/v9.0.x/testing/chain.go#L403). +- [`AssertEventsLegacy` function](https://github.com/cosmos/ibc-go/blob/v8.0.0/testing/events.go#L140) of `ibctesting` package (alias for `"github.com/cosmos/ibc-go/v9/testing"`) has been removed in [#6070](https://github.com/cosmos/ibc-go/pull/6070), and [`AssertEvents` function](https://github.com/cosmos/ibc-go/blob/release/v9.0.x/testing/events.go#L187) should be used instead. + +```diff +// testing/events.go +- func AssertEventsLegacy( +- suite *testifysuite.Suite, +- expected EventsMap, +- actual []abci.Event, +- ) + +func AssertEvents( + suite *testifysuite.Suite, + expected []abci.Event, + actual []abci.Event, +) +``` + +- The signature of the function `QueryConnectionHandshakeProof` has changed, since the validation of self client and consensus state has been remove from the connection handshake: + +```diff +func (endpoint *Endpoint) QueryConnectionHandshakeProof() ( +- clientState exported.ClientState, clientProof, +- consensusProof []byte, consensusHeight clienttypes.Height, + connectionProof []byte, proofHeight clienttypes.Height, +) +``` + +- The functions [`GenerateClientStateProof` and `GenerateConsensusStateProof`](https://github.com/cosmos/ibc-go/blob/v8.0.0/testing/solomachine.go#L513-L547) +have been removed. + +#### API deprecation notice + +- The functions `Setup`, `SetupClients`, `SetupConnections`, `CreateConnections`, and `CreateChannels` of the `Coordinator` type have been deprecated and will be removed in v11. Please use the new functions `Setup`, `SetupClients`, `SetupConnections`, `CreateConnections`, `CreateChannels` of the `Path` type. +- The function `SetChannelState` of the `Path` type has been deprecated and will be removed in v11. Please use the new function `UpdateChannel` of the `Path` type. + +## Relayers + +### Events + +#### 02-client + +- The function `CreateClient` of the keeper expects now a string for the client type (e.g. `07-tendermint`) and two `[]byte` for the Protobuf-serialized client and consensus states: + +```diff +func (k *Keeper) CreateClient( + ctx sdk.Context, ++ clientType string, +- clientState exported.ClientState, +- consensusState exported.ConsensusState, ++ clientState []byte, ++ consensusState []byte, +) (string, error) +``` + +- The [`header` attribute](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/core/02-client/keeper/events.go#L60) has been removed from the `update_client` event in [\#5110](https://github.com/cosmos/ibc-go/pull/5110). + +#### 04-channel + +- The constant [`AttributeVersion`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/core/04-channel/types/events.go#L14) has been renamed to `AttributeKeyVersion`. +- The `packet_data` and the `packet_ack` attributes of the `send_packet`, `recv_packet` and `write_acknowledgement` events have been removed in [#6023](https://github.com/cosmos/ibc-go/pull/6023). The attributes `packet_data_hex` and `packet_ack_hex` should be used instead. The [constants `AttributeKeyData` and `AttributeKeyAck`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/core/04-channel/types/events.go#L24-L27) have also been removed. + +##### Channel upgrades + +- The attributes `version`, `ordering` and `connection_hops` from the `channel_upgrade_init`, `channel_upgrade_try`, `channel_upgrade_ack`, `channel_upgrade_open`, `channel_upgrade_timeout` and `channel_upgrade_cancelled` events have been removed in [\#6063](https://github.com/cosmos/ibc-go/pull/6063). + +## IBC Light Clients + +### API removals + +- The [`ExportMetadata` interface function](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/core/exported/client.go#L59) has been removed from the `ClientState` interface. Core IBC will export all key/value's within the 02-client store. +- The [`ZeroCustomFields` interface function](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/core/exported/client.go#L64) has been removed from the `ClientState` interface. +- The following functions have also been removed from the `ClientState` interface: `Initialize`, `Status`, `GetLatestHeight`, `GetTimestampAtHeight`, `VerifyClientMessage`, `VerifyMembership`, `VerifyNonMembership`, `CheckForMisbehaviour`, `UpdateState`, `UpdateStateOnMisbehaviour`, `CheckSubstituteAndUpdateState` and `VerifyUpgradeAndUpdateState`. ibc-go v9 decouples routing at the 02-client layer from the light clients' encoding structure (i.e. every light client implementation of the `ClientState` interface is not used anymore to route the requests to the right light client at the `02-client` layer, instead a *light client module* is registered for every light client type and 02-client routes the requests to the right light client module based on the client ID). Light client developers must implement the newly introduced `LightClientModule` interface and are encouraged to move the logic implemented in the functions of their light client's implementation of the `ClientState` interface to the equivalent function in the `LightClientModule` interface. The table below shows the equivalence between the `ClientState` interface functions that have been removed and the functions in the `LightClientModule` interface: + +|`ClientState` interface|`LightClientModule` interface| +|-----------------------|-----------------------------| +|`Initialize` |`Initialize` | +|`Status` |`Status` | +|`GetLatestHeight` |`LatestHeight` | +|`GetTimestampAtHeight` |`TimestampAtHeight` | +|`VerifyClientMessage` |`VerifyClientMessage` | +|`VerifyMembership` |`VerifyMembership` | +|`VerifyNonMembership` |`VerifyNonMembership` | +|`CheckForMisbehaviour` |`CheckForMisbehaviour` | +|`UpdateState` |`UpdateState` | +|`UpdateStateOnMisbehaviour` |`UpdateStateOnMisbehaviour` | +|`CheckSubstituteAndUpdateState`|`RecoverClient` | +|`VerifyUpgradeAndUpdateState` |`VerifyUpgradeAndUpdateState`| +|`ExportMetadata` | | +|`ZeroCustomFields` | | + +Please check also the [Light client developer guide](../03-light-clients/01-developer-guide/01-overview.md) for more information. The light client module implementation for 07-tendermint may also be useful as reference. + +### 06-solomachine + +- The [`Initialize`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/light-clients/06-solomachine/client_state.go#L85), [`Status`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/light-clients/06-solomachine/client_state.go#L59), [`GetTimestampAtHeight`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/light-clients/06-solomachine/client_state.go#L46) and [`UpdateStateOnMisbehaviour`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/light-clients/06-solomachine/update.go#L105) functions in `ClientState` have been removed and all their logic has been moved to functions of the `LightClientModule`. The [`VerifyMembership`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/light-clients/06-solomachine/client_state.go#L111) and [`VerifyNonMembership`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/light-clients/06-solomachine/client_state.go#L168) functions have been made private. +- The [`Type` method](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/light-clients/06-solomachine/misbehaviour.go#L20) on `Misbehaviour` has been removed. + +### 07-tendermint + +- The [`IterateConsensusMetadata` function](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/light-clients/07-tendermint/store.go#L81) has been removed. The [`Initialize`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/light-clients/07-tendermint/client_state.go#L192), [`Status`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/light-clients/07-tendermint/client_state.go#L84), [`GetTimestampAtHeight`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/light-clients/07-tendermint/client_state.go#L62), [`VerifyMembership`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/light-clients/07-tendermint/client_state.go#L209), [`VerifyNonMembership`](https://github.com/cosmos/ibc-go/blob/v8.0.0/modules/light-clients/07-tendermint/client_state.go#L252) functions have been made private. + +### 08-wasm + +Refer to the [08-wasm migration documentation](../03-light-clients/04-wasm/09-migrations.md) for more information. + +### 09-localhost + +The 09-localhost light client has been made stateless and will no longer update the client on every block. The `ClientState` is constructed on demand when required. The `ClientState` itself is therefore no longer provable directly with `VerifyMembership` or `VerifyNonMembership`. + +An [automatic migration handler](https://github.com/cosmos/ibc-go/blob/release/v9.0.x/modules/core/02-client/keeper/migrations.go#L49) is configured to prune all previously stored client state data on IBC module store migration from `ConsensusVersion` 6 to 7. diff --git a/docs/versioned_docs/version-v9.0.x/05-migrations/14-v9-to-v10.md b/docs/versioned_docs/version-v9.0.x/05-migrations/14-v9-to-v10.md new file mode 100644 index 00000000000..fc00c16f5fc --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/05-migrations/14-v9-to-v10.md @@ -0,0 +1,36 @@ +# Migrating from v9 to v10 + +This guide provides instructions for migrating to a new version of ibc-go. + +There are four sections based on the four potential user groups of this document: + +- [Chains](#chains) +- [IBC Apps](#ibc-apps) + - [ICS27 - Interchain Accounts](#ics27---interchain-accounts) +- [Relayers](#relayers) +- [IBC Light Clients](#ibc-light-clients) + +**Note:** ibc-go supports golang semantic versioning and therefore all imports must be updated on major version releases. + +## Chains + +- No relevant changes were made in this release. + +## IBC Apps + +- (TODO: expand later) Removal of capabilities in `SendPacket` [\#7213](https://github.com/cosmos/ibc-go/pull/7213). +- (TODO: expand later) Removal of capabilities in `WriteAcknowledgement` [\#7225](https://github.com/cosmos/ibc-go/pull/7213). +- (TODO: expand later) Removal of capabilities in channel handshake methods [\#7232](https://github.com/cosmos/ibc-go/pull/7232). +- (TODO: expand later) More removal of capabilities in [\#7270](https://github.com/cosmos/ibc-go/pull/7270). + +### ICS27 - Interchain Accounts + +The channel capability migration introduced in v6 has been removed. Chains must upgrade from v6 or higher. + +## Relayers + +- No relevant changes were made in this release. + +## IBC Light Clients + +- No relevant changes were made in this release. diff --git a/docs/versioned_docs/version-v9.0.x/05-migrations/_category_.json b/docs/versioned_docs/version-v9.0.x/05-migrations/_category_.json new file mode 100644 index 00000000000..21f91f851a4 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/05-migrations/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Migrations", + "position": 5, + "link": null +} \ No newline at end of file diff --git a/docs/versioned_docs/version-v9.0.x/05-migrations/images/auth-module-decision-tree.png b/docs/versioned_docs/version-v9.0.x/05-migrations/images/auth-module-decision-tree.png new file mode 100644 index 00000000000..dc2c98e6618 Binary files /dev/null and b/docs/versioned_docs/version-v9.0.x/05-migrations/images/auth-module-decision-tree.png differ diff --git a/docs/versioned_docs/version-v9.0.x/05-migrations/migration.template.md b/docs/versioned_docs/version-v9.0.x/05-migrations/migration.template.md new file mode 100644 index 00000000000..09326af9626 --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/05-migrations/migration.template.md @@ -0,0 +1,28 @@ +# Migrating from \ to \ + +This guide provides instructions for migrating to a new version of ibc-go. + +There are four sections based on the four potential user groups of this document: + +- [Chains](#chains) +- [IBC Apps](#ibc-apps) +- [Relayers](#relayers) +- [IBC Light Clients](#ibc-light-clients) + +**Note:** ibc-go supports golang semantic versioning and therefore all imports must be updated on major version releases. + +## Chains + +- No relevant changes were made in this release. + +## IBC Apps + +- No relevant changes were made in this release. + +## Relayers + +- No relevant changes were made in this release. + +## IBC Light Clients + +- No relevant changes were made in this release. diff --git a/docs/versioned_docs/version-v9.0.x/images/ibcoverview-dark.svg b/docs/versioned_docs/version-v9.0.x/images/ibcoverview-dark.svg new file mode 100644 index 00000000000..e36ce323d4c --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/images/ibcoverview-dark.svg @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/versioned_docs/version-v9.0.x/images/ibcoverview-light.svg b/docs/versioned_docs/version-v9.0.x/images/ibcoverview-light.svg new file mode 100644 index 00000000000..10286c64bca --- /dev/null +++ b/docs/versioned_docs/version-v9.0.x/images/ibcoverview-light.svg @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/versioned_sidebars/version-v9.0.x-sidebars.json b/docs/versioned_sidebars/version-v9.0.x-sidebars.json new file mode 100644 index 00000000000..14944fb376c --- /dev/null +++ b/docs/versioned_sidebars/version-v9.0.x-sidebars.json @@ -0,0 +1,40 @@ +{ + "defaultSidebar": [ + { + "type": "autogenerated", + "dirName": "." + }, + { + "type": "category", + "label": "Resources", + "collapsed": false, + "items": [ + { + "type": "link", + "label": "IBC Specification", + "href": "https://github.com/cosmos/ibc" + }, + { + "type": "link", + "label": "Protobuf Documentation", + "href": "https://buf.build/cosmos/ibc/docs/main" + }, + { + "type": "link", + "label": "Developer Portal", + "href": "https://tutorials.cosmos.network" + }, + { + "type": "link", + "label": "Awesome Cosmos", + "href": "https://github.com/cosmos/awesome-cosmos" + }, + { + "type": "link", + "label": "ibc-rs", + "href": "https://github.com/cosmos/ibc-rs" + } + ] + } + ] +} diff --git a/docs/versions.json b/docs/versions.json index f97e11f9860..eb794db43d2 100644 --- a/docs/versions.json +++ b/docs/versions.json @@ -1,4 +1,5 @@ [ + "v9.0.x", "v8.5.x", "v7.8.x", "v6.3.x", diff --git a/e2e/go.mod b/e2e/go.mod index c67527f1bbc..3936cd68e02 100644 --- a/e2e/go.mod +++ b/e2e/go.mod @@ -25,7 +25,7 @@ require ( github.com/stretchr/testify v1.9.0 go.uber.org/zap v1.27.0 golang.org/x/mod v0.21.0 - google.golang.org/grpc v1.66.2 + google.golang.org/grpc v1.67.1 gopkg.in/yaml.v2 v2.4.0 ) @@ -33,18 +33,18 @@ require ( cloud.google.com/go v0.115.0 // indirect cloud.google.com/go/auth v0.6.0 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect - cloud.google.com/go/compute/metadata v0.3.0 // indirect + cloud.google.com/go/compute/metadata v0.5.0 // indirect cloud.google.com/go/iam v1.1.9 // indirect cloud.google.com/go/storage v1.41.0 // indirect - cosmossdk.io/api v0.7.5 // indirect - cosmossdk.io/client/v2 v2.0.0-beta.4 // indirect + cosmossdk.io/api v0.7.6 // indirect + cosmossdk.io/client/v2 v2.0.0-beta.5 // indirect cosmossdk.io/collections v0.4.0 // indirect cosmossdk.io/core v0.11.1 // indirect cosmossdk.io/depinject v1.0.0 // indirect cosmossdk.io/log v1.4.1 // indirect cosmossdk.io/store v1.1.1 // indirect cosmossdk.io/x/feegrant v0.1.1 // indirect - cosmossdk.io/x/tx v0.13.4 // indirect + cosmossdk.io/x/tx v0.13.5 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.2 // indirect @@ -117,7 +117,7 @@ require ( github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.3 // indirect - github.com/golang/glog v1.2.1 // indirect + github.com/golang/glog v1.2.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/mock v1.6.0 // indirect github.com/golang/protobuf v1.5.4 // indirect @@ -242,7 +242,7 @@ require ( golang.org/x/crypto v0.27.0 // indirect golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect golang.org/x/net v0.29.0 // indirect - golang.org/x/oauth2 v0.21.0 // indirect + golang.org/x/oauth2 v0.22.0 // indirect golang.org/x/sync v0.8.0 // indirect golang.org/x/sys v0.25.0 // indirect golang.org/x/term v0.24.0 // indirect @@ -251,9 +251,9 @@ require ( golang.org/x/tools v0.22.0 // indirect google.golang.org/api v0.186.0 // indirect google.golang.org/genproto v0.0.0-20240701130421-f6361c86f094 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect - google.golang.org/protobuf v1.34.2 // indirect + google.golang.org/protobuf v1.35.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/e2e/go.sum b/e2e/go.sum index 59f05a6f07e..aee68bcc541 100644 --- a/e2e/go.sum +++ b/e2e/go.sum @@ -72,8 +72,8 @@ cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= -cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= +cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= @@ -186,10 +186,10 @@ cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xX cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cosmossdk.io/api v0.7.5 h1:eMPTReoNmGUm8DeiQL9DyM8sYDjEhWzL1+nLbI9DqtQ= -cosmossdk.io/api v0.7.5/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= -cosmossdk.io/client/v2 v2.0.0-beta.4 h1:LGIzWbVTOof/IHQZeoWwxPX0fq607ONXhsfA7eUrQIg= -cosmossdk.io/client/v2 v2.0.0-beta.4/go.mod h1:c753d0sBv3AQRx6X+BOKL1aGpKjZMTZAHGiLPbVi5TE= +cosmossdk.io/api v0.7.6 h1:PC20PcXy1xYKH2KU4RMurVoFjjKkCgYRbVAD4PdqUuY= +cosmossdk.io/api v0.7.6/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +cosmossdk.io/client/v2 v2.0.0-beta.5 h1:0LVv3nEByn//hFDIrYLs2WvsEU3HodOelh4SDHnA/1I= +cosmossdk.io/client/v2 v2.0.0-beta.5/go.mod h1:4p0P6o0ro+FizakJUYS9SeM94RNbv0thLmkHRw5o5as= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= cosmossdk.io/core v0.11.1 h1:h9WfBey7NAiFfIcUhDVNS503I2P2HdZLebJlUIs8LPA= @@ -210,8 +210,8 @@ cosmossdk.io/x/evidence v0.1.1 h1:Ks+BLTa3uftFpElLTDp9L76t2b58htjVbSZ86aoK/E4= cosmossdk.io/x/evidence v0.1.1/go.mod h1:OoDsWlbtuyqS70LY51aX8FBTvguQqvFrt78qL7UzeNc= cosmossdk.io/x/feegrant v0.1.1 h1:EKFWOeo/pup0yF0svDisWWKAA9Zags6Zd0P3nRvVvw8= cosmossdk.io/x/feegrant v0.1.1/go.mod h1:2GjVVxX6G2fta8LWj7pC/ytHjryA6MHAJroBWHFNiEQ= -cosmossdk.io/x/tx v0.13.4 h1:Eg0PbJgeO0gM8p5wx6xa0fKR7hIV6+8lC56UrsvSo0Y= -cosmossdk.io/x/tx v0.13.4/go.mod h1:BkFqrnGGgW50Y6cwTy+JvgAhiffbGEKW6KF9ufcDpvk= +cosmossdk.io/x/tx v0.13.5 h1:FdnU+MdmFWn1pTsbfU0OCf2u6mJ8cqc1H4OMG418MLw= +cosmossdk.io/x/tx v0.13.5/go.mod h1:V6DImnwJMTq5qFjeGWpXNiT/fjgE4HtmclRmTqRVM3w= cosmossdk.io/x/upgrade v0.1.4 h1:/BWJim24QHoXde8Bc64/2BSEB6W4eTydq0X/2f8+g38= cosmossdk.io/x/upgrade v0.1.4/go.mod h1:9v0Aj+fs97O+Ztw+tG3/tp5JSlrmT7IcFhAebQHmOPo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -530,8 +530,8 @@ github.com/gogo/googleapis v1.4.1-0.20201022092350-68b0159b7869/go.mod h1:5YRNX2 github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= -github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= +github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -1296,8 +1296,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= -golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= +golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1676,8 +1676,8 @@ google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= google.golang.org/genproto v0.0.0-20240701130421-f6361c86f094 h1:6whtk83KtD3FkGrVb2hFXuQ+ZMbCNdakARIn/aHMmG8= google.golang.org/genproto v0.0.0-20240701130421-f6361c86f094/go.mod h1:Zs4wYw8z1zr6RNF4cwYb31mvN/EGaKAdQjNCF3DW6K4= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -1721,8 +1721,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -1739,8 +1739,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/go.mod b/go.mod index 08b5227b6e5..c20fe0e495c 100644 --- a/go.mod +++ b/go.mod @@ -5,14 +5,13 @@ toolchain go1.22.3 module github.com/cosmos/ibc-go/v9 require ( - cosmossdk.io/api v0.7.5 - cosmossdk.io/client/v2 v2.0.0-beta.3 + cosmossdk.io/api v0.7.6 cosmossdk.io/core v0.11.1 cosmossdk.io/errors v1.0.1 cosmossdk.io/log v1.4.1 cosmossdk.io/math v1.3.0 cosmossdk.io/store v1.1.1 - cosmossdk.io/x/tx v0.13.4 + cosmossdk.io/x/tx v0.13.5 cosmossdk.io/x/upgrade v0.1.4 github.com/cometbft/cometbft v0.38.12 github.com/cosmos/cosmos-db v1.0.2 @@ -26,9 +25,9 @@ require ( github.com/spf13/cast v1.7.0 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 - google.golang.org/grpc v1.66.2 - google.golang.org/protobuf v1.34.2 + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 + google.golang.org/grpc v1.67.1 + google.golang.org/protobuf v1.35.1 gopkg.in/yaml.v2 v2.4.0 ) @@ -36,7 +35,7 @@ require ( cloud.google.com/go v0.115.0 // indirect cloud.google.com/go/auth v0.6.0 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect - cloud.google.com/go/compute/metadata v0.3.0 // indirect + cloud.google.com/go/compute/metadata v0.5.0 // indirect cloud.google.com/go/iam v1.1.9 // indirect cloud.google.com/go/storage v1.41.0 // indirect cosmossdk.io/collections v0.4.0 // indirect @@ -90,7 +89,7 @@ require ( github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v1.2.1 // indirect + github.com/golang/glog v1.2.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/mock v1.6.0 // indirect github.com/golang/snappy v0.0.4 // indirect @@ -181,7 +180,7 @@ require ( golang.org/x/crypto v0.27.0 // indirect golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect golang.org/x/net v0.29.0 // indirect - golang.org/x/oauth2 v0.21.0 // indirect + golang.org/x/oauth2 v0.22.0 // indirect golang.org/x/sync v0.8.0 // indirect golang.org/x/sys v0.25.0 // indirect golang.org/x/term v0.24.0 // indirect diff --git a/go.sum b/go.sum index fc5995828a5..03de51cab79 100644 --- a/go.sum +++ b/go.sum @@ -72,8 +72,8 @@ cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= -cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= +cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= @@ -186,10 +186,8 @@ cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xX cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cosmossdk.io/api v0.7.5 h1:eMPTReoNmGUm8DeiQL9DyM8sYDjEhWzL1+nLbI9DqtQ= -cosmossdk.io/api v0.7.5/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= -cosmossdk.io/client/v2 v2.0.0-beta.3 h1:+TTuH0DwQYsUq2JFAl3fDZzKq5gQG7nt3dAattkjFDU= -cosmossdk.io/client/v2 v2.0.0-beta.3/go.mod h1:CZcL41HpJPOOayTCO28j8weNBQprG+SRiKX39votypo= +cosmossdk.io/api v0.7.6 h1:PC20PcXy1xYKH2KU4RMurVoFjjKkCgYRbVAD4PdqUuY= +cosmossdk.io/api v0.7.6/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= cosmossdk.io/core v0.11.1 h1:h9WfBey7NAiFfIcUhDVNS503I2P2HdZLebJlUIs8LPA= @@ -204,8 +202,8 @@ cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= cosmossdk.io/store v1.1.1 h1:NA3PioJtWDVU7cHHeyvdva5J/ggyLDkyH0hGHl2804Y= cosmossdk.io/store v1.1.1/go.mod h1:8DwVTz83/2PSI366FERGbWSH7hL6sB7HbYp8bqksNwM= -cosmossdk.io/x/tx v0.13.4 h1:Eg0PbJgeO0gM8p5wx6xa0fKR7hIV6+8lC56UrsvSo0Y= -cosmossdk.io/x/tx v0.13.4/go.mod h1:BkFqrnGGgW50Y6cwTy+JvgAhiffbGEKW6KF9ufcDpvk= +cosmossdk.io/x/tx v0.13.5 h1:FdnU+MdmFWn1pTsbfU0OCf2u6mJ8cqc1H4OMG418MLw= +cosmossdk.io/x/tx v0.13.5/go.mod h1:V6DImnwJMTq5qFjeGWpXNiT/fjgE4HtmclRmTqRVM3w= cosmossdk.io/x/upgrade v0.1.4 h1:/BWJim24QHoXde8Bc64/2BSEB6W4eTydq0X/2f8+g38= cosmossdk.io/x/upgrade v0.1.4/go.mod h1:9v0Aj+fs97O+Ztw+tG3/tp5JSlrmT7IcFhAebQHmOPo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -478,8 +476,8 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= -github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= +github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -1166,8 +1164,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= -golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= +golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1544,8 +1542,8 @@ google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= google.golang.org/genproto v0.0.0-20240701130421-f6361c86f094 h1:6whtk83KtD3FkGrVb2hFXuQ+ZMbCNdakARIn/aHMmG8= google.golang.org/genproto v0.0.0-20240701130421-f6361c86f094/go.mod h1:Zs4wYw8z1zr6RNF4cwYb31mvN/EGaKAdQjNCF3DW6K4= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -1589,8 +1587,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -1607,8 +1605,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/modules/apps/callbacks/go.mod b/modules/apps/callbacks/go.mod index c86dccbdeff..721ccd9021e 100644 --- a/modules/apps/callbacks/go.mod +++ b/modules/apps/callbacks/go.mod @@ -7,8 +7,8 @@ replace github.com/cosmos/ibc-go/v9 => ../../../ replace github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 require ( - cosmossdk.io/api v0.7.5 - cosmossdk.io/client/v2 v2.0.0-beta.3 + cosmossdk.io/api v0.7.6 + cosmossdk.io/client/v2 v2.0.0-beta.5 cosmossdk.io/core v0.11.1 cosmossdk.io/errors v1.0.1 cosmossdk.io/log v1.4.1 @@ -18,7 +18,7 @@ require ( cosmossdk.io/x/circuit v0.1.1 cosmossdk.io/x/evidence v0.1.1 cosmossdk.io/x/feegrant v0.1.1 - cosmossdk.io/x/tx v0.13.4 + cosmossdk.io/x/tx v0.13.5 cosmossdk.io/x/upgrade v0.1.4 github.com/cometbft/cometbft v0.38.12 github.com/cosmos/cosmos-db v1.0.2 @@ -35,7 +35,7 @@ require ( cloud.google.com/go v0.115.0 // indirect cloud.google.com/go/auth v0.6.0 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect - cloud.google.com/go/compute/metadata v0.3.0 // indirect + cloud.google.com/go/compute/metadata v0.5.0 // indirect cloud.google.com/go/iam v1.1.9 // indirect cloud.google.com/go/storage v1.41.0 // indirect cosmossdk.io/collections v0.4.0 // indirect @@ -94,7 +94,7 @@ require ( github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v1.2.1 // indirect + github.com/golang/glog v1.2.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/mock v1.6.0 // indirect github.com/golang/protobuf v1.5.4 // indirect @@ -185,7 +185,7 @@ require ( golang.org/x/crypto v0.27.0 // indirect golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect golang.org/x/net v0.29.0 // indirect - golang.org/x/oauth2 v0.21.0 // indirect + golang.org/x/oauth2 v0.22.0 // indirect golang.org/x/sync v0.8.0 // indirect golang.org/x/sys v0.25.0 // indirect golang.org/x/term v0.24.0 // indirect @@ -193,10 +193,10 @@ require ( golang.org/x/time v0.5.0 // indirect google.golang.org/api v0.186.0 // indirect google.golang.org/genproto v0.0.0-20240701130421-f6361c86f094 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect - google.golang.org/grpc v1.66.2 // indirect - google.golang.org/protobuf v1.34.2 // indirect + google.golang.org/grpc v1.67.1 // indirect + google.golang.org/protobuf v1.35.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/apps/callbacks/go.sum b/modules/apps/callbacks/go.sum index 892ba031de1..0123370b936 100644 --- a/modules/apps/callbacks/go.sum +++ b/modules/apps/callbacks/go.sum @@ -72,8 +72,8 @@ cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= -cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= +cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= @@ -186,10 +186,10 @@ cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xX cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cosmossdk.io/api v0.7.5 h1:eMPTReoNmGUm8DeiQL9DyM8sYDjEhWzL1+nLbI9DqtQ= -cosmossdk.io/api v0.7.5/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= -cosmossdk.io/client/v2 v2.0.0-beta.3 h1:+TTuH0DwQYsUq2JFAl3fDZzKq5gQG7nt3dAattkjFDU= -cosmossdk.io/client/v2 v2.0.0-beta.3/go.mod h1:CZcL41HpJPOOayTCO28j8weNBQprG+SRiKX39votypo= +cosmossdk.io/api v0.7.6 h1:PC20PcXy1xYKH2KU4RMurVoFjjKkCgYRbVAD4PdqUuY= +cosmossdk.io/api v0.7.6/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +cosmossdk.io/client/v2 v2.0.0-beta.5 h1:0LVv3nEByn//hFDIrYLs2WvsEU3HodOelh4SDHnA/1I= +cosmossdk.io/client/v2 v2.0.0-beta.5/go.mod h1:4p0P6o0ro+FizakJUYS9SeM94RNbv0thLmkHRw5o5as= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= cosmossdk.io/core v0.11.1 h1:h9WfBey7NAiFfIcUhDVNS503I2P2HdZLebJlUIs8LPA= @@ -212,8 +212,8 @@ cosmossdk.io/x/evidence v0.1.1 h1:Ks+BLTa3uftFpElLTDp9L76t2b58htjVbSZ86aoK/E4= cosmossdk.io/x/evidence v0.1.1/go.mod h1:OoDsWlbtuyqS70LY51aX8FBTvguQqvFrt78qL7UzeNc= cosmossdk.io/x/feegrant v0.1.1 h1:EKFWOeo/pup0yF0svDisWWKAA9Zags6Zd0P3nRvVvw8= cosmossdk.io/x/feegrant v0.1.1/go.mod h1:2GjVVxX6G2fta8LWj7pC/ytHjryA6MHAJroBWHFNiEQ= -cosmossdk.io/x/tx v0.13.4 h1:Eg0PbJgeO0gM8p5wx6xa0fKR7hIV6+8lC56UrsvSo0Y= -cosmossdk.io/x/tx v0.13.4/go.mod h1:BkFqrnGGgW50Y6cwTy+JvgAhiffbGEKW6KF9ufcDpvk= +cosmossdk.io/x/tx v0.13.5 h1:FdnU+MdmFWn1pTsbfU0OCf2u6mJ8cqc1H4OMG418MLw= +cosmossdk.io/x/tx v0.13.5/go.mod h1:V6DImnwJMTq5qFjeGWpXNiT/fjgE4HtmclRmTqRVM3w= cosmossdk.io/x/upgrade v0.1.4 h1:/BWJim24QHoXde8Bc64/2BSEB6W4eTydq0X/2f8+g38= cosmossdk.io/x/upgrade v0.1.4/go.mod h1:9v0Aj+fs97O+Ztw+tG3/tp5JSlrmT7IcFhAebQHmOPo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -491,8 +491,8 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= -github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= +github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -1178,8 +1178,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= -golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= +golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1554,8 +1554,8 @@ google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= google.golang.org/genproto v0.0.0-20240701130421-f6361c86f094 h1:6whtk83KtD3FkGrVb2hFXuQ+ZMbCNdakARIn/aHMmG8= google.golang.org/genproto v0.0.0-20240701130421-f6361c86f094/go.mod h1:Zs4wYw8z1zr6RNF4cwYb31mvN/EGaKAdQjNCF3DW6K4= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -1599,8 +1599,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -1617,8 +1617,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/modules/core/03-connection/types/genesis.go b/modules/core/03-connection/types/genesis.go index 941b441f7e1..fc6689a0704 100644 --- a/modules/core/03-connection/types/genesis.go +++ b/modules/core/03-connection/types/genesis.go @@ -4,6 +4,7 @@ import ( "fmt" host "github.com/cosmos/ibc-go/v9/modules/core/24-host" + "github.com/cosmos/ibc-go/v9/modules/core/exported" ) // NewConnectionPaths creates a ConnectionPaths instance. @@ -45,13 +46,14 @@ func (gs GenesisState) Validate() error { var maxSequence uint64 for i, conn := range gs.Connections { - sequence, err := ParseConnectionSequence(conn.Id) - if err != nil { - return err - } - - if sequence > maxSequence { - maxSequence = sequence + if conn.Id != exported.LocalhostConnectionID { + sequence, err := ParseConnectionSequence(conn.Id) + if err != nil { + return err + } + if sequence > maxSequence { + maxSequence = sequence + } } if err := conn.ValidateBasic(); err != nil { diff --git a/modules/core/03-connection/types/genesis_test.go b/modules/core/03-connection/types/genesis_test.go index c009d6410fb..39a930c1433 100644 --- a/modules/core/03-connection/types/genesis_test.go +++ b/modules/core/03-connection/types/genesis_test.go @@ -7,6 +7,7 @@ import ( "github.com/cosmos/ibc-go/v9/modules/core/03-connection/types" commitmenttypes "github.com/cosmos/ibc-go/v9/modules/core/23-commitment/types" + "github.com/cosmos/ibc-go/v9/modules/core/exported" ibctesting "github.com/cosmos/ibc-go/v9/testing" ) @@ -91,6 +92,20 @@ func TestValidateGenesis(t *testing.T) { ), expPass: false, }, + { + name: "localhost connection identifier", + genState: types.NewGenesisState( + []types.IdentifiedConnection{ + types.NewIdentifiedConnection(exported.LocalhostConnectionID, types.NewConnectionEnd(types.INIT, clientID, types.Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, []*types.Version{ibctesting.ConnectionVersion}, 500)), + }, + []types.ConnectionPaths{ + {clientID, []string{connectionID}}, + }, + 0, + types.DefaultParams(), + ), + expPass: true, + }, { name: "next connection sequence is not greater than maximum connection identifier sequence provided", genState: types.NewGenesisState( diff --git a/modules/core/04-channel/client/cli/tx.go b/modules/core/04-channel/client/cli/tx.go index c904336d9f4..748f9cf82be 100644 --- a/modules/core/04-channel/client/cli/tx.go +++ b/modules/core/04-channel/client/cli/tx.go @@ -70,7 +70,7 @@ func newUpgradeChannelsTxCmd() *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { versionStr := args[0] - clientCtx, err := client.GetClientQueryContext(cmd) + clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err } diff --git a/modules/core/23-commitment/types/merkle.go b/modules/core/23-commitment/types/merkle.go index a53452c43b3..319e3ea5b8b 100644 --- a/modules/core/23-commitment/types/merkle.go +++ b/modules/core/23-commitment/types/merkle.go @@ -151,7 +151,7 @@ func (proof MerkleProof) VerifyNonMembership(specs []*ics23.ProofSpec, root expo "got ExistenceProof in VerifyNonMembership. If this is unexpected, please ensure that proof was queried with the correct key.") default: return errorsmod.Wrapf(ErrInvalidProof, - "expected proof type: %T, got: %T", &ics23.CommitmentProof_Exist{}, proof.Proofs[0].Proof) + "expected proof type: %T, got: %T", &ics23.CommitmentProof_Nonexist{}, proof.Proofs[0].Proof) } return nil } diff --git a/modules/light-clients/07-tendermint/misbehaviour_handle_test.go b/modules/light-clients/07-tendermint/misbehaviour_handle_test.go index 23e7342cca8..9f81e0d9343 100644 --- a/modules/light-clients/07-tendermint/misbehaviour_handle_test.go +++ b/modules/light-clients/07-tendermint/misbehaviour_handle_test.go @@ -42,8 +42,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviour() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) err = path.EndpointA.UpdateClient() suite.Require().NoError(err) @@ -63,8 +63,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviour() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) misbehaviour = &ibctm.Misbehaviour{ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.ProposedHeader.Height+3, trustedHeight, suite.chainB.ProposedHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers), @@ -78,8 +78,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviour() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) misbehaviour = &ibctm.Misbehaviour{ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.ProposedHeader.Height+3, trustedHeight, suite.chainB.ProposedHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers), @@ -93,8 +93,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviour() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) misbehaviour = &ibctm.Misbehaviour{ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.ProposedHeader.Height+1, trustedHeight, suite.chainB.ProposedHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers), @@ -107,8 +107,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviour() { trustedHeight1, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals1, err := suite.chainB.GetTrustedValidators(int64(trustedHeight1.RevisionHeight)) - suite.Require().NoError(err) + trustedVals1, ok := suite.chainB.TrustedValidators[trustedHeight1.RevisionHeight] + suite.Require().True(ok) err = path.EndpointA.UpdateClient() suite.Require().NoError(err) @@ -116,8 +116,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviour() { trustedHeight2, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals2, err := suite.chainB.GetTrustedValidators(int64(trustedHeight2.RevisionHeight)) - suite.Require().NoError(err) + trustedVals2, ok := suite.chainB.TrustedValidators[trustedHeight2.RevisionHeight] + suite.Require().True(ok) misbehaviour = &ibctm.Misbehaviour{ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.ProposedHeader.Height, trustedHeight1, suite.chainB.ProposedHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals1, suite.chainB.Signers), @@ -131,8 +131,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviour() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) err = path.EndpointA.UpdateClient() suite.Require().NoError(err) @@ -156,8 +156,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviour() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) height, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) @@ -176,8 +176,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviour() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) // increment revision of chainID err = path.EndpointB.UpgradeChain() @@ -198,8 +198,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviour() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) err = path.EndpointA.UpdateClient() suite.Require().NoError(err) @@ -223,8 +223,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviour() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) err = path.EndpointA.UpdateClient() suite.Require().NoError(err) @@ -260,8 +260,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviour() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) misbehaviour = &ibctm.Misbehaviour{ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.ProposedHeader.Height, trustedHeight.Increment().(clienttypes.Height), suite.chainB.ProposedHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers), @@ -279,8 +279,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviour() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) err = path.EndpointA.UpdateClient() suite.Require().NoError(err) @@ -301,8 +301,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviour() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) err = path.EndpointA.UpdateClient() suite.Require().NoError(err) @@ -321,8 +321,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviour() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) err = path.EndpointA.UpdateClient() suite.Require().NoError(err) @@ -341,8 +341,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviour() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) err = path.EndpointA.UpdateClient() suite.Require().NoError(err) @@ -418,8 +418,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviourNonRevisionChainID() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) err = path.EndpointA.UpdateClient() suite.Require().NoError(err) @@ -439,8 +439,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviourNonRevisionChainID() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) misbehaviour = &ibctm.Misbehaviour{ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.ProposedHeader.Height+3, trustedHeight, suite.chainB.ProposedHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers), @@ -454,8 +454,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviourNonRevisionChainID() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) misbehaviour = &ibctm.Misbehaviour{ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.ProposedHeader.Height+3, trustedHeight, suite.chainB.ProposedHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers), @@ -469,8 +469,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviourNonRevisionChainID() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) misbehaviour = &ibctm.Misbehaviour{ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.ProposedHeader.Height+1, trustedHeight, suite.chainB.ProposedHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers), @@ -483,8 +483,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviourNonRevisionChainID() { trustedHeight1, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals1, err := suite.chainB.GetTrustedValidators(int64(trustedHeight1.RevisionHeight)) - suite.Require().NoError(err) + trustedVals1, ok := suite.chainB.TrustedValidators[trustedHeight1.RevisionHeight] + suite.Require().True(ok) err = path.EndpointA.UpdateClient() suite.Require().NoError(err) @@ -492,8 +492,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviourNonRevisionChainID() { trustedHeight2, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals2, err := suite.chainB.GetTrustedValidators(int64(trustedHeight2.RevisionHeight)) - suite.Require().NoError(err) + trustedVals2, ok := suite.chainB.TrustedValidators[trustedHeight2.RevisionHeight] + suite.Require().True(ok) misbehaviour = &ibctm.Misbehaviour{ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.ProposedHeader.Height, trustedHeight1, suite.chainB.ProposedHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals1, suite.chainB.Signers), @@ -507,8 +507,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviourNonRevisionChainID() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) err = path.EndpointA.UpdateClient() suite.Require().NoError(err) @@ -532,8 +532,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviourNonRevisionChainID() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) err = path.EndpointA.UpdateClient() suite.Require().NoError(err) @@ -569,8 +569,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviourNonRevisionChainID() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) misbehaviour = &ibctm.Misbehaviour{ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.ProposedHeader.Height, trustedHeight.Increment().(clienttypes.Height), suite.chainB.ProposedHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers), @@ -588,8 +588,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviourNonRevisionChainID() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) err = path.EndpointA.UpdateClient() suite.Require().NoError(err) @@ -610,8 +610,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviourNonRevisionChainID() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) err = path.EndpointA.UpdateClient() suite.Require().NoError(err) @@ -630,8 +630,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviourNonRevisionChainID() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) err = path.EndpointA.UpdateClient() suite.Require().NoError(err) @@ -650,8 +650,8 @@ func (suite *TendermintTestSuite) TestVerifyMisbehaviourNonRevisionChainID() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) err = path.EndpointA.UpdateClient() suite.Require().NoError(err) diff --git a/modules/light-clients/07-tendermint/update_test.go b/modules/light-clients/07-tendermint/update_test.go index aa53c5544cd..ab4deca0f86 100644 --- a/modules/light-clients/07-tendermint/update_test.go +++ b/modules/light-clients/07-tendermint/update_test.go @@ -52,8 +52,8 @@ func (suite *TendermintTestSuite) TestVerifyHeader() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight) + 1) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight+1] + suite.Require().True(ok) // passing the ProposedHeader.Height as the block height as it will become a previous height once we commit N blocks header = suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.ProposedHeader.Height, trustedHeight, suite.chainB.ProposedHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers) @@ -72,8 +72,8 @@ func (suite *TendermintTestSuite) TestVerifyHeader() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight) + 1) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight+1] + suite.Require().True(ok) // Create bothValSet with both suite validator and altVal bothValSet := cmttypes.NewValidatorSet(append(suite.chainB.Vals.Validators, altVal)) @@ -90,8 +90,8 @@ func (suite *TendermintTestSuite) TestVerifyHeader() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight) + 1) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight+1] + suite.Require().True(ok) // Create bothValSet with both suite validator and altVal bothValSet := cmttypes.NewValidatorSet(append(suite.chainB.Vals.Validators, altVal)) @@ -123,8 +123,8 @@ func (suite *TendermintTestSuite) TestVerifyHeader() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight) + 1) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight+1] + suite.Require().True(ok) // this will err as altValSet.Hash() != consState.NextValidatorsHash header = suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.ProposedHeader.Height+1, trustedHeight, suite.chainB.ProposedHeader.Time, altValSet, altValSet, trustedVals, altSigners) @@ -137,8 +137,8 @@ func (suite *TendermintTestSuite) TestVerifyHeader() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight) + 1) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight+1] + suite.Require().True(ok) header = suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.ProposedHeader.Height+1, trustedHeight, suite.chainB.ProposedHeader.Time, altValSet, altValSet, trustedVals, altSigners) }, @@ -149,8 +149,8 @@ func (suite *TendermintTestSuite) TestVerifyHeader() { malleate: func() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight) + 1) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight+1] + suite.Require().True(ok) header = suite.chainB.CreateTMClientHeader(chainIDRevision1, 3, trustedHeight, suite.chainB.ProposedHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers) }, @@ -162,8 +162,8 @@ func (suite *TendermintTestSuite) TestVerifyHeader() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight) + 1) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight+1] + suite.Require().True(ok) heightMinus1 := clienttypes.NewHeight(trustedHeight.RevisionNumber, trustedHeight.RevisionHeight-1) @@ -186,8 +186,8 @@ func (suite *TendermintTestSuite) TestVerifyHeader() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) header = suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.ProposedHeader.Height+1, trustedHeight, suite.chainB.ProposedHeader.Time.Add(-time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers) }, @@ -199,8 +199,8 @@ func (suite *TendermintTestSuite) TestVerifyHeader() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) header = suite.chainB.CreateTMClientHeader(chainID, suite.chainB.ProposedHeader.Height+1, trustedHeight, suite.chainB.ProposedHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers) }, @@ -212,8 +212,8 @@ func (suite *TendermintTestSuite) TestVerifyHeader() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight] + suite.Require().True(ok) header = suite.chainA.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.ProposedHeader.Height+1, trustedHeight, suite.chainB.ProposedHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers) @@ -227,8 +227,8 @@ func (suite *TendermintTestSuite) TestVerifyHeader() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight) + 1) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight+1] + suite.Require().True(ok) // passing the ProposedHeader.Height as the block height as it will become an update to previous revision once we upgrade the client header = suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.ProposedHeader.Height, trustedHeight, suite.chainB.ProposedHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers) @@ -245,8 +245,8 @@ func (suite *TendermintTestSuite) TestVerifyHeader() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight) + 1) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight+1] + suite.Require().True(ok) // passing the ProposedHeader.Height as the block height as it will become a previous height once we commit N blocks header = suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.ProposedHeader.Height, trustedHeight, suite.chainB.ProposedHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers) @@ -264,8 +264,8 @@ func (suite *TendermintTestSuite) TestVerifyHeader() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight) + 1) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight+1] + suite.Require().True(ok) header = suite.chainB.CreateTMClientHeader(suite.chainB.ChainID+"-1", suite.chainB.ProposedHeader.Height+5, trustedHeight, suite.chainB.ProposedHeader.Time, suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers) }, @@ -278,8 +278,8 @@ func (suite *TendermintTestSuite) TestVerifyHeader() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight) + 1) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight+1] + suite.Require().True(ok) // increment the revision of the chain err = path.EndpointB.UpgradeChain() @@ -757,10 +757,10 @@ func (suite *TendermintTestSuite) TestCheckForMisbehaviour() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight) + 1) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight+1] + suite.Require().True(ok) - err = path.EndpointA.UpdateClient() + err := path.EndpointA.UpdateClient() suite.Require().NoError(err) height, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) @@ -778,8 +778,8 @@ func (suite *TendermintTestSuite) TestCheckForMisbehaviour() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight) + 1) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight+1] + suite.Require().True(ok) clientMessage = &ibctm.Misbehaviour{ Header1: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.ProposedHeader.Height+3, trustedHeight, suite.chainB.ProposedHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers), @@ -866,8 +866,8 @@ func (suite *TendermintTestSuite) TestCheckForMisbehaviour() { trustedHeight, ok := path.EndpointA.GetClientLatestHeight().(clienttypes.Height) suite.Require().True(ok) - trustedVals, err := suite.chainB.GetTrustedValidators(int64(trustedHeight.RevisionHeight) + 1) - suite.Require().NoError(err) + trustedVals, ok := suite.chainB.TrustedValidators[trustedHeight.RevisionHeight+1] + suite.Require().True(ok) clientMessage = &ibctm.Misbehaviour{ Header2: suite.chainB.CreateTMClientHeader(suite.chainB.ChainID, suite.chainB.ProposedHeader.Height+3, trustedHeight, suite.chainB.ProposedHeader.Time.Add(time.Minute), suite.chainB.Vals, suite.chainB.NextVals, trustedVals, suite.chainB.Signers), diff --git a/modules/light-clients/08-wasm/go.mod b/modules/light-clients/08-wasm/go.mod index 72b8df1f04d..a4ba263bfac 100644 --- a/modules/light-clients/08-wasm/go.mod +++ b/modules/light-clients/08-wasm/go.mod @@ -9,8 +9,8 @@ replace github.com/cosmos/ibc-go/v9 => ../../../ replace github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 require ( - cosmossdk.io/api v0.7.5 - cosmossdk.io/client/v2 v2.0.0-beta.3 + cosmossdk.io/api v0.7.6 + cosmossdk.io/client/v2 v2.0.0-beta.5 cosmossdk.io/collections v0.4.0 cosmossdk.io/core v0.11.1 cosmossdk.io/errors v1.0.1 @@ -21,7 +21,7 @@ require ( cosmossdk.io/x/circuit v0.1.1 cosmossdk.io/x/evidence v0.1.1 cosmossdk.io/x/feegrant v0.1.1 - cosmossdk.io/x/tx v0.13.4 + cosmossdk.io/x/tx v0.13.5 cosmossdk.io/x/upgrade v0.1.4 github.com/CosmWasm/wasmvm/v2 v2.1.2 github.com/cometbft/cometbft v0.38.12 @@ -35,15 +35,15 @@ require ( github.com/spf13/cobra v1.8.1 github.com/spf13/viper v1.19.0 github.com/stretchr/testify v1.9.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 - google.golang.org/grpc v1.66.2 + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 + google.golang.org/grpc v1.67.1 ) require ( cloud.google.com/go v0.115.0 // indirect cloud.google.com/go/auth v0.6.0 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect - cloud.google.com/go/compute/metadata v0.3.0 // indirect + cloud.google.com/go/compute/metadata v0.5.0 // indirect cloud.google.com/go/iam v1.1.9 // indirect cloud.google.com/go/storage v1.41.0 // indirect cosmossdk.io/depinject v1.0.0 // indirect @@ -101,7 +101,7 @@ require ( github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v1.2.1 // indirect + github.com/golang/glog v1.2.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/mock v1.6.0 // indirect github.com/golang/snappy v0.0.4 // indirect @@ -191,7 +191,7 @@ require ( golang.org/x/crypto v0.27.0 // indirect golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect golang.org/x/net v0.29.0 // indirect - golang.org/x/oauth2 v0.21.0 // indirect + golang.org/x/oauth2 v0.22.0 // indirect golang.org/x/sync v0.8.0 // indirect golang.org/x/sys v0.25.0 // indirect golang.org/x/term v0.24.0 // indirect @@ -200,7 +200,7 @@ require ( google.golang.org/api v0.186.0 // indirect google.golang.org/genproto v0.0.0-20240701130421-f6361c86f094 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect - google.golang.org/protobuf v1.34.2 // indirect + google.golang.org/protobuf v1.35.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/modules/light-clients/08-wasm/go.sum b/modules/light-clients/08-wasm/go.sum index fbd65828cd4..afaead9c1eb 100644 --- a/modules/light-clients/08-wasm/go.sum +++ b/modules/light-clients/08-wasm/go.sum @@ -72,8 +72,8 @@ cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= -cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= +cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= @@ -186,10 +186,10 @@ cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xX cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cosmossdk.io/api v0.7.5 h1:eMPTReoNmGUm8DeiQL9DyM8sYDjEhWzL1+nLbI9DqtQ= -cosmossdk.io/api v0.7.5/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= -cosmossdk.io/client/v2 v2.0.0-beta.3 h1:+TTuH0DwQYsUq2JFAl3fDZzKq5gQG7nt3dAattkjFDU= -cosmossdk.io/client/v2 v2.0.0-beta.3/go.mod h1:CZcL41HpJPOOayTCO28j8weNBQprG+SRiKX39votypo= +cosmossdk.io/api v0.7.6 h1:PC20PcXy1xYKH2KU4RMurVoFjjKkCgYRbVAD4PdqUuY= +cosmossdk.io/api v0.7.6/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +cosmossdk.io/client/v2 v2.0.0-beta.5 h1:0LVv3nEByn//hFDIrYLs2WvsEU3HodOelh4SDHnA/1I= +cosmossdk.io/client/v2 v2.0.0-beta.5/go.mod h1:4p0P6o0ro+FizakJUYS9SeM94RNbv0thLmkHRw5o5as= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= cosmossdk.io/core v0.11.1 h1:h9WfBey7NAiFfIcUhDVNS503I2P2HdZLebJlUIs8LPA= @@ -212,8 +212,8 @@ cosmossdk.io/x/evidence v0.1.1 h1:Ks+BLTa3uftFpElLTDp9L76t2b58htjVbSZ86aoK/E4= cosmossdk.io/x/evidence v0.1.1/go.mod h1:OoDsWlbtuyqS70LY51aX8FBTvguQqvFrt78qL7UzeNc= cosmossdk.io/x/feegrant v0.1.1 h1:EKFWOeo/pup0yF0svDisWWKAA9Zags6Zd0P3nRvVvw8= cosmossdk.io/x/feegrant v0.1.1/go.mod h1:2GjVVxX6G2fta8LWj7pC/ytHjryA6MHAJroBWHFNiEQ= -cosmossdk.io/x/tx v0.13.4 h1:Eg0PbJgeO0gM8p5wx6xa0fKR7hIV6+8lC56UrsvSo0Y= -cosmossdk.io/x/tx v0.13.4/go.mod h1:BkFqrnGGgW50Y6cwTy+JvgAhiffbGEKW6KF9ufcDpvk= +cosmossdk.io/x/tx v0.13.5 h1:FdnU+MdmFWn1pTsbfU0OCf2u6mJ8cqc1H4OMG418MLw= +cosmossdk.io/x/tx v0.13.5/go.mod h1:V6DImnwJMTq5qFjeGWpXNiT/fjgE4HtmclRmTqRVM3w= cosmossdk.io/x/upgrade v0.1.4 h1:/BWJim24QHoXde8Bc64/2BSEB6W4eTydq0X/2f8+g38= cosmossdk.io/x/upgrade v0.1.4/go.mod h1:9v0Aj+fs97O+Ztw+tG3/tp5JSlrmT7IcFhAebQHmOPo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -493,8 +493,8 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= -github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= +github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -1182,8 +1182,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= -golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= +golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1558,8 +1558,8 @@ google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= google.golang.org/genproto v0.0.0-20240701130421-f6361c86f094 h1:6whtk83KtD3FkGrVb2hFXuQ+ZMbCNdakARIn/aHMmG8= google.golang.org/genproto v0.0.0-20240701130421-f6361c86f094/go.mod h1:Zs4wYw8z1zr6RNF4cwYb31mvN/EGaKAdQjNCF3DW6K4= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -1603,8 +1603,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -1621,8 +1621,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/simapp/README.md b/simapp/README.md index a3488dc0d53..86efd020404 100644 --- a/simapp/README.md +++ b/simapp/README.md @@ -1,47 +1,110 @@ -# simapp - -simapp is an application built using the Cosmos SDK for testing and educational purposes. - -## Running testnets with `simd` - -If you want to spin up a quick testnet with your friends, you can follow these steps. -Unless otherwise noted, every step must be done by everyone who wants to participate -in this testnet. - -1. `$ make build`. This will build the `simd` binary and install it in your Cosmos SDK repo, - inside a new `build` directory. The following instructions are run from inside - that directory. -2. If you've run `simd` before, you may need to reset your database before starting a new - testnet: `$ ./simd unsafe-reset-all` -3. `$ ./simd init [moniker]`. This will initialize a new working directory, by default at - `~/.simapp`. You need a provide a "moniker," but it doesn't matter what it is. -4. `$ ./simd keys add [key_name]`. This will create a new key, with a name of your choosing. - Save the output of this command somewhere; you'll need the address generated here later. -5. `$ ./simd add-genesis-account $(simd keys show [key_name] -a) [amount]`, where `key_name` - is the same key name as before; and `amount` is something like `10000000000000000000000000stake`. -6. `$ ./simd gentx [key_name] [amount] --chain-id [chain-id]`. This will create the - genesis transaction for your new chain. -7. Now, one person needs to create the genesis file `genesis.json` using the genesis transactions - from every participant, by gathering all the genesis transactions under `config/gentx` and then - calling `./simd collect-gentxs`. This will create a new `genesis.json` file that includes data - from all the validators (we sometimes call it the "super genesis file" to distinguish it from - single-validator genesis files). -8. Once you've received the super genesis file, overwrite your original `genesis.json` file with - the new super `genesis.json`. -9. Modify your `config/config.toml` (in the simapp working directory) to include the other participants as - persistent peers: - - ```text - # Comma separated list of nodes to keep persistent connections to - persistent_peers = "[validator address]@[ip address]:[port],[validator address]@[ip address]:[port]" - ``` - - You can find `validator address` by running `./simd tendermint show-node-id`. (It will be hex-encoded.) - By default, `port` is 26656. -10. Now you can start your nodes: `$ ./simd start`. - -Now you have a small testnet that you can use to try out changes to the Cosmos SDK or Tendermint! - -NOTE: Sometimes creating the network through the `collect-gentxs` will fail, and validators will start -in a funny state (and then panic). If this happens, you can try to create and start the network first -with a single validator and then add additional validators using a `create-validator` transaction. +# `SimApp` + +`SimApp` is a CLI application built using the Cosmos SDK for testing and educational purposes. + +## Running Testnets with `simd` + +Want to spin up a quick testnet with your friends? Follow these steps. Unless stated otherwise, all participants in the testnet must follow through with each step. + +### 1. Download and Setup + +Download IBC-go and unzip it. You can do this manually (via the GitHub UI) or with the git clone command: + +```sh +git clone github.com/cosmos/ibc-go.git +``` + +Next, run this command to build the `simd` binary in the `build` directory: + +```sh +make build +``` + +Use the following command and skip all the next steps to configure your SimApp node: + +```sh +make init-simapp +``` + +If you've run `simd` in the past, you may need to reset your database before starting up a new testnet. You can do that with this command: + +```sh +# you need to provide the moniker and chain ID +$ ./simd init [moniker] --chain-id [chain-id] +``` + +The command should initialize a new working directory at the `~simapp` location. +The `moniker` and `chain-id` can be anything, but you must use the same `chain-id` subsequently. + +### 2. Create a New Key + +Execute this command to create a new key: + +```sh + ./simd keys add [key_name] +``` + +⚠️ The command will create a new key with your chosen name. +Save the output somewhere safe; you'll need the address later. + +### 3. Add Genesis Account + +Add a genesis account to your testnet blockchain: + +```sh +./simd genesis add-genesis-account [key_name] [amount] +``` + +Where `key_name` is the same key name as before, and the `amount` is something like `10000000000000000000000000stake`. + +### 4. Add the Genesis Transaction + +This creates the genesis transaction for your testnet chain: + +```sh +./simd genesis gentx [key_name] [amount] --chain-id [chain-id] +``` + +The amount should be at least `1000000000stake`. Providing too much or too little may result in errors when you start your node. + +### 5. Create the Genesis File + +A participant must create the genesis file `genesis.json` with every participant's transaction. +You can do this by gathering all the Genesis transactions under `config/gentx` and then executing this command: + +```sh +./simd genesis collect-gentxs +``` + +The command will create a new `genesis.json` file that includes data from all the validators. We sometimes call this the "super genesis file" to distinguish it from single-validator genesis files. + +Once you've received the super genesis file, overwrite your original `genesis.json` file with the new super `genesis.json`. + +Modify your `config/config.toml` (in the simapp working directory) to include the other participants as persistent peers: + +```toml +# Comma-separated list of nodes to keep persistent connections to +persistent_peers = "[validator_address]@[ip_address]:[port],[validator_address]@[ip_address]:[port]" +``` + +You can find `validator_address` by executing: + +```sh +./simd comet show-node-id +``` + +The output will be the hex-encoded `validator_address`. The default `port` is 26656. + +### 6. Start the Nodes + +Finally, execute this command to start your nodes: + +```sh +./simd start +``` + +Now you have a small testnet that you can use to try out changes to the Cosmos SDK or CometBFT! + +> ⚠️ NOTE: Sometimes, creating the network through the `collect-gentxs` will fail, and validators will start in a funny state (and then panic). +> +> If this happens, you can try to create and start the network first with a single validator and then add additional validators using a `create-validator` transaction. diff --git a/simapp/app.go b/simapp/app.go index 2994befb5a4..cba03e2f857 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -123,16 +123,10 @@ import ( ibckeeper "github.com/cosmos/ibc-go/v9/modules/core/keeper" solomachine "github.com/cosmos/ibc-go/v9/modules/light-clients/06-solomachine" ibctm "github.com/cosmos/ibc-go/v9/modules/light-clients/07-tendermint" - "github.com/cosmos/ibc-go/v9/testing/mock" ) const appName = "SimApp" -// IBC application testing ports -const ( - MockFeePort string = mock.ModuleName + ibcfeetypes.ModuleName -) - var ( // DefaultNodeHome default home directories for the application daemon DefaultNodeHome string @@ -148,7 +142,6 @@ var ( ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, ibcfeetypes.ModuleName: nil, icatypes.ModuleName: nil, - mock.ModuleName: nil, } ) @@ -167,9 +160,8 @@ type SimApp struct { interfaceRegistry types.InterfaceRegistry // keys to access the substores - keys map[string]*storetypes.KVStoreKey - tkeys map[string]*storetypes.TransientStoreKey - memKeys map[string]*storetypes.MemoryStoreKey + keys map[string]*storetypes.KVStoreKey + tkeys map[string]*storetypes.TransientStoreKey // keepers AccountKeeper authkeeper.AccountKeeper @@ -194,12 +186,6 @@ type SimApp struct { ConsensusParamsKeeper consensusparamkeeper.Keeper CircuitKeeper circuitkeeper.Keeper - // make IBC modules public for test purposes - // these modules are never directly routed to by the IBC Router - IBCMockModule mock.IBCModule - ICAAuthModule mock.IBCModule - FeeMockModule mock.IBCModule - // the module manager ModuleManager *module.Manager BasicModuleManager module.BasicManager @@ -293,7 +279,6 @@ func NewSimApp( } tkeys := storetypes.NewTransientStoreKeys(paramstypes.TStoreKey) - memKeys := storetypes.NewMemoryStoreKeys(mock.MemStoreKey) app := &SimApp{ BaseApp: bApp, @@ -303,7 +288,6 @@ func NewSimApp( interfaceRegistry: interfaceRegistry, keys: keys, tkeys: tkeys, - memKeys: memKeys, } app.ParamsKeeper = initParamsKeeper(appCodec, legacyAmino, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey]) @@ -430,25 +414,6 @@ func NewSimApp( authtypes.NewModuleAddress(govtypes.ModuleName).String(), ) - // Mock Module Stack - - // Mock Module setup for testing IBC and also acts as the interchain accounts authentication module - // NOTE: the IBC mock keeper and application module is used only for testing core IBC. Do - // not replicate if you do not need to test core IBC or light clients. - mockModule := mock.NewAppModule() - - // The mock module is used for testing IBC - mockIBCModule := mock.NewIBCModule(&mockModule, mock.NewIBCApp(mock.ModuleName)) - app.IBCMockModule = mockIBCModule - ibcRouter.AddRoute(mock.ModuleName, mockIBCModule) - - // Mock IBC app wrapped with a middleware which does not implement the UpgradeableModule interface. - // NOTE: this is used to test integration with apps which do not yet fulfill the UpgradeableModule interface and error when - // an upgrade is tried on the channel. - mockBlockUpgradeIBCModule := mock.NewIBCModule(&mockModule, mock.NewIBCApp(mock.MockBlockUpgrade)) - mockBlockUpgradeMw := mock.NewBlockUpgradeMiddleware(&mockModule, mockBlockUpgradeIBCModule.IBCApp) - ibcRouter.AddRoute(mock.MockBlockUpgrade, mockBlockUpgradeMw) - // Create Transfer Stack // SendPacket, since it is originating from the application to core IBC: // transferKeeper.SendPacket -> fee.SendPacket -> channel.SendPacket @@ -471,15 +436,7 @@ func NewSimApp( // Create Interchain Accounts Stack // SendPacket, since it is originating from the application to core IBC: // icaControllerKeeper.SendTx -> fee.SendPacket -> channel.SendPacket - - // initialize ICA module with mock module as the authentication module on the controller side var icaControllerStack porttypes.IBCModule - icaControllerStack = mock.NewIBCModule(&mockModule, mock.NewIBCApp("")) - var ok bool - app.ICAAuthModule, ok = icaControllerStack.(mock.IBCModule) - if !ok { - panic(fmt.Errorf("cannot convert %T into %T", icaControllerStack, app.ICAAuthModule)) - } icaControllerStack = icacontroller.NewIBCMiddleware(app.ICAControllerKeeper) icaControllerStack = ibcfee.NewIBCMiddleware(icaControllerStack, app.IBCFeeKeeper) @@ -493,23 +450,7 @@ func NewSimApp( // Add host, controller & ica auth modules to IBC router ibcRouter. AddRoute(icacontrollertypes.SubModuleName, icaControllerStack). - AddRoute(icahosttypes.SubModuleName, icaHostStack). - AddRoute(mock.ModuleName+icacontrollertypes.SubModuleName, icaControllerStack) // ica with mock auth module stack route to ica (top level of middleware stack) - - // Create Mock IBC Fee module stack for testing - // SendPacket, mock module cannot send packets - - // OnRecvPacket, message that originates from core IBC and goes down to app, the flow is the otherway - // channel.RecvPacket -> fee.OnRecvPacket -> mockModule.OnRecvPacket - - // OnAcknowledgementPacket as this is where fee's are paid out - // mockModule.OnAcknowledgementPacket -> fee.OnAcknowledgementPacket -> channel.OnAcknowledgementPacket - - // create fee wrapped mock module - feeMockModule := mock.NewIBCModule(&mockModule, mock.NewIBCApp(MockFeePort)) - app.FeeMockModule = feeMockModule - feeWithMockModule := ibcfee.NewIBCMiddleware(feeMockModule, app.IBCFeeKeeper) - ibcRouter.AddRoute(MockFeePort, feeWithMockModule) + AddRoute(icahosttypes.SubModuleName, icaHostStack) // Set the IBC Routers app.IBCKeeper.SetRouter(ibcRouter) @@ -566,7 +507,6 @@ func NewSimApp( transfer.NewAppModule(app.TransferKeeper), ibcfee.NewAppModule(app.IBCFeeKeeper), ica.NewAppModule(&app.ICAControllerKeeper, &app.ICAHostKeeper), - mockModule, // IBC light clients ibctm.NewAppModule(tmLightClientModule), @@ -611,7 +551,6 @@ func NewSimApp( authz.ModuleName, icatypes.ModuleName, ibcfeetypes.ModuleName, - mock.ModuleName, ) app.ModuleManager.SetOrderEndBlockers( crisistypes.ModuleName, @@ -623,7 +562,6 @@ func NewSimApp( feegrant.ModuleName, icatypes.ModuleName, ibcfeetypes.ModuleName, - mock.ModuleName, group.ModuleName, ) @@ -635,7 +573,7 @@ func NewSimApp( banktypes.ModuleName, distrtypes.ModuleName, stakingtypes.ModuleName, slashingtypes.ModuleName, govtypes.ModuleName, minttypes.ModuleName, crisistypes.ModuleName, ibcexported.ModuleName, genutiltypes.ModuleName, evidencetypes.ModuleName, authz.ModuleName, ibctransfertypes.ModuleName, - icatypes.ModuleName, ibcfeetypes.ModuleName, mock.ModuleName, feegrant.ModuleName, paramstypes.ModuleName, upgradetypes.ModuleName, + icatypes.ModuleName, ibcfeetypes.ModuleName, feegrant.ModuleName, paramstypes.ModuleName, upgradetypes.ModuleName, vestingtypes.ModuleName, group.ModuleName, consensusparamtypes.ModuleName, circuittypes.ModuleName, } app.ModuleManager.SetOrderInitGenesis(genesisModuleOrder...) @@ -680,7 +618,6 @@ func NewSimApp( // initialize stores app.MountKVStores(keys) app.MountTransientStores(tkeys) - app.MountMemoryStores(memKeys) // initialize BaseApp app.SetInitChainer(app.InitChainer) @@ -949,7 +886,6 @@ func BlockedAddresses() map[string]bool { // allow the following addresses to receive funds delete(modAccAddrs, authtypes.NewModuleAddress(govtypes.ModuleName).String()) - delete(modAccAddrs, authtypes.NewModuleAddress(mock.ModuleName).String()) return modAccAddrs } @@ -968,10 +904,3 @@ func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino return paramsKeeper } - -// GetMemKey returns the MemStoreKey for the provided mem key. -// -// NOTE: This is solely used for testing purposes. -func (app *SimApp) GetMemKey(storeKey string) *storetypes.MemoryStoreKey { - return app.memKeys[storeKey] -} diff --git a/simapp/go.mod b/simapp/go.mod index 0e27d1f8ac0..b13be1a5d8c 100644 --- a/simapp/go.mod +++ b/simapp/go.mod @@ -7,8 +7,8 @@ module github.com/cosmos/ibc-go/simapp replace github.com/cosmos/ibc-go/v9 => ../ require ( - cosmossdk.io/api v0.7.5 - cosmossdk.io/client/v2 v2.0.0-beta.4 + cosmossdk.io/api v0.7.6 + cosmossdk.io/client/v2 v2.0.0-beta.5 cosmossdk.io/core v0.11.1 cosmossdk.io/log v1.4.1 cosmossdk.io/store v1.1.1 @@ -16,7 +16,7 @@ require ( cosmossdk.io/x/circuit v0.1.1 cosmossdk.io/x/evidence v0.1.1 cosmossdk.io/x/feegrant v0.1.1 - cosmossdk.io/x/tx v0.13.4 + cosmossdk.io/x/tx v0.13.5 cosmossdk.io/x/upgrade v0.1.4 github.com/cometbft/cometbft v0.38.12 github.com/cosmos/cosmos-db v1.0.2 @@ -33,7 +33,7 @@ require ( cloud.google.com/go v0.115.0 // indirect cloud.google.com/go/auth v0.6.0 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect - cloud.google.com/go/compute/metadata v0.3.0 // indirect + cloud.google.com/go/compute/metadata v0.5.0 // indirect cloud.google.com/go/iam v1.1.9 // indirect cloud.google.com/go/storage v1.41.0 // indirect cosmossdk.io/collections v0.4.0 // indirect @@ -94,7 +94,7 @@ require ( github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v1.2.1 // indirect + github.com/golang/glog v1.2.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/mock v1.6.0 // indirect github.com/golang/protobuf v1.5.4 // indirect @@ -185,7 +185,7 @@ require ( golang.org/x/crypto v0.27.0 // indirect golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect golang.org/x/net v0.29.0 // indirect - golang.org/x/oauth2 v0.21.0 // indirect + golang.org/x/oauth2 v0.22.0 // indirect golang.org/x/sync v0.8.0 // indirect golang.org/x/sys v0.25.0 // indirect golang.org/x/term v0.24.0 // indirect @@ -193,10 +193,10 @@ require ( golang.org/x/time v0.5.0 // indirect google.golang.org/api v0.186.0 // indirect google.golang.org/genproto v0.0.0-20240701130421-f6361c86f094 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect - google.golang.org/grpc v1.66.2 // indirect - google.golang.org/protobuf v1.34.2 // indirect + google.golang.org/grpc v1.67.1 // indirect + google.golang.org/protobuf v1.35.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/simapp/go.sum b/simapp/go.sum index 2c87428eded..0123370b936 100644 --- a/simapp/go.sum +++ b/simapp/go.sum @@ -72,8 +72,8 @@ cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= -cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= +cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= @@ -186,10 +186,10 @@ cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xX cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cosmossdk.io/api v0.7.5 h1:eMPTReoNmGUm8DeiQL9DyM8sYDjEhWzL1+nLbI9DqtQ= -cosmossdk.io/api v0.7.5/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= -cosmossdk.io/client/v2 v2.0.0-beta.4 h1:LGIzWbVTOof/IHQZeoWwxPX0fq607ONXhsfA7eUrQIg= -cosmossdk.io/client/v2 v2.0.0-beta.4/go.mod h1:c753d0sBv3AQRx6X+BOKL1aGpKjZMTZAHGiLPbVi5TE= +cosmossdk.io/api v0.7.6 h1:PC20PcXy1xYKH2KU4RMurVoFjjKkCgYRbVAD4PdqUuY= +cosmossdk.io/api v0.7.6/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +cosmossdk.io/client/v2 v2.0.0-beta.5 h1:0LVv3nEByn//hFDIrYLs2WvsEU3HodOelh4SDHnA/1I= +cosmossdk.io/client/v2 v2.0.0-beta.5/go.mod h1:4p0P6o0ro+FizakJUYS9SeM94RNbv0thLmkHRw5o5as= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= cosmossdk.io/core v0.11.1 h1:h9WfBey7NAiFfIcUhDVNS503I2P2HdZLebJlUIs8LPA= @@ -212,8 +212,8 @@ cosmossdk.io/x/evidence v0.1.1 h1:Ks+BLTa3uftFpElLTDp9L76t2b58htjVbSZ86aoK/E4= cosmossdk.io/x/evidence v0.1.1/go.mod h1:OoDsWlbtuyqS70LY51aX8FBTvguQqvFrt78qL7UzeNc= cosmossdk.io/x/feegrant v0.1.1 h1:EKFWOeo/pup0yF0svDisWWKAA9Zags6Zd0P3nRvVvw8= cosmossdk.io/x/feegrant v0.1.1/go.mod h1:2GjVVxX6G2fta8LWj7pC/ytHjryA6MHAJroBWHFNiEQ= -cosmossdk.io/x/tx v0.13.4 h1:Eg0PbJgeO0gM8p5wx6xa0fKR7hIV6+8lC56UrsvSo0Y= -cosmossdk.io/x/tx v0.13.4/go.mod h1:BkFqrnGGgW50Y6cwTy+JvgAhiffbGEKW6KF9ufcDpvk= +cosmossdk.io/x/tx v0.13.5 h1:FdnU+MdmFWn1pTsbfU0OCf2u6mJ8cqc1H4OMG418MLw= +cosmossdk.io/x/tx v0.13.5/go.mod h1:V6DImnwJMTq5qFjeGWpXNiT/fjgE4HtmclRmTqRVM3w= cosmossdk.io/x/upgrade v0.1.4 h1:/BWJim24QHoXde8Bc64/2BSEB6W4eTydq0X/2f8+g38= cosmossdk.io/x/upgrade v0.1.4/go.mod h1:9v0Aj+fs97O+Ztw+tG3/tp5JSlrmT7IcFhAebQHmOPo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -491,8 +491,8 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= -github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= +github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -1178,8 +1178,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= -golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= +golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1554,8 +1554,8 @@ google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= google.golang.org/genproto v0.0.0-20240701130421-f6361c86f094 h1:6whtk83KtD3FkGrVb2hFXuQ+ZMbCNdakARIn/aHMmG8= google.golang.org/genproto v0.0.0-20240701130421-f6361c86f094/go.mod h1:Zs4wYw8z1zr6RNF4cwYb31mvN/EGaKAdQjNCF3DW6K4= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= +google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -1599,8 +1599,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -1617,8 +1617,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/testing/README.md b/testing/README.md index 297a3150d3f..844b011fd99 100644 --- a/testing/README.md +++ b/testing/README.md @@ -323,8 +323,7 @@ This might look like: ```go suite.chainA.GetSimApp().ICAAuthModule.IBCApp.OnChanOpenInit = func( ctx sdk.Context, order channeltypes.Order, connectionHops []string, - portID, channelID string, chanCap *capabilitytypes.Capability, - counterparty channeltypes.Counterparty, version string, + portID, channelID string, counterparty channeltypes.Counterparty, version string, ) error { return fmt.Errorf("mock ica auth fails") } diff --git a/testing/chain.go b/testing/chain.go index 8a8dbabba0f..a898b64fd3d 100644 --- a/testing/chain.go +++ b/testing/chain.go @@ -17,8 +17,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - "github.com/cosmos/cosmos-sdk/x/staking/testutil" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" abci "github.com/cometbft/cometbft/abci/types" "github.com/cometbft/cometbft/crypto/tmhash" @@ -73,6 +71,10 @@ type TestChain struct { // the new PrivValidator entry. Signers map[string]cmttypes.PrivValidator + // TrustedValidators is a mapping used to obtain the validator set from which we can prove a header update. + // It maps from a header height to the next validator set associated with that header. + TrustedValidators map[uint64]*cmttypes.ValidatorSet + // autogenerated sender private key SenderPrivKey cryptotypes.PrivKey SenderAccount sdk.AccountI @@ -145,19 +147,20 @@ func NewTestChainWithValSet(tb testing.TB, coord *Coordinator, chainID string, v // create an account to send transactions from chain := &TestChain{ - TB: tb, - Coordinator: coord, - ChainID: chainID, - App: app, - ProposedHeader: header, - TxConfig: txConfig, - Codec: app.AppCodec(), - Vals: valSet, - NextVals: valSet, - Signers: signers, - SenderPrivKey: senderAccs[0].SenderPrivKey, - SenderAccount: senderAccs[0].SenderAccount, - SenderAccounts: senderAccs, + TB: tb, + Coordinator: coord, + ChainID: chainID, + App: app, + ProposedHeader: header, + TxConfig: txConfig, + Codec: app.AppCodec(), + Vals: valSet, + NextVals: valSet, + Signers: signers, + TrustedValidators: make(map[uint64]*cmttypes.ValidatorSet, 0), + SenderPrivKey: senderAccs[0].SenderPrivKey, + SenderAccount: senderAccs[0].SenderAccount, + SenderAccounts: senderAccs, } // commit genesis block @@ -309,12 +312,20 @@ func (chain *TestChain) commitBlock(res *abci.ResponseFinalizeBlock) { // set the last header to the current header // use nil trusted fields chain.LatestCommittedHeader = chain.CurrentTMClientHeader() + // set the trusted validator set to the next validator set + // The latest trusted validator set is the next validator set + // associated with the header being committed in storage. This will + // allow for header updates to be proved against these validators. + chain.TrustedValidators[uint64(chain.ProposedHeader.Height)] = chain.NextVals // val set changes returned from previous block get applied to the next validators // of this block. See tendermint spec for details. chain.Vals = chain.NextVals chain.NextVals = ApplyValSetChanges(chain, chain.Vals, res.ValidatorUpdates) + // increment the proposer priority of validators + chain.Vals.IncrementProposerPriority(1) + // increment the current header chain.ProposedHeader = cmtproto.Header{ ChainID: chain.ChainID, @@ -325,7 +336,7 @@ func (chain *TestChain) commitBlock(res *abci.ResponseFinalizeBlock) { Time: chain.ProposedHeader.Time, ValidatorsHash: chain.Vals.Hash(), NextValidatorsHash: chain.NextVals.Hash(), - ProposerAddress: chain.ProposedHeader.ProposerAddress, + ProposerAddress: chain.Vals.Proposer.Address, } } @@ -400,39 +411,6 @@ func (chain *TestChain) GetConsensusState(clientID string, height exported.Heigh return chain.App.GetIBCKeeper().ClientKeeper.GetClientConsensusState(chain.GetContext(), clientID, height) } -// GetTrustedValidators will return the trusted validator set of the chain for the given trusted height. Otherwise -// it will return an error. -func (chain *TestChain) GetTrustedValidators(trustedHeight int64) (*cmttypes.ValidatorSet, error) { - // historical information does not store the validator set which committed the header at - // height h. During BeginBlock, it stores the last updated validator set. This is equivalent to - // the next validator set at height h. This is because cometbft processes the validator set - // as follows: - // - // valSetChanges := endBlock() - // chain.Vals = chain.NextVals - // chain.NextVals = applyValSetChanges(chain.NextVals, valSetChanges) - // - // At height h, the validators in the historical information are the: - // validators used to sign height h + 1 (next validator set) - // - // Since we want to return the trusted validator set, which is the next validator set - // for height h, we can simply query using the trusted height. - histInfo, err := chain.App.GetStakingKeeper().GetHistoricalInfo(chain.GetContext(), trustedHeight) - if err != nil { - return nil, err - } - - valSet := stakingtypes.Validators{ - Validators: histInfo.Valset, - } - - tmValidators, err := testutil.ToCmtValidators(valSet, sdk.DefaultPowerReduction) - if err != nil { - return nil, err - } - return cmttypes.NewValidatorSet(tmValidators), nil -} - // GetAcknowledgement retrieves an acknowledgement for the provided packet. If the // acknowledgement does not exist then testing will fail. func (chain *TestChain) GetAcknowledgement(packet channeltypes.Packet) []byte { @@ -593,9 +571,9 @@ func (chain *TestChain) IBCClientHeader(header *ibctm.Header, trustedHeight clie return nil, errorsmod.Wrap(ibctm.ErrInvalidHeaderHeight, "trustedHeight must be a non-zero height") } - cmtTrustedVals, err := chain.GetTrustedValidators(int64(trustedHeight.RevisionHeight)) - if err != nil { - return nil, err + cmtTrustedVals, ok := chain.TrustedValidators[trustedHeight.RevisionHeight] + if !ok { + return nil, fmt.Errorf("unable to find trusted validators at height %d", trustedHeight.RevisionHeight) } trustedVals, err := cmtTrustedVals.ToProto() diff --git a/testing/chain_test.go b/testing/chain_test.go index 512e426eaca..e72057765b3 100644 --- a/testing/chain_test.go +++ b/testing/chain_test.go @@ -7,6 +7,7 @@ import ( sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/staking/types" ibctesting "github.com/cosmos/ibc-go/v9/testing" @@ -41,3 +42,36 @@ func TestChangeValSet(t *testing.T) { err = path.EndpointB.UpdateClient() require.NoError(t, err) } + +func TestJailProposerValidator(t *testing.T) { + coord := ibctesting.NewCoordinator(t, 2) + chainA := coord.GetChain(ibctesting.GetChainID(1)) + chainB := coord.GetChain(ibctesting.GetChainID(2)) + + path := ibctesting.NewPath(chainA, chainB) + coord.Setup(path) + + // save valset length before jailing + valsetLen := len(chainA.Vals.Validators) + + // jail the proposer validator in chain A + propAddr := sdk.ConsAddress(chainA.Vals.Proposer.Address) + + err := chainA.GetSimApp().StakingKeeper.Jail( + chainA.GetContext(), propAddr) + require.NoError(t, err) + + coord.CommitBlock(chainA) + + // verify that update clients works even after validator update goes into effect + err = path.EndpointB.UpdateClient() + require.NoError(t, err) + err = path.EndpointB.UpdateClient() + require.NoError(t, err) + + // check that the jailing has taken effect in chain A + require.Equal(t, valsetLen-1, len(chainA.Vals.Validators)) + + // check that the valset in chain A has a new proposer + require.False(t, propAddr.Equals(sdk.ConsAddress(chainA.Vals.Proposer.Address))) +} diff --git a/testing/simapp/app.go b/testing/simapp/app.go index 6ac8d9a87aa..320d5957b83 100644 --- a/testing/simapp/app.go +++ b/testing/simapp/app.go @@ -11,10 +11,6 @@ import ( "github.com/cosmos/gogoproto/proto" "github.com/spf13/cast" - autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" - reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1" - "cosmossdk.io/client/v2/autocli" - "cosmossdk.io/core/appmodule" "cosmossdk.io/log" storetypes "cosmossdk.io/store/types" "cosmossdk.io/x/tx/signing" @@ -31,7 +27,6 @@ import ( "github.com/cosmos/cosmos-sdk/codec/address" "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/runtime" - runtimeservices "github.com/cosmos/cosmos-sdk/runtime/services" "github.com/cosmos/cosmos-sdk/server" "github.com/cosmos/cosmos-sdk/server/api" "github.com/cosmos/cosmos-sdk/server/config" @@ -610,14 +605,6 @@ func NewSimApp( panic(err) } - autocliv1.RegisterQueryServer(app.GRPCQueryRouter(), runtimeservices.NewAutoCLIQueryService(app.ModuleManager.Modules)) - - reflectionSvc, err := runtimeservices.NewReflectionService() - if err != nil { - panic(err) - } - reflectionv1.RegisterReflectionServiceServer(app.GRPCQueryRouter(), reflectionSvc) - // add test gRPC service for testing gRPC queries in isolation testpb.RegisterQueryServer(app.GRPCQueryRouter(), testpb.QueryImpl{}) @@ -786,24 +773,6 @@ func (app *SimApp) TxConfig() client.TxConfig { return app.txConfig } -// AutoCliOpts returns the autocli options for the app. -func (app *SimApp) AutoCliOpts() autocli.AppOptions { - modules := make(map[string]appmodule.AppModule, 0) - for _, m := range app.ModuleManager.Modules { - if moduleWithName, ok := m.(module.HasName); ok { - moduleName := moduleWithName.Name() - if appModule, ok := moduleWithName.(appmodule.AppModule); ok { - modules[moduleName] = appModule - } - } - } - - return autocli.AppOptions{ - Modules: modules, - ModuleOptions: runtimeservices.ExtractAutoCLIOptions(app.ModuleManager.Modules), - } -} - // DefaultGenesis returns a default genesis from the registered AppModuleBasic's. func (app *SimApp) DefaultGenesis() map[string]json.RawMessage { return app.BasicModuleManager.DefaultGenesis(app.appCodec)