From bbc7046c5c11b88b858f57def56e838b0aa54585 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Fri, 29 Nov 2024 14:12:28 +0000 Subject: [PATCH 01/22] Add PFM related deps Co-authored-by: Jacob Turner --- Cargo.lock | 108 ++++++--- Cargo.toml | 12 +- crates/ibc/Cargo.toml | 2 + crates/ibc/src/context/common.rs | 9 +- crates/ibc/src/context/nft_transfer_mod.rs | 6 +- crates/ibc/src/context/transfer_mod.rs | 6 +- crates/ibc/src/context/validation.rs | 12 +- crates/ibc/src/lib.rs | 17 +- crates/tests/Cargo.toml | 2 + wasm/Cargo.lock | 124 ++++++++--- wasm_for_tests/Cargo.lock | 246 ++++++++++++++++++--- 11 files changed, 420 insertions(+), 124 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fd21a50996..fac60b7c5d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1885,6 +1885,16 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +[[package]] +name = "dur" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce5b6c91b5e394b75cd96c36393fc938496c030220207a0ccf34d6cd313d3b49" +dependencies = [ + "nom", + "rust_decimal", +] + [[package]] name = "duration-str" version = "0.10.0" @@ -3333,7 +3343,7 @@ dependencies = [ [[package]] name = "ibc" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-apps", "ibc-clients", @@ -3346,7 +3356,7 @@ dependencies = [ [[package]] name = "ibc-app-nft-transfer" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-app-nft-transfer-types", "ibc-core", @@ -3356,7 +3366,7 @@ dependencies = [ [[package]] name = "ibc-app-nft-transfer-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "arbitrary", "base64 0.22.1", @@ -3378,7 +3388,7 @@ dependencies = [ [[package]] name = "ibc-app-transfer" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-app-transfer-types", "ibc-core", @@ -3388,7 +3398,7 @@ dependencies = [ [[package]] name = "ibc-app-transfer-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "arbitrary", "borsh", @@ -3407,7 +3417,7 @@ dependencies = [ [[package]] name = "ibc-apps" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-app-nft-transfer", "ibc-app-transfer", @@ -3416,7 +3426,7 @@ dependencies = [ [[package]] name = "ibc-client-tendermint" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "derive_more", "ibc-client-tendermint-types", @@ -3433,7 +3443,7 @@ dependencies = [ [[package]] name = "ibc-client-tendermint-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "displaydoc", "ibc-core-client-types", @@ -3450,7 +3460,7 @@ dependencies = [ [[package]] name = "ibc-client-wasm-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "base64 0.22.1", "displaydoc", @@ -3464,7 +3474,7 @@ dependencies = [ [[package]] name = "ibc-clients" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-client-tendermint", "ibc-client-wasm-types", @@ -3473,7 +3483,7 @@ dependencies = [ [[package]] name = "ibc-core" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -3489,7 +3499,7 @@ dependencies = [ [[package]] name = "ibc-core-channel" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-core-channel-types", "ibc-core-client", @@ -3504,7 +3514,7 @@ dependencies = [ [[package]] name = "ibc-core-channel-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "arbitrary", "borsh", @@ -3528,7 +3538,7 @@ dependencies = [ [[package]] name = "ibc-core-client" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-core-client-context", "ibc-core-client-types", @@ -3541,7 +3551,7 @@ dependencies = [ [[package]] name = "ibc-core-client-context" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "derive_more", "displaydoc", @@ -3557,7 +3567,7 @@ dependencies = [ [[package]] name = "ibc-core-client-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "arbitrary", "borsh", @@ -3578,7 +3588,7 @@ dependencies = [ [[package]] name = "ibc-core-commitment-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "arbitrary", "borsh", @@ -3598,7 +3608,7 @@ dependencies = [ [[package]] name = "ibc-core-connection" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-client-wasm-types", "ibc-core-client", @@ -3612,7 +3622,7 @@ dependencies = [ [[package]] name = "ibc-core-connection-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "arbitrary", "borsh", @@ -3634,7 +3644,7 @@ dependencies = [ [[package]] name = "ibc-core-handler" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -3649,7 +3659,7 @@ dependencies = [ [[package]] name = "ibc-core-handler-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "arbitrary", "borsh", @@ -3674,7 +3684,7 @@ dependencies = [ [[package]] name = "ibc-core-host" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "derive_more", "displaydoc", @@ -3692,7 +3702,7 @@ dependencies = [ [[package]] name = "ibc-core-host-cosmos" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "derive_more", "displaydoc", @@ -3715,7 +3725,7 @@ dependencies = [ [[package]] name = "ibc-core-host-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "arbitrary", "borsh", @@ -3731,7 +3741,7 @@ dependencies = [ [[package]] name = "ibc-core-router" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "derive_more", "displaydoc", @@ -3745,7 +3755,7 @@ dependencies = [ [[package]] name = "ibc-core-router-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "borsh", "derive_more", @@ -3764,17 +3774,36 @@ dependencies = [ [[package]] name = "ibc-derive" version = "0.8.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "proc-macro2", "quote", "syn 2.0.52", ] +[[package]] +name = "ibc-middleware-packet-forward" +version = "0.6.0" +source = "git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.6.0#ca824cfbe550c529d30bf27a97026dd0a058cfdf" +dependencies = [ + "borsh", + "dur", + "either", + "ibc-app-transfer-types", + "ibc-core-channel", + "ibc-core-channel-types", + "ibc-core-host-types", + "ibc-core-router", + "ibc-core-router-types", + "ibc-primitives", + "serde", + "serde_json", +] + [[package]] name = "ibc-primitives" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "arbitrary", "borsh", @@ -3815,7 +3844,7 @@ dependencies = [ [[package]] name = "ibc-query" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "displaydoc", "ibc", @@ -3826,7 +3855,7 @@ dependencies = [ [[package]] name = "ibc-testkit" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "basecoin-store", "derive_more", @@ -5047,8 +5076,10 @@ dependencies = [ "assert_matches", "borsh", "data-encoding", + "dur", "ibc", "ibc-derive", + "ibc-middleware-packet-forward", "ibc-testkit", "ics23", "konst", @@ -5478,12 +5509,14 @@ dependencies = [ "concat-idents", "data-encoding", "derivative", + "dur", "escargot", "expectrl", "eyre", "flate2", "fs_extra", "hyper 0.14.27", + "ibc-middleware-packet-forward", "ibc-testkit", "ics23", "itertools 0.12.1", @@ -7265,12 +7298,18 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.35.0" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1790d1c4c0ca81211399e0e0af16333276f375209e71a37b67698a373db5b47a" +checksum = "b082d80e3e3cc52b2ed634388d436fe1f4de6af5786cc2de9ba9737527bdf555" dependencies = [ "arrayvec", + "borsh", + "bytes", "num-traits 0.2.17", + "rand 0.8.5", + "rkyv", + "serde", + "serde_json", ] [[package]] @@ -7660,11 +7699,12 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] diff --git a/Cargo.toml b/Cargo.toml index e8f5805ff4..0510ff1cf5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -100,6 +100,7 @@ derivation-path = "0.2.0" derivative = "2.2.0" directories = "4.0.1" drain_filter_polyfill = "0.1.3" +dur = "0.5.3" duration-str = "0.10.0" ed25519-consensus = "2.1.0" either = "1.12.0" @@ -118,10 +119,11 @@ flume = "0.11.1" fs_extra = "1.2.0" futures = "0.3" git2 = { version = "0.18.1", default-features = false } -# branch yuji/derive-arbitrary -ibc = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "38bd2a32f35117d4d9165a3c68c64ccd87ad56dd", features = ["serde"] } -ibc-derive = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" } -ibc-testkit = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "38bd2a32f35117d4d9165a3c68c64ccd87ad56dd", default-features = false } +# branch tiago/optional-ack +ibc = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "aa229566e6bb688cc2626dab276c3849abc0c583", features = ["serde"] } +ibc-derive = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "aa229566e6bb688cc2626dab276c3849abc0c583" } +ibc-middleware-packet-forward = { git = "https://github.com/heliaxdev/ibc-middleware", tag = "pfm/v0.6.0", features = ["borsh"] } +ibc-testkit = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "aa229566e6bb688cc2626dab276c3849abc0c583", default-features = false } ics23 = "0.12.0" usize-set = { version = "0.10.3", features = ["serialize-borsh", "serialize-serde"] } indexmap = { git = "https://github.com/heliaxdev/indexmap", tag = "2.2.4-heliax-1", features = ["borsh-schema", "serde"] } @@ -174,7 +176,7 @@ rpassword = "5.0.1" rustversion = "1.0" serde = {version = "1.0.125", features = ["derive"]} serde_bytes = "0.11.5" -serde_json = "1.0.62" +serde_json = "1.0.133" serde_tuple = "0.5.0" sha2 = "0.9.3" sha2-const = "0.1.2" diff --git a/crates/ibc/Cargo.toml b/crates/ibc/Cargo.toml index 39f0c77965..f520e810c3 100644 --- a/crates/ibc/Cargo.toml +++ b/crates/ibc/Cargo.toml @@ -40,10 +40,12 @@ namada_vp = { path = "../vp" } arbitrary = { workspace = true, optional = true } borsh.workspace = true data-encoding.workspace = true +dur.workspace = true konst.workspace = true linkme = {workspace = true, optional = true} ibc.workspace = true ibc-derive.workspace = true +ibc-middleware-packet-forward.workspace = true ibc-testkit = {workspace = true, optional = true} ics23.workspace = true masp_primitives.workspace = true diff --git a/crates/ibc/src/context/common.rs b/crates/ibc/src/context/common.rs index 7f920d8cb3..35233fd70e 100644 --- a/crates/ibc/src/context/common.rs +++ b/crates/ibc/src/context/common.rs @@ -576,14 +576,11 @@ pub trait IbcCommonContext: IbcStorageContext { port_id: &PortId, channel_id: &ChannelId, sequence: Sequence, - ) -> Result { + ) -> Result> { let key = storage::ack_key(port_id, channel_id, sequence); match self.storage().read_bytes(&key)? { - Some(value) => Ok(value.into()), - None => { - Err(PacketError::PacketAcknowledgementNotFound { sequence } - .into()) - } + Some(value) => Ok(Some(value.into())), + None => Ok(None), } } diff --git a/crates/ibc/src/context/nft_transfer_mod.rs b/crates/ibc/src/context/nft_transfer_mod.rs index 420d80362e..b8450468ce 100644 --- a/crates/ibc/src/context/nft_transfer_mod.rs +++ b/crates/ibc/src/context/nft_transfer_mod.rs @@ -261,7 +261,7 @@ where &mut self, packet: &Packet, _relayer: &Signer, - ) -> (ModuleExtras, Acknowledgement) { + ) -> (ModuleExtras, Option) { on_recv_packet_execute(&mut self.ctx, packet) } @@ -482,10 +482,10 @@ pub mod testing { &mut self, _packet: &Packet, _relayer: &Signer, - ) -> (ModuleExtras, Acknowledgement) { + ) -> (ModuleExtras, Option) { ( ModuleExtras::empty(), - AcknowledgementStatus::success(ack_success_b64()).into(), + Some(AcknowledgementStatus::success(ack_success_b64()).into()), ) } diff --git a/crates/ibc/src/context/transfer_mod.rs b/crates/ibc/src/context/transfer_mod.rs index 9a1075e280..a30826514d 100644 --- a/crates/ibc/src/context/transfer_mod.rs +++ b/crates/ibc/src/context/transfer_mod.rs @@ -276,7 +276,7 @@ where &mut self, packet: &Packet, _relayer: &Signer, - ) -> (ModuleExtras, Acknowledgement) { + ) -> (ModuleExtras, Option) { on_recv_packet_execute(&mut self.ctx, packet) } @@ -497,10 +497,10 @@ pub mod testing { &mut self, _packet: &Packet, _relayer: &Signer, - ) -> (ModuleExtras, Acknowledgement) { + ) -> (ModuleExtras, Option) { ( ModuleExtras::empty(), - AcknowledgementStatus::success(ack_success_b64()).into(), + Some(AcknowledgementStatus::success(ack_success_b64()).into()), ) } diff --git a/crates/ibc/src/context/validation.rs b/crates/ibc/src/context/validation.rs index 0f00feefcf..7173a14a82 100644 --- a/crates/ibc/src/context/validation.rs +++ b/crates/ibc/src/context/validation.rs @@ -5,6 +5,7 @@ use ibc::core::channel::types::channel::ChannelEnd; use ibc::core::channel::types::commitment::{ AcknowledgementCommitment, PacketCommitment, }; +use ibc::core::channel::types::error::PacketError; use ibc::core::channel::types::packet::Receipt; use ibc::core::client::context::{ ClientValidationContext, ExtClientValidationContext, @@ -253,11 +254,18 @@ where &self, path: &AckPath, ) -> Result { - self.inner.borrow().packet_ack( + let maybe_ack = self.inner.borrow().packet_ack( &path.port_id, &path.channel_id, path.sequence, - ) + )?; + + maybe_ack.ok_or_else(|| { + PacketError::PacketAcknowledgementNotFound { + sequence: path.sequence, + } + .into() + }) } fn channel_counter(&self) -> Result { diff --git a/crates/ibc/src/lib.rs b/crates/ibc/src/lib.rs index 9fa49d58aa..bd5aafc814 100644 --- a/crates/ibc/src/lib.rs +++ b/crates/ibc/src/lib.rs @@ -143,6 +143,8 @@ pub enum Error { ChainId(IdentifierError), #[error("Verifier insertion error: {0}")] Verifier(StorageError), + #[error("Storage read/write error: {0}")] + Storage(StorageError), #[error("IBC error: {0}")] Other(String), } @@ -690,7 +692,9 @@ where // Extract MASP tx from the memo in the packet if needed let masp_tx = match &*envelope { MsgEnvelope::Packet(PacketMsg::Recv(msg)) - if self.is_receiving_success(msg)? => + if self + .is_receiving_success(msg)? + .is_some_and(|ack_succ| ack_succ) => { extract_masp_tx_from_packet(&msg.packet) } @@ -713,8 +717,8 @@ where pub fn is_receiving_success( &self, msg: &IbcMsgRecvPacket, - ) -> Result { - let packet_ack = self + ) -> Result, Error> { + let Some(packet_ack) = self .ctx .inner .borrow() @@ -723,11 +727,14 @@ where &msg.packet.chan_id_on_b, msg.packet.seq_on_a, ) - .map_err(|e| Error::Context(Box::new(e)))?; + .map_err(|e| Error::Context(Box::new(e)))? + else { + return Ok(None); + }; let success_ack_commitment = compute_ack_commitment( &AcknowledgementStatus::success(ack_success_b64()).into(), ); - Ok(packet_ack == success_ack_commitment) + Ok(Some(packet_ack == success_ack_commitment)) } /// Validate according to the message in IBC VP diff --git a/crates/tests/Cargo.toml b/crates/tests/Cargo.toml index add26e1621..9ce5aca59e 100644 --- a/crates/tests/Cargo.toml +++ b/crates/tests/Cargo.toml @@ -38,7 +38,9 @@ namada_vm = {path = "../vm", features = ["testing"]} concat-idents.workspace = true derivative.workspace = true +dur.workspace = true hyper = {version = "0.14.20", features = ["full"]} +ibc-middleware-packet-forward.workspace = true ibc-testkit.workspace = true ics23.workspace = true itertools.workspace = true diff --git a/wasm/Cargo.lock b/wasm/Cargo.lock index 343b1db0ad..870d5ee10e 100644 --- a/wasm/Cargo.lock +++ b/wasm/Cargo.lock @@ -1362,6 +1362,16 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +[[package]] +name = "dur" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce5b6c91b5e394b75cd96c36393fc938496c030220207a0ccf34d6cd313d3b49" +dependencies = [ + "nom", + "rust_decimal", +] + [[package]] name = "duration-str" version = "0.10.0" @@ -2550,7 +2560,7 @@ dependencies = [ [[package]] name = "ibc" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-apps", "ibc-clients", @@ -2563,7 +2573,7 @@ dependencies = [ [[package]] name = "ibc-app-nft-transfer" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-app-nft-transfer-types", "ibc-core", @@ -2573,7 +2583,7 @@ dependencies = [ [[package]] name = "ibc-app-nft-transfer-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "base64 0.22.1", "borsh", @@ -2594,7 +2604,7 @@ dependencies = [ [[package]] name = "ibc-app-transfer" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-app-transfer-types", "ibc-core", @@ -2604,7 +2614,7 @@ dependencies = [ [[package]] name = "ibc-app-transfer-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "borsh", "derive_more", @@ -2622,7 +2632,7 @@ dependencies = [ [[package]] name = "ibc-apps" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-app-nft-transfer", "ibc-app-transfer", @@ -2631,7 +2641,7 @@ dependencies = [ [[package]] name = "ibc-client-tendermint" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "derive_more", "ibc-client-tendermint-types", @@ -2648,7 +2658,7 @@ dependencies = [ [[package]] name = "ibc-client-tendermint-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "displaydoc", "ibc-core-client-types", @@ -2665,7 +2675,7 @@ dependencies = [ [[package]] name = "ibc-client-wasm-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "base64 0.22.1", "displaydoc", @@ -2679,7 +2689,7 @@ dependencies = [ [[package]] name = "ibc-clients" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-client-tendermint", "ibc-client-wasm-types", @@ -2688,7 +2698,7 @@ dependencies = [ [[package]] name = "ibc-core" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -2704,7 +2714,7 @@ dependencies = [ [[package]] name = "ibc-core-channel" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-core-channel-types", "ibc-core-client", @@ -2719,7 +2729,7 @@ dependencies = [ [[package]] name = "ibc-core-channel-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "borsh", "derive_more", @@ -2742,7 +2752,7 @@ dependencies = [ [[package]] name = "ibc-core-client" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-core-client-context", "ibc-core-client-types", @@ -2755,7 +2765,7 @@ dependencies = [ [[package]] name = "ibc-core-client-context" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "derive_more", "displaydoc", @@ -2771,7 +2781,7 @@ dependencies = [ [[package]] name = "ibc-core-client-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "borsh", "derive_more", @@ -2791,7 +2801,7 @@ dependencies = [ [[package]] name = "ibc-core-commitment-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "borsh", "derive_more", @@ -2810,7 +2820,7 @@ dependencies = [ [[package]] name = "ibc-core-connection" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-client-wasm-types", "ibc-core-client", @@ -2824,7 +2834,7 @@ dependencies = [ [[package]] name = "ibc-core-connection-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "borsh", "derive_more", @@ -2845,7 +2855,7 @@ dependencies = [ [[package]] name = "ibc-core-handler" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -2860,7 +2870,7 @@ dependencies = [ [[package]] name = "ibc-core-handler-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "borsh", "derive_more", @@ -2884,7 +2894,7 @@ dependencies = [ [[package]] name = "ibc-core-host" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "derive_more", "displaydoc", @@ -2902,7 +2912,7 @@ dependencies = [ [[package]] name = "ibc-core-host-cosmos" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "derive_more", "displaydoc", @@ -2925,7 +2935,7 @@ dependencies = [ [[package]] name = "ibc-core-host-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "borsh", "derive_more", @@ -2940,7 +2950,7 @@ dependencies = [ [[package]] name = "ibc-core-router" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "derive_more", "displaydoc", @@ -2954,7 +2964,7 @@ dependencies = [ [[package]] name = "ibc-core-router-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "borsh", "derive_more", @@ -2973,17 +2983,36 @@ dependencies = [ [[package]] name = "ibc-derive" version = "0.8.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "proc-macro2", "quote", "syn 2.0.52", ] +[[package]] +name = "ibc-middleware-packet-forward" +version = "0.6.0" +source = "git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.6.0#ca824cfbe550c529d30bf27a97026dd0a058cfdf" +dependencies = [ + "borsh", + "dur", + "either", + "ibc-app-transfer-types", + "ibc-core-channel", + "ibc-core-channel-types", + "ibc-core-host-types", + "ibc-core-router", + "ibc-core-router-types", + "ibc-primitives", + "serde", + "serde_json", +] + [[package]] name = "ibc-primitives" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "borsh", "derive_more", @@ -3023,7 +3052,7 @@ dependencies = [ [[package]] name = "ibc-query" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "displaydoc", "ibc", @@ -3034,7 +3063,7 @@ dependencies = [ [[package]] name = "ibc-testkit" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "basecoin-store", "derive_more", @@ -3565,6 +3594,12 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.7.1" @@ -3764,8 +3799,10 @@ version = "0.46.1" dependencies = [ "borsh", "data-encoding", + "dur", "ibc", "ibc-derive", + "ibc-middleware-packet-forward", "ibc-testkit", "ics23", "konst", @@ -4049,7 +4086,9 @@ version = "0.46.1" dependencies = [ "concat-idents", "derivative", + "dur", "hyper 0.14.27", + "ibc-middleware-packet-forward", "ibc-testkit", "ics23", "itertools 0.12.1", @@ -4319,6 +4358,16 @@ dependencies = [ "tempfile", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nonempty" version = "0.7.0" @@ -5466,12 +5515,18 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.35.0" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1790d1c4c0ca81211399e0e0af16333276f375209e71a37b67698a373db5b47a" +checksum = "b082d80e3e3cc52b2ed634388d436fe1f4de6af5786cc2de9ba9737527bdf555" dependencies = [ "arrayvec", + "borsh", + "bytes", "num-traits 0.2.17", + "rand 0.8.5", + "rkyv", + "serde", + "serde_json", ] [[package]] @@ -5834,11 +5889,12 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] diff --git a/wasm_for_tests/Cargo.lock b/wasm_for_tests/Cargo.lock index f578ba42bc..e20c43470c 100644 --- a/wasm_for_tests/Cargo.lock +++ b/wasm_for_tests/Cargo.lock @@ -23,6 +23,17 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "1.1.2" @@ -381,6 +392,28 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +[[package]] +name = "bytecheck" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "byteorder" version = "1.5.0" @@ -683,6 +716,16 @@ dependencies = [ "syn 2.0.65", ] +[[package]] +name = "dur" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce5b6c91b5e394b75cd96c36393fc938496c030220207a0ccf34d6cd313d3b49" +dependencies = [ + "nom", + "rust_decimal", +] + [[package]] name = "dyn-clone" version = "1.0.16" @@ -1027,6 +1070,15 @@ dependencies = [ "subtle", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + [[package]] name = "hashbrown" version = "0.14.3" @@ -1100,7 +1152,7 @@ dependencies = [ [[package]] name = "ibc" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-apps", "ibc-clients", @@ -1113,7 +1165,7 @@ dependencies = [ [[package]] name = "ibc-app-nft-transfer" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-app-nft-transfer-types", "ibc-core", @@ -1123,7 +1175,7 @@ dependencies = [ [[package]] name = "ibc-app-nft-transfer-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "base64 0.22.1", "borsh", @@ -1144,7 +1196,7 @@ dependencies = [ [[package]] name = "ibc-app-transfer" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-app-transfer-types", "ibc-core", @@ -1154,7 +1206,7 @@ dependencies = [ [[package]] name = "ibc-app-transfer-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "borsh", "derive_more", @@ -1172,7 +1224,7 @@ dependencies = [ [[package]] name = "ibc-apps" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-app-nft-transfer", "ibc-app-transfer", @@ -1181,7 +1233,7 @@ dependencies = [ [[package]] name = "ibc-client-tendermint" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "derive_more", "ibc-client-tendermint-types", @@ -1198,7 +1250,7 @@ dependencies = [ [[package]] name = "ibc-client-tendermint-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "displaydoc", "ibc-core-client-types", @@ -1215,7 +1267,7 @@ dependencies = [ [[package]] name = "ibc-client-wasm-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "base64 0.22.1", "displaydoc", @@ -1229,7 +1281,7 @@ dependencies = [ [[package]] name = "ibc-clients" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-client-tendermint", "ibc-client-wasm-types", @@ -1238,7 +1290,7 @@ dependencies = [ [[package]] name = "ibc-core" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -1254,7 +1306,7 @@ dependencies = [ [[package]] name = "ibc-core-channel" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-core-channel-types", "ibc-core-client", @@ -1269,7 +1321,7 @@ dependencies = [ [[package]] name = "ibc-core-channel-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "borsh", "derive_more", @@ -1292,7 +1344,7 @@ dependencies = [ [[package]] name = "ibc-core-client" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-core-client-context", "ibc-core-client-types", @@ -1305,7 +1357,7 @@ dependencies = [ [[package]] name = "ibc-core-client-context" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "derive_more", "displaydoc", @@ -1321,7 +1373,7 @@ dependencies = [ [[package]] name = "ibc-core-client-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "borsh", "derive_more", @@ -1341,7 +1393,7 @@ dependencies = [ [[package]] name = "ibc-core-commitment-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "borsh", "derive_more", @@ -1360,7 +1412,7 @@ dependencies = [ [[package]] name = "ibc-core-connection" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-client-wasm-types", "ibc-core-client", @@ -1374,7 +1426,7 @@ dependencies = [ [[package]] name = "ibc-core-connection-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "borsh", "derive_more", @@ -1395,7 +1447,7 @@ dependencies = [ [[package]] name = "ibc-core-handler" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -1410,7 +1462,7 @@ dependencies = [ [[package]] name = "ibc-core-handler-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "borsh", "derive_more", @@ -1434,7 +1486,7 @@ dependencies = [ [[package]] name = "ibc-core-host" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "derive_more", "displaydoc", @@ -1452,7 +1504,7 @@ dependencies = [ [[package]] name = "ibc-core-host-cosmos" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "derive_more", "displaydoc", @@ -1475,7 +1527,7 @@ dependencies = [ [[package]] name = "ibc-core-host-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "borsh", "derive_more", @@ -1490,7 +1542,7 @@ dependencies = [ [[package]] name = "ibc-core-router" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "derive_more", "displaydoc", @@ -1504,7 +1556,7 @@ dependencies = [ [[package]] name = "ibc-core-router-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "borsh", "derive_more", @@ -1523,17 +1575,36 @@ dependencies = [ [[package]] name = "ibc-derive" version = "0.8.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "proc-macro2", "quote", "syn 2.0.65", ] +[[package]] +name = "ibc-middleware-packet-forward" +version = "0.6.0" +source = "git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.6.0#ca824cfbe550c529d30bf27a97026dd0a058cfdf" +dependencies = [ + "borsh", + "dur", + "either", + "ibc-app-transfer-types", + "ibc-core-channel", + "ibc-core-channel-types", + "ibc-core-host-types", + "ibc-core-router", + "ibc-core-router-types", + "ibc-primitives", + "serde", + "serde_json", +] + [[package]] name = "ibc-primitives" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38bd2a32f35117d4d9165a3c68c64ccd87ad56dd#38bd2a32f35117d4d9165a3c68c64ccd87ad56dd" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" dependencies = [ "borsh", "derive_more", @@ -1659,7 +1730,7 @@ source = "git+https://github.com/heliaxdev/indexmap?tag=2.2.4-heliax-1#b5b5b547b dependencies = [ "borsh", "equivalent", - "hashbrown", + "hashbrown 0.14.3", "serde", ] @@ -1670,7 +1741,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.14.3", ] [[package]] @@ -1927,6 +1998,12 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "multimap" version = "0.8.3" @@ -2049,8 +2126,10 @@ version = "0.46.1" dependencies = [ "borsh", "data-encoding", + "dur", "ibc", "ibc-derive", + "ibc-middleware-packet-forward", "ics23", "konst", "masp_primitives", @@ -2386,6 +2465,16 @@ dependencies = [ "sha2 0.9.9", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nonempty" version = "0.7.0" @@ -2860,6 +2949,26 @@ dependencies = [ "prost 0.13.2", ] +[[package]] +name = "ptr_meta" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "quote" version = "1.0.36" @@ -3005,6 +3114,15 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +[[package]] +name = "rend" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" +dependencies = [ + "bytecheck", +] + [[package]] name = "rfc6979" version = "0.4.0" @@ -3024,6 +3142,35 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "rkyv" +version = "0.7.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b" +dependencies = [ + "bitvec", + "bytecheck", + "bytes", + "hashbrown 0.12.3", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.7.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "rlp" version = "0.5.2" @@ -3046,6 +3193,22 @@ dependencies = [ "svgbobdoc", ] +[[package]] +name = "rust_decimal" +version = "1.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b082d80e3e3cc52b2ed634388d436fe1f4de6af5786cc2de9ba9737527bdf555" +dependencies = [ + "arrayvec", + "borsh", + "bytes", + "num-traits 0.2.17", + "rand", + "rkyv", + "serde", + "serde_json", +] + [[package]] name = "rustc-hex" version = "2.1.0" @@ -3134,6 +3297,12 @@ dependencies = [ "syn 2.0.65", ] +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + [[package]] name = "sec1" version = "0.7.3" @@ -3218,11 +3387,12 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -3298,6 +3468,12 @@ dependencies = [ "rand_core", ] +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "slab" version = "0.4.9" @@ -3898,6 +4074,12 @@ dependencies = [ "serde", ] +[[package]] +name = "uuid" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" + [[package]] name = "version_check" version = "0.9.4" From 6a67ca6f25f16e3c25ec5c8aeb312ebf611f6448 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Fri, 29 Nov 2024 14:20:51 +0000 Subject: [PATCH 02/22] Increase the visibility of some IBC code Co-authored-by: Jacob Turner --- crates/ibc/src/context/token_transfer.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/ibc/src/context/token_transfer.rs b/crates/ibc/src/context/token_transfer.rs index da3bedc41c..fecc8d4d2d 100644 --- a/crates/ibc/src/context/token_transfer.rs +++ b/crates/ibc/src/context/token_transfer.rs @@ -25,8 +25,8 @@ pub struct TokenTransferContext where C: IbcCommonContext, { - inner: Rc>, - verifiers: Rc>>, + pub(crate) inner: Rc>, + pub(crate) verifiers: Rc>>, is_shielded: bool, } @@ -47,7 +47,7 @@ where } /// Insert a verifier address whose VP will verify the tx. - fn insert_verifier(&mut self, addr: &Address) { + pub(crate) fn insert_verifier(&mut self, addr: &Address) { self.verifiers.borrow_mut().insert(addr.clone()); } From 6241217210314048953725d92c07d2054dc9eb8a Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Fri, 29 Nov 2024 14:17:14 +0000 Subject: [PATCH 03/22] Implement PFM module Co-authored-by: Jacob Turner --- crates/ibc/src/context/mod.rs | 1 + crates/ibc/src/context/pfm_mod.rs | 529 ++++++++++++++++++++++++++++++ 2 files changed, 530 insertions(+) create mode 100644 crates/ibc/src/context/pfm_mod.rs diff --git a/crates/ibc/src/context/mod.rs b/crates/ibc/src/context/mod.rs index d6e238c6c9..89a82b13e7 100644 --- a/crates/ibc/src/context/mod.rs +++ b/crates/ibc/src/context/mod.rs @@ -5,6 +5,7 @@ pub mod common; pub mod execution; pub mod nft_transfer; pub mod nft_transfer_mod; +pub mod pfm_mod; pub mod router; pub mod storage; pub mod token_transfer; diff --git a/crates/ibc/src/context/pfm_mod.rs b/crates/ibc/src/context/pfm_mod.rs new file mode 100644 index 0000000000..59ded9263b --- /dev/null +++ b/crates/ibc/src/context/pfm_mod.rs @@ -0,0 +1,529 @@ +//! Implementation of Packet Forward Middleware on top of the ICS-20 +//! [`TransferModule`]. + +use std::cell::RefCell; +use std::collections::BTreeSet; +use std::fmt::{Debug, Formatter}; +use std::marker::PhantomData; +use std::rc::Rc; + +use ibc::apps::transfer::context::TokenTransferExecutionContext; +use ibc::apps::transfer::handler::{ + refund_packet_token_execute, send_transfer_execute, +}; +use ibc::apps::transfer::types::msgs::transfer::MsgTransfer; +use ibc::apps::transfer::types::packet::PacketData; +use ibc::apps::transfer::types::{is_receiver_chain_source, TracePrefix}; +use ibc::core::channel::handler::{ + commit_packet_acknowledgment, emit_packet_acknowledgement_event, +}; +use ibc::core::channel::types::acknowledgement::Acknowledgement; +use ibc::core::channel::types::channel::{Counterparty, Order}; +use ibc::core::channel::types::error::{ChannelError, PacketError}; +use ibc::core::channel::types::packet::Packet; +use ibc::core::channel::types::timeout::TimeoutTimestamp; +use ibc::core::channel::types::Version; +use ibc::core::host::types::identifiers::{ + ChannelId, ConnectionId, PortId, Sequence, +}; +use ibc::core::router::module::Module; +use ibc::core::router::types::module::{ModuleExtras, ModuleId}; +use ibc::primitives::Signer; +use ibc_middleware_packet_forward::{ + InFlightPacket, InFlightPacketKey, PacketForwardMiddleware, PfmContext, +}; +use namada_core::address::{Address, IBC as IBC_ADDRESS, MULTITOKEN}; +use namada_core::storage::{self, KeySeg}; +use namada_state::{StorageRead, StorageWrite}; + +use crate::context::transfer_mod::TransferModule; +use crate::context::IbcContext; +use crate::{ + Error, IbcCommonContext, IbcStorageContext, ModuleWrapper, + TokenTransferContext, +}; + +const MIDDLEWARES_SUBKEY: &str = "middleware"; +const PFM_SUBKEY: &str = "pfm"; + +/// Get the Namada storage key associated to the provided `InFlightPacketKey`. +pub fn get_inflight_packet_key( + inflight_packet_key: &InFlightPacketKey, +) -> storage::Key { + let key: storage::Key = IBC_ADDRESS.to_db_key().into(); + key.with_segment(MIDDLEWARES_SUBKEY.to_string()) + .with_segment(PFM_SUBKEY.to_string()) + .with_segment(inflight_packet_key.port.to_string()) + .with_segment(inflight_packet_key.channel.to_string()) + .with_segment(inflight_packet_key.sequence.to_string()) +} + +/// A wrapper around an IBC transfer module necessary to +/// build execution contexts. This allows us to implement +/// packet forward middleware on this struct. +pub struct PfmTransferModule +where + C: IbcCommonContext + Debug, +{ + /// The main module + pub transfer_module: TransferModule, + #[allow(missing_docs)] + pub _phantom: PhantomData, +} + +impl PfmTransferModule +where + C: IbcCommonContext + Debug, +{ + /// Create a new [`PfmTransferModule`] + pub fn wrap( + ctx: Rc>, + verifiers: Rc>>, + ) -> PacketForwardMiddleware { + PacketForwardMiddleware::next(Self { + transfer_module: TransferModule::new(ctx, verifiers), + _phantom: Default::default(), + }) + } +} + +impl Debug + for PfmTransferModule +{ + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct(stringify!(PfmTransferModule)) + .field("transfer_module", &self.transfer_module) + .finish_non_exhaustive() + } +} + +impl Module for PfmTransferModule +where + C: IbcCommonContext + Debug, +{ + fn on_chan_open_init_validate( + &self, + order: Order, + connection_hops: &[ConnectionId], + port_id: &PortId, + channel_id: &ChannelId, + counterparty: &Counterparty, + version: &Version, + ) -> Result { + self.transfer_module.on_chan_open_init_validate( + order, + connection_hops, + port_id, + channel_id, + counterparty, + version, + ) + } + + fn on_chan_open_init_execute( + &mut self, + order: Order, + connection_hops: &[ConnectionId], + port_id: &PortId, + channel_id: &ChannelId, + counterparty: &Counterparty, + version: &Version, + ) -> Result<(ModuleExtras, Version), ChannelError> { + self.transfer_module.on_chan_open_init_execute( + order, + connection_hops, + port_id, + channel_id, + counterparty, + version, + ) + } + + fn on_chan_open_try_validate( + &self, + order: Order, + connection_hops: &[ConnectionId], + port_id: &PortId, + channel_id: &ChannelId, + counterparty: &Counterparty, + counterparty_version: &Version, + ) -> Result { + self.transfer_module.on_chan_open_try_validate( + order, + connection_hops, + port_id, + channel_id, + counterparty, + counterparty_version, + ) + } + + fn on_chan_open_try_execute( + &mut self, + order: Order, + connection_hops: &[ConnectionId], + port_id: &PortId, + channel_id: &ChannelId, + counterparty: &Counterparty, + counterparty_version: &Version, + ) -> Result<(ModuleExtras, Version), ChannelError> { + self.transfer_module.on_chan_open_try_execute( + order, + connection_hops, + port_id, + channel_id, + counterparty, + counterparty_version, + ) + } + + fn on_chan_open_ack_validate( + &self, + port_id: &PortId, + channel_id: &ChannelId, + counterparty_version: &Version, + ) -> Result<(), ChannelError> { + self.transfer_module.on_chan_open_ack_validate( + port_id, + channel_id, + counterparty_version, + ) + } + + fn on_chan_open_ack_execute( + &mut self, + port_id: &PortId, + channel_id: &ChannelId, + counterparty_version: &Version, + ) -> Result { + self.transfer_module.on_chan_open_ack_execute( + port_id, + channel_id, + counterparty_version, + ) + } + + fn on_chan_open_confirm_validate( + &self, + port_id: &PortId, + channel_id: &ChannelId, + ) -> Result<(), ChannelError> { + self.transfer_module + .on_chan_open_confirm_validate(port_id, channel_id) + } + + fn on_chan_open_confirm_execute( + &mut self, + port_id: &PortId, + channel_id: &ChannelId, + ) -> Result { + self.transfer_module + .on_chan_open_confirm_execute(port_id, channel_id) + } + + fn on_chan_close_init_validate( + &self, + port_id: &PortId, + channel_id: &ChannelId, + ) -> Result<(), ChannelError> { + self.transfer_module + .on_chan_close_init_validate(port_id, channel_id) + } + + fn on_chan_close_init_execute( + &mut self, + port_id: &PortId, + channel_id: &ChannelId, + ) -> Result { + self.transfer_module + .on_chan_close_init_execute(port_id, channel_id) + } + + fn on_chan_close_confirm_validate( + &self, + port_id: &PortId, + channel_id: &ChannelId, + ) -> Result<(), ChannelError> { + self.transfer_module + .on_chan_close_confirm_validate(port_id, channel_id) + } + + fn on_chan_close_confirm_execute( + &mut self, + port_id: &PortId, + channel_id: &ChannelId, + ) -> Result { + self.transfer_module + .on_chan_close_confirm_execute(port_id, channel_id) + } + + fn on_recv_packet_execute( + &mut self, + packet: &Packet, + relayer: &Signer, + ) -> (ModuleExtras, Option) { + self.transfer_module.on_recv_packet_execute(packet, relayer) + } + + fn on_acknowledgement_packet_validate( + &self, + packet: &Packet, + acknowledgement: &Acknowledgement, + relayer: &Signer, + ) -> Result<(), PacketError> { + self.transfer_module.on_acknowledgement_packet_validate( + packet, + acknowledgement, + relayer, + ) + } + + fn on_acknowledgement_packet_execute( + &mut self, + packet: &Packet, + acknowledgement: &Acknowledgement, + relayer: &Signer, + ) -> (ModuleExtras, Result<(), PacketError>) { + self.transfer_module.on_acknowledgement_packet_execute( + packet, + acknowledgement, + relayer, + ) + } + + fn on_timeout_packet_validate( + &self, + packet: &Packet, + relayer: &Signer, + ) -> Result<(), PacketError> { + self.transfer_module + .on_timeout_packet_validate(packet, relayer) + } + + fn on_timeout_packet_execute( + &mut self, + packet: &Packet, + relayer: &Signer, + ) -> (ModuleExtras, Result<(), PacketError>) { + self.transfer_module + .on_timeout_packet_execute(packet, relayer) + } +} + +impl PfmContext for PfmTransferModule +where + C: IbcCommonContext + Debug, + Params: namada_systems::parameters::Read<::Storage>, +{ + type Error = crate::Error; + + fn send_transfer_execute( + &mut self, + msg: MsgTransfer, + ) -> Result { + let seq = self + .transfer_module + .ctx + .inner + .borrow() + .get_next_sequence_send(&msg.port_id_on_a, &msg.chan_id_on_a) + .map_err(|e| Error::Context(Box::new(e)))?; + tracing::debug!(?seq, ?msg, "PFM send_transfer_execute"); + + let mut ctx = IbcContext::::new( + self.transfer_module.ctx.inner.clone(), + ); + let mut token_transfer_ctx = TokenTransferContext::new( + self.transfer_module.ctx.inner.clone(), + Default::default(), + ); + + self.transfer_module.ctx.insert_verifier(&MULTITOKEN); + + send_transfer_execute(&mut ctx, &mut token_transfer_ctx, msg) + .map_err(Error::TokenTransfer)?; + + Ok(seq) + } + + fn receive_refund_execute( + &mut self, + packet: &Packet, + data: PacketData, + ) -> Result<(), Self::Error> { + tracing::debug!(?packet, ?data, "PFM receive_refund_execute"); + let mut token_transfer_ctx = TokenTransferContext::new( + self.transfer_module.ctx.inner.clone(), + self.transfer_module.ctx.verifiers.clone(), + ); + self.transfer_module.ctx.insert_verifier(&MULTITOKEN); + refund_packet_token_execute(&mut token_transfer_ctx, packet, &data) + .map_err(Error::TokenTransfer) + } + + fn send_refund_execute( + &mut self, + msg: &InFlightPacket, + ) -> Result<(), Self::Error> { + tracing::debug!(?msg, "PFM send_refund_execute"); + + let packet_data: PacketData = serde_json::from_slice(&msg.packet_data) + .expect( + "The in-flight packet data should have belonged to an ICS-20 \ + packet", + ); + + let mut token_transfer_ctx = TokenTransferContext::new( + self.transfer_module.ctx.inner.clone(), + self.transfer_module.ctx.verifiers.clone(), + ); + + self.transfer_module.ctx.insert_verifier(&MULTITOKEN); + + if is_receiver_chain_source( + msg.packet_src_port_id.clone(), + msg.packet_src_channel_id.clone(), + &packet_data.token.denom, + ) { + let coin = { + let mut c = packet_data.token; + c.denom.remove_trace_prefix(&TracePrefix::new( + msg.packet_src_port_id.clone(), + msg.packet_src_channel_id.clone(), + )); + c + }; + + token_transfer_ctx + .escrow_coins_execute( + &IBC_ADDRESS, + &msg.refund_port_id, + &msg.refund_channel_id, + &coin, + &String::new().into(), + ) + .map_err(Error::TokenTransfer) + } else { + let coin = { + let mut c = packet_data.token; + c.denom.add_trace_prefix(TracePrefix::new( + msg.refund_port_id.clone(), + msg.refund_channel_id.clone(), + )); + c + }; + + token_transfer_ctx + .burn_coins_execute(&IBC_ADDRESS, &coin, &String::new().into()) + .map_err(Error::TokenTransfer) + } + } + + fn write_ack_and_events( + &mut self, + packet: &Packet, + acknowledgement: &Acknowledgement, + ) -> Result<(), Self::Error> { + tracing::debug!(?packet, ?acknowledgement, "PFM write_ack_and_events"); + let mut ctx = IbcContext::::new( + self.transfer_module.ctx.inner.clone(), + ); + commit_packet_acknowledgment(&mut ctx, packet, acknowledgement) + .map_err(|e| Error::Context(Box::new(e)))?; + emit_packet_acknowledgement_event( + &mut ctx, + packet.clone(), + acknowledgement.clone(), + ) + .map_err(|e| Error::Context(Box::new(e))) + } + + fn override_receiver( + &self, + _channel: &ChannelId, + _original_sender: &Signer, + ) -> Result { + Ok(IBC_ADDRESS.to_string().into()) + } + + #[allow(clippy::arithmetic_side_effects)] + fn timeout_timestamp( + &self, + timeout_duration: dur::Duration, + ) -> Result { + let timestamp = self + .transfer_module + .ctx + .inner + .borrow() + .host_timestamp() + .map_err(|e| Error::Other(e.to_string()))? + + timeout_duration.try_to_std().ok_or_else(|| { + Error::Other(format!( + "Packet timeout duration is too large: {timeout_duration}" + )) + })?; + let ts = timestamp + .map(TimeoutTimestamp::At) + .map_err(|e| Error::Other(e.to_string()))?; + tracing::debug!(timeout_timestamp = ?ts, "PFM timeout_timestamp"); + Ok(ts) + } + + fn store_inflight_packet( + &mut self, + key: InFlightPacketKey, + inflight_packet: InFlightPacket, + ) -> Result<(), Self::Error> { + tracing::debug!(?key, ?inflight_packet, "PFM store_inflight_packet"); + let mut ctx = self.transfer_module.ctx.inner.borrow_mut(); + let key = get_inflight_packet_key(&key); + ctx.storage_mut() + .write(&key, inflight_packet) + .map_err(Error::Storage) + } + + fn retrieve_inflight_packet( + &self, + key: &InFlightPacketKey, + ) -> Result, Self::Error> { + let mut ctx = self.transfer_module.ctx.inner.borrow_mut(); + let key = get_inflight_packet_key(key); + let packet = ctx.storage_mut().read(&key).map_err(Error::Storage); + + tracing::debug!(?key, ?packet, "PFM retrieve_inflight_packet"); + + packet + } + + fn delete_inflight_packet( + &mut self, + key: &InFlightPacketKey, + ) -> Result<(), Self::Error> { + tracing::debug!(?key, "PFM delete_inflight_packet"); + let mut ctx = self.transfer_module.ctx.inner.borrow_mut(); + let key = get_inflight_packet_key(key); + ctx.storage_mut().delete(&key).map_err(Error::Storage) + } +} + +impl ModuleWrapper for PacketForwardMiddleware +where + T: Module + PfmContext, +{ + fn as_module(&self) -> &dyn Module { + self + } + + fn as_module_mut(&mut self) -> &mut dyn Module { + self + } + + fn module_id(&self) -> ModuleId { + ModuleId::new(ibc::apps::transfer::types::MODULE_ID_STR.to_string()) + } + + fn port_id(&self) -> PortId { + PortId::transfer() + } +} From 90c4e7f647bb17706b0c8161895076f2e3c4ef5b Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Fri, 29 Nov 2024 14:28:02 +0000 Subject: [PATCH 04/22] Hook up PFM middleware to ICS-20 transfer module Co-authored-by: Jacob Turner --- crates/benches/native_vps.rs | 15 ++++++++++----- crates/ibc/src/vp/mod.rs | 11 +++++++---- crates/tx_prelude/src/ibc.rs | 8 ++++++-- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/crates/benches/native_vps.rs b/crates/benches/native_vps.rs index c31d1901aa..8479a39d43 100644 --- a/crates/benches/native_vps.rs +++ b/crates/benches/native_vps.rs @@ -24,6 +24,7 @@ use namada_apps_lib::governance::pgf::storage::steward::StewardDetail; use namada_apps_lib::governance::storage::proposal::ProposalType; use namada_apps_lib::governance::storage::vote::ProposalVote; use namada_apps_lib::governance::{InitProposalData, VoteProposalData}; +use namada_apps_lib::ibc::context::pfm_mod::PfmTransferModule; use namada_apps_lib::ibc::core::channel::types::channel::Order; use namada_apps_lib::ibc::core::channel::types::msgs::MsgChannelOpenInit; use namada_apps_lib::ibc::core::channel::types::Version as ChannelVersion; @@ -35,9 +36,7 @@ use namada_apps_lib::ibc::core::host::types::identifiers::{ ClientId, ConnectionId, PortId, }; use namada_apps_lib::ibc::primitives::ToProto; -use namada_apps_lib::ibc::{ - IbcActions, NftTransferModule, TransferModule, COMMITMENT_PREFIX, -}; +use namada_apps_lib::ibc::{IbcActions, NftTransferModule, COMMITMENT_PREFIX}; use namada_apps_lib::masp_primitives::merkle_tree::CommitmentTree; use namada_apps_lib::masp_primitives::transaction::Transaction; use namada_apps_lib::masp_proofs::sapling::SaplingVerificationContextInner; @@ -1725,7 +1724,10 @@ fn ibc_vp_validate_action(c: &mut Criterion) { ); actions.set_validation_params(ibc.validation_params().unwrap()); - let module = TransferModule::new(ctx.clone(), verifiers); + let module = PfmTransferModule::<_, parameters::Store<_>>::wrap( + ctx.clone(), + verifiers, + ); actions.add_transfer_module(module); let module = NftTransferModule::<_, token::Store<()>>::new(ctx); actions.add_transfer_module(module); @@ -1786,7 +1788,10 @@ fn ibc_vp_execute_action(c: &mut Criterion) { ); actions.set_validation_params(ibc.validation_params().unwrap()); - let module = TransferModule::new(ctx.clone(), verifiers); + let module = PfmTransferModule::<_, parameters::Store<_>>::wrap( + ctx.clone(), + verifiers, + ); actions.add_transfer_module(module); let module = NftTransferModule::<_, token::Store<()>>::new(ctx); actions.add_transfer_module(module); diff --git a/crates/ibc/src/vp/mod.rs b/crates/ibc/src/vp/mod.rs index ebff0d9196..bfc0be1e90 100644 --- a/crates/ibc/src/vp/mod.rs +++ b/crates/ibc/src/vp/mod.rs @@ -27,6 +27,7 @@ use namada_vp::native_vp::{Ctx, CtxPreStorageRead, NativeVp, VpEvaluator}; use namada_vp::VpEnv; use thiserror::Error; +use crate::context::pfm_mod::PfmTransferModule; use crate::core::host::types::identifiers::ChainId as IbcChainId; use crate::core::host::types::path::UPGRADED_IBC_STATE; use crate::event::IbcEvent; @@ -36,8 +37,8 @@ use crate::storage::{ }; use crate::trace::calc_hash; use crate::{ - Error as ActionError, IbcActions, NftTransferModule, TransferModule, - ValidationParams, COMMITMENT_PREFIX, + Error as ActionError, IbcActions, NftTransferModule, ValidationParams, + COMMITMENT_PREFIX, }; #[allow(missing_docs)] @@ -246,7 +247,8 @@ where ctx.clone(), verifiers.clone(), ); - let module = TransferModule::new(ctx.clone(), verifiers); + let module = + PfmTransferModule::<_, ParamsPseudo>::wrap(ctx.clone(), verifiers); actions.add_transfer_module(module); let module = NftTransferModule::<_, Token>::new(ctx.clone()); actions.add_transfer_module(module); @@ -301,7 +303,8 @@ where IbcActions::<_, Params, Token>::new(ctx.clone(), verifiers.clone()); actions.set_validation_params(self.validation_params()?); - let module = TransferModule::new(ctx.clone(), verifiers); + let module = + PfmTransferModule::<_, Params>::wrap(ctx.clone(), verifiers); actions.add_transfer_module(module); let module = NftTransferModule::<_, Token>::new(ctx); actions.add_transfer_module(module); diff --git a/crates/tx_prelude/src/ibc.rs b/crates/tx_prelude/src/ibc.rs index 283dc0f723..436a6befc2 100644 --- a/crates/tx_prelude/src/ibc.rs +++ b/crates/tx_prelude/src/ibc.rs @@ -6,6 +6,7 @@ use std::rc::Rc; use namada_core::address::Address; use namada_core::token::Amount; +use namada_ibc::context::pfm_mod::PfmTransferModule; pub use namada_ibc::event::{IbcEvent, IbcEventType}; pub use namada_ibc::storage::{ burn_tokens, client_state_key, is_ibc_key, mint_limit_key, mint_tokens, @@ -19,7 +20,7 @@ pub use namada_ibc::{ }; use namada_tx_env::TxEnv; -use crate::{token, Ctx, Result}; +use crate::{parameters, token, Ctx, Result}; /// IBC actions to handle an IBC message. The `verifiers` inserted into the set /// must be inserted into the tx context with `Ctx::insert_verifier` after tx @@ -30,7 +31,10 @@ pub fn ibc_actions( let ctx = Rc::new(RefCell::new(ctx.clone())); let verifiers = Rc::new(RefCell::new(BTreeSet::
::new())); let mut actions = IbcActions::new(ctx.clone(), verifiers.clone()); - let module = TransferModule::new(ctx.clone(), verifiers); + let module = PfmTransferModule::<_, parameters::Store>::wrap( + ctx.clone(), + verifiers, + ); actions.add_transfer_module(module); let module = NftTransferModule::>::new(ctx); actions.add_transfer_module(module); From c25bafa7b0b72cc2e4db631699beb6cc8588824b Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Fri, 29 Nov 2024 14:28:36 +0000 Subject: [PATCH 05/22] Add PFM e2e tests Co-authored-by: Jacob Turner Co-authored-by: Yuji Ito --- crates/tests/src/e2e/helpers.rs | 72 +- crates/tests/src/e2e/ibc_tests.rs | 1036 ++++++++++++++++++++++++++--- crates/tests/src/e2e/setup.rs | 66 +- 3 files changed, 1032 insertions(+), 142 deletions(-) diff --git a/crates/tests/src/e2e/helpers.rs b/crates/tests/src/e2e/helpers.rs index 5c3a9d25a1..3df93fddc7 100644 --- a/crates/tests/src/e2e/helpers.rs +++ b/crates/tests/src/e2e/helpers.rs @@ -31,8 +31,8 @@ use namada_sdk::wallet::Wallet; use toml::Value; use super::setup::{ - self, run_cosmos_cmd, sleep, NamadaBgCmd, NamadaCmd, Test, ENV_VAR_DEBUG, - ENV_VAR_USE_PREBUILT_BINARIES, + self, run_cosmos_cmd, sleep, NamadaBgCmd, NamadaCmd, Test, TestDir, + ENV_VAR_DEBUG, ENV_VAR_USE_PREBUILT_BINARIES, }; use crate::e2e::setup::{constants, Bin, CosmosChainType, Who, APPS_PACKAGE}; use crate::strings::{LEDGER_STARTED, TX_APPLIED_SUCCESS}; @@ -493,7 +493,11 @@ pub fn epochs_per_year_from_min_duration(min_duration: u64) -> u64 { } /// Make a Hermes config -pub fn make_hermes_config(test_a: &Test, test_b: &Test) -> Result<()> { +pub fn make_hermes_config( + hermes_dir: &TestDir, + test_a: &Test, + test_b: &Test, +) -> Result<()> { let mut config = toml::map::Map::new(); let mut global = toml::map::Map::new(); @@ -533,9 +537,9 @@ pub fn make_hermes_config(test_a: &Test, test_b: &Test) -> Result<()> { let chains = vec![ make_hermes_chain_config(test_a), match CosmosChainType::chain_type(test_b.net.chain_id.as_str()) { - Ok(chain_type) => { - make_hermes_chain_config_for_cosmos(chain_type, test_b) - } + Ok(chain_type) => make_hermes_chain_config_for_cosmos( + hermes_dir, chain_type, test_b, + ), Err(_) => make_hermes_chain_config(test_b), }, ]; @@ -543,16 +547,7 @@ pub fn make_hermes_config(test_a: &Test, test_b: &Test) -> Result<()> { config.insert("chains".to_owned(), Value::Array(chains)); let toml_string = toml::to_string(&Value::Table(config)).unwrap(); - let hermes_dir = test_a.test_dir.as_ref().join("hermes"); - std::fs::create_dir_all(&hermes_dir).unwrap(); - let config_path = hermes_dir.join("config.toml"); - let mut file = File::create(config_path).unwrap(); - file.write_all(toml_string.as_bytes()).map_err(|e| { - eyre!(format!("Writing a Hermes config failed: {}", e,)) - })?; - // One Hermes config.toml is OK, but add one more config.toml to execute - // Hermes from test_b - let hermes_dir = test_b.test_dir.as_ref().join("hermes"); + let hermes_dir = hermes_dir.as_ref().join("hermes"); std::fs::create_dir_all(&hermes_dir).unwrap(); let config_path = hermes_dir.join("config.toml"); let mut file = File::create(config_path).unwrap(); @@ -607,12 +602,14 @@ fn make_hermes_chain_config(test: &Test) -> Value { } fn make_hermes_chain_config_for_cosmos( + hermes_dir: &TestDir, chain_type: CosmosChainType, test: &Test, ) -> Value { let mut table = toml::map::Map::new(); table.insert("mode".to_owned(), Value::String("push".to_owned())); - let url = format!("ws://{}/websocket", setup::constants::COSMOS_RPC); + let offset = chain_type.get_offset(); + let url = format!("ws://127.0.0.1:6416{}/websocket", offset); table.insert("url".to_owned(), Value::String(url)); table.insert("batch_delay".to_owned(), Value::String("500ms".to_owned())); let event_source = Value::Table(table); @@ -623,14 +620,16 @@ fn make_hermes_chain_config_for_cosmos( Value::String(test.net.chain_id.to_string()), ); chain.insert("type".to_owned(), Value::String("CosmosSdk".to_owned())); + chain.insert( "rpc_addr".to_owned(), - Value::String(format!("http://{}", setup::constants::COSMOS_RPC)), + Value::String(format!("http://127.0.0.1:6416{}", offset)), ); chain.insert( "grpc_addr".to_owned(), - Value::String("http://127.0.0.1:9090".to_owned()), + Value::String(format!("http://127.0.0.1:{}", offset + 9090)), ); + chain.insert("event_source".to_owned(), event_source); chain.insert( "account_prefix".to_owned(), @@ -640,7 +639,8 @@ fn make_hermes_chain_config_for_cosmos( "key_name".to_owned(), Value::String(setup::constants::COSMOS_RELAYER.to_string()), ); - let key_dir = test.test_dir.as_ref().join("hermes/keys"); + let hermes_dir: &Path = hermes_dir.as_ref(); + let key_dir = hermes_dir.join("hermes/keys"); chain.insert( "key_store_folder".to_owned(), Value::String(key_dir.to_string_lossy().to_string()), @@ -672,6 +672,28 @@ pub fn update_cosmos_config(test: &Test) -> Result<()> { *timeout_propose = "1s".into(); } } + let offset = CosmosChainType::chain_type(test.net.chain_id.as_str()) + .unwrap() + .get_offset(); + let p2p = values + .get_mut("p2p") + .expect("Test failed") + .as_table_mut() + .expect("Test failed"); + let Some(laddr) = p2p.get_mut("laddr") else { + panic!("Test failed") + }; + *laddr = format!("tcp://0.0.0.0:266{}{}", offset, offset).into(); + let rpc = values + .get_mut("rpc") + .expect("Test failed") + .as_table_mut() + .expect("Test failed"); + let Some(laddr) = rpc.get_mut("laddr") else { + panic!("Test failed") + }; + *laddr = format!("tcp://0.0.0.0:6416{offset}").into(); + let mut file = OpenOptions::new() .write(true) .truncate(true) @@ -738,6 +760,13 @@ pub fn update_cosmos_config(test: &Test) -> Result<()> { Ok(()) } +pub fn get_cosmos_rpc_address(test: &Test) -> String { + let offset = CosmosChainType::chain_type(test.net.chain_id.as_str()) + .unwrap() + .get_offset(); + format!("127.0.0.1:6416{offset}") +} + pub fn find_cosmos_address( test: &Test, alias: impl AsRef, @@ -759,7 +788,8 @@ pub fn find_cosmos_address( } pub fn get_cosmos_gov_address(test: &Test) -> Result { - let args = ["query", "auth", "module-account", "gov"]; + let rpc = format!("tcp://{}", get_cosmos_rpc_address(test)); + let args = ["query", "auth", "module-account", "gov", "--node", &rpc]; let mut cosmos = run_cosmos_cmd(test, args, Some(40))?; let (_, matched) = cosmos.exp_regex("cosmos[a-z0-9]+")?; diff --git a/crates/tests/src/e2e/ibc_tests.rs b/crates/tests/src/e2e/ibc_tests.rs index e720a72f18..2e63db39f5 100644 --- a/crates/tests/src/e2e/ibc_tests.rs +++ b/crates/tests/src/e2e/ibc_tests.rs @@ -15,6 +15,8 @@ use std::path::{Path, PathBuf}; use color_eyre::eyre::Result; use eyre::eyre; +use ibc_middleware_packet_forward::ForwardMetadata; +use itertools::Either; use namada_apps_lib::client::rpc::query_storage_value_bytes; use namada_apps_lib::config::ethereum_bridge; use namada_apps_lib::config::genesis::templates; @@ -48,7 +50,7 @@ use sha2::{Digest, Sha256}; use crate::e2e::helpers::{ epoch_sleep, epochs_per_year_from_min_duration, find_address, find_cosmos_address, find_payment_address, get_actor_rpc, - get_cosmos_gov_address, get_epoch, + get_cosmos_gov_address, get_cosmos_rpc_address, get_epoch, }; use crate::e2e::ledger_tests::{ start_namada_ledger_node_wait_wasm, write_json_file, @@ -56,8 +58,10 @@ use crate::e2e::ledger_tests::{ use crate::e2e::setup::{ self, apply_use_device, run_cosmos_cmd, run_hermes_cmd, set_ethereum_bridge_mode, setup_cosmos, setup_hermes, sleep, working_dir, - Bin, CosmosChainType, NamadaCmd, Test, Who, ENV_VAR_COSMWASM_CONTRACT_DIR, + Bin, CosmosChainType, NamadaCmd, Test, TestDir, Who, + ENV_VAR_COSMWASM_CONTRACT_DIR, }; +use crate::ibc::primitives::Signer; use crate::strings::TX_APPLIED_SUCCESS; use crate::{run, run_as}; @@ -101,14 +105,15 @@ fn ibc_transfers() -> Result<()> { setup::set_validators(1, genesis, base_dir, |_| 0, vec![]) }; let (ledger, gaia, test, test_gaia) = - run_namada_cosmos(CosmosChainType::Gaia, update_genesis)?; + run_namada_cosmos(CosmosChainType::Gaia(None), update_genesis)?; let _bg_ledger = ledger.background(); let _bg_gaia = gaia.background(); - setup_hermes(&test, &test_gaia)?; + let hermes_dir = setup_hermes(&test, &test_gaia)?; let port_id_namada = FT_PORT_ID.parse().unwrap(); let port_id_gaia = FT_PORT_ID.parse().unwrap(); let (channel_id_namada, channel_id_gaia) = create_channel_with_hermes( + &hermes_dir, &test, &test_gaia, &port_id_namada, @@ -116,7 +121,7 @@ fn ibc_transfers() -> Result<()> { )?; // Start relaying - let hermes = run_hermes(&test)?; + let hermes = run_hermes(&hermes_dir)?; let bg_hermes = hermes.background(); // 1. Transparent transfers @@ -137,7 +142,12 @@ fn ibc_transfers() -> Result<()> { None, false, )?; - wait_for_packet_relay(&port_id_namada, &channel_id_namada, &test)?; + wait_for_packet_relay( + &hermes_dir, + &port_id_namada, + &channel_id_namada, + &test, + )?; check_balance(&test, ALBERT, APFEL, 999_998)?; let token_addr = find_address(&test, APFEL)?; @@ -163,7 +173,7 @@ fn ibc_transfers() -> Result<()> { None, None, )?; - wait_for_packet_relay(&port_id_gaia, &channel_id_gaia, &test)?; + wait_for_packet_relay(&hermes_dir, &port_id_gaia, &channel_id_gaia, &test)?; // Check the balances check_balance(&test, ALBERT, APFEL, 999_999)?; @@ -186,7 +196,7 @@ fn ibc_transfers() -> Result<()> { None, None, )?; - wait_for_packet_relay(&port_id_gaia, &channel_id_gaia, &test)?; + wait_for_packet_relay(&hermes_dir, &port_id_gaia, &channel_id_gaia, &test)?; // Check the token on Namada let ibc_denom_on_namada = @@ -209,7 +219,12 @@ fn ibc_transfers() -> Result<()> { None, false, )?; - wait_for_packet_relay(&port_id_namada, &channel_id_namada, &test)?; + wait_for_packet_relay( + &hermes_dir, + &port_id_namada, + &channel_id_namada, + &test, + )?; // Check the balances check_balance(&test, ALBERT, &ibc_denom_on_namada, 100)?; @@ -244,10 +259,15 @@ fn ibc_transfers() -> Result<()> { 100, &port_id_gaia, &channel_id_gaia, - Some(shielding_data_path), + Some(Either::Left(shielding_data_path)), None, )?; - wait_for_packet_relay(&port_id_gaia, &channel_id_gaia, &test_gaia)?; + wait_for_packet_relay( + &hermes_dir, + &port_id_gaia, + &channel_id_gaia, + &test_gaia, + )?; // Check the token on Namada check_shielded_balance(&test, AA_VIEWING_KEY, &ibc_denom_on_namada, 100)?; check_cosmos_balance(&test_gaia, COSMOS_USER, COSMOS_COIN, 800)?; @@ -281,7 +301,12 @@ fn ibc_transfers() -> Result<()> { None, true, )?; - wait_for_packet_relay(&port_id_namada, &channel_id_namada, &test)?; + wait_for_packet_relay( + &hermes_dir, + &port_id_namada, + &channel_id_namada, + &test, + )?; check_shielded_balance(&test, AB_VIEWING_KEY, &ibc_denom_on_namada, 40)?; check_cosmos_balance(&test_gaia, COSMOS_USER, COSMOS_COIN, 810)?; @@ -305,10 +330,10 @@ fn ibc_transfers() -> Result<()> { 1_000_000, &port_id_gaia, &channel_id_gaia, - Some(memo_path), + Some(Either::Left(memo_path)), None, )?; - wait_for_packet_relay(&port_id_gaia, &channel_id_gaia, &test)?; + wait_for_packet_relay(&hermes_dir, &port_id_gaia, &channel_id_gaia, &test)?; // Check the token on Namada check_shielded_balance(&test, AA_VIEWING_KEY, APFEL, 1)?; @@ -330,7 +355,12 @@ fn ibc_transfers() -> Result<()> { None, false, )?; - wait_for_packet_relay(&port_id_namada, &channel_id_namada, &test)?; + wait_for_packet_relay( + &hermes_dir, + &port_id_namada, + &channel_id_namada, + &test, + )?; // The balance should not be changed check_balance(&test, ALBERT, APFEL, 999_999)?; @@ -357,10 +387,15 @@ fn ibc_transfers() -> Result<()> { sleep(10); // Restart relaying - let hermes = run_hermes(&test)?; + let hermes = run_hermes(&hermes_dir)?; let bg_hermes = hermes.background(); - wait_for_packet_relay(&port_id_namada, &channel_id_namada, &test)?; + wait_for_packet_relay( + &hermes_dir, + &port_id_namada, + &channel_id_namada, + &test, + )?; // The balance should not be changed check_balance(&test, ALBERT, &ibc_denom_on_namada, 100)?; @@ -380,7 +415,12 @@ fn ibc_transfers() -> Result<()> { None, true, )?; - wait_for_packet_relay(&port_id_namada, &channel_id_namada, &test)?; + wait_for_packet_relay( + &hermes_dir, + &port_id_namada, + &channel_id_namada, + &test, + )?; // Check the token has been refunded to the refund target check_shielded_balance(&test, AA_VIEWING_KEY, &ibc_denom_on_namada, 40)?; check_balance(&test, IBC_REFUND_TARGET_ALIAS, &ibc_denom_on_namada, 10)?; @@ -409,10 +449,15 @@ fn ibc_transfers() -> Result<()> { sleep(10); // Restart relaying - let hermes = run_hermes(&test)?; + let hermes = run_hermes(&hermes_dir)?; let _bg_hermes = hermes.background(); - wait_for_packet_relay(&port_id_namada, &channel_id_namada, &test)?; + wait_for_packet_relay( + &hermes_dir, + &port_id_namada, + &channel_id_namada, + &test, + )?; // Check the token has been refunded to the refund target check_shielded_balance(&test, AA_VIEWING_KEY, APFEL, 0)?; check_balance(&test, IBC_REFUND_TARGET_ALIAS, APFEL, 1)?; @@ -438,7 +483,12 @@ fn ibc_transfers() -> Result<()> { // MASP VP shall reject it, make it timeout Some(Duration::new(10, 0)), )?; - wait_for_packet_relay(&port_id_namada, &channel_id_namada, &test)?; + wait_for_packet_relay( + &hermes_dir, + &port_id_namada, + &channel_id_namada, + &test, + )?; // Check the balance didn't change check_shielded_balance(&test, AA_VIEWING_KEY, &ibc_denom_on_namada, 40)?; check_cosmos_balance(&test_gaia, COSMOS_USER, COSMOS_COIN, 810)?; @@ -462,11 +512,16 @@ fn ibc_transfers() -> Result<()> { 101, &port_id_gaia, &channel_id_gaia, - Some(shielding_data_path), + Some(Either::Left(shielding_data_path)), // MASP VP shall reject it, make it timeout Some(Duration::new(10, 0)), )?; - wait_for_packet_relay(&port_id_gaia, &channel_id_gaia, &test_gaia)?; + wait_for_packet_relay( + &hermes_dir, + &port_id_gaia, + &channel_id_gaia, + &test_gaia, + )?; // Check the balances didn't change check_shielded_balance(&test, AA_VIEWING_KEY, &ibc_denom_on_namada, 40)?; check_cosmos_balance(&test_gaia, COSMOS_USER, COSMOS_COIN, 810)?; @@ -493,7 +548,7 @@ fn ibc_nft_transfers() -> Result<()> { let _bg_ledger = ledger.background(); let _bg_wasmd = cosmwasm.background(); - setup_hermes(&test, &test_cosmwasm)?; + let hermes_dir = setup_hermes(&test, &test_cosmwasm)?; let port_id_namada: PortId = NFT_PORT_ID.parse().unwrap(); let (cw721_contract, ics721_contract) = @@ -504,6 +559,7 @@ fn ibc_nft_transfers() -> Result<()> { let port_id_cosmwasm = get_cosmwasm_port_id(&test_cosmwasm, &ics721_contract)?; let (channel_id_namada, channel_id_cosmwasm) = create_channel_with_hermes( + &hermes_dir, &test, &test_cosmwasm, &port_id_namada, @@ -528,7 +584,12 @@ fn ibc_nft_transfers() -> Result<()> { None, None, )?; - clear_packet(&port_id_cosmwasm, &channel_id_cosmwasm, &test_cosmwasm)?; + clear_packet( + &hermes_dir, + &port_id_cosmwasm, + &channel_id_cosmwasm, + &test_cosmwasm, + )?; check_balance(&test, &namada_receiver, &ibc_trace_on_namada, 1)?; // Namada to CosmWasm @@ -546,7 +607,7 @@ fn ibc_nft_transfers() -> Result<()> { None, false, )?; - clear_packet(&port_id_namada, &channel_id_namada, &test)?; + clear_packet(&hermes_dir, &port_id_namada, &channel_id_namada, &test)?; check_balance(&test, &namada_receiver, &ibc_trace_on_namada, 0)?; // 2. Shielding/Unshielding transfers @@ -572,7 +633,12 @@ fn ibc_nft_transfers() -> Result<()> { Some(shielding_data_path), None, )?; - clear_packet(&port_id_cosmwasm, &channel_id_cosmwasm, &test_cosmwasm)?; + clear_packet( + &hermes_dir, + &port_id_cosmwasm, + &channel_id_cosmwasm, + &test_cosmwasm, + )?; check_shielded_balance(&test, AA_VIEWING_KEY, &ibc_trace_on_namada, 1)?; // Shielded transfer on Namada @@ -604,7 +670,7 @@ fn ibc_nft_transfers() -> Result<()> { None, true, )?; - clear_packet(&port_id_namada, &channel_id_namada, &test)?; + clear_packet(&hermes_dir, &port_id_namada, &channel_id_namada, &test)?; check_shielded_balance(&test, AB_VIEWING_KEY, &ibc_trace_on_namada, 0)?; Ok(()) @@ -627,14 +693,15 @@ fn pgf_over_ibc() -> Result<()> { setup::set_validators(1, genesis, base_dir, |_| 0, vec![]) }; let (ledger, gaia, test, test_gaia) = - run_namada_cosmos(CosmosChainType::Gaia, update_genesis)?; + run_namada_cosmos(CosmosChainType::Gaia(None), update_genesis)?; let _bg_ledger = ledger.background(); let _bg_gaia = gaia.background(); - setup_hermes(&test, &test_gaia)?; + let hermes_dir = setup_hermes(&test, &test_gaia)?; let port_id_namada = FT_PORT_ID.parse().unwrap(); let port_id_gaia: PortId = FT_PORT_ID.parse().unwrap(); let (channel_id_namada, channel_id_gaia) = create_channel_with_hermes( + &hermes_dir, &test, &test_gaia, &port_id_namada, @@ -642,7 +709,7 @@ fn pgf_over_ibc() -> Result<()> { )?; // Start relaying - let hermes = run_hermes(&test)?; + let hermes = run_hermes(&hermes_dir)?; let _bg_hermes = hermes.background(); // Transfer to PGF account @@ -688,7 +755,12 @@ fn pgf_over_ibc() -> Result<()> { while epoch < grace_epoch { epoch = epoch_sleep(&test, &rpc, 120)?; } - wait_for_packet_relay(&port_id_namada, &channel_id_namada, &test)?; + wait_for_packet_relay( + &hermes_dir, + &port_id_namada, + &channel_id_namada, + &test, + )?; // Check balances after funding over IBC let token_addr = find_address(&test, NAM)?; @@ -724,7 +796,7 @@ fn fee_payment_with_ibc_token() -> Result<()> { setup::set_validators(1, genesis, base_dir, |_| 0, vec![]) }; let (ledger, gaia, test, test_gaia) = - run_namada_cosmos(CosmosChainType::Gaia, update_genesis)?; + run_namada_cosmos(CosmosChainType::Gaia(None), update_genesis)?; let _bg_ledger = ledger.background(); let _bg_gaia = gaia.background(); @@ -747,10 +819,11 @@ fn fee_payment_with_ibc_token() -> Result<()> { submit_votes(&test)?; // Create an IBC channel while waiting the grace epoch - setup_hermes(&test, &test_gaia)?; + let hermes_dir = setup_hermes(&test, &test_gaia)?; let port_id_gaia = FT_PORT_ID.parse().unwrap(); let port_id_namada = FT_PORT_ID.parse().unwrap(); let (channel_id_namada, channel_id_gaia) = create_channel_with_hermes( + &hermes_dir, &test, &test_gaia, &port_id_namada, @@ -759,7 +832,7 @@ fn fee_payment_with_ibc_token() -> Result<()> { let ibc_token_on_namada = format!("{port_id_namada}/{channel_id_namada}/{COSMOS_COIN}"); // Start relaying - let hermes = run_hermes(&test)?; + let hermes = run_hermes(&hermes_dir)?; let _bg_hermes = hermes.background(); // wait for the grace @@ -781,7 +854,7 @@ fn fee_payment_with_ibc_token() -> Result<()> { None, None, )?; - wait_for_packet_relay(&port_id_gaia, &channel_id_gaia, &test)?; + wait_for_packet_relay(&hermes_dir, &port_id_gaia, &channel_id_gaia, &test)?; // Check the token on Namada check_balance(&test, ALBERT_KEY, &ibc_token_on_namada, 250)?; @@ -830,7 +903,7 @@ fn ibc_token_inflation() -> Result<()> { setup::set_validators(1, genesis, base_dir, |_| 0, vec![]) }; let (ledger, gaia, test, test_gaia) = - run_namada_cosmos(CosmosChainType::Gaia, update_genesis)?; + run_namada_cosmos(CosmosChainType::Gaia(None), update_genesis)?; let _bg_ledger = ledger.background(); let _bg_gaia = gaia.background(); @@ -853,17 +926,18 @@ fn ibc_token_inflation() -> Result<()> { submit_votes(&test)?; // Create an IBC channel while waiting the grace epoch - setup_hermes(&test, &test_gaia)?; + let hermes_dir = setup_hermes(&test, &test_gaia)?; let port_id_namada = FT_PORT_ID.parse().unwrap(); let port_id_gaia = FT_PORT_ID.parse().unwrap(); let (channel_id_namada, channel_id_gaia) = create_channel_with_hermes( + &hermes_dir, &test, &test_gaia, &port_id_namada, &port_id_gaia, )?; // Start relaying - let hermes = run_hermes(&test)?; + let hermes = run_hermes(&hermes_dir)?; let _bg_hermes = hermes.background(); // wait for the grace @@ -893,10 +967,10 @@ fn ibc_token_inflation() -> Result<()> { 1, &port_id_gaia, &channel_id_gaia, - Some(shielding_data_path), + Some(Either::Left(shielding_data_path)), None, )?; - wait_for_packet_relay(&port_id_gaia, &channel_id_gaia, &test)?; + wait_for_packet_relay(&hermes_dir, &port_id_gaia, &channel_id_gaia, &test)?; // wait the next masp epoch to dispense the reward let mut epoch = get_epoch(&test, &rpc).unwrap(); @@ -922,14 +996,16 @@ fn ibc_upgrade_client() -> Result<()> { setup::set_validators(1, genesis, base_dir, |_| 0, vec![]) }; let (ledger, gaia, test, test_gaia) = - run_namada_cosmos(CosmosChainType::Gaia, update_genesis)?; + run_namada_cosmos(CosmosChainType::Gaia(None), update_genesis)?; let _bg_ledger = ledger.background(); let _bg_gaia = gaia.background(); + sleep(5); - setup_hermes(&test, &test_gaia)?; + let hermes_dir = setup_hermes(&test, &test_gaia)?; let port_id_namada = FT_PORT_ID.parse().unwrap(); let port_id_gaia: PortId = FT_PORT_ID.parse().unwrap(); create_channel_with_hermes( + &hermes_dir, &test, &test_gaia, &port_id_namada, @@ -954,7 +1030,7 @@ fn ibc_upgrade_client() -> Result<()> { } // Upgrade the IBC client of Gaia on Namada with Hermes - upgrade_client(&test, test.net.chain_id.to_string(), upgrade_height)?; + upgrade_client(&hermes_dir, test.net.chain_id.to_string(), upgrade_height)?; // Check the upgraded client let upgraded_client_state = @@ -993,14 +1069,15 @@ fn ibc_rate_limit() -> Result<()> { setup::set_validators(1, genesis, base_dir, |_| 0, vec![]) }; let (ledger, gaia, test, test_gaia) = - run_namada_cosmos(CosmosChainType::Gaia, update_genesis)?; + run_namada_cosmos(CosmosChainType::Gaia(None), update_genesis)?; let _bg_ledger = ledger.background(); let _bg_gaia = gaia.background(); - setup_hermes(&test, &test_gaia)?; + let hermes_dir = setup_hermes(&test, &test_gaia)?; let port_id_namada = FT_PORT_ID.parse().unwrap(); let port_id_gaia: PortId = FT_PORT_ID.parse().unwrap(); let (channel_id_namada, channel_id_gaia) = create_channel_with_hermes( + &hermes_dir, &test, &test_gaia, &port_id_namada, @@ -1008,7 +1085,7 @@ fn ibc_rate_limit() -> Result<()> { )?; // Start relaying - let hermes = run_hermes(&test)?; + let hermes = run_hermes(&hermes_dir)?; let _bg_hermes = hermes.background(); // wait for the next epoch @@ -1100,7 +1177,7 @@ fn ibc_rate_limit() -> Result<()> { None, Some(Duration::new(10, 0)), )?; - wait_for_packet_relay(&port_id_gaia, &channel_id_gaia, &test)?; + wait_for_packet_relay(&hermes_dir, &port_id_gaia, &channel_id_gaia, &test)?; // Check if Namada hasn't receive it let ibc_denom = @@ -1113,6 +1190,722 @@ fn ibc_rate_limit() -> Result<()> { Ok(()) } +/// Test the happy flows of ibc pfm +/// +/// Setup: Two instances of Gaia and one +/// Namada instance. +/// +/// 1. Test sending a transfer from first cosmos chain to the second via the PFM +/// module on Namada (henceforth denoted "via PFM") +/// 2. Test sending the above transfer back to first cosmos chain via PFM +/// 3. Send wrapped NAM from first cosmos chain to the second via PFM +/// 4. Reverse the transaction in the step above +#[test] +fn ibc_pfm_happy_flows() -> Result<()> { + let update_genesis = + |mut genesis: templates::All, base_dir: &_| { + genesis.parameters.parameters.epochs_per_year = + epochs_per_year_from_min_duration(1800); + genesis.parameters.ibc_params.default_mint_limit = + Amount::max_signed(); + genesis + .parameters + .ibc_params + .default_per_epoch_throughput_limit = Amount::max_signed(); + setup::set_validators(1, genesis, base_dir, |_| 0, vec![]) + }; + let (ledger, gaia_1, test, test_gaia_1) = + run_namada_cosmos(CosmosChainType::Gaia(Some(1)), update_genesis)?; + + // set up a second cosmos network + let test_gaia_2 = setup_cosmos(CosmosChainType::Gaia(Some(2)))?; + let gaia_2 = run_cosmos(&test_gaia_2, false)?; + sleep(5); + + let _bg_ledger = ledger.background(); + let _bg_gaia_1 = gaia_1.background(); + let _bg_gaia_2 = gaia_2.background(); + let hermes_gaia1_namada = setup_hermes(&test, &test_gaia_1)?; + let hermes_namada_gaia2 = setup_hermes(&test, &test_gaia_2)?; + sleep(5); + // create hermes relayers for connections between both cosmos chains and + // namada + let port_id_namada = FT_PORT_ID.parse().unwrap(); + let port_id_gaia_1 = FT_PORT_ID.parse().unwrap(); + let port_id_gaia_2 = FT_PORT_ID.parse().unwrap(); + + let (channel_id_gaia_1, channel_id_namada_1) = create_channel_with_hermes( + &hermes_gaia1_namada, + &test_gaia_1, + &test, + &port_id_namada, + &port_id_gaia_1, + )?; + let (channel_id_gaia_2, channel_id_namada_2) = create_channel_with_hermes( + &hermes_namada_gaia2, + &test_gaia_2, + &test, + &port_id_namada, + &port_id_gaia_2, + )?; + + // Start relaying + let hermes_1 = run_hermes(&hermes_gaia1_namada)?; + let hermes_2 = run_hermes(&hermes_namada_gaia2)?; + let _bg_hermes_1 = hermes_1.background(); + let _bg_hermes_2 = hermes_2.background(); + + // ------------------- Step 1. ------------------- + + // Bertha is our most trusted intermediary in all things + let namada_receiver = find_address(&test, BERTHA)?.to_string(); + // this will cause the ibc packet to be forwarded to the second + // cosmos chain. + let pfm_memo = packet_forward_memo( + find_cosmos_address(&test_gaia_2, COSMOS_USER)?.into(), + &port_id_namada, + &channel_id_namada_2, + None, + ); + transfer_from_cosmos( + &test_gaia_1, + COSMOS_USER, + &namada_receiver, + "samoleans", + 10, + &port_id_gaia_1, + &channel_id_gaia_1, + Some(Either::Right(pfm_memo)), + None, + )?; + wait_for_packet_relay( + &hermes_gaia1_namada, + &port_id_namada, + &channel_id_namada_1, + &test, + )?; + wait_for_packet_relay( + &hermes_namada_gaia2, + &port_id_gaia_2, + &channel_id_gaia_2, + &test_gaia_2, + )?; + // Check the samoleans have been received on the second cosmos chain + check_cosmos_balance( + &test_gaia_2, + COSMOS_USER, + format!( + "transfer/{channel_id_gaia_2}/transfer/{channel_id_namada_1}/\ + samoleans" + ), + 10, + )?; + + // Check the samoleans have been sent from the first cosmos chain + check_cosmos_balance(&test_gaia_1, COSMOS_USER, "samoleans", 1000 - 10)?; + + // ------------------- Step 2. ------------------- + + // this will cause the ibc packet to be forwarded to the first + // cosmos chain. + let pfm_memo = packet_forward_memo( + find_cosmos_address(&test_gaia_1, COSMOS_USER)?.into(), + &port_id_namada, + &channel_id_namada_1, + None, + ); + transfer_from_cosmos( + &test_gaia_2, + COSMOS_USER, + &namada_receiver, + format!( + "transfer/{channel_id_gaia_2}/transfer/{channel_id_namada_1}/\ + samoleans" + ), + 10, + &port_id_gaia_1, + &channel_id_gaia_1, + Some(Either::Right(pfm_memo)), + None, + )?; + + wait_for_packet_relay( + &hermes_namada_gaia2, + &port_id_namada, + &channel_id_namada_2, + &test, + )?; + wait_for_packet_relay( + &hermes_gaia1_namada, + &port_id_gaia_1, + &channel_id_gaia_1, + &test_gaia_1, + )?; + + // Check the samoleans have been received on the fist cosmos chain + check_cosmos_balance(&test_gaia_1, COSMOS_USER, "samoleans", 1000)?; + + // ------------------- Step 3. ------------------- + let nam_addr = find_address(&test, NAM)?; + // we first send some NAM to the first cosmos chain. + let gaia_receiver = find_cosmos_address(&test_gaia_1, COSMOS_USER)?; + transfer( + &test, + BERTHA, + gaia_receiver, + NAM, + 20, + Some(BERTHA_KEY), + &port_id_namada, + &channel_id_namada_1, + None, + None, + None, + false, + )?; + + wait_for_packet_relay( + &hermes_gaia1_namada, + &port_id_gaia_1, + &channel_id_gaia_1, + &test_gaia_1, + )?; + + // Check the NAM have been sent to the first cosmos chain + check_cosmos_balance( + &test_gaia_1, + COSMOS_USER, + format!("transfer/{channel_id_gaia_1}/{nam_addr}"), + 20_000_000, + )?; + + // this will cause the ibc packet to be forwarded to the second + // cosmos chain. + let pfm_memo = packet_forward_memo( + find_cosmos_address(&test_gaia_2, COSMOS_USER)?.into(), + &port_id_namada, + &channel_id_namada_2, + None, + ); + + transfer_from_cosmos( + &test_gaia_1, + COSMOS_USER, + &namada_receiver, + format!("transfer/{channel_id_gaia_1}/{nam_addr}"), + 10_000_000, + &port_id_gaia_1, + &channel_id_gaia_1, + Some(Either::Right(pfm_memo)), + None, + )?; + wait_for_packet_relay( + &hermes_gaia1_namada, + &port_id_namada, + &channel_id_namada_1, + &test, + )?; + wait_for_packet_relay( + &hermes_namada_gaia2, + &port_id_gaia_2, + &channel_id_gaia_2, + &test_gaia_2, + )?; + // Check the NAM have been received on the second cosmos chain + check_cosmos_balance( + &test_gaia_2, + COSMOS_USER, + format!("transfer/{channel_id_gaia_2}/{nam_addr}"), + 10_000_000, + )?; + + // Check the NAM have been sent from the first cosmos chain + check_cosmos_balance( + &test_gaia_1, + COSMOS_USER, + format!("transfer/{channel_id_gaia_1}/{nam_addr}"), + 20_000_000 - 10_000_000, + )?; + + // ------------------- Step 4. ------------------- + + // this will cause the ibc packet to be forwarded to the first + // cosmos chain. + let pfm_memo = packet_forward_memo( + find_cosmos_address(&test_gaia_1, COSMOS_USER)?.into(), + &port_id_namada, + &channel_id_namada_1, + None, + ); + transfer_from_cosmos( + &test_gaia_2, + COSMOS_USER, + &namada_receiver, + format!("transfer/{channel_id_gaia_2}/{nam_addr}"), + 10_000_000, + &port_id_gaia_1, + &channel_id_gaia_1, + Some(Either::Right(pfm_memo)), + None, + )?; + + wait_for_packet_relay( + &hermes_namada_gaia2, + &port_id_namada, + &channel_id_namada_2, + &test, + )?; + wait_for_packet_relay( + &hermes_gaia1_namada, + &port_id_gaia_1, + &channel_id_gaia_1, + &test_gaia_1, + )?; + + // Check the NAM have been received on the first cosmos chain + check_cosmos_balance( + &test_gaia_1, + COSMOS_USER, + format!("transfer/{channel_id_gaia_1}/{nam_addr}"), + 20_000_000, + )?; + + Ok(()) +} +/// Test the flows of ibc pfm where the packet cannot be +/// completed and refunds must be issued. +/// +/// Setup: Two instances of Gaia and one +/// Namada instance. +/// +/// 1. Test sending a transfer from first cosmos chain to the second via the PFM +/// module on Namada (henceforth denoted "via PFM"), failing on the second +/// cosmos chain due to an error. +/// 2. Same as above except that the failure occurs due to a time-out on the +/// second cosmos chain. +/// 3. Same as the first except that wrapped NAM is sent from the first cosmos +/// chain +/// 4. Same as above except that the failure occurs due to a time-out on the +/// second cosmos chain. +/// 5. Test sending assets from the second cosmos network to the first and then +/// failing to send it back to the second due to an error +/// 6. Same as above except that the failure occurs due to a time-out on the +/// second cosmos chain. +#[test] +fn ibc_pfm_unhappy_flows() -> Result<()> { + let update_genesis = + |mut genesis: templates::All, base_dir: &_| { + genesis.parameters.parameters.epochs_per_year = + epochs_per_year_from_min_duration(1800); + genesis.parameters.ibc_params.default_mint_limit = + Amount::max_signed(); + genesis + .parameters + .ibc_params + .default_per_epoch_throughput_limit = Amount::max_signed(); + setup::set_validators(1, genesis, base_dir, |_| 0, vec![]) + }; + let (ledger, gaia_1, test, test_gaia_1) = + run_namada_cosmos(CosmosChainType::Gaia(Some(1)), update_genesis)?; + + // set up a second cosmos network + let test_gaia_2 = setup_cosmos(CosmosChainType::Gaia(Some(2)))?; + let gaia_2 = run_cosmos(&test_gaia_2, false)?; + sleep(5); + + let _bg_ledger = ledger.background(); + let _bg_gaia_1 = gaia_1.background(); + let _bg_gaia_2 = gaia_2.background(); + let hermes_gaia1_namada = setup_hermes(&test, &test_gaia_1)?; + let hermes_namada_gaia2 = setup_hermes(&test, &test_gaia_2)?; + sleep(5); + // create hermes relayers for connections between both cosmos chains and + // namada + let port_id_namada = FT_PORT_ID.parse().unwrap(); + let port_id_gaia_1 = FT_PORT_ID.parse().unwrap(); + let port_id_gaia_2 = FT_PORT_ID.parse().unwrap(); + + let (channel_id_gaia_1, channel_id_namada_1) = create_channel_with_hermes( + &hermes_gaia1_namada, + &test_gaia_1, + &test, + &port_id_namada, + &port_id_gaia_1, + )?; + let (channel_id_gaia_2, channel_id_namada_2) = create_channel_with_hermes( + &hermes_namada_gaia2, + &test_gaia_2, + &test, + &port_id_namada, + &port_id_gaia_2, + )?; + + // Start relaying + let hermes_1 = run_hermes(&hermes_gaia1_namada)?; + let hermes_2 = run_hermes(&hermes_namada_gaia2)?; + let _bg_hermes_1 = hermes_1.background(); + let bg_hermes_2 = hermes_2.background(); + + // ------------------- Step 1. ------------------- + + // Bertha is our most trusted intermediary in all things + let namada_receiver = find_address(&test, BERTHA)?.to_string(); + // this will cause the ibc packet to be forwarded to the second + // cosmos chain. + let pfm_memo = packet_forward_memo( + // NB: since the receiver is invalid, the ICS-20 + // transfer will fail, and the first cosmos chain + // will receive an ack error + "Hodor".to_string().into(), + &port_id_namada, + &channel_id_namada_2, + None, + ); + transfer_from_cosmos( + &test_gaia_1, + COSMOS_USER, + &namada_receiver, + "samoleans", + 10, + &port_id_gaia_1, + &channel_id_gaia_1, + Some(Either::Right(pfm_memo)), + None, + )?; + wait_for_packet_relay( + &hermes_gaia1_namada, + &port_id_namada, + &channel_id_namada_1, + &test, + )?; + wait_for_packet_relay( + &hermes_namada_gaia2, + &port_id_gaia_2, + &channel_id_gaia_2, + &test_gaia_2, + )?; + + // Check the samoleans have been refunded on the first chain + check_cosmos_balance(&test_gaia_1, COSMOS_USER, "samoleans", 1000)?; + + // ------------------- Step 2. ------------------- + + let pfm_memo = packet_forward_memo( + find_cosmos_address(&test_gaia_1, COSMOS_USER)?.into(), + &port_id_namada, + &channel_id_namada_2, + Some(Duration::new(1, 0)), + ); + // Stop Hermes for timeout test + let mut hermes_2 = bg_hermes_2.foreground(); + hermes_2.interrupt()?; + + transfer_from_cosmos( + &test_gaia_1, + COSMOS_USER, + &namada_receiver, + "samoleans", + 10, + &port_id_gaia_1, + &channel_id_gaia_1, + Some(Either::Right(pfm_memo)), + None, + )?; + + // wait for the timeout + sleep(10); + + // Restart relaying + let hermes_2 = run_hermes(&hermes_namada_gaia2)?; + let bg_hermes_2 = hermes_2.background(); + + wait_for_packet_relay( + &hermes_gaia1_namada, + &port_id_namada, + &channel_id_namada_1, + &test, + )?; + wait_for_packet_relay( + &hermes_namada_gaia2, + &port_id_gaia_2, + &channel_id_gaia_2, + &test_gaia_2, + )?; + + // Check the samoleans have been refunded on the first chain + check_cosmos_balance(&test_gaia_1, COSMOS_USER, "samoleans", 1000)?; + + // ------------------- Step 3. ------------------- + + let nam_addr = find_address(&test, NAM)?; + // we first send some NAM to the first cosmos chain. + let gaia_receiver = find_cosmos_address(&test_gaia_1, COSMOS_USER)?; + transfer( + &test, + BERTHA, + gaia_receiver, + NAM, + 20, + Some(BERTHA_KEY), + &port_id_namada, + &channel_id_namada_1, + None, + None, + None, + false, + )?; + + wait_for_packet_relay( + &hermes_gaia1_namada, + &port_id_gaia_1, + &channel_id_gaia_1, + &test_gaia_1, + )?; + + // Check the NAM have been sent to the first cosmos chain + check_cosmos_balance( + &test_gaia_1, + COSMOS_USER, + format!("transfer/{channel_id_gaia_1}/{nam_addr}"), + 20_000_000, + )?; + + // this will cause the ibc packet to be forwarded to the second + // cosmos chain. + let pfm_memo = packet_forward_memo( + "Hodor".to_string().into(), + &port_id_namada, + &channel_id_namada_2, + None, + ); + transfer_from_cosmos( + &test_gaia_1, + COSMOS_USER, + &namada_receiver, + format!("transfer/{channel_id_gaia_1}/{nam_addr}"), + 10_000_000, + &port_id_gaia_1, + &channel_id_gaia_1, + Some(Either::Right(pfm_memo)), + None, + )?; + wait_for_packet_relay( + &hermes_gaia1_namada, + &port_id_namada, + &channel_id_namada_1, + &test, + )?; + wait_for_packet_relay( + &hermes_namada_gaia2, + &port_id_gaia_2, + &channel_id_gaia_2, + &test_gaia_2, + )?; + + // Check the NAM have been refunded on the first chain + check_cosmos_balance( + &test_gaia_1, + COSMOS_USER, + format!("transfer/{channel_id_gaia_1}/{nam_addr}"), + 20_000_000, + )?; + + // ------------------- Step 4. ------------------- + + let pfm_memo = packet_forward_memo( + find_cosmos_address(&test_gaia_2, COSMOS_USER)?.into(), + &port_id_namada, + &channel_id_namada_2, + Some(Duration::new(1, 0)), + ); + // Stop Hermes for timeout test + let mut hermes_2 = bg_hermes_2.foreground(); + hermes_2.interrupt()?; + + transfer_from_cosmos( + &test_gaia_1, + COSMOS_USER, + &namada_receiver, + format!("transfer/{channel_id_gaia_1}/{nam_addr}"), + 10_000_000, + &port_id_gaia_1, + &channel_id_gaia_1, + Some(Either::Right(pfm_memo)), + None, + )?; + + // wait for the timeout + sleep(10); + + // Restart relaying + let hermes_2 = run_hermes(&hermes_namada_gaia2)?; + let bg_hermes_2 = hermes_2.background(); + + wait_for_packet_relay( + &hermes_gaia1_namada, + &port_id_namada, + &channel_id_namada_1, + &test, + )?; + wait_for_packet_relay( + &hermes_namada_gaia2, + &port_id_gaia_2, + &channel_id_gaia_2, + &test_gaia_2, + )?; + + // Check the NAM have been refunded on the first chain + check_cosmos_balance( + &test_gaia_1, + COSMOS_USER, + format!("transfer/{channel_id_gaia_1}/{nam_addr}"), + 20_000_000, + )?; + + // ------------------- Step 5. ------------------- + + // we first send some samoleans to the first cosmos chain from the second. + let pfm_memo = packet_forward_memo( + find_cosmos_address(&test_gaia_1, COSMOS_USER)?.into(), + &port_id_namada, + &channel_id_namada_1, + None, + ); + transfer_from_cosmos( + &test_gaia_2, + COSMOS_USER, + &namada_receiver, + "samoleans", + 10, + &port_id_gaia_2, + &channel_id_gaia_2, + Some(Either::Right(pfm_memo)), + None, + )?; + + wait_for_packet_relay( + &hermes_gaia1_namada, + &port_id_gaia_1, + &channel_id_gaia_1, + &test_gaia_1, + )?; + + // Check the non-native samoleans have been sent to the first cosmos chain + check_cosmos_balance( + &test_gaia_1, + COSMOS_USER, + format!( + "transfer/{channel_id_gaia_1}/transfer/{channel_id_namada_2}/\ + samoleans" + ), + 10, + )?; + + // this will cause the ibc packet to be forwarded to the second + // cosmos chain. + let pfm_memo = packet_forward_memo( + "Hodor".to_string().into(), + &port_id_namada, + &channel_id_namada_2, + None, + ); + transfer_from_cosmos( + &test_gaia_1, + COSMOS_USER, + &namada_receiver, + format!( + "transfer/{channel_id_gaia_1}/transfer/{channel_id_namada_2}/\ + samoleans" + ), + 10, + &port_id_gaia_1, + &channel_id_gaia_1, + Some(Either::Right(pfm_memo)), + None, + )?; + wait_for_packet_relay( + &hermes_gaia1_namada, + &port_id_namada, + &channel_id_namada_1, + &test, + )?; + wait_for_packet_relay( + &hermes_namada_gaia2, + &port_id_gaia_2, + &channel_id_gaia_2, + &test_gaia_2, + )?; + + // Check the non-native samoleans have been refunded on the first chain + check_cosmos_balance( + &test_gaia_1, + COSMOS_USER, + format!( + "transfer/{channel_id_gaia_1}/transfer/{channel_id_namada_2}/\ + samoleans" + ), + 10, + )?; + + // ------------------- Step 6. ------------------- + let pfm_memo = packet_forward_memo( + find_cosmos_address(&test_gaia_2, COSMOS_USER)?.into(), + &port_id_namada, + &channel_id_namada_2, + Some(Duration::new(1, 0)), + ); + // Stop Hermes for timeout test + let mut hermes_2 = bg_hermes_2.foreground(); + hermes_2.interrupt()?; + + transfer_from_cosmos( + &test_gaia_1, + COSMOS_USER, + &namada_receiver, + format!( + "transfer/{channel_id_gaia_1}/transfer/{channel_id_namada_2}/\ + samoleans" + ), + 10, + &port_id_gaia_1, + &channel_id_gaia_1, + Some(Either::Right(pfm_memo)), + None, + )?; + + // wait for the timeout + sleep(10); + + // Restart relaying + let hermes_2 = run_hermes(&hermes_namada_gaia2)?; + let _bg_hermes_2 = hermes_2.background(); + + wait_for_packet_relay( + &hermes_gaia1_namada, + &port_id_namada, + &channel_id_namada_1, + &test, + )?; + wait_for_packet_relay( + &hermes_namada_gaia2, + &port_id_gaia_2, + &channel_id_gaia_2, + &test_gaia_2, + )?; + + // Check the non-native samoleans have been refunded on the first chain + check_cosmos_balance( + &test_gaia_1, + COSMOS_USER, + format!( + "transfer/{channel_id_gaia_1}/transfer/{channel_id_namada_2}/\ + samoleans" + ), + 10, + )?; + Ok(()) +} + fn run_namada_cosmos( chain_type: CosmosChainType, mut update_genesis: impl FnMut( @@ -1134,13 +1927,14 @@ fn run_namada_cosmos( // Cosmos let test_cosmos = setup_cosmos(chain_type)?; - let cosmos = run_cosmos(&test_cosmos)?; + let cosmos = run_cosmos(&test_cosmos, true)?; sleep(5); Ok((ledger, cosmos, test, test_cosmos)) } fn create_channel_with_hermes( + hermes_dir: &TestDir, test_a: &Test, test_b: &Test, port_id_a: &PortId, @@ -1170,7 +1964,7 @@ fn create_channel_with_hermes( "--yes", ]; - let mut hermes = run_hermes_cmd(test_a, args, Some(240))?; + let mut hermes = run_hermes_cmd(hermes_dir, args, Some(240))?; let (channel_id_a, channel_id_b) = get_channel_ids_from_hermes_output(&mut hermes)?; hermes.assert_success(); @@ -1192,35 +1986,32 @@ fn get_channel_ids_from_hermes_output( Ok((channel_id_a, channel_id_b)) } -fn run_hermes(test: &Test) -> Result { +fn run_hermes(hermes_dir: &TestDir) -> Result { let args = ["start"]; - let mut hermes = run_hermes_cmd(test, args, Some(40))?; + let mut hermes = run_hermes_cmd(hermes_dir, args, Some(40))?; hermes.exp_string("Hermes has started")?; Ok(hermes) } -fn run_cosmos(test: &Test) -> Result { +fn run_cosmos(test: &Test, kill: bool) -> Result { let chain_type = CosmosChainType::chain_type(test.net.chain_id.as_str())?; let cmd_path = chain_type.command_path(); // cosmos process is sometimes left lingering causing subsequent runs to // fail - std::process::Command::new("pkill") - .args(["-9", cmd_path]) - .output() - .unwrap(); - - let args = [ - "start", - "--pruning", - "nothing", - "--grpc.address", - "0.0.0.0:9090", - ]; + if kill { + std::process::Command::new("pkill") + .args(["-9", cmd_path]) + .output() + .unwrap(); + } + let port_arg = format!("0.0.0.0:{}", 9090 + chain_type.get_offset()); + let args = ["start", "--pruning", "nothing", "--grpc.address", &port_arg]; let cosmos = run_cosmos_cmd(test, args, Some(40))?; Ok(cosmos) } fn wait_for_packet_relay( + hermes_dir: &TestDir, port_id: &PortId, channel_id: &ChannelId, test: &Test, @@ -1239,7 +2030,7 @@ fn wait_for_packet_relay( ]; for _ in 0..10 { sleep(10); - let mut hermes = run_hermes_cmd(test, args, Some(40))?; + let mut hermes = run_hermes_cmd(hermes_dir, args, Some(40))?; // Check no pending packet if hermes .exp_string( @@ -1260,6 +2051,7 @@ fn wait_for_packet_relay( } fn clear_packet( + hermes_dir: &TestDir, port_id: &PortId, channel_id: &ChannelId, test: &Test, @@ -1274,14 +2066,14 @@ fn clear_packet( "--channel", channel_id.as_str(), ]; - let mut hermes = run_hermes_cmd(test, args, Some(40))?; + let mut hermes = run_hermes_cmd(hermes_dir, args, Some(40))?; hermes.assert_success(); Ok(()) } fn upgrade_client( - test: &Test, + hermes_dir: &TestDir, host_chain_id: impl AsRef, upgrade_height: u64, ) -> Result<()> { @@ -1295,7 +2087,7 @@ fn upgrade_client( "--upgrade-height", &upgrade_height.to_string(), ]; - let mut hermes = run_hermes_cmd(test, args, Some(120))?; + let mut hermes = run_hermes_cmd(hermes_dir, args, Some(120))?; hermes.exp_string("upgraded-chain")?; hermes.assert_success(); @@ -1674,7 +2466,7 @@ fn propose_upgrade_client( let proposal_json_path = test_gaia.test_dir.path().join("proposal.json"); write_json_file(proposal_json_path.as_path(), proposal_json); - let rpc = format!("tcp://{COSMOS_RPC}"); + let rpc = format!("tcp://{}", get_cosmos_rpc_address(test_gaia)); let submit_proposal_args = vec![ "tx", "gov", @@ -1744,7 +2536,8 @@ fn propose_gas_token(test: &Test) -> Result { } fn wait_for_pass(test: &Test) -> Result<()> { - let args = ["query", "gov", "proposal", "1"]; + let rpc = format!("tcp://{}", get_cosmos_rpc_address(test)); + let args = ["query", "gov", "proposal", "1", "--node", &rpc]; for _ in 0..10 { sleep(5); let mut gaia = run_cosmos_cmd(test, args, Some(40))?; @@ -1757,7 +2550,7 @@ fn wait_for_pass(test: &Test) -> Result<()> { } fn vote_on_gaia(test: &Test) -> Result<()> { - let rpc = format!("tcp://{COSMOS_RPC}"); + let rpc = format!("tcp://{}", get_cosmos_rpc_address(test)); let args = vec![ "tx", "gov", @@ -1833,13 +2626,16 @@ fn transfer_from_cosmos( amount: u64, port_id: &PortId, channel_id: &ChannelId, - memo_path: Option, + memo: Option>, timeout_sec: Option, ) -> Result<()> { let port_id = port_id.to_string(); let channel_id = channel_id.to_string(); let amount = format!("{}{}", amount, token.as_ref()); - let rpc = format!("tcp://{COSMOS_RPC}"); + let offset = CosmosChainType::chain_type(test.net.chain_id.as_str()) + .unwrap() + .get_offset(); + let rpc = format!("tcp://127.0.0.1:6416{offset}"); // If the receiver is a pyament address we want to mask it to the more // general MASP internal address to improve on privacy let receiver = match PaymentAddress::from_str(receiver.as_ref()) { @@ -1867,13 +2663,16 @@ fn transfer_from_cosmos( "--yes", ]; - let memo = memo_path - .as_ref() - .map(|path| { - std::fs::read_to_string(path).expect("Reading memo file failed") + let is_memo = memo.is_some(); + let memo = memo + .map(|m| match m { + Either::Left(path) => { + std::fs::read_to_string(path).expect("Reading memo file failed") + } + Either::Right(memo) => memo, }) .unwrap_or_default(); - if memo_path.is_some() { + if is_memo { args.push("--memo"); args.push(&memo); } @@ -1914,7 +2713,10 @@ fn check_tx_height(test: &Test, client: &mut NamadaCmd) -> Result { } fn query_height(test: &Test) -> Result { - let rpc = get_actor_rpc(test, Who::Validator(0)); + let rpc = match CosmosChainType::chain_type(test.net.chain_id.as_str()) { + Ok(_) => format!("http://{}", get_cosmos_rpc_address(test)), + Err(_) => get_actor_rpc(test, Who::Validator(0)), + }; let tendermint_url = Url::from_str(&rpc).unwrap(); let client = HttpClient::new(tendermint_url).unwrap(); @@ -1992,14 +2794,11 @@ fn check_cosmos_balance( expected_amount: u64, ) -> Result<()> { let addr = find_cosmos_address(test, owner)?; - let args = [ - "query", - "bank", - "balances", - &addr, - "--node", - &format!("tcp://{COSMOS_RPC}"), - ]; + let offset = CosmosChainType::chain_type(test.net.chain_id.as_str()) + .unwrap() + .get_offset(); + let rpc = format!("tcp://127.0.0.1:6416{offset}"); + let args = ["query", "bank", "balances", &addr, "--node", &rpc]; let mut cosmos = run_cosmos_cmd(test, args, Some(40))?; cosmos.exp_string(&format!("amount: \"{expected_amount}\""))?; let expected_denom = if denom.as_ref().contains('/') { @@ -2098,9 +2897,9 @@ fn initialize_nft_contracts(test: &Test) -> Result<(String, String)> { Ok(dir) => PathBuf::from(dir), Err(_) => working_dir(), }; - let rpc = format!("tcp://{COSMOS_RPC}"); + let rpc = format!("tcp://{}", get_cosmos_rpc_address(test)); let minter_addr = find_cosmos_address(test, COSMOS_USER)?; - + sleep(5); // Store cw721 contract let cw721_wasm_path = contract_dir.join(CW721_WASM).to_string_lossy().to_string(); @@ -2127,7 +2926,7 @@ fn initialize_nft_contracts(test: &Test) -> Result<(String, String)> { ]; let mut cosmos = run_cosmos_cmd(test, args, Some(40))?; cosmos.exp_eof()?; - sleep(1); + sleep(5); // Store ics721 contract let ics721_wasm_path = @@ -2157,10 +2956,6 @@ fn initialize_nft_contracts(test: &Test) -> Result<(String, String)> { cosmos.exp_eof()?; sleep(1); - let args = vec!["query", "wasm", "list-code"]; - let mut cosmos = run_cosmos_cmd(test, args, Some(40))?; - cosmos.assert_success(); - // Instantiate cw721 contract let json = serde_json::json!({ "name": "test_nft", @@ -2229,17 +3024,32 @@ fn initialize_nft_contracts(test: &Test) -> Result<(String, String)> { ]; let mut cosmos = run_cosmos_cmd(test, args, Some(40))?; cosmos.exp_eof()?; + sleep(1); // Check the CW721 contract - let args = vec!["query", "wasm", "list-contract-by-code", "1"]; + let args = vec![ + "query", + "wasm", + "list-contract-by-code", + "1", + "--node", + &rpc, + ]; let mut cosmos = run_cosmos_cmd(test, args, Some(40))?; let (_unread, matched) = cosmos.exp_regex("wasm.*")?; let cw721_contract = matched.trim().to_string(); cosmos.exp_eof()?; // Check the ICS721 contract - let args = vec!["query", "wasm", "list-contract-by-code", "2"]; + let args = vec![ + "query", + "wasm", + "list-contract-by-code", + "2", + "--node", + &rpc, + ]; let mut cosmos = run_cosmos_cmd(test, args, Some(40))?; let (_unread, matched) = cosmos.exp_regex("wasm.*")?; let ics721_contract = matched.trim().to_string(); @@ -2249,8 +3059,10 @@ fn initialize_nft_contracts(test: &Test) -> Result<(String, String)> { } fn get_cosmwasm_port_id(test: &Test, ics721_contract: &str) -> Result { + let rpc = format!("tcp://{}", get_cosmos_rpc_address(test)); // Get the port ID - let args = vec!["query", "wasm", "contract", ics721_contract]; + let args = + vec!["query", "wasm", "contract", ics721_contract, "--node", &rpc]; let mut cosmos = run_cosmos_cmd(test, args, Some(40))?; let (_unread, matched) = cosmos.exp_regex("ibc_port_id: wasm.*")?; let port_id = matched.trim().split(' ').last().expect("invalid output"); @@ -2266,7 +3078,7 @@ fn mint_nft( minter_addr: &str, token_id: &str, ) -> Result<()> { - let rpc = format!("tcp://{COSMOS_RPC}"); + let rpc = format!("tcp://{}", get_cosmos_rpc_address(test)); // Mint an NFT let json = serde_json::json!({ @@ -2319,7 +3131,7 @@ fn nft_transfer_from_cosmos( ) -> Result<()> { let channel_id = channel_id.to_string(); let timeout_height = timeout_height.unwrap_or(100000); - let rpc = format!("tcp://{COSMOS_RPC}"); + let rpc = format!("tcp://{}", get_cosmos_rpc_address(test)); let receiver = match PaymentAddress::from_str(receiver.as_ref()) { Ok(_) => MASP.to_string(), @@ -2382,3 +3194,27 @@ fn nft_transfer_from_cosmos( Ok(()) } + +/// Create a packet forward memo and serialize it +fn packet_forward_memo( + receiver: Signer, + port_id: &PortId, + channel_id: &ChannelId, + timeout: Option, +) -> String { + serde_json::to_string(&ibc_middleware_packet_forward::PacketMetadata { + forward: ForwardMetadata { + receiver, + port: port_id.clone(), + channel: channel_id.clone(), + timeout: timeout.map(|t| { + ibc_middleware_packet_forward::Duration::from_dur( + dur::Duration::from_std(t), + ) + }), + retries: Some(0), + next: None, + }, + }) + .expect("Test failed") +} diff --git a/crates/tests/src/e2e/setup.rs b/crates/tests/src/e2e/setup.rs index d7c9a663e9..d0bdb14f80 100644 --- a/crates/tests/src/e2e/setup.rs +++ b/crates/tests/src/e2e/setup.rs @@ -1239,10 +1239,12 @@ pub fn sleep(seconds: u64) { thread::sleep(time::Duration::from_secs(seconds)); } -pub fn setup_hermes(test_a: &Test, test_b: &Test) -> Result<()> { +pub fn setup_hermes(test_a: &Test, test_b: &Test) -> Result { + let hermes_dir = TestDir::new(); + println!("\n{}", "Setting up Hermes".underline().green(),); - make_hermes_config(test_a, test_b)?; + make_hermes_config(&hermes_dir, test_a, test_b)?; for test in [test_a, test_b] { let chain_id = test.net.chain_id.as_str(); @@ -1255,20 +1257,24 @@ pub fn setup_hermes(test_a: &Test, test_b: &Test) -> Result<()> { let args = [ "keys", "add", + // TODO: this overwrite is required because hermes keys are pulled + // from the namada chain dir... however, ideally we would store the + // `wallet.toml` file under hermes' own dir + "--overwrite", "--chain", chain_id, "--key-file", &key_file_path.to_string_lossy(), ]; - let mut hermes = run_hermes_cmd(test, args, Some(20))?; + let mut hermes = run_hermes_cmd(&hermes_dir, args, Some(20))?; hermes.assert_success(); } - Ok(()) + Ok(hermes_dir) } pub fn run_hermes_cmd( - test: &Test, + hermes_dir: &TestDir, args: I, timeout_sec: Option, ) -> Result @@ -1277,7 +1283,8 @@ where S: AsRef, { let mut run_cmd = Command::new("hermes"); - let hermes_dir = test.test_dir.as_ref().join("hermes"); + let hermes_dir: &Path = hermes_dir.as_ref(); + let hermes_dir = hermes_dir.join("hermes"); run_cmd.current_dir(hermes_dir.clone()); let config_path = hermes_dir.join("config.toml"); run_cmd.args(["--config", &config_path.to_string_lossy()]); @@ -1300,7 +1307,7 @@ where let log_path = { let mut rng = rand::thread_rng(); - let log_dir = test.get_base_dir(Who::NonValidator).join("logs"); + let log_dir = hermes_dir.join("logs"); std::fs::create_dir_all(&log_dir)?; log_dir.join(format!( "{}-hermes-{}.log", @@ -1332,46 +1339,63 @@ where #[derive(Clone, Copy, Debug)] pub enum CosmosChainType { - Gaia, + Gaia(Option), CosmWasm, } impl CosmosChainType { - pub fn chain_id(&self) -> &str { + pub fn chain_id(&self) -> String { match self { - Self::Gaia => constants::GAIA_CHAIN_ID, - Self::CosmWasm => constants::COSMWASM_CHAIN_ID, + Self::Gaia(Some(suffix)) => { + format!("{}{}", constants::GAIA_CHAIN_ID, suffix) + } + Self::Gaia(_) => constants::GAIA_CHAIN_ID.to_string(), + Self::CosmWasm => constants::COSMWASM_CHAIN_ID.to_string(), } } pub fn command_path(&self) -> &str { match self { - Self::Gaia => "gaiad", + Self::Gaia(_) => "gaiad", Self::CosmWasm => "wasmd", } } pub fn chain_type(chain_id: &str) -> Result { - match chain_id { - constants::GAIA_CHAIN_ID => Ok(Self::Gaia), - constants::COSMWASM_CHAIN_ID => Ok(Self::CosmWasm), - _ => Err(eyre!(format!("Unexpected Cosmos chain ID: {chain_id}"))), + if chain_id == constants::COSMWASM_CHAIN_ID { + return Ok(Self::CosmWasm); + } + match chain_id.strip_prefix(constants::GAIA_CHAIN_ID) { + Some("") => Ok(Self::Gaia(None)), + Some(suffix) => { + Ok(Self::Gaia(Some(suffix.parse().map_err(|_| { + eyre!("Unexpected Cosmos chain ID: {chain_id}") + })?))) + } + _ => Err(eyre!("Unexpected Cosmos chain ID: {chain_id}")), } } pub fn account_prefix(&self) -> &str { match self { - Self::Gaia => "cosmos", + Self::Gaia(_) => "cosmos", Self::CosmWasm => "wasm", } } + + pub fn get_offset(&self) -> u64 { + match self { + Self::Gaia(Some(off)) => *off, + _ => 0, + } + } } pub fn setup_cosmos(chain_type: CosmosChainType) -> Result { let working_dir = working_dir(); let test_dir = TestDir::new(); let chain_id = chain_type.chain_id(); - let cosmos_dir = test_dir.as_ref().join(chain_id); + let cosmos_dir = test_dir.as_ref().join(&chain_id); let net = Network { chain_id: ChainId(chain_id.to_string()), }; @@ -1383,7 +1407,7 @@ pub fn setup_cosmos(chain_type: CosmosChainType) -> Result { }; // initialize - let args = ["--chain-id", chain_id, "init", chain_id]; + let args = ["--chain-id", &chain_id, "init", &chain_id]; let mut cosmos = run_cosmos_cmd(&test, args, Some(10))?; cosmos.assert_success(); @@ -1448,7 +1472,7 @@ pub fn setup_cosmos(chain_type: CosmosChainType) -> Result { "--keyring-backend", "test", "--chain-id", - chain_id, + &chain_id, ]; let mut cosmos = run_cosmos_cmd(&test, args, Some(10))?; cosmos.assert_success(); @@ -1580,7 +1604,7 @@ pub mod constants { // Gaia or CosmWasm pub const GAIA_CHAIN_ID: &str = "gaia"; pub const COSMWASM_CHAIN_ID: &str = "cosmwasm"; - pub const COSMOS_RPC: &str = "127.0.0.1:26657"; + pub const COSMOS_RPC: &str = "127.0.0.1:64160"; pub const COSMOS_USER: &str = "user"; pub const COSMOS_RELAYER: &str = "relayer"; pub const COSMOS_VALIDATOR: &str = "validator"; From 8599d48ffc591de9a46c77622d158f59c127ed95 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Fri, 29 Nov 2024 14:29:27 +0000 Subject: [PATCH 06/22] Enable PFM e2e tests in CI Co-authored-by: Jacob Turner --- .github/workflows/scripts/e2e.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/scripts/e2e.json b/.github/workflows/scripts/e2e.json index de3d28724d..c63422bf67 100644 --- a/.github/workflows/scripts/e2e.json +++ b/.github/workflows/scripts/e2e.json @@ -6,6 +6,8 @@ "e2e::ibc_tests::fee_payment_with_ibc_token": 357, "e2e::ibc_tests::ibc_token_inflation": 840, "e2e::ibc_tests::ibc_rate_limit": 485, + "e2e::ibc_tests::ibc_pfm_happy_flows": 485, + "e2e::ibc_tests::ibc_pfm_unhappy_flows": 485, "e2e::ibc_tests::ibc_upgrade_client": 280, "e2e::eth_bridge_tests::test_add_to_bridge_pool": 10, "e2e::ledger_tests::double_signing_gets_slashed": 12, From bbc1cb14cf1804d8c1363e4a9e49d8b7459523e1 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Fri, 29 Nov 2024 14:35:10 +0000 Subject: [PATCH 07/22] Changelog for #4082 --- .changelog/unreleased/features/4082-ibc-pfm.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/unreleased/features/4082-ibc-pfm.md diff --git a/.changelog/unreleased/features/4082-ibc-pfm.md b/.changelog/unreleased/features/4082-ibc-pfm.md new file mode 100644 index 0000000000..5aebd47ffc --- /dev/null +++ b/.changelog/unreleased/features/4082-ibc-pfm.md @@ -0,0 +1,3 @@ +- Implement compatibility with Strangelove's Packet Forward Middleware + in Namada, to allow forwarding ICS-20 packets over multiple chains. + ([\#4082](https://github.com/anoma/namada/pull/4082)) \ No newline at end of file From 93dc887963d7588f8fbadb3f56cd1d1a2464473e Mon Sep 17 00:00:00 2001 From: satan Date: Mon, 2 Dec 2024 09:27:09 +0100 Subject: [PATCH 08/22] Remove receiver validation on pfm ibc packets --- crates/ibc/src/lib.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/crates/ibc/src/lib.rs b/crates/ibc/src/lib.rs index bd5aafc814..69a064dcb6 100644 --- a/crates/ibc/src/lib.rs +++ b/crates/ibc/src/lib.rs @@ -80,6 +80,7 @@ use ibc::core::host::types::identifiers::{ChannelId, PortId, Sequence}; use ibc::core::router::types::error::RouterError; use ibc::primitives::proto::Any; pub use ibc::*; +use ibc_middleware_packet_forward::PacketMetadata; use masp_primitives::transaction::Transaction as MaspTransaction; pub use msg::*; use namada_core::address::{self, Address}; @@ -793,6 +794,10 @@ where } } +fn is_packet_forward(data: &PacketData) -> bool { + serde_json::from_str::(data.memo.as_ref()).is_ok() +} + // Extract the involved namada address from the packet (either sender or // receiver) to trigger its vp. Returns None if an address could not be found fn get_envelope_verifier( @@ -802,9 +807,14 @@ fn get_envelope_verifier( MsgEnvelope::Packet(PacketMsg::Recv(msg)) => { match msg.packet.port_id_on_b.as_str() { FT_PORT_ID_STR => { - serde_json::from_slice::(&msg.packet.data) - .ok() - .map(|packet_data| packet_data.receiver) + let packet_data = + serde_json::from_slice::(&msg.packet.data) + .ok()?; + if is_packet_forward(&packet_data) { + None + } else { + Some(packet_data.receiver) + } } NFT_PORT_ID_STR => { serde_json::from_slice::(&msg.packet.data) From ba8dc8dbe160dc249d56c1be55ec572b2b1cabbb Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Mon, 2 Dec 2024 14:20:09 +0100 Subject: [PATCH 09/22] Add function to build transfer middlewares stack --- crates/benches/native_vps.rs | 6 ++-- crates/ibc/src/context/middlewares.rs | 33 ++++++++++++++++++++ crates/ibc/src/context/mod.rs | 1 + crates/ibc/src/context/pfm_mod.rs | 44 +++------------------------ crates/ibc/src/storage.rs | 21 +++++++++++++ crates/ibc/src/vp/mod.rs | 10 +++--- crates/tx_prelude/src/ibc.rs | 4 +-- 7 files changed, 71 insertions(+), 48 deletions(-) create mode 100644 crates/ibc/src/context/middlewares.rs diff --git a/crates/benches/native_vps.rs b/crates/benches/native_vps.rs index 8479a39d43..9caa909e1c 100644 --- a/crates/benches/native_vps.rs +++ b/crates/benches/native_vps.rs @@ -24,7 +24,7 @@ use namada_apps_lib::governance::pgf::storage::steward::StewardDetail; use namada_apps_lib::governance::storage::proposal::ProposalType; use namada_apps_lib::governance::storage::vote::ProposalVote; use namada_apps_lib::governance::{InitProposalData, VoteProposalData}; -use namada_apps_lib::ibc::context::pfm_mod::PfmTransferModule; +use namada_apps_lib::ibc::context::middlewares::create_transfer_middlewares; use namada_apps_lib::ibc::core::channel::types::channel::Order; use namada_apps_lib::ibc::core::channel::types::msgs::MsgChannelOpenInit; use namada_apps_lib::ibc::core::channel::types::Version as ChannelVersion; @@ -1724,7 +1724,7 @@ fn ibc_vp_validate_action(c: &mut Criterion) { ); actions.set_validation_params(ibc.validation_params().unwrap()); - let module = PfmTransferModule::<_, parameters::Store<_>>::wrap( + let module = create_transfer_middlewares::<_, parameters::Store<_>>( ctx.clone(), verifiers, ); @@ -1788,7 +1788,7 @@ fn ibc_vp_execute_action(c: &mut Criterion) { ); actions.set_validation_params(ibc.validation_params().unwrap()); - let module = PfmTransferModule::<_, parameters::Store<_>>::wrap( + let module = create_transfer_middlewares::<_, parameters::Store<_>>( ctx.clone(), verifiers, ); diff --git a/crates/ibc/src/context/middlewares.rs b/crates/ibc/src/context/middlewares.rs new file mode 100644 index 0000000000..5c6d2ef2ea --- /dev/null +++ b/crates/ibc/src/context/middlewares.rs @@ -0,0 +1,33 @@ +//! Middleware entry points on Namada. + +use std::cell::RefCell; +use std::collections::BTreeSet; +use std::fmt::Debug; +use std::marker::PhantomData; +use std::rc::Rc; + +use ibc_middleware_packet_forward::PacketForwardMiddleware; +use namada_core::address::Address; + +use crate::context::pfm_mod::PfmTransferModule; +use crate::context::transfer_mod::TransferModule; +use crate::{IbcCommonContext, IbcStorageContext}; + +/// The stack of middlewares of the transfer module. +pub type TransferMiddlewares = + PacketForwardMiddleware>; + +/// Create a new instance of [`TransferMiddlewares`] +pub fn create_transfer_middlewares( + ctx: Rc>, + verifiers: Rc>>, +) -> TransferMiddlewares +where + C: IbcCommonContext + Debug, + Params: namada_systems::parameters::Read<::Storage>, +{ + PacketForwardMiddleware::next(PfmTransferModule { + transfer_module: TransferModule::new(ctx, verifiers), + _phantom: PhantomData, + }) +} diff --git a/crates/ibc/src/context/mod.rs b/crates/ibc/src/context/mod.rs index 89a82b13e7..441f46eeeb 100644 --- a/crates/ibc/src/context/mod.rs +++ b/crates/ibc/src/context/mod.rs @@ -3,6 +3,7 @@ pub mod client; pub mod common; pub mod execution; +pub mod middlewares; pub mod nft_transfer; pub mod nft_transfer_mod; pub mod pfm_mod; diff --git a/crates/ibc/src/context/pfm_mod.rs b/crates/ibc/src/context/pfm_mod.rs index 59ded9263b..d3df7444ad 100644 --- a/crates/ibc/src/context/pfm_mod.rs +++ b/crates/ibc/src/context/pfm_mod.rs @@ -1,11 +1,8 @@ //! Implementation of Packet Forward Middleware on top of the ICS-20 //! [`TransferModule`]. -use std::cell::RefCell; -use std::collections::BTreeSet; use std::fmt::{Debug, Formatter}; use std::marker::PhantomData; -use std::rc::Rc; use ibc::apps::transfer::context::TokenTransferExecutionContext; use ibc::apps::transfer::handler::{ @@ -32,32 +29,17 @@ use ibc::primitives::Signer; use ibc_middleware_packet_forward::{ InFlightPacket, InFlightPacketKey, PacketForwardMiddleware, PfmContext, }; -use namada_core::address::{Address, IBC as IBC_ADDRESS, MULTITOKEN}; -use namada_core::storage::{self, KeySeg}; +use namada_core::address::{IBC as IBC_ADDRESS, MULTITOKEN}; use namada_state::{StorageRead, StorageWrite}; use crate::context::transfer_mod::TransferModule; use crate::context::IbcContext; +use crate::storage::inflight_packet_key; use crate::{ Error, IbcCommonContext, IbcStorageContext, ModuleWrapper, TokenTransferContext, }; -const MIDDLEWARES_SUBKEY: &str = "middleware"; -const PFM_SUBKEY: &str = "pfm"; - -/// Get the Namada storage key associated to the provided `InFlightPacketKey`. -pub fn get_inflight_packet_key( - inflight_packet_key: &InFlightPacketKey, -) -> storage::Key { - let key: storage::Key = IBC_ADDRESS.to_db_key().into(); - key.with_segment(MIDDLEWARES_SUBKEY.to_string()) - .with_segment(PFM_SUBKEY.to_string()) - .with_segment(inflight_packet_key.port.to_string()) - .with_segment(inflight_packet_key.channel.to_string()) - .with_segment(inflight_packet_key.sequence.to_string()) -} - /// A wrapper around an IBC transfer module necessary to /// build execution contexts. This allows us to implement /// packet forward middleware on this struct. @@ -71,22 +53,6 @@ where pub _phantom: PhantomData, } -impl PfmTransferModule -where - C: IbcCommonContext + Debug, -{ - /// Create a new [`PfmTransferModule`] - pub fn wrap( - ctx: Rc>, - verifiers: Rc>>, - ) -> PacketForwardMiddleware { - PacketForwardMiddleware::next(Self { - transfer_module: TransferModule::new(ctx, verifiers), - _phantom: Default::default(), - }) - } -} - impl Debug for PfmTransferModule { @@ -477,7 +443,7 @@ where ) -> Result<(), Self::Error> { tracing::debug!(?key, ?inflight_packet, "PFM store_inflight_packet"); let mut ctx = self.transfer_module.ctx.inner.borrow_mut(); - let key = get_inflight_packet_key(&key); + let key = inflight_packet_key(&key); ctx.storage_mut() .write(&key, inflight_packet) .map_err(Error::Storage) @@ -488,7 +454,7 @@ where key: &InFlightPacketKey, ) -> Result, Self::Error> { let mut ctx = self.transfer_module.ctx.inner.borrow_mut(); - let key = get_inflight_packet_key(key); + let key = inflight_packet_key(key); let packet = ctx.storage_mut().read(&key).map_err(Error::Storage); tracing::debug!(?key, ?packet, "PFM retrieve_inflight_packet"); @@ -502,7 +468,7 @@ where ) -> Result<(), Self::Error> { tracing::debug!(?key, "PFM delete_inflight_packet"); let mut ctx = self.transfer_module.ctx.inner.borrow_mut(); - let key = get_inflight_packet_key(key); + let key = inflight_packet_key(key); ctx.storage_mut().delete(&key).map_err(Error::Storage) } } diff --git a/crates/ibc/src/storage.rs b/crates/ibc/src/storage.rs index 38b0d7e905..37754320ce 100644 --- a/crates/ibc/src/storage.rs +++ b/crates/ibc/src/storage.rs @@ -13,6 +13,7 @@ use ibc::core::host::types::path::{ ReceiptPath, SeqAckPath, SeqRecvPath, SeqSendPath, UpgradeClientStatePath, UpgradeConsensusStatePath, }; +use ibc_middleware_packet_forward::InFlightPacketKey; use namada_core::address::{Address, InternalAddress}; use namada_core::storage::{DbKeySeg, Key, KeySeg}; use namada_core::token::Amount; @@ -647,3 +648,23 @@ pub fn withdraw_key(token: &Address) -> Key { .push(&token.to_string().to_db_key()) .expect("Cannot obtain a storage key") } + +/// Get a middleware key prefix. +pub fn middlewares_prefix() -> Key { + const MIDDLEWARES_SUBKEY: &str = "middleware"; + + let key: Key = namada_core::address::IBC.to_db_key().into(); + key.with_segment(MIDDLEWARES_SUBKEY.to_string()) +} + +/// Get the Namada storage key associated with the provided +/// [`InFlightPacketKey`]. +pub fn inflight_packet_key(inflight_packet_key: &InFlightPacketKey) -> Key { + const PFM_SUBKEY: &str = "pfm"; + + middlewares_prefix() + .with_segment(PFM_SUBKEY.to_string()) + .with_segment(inflight_packet_key.port.to_string()) + .with_segment(inflight_packet_key.channel.to_string()) + .with_segment(inflight_packet_key.sequence.to_string()) +} diff --git a/crates/ibc/src/vp/mod.rs b/crates/ibc/src/vp/mod.rs index bfc0be1e90..410fd75f83 100644 --- a/crates/ibc/src/vp/mod.rs +++ b/crates/ibc/src/vp/mod.rs @@ -27,7 +27,7 @@ use namada_vp::native_vp::{Ctx, CtxPreStorageRead, NativeVp, VpEvaluator}; use namada_vp::VpEnv; use thiserror::Error; -use crate::context::pfm_mod::PfmTransferModule; +use crate::context::middlewares::create_transfer_middlewares; use crate::core::host::types::identifiers::ChainId as IbcChainId; use crate::core::host::types::path::UPGRADED_IBC_STATE; use crate::event::IbcEvent; @@ -247,8 +247,10 @@ where ctx.clone(), verifiers.clone(), ); - let module = - PfmTransferModule::<_, ParamsPseudo>::wrap(ctx.clone(), verifiers); + let module = create_transfer_middlewares::<_, ParamsPseudo>( + ctx.clone(), + verifiers, + ); actions.add_transfer_module(module); let module = NftTransferModule::<_, Token>::new(ctx.clone()); actions.add_transfer_module(module); @@ -304,7 +306,7 @@ where actions.set_validation_params(self.validation_params()?); let module = - PfmTransferModule::<_, Params>::wrap(ctx.clone(), verifiers); + create_transfer_middlewares::<_, Params>(ctx.clone(), verifiers); actions.add_transfer_module(module); let module = NftTransferModule::<_, Token>::new(ctx); actions.add_transfer_module(module); diff --git a/crates/tx_prelude/src/ibc.rs b/crates/tx_prelude/src/ibc.rs index 436a6befc2..25e2b27267 100644 --- a/crates/tx_prelude/src/ibc.rs +++ b/crates/tx_prelude/src/ibc.rs @@ -6,7 +6,7 @@ use std::rc::Rc; use namada_core::address::Address; use namada_core::token::Amount; -use namada_ibc::context::pfm_mod::PfmTransferModule; +use namada_ibc::context::middlewares::create_transfer_middlewares; pub use namada_ibc::event::{IbcEvent, IbcEventType}; pub use namada_ibc::storage::{ burn_tokens, client_state_key, is_ibc_key, mint_limit_key, mint_tokens, @@ -31,7 +31,7 @@ pub fn ibc_actions( let ctx = Rc::new(RefCell::new(ctx.clone())); let verifiers = Rc::new(RefCell::new(BTreeSet::
::new())); let mut actions = IbcActions::new(ctx.clone(), verifiers.clone()); - let module = PfmTransferModule::<_, parameters::Store>::wrap( + let module = create_transfer_middlewares::<_, parameters::Store>( ctx.clone(), verifiers, ); From 5093c246f579d4f55b366aa3e3c8f67776959b5c Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Mon, 2 Dec 2024 14:37:33 +0100 Subject: [PATCH 10/22] Move PFM to middlewares --- crates/ibc/src/context/middlewares.rs | 5 ++++- crates/ibc/src/context/{ => middlewares}/pfm_mod.rs | 0 crates/ibc/src/context/mod.rs | 1 - 3 files changed, 4 insertions(+), 2 deletions(-) rename crates/ibc/src/context/{ => middlewares}/pfm_mod.rs (100%) diff --git a/crates/ibc/src/context/middlewares.rs b/crates/ibc/src/context/middlewares.rs index 5c6d2ef2ea..76455a48f7 100644 --- a/crates/ibc/src/context/middlewares.rs +++ b/crates/ibc/src/context/middlewares.rs @@ -1,5 +1,8 @@ //! Middleware entry points on Namada. +pub mod pfm_mod; +// mod crossroads_mod; + use std::cell::RefCell; use std::collections::BTreeSet; use std::fmt::Debug; @@ -9,7 +12,7 @@ use std::rc::Rc; use ibc_middleware_packet_forward::PacketForwardMiddleware; use namada_core::address::Address; -use crate::context::pfm_mod::PfmTransferModule; +use self::pfm_mod::PfmTransferModule; use crate::context::transfer_mod::TransferModule; use crate::{IbcCommonContext, IbcStorageContext}; diff --git a/crates/ibc/src/context/pfm_mod.rs b/crates/ibc/src/context/middlewares/pfm_mod.rs similarity index 100% rename from crates/ibc/src/context/pfm_mod.rs rename to crates/ibc/src/context/middlewares/pfm_mod.rs diff --git a/crates/ibc/src/context/mod.rs b/crates/ibc/src/context/mod.rs index 441f46eeeb..447ed02fc5 100644 --- a/crates/ibc/src/context/mod.rs +++ b/crates/ibc/src/context/mod.rs @@ -6,7 +6,6 @@ pub mod execution; pub mod middlewares; pub mod nft_transfer; pub mod nft_transfer_mod; -pub mod pfm_mod; pub mod router; pub mod storage; pub mod token_transfer; From f4373f51af190797989cf1b2d9b682db9970cf7a Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Mon, 2 Dec 2024 14:53:26 +0100 Subject: [PATCH 11/22] Move module wrapper impl --- crates/ibc/src/context/middlewares.rs | 27 ++++++++++++++++- crates/ibc/src/context/middlewares/pfm_mod.rs | 30 ++----------------- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/crates/ibc/src/context/middlewares.rs b/crates/ibc/src/context/middlewares.rs index 76455a48f7..26c218c531 100644 --- a/crates/ibc/src/context/middlewares.rs +++ b/crates/ibc/src/context/middlewares.rs @@ -9,7 +9,10 @@ use std::fmt::Debug; use std::marker::PhantomData; use std::rc::Rc; -use ibc_middleware_packet_forward::PacketForwardMiddleware; +use ibc::core::host::types::identifiers::PortId; +use ibc::core::router::module::Module; +use ibc::core::router::types::module::ModuleId; +use ibc_middleware_packet_forward::{PacketForwardMiddleware, PfmContext}; use namada_core::address::Address; use self::pfm_mod::PfmTransferModule; @@ -34,3 +37,25 @@ where _phantom: PhantomData, }) } + +impl crate::ModuleWrapper for TransferMiddlewares +where + C: IbcCommonContext + Debug, + PfmTransferModule: PfmContext, +{ + fn as_module(&self) -> &dyn Module { + self + } + + fn as_module_mut(&mut self) -> &mut dyn Module { + self + } + + fn module_id(&self) -> ModuleId { + ModuleId::new(ibc::apps::transfer::types::MODULE_ID_STR.to_string()) + } + + fn port_id(&self) -> PortId { + PortId::transfer() + } +} diff --git a/crates/ibc/src/context/middlewares/pfm_mod.rs b/crates/ibc/src/context/middlewares/pfm_mod.rs index d3df7444ad..862ec3d085 100644 --- a/crates/ibc/src/context/middlewares/pfm_mod.rs +++ b/crates/ibc/src/context/middlewares/pfm_mod.rs @@ -24,10 +24,10 @@ use ibc::core::host::types::identifiers::{ ChannelId, ConnectionId, PortId, Sequence, }; use ibc::core::router::module::Module; -use ibc::core::router::types::module::{ModuleExtras, ModuleId}; +use ibc::core::router::types::module::ModuleExtras; use ibc::primitives::Signer; use ibc_middleware_packet_forward::{ - InFlightPacket, InFlightPacketKey, PacketForwardMiddleware, PfmContext, + InFlightPacket, InFlightPacketKey, PfmContext, }; use namada_core::address::{IBC as IBC_ADDRESS, MULTITOKEN}; use namada_state::{StorageRead, StorageWrite}; @@ -35,10 +35,7 @@ use namada_state::{StorageRead, StorageWrite}; use crate::context::transfer_mod::TransferModule; use crate::context::IbcContext; use crate::storage::inflight_packet_key; -use crate::{ - Error, IbcCommonContext, IbcStorageContext, ModuleWrapper, - TokenTransferContext, -}; +use crate::{Error, IbcCommonContext, IbcStorageContext, TokenTransferContext}; /// A wrapper around an IBC transfer module necessary to /// build execution contexts. This allows us to implement @@ -472,24 +469,3 @@ where ctx.storage_mut().delete(&key).map_err(Error::Storage) } } - -impl ModuleWrapper for PacketForwardMiddleware -where - T: Module + PfmContext, -{ - fn as_module(&self) -> &dyn Module { - self - } - - fn as_module_mut(&mut self) -> &mut dyn Module { - self - } - - fn module_id(&self) -> ModuleId { - ModuleId::new(ibc::apps::transfer::types::MODULE_ID_STR.to_string()) - } - - fn port_id(&self) -> PortId { - PortId::transfer() - } -} From bbf6014cc0bb32670be0abab30a3bd01b4de088d Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Mon, 2 Dec 2024 16:16:46 +0100 Subject: [PATCH 12/22] Handle receiving PFM packets with invalid receivers --- Cargo.lock | 64 +++++++++---------- Cargo.toml | 8 +-- crates/core/src/address.rs | 13 +++- crates/ibc/src/context/middlewares.rs | 2 +- crates/ibc/src/context/middlewares/pfm_mod.rs | 18 +++++- crates/ibc/src/context/token_transfer.rs | 31 +++++++++ wasm/Cargo.lock | 64 +++++++++---------- wasm_for_tests/Cargo.lock | 60 ++++++++--------- 8 files changed, 157 insertions(+), 103 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fac60b7c5d..078903fa0c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3343,7 +3343,7 @@ dependencies = [ [[package]] name = "ibc" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-apps", "ibc-clients", @@ -3356,7 +3356,7 @@ dependencies = [ [[package]] name = "ibc-app-nft-transfer" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-app-nft-transfer-types", "ibc-core", @@ -3366,7 +3366,7 @@ dependencies = [ [[package]] name = "ibc-app-nft-transfer-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "arbitrary", "base64 0.22.1", @@ -3388,7 +3388,7 @@ dependencies = [ [[package]] name = "ibc-app-transfer" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-app-transfer-types", "ibc-core", @@ -3398,7 +3398,7 @@ dependencies = [ [[package]] name = "ibc-app-transfer-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "arbitrary", "borsh", @@ -3417,7 +3417,7 @@ dependencies = [ [[package]] name = "ibc-apps" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-app-nft-transfer", "ibc-app-transfer", @@ -3426,7 +3426,7 @@ dependencies = [ [[package]] name = "ibc-client-tendermint" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "derive_more", "ibc-client-tendermint-types", @@ -3443,7 +3443,7 @@ dependencies = [ [[package]] name = "ibc-client-tendermint-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "displaydoc", "ibc-core-client-types", @@ -3460,7 +3460,7 @@ dependencies = [ [[package]] name = "ibc-client-wasm-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "base64 0.22.1", "displaydoc", @@ -3474,7 +3474,7 @@ dependencies = [ [[package]] name = "ibc-clients" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-client-tendermint", "ibc-client-wasm-types", @@ -3483,7 +3483,7 @@ dependencies = [ [[package]] name = "ibc-core" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -3499,7 +3499,7 @@ dependencies = [ [[package]] name = "ibc-core-channel" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-core-channel-types", "ibc-core-client", @@ -3514,7 +3514,7 @@ dependencies = [ [[package]] name = "ibc-core-channel-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "arbitrary", "borsh", @@ -3538,7 +3538,7 @@ dependencies = [ [[package]] name = "ibc-core-client" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-core-client-context", "ibc-core-client-types", @@ -3551,7 +3551,7 @@ dependencies = [ [[package]] name = "ibc-core-client-context" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "derive_more", "displaydoc", @@ -3567,7 +3567,7 @@ dependencies = [ [[package]] name = "ibc-core-client-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "arbitrary", "borsh", @@ -3588,7 +3588,7 @@ dependencies = [ [[package]] name = "ibc-core-commitment-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "arbitrary", "borsh", @@ -3608,7 +3608,7 @@ dependencies = [ [[package]] name = "ibc-core-connection" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-client-wasm-types", "ibc-core-client", @@ -3622,7 +3622,7 @@ dependencies = [ [[package]] name = "ibc-core-connection-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "arbitrary", "borsh", @@ -3644,7 +3644,7 @@ dependencies = [ [[package]] name = "ibc-core-handler" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -3659,7 +3659,7 @@ dependencies = [ [[package]] name = "ibc-core-handler-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "arbitrary", "borsh", @@ -3684,7 +3684,7 @@ dependencies = [ [[package]] name = "ibc-core-host" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "derive_more", "displaydoc", @@ -3702,7 +3702,7 @@ dependencies = [ [[package]] name = "ibc-core-host-cosmos" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "derive_more", "displaydoc", @@ -3725,7 +3725,7 @@ dependencies = [ [[package]] name = "ibc-core-host-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "arbitrary", "borsh", @@ -3741,7 +3741,7 @@ dependencies = [ [[package]] name = "ibc-core-router" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "derive_more", "displaydoc", @@ -3755,7 +3755,7 @@ dependencies = [ [[package]] name = "ibc-core-router-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "borsh", "derive_more", @@ -3774,7 +3774,7 @@ dependencies = [ [[package]] name = "ibc-derive" version = "0.8.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "proc-macro2", "quote", @@ -3783,8 +3783,8 @@ dependencies = [ [[package]] name = "ibc-middleware-packet-forward" -version = "0.6.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.6.0#ca824cfbe550c529d30bf27a97026dd0a058cfdf" +version = "0.8.0" +source = "git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.8.0#9c4a410063df8562c726c76009ff08b4e5a1894a" dependencies = [ "borsh", "dur", @@ -3803,7 +3803,7 @@ dependencies = [ [[package]] name = "ibc-primitives" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "arbitrary", "borsh", @@ -3844,7 +3844,7 @@ dependencies = [ [[package]] name = "ibc-query" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "displaydoc", "ibc", @@ -3855,7 +3855,7 @@ dependencies = [ [[package]] name = "ibc-testkit" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "basecoin-store", "derive_more", diff --git a/Cargo.toml b/Cargo.toml index 0510ff1cf5..20cbd032ae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -120,10 +120,10 @@ fs_extra = "1.2.0" futures = "0.3" git2 = { version = "0.18.1", default-features = false } # branch tiago/optional-ack -ibc = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "aa229566e6bb688cc2626dab276c3849abc0c583", features = ["serde"] } -ibc-derive = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "aa229566e6bb688cc2626dab276c3849abc0c583" } -ibc-middleware-packet-forward = { git = "https://github.com/heliaxdev/ibc-middleware", tag = "pfm/v0.6.0", features = ["borsh"] } -ibc-testkit = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "aa229566e6bb688cc2626dab276c3849abc0c583", default-features = false } +ibc = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "38489943c4e75206eaffeeeec6153c039c2499d1", features = ["serde"] } +ibc-derive = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "38489943c4e75206eaffeeeec6153c039c2499d1" } +ibc-middleware-packet-forward = { git = "https://github.com/heliaxdev/ibc-middleware", tag = "pfm/v0.8.0", features = ["borsh"] } +ibc-testkit = { git = "https://github.com/heliaxdev/cosmos-ibc-rs", rev = "38489943c4e75206eaffeeeec6153c039c2499d1", default-features = false } ics23 = "0.12.0" usize-set = { version = "0.10.3", features = ["serialize-borsh", "serialize-serde"] } indexmap = { git = "https://github.com/heliaxdev/indexmap", tag = "2.2.4-heliax-1", features = ["borsh-schema", "serde"] } diff --git a/crates/core/src/address.rs b/crates/core/src/address.rs index 7023b70b4a..0590c695eb 100644 --- a/crates/core/src/address.rs +++ b/crates/core/src/address.rs @@ -393,11 +393,10 @@ impl Debug for Address { } } -// compute an Address from an IBC signer -impl TryFrom for Address { +impl TryFrom<&Signer> for Address { type Error = DecodeError; - fn try_from(signer: Signer) -> Result { + fn try_from(signer: &Signer) -> Result { // The given address should be an address or payment address. When // sending a token from a spending key, it has been already // replaced with the MASP address. @@ -412,6 +411,14 @@ impl TryFrom for Address { } } +impl TryFrom for Address { + type Error = DecodeError; + + fn try_from(signer: Signer) -> Result { + (&signer).try_into() + } +} + /// An established address is generated on-chain #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[derive( diff --git a/crates/ibc/src/context/middlewares.rs b/crates/ibc/src/context/middlewares.rs index 26c218c531..8d65666e63 100644 --- a/crates/ibc/src/context/middlewares.rs +++ b/crates/ibc/src/context/middlewares.rs @@ -32,7 +32,7 @@ where C: IbcCommonContext + Debug, Params: namada_systems::parameters::Read<::Storage>, { - PacketForwardMiddleware::next(PfmTransferModule { + PacketForwardMiddleware::wrap(PfmTransferModule { transfer_module: TransferModule::new(ctx, verifiers), _phantom: PhantomData, }) diff --git a/crates/ibc/src/context/middlewares/pfm_mod.rs b/crates/ibc/src/context/middlewares/pfm_mod.rs index 862ec3d085..70454fbf4a 100644 --- a/crates/ibc/src/context/middlewares/pfm_mod.rs +++ b/crates/ibc/src/context/middlewares/pfm_mod.rs @@ -225,7 +225,23 @@ where packet: &Packet, relayer: &Signer, ) -> (ModuleExtras, Option) { - self.transfer_module.on_recv_packet_execute(packet, relayer) + let Ok(packet_data) = + serde_json::from_slice::(&packet.data) + else { + return self + .transfer_module + .on_recv_packet_execute(packet, relayer); + }; + + if crate::is_packet_forward(&packet_data) { + self.transfer_module.ctx.enable_parse_addr_as_governance(); + let ret = + self.transfer_module.on_recv_packet_execute(packet, relayer); + self.transfer_module.ctx.disable_parse_addr_as_governance(); + ret + } else { + self.transfer_module.on_recv_packet_execute(packet, relayer) + } } fn on_acknowledgement_packet_validate( diff --git a/crates/ibc/src/context/token_transfer.rs b/crates/ibc/src/context/token_transfer.rs index fecc8d4d2d..789d7ca635 100644 --- a/crates/ibc/src/context/token_transfer.rs +++ b/crates/ibc/src/context/token_transfer.rs @@ -12,6 +12,7 @@ use ibc::apps::transfer::types::{Memo, PrefixedCoin, PrefixedDenom}; use ibc::core::channel::types::error::ChannelError; use ibc::core::handler::types::error::ContextError; use ibc::core::host::types::identifiers::{ChannelId, PortId}; +use ibc::core::primitives::Signer; use namada_core::address::{Address, InternalAddress, MASP}; use namada_core::token::Amount; use namada_core::uint::Uint; @@ -28,6 +29,7 @@ where pub(crate) inner: Rc>, pub(crate) verifiers: Rc>>, is_shielded: bool, + parse_addr_as_governance: bool, } impl TokenTransferContext @@ -43,6 +45,7 @@ where inner, verifiers, is_shielded: false, + parse_addr_as_governance: false, } } @@ -51,6 +54,16 @@ where self.verifiers.borrow_mut().insert(addr.clone()); } + /// Enable parsing ibc signers as the governance address + pub fn enable_parse_addr_as_governance(&mut self) { + self.parse_addr_as_governance = true; + } + + /// Disable parsing ibc signers as the governance address + pub fn disable_parse_addr_as_governance(&mut self) { + self.parse_addr_as_governance = false; + } + /// Set to enable a shielded transfer pub fn enable_shielded_transfer(&mut self) { self.is_shielded = true; @@ -179,6 +192,24 @@ where { type AccountId = Address; + fn sender_account_from_signer( + &self, + signer: &Signer, + ) -> Option { + Address::decode(signer.as_ref()).ok() + } + + fn receiver_account_from_signer( + &self, + signer: &Signer, + ) -> Option { + if self.parse_addr_as_governance { + Some(namada_core::address::GOV) + } else { + Address::try_from(signer).ok() + } + } + fn get_port(&self) -> Result { Ok(PortId::transfer()) } diff --git a/wasm/Cargo.lock b/wasm/Cargo.lock index 870d5ee10e..aa7f3327b5 100644 --- a/wasm/Cargo.lock +++ b/wasm/Cargo.lock @@ -2560,7 +2560,7 @@ dependencies = [ [[package]] name = "ibc" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-apps", "ibc-clients", @@ -2573,7 +2573,7 @@ dependencies = [ [[package]] name = "ibc-app-nft-transfer" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-app-nft-transfer-types", "ibc-core", @@ -2583,7 +2583,7 @@ dependencies = [ [[package]] name = "ibc-app-nft-transfer-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "base64 0.22.1", "borsh", @@ -2604,7 +2604,7 @@ dependencies = [ [[package]] name = "ibc-app-transfer" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-app-transfer-types", "ibc-core", @@ -2614,7 +2614,7 @@ dependencies = [ [[package]] name = "ibc-app-transfer-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "borsh", "derive_more", @@ -2632,7 +2632,7 @@ dependencies = [ [[package]] name = "ibc-apps" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-app-nft-transfer", "ibc-app-transfer", @@ -2641,7 +2641,7 @@ dependencies = [ [[package]] name = "ibc-client-tendermint" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "derive_more", "ibc-client-tendermint-types", @@ -2658,7 +2658,7 @@ dependencies = [ [[package]] name = "ibc-client-tendermint-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "displaydoc", "ibc-core-client-types", @@ -2675,7 +2675,7 @@ dependencies = [ [[package]] name = "ibc-client-wasm-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "base64 0.22.1", "displaydoc", @@ -2689,7 +2689,7 @@ dependencies = [ [[package]] name = "ibc-clients" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-client-tendermint", "ibc-client-wasm-types", @@ -2698,7 +2698,7 @@ dependencies = [ [[package]] name = "ibc-core" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -2714,7 +2714,7 @@ dependencies = [ [[package]] name = "ibc-core-channel" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-core-channel-types", "ibc-core-client", @@ -2729,7 +2729,7 @@ dependencies = [ [[package]] name = "ibc-core-channel-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "borsh", "derive_more", @@ -2752,7 +2752,7 @@ dependencies = [ [[package]] name = "ibc-core-client" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-core-client-context", "ibc-core-client-types", @@ -2765,7 +2765,7 @@ dependencies = [ [[package]] name = "ibc-core-client-context" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "derive_more", "displaydoc", @@ -2781,7 +2781,7 @@ dependencies = [ [[package]] name = "ibc-core-client-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "borsh", "derive_more", @@ -2801,7 +2801,7 @@ dependencies = [ [[package]] name = "ibc-core-commitment-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "borsh", "derive_more", @@ -2820,7 +2820,7 @@ dependencies = [ [[package]] name = "ibc-core-connection" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-client-wasm-types", "ibc-core-client", @@ -2834,7 +2834,7 @@ dependencies = [ [[package]] name = "ibc-core-connection-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "borsh", "derive_more", @@ -2855,7 +2855,7 @@ dependencies = [ [[package]] name = "ibc-core-handler" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -2870,7 +2870,7 @@ dependencies = [ [[package]] name = "ibc-core-handler-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "borsh", "derive_more", @@ -2894,7 +2894,7 @@ dependencies = [ [[package]] name = "ibc-core-host" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "derive_more", "displaydoc", @@ -2912,7 +2912,7 @@ dependencies = [ [[package]] name = "ibc-core-host-cosmos" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "derive_more", "displaydoc", @@ -2935,7 +2935,7 @@ dependencies = [ [[package]] name = "ibc-core-host-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "borsh", "derive_more", @@ -2950,7 +2950,7 @@ dependencies = [ [[package]] name = "ibc-core-router" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "derive_more", "displaydoc", @@ -2964,7 +2964,7 @@ dependencies = [ [[package]] name = "ibc-core-router-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "borsh", "derive_more", @@ -2983,7 +2983,7 @@ dependencies = [ [[package]] name = "ibc-derive" version = "0.8.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "proc-macro2", "quote", @@ -2992,8 +2992,8 @@ dependencies = [ [[package]] name = "ibc-middleware-packet-forward" -version = "0.6.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.6.0#ca824cfbe550c529d30bf27a97026dd0a058cfdf" +version = "0.8.0" +source = "git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.8.0#9c4a410063df8562c726c76009ff08b4e5a1894a" dependencies = [ "borsh", "dur", @@ -3012,7 +3012,7 @@ dependencies = [ [[package]] name = "ibc-primitives" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "borsh", "derive_more", @@ -3052,7 +3052,7 @@ dependencies = [ [[package]] name = "ibc-query" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "displaydoc", "ibc", @@ -3063,7 +3063,7 @@ dependencies = [ [[package]] name = "ibc-testkit" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "basecoin-store", "derive_more", diff --git a/wasm_for_tests/Cargo.lock b/wasm_for_tests/Cargo.lock index e20c43470c..a2a29722b8 100644 --- a/wasm_for_tests/Cargo.lock +++ b/wasm_for_tests/Cargo.lock @@ -1152,7 +1152,7 @@ dependencies = [ [[package]] name = "ibc" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-apps", "ibc-clients", @@ -1165,7 +1165,7 @@ dependencies = [ [[package]] name = "ibc-app-nft-transfer" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-app-nft-transfer-types", "ibc-core", @@ -1175,7 +1175,7 @@ dependencies = [ [[package]] name = "ibc-app-nft-transfer-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "base64 0.22.1", "borsh", @@ -1196,7 +1196,7 @@ dependencies = [ [[package]] name = "ibc-app-transfer" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-app-transfer-types", "ibc-core", @@ -1206,7 +1206,7 @@ dependencies = [ [[package]] name = "ibc-app-transfer-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "borsh", "derive_more", @@ -1224,7 +1224,7 @@ dependencies = [ [[package]] name = "ibc-apps" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-app-nft-transfer", "ibc-app-transfer", @@ -1233,7 +1233,7 @@ dependencies = [ [[package]] name = "ibc-client-tendermint" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "derive_more", "ibc-client-tendermint-types", @@ -1250,7 +1250,7 @@ dependencies = [ [[package]] name = "ibc-client-tendermint-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "displaydoc", "ibc-core-client-types", @@ -1267,7 +1267,7 @@ dependencies = [ [[package]] name = "ibc-client-wasm-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "base64 0.22.1", "displaydoc", @@ -1281,7 +1281,7 @@ dependencies = [ [[package]] name = "ibc-clients" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-client-tendermint", "ibc-client-wasm-types", @@ -1290,7 +1290,7 @@ dependencies = [ [[package]] name = "ibc-core" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -1306,7 +1306,7 @@ dependencies = [ [[package]] name = "ibc-core-channel" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-core-channel-types", "ibc-core-client", @@ -1321,7 +1321,7 @@ dependencies = [ [[package]] name = "ibc-core-channel-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "borsh", "derive_more", @@ -1344,7 +1344,7 @@ dependencies = [ [[package]] name = "ibc-core-client" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-core-client-context", "ibc-core-client-types", @@ -1357,7 +1357,7 @@ dependencies = [ [[package]] name = "ibc-core-client-context" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "derive_more", "displaydoc", @@ -1373,7 +1373,7 @@ dependencies = [ [[package]] name = "ibc-core-client-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "borsh", "derive_more", @@ -1393,7 +1393,7 @@ dependencies = [ [[package]] name = "ibc-core-commitment-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "borsh", "derive_more", @@ -1412,7 +1412,7 @@ dependencies = [ [[package]] name = "ibc-core-connection" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-client-wasm-types", "ibc-core-client", @@ -1426,7 +1426,7 @@ dependencies = [ [[package]] name = "ibc-core-connection-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "borsh", "derive_more", @@ -1447,7 +1447,7 @@ dependencies = [ [[package]] name = "ibc-core-handler" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -1462,7 +1462,7 @@ dependencies = [ [[package]] name = "ibc-core-handler-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "borsh", "derive_more", @@ -1486,7 +1486,7 @@ dependencies = [ [[package]] name = "ibc-core-host" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "derive_more", "displaydoc", @@ -1504,7 +1504,7 @@ dependencies = [ [[package]] name = "ibc-core-host-cosmos" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "derive_more", "displaydoc", @@ -1527,7 +1527,7 @@ dependencies = [ [[package]] name = "ibc-core-host-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "borsh", "derive_more", @@ -1542,7 +1542,7 @@ dependencies = [ [[package]] name = "ibc-core-router" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "derive_more", "displaydoc", @@ -1556,7 +1556,7 @@ dependencies = [ [[package]] name = "ibc-core-router-types" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "borsh", "derive_more", @@ -1575,7 +1575,7 @@ dependencies = [ [[package]] name = "ibc-derive" version = "0.8.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "proc-macro2", "quote", @@ -1584,8 +1584,8 @@ dependencies = [ [[package]] name = "ibc-middleware-packet-forward" -version = "0.6.0" -source = "git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.6.0#ca824cfbe550c529d30bf27a97026dd0a058cfdf" +version = "0.8.0" +source = "git+https://github.com/heliaxdev/ibc-middleware?tag=pfm/v0.8.0#9c4a410063df8562c726c76009ff08b4e5a1894a" dependencies = [ "borsh", "dur", @@ -1604,7 +1604,7 @@ dependencies = [ [[package]] name = "ibc-primitives" version = "0.54.0" -source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=aa229566e6bb688cc2626dab276c3849abc0c583#aa229566e6bb688cc2626dab276c3849abc0c583" +source = "git+https://github.com/heliaxdev/cosmos-ibc-rs?rev=38489943c4e75206eaffeeeec6153c039c2499d1#38489943c4e75206eaffeeeec6153c039c2499d1" dependencies = [ "borsh", "derive_more", From d0a242fc92f3f4cf90559649a14237690b6fc213 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Mon, 2 Dec 2024 17:31:53 +0100 Subject: [PATCH 13/22] Changelog for #4134 --- .../unreleased/features/4134-ibc-pfm-with-invalid-addrs.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changelog/unreleased/features/4134-ibc-pfm-with-invalid-addrs.md diff --git a/.changelog/unreleased/features/4134-ibc-pfm-with-invalid-addrs.md b/.changelog/unreleased/features/4134-ibc-pfm-with-invalid-addrs.md new file mode 100644 index 0000000000..ab53b5da5a --- /dev/null +++ b/.changelog/unreleased/features/4134-ibc-pfm-with-invalid-addrs.md @@ -0,0 +1,2 @@ +- Disable validation of IBC ICS-20 receivers, while handling PFM packets. + ([\#4134](https://github.com/anoma/namada/pull/4134)) \ No newline at end of file From ae8bb137449d38431831f4d0276b30198d4828c7 Mon Sep 17 00:00:00 2001 From: yito88 Date: Thu, 2 Jan 2025 23:19:35 +0100 Subject: [PATCH 14/22] WIP: set MaspEpoch --- crates/core/src/masp.rs | 2 +- crates/ibc/src/actions.rs | 1 + crates/ibc/src/context/common.rs | 45 ++++++ crates/ibc/src/context/middlewares.rs | 5 +- crates/ibc/src/context/middlewares/pfm_mod.rs | 16 +- crates/ibc/src/context/transfer_mod.rs | 81 ++++++++-- crates/ibc/src/lib.rs | 148 +++++++++++++++++- crates/ibc/src/msg.rs | 55 +++++-- crates/ibc/src/storage.rs | 24 +++ crates/ibc/src/vp/mod.rs | 16 +- crates/sdk/src/tx.rs | 144 +++++++++++------ 11 files changed, 438 insertions(+), 99 deletions(-) diff --git a/crates/core/src/masp.rs b/crates/core/src/masp.rs index caac4ccde8..40e521c6e7 100644 --- a/crates/core/src/masp.rs +++ b/crates/core/src/masp.rs @@ -104,7 +104,7 @@ impl Display for MaspTxId { Serialize, Deserialize, )] -pub struct MaspEpoch(Epoch); +pub struct MaspEpoch(pub Epoch); impl Display for MaspEpoch { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { diff --git a/crates/ibc/src/actions.rs b/crates/ibc/src/actions.rs index a266c69370..9128a05ca7 100644 --- a/crates/ibc/src/actions.rs +++ b/crates/ibc/src/actions.rs @@ -244,6 +244,7 @@ where let data = MsgTransfer:: { message, transfer: None, + refund_masp_tx: None, } .serialize_to_vec(); diff --git a/crates/ibc/src/context/common.rs b/crates/ibc/src/context/common.rs index 35233fd70e..38558cad4e 100644 --- a/crates/ibc/src/context/common.rs +++ b/crates/ibc/src/context/common.rs @@ -19,8 +19,10 @@ use ibc::core::host::types::identifiers::{ }; use ibc::primitives::proto::{Any, Protobuf}; use ibc::primitives::Timestamp; +use masp_primitives::transaction::Transaction as MaspTransaction; use namada_core::address::Address; use namada_core::chain::BlockHeight; +use namada_core::masp::MaspEpoch; use namada_core::storage::Key; use namada_core::tendermint::Time as TmTime; use namada_core::token::Amount; @@ -759,6 +761,49 @@ pub trait IbcCommonContext: IbcStorageContext { .write(&key, amount) .map_err(ContextError::from) } + + /// Read the MASP shielding transaction for the shielded refund + fn refund_masp_tx( + &self, + port_id: &PortId, + channel_id: &ChannelId, + sequence: Sequence, + epoch: MaspEpoch, + ) -> Result> { + let key = + storage::refund_masp_tx_key(port_id, channel_id, sequence, epoch); + self.storage().read(&key).map_err(ContextError::from) + } + + /// Write the MASP shielding transaction for the shielded refund + fn store_refund_masp_tx( + &mut self, + port_id: &PortId, + channel_id: &ChannelId, + sequence: Sequence, + epoch: MaspEpoch, + masp_tx: MaspTransaction, + ) -> Result<()> { + let key = + storage::refund_masp_tx_key(port_id, channel_id, sequence, epoch); + self.storage_mut() + .write(&key, masp_tx) + .map_err(ContextError::from) + } + + /// Delete MASP shielding transactions for the shielded refund + fn delete_refund_masp_txs( + &mut self, + port_id: &PortId, + channel_id: &ChannelId, + sequence: Sequence, + ) -> Result<()> { + let prefix = + storage::refund_masp_tx_prefix(port_id, channel_id, sequence); + self.storage_mut() + .delete_prefix(&prefix) + .map_err(ContextError::from) + } } /// Read and decode the IBC sequence diff --git a/crates/ibc/src/context/middlewares.rs b/crates/ibc/src/context/middlewares.rs index 8d65666e63..c9df58b450 100644 --- a/crates/ibc/src/context/middlewares.rs +++ b/crates/ibc/src/context/middlewares.rs @@ -30,7 +30,8 @@ pub fn create_transfer_middlewares( ) -> TransferMiddlewares where C: IbcCommonContext + Debug, - Params: namada_systems::parameters::Read<::Storage>, + Params: namada_systems::parameters::Read<::Storage> + + Debug, { PacketForwardMiddleware::wrap(PfmTransferModule { transfer_module: TransferModule::new(ctx, verifiers), @@ -42,6 +43,8 @@ impl crate::ModuleWrapper for TransferMiddlewares where C: IbcCommonContext + Debug, PfmTransferModule: PfmContext, + Params: namada_systems::parameters::Read<::Storage> + + Debug, { fn as_module(&self) -> &dyn Module { self diff --git a/crates/ibc/src/context/middlewares/pfm_mod.rs b/crates/ibc/src/context/middlewares/pfm_mod.rs index 70454fbf4a..cadd087829 100644 --- a/crates/ibc/src/context/middlewares/pfm_mod.rs +++ b/crates/ibc/src/context/middlewares/pfm_mod.rs @@ -43,15 +43,20 @@ use crate::{Error, IbcCommonContext, IbcStorageContext, TokenTransferContext}; pub struct PfmTransferModule where C: IbcCommonContext + Debug, + Params: namada_systems::parameters::Read<::Storage> + + Debug, { /// The main module - pub transfer_module: TransferModule, + pub transfer_module: TransferModule, #[allow(missing_docs)] pub _phantom: PhantomData, } -impl Debug - for PfmTransferModule +impl Debug for PfmTransferModule +where + C: IbcCommonContext + Debug, + Params: namada_systems::parameters::Read<::Storage> + + Debug, { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct(stringify!(PfmTransferModule)) @@ -63,6 +68,8 @@ impl Debug impl Module for PfmTransferModule where C: IbcCommonContext + Debug, + Params: namada_systems::parameters::Read<::Storage> + + Debug, { fn on_chan_open_init_validate( &self, @@ -292,7 +299,8 @@ where impl PfmContext for PfmTransferModule where C: IbcCommonContext + Debug, - Params: namada_systems::parameters::Read<::Storage>, + Params: namada_systems::parameters::Read<::Storage> + + Debug, { type Error = crate::Error; diff --git a/crates/ibc/src/context/transfer_mod.rs b/crates/ibc/src/context/transfer_mod.rs index a30826514d..d33b537b85 100644 --- a/crates/ibc/src/context/transfer_mod.rs +++ b/crates/ibc/src/context/transfer_mod.rs @@ -3,6 +3,7 @@ use std::cell::RefCell; use std::collections::BTreeSet; use std::fmt::Debug; +use std::marker::PhantomData; use std::rc::Rc; use ibc::apps::transfer::context::TokenTransferValidationContext; @@ -18,8 +19,11 @@ use ibc::apps::transfer::module::{ on_timeout_packet_validate, }; use ibc::apps::transfer::types::error::TokenTransferError; +use ibc::apps::transfer::types::packet::PacketData; use ibc::apps::transfer::types::MODULE_ID_STR; -use ibc::core::channel::types::acknowledgement::Acknowledgement; +use ibc::core::channel::types::acknowledgement::{ + Acknowledgement, AcknowledgementStatus, +}; use ibc::core::channel::types::channel::{Counterparty, Order}; use ibc::core::channel::types::error::{ChannelError, PacketError}; use ibc::core::channel::types::packet::Packet; @@ -28,10 +32,11 @@ use ibc::core::host::types::identifiers::{ChannelId, ConnectionId, PortId}; use ibc::core::router::module::Module; use ibc::core::router::types::module::{ModuleExtras, ModuleId}; use ibc::primitives::Signer; -use namada_core::address::Address; +use namada_core::address::{Address, MASP}; +use namada_core::masp::MaspEpoch; +use namada_state::StorageRead; -use super::common::IbcCommonContext; -use super::token_transfer::TokenTransferContext; +use crate::{IbcCommonContext, IbcStorageContext, TokenTransferContext}; /// IBC module wrapper for getting the reference of the module pub trait ModuleWrapper: Module { @@ -50,17 +55,19 @@ pub trait ModuleWrapper: Module { /// IBC module for token transfer #[derive(Debug)] -pub struct TransferModule +pub struct TransferModule where C: IbcCommonContext, { /// IBC actions pub ctx: TokenTransferContext, + _marker: PhantomData, } -impl TransferModule +impl TransferModule where C: IbcCommonContext, + Params: namada_systems::parameters::Read<::Storage>, { /// Make a new module pub fn new( @@ -69,13 +76,16 @@ where ) -> Self { Self { ctx: TokenTransferContext::new(ctx, verifiers), + _marker: PhantomData, } } } -impl ModuleWrapper for TransferModule +impl ModuleWrapper for TransferModule where C: IbcCommonContext + Debug, + Params: namada_systems::parameters::Read<::Storage> + + Debug, { fn as_module(&self) -> &dyn Module { self @@ -94,9 +104,11 @@ where } } -impl Module for TransferModule +impl Module for TransferModule where C: IbcCommonContext + Debug, + Params: namada_systems::parameters::Read<::Storage> + + Debug, { #[allow(clippy::too_many_arguments)] fn on_chan_open_init_validate( @@ -301,12 +313,53 @@ where acknowledgement: &Acknowledgement, relayer: &Signer, ) -> (ModuleExtras, Result<(), PacketError>) { - let (extras, result) = on_acknowledgement_packet_execute( - &mut self.ctx, - packet, - acknowledgement, - relayer, - ); + let updated_packet = serde_json::from_slice::( + acknowledgement.as_ref(), + ) + .ok() + .and_then(|ack| { + if ack.is_successful() { + return None; + } + let inner = self.ctx.inner.borrow(); + let epoch = inner.storage().get_block_epoch().ok()?; + let masp_epoch_multiplier = + Params::masp_epoch_multiplier(inner.storage()).ok()?; + let masp_epoch = + MaspEpoch::try_from_epoch(epoch, masp_epoch_multiplier).ok()?; + self.ctx + .inner + .borrow() + .refund_masp_tx( + &packet.port_id_on_a, + &packet.chan_id_on_a, + packet.seq_on_a, + masp_epoch, + ) + .ok()??; + let mut data: PacketData = + serde_json::from_slice(&packet.data).ok()?; + data.sender = Signer::from(MASP.to_string()); + let mut packet = packet.clone(); + packet.data = serde_json::to_vec(&data) + .expect("Packet data should be encoded"); + Some(packet) + }); + + let (extras, result) = match updated_packet { + Some(packet) => on_acknowledgement_packet_execute( + &mut self.ctx, + &packet, + acknowledgement, + relayer, + ), + None => on_acknowledgement_packet_execute( + &mut self.ctx, + packet, + acknowledgement, + relayer, + ), + }; (extras, result.map_err(into_packet_error)) } diff --git a/crates/ibc/src/lib.rs b/crates/ibc/src/lib.rs index 69a064dcb6..8d89004ddc 100644 --- a/crates/ibc/src/lib.rs +++ b/crates/ibc/src/lib.rs @@ -90,7 +90,7 @@ use namada_core::ibc::core::channel::types::commitment::{ compute_packet_commitment, AcknowledgementCommitment, PacketCommitment, }; pub use namada_core::ibc::*; -use namada_core::masp::{addr_taddr, ibc_taddr, TAddrData}; +use namada_core::masp::{addr_taddr, ibc_taddr, MaspEpoch, TAddrData}; use namada_core::masp_primitives::transaction::components::ValueSum; use namada_core::token::Amount; use namada_events::EmitEvents; @@ -639,12 +639,26 @@ where if msg.transfer.is_some() { token_transfer_ctx.enable_shielded_transfer(); } + let port_id = msg.message.port_id_on_a.clone(); + let channel_id = msg.message.chan_id_on_a.clone(); send_transfer_execute( &mut self.ctx, &mut token_transfer_ctx, msg.message, ) .map_err(Error::TokenTransfer)?; + + if let Some((_, (epoch, refund_masp_tx))) = + msg.transfer.as_ref().zip(msg.refund_masp_tx) + { + self.save_refund_masp_tx( + &port_id, + &channel_id, + epoch, + refund_masp_tx, + )?; + } + Ok((msg.transfer, None)) } IbcMessage::NftTransfer(msg) => { @@ -653,6 +667,8 @@ where if msg.transfer.is_some() { nft_transfer_ctx.enable_shielded_transfer(); } + let port_id = msg.message.port_id_on_a.clone(); + let channel_id = msg.message.chan_id_on_a.clone(); // Add the source to the set of verifiers self.verifiers.borrow_mut().insert( Address::from_str(msg.message.packet_data.sender.as_ref()) @@ -672,6 +688,18 @@ where msg.message, ) .map_err(Error::NftTransfer)?; + + if let Some((_, (epoch, refund_masp_tx))) = + msg.transfer.as_ref().zip(msg.refund_masp_tx) + { + self.save_refund_masp_tx( + &port_id, + &channel_id, + epoch, + refund_masp_tx, + )?; + } + Ok((msg.transfer, None)) } IbcMessage::Envelope(envelope) => { @@ -699,12 +727,92 @@ where { extract_masp_tx_from_packet(&msg.packet) } - #[cfg(is_apple_silicon)] + // Check if the refund masp tx is stored when the transfer + // failed, i.e. ack with an error or timeout MsgEnvelope::Packet(PacketMsg::Ack(msg)) => { - // NOTE: This is unneeded but wasm compilation error - // happened if deleted on macOS with Apple Silicon - let _ = extract_masp_tx_from_packet(&msg.packet); - None + match serde_json::from_slice::( + msg.acknowledgement.as_ref(), + ) { + Ok(ack) if !ack.is_successful() => { + let inner = self.ctx.inner.borrow(); + let epoch = inner + .storage() + .get_block_epoch() + .map_err(Error::Storage)?; + let masp_epoch_multiplier = + Params::masp_epoch_multiplier( + inner.storage(), + ) + .map_err(Error::Storage)?; + let masp_epoch = MaspEpoch::try_from_epoch( + epoch, + masp_epoch_multiplier, + ) + .map_err(|e| Error::Other(e.to_string()))?; + let refund_masp_tx = self + .ctx + .inner + .borrow() + .refund_masp_tx( + &msg.packet.port_id_on_a, + &msg.packet.chan_id_on_a, + msg.packet.seq_on_a, + masp_epoch, + ) + .map_err(|e| Error::Context(Box::new(e)))?; + // Delete refund masp txs of the packet + // including, the one for the previous epoch + self.ctx + .inner + .borrow_mut() + .delete_refund_masp_txs( + &msg.packet.port_id_on_a, + &msg.packet.chan_id_on_a, + msg.packet.seq_on_a, + ) + .map_err(|e| Error::Context(Box::new(e)))?; + refund_masp_tx + } + _ => None, + } + } + MsgEnvelope::Packet(PacketMsg::Timeout(msg)) => { + let inner = self.ctx.inner.borrow(); + let epoch = inner + .storage() + .get_block_epoch() + .map_err(Error::Storage)?; + let masp_epoch_multiplier = + Params::masp_epoch_multiplier(inner.storage()) + .map_err(Error::Storage)?; + let masp_epoch = MaspEpoch::try_from_epoch( + epoch, + masp_epoch_multiplier, + ) + .map_err(|e| Error::Other(e.to_string()))?; + let refund_masp_tx = self + .ctx + .inner + .borrow() + .refund_masp_tx( + &msg.packet.port_id_on_a, + &msg.packet.chan_id_on_a, + msg.packet.seq_on_a, + masp_epoch, + ) + .map_err(|e| Error::Context(Box::new(e)))?; + // Delete refund masp txs of the packet, including the + // one for the previous epoch + self.ctx + .inner + .borrow_mut() + .delete_refund_masp_txs( + &msg.packet.port_id_on_a, + &msg.packet.chan_id_on_a, + msg.packet.seq_on_a, + ) + .map_err(|e| Error::Context(Box::new(e)))?; + refund_masp_tx } _ => None, }; @@ -792,6 +900,32 @@ where } Ok(()) } + + fn save_refund_masp_tx( + &mut self, + port_id: &PortId, + channel_id: &ChannelId, + epoch: MaspEpoch, + refund_masp_tx: MaspTransaction, + ) -> Result<(), Error> { + let sequence = get_last_sequence_send( + self.ctx.inner.borrow().storage(), + port_id, + channel_id, + ) + .map_err(Error::Storage)?; + self.ctx + .inner + .borrow_mut() + .store_refund_masp_tx( + port_id, + channel_id, + sequence, + epoch, + refund_masp_tx, + ) + .map_err(|e| Error::Context(Box::new(e))) + } } fn is_packet_forward(data: &PacketData) -> bool { @@ -880,6 +1014,7 @@ pub fn decode_message( let msg = MsgTransfer { message, transfer: None, + refund_masp_tx: None, }; return Ok(IbcMessage::Transfer(Box::new(msg))); } @@ -887,6 +1022,7 @@ pub fn decode_message( let msg = MsgNftTransfer { message, transfer: None, + refund_masp_tx: None, }; return Ok(IbcMessage::NftTransfer(msg)); } diff --git a/crates/ibc/src/msg.rs b/crates/ibc/src/msg.rs index 8a15817c00..1c3dc10b46 100644 --- a/crates/ibc/src/msg.rs +++ b/crates/ibc/src/msg.rs @@ -16,6 +16,7 @@ use ibc::core::host::types::identifiers::PortId; use ibc::primitives::proto::Protobuf; use masp_primitives::transaction::Transaction as MaspTransaction; use namada_core::borsh::BorshSerializeExt; +use namada_core::masp::MaspEpoch; /// The different variants of an Ibc message #[derive(Debug, Clone)] @@ -36,6 +37,8 @@ pub struct MsgTransfer { pub message: IbcMsgTransfer, /// Shieleded transfer for MASP transaction pub transfer: Option, + /// MASP transaction for refund + pub refund_masp_tx: Option<(MaspEpoch, MaspTransaction)>, } impl BorshSerialize for MsgTransfer { @@ -44,7 +47,7 @@ impl BorshSerialize for MsgTransfer { writer: &mut W, ) -> std::io::Result<()> { let encoded_msg = self.message.clone().encode_vec(); - let members = (encoded_msg, &self.transfer); + let members = (encoded_msg, &self.transfer, &self.refund_masp_tx); BorshSerialize::serialize(&members, writer) } } @@ -54,11 +57,18 @@ impl BorshDeserialize for MsgTransfer { reader: &mut R, ) -> std::io::Result { use std::io::{Error, ErrorKind}; - let (msg, transfer): (Vec, Option) = - BorshDeserialize::deserialize_reader(reader)?; + let (msg, transfer, refund_masp_tx): ( + Vec, + Option, + Option<(MaspEpoch, MaspTransaction)>, + ) = BorshDeserialize::deserialize_reader(reader)?; let message = IbcMsgTransfer::decode_vec(&msg) .map_err(|err| Error::new(ErrorKind::InvalidData, err))?; - Ok(Self { message, transfer }) + Ok(Self { + message, + transfer, + refund_masp_tx, + }) } } @@ -66,10 +76,12 @@ impl BorshSchema for MsgTransfer { fn add_definitions_recursively( definitions: &mut BTreeMap, ) { - <(Vec, Option)>::add_definitions_recursively(definitions); - let fields = Fields::UnnamedFields(vec![ - <(Vec, Option)>::declaration(), - ]); + <(Vec, Option, Option)>::add_definitions_recursively(definitions); + let fields = Fields::UnnamedFields(vec![<( + Vec, + Option, + Option<(MaspEpoch, MaspTransaction)>, + )>::declaration()]); definitions.insert(Self::declaration(), Definition::Struct { fields }); } @@ -86,6 +98,8 @@ pub struct MsgNftTransfer { pub message: IbcMsgNftTransfer, /// Shieleded transfer for MASP transaction pub transfer: Option, + /// MASP transaction for refund + pub refund_masp_tx: Option<(MaspEpoch, MaspTransaction)>, } impl BorshSerialize for MsgNftTransfer { @@ -94,7 +108,7 @@ impl BorshSerialize for MsgNftTransfer { writer: &mut W, ) -> std::io::Result<()> { let encoded_msg = self.message.clone().encode_vec(); - let members = (encoded_msg, &self.transfer); + let members = (encoded_msg, &self.transfer, &self.refund_masp_tx); BorshSerialize::serialize(&members, writer) } } @@ -104,11 +118,18 @@ impl BorshDeserialize for MsgNftTransfer { reader: &mut R, ) -> std::io::Result { use std::io::{Error, ErrorKind}; - let (msg, transfer): (Vec, Option) = - BorshDeserialize::deserialize_reader(reader)?; + let (msg, transfer, refund_masp_tx): ( + Vec, + Option, + Option<(MaspEpoch, MaspTransaction)>, + ) = BorshDeserialize::deserialize_reader(reader)?; let message = IbcMsgNftTransfer::decode_vec(&msg) .map_err(|err| Error::new(ErrorKind::InvalidData, err))?; - Ok(Self { message, transfer }) + Ok(Self { + message, + transfer, + refund_masp_tx, + }) } } @@ -116,10 +137,12 @@ impl BorshSchema for MsgNftTransfer { fn add_definitions_recursively( definitions: &mut BTreeMap, ) { - <(Vec, Option)>::add_definitions_recursively(definitions); - let fields = Fields::UnnamedFields(vec![ - <(Vec, Option)>::declaration(), - ]); + <(Vec, Option, Option)>::add_definitions_recursively(definitions); + let fields = Fields::UnnamedFields(vec![<( + Vec, + Option, + Option<(MaspEpoch, MaspTransaction)>, + )>::declaration()]); definitions.insert(Self::declaration(), Definition::Struct { fields }); } diff --git a/crates/ibc/src/storage.rs b/crates/ibc/src/storage.rs index 37754320ce..dd4baacb20 100644 --- a/crates/ibc/src/storage.rs +++ b/crates/ibc/src/storage.rs @@ -15,6 +15,7 @@ use ibc::core::host::types::path::{ }; use ibc_middleware_packet_forward::InFlightPacketKey; use namada_core::address::{Address, InternalAddress}; +use namada_core::masp::MaspEpoch; use namada_core::storage::{DbKeySeg, Key, KeySeg}; use namada_core::token::Amount; use namada_events::EmitEvents; @@ -39,6 +40,7 @@ const MINT: &str = "mint"; const THROUGHPUT_LIMIT: &str = "throughput_limit"; const DEPOSIT: &str = "deposit"; const WITHDRAW: &str = "withdraw"; +const REFUND_MASP_TX: &str = "refund_masp_tx"; /// Mint IBC tokens. This function doesn't emit event (see /// `mint_tokens_and_emit_event` below) @@ -668,3 +670,25 @@ pub fn inflight_packet_key(inflight_packet_key: &InFlightPacketKey) -> Key { .with_segment(inflight_packet_key.channel.to_string()) .with_segment(inflight_packet_key.sequence.to_string()) } + +/// Returns a key prefix of the MASP transactions for the shielded refund +pub fn refund_masp_tx_prefix( + port_id: &PortId, + channel_id: &ChannelId, + sequence: Sequence, +) -> Key { + let path = format!("{REFUND_MASP_TX}/{port_id}/{channel_id}/{sequence}"); + ibc_key(path) + .expect("Creating a key for the masp tx for refund shouldn't fail") +} + +/// Returns a key of the MASP transaction for the shielded refund +pub fn refund_masp_tx_key( + port_id: &PortId, + channel_id: &ChannelId, + sequence: Sequence, + epoch: MaspEpoch, +) -> Key { + let prefix = refund_masp_tx_prefix(port_id, channel_id, sequence); + prefix.with_segment(epoch.0) +} diff --git a/crates/ibc/src/vp/mod.rs b/crates/ibc/src/vp/mod.rs index 410fd75f83..c779464228 100644 --- a/crates/ibc/src/vp/mod.rs +++ b/crates/ibc/src/vp/mod.rs @@ -129,11 +129,12 @@ where EVAL: 'static + VpEvaluator<'ctx, S, CA, EVAL> + Debug, CA: 'static + Clone + Debug, Gov: governance::Read>, - Params: parameters::Read>, + Params: + parameters::Read> + Debug, ParamsPre: parameters::Keys + parameters::Read>, - ParamsPseudo: - parameters::Read>, + ParamsPseudo: parameters::Read> + + Debug, Token: token::Keys + token::Write> + Debug, @@ -210,11 +211,12 @@ where S: 'static + StateRead, EVAL: 'static + VpEvaluator<'ctx, S, CA, EVAL> + Debug, CA: 'static + Clone + Debug, - Params: parameters::Read>, + Params: + parameters::Read> + Debug, ParamsPre: parameters::Keys + parameters::Read>, - ParamsPseudo: - parameters::Read>, + ParamsPseudo: parameters::Read> + + Debug, Token: token::Keys + token::Write> + Debug, @@ -2358,6 +2360,7 @@ mod tests { let tx_data = MsgTransfer:: { message: msg, transfer: None, + refund_masp_tx: None, } .serialize_to_vec(); @@ -3218,6 +3221,7 @@ mod tests { let tx_data = MsgNftTransfer:: { message: msg, transfer: None, + refund_masp_tx: None, } .serialize_to_vec(); diff --git a/crates/sdk/src/tx.rs b/crates/sdk/src/tx.rs index 19a6a5ba17..2cd3dc31cc 100644 --- a/crates/sdk/src/tx.rs +++ b/crates/sdk/src/tx.rs @@ -41,7 +41,9 @@ use namada_core::ibc::core::client::types::Height as IbcHeight; use namada_core::ibc::core::host::types::identifiers::{ChannelId, PortId}; use namada_core::ibc::primitives::Timestamp as IbcTimestamp; use namada_core::key::{self, *}; -use namada_core::masp::{AssetData, MaspEpoch, TransferSource, TransferTarget}; +use namada_core::masp::{ + AssetData, MaspEpoch, PaymentAddress, TransferSource, TransferTarget, +}; use namada_core::storage; use namada_core::time::DateTimeUtc; use namada_governance::cli::onchain::{ @@ -2613,7 +2615,7 @@ pub async fn build_ibc_transfer( )); } - let refund_target = + let (shielded_refund_target, trans_refund_target) = get_refund_target(context, &args.source, &args.refund_target).await?; let source = args.source.effective_address(); @@ -2781,8 +2783,11 @@ pub async fn build_ibc_transfer( // The refund target should be given or created if the source is shielded. // Otherwise, the refund target should be None. assert!( - (args.source.spending_key().is_some() && refund_target.is_some()) - || (args.source.address().is_some() && refund_target.is_none()) + (args.source.spending_key().is_some() + && (shielded_refund_target.is_some() + || trans_refund_target.is_some())) + || (args.source.address().is_some() + && shielded_refund_target.is_none()) ); // The memo is either IbcShieldingData or just a memo let memo = args @@ -2791,11 +2796,36 @@ pub async fn build_ibc_transfer( .map_or(args.ibc_memo.clone(), |shielding_data| { Some(shielding_data.clone().into()) }); - // If the refund address is given, set the refund address. It is used only - // when refunding and won't affect the actual transfer because the actual - // source will be the MASP address and the MASP transaction is generated by - // the shielded source address. - let sender = refund_target + // For transfer to the shielded refund target + let refund_masp_tx = match shielded_refund_target { + Some(target) => { + let masp_transfer_data = vec![MaspTransferData { + // The token will be unescrowed from IBC address + source: TransferSource::Address(IBC), + target: TransferTarget::PaymentAddress(target), + token: args.token.clone(), + amount: validated_amount, + }]; + construct_shielded_parts( + context, + masp_transfer_data, + None, + args.tx.expiration.to_datetime(), + bparams, + ) + .await? + .map(|(shielded_transfer, _)| { + (shielded_transfer.epoch.into(), shielded_transfer.masp_tx) + }) + } + None => None, + }; + + // If the transparent refund address is given, set the refund address. It is + // used only when refunding and won't affect the actual transfer because + // the actual source will be the MASP address and the MASP transaction + // is generated by the shielded source address. + let sender = trans_refund_target .map(|t| t.to_string()) .unwrap_or(source.to_string()) .into(); @@ -2820,7 +2850,12 @@ pub async fn build_ibc_transfer( timeout_height_on_b: timeout_height, timeout_timestamp_on_b: timeout_timestamp, }; - MsgTransfer { message, transfer }.serialize_to_vec() + MsgTransfer { + message, + transfer, + refund_masp_tx, + } + .serialize_to_vec() } else if let Some((trace_path, base_class_id, token_id)) = is_nft_trace(&ibc_denom) { @@ -4084,60 +4119,67 @@ async fn target_exists_or_err( } /// Returns the given refund target address if the given address is valid for -/// the IBC shielded transfer. Returns an error if the address is a payment -/// address or given for non-shielded transfer. +/// the IBC shielded transfer. Returns the refund target address and the +/// fallback transparent address. Returns an error if the address is given for +/// non-shielded transfer. async fn get_refund_target( context: &impl Namada, source: &TransferSource, refund_target: &Option, -) -> Result> { +) -> Result<(Option, Option
)> { match (source, refund_target) { - (_, Some(TransferTarget::PaymentAddress(pa))) => { - Err(Error::Other(format!( - "Supporting only a transparent address as a refund target: {}", - pa, - ))) - } - ( - TransferSource::ExtendedKey(_), - Some(TransferTarget::Address(addr)), - ) => Ok(Some(addr.clone())), + (TransferSource::ExtendedKey(_), Some(target)) => match target { + TransferTarget::PaymentAddress(pa) => { + let fallback_target = + get_fallback_refund_target(context).await?; + Ok((Some(pa.clone()), Some(fallback_target))) + } + TransferTarget::Address(addr) => Ok((None, Some(addr.clone()))), + TransferTarget::Ibc(_) => { + Err(Error::Other(format!("Invalid refund target: {target}"))) + } + }, (TransferSource::ExtendedKey(_), None) => { // Generate a new transparent address if it doesn't exist - let mut rng = OsRng; - let mut wallet = context.wallet_mut().await; - let mut alias = - format!("{IBC_REFUND_ALIAS_PREFIX}-{}", rng.next_u64()); - while wallet.find_address(&alias).is_some() { - alias = format!("{IBC_REFUND_ALIAS_PREFIX}-{}", rng.next_u64()); - } - wallet - .gen_store_secret_key( - SchemeType::Ed25519, - Some(alias.clone()), - false, - None, - &mut rng, - ) - .ok_or_else(|| { - Error::Other( - "Adding a new refund address failed".to_string(), - ) - })?; - wallet.save().map_err(|e| { - Error::Other(format!("Saving wallet error: {e}")) - })?; - let addr = wallet.find_address(alias).ok_or_else(|| { - Error::Other("Finding the reund address failed".to_string()) - })?; - Ok(Some(addr.into_owned())) + let addr = get_fallback_refund_target(context).await?; + Ok((None, Some(addr))) } (_, Some(_)) => Err(Error::Other( "Refund target can't be specified for non-shielded transfer" .to_string(), )), - (_, None) => Ok(None), + (_, None) => Ok((None, None)), + } +} + +async fn get_fallback_refund_target(context: &impl Namada) -> Result
{ + let mut rng = OsRng; + let mut wallet = context.wallet_mut().await; + let mut alias = format!("{IBC_REFUND_ALIAS_PREFIX}-{}", rng.next_u64()); + while wallet.find_address(&alias).is_some() { + alias = format!("{IBC_REFUND_ALIAS_PREFIX}-{}", rng.next_u64()); } + wallet + .gen_store_secret_key( + SchemeType::Ed25519, + Some(alias.clone()), + false, + None, + &mut rng, + ) + .ok_or_else(|| { + Error::Other("Adding a new refund address failed".to_string()) + })?; + wallet + .save() + .map_err(|e| Error::Other(format!("Saving wallet error: {e}")))?; + let addr = wallet + .find_address(alias) + .ok_or_else(|| { + Error::Other("Finding the reund address failed".to_string()) + })? + .into_owned(); + Ok(addr) } enum CheckBalance { From e607d27c63f2d30bcea2fc43d705e9795f390ddd Mon Sep 17 00:00:00 2001 From: yito88 Date: Mon, 6 Jan 2025 23:28:49 +0100 Subject: [PATCH 15/22] borrow_mut inner --- crates/ibc/src/context/transfer_mod.rs | 4 +--- crates/ibc/src/lib.rs | 22 ++++++---------------- crates/ibc/src/storage.rs | 8 +++++--- crates/node/src/bench_utils.rs | 2 ++ crates/sdk/src/lib.rs | 8 ++++---- crates/sdk/src/tx.rs | 13 +++++++++---- crates/tests/src/vm_host_env/ibc.rs | 1 + 7 files changed, 28 insertions(+), 30 deletions(-) diff --git a/crates/ibc/src/context/transfer_mod.rs b/crates/ibc/src/context/transfer_mod.rs index d33b537b85..98b5dc685e 100644 --- a/crates/ibc/src/context/transfer_mod.rs +++ b/crates/ibc/src/context/transfer_mod.rs @@ -327,9 +327,7 @@ where Params::masp_epoch_multiplier(inner.storage()).ok()?; let masp_epoch = MaspEpoch::try_from_epoch(epoch, masp_epoch_multiplier).ok()?; - self.ctx - .inner - .borrow() + inner .refund_masp_tx( &packet.port_id_on_a, &packet.chan_id_on_a, diff --git a/crates/ibc/src/lib.rs b/crates/ibc/src/lib.rs index 8d89004ddc..5bb8f10df2 100644 --- a/crates/ibc/src/lib.rs +++ b/crates/ibc/src/lib.rs @@ -734,7 +734,7 @@ where msg.acknowledgement.as_ref(), ) { Ok(ack) if !ack.is_successful() => { - let inner = self.ctx.inner.borrow(); + let mut inner = self.ctx.inner.borrow_mut(); let epoch = inner .storage() .get_block_epoch() @@ -749,10 +749,7 @@ where masp_epoch_multiplier, ) .map_err(|e| Error::Other(e.to_string()))?; - let refund_masp_tx = self - .ctx - .inner - .borrow() + let refund_masp_tx = inner .refund_masp_tx( &msg.packet.port_id_on_a, &msg.packet.chan_id_on_a, @@ -762,9 +759,7 @@ where .map_err(|e| Error::Context(Box::new(e)))?; // Delete refund masp txs of the packet // including, the one for the previous epoch - self.ctx - .inner - .borrow_mut() + inner .delete_refund_masp_txs( &msg.packet.port_id_on_a, &msg.packet.chan_id_on_a, @@ -777,7 +772,7 @@ where } } MsgEnvelope::Packet(PacketMsg::Timeout(msg)) => { - let inner = self.ctx.inner.borrow(); + let mut inner = self.ctx.inner.borrow_mut(); let epoch = inner .storage() .get_block_epoch() @@ -790,10 +785,7 @@ where masp_epoch_multiplier, ) .map_err(|e| Error::Other(e.to_string()))?; - let refund_masp_tx = self - .ctx - .inner - .borrow() + let refund_masp_tx = inner .refund_masp_tx( &msg.packet.port_id_on_a, &msg.packet.chan_id_on_a, @@ -803,9 +795,7 @@ where .map_err(|e| Error::Context(Box::new(e)))?; // Delete refund masp txs of the packet, including the // one for the previous epoch - self.ctx - .inner - .borrow_mut() + inner .delete_refund_masp_txs( &msg.packet.port_id_on_a, &msg.packet.chan_id_on_a, diff --git a/crates/ibc/src/storage.rs b/crates/ibc/src/storage.rs index dd4baacb20..88b74734c6 100644 --- a/crates/ibc/src/storage.rs +++ b/crates/ibc/src/storage.rs @@ -677,9 +677,11 @@ pub fn refund_masp_tx_prefix( channel_id: &ChannelId, sequence: Sequence, ) -> Key { - let path = format!("{REFUND_MASP_TX}/{port_id}/{channel_id}/{sequence}"); - ibc_key(path) - .expect("Creating a key for the masp tx for refund shouldn't fail") + let key: Key = namada_core::address::IBC.to_db_key().into(); + key.with_segment(REFUND_MASP_TX.to_string()) + .with_segment(port_id.to_string()) + .with_segment(channel_id.to_string()) + .with_segment(sequence.to_string()) } /// Returns a key of the MASP transaction for the shielded refund diff --git a/crates/node/src/bench_utils.rs b/crates/node/src/bench_utils.rs index c56dd1303d..24f63b792f 100644 --- a/crates/node/src/bench_utils.rs +++ b/crates/node/src/bench_utils.rs @@ -259,6 +259,7 @@ impl BenchShellInner { let msg = MsgTransfer:: { message, transfer: None, + refund_masp_tx: None, }; self.generate_ibc_tx(TX_IBC_WASM, msg.serialize_to_vec()) @@ -1369,6 +1370,7 @@ impl BenchShieldedCtx { let msg = MsgTransfer:: { message: msg, transfer: Some(transfer), + refund_masp_tx: None, }; let mut ibc_tx = ctx diff --git a/crates/sdk/src/lib.rs b/crates/sdk/src/lib.rs index 7b175d79c5..d0a7222d54 100644 --- a/crates/sdk/src/lib.rs +++ b/crates/sdk/src/lib.rs @@ -1525,9 +1525,9 @@ pub mod testing { Option<(ShieldedTransfer, HashMap, StoredBuildParams)>, ) { if let Some((transfer, aux)) = transfer_aux { - (MsgTransfer { message, transfer: Some(transfer) }, aux) + (MsgTransfer { message, transfer: Some(transfer), refund_masp_tx: None }, aux) } else { - (MsgTransfer { message, transfer: None }, None) + (MsgTransfer { message, transfer: None, refund_masp_tx: None }, None) } } } @@ -1575,9 +1575,9 @@ pub mod testing { Option<(ShieldedTransfer, HashMap, StoredBuildParams)>, ) { if let Some((transfer, aux)) = transfer_aux { - (MsgNftTransfer { message, transfer: Some(transfer) }, aux) + (MsgNftTransfer { message, transfer: Some(transfer), refund_masp_tx: None }, aux) } else { - (MsgNftTransfer { message, transfer: None }, None) + (MsgNftTransfer { message, transfer: None, refund_masp_tx: None }, None) } } } diff --git a/crates/sdk/src/tx.rs b/crates/sdk/src/tx.rs index 2cd3dc31cc..9ac2742bfe 100644 --- a/crates/sdk/src/tx.rs +++ b/crates/sdk/src/tx.rs @@ -2796,7 +2796,7 @@ pub async fn build_ibc_transfer( .map_or(args.ibc_memo.clone(), |shielding_data| { Some(shielding_data.clone().into()) }); - // For transfer to the shielded refund target + // Shielded transfer to the shielded refund target let refund_masp_tx = match shielded_refund_target { Some(target) => { let masp_transfer_data = vec![MaspTransferData { @@ -2815,7 +2815,7 @@ pub async fn build_ibc_transfer( ) .await? .map(|(shielded_transfer, _)| { - (shielded_transfer.epoch.into(), shielded_transfer.masp_tx) + (shielded_transfer.epoch, shielded_transfer.masp_tx) }) } None => None, @@ -2886,7 +2886,12 @@ pub async fn build_ibc_transfer( timeout_height_on_b: timeout_height, timeout_timestamp_on_b: timeout_timestamp, }; - MsgNftTransfer { message, transfer }.serialize_to_vec() + MsgNftTransfer { + message, + transfer, + refund_masp_tx, + } + .serialize_to_vec() } else { return Err(Error::Other(format!("Invalid IBC denom: {ibc_denom}"))); }; @@ -4132,7 +4137,7 @@ async fn get_refund_target( TransferTarget::PaymentAddress(pa) => { let fallback_target = get_fallback_refund_target(context).await?; - Ok((Some(pa.clone()), Some(fallback_target))) + Ok((Some(*pa), Some(fallback_target))) } TransferTarget::Address(addr) => Ok((None, Some(addr.clone()))), TransferTarget::Ibc(_) => { diff --git a/crates/tests/src/vm_host_env/ibc.rs b/crates/tests/src/vm_host_env/ibc.rs index 69d18a45df..2116a07956 100644 --- a/crates/tests/src/vm_host_env/ibc.rs +++ b/crates/tests/src/vm_host_env/ibc.rs @@ -614,6 +614,7 @@ pub fn msg_transfer( MsgTransfer { message, transfer: None, + refund_masp_tx: None, } } From 0d473cddf8728cc9a3201b1d2c89c7fda56ac073 Mon Sep 17 00:00:00 2001 From: yito88 Date: Thu, 9 Jan 2025 00:08:43 +0100 Subject: [PATCH 16/22] WIP: fix masp vp and add test --- crates/ibc/src/lib.rs | 253 ++++++++++++++++++++++++------ crates/sdk/src/validation.rs | 1 + crates/shielded_token/src/vp.rs | 44 ++++-- crates/systems/src/ibc.rs | 9 +- crates/tests/src/e2e/ibc_tests.rs | 107 +++++++++---- 5 files changed, 324 insertions(+), 90 deletions(-) diff --git a/crates/ibc/src/lib.rs b/crates/ibc/src/lib.rs index 5bb8f10df2..0cdf6c7f89 100644 --- a/crates/ibc/src/lib.rs +++ b/crates/ibc/src/lib.rs @@ -36,7 +36,6 @@ use std::str::FromStr; pub use actions::transfer_over_ibc; use apps::transfer::types::packet::PacketData; -use apps::transfer::types::PORT_ID_STR; use borsh::BorshDeserialize; pub use context::common::IbcCommonContext; pub use context::nft_transfer::NftTransferContext; @@ -242,17 +241,50 @@ where .into_storage_result() .ok(); let tx = if let Some(IbcMessage::Envelope(ref envelope)) = msg { - Some(extract_masp_tx_from_envelope(envelope).ok_or_else(|| { - StorageError::new_const( - "Missing MASP transaction in IBC message", - ) - })?) + extract_masp_tx_from_envelope(envelope) } else { None }; Ok(tx) } + fn try_get_refund_masp_tx( + storage: &S, + tx_data: &[u8], + masp_epoch: MaspEpoch, + ) -> StorageResult> { + let msg = decode_message::(tx_data) + .into_storage_result() + .ok(); + // refund only when ack or timeout in an IBC envelope message + let Some(IbcMessage::Envelope(envelope)) = msg else { + return Ok(None); + }; + + let packet_info = match &*envelope { + MsgEnvelope::Packet(PacketMsg::Ack(msg)) => Some(( + &msg.packet.port_id_on_a, + &msg.packet.chan_id_on_a, + msg.packet.seq_on_a, + )), + MsgEnvelope::Packet(PacketMsg::Timeout(msg)) => Some(( + &msg.packet.port_id_on_a, + &msg.packet.chan_id_on_a, + msg.packet.seq_on_a, + )), + _ => None, + }; + + if let Some((port_id, channel_id, sequence)) = packet_info { + let key = storage::refund_masp_tx_key( + port_id, channel_id, sequence, masp_epoch, + ); + storage.read(&key) + } else { + Ok(None) + } + } + fn apply_ibc_packet( storage: &S, tx_data: &[u8], @@ -293,62 +325,155 @@ where keys_changed, )?; } - // This event is emitted on the receiver - Some(IbcMessage::Envelope(envelope)) => { - if let MsgEnvelope::Packet(PacketMsg::Recv(msg)) = *envelope { - if msg.packet.port_id_on_b.as_str() == PORT_ID_STR { - let packet_data = serde_json::from_slice::( - &msg.packet.data, - ) - .map_err(StorageError::new)?; - let receiver = packet_data.receiver.to_string(); + Some(IbcMessage::Envelope(envelope)) => match *envelope { + MsgEnvelope::Packet(PacketMsg::Recv(msg)) => { + let recv_info = match msg.packet.port_id_on_b.as_str() { + FT_PORT_ID_STR => { + let packet_data = + serde_json::from_slice::( + &msg.packet.data, + ) + .map_err(StorageError::new)?; + let receiver = packet_data.receiver.to_string(); + let ibc_denom = packet_data.token.denom.to_string(); + let amount = packet_data + .token + .amount + .try_into() + .into_storage_result()?; + Some((receiver, vec![ibc_denom], amount)) + } + NFT_PORT_ID_STR => { + let packet_data = + serde_json::from_slice::( + &msg.packet.data, + ) + .map_err(StorageError::new)?; + let receiver = packet_data.receiver.to_string(); + let ibc_traces = packet_data + .token_ids + .0 + .iter() + .map(|token_id| { + ibc_trace_for_nft( + &packet_data.class_id, + token_id, + ) + }) + .collect(); + Some((receiver, ibc_traces, Amount::from_u64(1))) + } + _ => None, + }; + if let Some((receiver, ibc_traces, amount)) = recv_info { let addr = TAddrData::Ibc(receiver.clone()); accum.decoder.insert(ibc_taddr(receiver), addr); - let ibc_denom = packet_data.token.denom.to_string(); - let amount = packet_data - .token - .amount - .try_into() - .into_storage_result()?; accum = apply_recv_msg( storage, accum, &msg, - vec![ibc_denom], + ibc_traces, amount, keys_changed, )?; - } else { - let packet_data = - serde_json::from_slice::( - &msg.packet.data, - ) - .map_err(StorageError::new)?; - let receiver = packet_data.receiver.to_string(); - let addr = TAddrData::Ibc(receiver.clone()); - accum.decoder.insert(ibc_taddr(receiver), addr); - let ibc_traces = packet_data - .token_ids - .0 - .iter() - .map(|token_id| { - ibc_trace_for_nft( - &packet_data.class_id, - token_id, + } + } + MsgEnvelope::Packet(PacketMsg::Ack(msg)) => { + let refund_info = match msg.packet.port_id_on_a.as_str() { + FT_PORT_ID_STR => { + let packet_data = + serde_json::from_slice::( + &msg.packet.data, ) - }) - .collect(); - accum = apply_recv_msg( - storage, + .map_err(StorageError::new)?; + let ibc_denom = packet_data.token.denom.to_string(); + let amount = packet_data + .token + .amount + .try_into() + .into_storage_result()?; + Some((vec![ibc_denom], amount)) + } + NFT_PORT_ID_STR => { + let packet_data = + serde_json::from_slice::( + &msg.packet.data, + ) + .map_err(StorageError::new)?; + let ibc_traces = packet_data + .token_ids + .0 + .iter() + .map(|token_id| { + ibc_trace_for_nft( + &packet_data.class_id, + token_id, + ) + }) + .collect(); + Some((ibc_traces, Amount::from_u64(1))) + } + _ => None, + }; + if let Some((ibc_traces, amount)) = refund_info { + accum = apply_refund_msg( accum, - &msg, + &msg.packet.port_id_on_a, + &msg.packet.chan_id_on_a, ibc_traces, - Amount::from_u64(1), - keys_changed, + amount, )?; } } - } + MsgEnvelope::Packet(PacketMsg::Timeout(msg)) => { + let refund_info = match msg.packet.port_id_on_a.as_str() { + FT_PORT_ID_STR => { + let packet_data = + serde_json::from_slice::( + &msg.packet.data, + ) + .map_err(StorageError::new)?; + let ibc_denom = packet_data.token.denom.to_string(); + let amount = packet_data + .token + .amount + .try_into() + .into_storage_result()?; + Some((vec![ibc_denom], amount)) + } + NFT_PORT_ID_STR => { + let packet_data = + serde_json::from_slice::( + &msg.packet.data, + ) + .map_err(StorageError::new)?; + let ibc_traces = packet_data + .token_ids + .0 + .iter() + .map(|token_id| { + ibc_trace_for_nft( + &packet_data.class_id, + token_id, + ) + }) + .collect(); + Some((ibc_traces, Amount::from_u64(1))) + } + _ => None, + }; + if let Some((ibc_traces, amount)) = refund_info { + accum = apply_refund_msg( + accum, + &msg.packet.port_id_on_a, + &msg.packet.chan_id_on_a, + ibc_traces, + amount, + )?; + } + } + _ => {} + }, } Ok(accum) } @@ -570,6 +695,40 @@ where Ok(accum) } +// Apply a refund to the changed balances structure +fn apply_refund_msg( + mut accum: ChangedBalances, + src_port_id: &PortId, + src_channel_id: &ChannelId, + ibc_traces: Vec, + amount: Amount, +) -> StorageResult { + // Shielded refund only happens if MsgAcknowledgement or MsgTimeout is + // successful + for ibc_trace in &ibc_traces { + // If there is a transfer to the IBC account, then deduplicate the + // balance increase since we already account for it below + let token = convert_to_address(ibc_trace).into_storage_result()?; + let delta = ValueSum::from_pair(token, amount); + if !is_sender_chain_source(ibc_trace, src_port_id, src_channel_id) { + // Enable funds to be taken from the IBC internal address and be + // deposited elsewhere Required for the IBC internal + // Address to release funds + let ibc_taddr = addr_taddr(address::IBC); + let pre_entry = accum + .pre + .get(&ibc_taddr) + .cloned() + .unwrap_or(ValueSum::zero()); + accum.pre.insert( + ibc_taddr, + checked!(pre_entry + &delta).map_err(StorageError::new)?, + ); + } + } + Ok(accum) +} + /// IBC actions to handle IBC operations #[derive(Debug)] pub struct IbcActions<'a, C, Params, Token> diff --git a/crates/sdk/src/validation.rs b/crates/sdk/src/validation.rs index f2ed9307b7..aa0606e4fa 100644 --- a/crates/sdk/src/validation.rs +++ b/crates/sdk/src/validation.rs @@ -81,6 +81,7 @@ pub type MaspVp<'ctx, CTX> = token::vp::MaspVp< CTX, parameters::Store<>::Pre>, governance::Store<>::Pre>, + ibc::Store<>::Pre>, ibc::Store<>::Post>, token::Store<>::Pre>, token::Transfer, diff --git a/crates/shielded_token/src/vp.rs b/crates/shielded_token/src/vp.rs index 49fde69909..7c944fe0a3 100644 --- a/crates/shielded_token/src/vp.rs +++ b/crates/shielded_token/src/vp.rs @@ -37,10 +37,18 @@ use crate::storage_key::{ use crate::validation::verify_shielded_tx; /// MASP VP -pub struct MaspVp<'ctx, CTX, Params, Gov, Ibc, TransToken, Transfer> { +pub struct MaspVp<'ctx, CTX, Params, Gov, IbcPre, IbcPost, TransToken, Transfer> +{ /// Generic types for DI - pub _marker: - PhantomData<(&'ctx CTX, Params, Gov, Ibc, TransToken, Transfer)>, + pub _marker: PhantomData<( + &'ctx CTX, + Params, + Gov, + IbcPre, + IbcPost, + TransToken, + Transfer, + )>, } // Balances changed by a transaction @@ -56,15 +64,25 @@ struct ChangedBalances { post: BTreeMap>, } -impl<'view, 'ctx: 'view, CTX, Params, Gov, Ibc, TransToken, Transfer> - MaspVp<'ctx, CTX, Params, Gov, Ibc, TransToken, Transfer> +impl< + 'view, + 'ctx: 'view, + CTX, + Params, + Gov, + IbcPre, + IbcPost, + TransToken, + Transfer, +> MaspVp<'ctx, CTX, Params, Gov, IbcPre, IbcPost, TransToken, Transfer> where CTX: VpEnv<'ctx> + namada_tx::action::Read + ReadConversionState, Params: parameters::Read<>::Pre>, Gov: governance::Read<>::Pre>, - Ibc: ibc::Read<>::Post>, + IbcPre: ibc::Read<>::Pre>, + IbcPost: ibc::Read<>::Post>, TransToken: trans_token::Keys + trans_token::Read<>::Pre>, Transfer: BorshDeserialize, @@ -370,7 +388,7 @@ where post, } = changed_balances; let ibc::ChangedBalances { decoder, pre, post } = - Ibc::apply_ibc_packet::( + IbcPost::apply_ibc_packet::( &ctx.post(), tx_data, ibc::ChangedBalances { decoder, pre, post }, @@ -406,8 +424,13 @@ where // Try to get the Transaction object from the tx first (IBC) and from // the actions afterwards let shielded_tx = if let Some(tx) = - Ibc::try_extract_masp_tx_from_envelope::(&tx_data)? - { + IbcPre::try_extract_masp_tx_from_envelope::(&tx_data)?.or( + IbcPre::try_get_refund_masp_tx::( + &ctx.pre(), + &tx_data, + masp_epoch, + )?, + ) { tx } else { let masp_section_ref = @@ -931,6 +954,9 @@ mod shielded_token_tests { namada_governance::Store< CtxPreStorageRead<'ctx, 'ctx, S, VpCache, Eval>, >, + namada_ibc::Store< + CtxPreStorageRead<'ctx, 'ctx, S, VpCache, Eval>, + >, namada_ibc::Store< CtxPostStorageRead<'ctx, 'ctx, S, VpCache, Eval>, >, diff --git a/crates/systems/src/ibc.rs b/crates/systems/src/ibc.rs index c84a4304a9..33ca68173b 100644 --- a/crates/systems/src/ibc.rs +++ b/crates/systems/src/ibc.rs @@ -6,7 +6,7 @@ use masp_primitives::transaction::components::ValueSum; use masp_primitives::transaction::TransparentAddress; use namada_core::address::Address; use namada_core::borsh::BorshDeserialize; -use namada_core::masp::TAddrData; +use namada_core::masp::{MaspEpoch, TAddrData}; use namada_core::{masp_primitives, storage, token}; pub use namada_storage::Result; @@ -17,6 +17,13 @@ pub trait Read { tx_data: &[u8], ) -> Result>; + /// Try to read a MASP transaction for the refund + fn try_get_refund_masp_tx( + storage: &S, + tx_data: &[u8], + masp_epoch: MaspEpoch, + ) -> Result>; + /// Apply relevant IBC packets to the changed balances structure fn apply_ibc_packet( storage: &S, diff --git a/crates/tests/src/e2e/ibc_tests.rs b/crates/tests/src/e2e/ibc_tests.rs index 2e63db39f5..fe11fee239 100644 --- a/crates/tests/src/e2e/ibc_tests.rs +++ b/crates/tests/src/e2e/ibc_tests.rs @@ -140,7 +140,7 @@ fn ibc_transfers() -> Result<()> { None, None, None, - false, + None, )?; wait_for_packet_relay( &hermes_dir, @@ -217,7 +217,7 @@ fn ibc_transfers() -> Result<()> { None, None, None, - false, + None, )?; wait_for_packet_relay( &hermes_dir, @@ -299,7 +299,7 @@ fn ibc_transfers() -> Result<()> { None, None, None, - true, + Some(BB_PAYMENT_ADDRESS), )?; wait_for_packet_relay( &hermes_dir, @@ -353,7 +353,7 @@ fn ibc_transfers() -> Result<()> { None, None, None, - false, + None, )?; wait_for_packet_relay( &hermes_dir, @@ -381,7 +381,7 @@ fn ibc_transfers() -> Result<()> { Some(Duration::new(10, 0)), None, None, - false, + None, )?; // wait for the timeout sleep(10); @@ -400,7 +400,7 @@ fn ibc_transfers() -> Result<()> { check_balance(&test, ALBERT, &ibc_denom_on_namada, 100)?; // Unshielding transfer to Gaia's invalid account to check the refund for - // the burned IBC token + // the burned IBC token with a transparent refund target transfer( &test, A_SPENDING_KEY, @@ -413,7 +413,7 @@ fn ibc_transfers() -> Result<()> { None, None, None, - true, + Some(IBC_REFUND_TARGET_ALIAS), )?; wait_for_packet_relay( &hermes_dir, @@ -425,6 +425,31 @@ fn ibc_transfers() -> Result<()> { check_shielded_balance(&test, AA_VIEWING_KEY, &ibc_denom_on_namada, 40)?; check_balance(&test, IBC_REFUND_TARGET_ALIAS, &ibc_denom_on_namada, 10)?; + // Unshielding transfer to Gaia's invalid account to check the refund for + // the burned IBC token with a shielded refund target + transfer( + &test, + A_SPENDING_KEY, + "invalid_receiver", + &ibc_denom_on_namada, + 10, + Some(ALBERT_KEY), + &port_id_namada, + &channel_id_namada, + None, + None, + None, + Some(AA_PAYMENT_ADDRESS), + )?; + wait_for_packet_relay( + &hermes_dir, + &port_id_namada, + &channel_id_namada, + &test, + )?; + // Check the token has been refunded to the source + check_shielded_balance(&test, AA_VIEWING_KEY, &ibc_denom_on_namada, 40)?; + // Stop Hermes for timeout test let mut hermes = bg_hermes.foreground(); hermes.interrupt()?; @@ -443,7 +468,7 @@ fn ibc_transfers() -> Result<()> { Some(Duration::new(10, 0)), None, None, - true, + Some(IBC_REFUND_TARGET_ALIAS), )?; // wait for the timeout sleep(10); @@ -605,7 +630,7 @@ fn ibc_nft_transfers() -> Result<()> { None, None, None, - false, + None, )?; clear_packet(&hermes_dir, &port_id_namada, &channel_id_namada, &test)?; check_balance(&test, &namada_receiver, &ibc_trace_on_namada, 0)?; @@ -668,7 +693,7 @@ fn ibc_nft_transfers() -> Result<()> { None, None, None, - true, + Some(BB_PAYMENT_ADDRESS), )?; clear_packet(&hermes_dir, &port_id_namada, &channel_id_namada, &test)?; check_shielded_balance(&test, AB_VIEWING_KEY, &ibc_trace_on_namada, 0)?; @@ -1110,7 +1135,7 @@ fn ibc_rate_limit() -> Result<()> { None, None, None, - false, + None, )?; // Transfer 1 NAM from Namada to Gaia again will fail @@ -1129,7 +1154,7 @@ fn ibc_rate_limit() -> Result<()> { Some( "Transfer exceeding the per-epoch throughput limit is not allowed", ), - false, + None, )?; // wait for the next epoch @@ -1152,7 +1177,7 @@ fn ibc_rate_limit() -> Result<()> { None, None, None, - false, + None, )?; // wait for the next epoch @@ -1361,7 +1386,7 @@ fn ibc_pfm_happy_flows() -> Result<()> { None, None, None, - false, + None, )?; wait_for_packet_relay( @@ -1652,7 +1677,7 @@ fn ibc_pfm_unhappy_flows() -> Result<()> { None, None, None, - false, + None, )?; wait_for_packet_relay( @@ -2144,7 +2169,7 @@ fn try_invalid_transfers( None, // the IBC denom can't be parsed when using an invalid port Some(&format!("Invalid IBC denom: {nam_addr}")), - false, + None, )?; // invalid channel @@ -2160,7 +2185,7 @@ fn try_invalid_transfers( None, None, Some("IBC token transfer error: context error: `ICS04 Channel error"), - false, + None, )?; Ok(()) @@ -2215,7 +2240,7 @@ fn transfer( timeout_sec: Option, shielding_data_path: Option, expected_err: Option<&str>, - gen_refund_target: bool, + refund_target: Option<&str>, ) -> Result { let rpc = get_actor_rpc(test, Who::Validator(0)); @@ -2263,22 +2288,12 @@ fn transfer( tx_args.push(&memo); } - if gen_refund_target { - let mut cmd = run!( - test, - Bin::Wallet, - &[ - "gen", - "--alias", - IBC_REFUND_TARGET_ALIAS, - "--alias-force", - "--unsafe-dont-encrypt" - ], - Some(20), - )?; - cmd.assert_success(); + if let Some(refund_target) = refund_target { + if !is_payment_address(test, refund_target)? { + gen_refund_target(test, refund_target)?; + } tx_args.push("--refund-target"); - tx_args.push(IBC_REFUND_TARGET_ALIAS); + tx_args.push(refund_target); } let mut client = run!(test, Bin::Client, tx_args, Some(300))?; @@ -3218,3 +3233,29 @@ fn packet_forward_memo( }) .expect("Test failed") } + +fn gen_refund_target(test: &Test, alias: &str) -> Result<()> { + let mut cmd = run!( + test, + Bin::Wallet, + &[ + "gen", + "--alias", + alias, + "--alias-force", + "--unsafe-dont-encrypt" + ], + Some(20), + )?; + cmd.assert_success(); + Ok(()) +} + +fn is_payment_address(test: &Test, alias: &str) -> Result { + let mut cmd = + run!(test, Bin::Wallet, &["find", "--alias", alias,], Some(20),)?; + let ret = cmd.exp_string("Found payment address:").is_ok(); + cmd.assert_success(); + + Ok(ret) +} From fd6c2d30a721c1115521e652bec73920994e03c5 Mon Sep 17 00:00:00 2001 From: yito88 Date: Thu, 9 Jan 2025 22:45:32 +0100 Subject: [PATCH 17/22] shielded sync retrieves refund masp tx --- crates/ibc/src/context/common.rs | 14 --- crates/ibc/src/lib.rs | 36 ++----- crates/sdk/src/masp.rs | 167 ++++++++++++++++++------------- crates/sdk/src/masp/utilities.rs | 10 +- crates/sdk/src/rpc.rs | 19 ++++ 5 files changed, 135 insertions(+), 111 deletions(-) diff --git a/crates/ibc/src/context/common.rs b/crates/ibc/src/context/common.rs index 38558cad4e..8d088da920 100644 --- a/crates/ibc/src/context/common.rs +++ b/crates/ibc/src/context/common.rs @@ -790,20 +790,6 @@ pub trait IbcCommonContext: IbcStorageContext { .write(&key, masp_tx) .map_err(ContextError::from) } - - /// Delete MASP shielding transactions for the shielded refund - fn delete_refund_masp_txs( - &mut self, - port_id: &PortId, - channel_id: &ChannelId, - sequence: Sequence, - ) -> Result<()> { - let prefix = - storage::refund_masp_tx_prefix(port_id, channel_id, sequence); - self.storage_mut() - .delete_prefix(&prefix) - .map_err(ContextError::from) - } } /// Read and decode the IBC sequence diff --git a/crates/ibc/src/lib.rs b/crates/ibc/src/lib.rs index 0cdf6c7f89..a156a8dcc7 100644 --- a/crates/ibc/src/lib.rs +++ b/crates/ibc/src/lib.rs @@ -712,8 +712,8 @@ fn apply_refund_msg( let delta = ValueSum::from_pair(token, amount); if !is_sender_chain_source(ibc_trace, src_port_id, src_channel_id) { // Enable funds to be taken from the IBC internal address and be - // deposited elsewhere Required for the IBC internal - // Address to release funds + // deposited elsewhere + // Required for the IBC internal address to release funds let ibc_taddr = addr_taddr(address::IBC); let pre_entry = accum .pre @@ -893,7 +893,7 @@ where msg.acknowledgement.as_ref(), ) { Ok(ack) if !ack.is_successful() => { - let mut inner = self.ctx.inner.borrow_mut(); + let inner = self.ctx.inner.borrow_mut(); let epoch = inner .storage() .get_block_epoch() @@ -908,30 +908,20 @@ where masp_epoch_multiplier, ) .map_err(|e| Error::Other(e.to_string()))?; - let refund_masp_tx = inner + inner .refund_masp_tx( &msg.packet.port_id_on_a, &msg.packet.chan_id_on_a, msg.packet.seq_on_a, masp_epoch, ) - .map_err(|e| Error::Context(Box::new(e)))?; - // Delete refund masp txs of the packet - // including, the one for the previous epoch - inner - .delete_refund_masp_txs( - &msg.packet.port_id_on_a, - &msg.packet.chan_id_on_a, - msg.packet.seq_on_a, - ) - .map_err(|e| Error::Context(Box::new(e)))?; - refund_masp_tx + .map_err(|e| Error::Context(Box::new(e)))? } _ => None, } } MsgEnvelope::Packet(PacketMsg::Timeout(msg)) => { - let mut inner = self.ctx.inner.borrow_mut(); + let inner = self.ctx.inner.borrow_mut(); let epoch = inner .storage() .get_block_epoch() @@ -944,24 +934,14 @@ where masp_epoch_multiplier, ) .map_err(|e| Error::Other(e.to_string()))?; - let refund_masp_tx = inner + inner .refund_masp_tx( &msg.packet.port_id_on_a, &msg.packet.chan_id_on_a, msg.packet.seq_on_a, masp_epoch, ) - .map_err(|e| Error::Context(Box::new(e)))?; - // Delete refund masp txs of the packet, including the - // one for the previous epoch - inner - .delete_refund_masp_txs( - &msg.packet.port_id_on_a, - &msg.packet.chan_id_on_a, - msg.packet.seq_on_a, - ) - .map_err(|e| Error::Context(Box::new(e)))?; - refund_masp_tx + .map_err(|e| Error::Context(Box::new(e)))? } _ => None, }; diff --git a/crates/sdk/src/masp.rs b/crates/sdk/src/masp.rs index bbd3becf37..c66de3fbf2 100644 --- a/crates/sdk/src/masp.rs +++ b/crates/sdk/src/masp.rs @@ -16,6 +16,9 @@ use namada_events::extend::{ IndexedMaspData, MaspDataRefs as MaspDataRefsAttr, MaspTxRef, MaspTxRefs, ReadFromEventAttributes, }; +use namada_ibc::core::channel::types::msgs::PacketMsg; +use namada_ibc::core::handler::types::msgs::MsgEnvelope; +use namada_ibc::storage::refund_masp_tx_key; use namada_ibc::{decode_message, extract_masp_tx_from_envelope, IbcMessage}; use namada_io::client::Client; use namada_token::masp::shielded_wallet::ShieldedQueries; @@ -25,17 +28,20 @@ pub use utilities::{IndexerMaspClient, LedgerMaspClient}; use crate::error::{Error, QueryError}; use crate::rpc::{ - query_block, query_conversion, query_denom, query_masp_epoch, - query_max_block_time_estimate, query_native_token, + query_block, query_conversion, query_denom, query_has_storage_key, + query_masp_epoch, query_masp_epoch_at_height, + query_max_block_time_estimate, query_native_token, query_storage_value, }; use crate::{token, MaybeSend, MaybeSync}; /// Extract the relevant shield portions from a [`Tx`] MASP section or an IBC /// message, if any. #[allow(clippy::result_large_err)] -fn extract_masp_tx( +async fn extract_masp_tx( + client: &C, tx: &Tx, masp_refs: &MaspTxRefs, + height: BlockHeight, ) -> Result, Error> { // NOTE: It is possible to have two identical references in a same batch: // this is because, some types of MASP data packet can be correctly executed @@ -44,73 +50,67 @@ fn extract_masp_tx( // and in the returned type): if the same reference shows up multiple // times in the input we must process it the same number of times to // ensure we contruct the correct state - masp_refs - .0 - .iter() - .try_fold(vec![], |mut acc, ref masp_ref| { - match masp_ref { - MaspTxRef::MaspSection(id) => { - // Simply looking for masp sections attached to the tx - // is not safe. We don't validate the sections attached to a - // transaction se we could end up with transactions carrying - // an unnecessary masp section. We must instead look for the - // required masp sections published in the events - let transaction = tx - .get_masp_section(id) - .ok_or_else(|| { - Error::Other(format!( - "Missing expected masp transaction with id \ - {id}" - )) - })? - .clone(); - acc.push(transaction); - - Ok(acc) - } - MaspTxRef::IbcData(hash) => { - // Dereference the masp ref to the first instance that - // matches is, even if it is not the exact one that produced - // the event, the data we extract will be exactly the same - let masp_ibc_tx = tx - .commitments() - .iter() - .find(|cmt| cmt.data_sechash() == hash) - .ok_or_else(|| { - Error::Other(format!( - "Couldn't find data section with hash {hash}" - )) - })?; - let tx_data = tx.data(masp_ibc_tx).ok_or_else(|| { - Error::Other( - "Missing expected data section".to_string(), - ) + let mut acc = vec![]; + for masp_ref in &masp_refs.0 { + match masp_ref { + MaspTxRef::MaspSection(ref id) => { + // Simply looking for masp sections attached to the tx + // is not safe. We don't validate the sections attached to a + // transaction se we could end up with transactions carrying + // an unnecessary masp section. We must instead look for the + // required masp sections published in the events + let transaction = tx + .get_masp_section(id) + .ok_or_else(|| { + Error::Other(format!( + "Missing expected masp transaction with id {id}" + )) + })? + .clone(); + acc.push(transaction); + } + MaspTxRef::IbcData(hash) => { + // Dereference the masp ref to the first instance that + // matches is, even if it is not the exact one that produced + // the event, the data we extract will be exactly the same + let masp_ibc_tx = tx + .commitments() + .iter() + .find(|cmt| cmt.data_sechash() == hash) + .ok_or_else(|| { + Error::Other(format!( + "Couldn't find data section with hash {hash}" + )) })?; + let tx_data = tx.data(masp_ibc_tx).ok_or_else(|| { + Error::Other("Missing expected data section".to_string()) + })?; - let IbcMessage::Envelope(envelope) = - decode_message::(&tx_data) - .map_err(|e| Error::Other(e.to_string()))? - else { - return Err(Error::Other( - "Expected IBC packet to be an envelope".to_string(), - )); - }; - - if let Some(transaction) = - extract_masp_tx_from_envelope(&envelope) - { - acc.push(transaction); - - Ok(acc) - } else { - Err(Error::Other( - "Failed to retrieve MASP over IBC transaction" - .to_string(), - )) - } - } + let IbcMessage::Envelope(envelope) = + decode_message::(&tx_data) + .map_err(|e| Error::Other(e.to_string()))? + else { + return Err(Error::Other( + "Expected IBC packet to be an envelope".to_string(), + )); + }; + + if let Some(transaction) = + extract_masp_tx_from_envelope(&envelope) + .or(get_refund_masp_tx(client, height, &envelope) + .await?) + { + acc.push(transaction); + } else { + return Err(Error::Other( + "Failed to retrieve MASP over IBC transaction" + .to_string(), + )); + }; } - }) + } + } + Ok(acc) } // Retrieves all the indexes at the specified height which refer @@ -138,6 +138,39 @@ async fn get_indexed_masp_events_at_height( .unwrap_or_default()) } +async fn get_refund_masp_tx( + client: &C, + height: BlockHeight, + envelope: &MsgEnvelope, +) -> Result, Error> { + let Some(masp_epoch) = query_masp_epoch_at_height(client, height).await? + else { + return Ok(None); + }; + + let (port_id, channel_id, sequence) = match envelope { + MsgEnvelope::Packet(PacketMsg::Ack(msg)) => ( + &msg.packet.port_id_on_a, + &msg.packet.chan_id_on_a, + msg.packet.seq_on_a, + ), + MsgEnvelope::Packet(PacketMsg::Timeout(msg)) => ( + &msg.packet.port_id_on_a, + &msg.packet.chan_id_on_a, + msg.packet.seq_on_a, + ), + _ => return Ok(None), + }; + + let key = refund_masp_tx_key(port_id, channel_id, sequence, masp_epoch); + if query_has_storage_key(client, &key).await? { + let tx = query_storage_value(client, &key).await?; + Ok(Some(tx)) + } else { + Ok(None) + } +} + /// An implementation of a shielded wallet /// along with methods for interacting with a node #[derive(Default, Debug)] diff --git a/crates/sdk/src/masp/utilities.rs b/crates/sdk/src/masp/utilities.rs index 47be9bfbae..2015a60a2a 100644 --- a/crates/sdk/src/masp/utilities.rs +++ b/crates/sdk/src/masp/utilities.rs @@ -119,8 +119,14 @@ impl LedgerMaspClient { let tx = Tx::try_from_bytes(block[tx_index.0 as usize].as_ref()) .map_err(|e| Error::Other(e.to_string()))?; - let extracted_masp_txs = extract_masp_tx(&tx, &masp_refs) - .map_err(|e| Error::Other(e.to_string()))?; + let extracted_masp_txs = extract_masp_tx( + &self.inner.client, + &tx, + &masp_refs, + height.into(), + ) + .await + .map_err(|e| Error::Other(e.to_string()))?; index_txs( &mut txs, diff --git a/crates/sdk/src/rpc.rs b/crates/sdk/src/rpc.rs index 2e9792b61c..ed101ef86d 100644 --- a/crates/sdk/src/rpc.rs +++ b/crates/sdk/src/rpc.rs @@ -185,6 +185,25 @@ pub async fn query_epoch_at_height( convert_response::(RPC.shell().epoch_at_height(client, &height).await) } +/// Query the MASP epoch of the given block height, if it exists. +/// Will return none if the input block height is greater than +/// the latest committed block height. +pub async fn query_masp_epoch_at_height( + client: &C, + height: BlockHeight, +) -> Result, error::Error> { + let Some(epoch) = query_epoch_at_height(client, height).await? else { + return Ok(None); + }; + + let key = params_storage::get_masp_epoch_multiplier_key(); + let multiplier: u64 = query_storage_value(client, &key).await?; + + let masp_epoch = MaspEpoch::try_from_epoch(epoch, multiplier) + .map_err(|e| error::Error::Other(e.to_string()))?; + Ok(Some(masp_epoch)) +} + /// Query the last committed block, if any. pub async fn query_block( client: &C, From 882ff5f4a2b8ca1136c5b2f54f6ce861bbde5b78 Mon Sep 17 00:00:00 2001 From: yito88 Date: Fri, 10 Jan 2025 11:42:32 +0100 Subject: [PATCH 18/22] packet info --- crates/ibc/src/lib.rs | 37 +++++++++++++------------------------ crates/ibc/src/msg.rs | 17 ++++++++++++++++- crates/sdk/src/masp.rs | 22 ++++++++-------------- 3 files changed, 37 insertions(+), 39 deletions(-) diff --git a/crates/ibc/src/lib.rs b/crates/ibc/src/lib.rs index a156a8dcc7..02ff718b12 100644 --- a/crates/ibc/src/lib.rs +++ b/crates/ibc/src/lib.rs @@ -253,36 +253,25 @@ where tx_data: &[u8], masp_epoch: MaspEpoch, ) -> StorageResult> { - let msg = decode_message::(tx_data) - .into_storage_result() - .ok(); // refund only when ack or timeout in an IBC envelope message - let Some(IbcMessage::Envelope(envelope)) = msg else { + let Some(IbcMessage::Envelope(envelope)) = + decode_message::(tx_data) + .into_storage_result() + .ok() + else { return Ok(None); }; - let packet_info = match &*envelope { - MsgEnvelope::Packet(PacketMsg::Ack(msg)) => Some(( - &msg.packet.port_id_on_a, - &msg.packet.chan_id_on_a, - msg.packet.seq_on_a, - )), - MsgEnvelope::Packet(PacketMsg::Timeout(msg)) => Some(( - &msg.packet.port_id_on_a, - &msg.packet.chan_id_on_a, - msg.packet.seq_on_a, - )), - _ => None, + let Some((port_id, channel_id, sequence)) = + packet_info_from_envelope(&envelope) + else { + return Ok(None); }; - if let Some((port_id, channel_id, sequence)) = packet_info { - let key = storage::refund_masp_tx_key( - port_id, channel_id, sequence, masp_epoch, - ); - storage.read(&key) - } else { - Ok(None) - } + let key = storage::refund_masp_tx_key( + port_id, channel_id, sequence, masp_epoch, + ); + storage.read(&key) } fn apply_ibc_packet( diff --git a/crates/ibc/src/msg.rs b/crates/ibc/src/msg.rs index 1c3dc10b46..f2a913ec8d 100644 --- a/crates/ibc/src/msg.rs +++ b/crates/ibc/src/msg.rs @@ -12,7 +12,7 @@ use ibc::apps::transfer::types::PORT_ID_STR as FT_PORT_ID_STR; use ibc::core::channel::types::msgs::PacketMsg; use ibc::core::channel::types::packet::Packet; use ibc::core::handler::types::msgs::MsgEnvelope; -use ibc::core::host::types::identifiers::PortId; +use ibc::core::host::types::identifiers::{ChannelId, PortId, Sequence}; use ibc::primitives::proto::Protobuf; use masp_primitives::transaction::Transaction as MaspTransaction; use namada_core::borsh::BorshSerializeExt; @@ -173,6 +173,21 @@ pub fn extract_masp_tx_from_envelope( } } +/// Get the port ID, channel ID and sequence of the packet in the envelope. The +/// envelope doesn't have a packet, returns None. +pub fn packet_info_from_envelope( + envelope: &MsgEnvelope, +) -> Option<(&PortId, &ChannelId, Sequence)> { + let packet = match envelope { + MsgEnvelope::Packet(PacketMsg::Recv(msg)) => &msg.packet, + MsgEnvelope::Packet(PacketMsg::Ack(msg)) => &msg.packet, + MsgEnvelope::Packet(PacketMsg::Timeout(msg)) => &msg.packet, + MsgEnvelope::Packet(PacketMsg::TimeoutOnClose(msg)) => &msg.packet, + _ => return None, + }; + Some((&packet.port_id_on_a, &packet.chan_id_on_a, packet.seq_on_a)) +} + /// Decode IBC shielding data from the string pub fn decode_ibc_shielding_data( s: impl AsRef, diff --git a/crates/sdk/src/masp.rs b/crates/sdk/src/masp.rs index c66de3fbf2..4c9947bc11 100644 --- a/crates/sdk/src/masp.rs +++ b/crates/sdk/src/masp.rs @@ -16,10 +16,12 @@ use namada_events::extend::{ IndexedMaspData, MaspDataRefs as MaspDataRefsAttr, MaspTxRef, MaspTxRefs, ReadFromEventAttributes, }; -use namada_ibc::core::channel::types::msgs::PacketMsg; use namada_ibc::core::handler::types::msgs::MsgEnvelope; use namada_ibc::storage::refund_masp_tx_key; -use namada_ibc::{decode_message, extract_masp_tx_from_envelope, IbcMessage}; +use namada_ibc::{ + decode_message, extract_masp_tx_from_envelope, packet_info_from_envelope, + IbcMessage, +}; use namada_io::client::Client; use namada_token::masp::shielded_wallet::ShieldedQueries; pub use namada_token::masp::{utils, *}; @@ -148,18 +150,10 @@ async fn get_refund_masp_tx( return Ok(None); }; - let (port_id, channel_id, sequence) = match envelope { - MsgEnvelope::Packet(PacketMsg::Ack(msg)) => ( - &msg.packet.port_id_on_a, - &msg.packet.chan_id_on_a, - msg.packet.seq_on_a, - ), - MsgEnvelope::Packet(PacketMsg::Timeout(msg)) => ( - &msg.packet.port_id_on_a, - &msg.packet.chan_id_on_a, - msg.packet.seq_on_a, - ), - _ => return Ok(None), + let Some((port_id, channel_id, sequence)) = + packet_info_from_envelope(envelope) + else { + return Ok(None); }; let key = refund_masp_tx_key(port_id, channel_id, sequence, masp_epoch); From a9fec3ee446aedbc27ae9286c8a90373fc302508 Mon Sep 17 00:00:00 2001 From: yito88 Date: Fri, 10 Jan 2025 12:54:41 +0100 Subject: [PATCH 19/22] nft shielded refund --- crates/benches/native_vps.rs | 12 +++- crates/ibc/src/context/nft_transfer.rs | 2 +- crates/ibc/src/context/nft_transfer_mod.rs | 79 ++++++++++++++++++---- crates/ibc/src/context/transfer_mod.rs | 17 +++-- crates/ibc/src/lib.rs | 57 ++++++++-------- crates/ibc/src/msg.rs | 3 +- crates/ibc/src/vp/mod.rs | 5 +- crates/tx_prelude/src/ibc.rs | 5 +- 8 files changed, 121 insertions(+), 59 deletions(-) diff --git a/crates/benches/native_vps.rs b/crates/benches/native_vps.rs index 9caa909e1c..04c666b368 100644 --- a/crates/benches/native_vps.rs +++ b/crates/benches/native_vps.rs @@ -1729,7 +1729,11 @@ fn ibc_vp_validate_action(c: &mut Criterion) { verifiers, ); actions.add_transfer_module(module); - let module = NftTransferModule::<_, token::Store<()>>::new(ctx); + let module = NftTransferModule::< + _, + parameters::Store<_>, + token::Store<()>, + >::new(ctx); actions.add_transfer_module(module); group.bench_function(bench_name, |b| { @@ -1793,7 +1797,11 @@ fn ibc_vp_execute_action(c: &mut Criterion) { verifiers, ); actions.add_transfer_module(module); - let module = NftTransferModule::<_, token::Store<()>>::new(ctx); + let module = NftTransferModule::< + _, + parameters::Store<_>, + token::Store<()>, + >::new(ctx); actions.add_transfer_module(module); group.bench_function(bench_name, |b| { diff --git a/crates/ibc/src/context/nft_transfer.rs b/crates/ibc/src/context/nft_transfer.rs index d2c50e90b1..af5304d0e9 100644 --- a/crates/ibc/src/context/nft_transfer.rs +++ b/crates/ibc/src/context/nft_transfer.rs @@ -27,7 +27,7 @@ pub struct NftTransferContext where C: IbcCommonContext, { - inner: Rc>, + pub(crate) inner: Rc>, is_shielded: bool, _marker: PhantomData, } diff --git a/crates/ibc/src/context/nft_transfer_mod.rs b/crates/ibc/src/context/nft_transfer_mod.rs index b8450468ce..9c631e8796 100644 --- a/crates/ibc/src/context/nft_transfer_mod.rs +++ b/crates/ibc/src/context/nft_transfer_mod.rs @@ -2,6 +2,7 @@ use std::cell::RefCell; use std::fmt::Debug; +use std::marker::PhantomData; use std::rc::Rc; use ibc::apps::nft_transfer::context::NftTransferValidationContext; @@ -17,8 +18,11 @@ use ibc::apps::nft_transfer::module::{ on_timeout_packet_validate, }; use ibc::apps::nft_transfer::types::error::NftTransferError; +use ibc::apps::nft_transfer::types::packet::PacketData; use ibc::apps::nft_transfer::types::MODULE_ID_STR; -use ibc::core::channel::types::acknowledgement::Acknowledgement; +use ibc::core::channel::types::acknowledgement::{ + Acknowledgement, AcknowledgementStatus, +}; use ibc::core::channel::types::channel::{Counterparty, Order}; use ibc::core::channel::types::error::{ChannelError, PacketError}; use ibc::core::channel::types::packet::Packet; @@ -27,38 +31,43 @@ use ibc::core::host::types::identifiers::{ChannelId, ConnectionId, PortId}; use ibc::core::router::module::Module; use ibc::core::router::types::module::{ModuleExtras, ModuleId}; use ibc::primitives::Signer; +use namada_core::address::MASP; use namada_systems::trans_token; -use super::common::IbcCommonContext; -use super::nft_transfer::NftTransferContext; -use super::transfer_mod::ModuleWrapper; +use crate::context::transfer_mod::ModuleWrapper; +use crate::{IbcCommonContext, IbcStorageContext, NftTransferContext}; /// IBC module for NFT transfer #[derive(Debug)] -pub struct NftTransferModule +pub struct NftTransferModule where C: IbcCommonContext, { /// IBC actions pub ctx: NftTransferContext, + _marker: PhantomData, } -impl NftTransferModule +impl NftTransferModule where C: IbcCommonContext, + Params: namada_systems::parameters::Read<::Storage>, Token: trans_token::Keys, { /// Make a new module pub fn new(ctx: Rc>) -> Self { Self { ctx: NftTransferContext::new(ctx), + _marker: PhantomData, } } } -impl ModuleWrapper for NftTransferModule +impl ModuleWrapper for NftTransferModule where C: IbcCommonContext + Debug, + Params: namada_systems::parameters::Read<::Storage> + + Debug, Token: trans_token::Keys + Debug, { fn as_module(&self) -> &dyn Module { @@ -78,9 +87,11 @@ where } } -impl Module for NftTransferModule +impl Module for NftTransferModule where C: IbcCommonContext + Debug, + Params: namada_systems::parameters::Read<::Storage> + + Debug, Token: trans_token::Keys + Debug, { #[allow(clippy::too_many_arguments)] @@ -286,12 +297,52 @@ where acknowledgement: &Acknowledgement, relayer: &Signer, ) -> (ModuleExtras, Result<(), PacketError>) { - let (extras, result) = on_acknowledgement_packet_execute( - &mut self.ctx, - packet, - acknowledgement, - relayer, - ); + let updated_packet = serde_json::from_slice::( + acknowledgement.as_ref(), + ) + .ok() + .and_then(|ack| { + if ack.is_successful() { + return None; + } + let masp_epoch = crate::get_masp_epoch::< + ::Storage, + Params, + >(self.ctx.inner.borrow().storage()) + .ok()?; + self.ctx + .inner + .borrow() + .refund_masp_tx( + &packet.port_id_on_a, + &packet.chan_id_on_a, + packet.seq_on_a, + masp_epoch, + ) + .ok()??; + let mut data: PacketData = + serde_json::from_slice(&packet.data).ok()?; + data.sender = Signer::from(MASP.to_string()); + let mut packet = packet.clone(); + packet.data = serde_json::to_vec(&data) + .expect("Packet data should be encoded"); + Some(packet) + }); + + let (extras, result) = match updated_packet { + Some(packet) => on_acknowledgement_packet_execute( + &mut self.ctx, + &packet, + acknowledgement, + relayer, + ), + None => on_acknowledgement_packet_execute( + &mut self.ctx, + packet, + acknowledgement, + relayer, + ), + }; (extras, result.map_err(into_packet_error)) } diff --git a/crates/ibc/src/context/transfer_mod.rs b/crates/ibc/src/context/transfer_mod.rs index 98b5dc685e..67cd97a3fa 100644 --- a/crates/ibc/src/context/transfer_mod.rs +++ b/crates/ibc/src/context/transfer_mod.rs @@ -33,8 +33,6 @@ use ibc::core::router::module::Module; use ibc::core::router::types::module::{ModuleExtras, ModuleId}; use ibc::primitives::Signer; use namada_core::address::{Address, MASP}; -use namada_core::masp::MaspEpoch; -use namada_state::StorageRead; use crate::{IbcCommonContext, IbcStorageContext, TokenTransferContext}; @@ -321,13 +319,14 @@ where if ack.is_successful() { return None; } - let inner = self.ctx.inner.borrow(); - let epoch = inner.storage().get_block_epoch().ok()?; - let masp_epoch_multiplier = - Params::masp_epoch_multiplier(inner.storage()).ok()?; - let masp_epoch = - MaspEpoch::try_from_epoch(epoch, masp_epoch_multiplier).ok()?; - inner + let masp_epoch = crate::get_masp_epoch::< + ::Storage, + Params, + >(self.ctx.inner.borrow().storage()) + .ok()?; + self.ctx + .inner + .borrow() .refund_masp_tx( &packet.port_id_on_a, &packet.chan_id_on_a, diff --git a/crates/ibc/src/lib.rs b/crates/ibc/src/lib.rs index 02ff718b12..f30d1673cb 100644 --- a/crates/ibc/src/lib.rs +++ b/crates/ibc/src/lib.rs @@ -882,22 +882,16 @@ where msg.acknowledgement.as_ref(), ) { Ok(ack) if !ack.is_successful() => { - let inner = self.ctx.inner.borrow_mut(); - let epoch = inner - .storage() - .get_block_epoch() - .map_err(Error::Storage)?; - let masp_epoch_multiplier = - Params::masp_epoch_multiplier( - inner.storage(), - ) - .map_err(Error::Storage)?; - let masp_epoch = MaspEpoch::try_from_epoch( - epoch, - masp_epoch_multiplier, + let masp_epoch = get_masp_epoch::< + ::Storage, + Params, + >( + self.ctx.inner.borrow().storage(), ) - .map_err(|e| Error::Other(e.to_string()))?; - inner + .map_err(Error::Storage)?; + self.ctx + .inner + .borrow() .refund_masp_tx( &msg.packet.port_id_on_a, &msg.packet.chan_id_on_a, @@ -910,20 +904,16 @@ where } } MsgEnvelope::Packet(PacketMsg::Timeout(msg)) => { - let inner = self.ctx.inner.borrow_mut(); - let epoch = inner - .storage() - .get_block_epoch() - .map_err(Error::Storage)?; - let masp_epoch_multiplier = - Params::masp_epoch_multiplier(inner.storage()) - .map_err(Error::Storage)?; - let masp_epoch = MaspEpoch::try_from_epoch( - epoch, - masp_epoch_multiplier, + let masp_epoch = get_masp_epoch::< + ::Storage, + Params, + >( + self.ctx.inner.borrow().storage() ) - .map_err(|e| Error::Other(e.to_string()))?; - inner + .map_err(Error::Storage)?; + self.ctx + .inner + .borrow() .refund_masp_tx( &msg.packet.port_id_on_a, &msg.packet.chan_id_on_a, @@ -1178,6 +1168,17 @@ pub fn get_last_sequence_send( Ok(checked!(next_seq - 1)?.into()) } +fn get_masp_epoch(storage: &S) -> Result +where + S: StorageRead, + Params: namada_systems::parameters::Read, +{ + let epoch = storage.get_block_epoch()?; + let masp_epoch_multiplier = Params::masp_epoch_multiplier(storage)?; + MaspEpoch::try_from_epoch(epoch, masp_epoch_multiplier) + .map_err(StorageError::new_const) +} + fn received_ibc_trace( base_trace: impl AsRef, src_port_id: &PortId, diff --git a/crates/ibc/src/msg.rs b/crates/ibc/src/msg.rs index f2a913ec8d..429c0814c4 100644 --- a/crates/ibc/src/msg.rs +++ b/crates/ibc/src/msg.rs @@ -173,8 +173,7 @@ pub fn extract_masp_tx_from_envelope( } } -/// Get the port ID, channel ID and sequence of the packet in the envelope. The -/// envelope doesn't have a packet, returns None. +/// Get the port ID, channel ID and sequence of the packet in the envelope pub fn packet_info_from_envelope( envelope: &MsgEnvelope, ) -> Option<(&PortId, &ChannelId, Sequence)> { diff --git a/crates/ibc/src/vp/mod.rs b/crates/ibc/src/vp/mod.rs index c779464228..76dec53be3 100644 --- a/crates/ibc/src/vp/mod.rs +++ b/crates/ibc/src/vp/mod.rs @@ -254,7 +254,8 @@ where verifiers, ); actions.add_transfer_module(module); - let module = NftTransferModule::<_, Token>::new(ctx.clone()); + let module = + NftTransferModule::<_, ParamsPseudo, Token>::new(ctx.clone()); actions.add_transfer_module(module); // Charge gas for the expensive execution self.ctx.charge_gas(IBC_ACTION_EXECUTE_GAS.into())?; @@ -310,7 +311,7 @@ where let module = create_transfer_middlewares::<_, Params>(ctx.clone(), verifiers); actions.add_transfer_module(module); - let module = NftTransferModule::<_, Token>::new(ctx); + let module = NftTransferModule::<_, Params, Token>::new(ctx); actions.add_transfer_module(module); // Charge gas for the expensive validation self.ctx.charge_gas(IBC_ACTION_VALIDATE_GAS.into())?; diff --git a/crates/tx_prelude/src/ibc.rs b/crates/tx_prelude/src/ibc.rs index 25e2b27267..fc07716c89 100644 --- a/crates/tx_prelude/src/ibc.rs +++ b/crates/tx_prelude/src/ibc.rs @@ -36,7 +36,10 @@ pub fn ibc_actions( verifiers, ); actions.add_transfer_module(module); - let module = NftTransferModule::>::new(ctx); + let module = + NftTransferModule::<_, parameters::Store, token::Store>::new( + ctx, + ); actions.add_transfer_module(module); actions } From f5f0db4df2493151203f5377b83062467f81d442 Mon Sep 17 00:00:00 2001 From: yito88 Date: Fri, 10 Jan 2025 23:20:54 +0100 Subject: [PATCH 20/22] refund when timeout --- crates/ibc/src/context/nft_transfer_mod.rs | 42 +++++------ crates/ibc/src/context/transfer_mod.rs | 43 +++++------- crates/ibc/src/lib.rs | 47 ++++++++++++- crates/tests/src/e2e/ibc_tests.rs | 81 ++++++++++++++++++---- 4 files changed, 149 insertions(+), 64 deletions(-) diff --git a/crates/ibc/src/context/nft_transfer_mod.rs b/crates/ibc/src/context/nft_transfer_mod.rs index 9c631e8796..9233be1632 100644 --- a/crates/ibc/src/context/nft_transfer_mod.rs +++ b/crates/ibc/src/context/nft_transfer_mod.rs @@ -18,7 +18,6 @@ use ibc::apps::nft_transfer::module::{ on_timeout_packet_validate, }; use ibc::apps::nft_transfer::types::error::NftTransferError; -use ibc::apps::nft_transfer::types::packet::PacketData; use ibc::apps::nft_transfer::types::MODULE_ID_STR; use ibc::core::channel::types::acknowledgement::{ Acknowledgement, AcknowledgementStatus, @@ -31,11 +30,13 @@ use ibc::core::host::types::identifiers::{ChannelId, ConnectionId, PortId}; use ibc::core::router::module::Module; use ibc::core::router::types::module::{ModuleExtras, ModuleId}; use ibc::primitives::Signer; -use namada_core::address::MASP; use namada_systems::trans_token; use crate::context::transfer_mod::ModuleWrapper; -use crate::{IbcCommonContext, IbcStorageContext, NftTransferContext}; +use crate::{ + try_replace_sender_for_shielded_refund, IbcCommonContext, + IbcStorageContext, NftTransferContext, +}; /// IBC module for NFT transfer #[derive(Debug)] @@ -305,28 +306,10 @@ where if ack.is_successful() { return None; } - let masp_epoch = crate::get_masp_epoch::< + try_replace_sender_for_shielded_refund::< ::Storage, Params, - >(self.ctx.inner.borrow().storage()) - .ok()?; - self.ctx - .inner - .borrow() - .refund_masp_tx( - &packet.port_id_on_a, - &packet.chan_id_on_a, - packet.seq_on_a, - masp_epoch, - ) - .ok()??; - let mut data: PacketData = - serde_json::from_slice(&packet.data).ok()?; - data.sender = Signer::from(MASP.to_string()); - let mut packet = packet.clone(); - packet.data = serde_json::to_vec(&data) - .expect("Packet data should be encoded"); - Some(packet) + >(self.ctx.inner.borrow().storage(), packet) }); let (extras, result) = match updated_packet { @@ -360,8 +343,17 @@ where packet: &Packet, relayer: &Signer, ) -> (ModuleExtras, Result<(), PacketError>) { - let (extras, result) = - on_timeout_packet_execute(&mut self.ctx, packet, relayer); + let updated_packet = + try_replace_sender_for_shielded_refund::< + ::Storage, + Params, + >(self.ctx.inner.borrow().storage(), packet); + + let (extras, result) = if let Some(packet) = updated_packet { + on_timeout_packet_execute(&mut self.ctx, &packet, relayer) + } else { + on_timeout_packet_execute(&mut self.ctx, packet, relayer) + }; (extras, result.map_err(into_packet_error)) } } diff --git a/crates/ibc/src/context/transfer_mod.rs b/crates/ibc/src/context/transfer_mod.rs index 67cd97a3fa..640d99129c 100644 --- a/crates/ibc/src/context/transfer_mod.rs +++ b/crates/ibc/src/context/transfer_mod.rs @@ -19,7 +19,6 @@ use ibc::apps::transfer::module::{ on_timeout_packet_validate, }; use ibc::apps::transfer::types::error::TokenTransferError; -use ibc::apps::transfer::types::packet::PacketData; use ibc::apps::transfer::types::MODULE_ID_STR; use ibc::core::channel::types::acknowledgement::{ Acknowledgement, AcknowledgementStatus, @@ -32,9 +31,12 @@ use ibc::core::host::types::identifiers::{ChannelId, ConnectionId, PortId}; use ibc::core::router::module::Module; use ibc::core::router::types::module::{ModuleExtras, ModuleId}; use ibc::primitives::Signer; -use namada_core::address::{Address, MASP}; +use namada_core::address::Address; -use crate::{IbcCommonContext, IbcStorageContext, TokenTransferContext}; +use crate::{ + try_replace_sender_for_shielded_refund, IbcCommonContext, + IbcStorageContext, TokenTransferContext, +}; /// IBC module wrapper for getting the reference of the module pub trait ModuleWrapper: Module { @@ -319,28 +321,10 @@ where if ack.is_successful() { return None; } - let masp_epoch = crate::get_masp_epoch::< + try_replace_sender_for_shielded_refund::< ::Storage, Params, - >(self.ctx.inner.borrow().storage()) - .ok()?; - self.ctx - .inner - .borrow() - .refund_masp_tx( - &packet.port_id_on_a, - &packet.chan_id_on_a, - packet.seq_on_a, - masp_epoch, - ) - .ok()??; - let mut data: PacketData = - serde_json::from_slice(&packet.data).ok()?; - data.sender = Signer::from(MASP.to_string()); - let mut packet = packet.clone(); - packet.data = serde_json::to_vec(&data) - .expect("Packet data should be encoded"); - Some(packet) + >(self.ctx.inner.borrow().storage(), packet) }); let (extras, result) = match updated_packet { @@ -374,8 +358,17 @@ where packet: &Packet, relayer: &Signer, ) -> (ModuleExtras, Result<(), PacketError>) { - let (extras, result) = - on_timeout_packet_execute(&mut self.ctx, packet, relayer); + let updated_packet = + try_replace_sender_for_shielded_refund::< + ::Storage, + Params, + >(self.ctx.inner.borrow().storage(), packet); + + let (extras, result) = if let Some(packet) = updated_packet { + on_timeout_packet_execute(&mut self.ctx, &packet, relayer) + } else { + on_timeout_packet_execute(&mut self.ctx, packet, relayer) + }; (extras, result.map_err(into_packet_error)) } } diff --git a/crates/ibc/src/lib.rs b/crates/ibc/src/lib.rs index f30d1673cb..8ee5468e04 100644 --- a/crates/ibc/src/lib.rs +++ b/crates/ibc/src/lib.rs @@ -69,6 +69,7 @@ use ibc::core::channel::types::commitment::compute_ack_commitment; use ibc::core::channel::types::msgs::{ MsgRecvPacket as IbcMsgRecvPacket, PacketMsg, }; +use ibc::core::channel::types::packet::Packet; use ibc::core::channel::types::timeout::{TimeoutHeight, TimeoutTimestamp}; use ibc::core::entrypoint::{execute, validate}; use ibc::core::handler::types::error::ContextError; @@ -252,7 +253,7 @@ where storage: &S, tx_data: &[u8], masp_epoch: MaspEpoch, - ) -> StorageResult> { + ) -> StorageResult> { // refund only when ack or timeout in an IBC envelope message let Some(IbcMessage::Envelope(envelope)) = decode_message::(tx_data) @@ -1299,6 +1300,50 @@ fn retrieve_nft_data( Ok(message) } +/// Replace the sender address with the MASP address for a shielded refund +fn try_replace_sender_for_shielded_refund( + storage: &S, + packet: &Packet, +) -> Option +where + S: StorageRead, + Params: namada_systems::parameters::Read, +{ + // Check if the refund MASP transaction for the current MASP epoch exists + let masp_epoch = get_masp_epoch::(storage).ok()?; + let refund_masp_tx_key = storage::refund_masp_tx_key( + &packet.port_id_on_a, + &packet.chan_id_on_a, + packet.seq_on_a, + masp_epoch, + ); + if !storage.has_key(&refund_masp_tx_key).ok()? { + // The refund target is a transparent address or the MASP epoch in the + // MASP transaction is stale. The refund target is the sender. + return None; + } + + let mut packet = packet.clone(); + match packet.port_id_on_a.as_str() { + FT_PORT_ID_STR => { + let mut data: PacketData = + serde_json::from_slice(&packet.data).ok()?; + data.sender = address::MASP.to_string().into(); + packet.data = serde_json::to_vec(&data) + .expect("Packet data should be encoded"); + } + NFT_PORT_ID_STR => { + let mut data: NftPacketData = + serde_json::from_slice(&packet.data).ok()?; + data.sender = address::MASP.to_string().into(); + packet.data = serde_json::to_vec(&data) + .expect("Packet data should be encoded"); + } + _ => return None, + } + Some(packet) +} + /// Initialize storage in the genesis block. pub fn init_genesis_storage(storage: &mut S) where diff --git a/crates/tests/src/e2e/ibc_tests.rs b/crates/tests/src/e2e/ibc_tests.rs index fe11fee239..e0343e2a39 100644 --- a/crates/tests/src/e2e/ibc_tests.rs +++ b/crates/tests/src/e2e/ibc_tests.rs @@ -400,7 +400,7 @@ fn ibc_transfers() -> Result<()> { check_balance(&test, ALBERT, &ibc_denom_on_namada, 100)?; // Unshielding transfer to Gaia's invalid account to check the refund for - // the burned IBC token with a transparent refund target + // the burned IBC token with a shielded refund target transfer( &test, A_SPENDING_KEY, @@ -413,7 +413,7 @@ fn ibc_transfers() -> Result<()> { None, None, None, - Some(IBC_REFUND_TARGET_ALIAS), + Some(AA_PAYMENT_ADDRESS), )?; wait_for_packet_relay( &hermes_dir, @@ -421,12 +421,11 @@ fn ibc_transfers() -> Result<()> { &channel_id_namada, &test, )?; - // Check the token has been refunded to the refund target - check_shielded_balance(&test, AA_VIEWING_KEY, &ibc_denom_on_namada, 40)?; - check_balance(&test, IBC_REFUND_TARGET_ALIAS, &ibc_denom_on_namada, 10)?; + // Check the token has been refunded to the source + check_shielded_balance(&test, AA_VIEWING_KEY, &ibc_denom_on_namada, 50)?; // Unshielding transfer to Gaia's invalid account to check the refund for - // the burned IBC token with a shielded refund target + // the burned IBC token with a transparent refund target transfer( &test, A_SPENDING_KEY, @@ -439,7 +438,7 @@ fn ibc_transfers() -> Result<()> { None, None, None, - Some(AA_PAYMENT_ADDRESS), + Some(IBC_REFUND_TARGET_ALIAS), )?; wait_for_packet_relay( &hermes_dir, @@ -447,15 +446,52 @@ fn ibc_transfers() -> Result<()> { &channel_id_namada, &test, )?; - // Check the token has been refunded to the source + // Check the token has been refunded to the refund target check_shielded_balance(&test, AA_VIEWING_KEY, &ibc_denom_on_namada, 40)?; + check_balance(&test, IBC_REFUND_TARGET_ALIAS, &ibc_denom_on_namada, 10)?; // Stop Hermes for timeout test let mut hermes = bg_hermes.foreground(); hermes.interrupt()?; // Unshielding transfer will be timed out to check the refund for the - // escrowed IBC token + // escrowed IBC token with a shielded refund target + transfer( + &test, + A_SPENDING_KEY, + &gaia_receiver, + APFEL, + 1, + Some(ALBERT_KEY), + &port_id_namada, + &channel_id_namada, + Some(Duration::new(10, 0)), + None, + None, + Some(AA_PAYMENT_ADDRESS), + )?; + // wait for the timeout + sleep(10); + + // Restart relaying + let hermes = run_hermes(&hermes_dir)?; + let bg_hermes = hermes.background(); + + wait_for_packet_relay( + &hermes_dir, + &port_id_namada, + &channel_id_namada, + &test, + )?; + // Check the token has been refunded to the refund target + check_shielded_balance(&test, AA_VIEWING_KEY, APFEL, 1)?; + + // Stop Hermes for timeout test + let mut hermes = bg_hermes.foreground(); + hermes.interrupt()?; + + // Unshielding transfer will be timed out to check the refund for the + // escrowed IBC token with a transparent refund target transfer( &test, A_SPENDING_KEY, @@ -680,11 +716,12 @@ fn ibc_nft_transfers() -> Result<()> { check_shielded_balance(&test, AA_VIEWING_KEY, &ibc_trace_on_namada, 0)?; check_shielded_balance(&test, AB_VIEWING_KEY, &ibc_trace_on_namada, 1)?; - // Unshielding transfer + // Unshielding transfer to an invalid receiver + // Refund the NFT to another shielded account transfer( &test, B_SPENDING_KEY, - &minter_addr, + "invalid_receiver", &ibc_trace_on_namada, 1, Some(BERTHA_KEY), @@ -693,10 +730,28 @@ fn ibc_nft_transfers() -> Result<()> { None, None, None, - Some(BB_PAYMENT_ADDRESS), + Some(AC_PAYMENT_ADDRESS), + )?; + clear_packet(&hermes_dir, &port_id_namada, &channel_id_namada, &test)?; + check_shielded_balance(&test, AC_VIEWING_KEY, &ibc_trace_on_namada, 1)?; + + // Unshielding transfer + transfer( + &test, + C_SPENDING_KEY, + &minter_addr, + &ibc_trace_on_namada, + 1, + Some(CHRISTEL_KEY), + &port_id_namada, + &channel_id_namada, + None, + None, + None, + Some(AC_PAYMENT_ADDRESS), )?; clear_packet(&hermes_dir, &port_id_namada, &channel_id_namada, &test)?; - check_shielded_balance(&test, AB_VIEWING_KEY, &ibc_trace_on_namada, 0)?; + check_shielded_balance(&test, AC_VIEWING_KEY, &ibc_trace_on_namada, 0)?; Ok(()) } From b4933828a470993b423d7f3140cd5e14f045e61c Mon Sep 17 00:00:00 2001 From: yito88 Date: Mon, 13 Jan 2025 11:33:07 +0100 Subject: [PATCH 21/22] clean packet parsing --- crates/ibc/src/lib.rs | 223 ++++++++++++++++-------------------------- 1 file changed, 83 insertions(+), 140 deletions(-) diff --git a/crates/ibc/src/lib.rs b/crates/ibc/src/lib.rs index 8ee5468e04..dc901cd9f4 100644 --- a/crates/ibc/src/lib.rs +++ b/crates/ibc/src/lib.rs @@ -227,6 +227,59 @@ impl TryFrom for IbcTransferInfo { } } +struct ReceiveInfo { + ibc_traces: Vec, + amount: Amount, + receiver: String, +} + +fn recv_info_from_packet( + packet: &Packet, + is_src_chain: bool, +) -> Result { + let port_id = if is_src_chain { + &packet.port_id_on_a + } else { + &packet.port_id_on_b + }; + match port_id.as_str() { + FT_PORT_ID_STR => { + let packet_data = + serde_json::from_slice::(&packet.data) + .into_storage_result()?; + let receiver = packet_data.receiver.to_string(); + let ibc_denom = packet_data.token.denom.to_string(); + let amount = + packet_data.token.amount.try_into().into_storage_result()?; + Ok(ReceiveInfo { + ibc_traces: vec![ibc_denom], + amount, + receiver, + }) + } + NFT_PORT_ID_STR => { + let packet_data = + serde_json::from_slice::(&packet.data) + .map_err(StorageError::new)?; + let receiver = packet_data.receiver.to_string(); + let ibc_traces = packet_data + .token_ids + .0 + .iter() + .map(|token_id| { + ibc_trace_for_nft(&packet_data.class_id, token_id) + }) + .collect(); + Ok(ReceiveInfo { + ibc_traces, + amount: Amount::from_u64(1), + receiver, + }) + } + _ => Err(StorageError::new_const("Invalid packet port: {packet}")), + } +} + /// IBC storage `Keys/Read/Write` implementation #[derive(Debug)] pub struct Store(PhantomData); @@ -317,150 +370,40 @@ where } Some(IbcMessage::Envelope(envelope)) => match *envelope { MsgEnvelope::Packet(PacketMsg::Recv(msg)) => { - let recv_info = match msg.packet.port_id_on_b.as_str() { - FT_PORT_ID_STR => { - let packet_data = - serde_json::from_slice::( - &msg.packet.data, - ) - .map_err(StorageError::new)?; - let receiver = packet_data.receiver.to_string(); - let ibc_denom = packet_data.token.denom.to_string(); - let amount = packet_data - .token - .amount - .try_into() - .into_storage_result()?; - Some((receiver, vec![ibc_denom], amount)) - } - NFT_PORT_ID_STR => { - let packet_data = - serde_json::from_slice::( - &msg.packet.data, - ) - .map_err(StorageError::new)?; - let receiver = packet_data.receiver.to_string(); - let ibc_traces = packet_data - .token_ids - .0 - .iter() - .map(|token_id| { - ibc_trace_for_nft( - &packet_data.class_id, - token_id, - ) - }) - .collect(); - Some((receiver, ibc_traces, Amount::from_u64(1))) - } - _ => None, - }; - if let Some((receiver, ibc_traces, amount)) = recv_info { - let addr = TAddrData::Ibc(receiver.clone()); - accum.decoder.insert(ibc_taddr(receiver), addr); - accum = apply_recv_msg( - storage, - accum, - &msg, - ibc_traces, - amount, - keys_changed, - )?; - } + let recv_info = recv_info_from_packet(&msg.packet, false) + .map_err(StorageError::new)?; + let addr = TAddrData::Ibc(recv_info.receiver.clone()); + accum.decoder.insert(ibc_taddr(recv_info.receiver), addr); + accum = apply_recv_msg( + storage, + accum, + &msg, + recv_info.ibc_traces, + recv_info.amount, + keys_changed, + )?; } MsgEnvelope::Packet(PacketMsg::Ack(msg)) => { - let refund_info = match msg.packet.port_id_on_a.as_str() { - FT_PORT_ID_STR => { - let packet_data = - serde_json::from_slice::( - &msg.packet.data, - ) - .map_err(StorageError::new)?; - let ibc_denom = packet_data.token.denom.to_string(); - let amount = packet_data - .token - .amount - .try_into() - .into_storage_result()?; - Some((vec![ibc_denom], amount)) - } - NFT_PORT_ID_STR => { - let packet_data = - serde_json::from_slice::( - &msg.packet.data, - ) - .map_err(StorageError::new)?; - let ibc_traces = packet_data - .token_ids - .0 - .iter() - .map(|token_id| { - ibc_trace_for_nft( - &packet_data.class_id, - token_id, - ) - }) - .collect(); - Some((ibc_traces, Amount::from_u64(1))) - } - _ => None, - }; - if let Some((ibc_traces, amount)) = refund_info { - accum = apply_refund_msg( - accum, - &msg.packet.port_id_on_a, - &msg.packet.chan_id_on_a, - ibc_traces, - amount, - )?; - } + let refund_info = recv_info_from_packet(&msg.packet, true) + .map_err(StorageError::new)?; + accum = apply_refund_msg( + accum, + &msg.packet.port_id_on_a, + &msg.packet.chan_id_on_a, + refund_info.ibc_traces, + refund_info.amount, + )?; } MsgEnvelope::Packet(PacketMsg::Timeout(msg)) => { - let refund_info = match msg.packet.port_id_on_a.as_str() { - FT_PORT_ID_STR => { - let packet_data = - serde_json::from_slice::( - &msg.packet.data, - ) - .map_err(StorageError::new)?; - let ibc_denom = packet_data.token.denom.to_string(); - let amount = packet_data - .token - .amount - .try_into() - .into_storage_result()?; - Some((vec![ibc_denom], amount)) - } - NFT_PORT_ID_STR => { - let packet_data = - serde_json::from_slice::( - &msg.packet.data, - ) - .map_err(StorageError::new)?; - let ibc_traces = packet_data - .token_ids - .0 - .iter() - .map(|token_id| { - ibc_trace_for_nft( - &packet_data.class_id, - token_id, - ) - }) - .collect(); - Some((ibc_traces, Amount::from_u64(1))) - } - _ => None, - }; - if let Some((ibc_traces, amount)) = refund_info { - accum = apply_refund_msg( - accum, - &msg.packet.port_id_on_a, - &msg.packet.chan_id_on_a, - ibc_traces, - amount, - )?; - } + let refund_info = recv_info_from_packet(&msg.packet, true) + .map_err(StorageError::new)?; + accum = apply_refund_msg( + accum, + &msg.packet.port_id_on_a, + &msg.packet.chan_id_on_a, + refund_info.ibc_traces, + refund_info.amount, + )?; } _ => {} }, From 9ced9743f1a6b745f2ecca87c80ac4ec56a2f5af Mon Sep 17 00:00:00 2001 From: yito88 Date: Mon, 13 Jan 2025 17:01:12 +0100 Subject: [PATCH 22/22] changelog --- .changelog/unreleased/features/4168-ibc-shielded-refund.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changelog/unreleased/features/4168-ibc-shielded-refund.md diff --git a/.changelog/unreleased/features/4168-ibc-shielded-refund.md b/.changelog/unreleased/features/4168-ibc-shielded-refund.md new file mode 100644 index 0000000000..354f68ffc2 --- /dev/null +++ b/.changelog/unreleased/features/4168-ibc-shielded-refund.md @@ -0,0 +1,2 @@ +- Support a shielded address for the refund target when IBC transfer failure or + timeout ([\#4168](https://github.com/anoma/namada/issues/4168)) \ No newline at end of file