diff --git a/.circleci/config.yml b/.circleci/config.yml index a21a30f6a5..ec1a0648b5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -77,6 +77,7 @@ workflows: - contract_empty # - contract_floaty # This contract needs nightly Rust to compile - contract_hackatom + - contract_ibc_callbacks - contract_ibc_reflect - contract_ibc_reflect_send - contract_queue @@ -653,6 +654,36 @@ jobs: - target/wasm32-unknown-unknown/release/deps key: cargocache-v2-contract_hackatom-rust:1.73-{{ checksum "Cargo.lock" }} + contract_ibc_callbacks: + docker: + - image: rust:1.73 + environment: + RUST_BACKTRACE: 1 + working_directory: ~/cosmwasm/contracts/ibc-callbacks + steps: + - checkout: + path: ~/cosmwasm + - run: + name: Version information + command: rustc --version; cargo --version; rustup --version + - restore_cache: + keys: + - cargocache-v2-contract_ibc_callbacks-rust:1.73-{{ checksum "Cargo.lock" }} + # TODO: Enable this once 2.1 has been released to crates.io + - check_contract: + min_version: "2.1" + skip_cosmwasm_check: true + - save_cache: + paths: + - /usr/local/cargo/registry + - target/debug/.fingerprint + - target/debug/build + - target/debug/deps + - target/wasm32-unknown-unknown/release/.fingerprint + - target/wasm32-unknown-unknown/release/build + - target/wasm32-unknown-unknown/release/deps + key: cargocache-v2-contract_ibc_callbacks-rust:1.73-{{ checksum "Cargo.lock" }} + contract_ibc_reflect: docker: - image: rust:1.73 diff --git a/CHANGELOG.md b/CHANGELOG.md index 01c5b3fcb5..0c31c742fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,8 +41,13 @@ and this project adheres to `bls12_381_pairing_equality`, `bls12_381_hash_to_g1`, and `bls12_381_hash_to_g2` to enable BLS12-381 curve operations, such as verifying pairing equalities ([#2106]) +- cosmwasm-std: Add IBC Callbacks support, including two new entrypoints + `ibc_source_callback` and `ibc_destination_callback`, as well as the + `IbcCallbackRequest` type. ([#2025]) +- cosmwasm-vm: Add support for the two new IBC Callbacks entrypoints. ([#2025]) [#1983]: https://github.com/CosmWasm/cosmwasm/pull/1983 +[#2025]: https://github.com/CosmWasm/cosmwasm/pull/2025 [#2057]: https://github.com/CosmWasm/cosmwasm/pull/2057 [#2058]: https://github.com/CosmWasm/cosmwasm/pull/2058 [#2068]: https://github.com/CosmWasm/cosmwasm/pull/2068 diff --git a/contracts/ibc-callbacks/.cargo/config b/contracts/ibc-callbacks/.cargo/config new file mode 100644 index 0000000000..f5174787c2 --- /dev/null +++ b/contracts/ibc-callbacks/.cargo/config @@ -0,0 +1,6 @@ +[alias] +wasm = "build --release --lib --target wasm32-unknown-unknown" +wasm-debug = "build --lib --target wasm32-unknown-unknown" +unit-test = "test --lib" +integration-test = "test --test integration" +schema = "run --bin schema" diff --git a/contracts/ibc-callbacks/Cargo.lock b/contracts/ibc-callbacks/Cargo.lock new file mode 100644 index 0000000000..e7176f96b1 --- /dev/null +++ b/contracts/ibc-callbacks/Cargo.lock @@ -0,0 +1,2268 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli 0.28.1", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[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 = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + +[[package]] +name = "ark-bls12-381" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c775f0d12169cba7aae4caeb547bb6a50781c7449a8aa53793827c9ec4abf488" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools", + "num-traits", + "rayon", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest", + "itertools", + "num-bigint", + "num-traits", + "paste", + "rayon", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand", + "rayon", +] + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bech32" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bnum" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e31ea183f6ee62ac8b8a8cf7feddd766317adfb13ff469de57ce033efd6a790" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" + +[[package]] +name = "cc" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clru" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbd0f76e066e64fdc5631e3bb46381254deab9ef1158292f27c8c57e3bf3fe59" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "corosensei" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80128832c58ea9cbd041d2a759ec449224487b2c1e400453d99d244eead87a8e" +dependencies = [ + "autocfg", + "cfg-if", + "libc", + "scopeguard", + "windows-sys 0.33.0", +] + +[[package]] +name = "cosmwasm-core" +version = "2.0.1" +dependencies = [ + "base64", + "bnum", + "cosmwasm-crypto", + "derive_more", + "hex", + "schemars", + "serde", + "sha2", + "static_assertions", + "thiserror", +] + +[[package]] +name = "cosmwasm-crypto" +version = "2.0.1" +dependencies = [ + "ark-bls12-381", + "ark-ec", + "ark-ff", + "ark-serialize", + "cfg-if", + "derive_more", + "digest", + "ecdsa", + "ed25519-zebra", + "k256", + "num-traits", + "p256", + "rand_core", + "rayon", + "sha2", + "thiserror", +] + +[[package]] +name = "cosmwasm-derive" +version = "2.0.1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "cosmwasm-schema" +version = "2.0.1" +dependencies = [ + "cosmwasm-schema-derive", + "schemars", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cosmwasm-schema-derive" +version = "2.0.1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "cosmwasm-std" +version = "2.0.1" +dependencies = [ + "base64", + "bech32", + "cosmwasm-core", + "cosmwasm-crypto", + "cosmwasm-derive", + "derive_more", + "hex", + "rand_core", + "schemars", + "serde", + "serde-json-wasm", + "sha2", + "thiserror", +] + +[[package]] +name = "cosmwasm-vm" +version = "2.0.1" +dependencies = [ + "bech32", + "bytes", + "clru", + "cosmwasm-crypto", + "cosmwasm-std", + "crc32fast", + "derivative", + "hex", + "rand_core", + "schemars", + "serde", + "serde_json", + "sha2", + "strum", + "thiserror", + "tracing", + "wasmer", + "wasmer-middlewares", +] + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "cranelift-bforest" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2ab4512dfd3a6f4be184403a195f76e81a8a9f9e6c898e19d2dc3ce20e0115" +dependencies = [ + "cranelift-entity", +] + +[[package]] +name = "cranelift-codegen" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98b022ed2a5913a38839dfbafe6cf135342661293b08049843362df4301261dc" +dependencies = [ + "arrayvec", + "bumpalo", + "cranelift-bforest", + "cranelift-codegen-meta", + "cranelift-codegen-shared", + "cranelift-egraph", + "cranelift-entity", + "cranelift-isle", + "gimli 0.26.2", + "log", + "regalloc2", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "639307b45434ad112a98f8300c0f0ab085cbefcd767efcdef9ef19d4c0756e74" +dependencies = [ + "cranelift-codegen-shared", +] + +[[package]] +name = "cranelift-codegen-shared" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "278e52e29c53fcf32431ef08406c295699a70306d05a0715c5b1bf50e33a9ab7" + +[[package]] +name = "cranelift-egraph" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624b54323b06e675293939311943ba82d323bb340468ce1889be5da7932c8d73" +dependencies = [ + "cranelift-entity", + "fxhash", + "hashbrown 0.12.3", + "indexmap 1.9.3", + "log", + "smallvec", +] + +[[package]] +name = "cranelift-entity" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a59bcbca89c3f1b70b93ab3cbba5e5e0cbf3e63dadb23c7525cb142e21a9d4c" + +[[package]] +name = "cranelift-frontend" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d70abacb8cfef3dc8ff7e8836e9c1d70f7967dfdac824a4cd5e30223415aca6" +dependencies = [ + "cranelift-codegen", + "log", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-isle" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "393bc73c451830ff8dbb3a07f61843d6cb41a084f9996319917c0b291ed785bb" + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "platforms", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "darling" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "darling_macro" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "1.0.0-beta.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7abbfc297053be59290e3152f8cbcd52c8642e0728b69ee187d991d4c1af08d" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0-beta.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bba3e9872d7c58ce7ef0fcf1844fcc3e23ef2a58377b50df35dd98e42a5726e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", + "unicode-xid", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "dynasm" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "add9a102807b524ec050363f09e06f1504214b0e1c7797f64261c891022dce8b" +dependencies = [ + "bitflags 1.3.2", + "byteorder", + "lazy_static", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "dynasmrt" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64fba5a42bd76a17cad4bfa00de168ee1cbfa06a5e8ce992ae880218c05641a9" +dependencies = [ + "byteorder", + "dynasm", + "memmap2 0.5.10", +] + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "signature", +] + +[[package]] +name = "ed25519-zebra" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d9ce6874da5d4415896cd45ffbc4d1cfc0c4f9c079427bd870742c30f2f65a9" +dependencies = [ + "curve25519-dalek", + "ed25519", + "hashbrown 0.14.5", + "hex", + "rand_core", + "sha2", + "zeroize", +] + +[[package]] +name = "either" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "enum-iterator" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eeac5c5edb79e4e39fe8439ef35207780a11f69c52cbe424ce3dfad4cb78de6" +dependencies = [ + "enum-iterator-derive", +] + +[[package]] +name = "enum-iterator-derive" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c134c37760b27a871ba422106eedbb8247da973a09e82558bf26d619c882b159" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "enumset" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "226c0da7462c13fb57e5cc9e0dc8f0635e7d27f276a3a7fd30054647f669007d" +dependencies = [ + "enumset_derive", +] + +[[package]] +name = "enumset_derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" +dependencies = [ + "fallible-iterator", + "indexmap 1.9.3", + "stable_deref_trait", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash 0.7.8", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash 0.8.11", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash 0.8.11", + "allocator-api2", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "ibc-callbacks" +version = "0.0.0" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cosmwasm-vm", + "schemars", + "serde", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown 0.14.5", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "k256" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "sha2", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "mach" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +dependencies = [ + "libc", +] + +[[package]] +name = "mach2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +dependencies = [ + "libc", +] + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + +[[package]] +name = "memmap2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d28bba84adfe6646737845bc5ebbfa2c08424eb1c37e94a1fd2a82adb56a872" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +dependencies = [ + "adler", +] + +[[package]] +name = "more-asserts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389" + +[[package]] +name = "num-bigint" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "platforms" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43" +dependencies = [ + "unicode-ident", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +dependencies = [ + "bitflags 2.5.0", +] + +[[package]] +name = "regalloc2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300d4fbfb40c1c66a78ba3ddd41c1110247cf52f97b87d0f2fc9209bd49b030c" +dependencies = [ + "fxhash", + "log", + "slice-group-by", + "smallvec", +] + +[[package]] +name = "region" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6b6ebd13bc009aef9cd476c1310d49ac354d36e240cf1bd753290f3dc7199a7" +dependencies = [ + "bitflags 1.3.2", + "libc", + "mach2", + "windows-sys 0.52.0", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "rkyv" +version = "0.7.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cba464629b3394fc4dbc6f940ff8f5b4ff5c7aef40f29166fd4ad12acbc99c0" +dependencies = [ + "bitvec", + "bytecheck", + "bytes", + "hashbrown 0.12.3", + "indexmap 1.9.3", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.7.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7dddfff8de25e6f62b9d64e6e432bf1c6736c57d20323e15ee10435fbda7c65" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "schemars" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0218ceea14babe24a4a5836f86ade86c1effbc198164e619194cb5069187e29" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed5a1ccce8ff962e31a165d41f6e2a2dd1245099dc4d594f5574a86cd90f4d3" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.65", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "subtle", + "zeroize", +] + +[[package]] +name = "self_cell" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.202" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-json-wasm" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05da0d153dd4595bdffd5099dc0e9ce425b205ee648eb93437ff7302af8c9a5" +dependencies = [ + "serde", +] + +[[package]] +name = "serde-wasm-bindgen" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "serde_derive" +version = "1.0.202" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "serde_json" +version = "1.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shared-buffer" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6c99835bad52957e7aa241d3975ed17c1e5f8c92026377d117a606f36b84b16" +dependencies = [ + "bytes", + "memmap2 0.6.2", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + +[[package]] +name = "simdutf8" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" + +[[package]] +name = "slice-group-by" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strum" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.65", +] + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2863d96a84c6439701d7a38f9de935ec562c8832cc55d1dde0f513b52fad106" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "target-lexicon" +version = "0.12.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" + +[[package]] +name = "thiserror" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "uuid" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.65", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "wasmer" +version = "4.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c15724dc25d1ee57962334aea8e41ade2675e5ea2ac6b8d42da6051b0face66" +dependencies = [ + "bytes", + "cfg-if", + "derivative", + "indexmap 1.9.3", + "js-sys", + "more-asserts", + "rustc-demangle", + "serde", + "serde-wasm-bindgen", + "shared-buffer", + "target-lexicon", + "thiserror", + "tracing", + "wasm-bindgen", + "wasmer-compiler", + "wasmer-compiler-cranelift", + "wasmer-compiler-singlepass", + "wasmer-derive", + "wasmer-types", + "wasmer-vm", + "winapi", +] + +[[package]] +name = "wasmer-compiler" +version = "4.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55a7f3b3a96f8d844c25e2c032af9572306dd63fa93dc17bcca4c5458ac569bd" +dependencies = [ + "backtrace", + "bytes", + "cfg-if", + "enum-iterator", + "enumset", + "lazy_static", + "leb128", + "memmap2 0.5.10", + "more-asserts", + "region", + "rkyv", + "self_cell", + "shared-buffer", + "smallvec", + "thiserror", + "wasmer-types", + "wasmer-vm", + "wasmparser", + "winapi", +] + +[[package]] +name = "wasmer-compiler-cranelift" +version = "4.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "102e2c5bacac69495c4025767e2fa26797ffb27f242dccb7cf57d9cefd944386" +dependencies = [ + "cranelift-codegen", + "cranelift-entity", + "cranelift-frontend", + "gimli 0.26.2", + "more-asserts", + "rayon", + "smallvec", + "target-lexicon", + "tracing", + "wasmer-compiler", + "wasmer-types", +] + +[[package]] +name = "wasmer-compiler-singlepass" +version = "4.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2071db9b993508dac72d12f7a9372e0c095fbdc173e0009c4b75886bed4a855e" +dependencies = [ + "byteorder", + "dynasm", + "dynasmrt", + "enumset", + "gimli 0.26.2", + "lazy_static", + "more-asserts", + "rayon", + "smallvec", + "wasmer-compiler", + "wasmer-types", +] + +[[package]] +name = "wasmer-derive" +version = "4.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea737fa08f95d6abc4459f42a70a9833e8974b814e74971d77ef473814f4d4c" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "wasmer-middlewares" +version = "4.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0346ed39c185c1c5c1094e6c0271d798276a34f80e1e5576bcb2e32fa2e7f05a" +dependencies = [ + "wasmer", + "wasmer-types", + "wasmer-vm", +] + +[[package]] +name = "wasmer-types" +version = "4.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0689110e291b0f07fc665f2824e5ff81df120848e8a9acfbf1a9bf7990773f9" +dependencies = [ + "bytecheck", + "enum-iterator", + "enumset", + "indexmap 1.9.3", + "more-asserts", + "rkyv", + "target-lexicon", + "thiserror", +] + +[[package]] +name = "wasmer-vm" +version = "4.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd41f822a1ac4242d478754e8ceba2806a00ea5072803622e1fe91e8e28b2a1" +dependencies = [ + "backtrace", + "cc", + "cfg-if", + "corosensei", + "crossbeam-queue", + "dashmap", + "derivative", + "enum-iterator", + "fnv", + "indexmap 1.9.3", + "lazy_static", + "libc", + "mach", + "memoffset", + "more-asserts", + "region", + "scopeguard", + "thiserror", + "wasmer-types", + "winapi", +] + +[[package]] +name = "wasmparser" +version = "0.121.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dbe55c8f9d0dbd25d9447a5a889ff90c0cc3feaa7395310d3d826b2c703eaab" +dependencies = [ + "bitflags 2.5.0", + "indexmap 2.2.6", + "semver", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43dbb096663629518eb1dfa72d80243ca5a6aca764cae62a2df70af760a9be75" +dependencies = [ + "windows_aarch64_msvc 0.33.0", + "windows_i686_gnu 0.33.0", + "windows_i686_msvc 0.33.0", + "windows_x86_64_gnu 0.33.0", + "windows_x86_64_msvc 0.33.0", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.52.5", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd761fd3eb9ab8cc1ed81e56e567f02dd82c4c837e48ac3b2181b9ffc5060807" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab0cf703a96bab2dc0c02c0fa748491294bf9b7feb27e1f4f96340f208ada0e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cfdbe89cc9ad7ce618ba34abc34bbb6c36d99e96cae2245b7943cd75ee773d0" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4dd9b0c0e9ece7bb22e84d70d01b71c6d6248b81a3c60d11869451b4cb24784" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff1e4aa646495048ec7f3ffddc411e1d829c026a2ec62b39da15c1055e406eaa" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "zerocopy" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] diff --git a/contracts/ibc-callbacks/Cargo.toml b/contracts/ibc-callbacks/Cargo.toml new file mode 100644 index 0000000000..f45204c680 --- /dev/null +++ b/contracts/ibc-callbacks/Cargo.toml @@ -0,0 +1,37 @@ +[package] +name = "ibc-callbacks" +version = "0.0.0" +authors = ["Christoph Otter "] +edition = "2021" +publish = false +license = "Apache-2.0" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[profile.release] +opt-level = 3 +debug = false +rpath = false +lto = true +debug-assertions = false +codegen-units = 1 +panic = 'abort' +incremental = false +overflow-checks = true + +[features] +default = [] +# Use cranelift backend instead of singlepass. +cranelift = ["cosmwasm-vm/cranelift"] + +[dependencies] +cosmwasm-schema = { path = "../../packages/schema" } +cosmwasm-std = { path = "../../packages/std", features = ["iterator", "stargate"] } +schemars = "0.8.3" +serde = { version = "1.0.103", default-features = false, features = ["derive"] } + +[dev-dependencies] +cosmwasm-vm = { path = "../../packages/vm", default-features = false, features = ["iterator", "stargate"] } diff --git a/contracts/ibc-callbacks/README.md b/contracts/ibc-callbacks/README.md new file mode 100644 index 0000000000..e2435dc1dc --- /dev/null +++ b/contracts/ibc-callbacks/README.md @@ -0,0 +1,8 @@ +# IBC Callbacks Contract + +This is a simple contract to demonstrate [IBC Callbacks]. It sends an ICS-20 +transfer message to a remote chain and writes to storage which callbacks were +called. This can then be queried using the `CallbackStats` query. + +[ibc callbacks]: + https://github.com/cosmos/ibc-go/blob/main/docs/architecture/adr-008-app-caller-cbs.md diff --git a/contracts/ibc-callbacks/schema/ibc-callbacks.json b/contracts/ibc-callbacks/schema/ibc-callbacks.json new file mode 100644 index 0000000000..eb38638e78 --- /dev/null +++ b/contracts/ibc-callbacks/schema/ibc-callbacks.json @@ -0,0 +1,343 @@ +{ + "contract_name": "ibc-callbacks", + "contract_version": "0.0.0", + "idl_version": "1.0.0", + "instantiate": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "InstantiateMsg", + "description": "An empty struct that serves as a placeholder in different places, such as contracts that don't set a custom message.\n\nIt is designed to be expressable in correct JSON and JSON Schema but contains no meaningful data. Previously we used enums without cases, but those cannot represented as valid JSON Schema (https://github.com/CosmWasm/cosmwasm/issues/451)", + "type": "object", + "additionalProperties": false + }, + "execute": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ExecuteMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "transfer" + ], + "properties": { + "transfer": { + "type": "object", + "required": [ + "channel_id", + "timeout_seconds", + "to_address" + ], + "properties": { + "callback_type": { + "description": "Who should receive callbacks for the message", + "default": "both", + "allOf": [ + { + "$ref": "#/definitions/CallbackType" + } + ] + }, + "channel_id": { + "description": "The channel to send the packet through", + "type": "string" + }, + "timeout_seconds": { + "description": "The amount of seconds from now the transfer should timeout at", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "to_address": { + "description": "Address on the destination chain", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ], + "definitions": { + "CallbackType": { + "oneOf": [ + { + "description": "Only this contract on the source chain should receive callbacks", + "type": "string", + "enum": [ + "src" + ] + }, + { + "description": "Only the destination address should receive callbacks", + "type": "string", + "enum": [ + "dst" + ] + }, + { + "description": "Both the source contract and the destination address should receive callbacks", + "type": "string", + "enum": [ + "both" + ] + } + ] + } + } + }, + "query": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsg", + "oneOf": [ + { + "description": "Returns stats about what callbacks have been received", + "type": "object", + "required": [ + "callback_stats" + ], + "properties": { + "callback_stats": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] + }, + "migrate": null, + "sudo": null, + "responses": { + "callback_stats": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "CallbackStats", + "description": "A counter for the number of times the respective callback has been called", + "type": "object", + "required": [ + "ibc_ack_callbacks", + "ibc_destination_callbacks", + "ibc_timeout_callbacks" + ], + "properties": { + "ibc_ack_callbacks": { + "type": "array", + "items": { + "$ref": "#/definitions/IbcAckCallbackMsg" + } + }, + "ibc_destination_callbacks": { + "type": "array", + "items": { + "$ref": "#/definitions/IbcDestinationCallbackMsg" + } + }, + "ibc_timeout_callbacks": { + "type": "array", + "items": { + "$ref": "#/definitions/IbcTimeoutCallbackMsg" + } + } + }, + "additionalProperties": false, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "Binary": { + "description": "Binary is a wrapper around Vec to add base64 de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is only needed as serde-json-{core,wasm} has a horrible encoding for Vec. See also .", + "type": "string" + }, + "IbcAckCallbackMsg": { + "type": "object", + "required": [ + "acknowledgement", + "original_packet", + "relayer" + ], + "properties": { + "acknowledgement": { + "$ref": "#/definitions/IbcAcknowledgement" + }, + "original_packet": { + "$ref": "#/definitions/IbcPacket" + }, + "relayer": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + }, + "IbcAcknowledgement": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/definitions/Binary" + } + }, + "additionalProperties": false + }, + "IbcDestinationCallbackMsg": { + "description": "The message type of the IBC destination callback.\n\nThe IBC destination callback is needed for cases where someone triggers the sending of an IBC packet through some other message (i.e. not through [`crate::IbcMsg::SendPacket`]) and your contract needs to know that it received this. A prominent example is the [`crate::IbcMsg::Transfer`] message. Without callbacks, you cannot know that someone sent you IBC coins.\n\nIt is important to validate that the packet and acknowledgement are what you expect them to be. For example for a transfer message, the receiver is not necessarily the contract itself.\n\nThe callback is called after the packet was acknowledged on the destination chain, as follows: - If the acknowledgement is synchronous (i.e. returned immediately when the packet is received), the callback is called only if the acknowledgement was successful. - If the acknowledgement is asynchronous (i.e. written later using `WriteAcknowledgement`), the callback is called regardless of the success of the acknowledgement.\n\nNote that there are some prerequisites that need to be fulfilled to receive destination callbacks: - The contract must implement the `ibc_destination_callback` entrypoint. - The IBC application in the destination chain must have support for the callbacks middleware. - You have to add serialized [`IbcCallbackRequest`] to a specific field of the message. For `IbcMsg::Transfer`, this is the `memo` field and it needs to be json-encoded.", + "type": "object", + "required": [ + "ack", + "packet" + ], + "properties": { + "ack": { + "$ref": "#/definitions/IbcAcknowledgement" + }, + "packet": { + "$ref": "#/definitions/IbcPacket" + } + }, + "additionalProperties": false + }, + "IbcEndpoint": { + "type": "object", + "required": [ + "channel_id", + "port_id" + ], + "properties": { + "channel_id": { + "type": "string" + }, + "port_id": { + "type": "string" + } + }, + "additionalProperties": false + }, + "IbcPacket": { + "type": "object", + "required": [ + "data", + "dest", + "sequence", + "src", + "timeout" + ], + "properties": { + "data": { + "description": "The raw data sent from the other side in the packet", + "allOf": [ + { + "$ref": "#/definitions/Binary" + } + ] + }, + "dest": { + "description": "identifies the channel and port on the receiving chain.", + "allOf": [ + { + "$ref": "#/definitions/IbcEndpoint" + } + ] + }, + "sequence": { + "description": "The sequence number of the packet on the given channel", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "src": { + "description": "identifies the channel and port on the sending chain.", + "allOf": [ + { + "$ref": "#/definitions/IbcEndpoint" + } + ] + }, + "timeout": { + "$ref": "#/definitions/IbcTimeout" + } + }, + "additionalProperties": false + }, + "IbcTimeout": { + "description": "In IBC each package must set at least one type of timeout: the timestamp or the block height. Using this rather complex enum instead of two timeout fields we ensure that at least one timeout is set.", + "type": "object", + "properties": { + "block": { + "anyOf": [ + { + "$ref": "#/definitions/IbcTimeoutBlock" + }, + { + "type": "null" + } + ] + }, + "timestamp": { + "anyOf": [ + { + "$ref": "#/definitions/Timestamp" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + }, + "IbcTimeoutBlock": { + "description": "IBCTimeoutHeight Height is a monotonically increasing data type that can be compared against another Height for the purposes of updating and freezing clients. Ordering is (revision_number, timeout_height)", + "type": "object", + "required": [ + "height", + "revision" + ], + "properties": { + "height": { + "description": "block height after which the packet times out. the height within the given revision", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "revision": { + "description": "the version that the client is currently on (e.g. after resetting the chain this could increment 1 as height drops to 0)", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "IbcTimeoutCallbackMsg": { + "type": "object", + "required": [ + "packet", + "relayer" + ], + "properties": { + "packet": { + "$ref": "#/definitions/IbcPacket" + }, + "relayer": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Uint64": { + "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", + "type": "string" + } + } + } + } +} diff --git a/contracts/ibc-callbacks/schema/raw/execute.json b/contracts/ibc-callbacks/schema/raw/execute.json new file mode 100644 index 0000000000..e5bed95bb4 --- /dev/null +++ b/contracts/ibc-callbacks/schema/raw/execute.json @@ -0,0 +1,76 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "ExecuteMsg", + "oneOf": [ + { + "type": "object", + "required": [ + "transfer" + ], + "properties": { + "transfer": { + "type": "object", + "required": [ + "channel_id", + "timeout_seconds", + "to_address" + ], + "properties": { + "callback_type": { + "description": "Who should receive callbacks for the message", + "default": "both", + "allOf": [ + { + "$ref": "#/definitions/CallbackType" + } + ] + }, + "channel_id": { + "description": "The channel to send the packet through", + "type": "string" + }, + "timeout_seconds": { + "description": "The amount of seconds from now the transfer should timeout at", + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "to_address": { + "description": "Address on the destination chain", + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + ], + "definitions": { + "CallbackType": { + "oneOf": [ + { + "description": "Only this contract on the source chain should receive callbacks", + "type": "string", + "enum": [ + "src" + ] + }, + { + "description": "Only the destination address should receive callbacks", + "type": "string", + "enum": [ + "dst" + ] + }, + { + "description": "Both the source contract and the destination address should receive callbacks", + "type": "string", + "enum": [ + "both" + ] + } + ] + } + } +} diff --git a/contracts/ibc-callbacks/schema/raw/instantiate.json b/contracts/ibc-callbacks/schema/raw/instantiate.json new file mode 100644 index 0000000000..d7966224ed --- /dev/null +++ b/contracts/ibc-callbacks/schema/raw/instantiate.json @@ -0,0 +1,7 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "InstantiateMsg", + "description": "An empty struct that serves as a placeholder in different places, such as contracts that don't set a custom message.\n\nIt is designed to be expressable in correct JSON and JSON Schema but contains no meaningful data. Previously we used enums without cases, but those cannot represented as valid JSON Schema (https://github.com/CosmWasm/cosmwasm/issues/451)", + "type": "object", + "additionalProperties": false +} diff --git a/contracts/ibc-callbacks/schema/raw/query.json b/contracts/ibc-callbacks/schema/raw/query.json new file mode 100644 index 0000000000..cb4a315dbe --- /dev/null +++ b/contracts/ibc-callbacks/schema/raw/query.json @@ -0,0 +1,20 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "QueryMsg", + "oneOf": [ + { + "description": "Returns stats about what callbacks have been received", + "type": "object", + "required": [ + "callback_stats" + ], + "properties": { + "callback_stats": { + "type": "object", + "additionalProperties": false + } + }, + "additionalProperties": false + } + ] +} diff --git a/contracts/ibc-callbacks/schema/raw/response_to_callback_stats.json b/contracts/ibc-callbacks/schema/raw/response_to_callback_stats.json new file mode 100644 index 0000000000..02e8342828 --- /dev/null +++ b/contracts/ibc-callbacks/schema/raw/response_to_callback_stats.json @@ -0,0 +1,231 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "CallbackStats", + "description": "A counter for the number of times the respective callback has been called", + "type": "object", + "required": [ + "ibc_ack_callbacks", + "ibc_destination_callbacks", + "ibc_timeout_callbacks" + ], + "properties": { + "ibc_ack_callbacks": { + "type": "array", + "items": { + "$ref": "#/definitions/IbcAckCallbackMsg" + } + }, + "ibc_destination_callbacks": { + "type": "array", + "items": { + "$ref": "#/definitions/IbcDestinationCallbackMsg" + } + }, + "ibc_timeout_callbacks": { + "type": "array", + "items": { + "$ref": "#/definitions/IbcTimeoutCallbackMsg" + } + } + }, + "additionalProperties": false, + "definitions": { + "Addr": { + "description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.", + "type": "string" + }, + "Binary": { + "description": "Binary is a wrapper around Vec to add base64 de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is only needed as serde-json-{core,wasm} has a horrible encoding for Vec. See also .", + "type": "string" + }, + "IbcAckCallbackMsg": { + "type": "object", + "required": [ + "acknowledgement", + "original_packet", + "relayer" + ], + "properties": { + "acknowledgement": { + "$ref": "#/definitions/IbcAcknowledgement" + }, + "original_packet": { + "$ref": "#/definitions/IbcPacket" + }, + "relayer": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + }, + "IbcAcknowledgement": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/definitions/Binary" + } + }, + "additionalProperties": false + }, + "IbcDestinationCallbackMsg": { + "description": "The message type of the IBC destination callback.\n\nThe IBC destination callback is needed for cases where someone triggers the sending of an IBC packet through some other message (i.e. not through [`crate::IbcMsg::SendPacket`]) and your contract needs to know that it received this. A prominent example is the [`crate::IbcMsg::Transfer`] message. Without callbacks, you cannot know that someone sent you IBC coins.\n\nIt is important to validate that the packet and acknowledgement are what you expect them to be. For example for a transfer message, the receiver is not necessarily the contract itself.\n\nThe callback is called after the packet was acknowledged on the destination chain, as follows: - If the acknowledgement is synchronous (i.e. returned immediately when the packet is received), the callback is called only if the acknowledgement was successful. - If the acknowledgement is asynchronous (i.e. written later using `WriteAcknowledgement`), the callback is called regardless of the success of the acknowledgement.\n\nNote that there are some prerequisites that need to be fulfilled to receive destination callbacks: - The contract must implement the `ibc_destination_callback` entrypoint. - The IBC application in the destination chain must have support for the callbacks middleware. - You have to add serialized [`IbcCallbackRequest`] to a specific field of the message. For `IbcMsg::Transfer`, this is the `memo` field and it needs to be json-encoded.", + "type": "object", + "required": [ + "ack", + "packet" + ], + "properties": { + "ack": { + "$ref": "#/definitions/IbcAcknowledgement" + }, + "packet": { + "$ref": "#/definitions/IbcPacket" + } + }, + "additionalProperties": false + }, + "IbcEndpoint": { + "type": "object", + "required": [ + "channel_id", + "port_id" + ], + "properties": { + "channel_id": { + "type": "string" + }, + "port_id": { + "type": "string" + } + }, + "additionalProperties": false + }, + "IbcPacket": { + "type": "object", + "required": [ + "data", + "dest", + "sequence", + "src", + "timeout" + ], + "properties": { + "data": { + "description": "The raw data sent from the other side in the packet", + "allOf": [ + { + "$ref": "#/definitions/Binary" + } + ] + }, + "dest": { + "description": "identifies the channel and port on the receiving chain.", + "allOf": [ + { + "$ref": "#/definitions/IbcEndpoint" + } + ] + }, + "sequence": { + "description": "The sequence number of the packet on the given channel", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "src": { + "description": "identifies the channel and port on the sending chain.", + "allOf": [ + { + "$ref": "#/definitions/IbcEndpoint" + } + ] + }, + "timeout": { + "$ref": "#/definitions/IbcTimeout" + } + }, + "additionalProperties": false + }, + "IbcTimeout": { + "description": "In IBC each package must set at least one type of timeout: the timestamp or the block height. Using this rather complex enum instead of two timeout fields we ensure that at least one timeout is set.", + "type": "object", + "properties": { + "block": { + "anyOf": [ + { + "$ref": "#/definitions/IbcTimeoutBlock" + }, + { + "type": "null" + } + ] + }, + "timestamp": { + "anyOf": [ + { + "$ref": "#/definitions/Timestamp" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false + }, + "IbcTimeoutBlock": { + "description": "IBCTimeoutHeight Height is a monotonically increasing data type that can be compared against another Height for the purposes of updating and freezing clients. Ordering is (revision_number, timeout_height)", + "type": "object", + "required": [ + "height", + "revision" + ], + "properties": { + "height": { + "description": "block height after which the packet times out. the height within the given revision", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "revision": { + "description": "the version that the client is currently on (e.g. after resetting the chain this could increment 1 as height drops to 0)", + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + }, + "additionalProperties": false + }, + "IbcTimeoutCallbackMsg": { + "type": "object", + "required": [ + "packet", + "relayer" + ], + "properties": { + "packet": { + "$ref": "#/definitions/IbcPacket" + }, + "relayer": { + "$ref": "#/definitions/Addr" + } + }, + "additionalProperties": false + }, + "Timestamp": { + "description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```", + "allOf": [ + { + "$ref": "#/definitions/Uint64" + } + ] + }, + "Uint64": { + "description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```", + "type": "string" + } + } +} diff --git a/contracts/ibc-callbacks/src/bin/schema.rs b/contracts/ibc-callbacks/src/bin/schema.rs new file mode 100644 index 0000000000..f25266eaec --- /dev/null +++ b/contracts/ibc-callbacks/src/bin/schema.rs @@ -0,0 +1,12 @@ +use cosmwasm_schema::write_api; +use cosmwasm_std::Empty; +use ibc_callbacks::msg::{ExecuteMsg, QueryMsg}; + +fn main() { + // Clear & write standard API + write_api! { + instantiate: Empty, + query: QueryMsg, + execute: ExecuteMsg, + } +} diff --git a/contracts/ibc-callbacks/src/contract.rs b/contracts/ibc-callbacks/src/contract.rs new file mode 100644 index 0000000000..a0f4223de5 --- /dev/null +++ b/contracts/ibc-callbacks/src/contract.rs @@ -0,0 +1,138 @@ +use cosmwasm_std::{ + entry_point, to_json_binary, to_json_string, Binary, Deps, DepsMut, Empty, Env, + IbcBasicResponse, IbcCallbackRequest, IbcDestinationCallbackMsg, IbcDstCallback, IbcMsg, + IbcSourceCallbackMsg, IbcSrcCallback, IbcTimeout, MessageInfo, Response, StdError, StdResult, +}; + +use crate::msg::{CallbackType, ExecuteMsg, QueryMsg}; +use crate::state::{load_stats, save_stats, CallbackStats}; + +#[entry_point] +pub fn instantiate( + deps: DepsMut, + _env: Env, + _info: MessageInfo, + _msg: Empty, +) -> StdResult { + // initialize counts + let counts = CallbackStats::default(); + save_stats(deps.storage, &counts)?; + + Ok(Response::new().add_attribute("action", "instantiate")) +} + +/// Sends an `IbcMsg::Transfer` to the given `to_address` on the given `channel_id`. +#[entry_point] +pub fn execute( + _deps: DepsMut, + env: Env, + info: MessageInfo, + msg: ExecuteMsg, +) -> StdResult { + match msg { + ExecuteMsg::Transfer { + to_address, + channel_id, + timeout_seconds, + callback_type, + } => execute_transfer( + env, + info, + to_address, + channel_id, + timeout_seconds, + callback_type, + ), + } +} + +fn execute_transfer( + env: Env, + info: MessageInfo, + to_address: String, + channel_id: String, + timeout_seconds: u32, + callback_type: CallbackType, +) -> StdResult { + let src_callback = IbcSrcCallback { + address: env.contract.address, + gas_limit: None, + }; + let dst_callback = IbcDstCallback { + address: to_address.clone(), + gas_limit: None, + }; + let coin = match &*info.funds { + [coin] if !coin.amount.is_zero() => coin, + _ => { + return Err(StdError::generic_err( + "Must send exactly one denom to trigger ics-20 transfer", + )) + } + }; + + let transfer_msg = IbcMsg::Transfer { + to_address, + timeout: IbcTimeout::with_timestamp(env.block.time.plus_seconds(timeout_seconds as u64)), + channel_id, + amount: coin.clone(), + memo: Some(to_json_string(&match callback_type { + CallbackType::Both => IbcCallbackRequest::both(src_callback, dst_callback), + CallbackType::Src => IbcCallbackRequest::source(src_callback), + CallbackType::Dst => IbcCallbackRequest::destination(dst_callback), + })?), + }; + + Ok(Response::new() + .add_message(transfer_msg) + .add_attribute("action", "execute")) +} + +#[entry_point] +pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { + match msg { + QueryMsg::CallbackStats {} => to_json_binary(&load_stats(deps.storage)?), + } +} + +/// This is the entrypoint that is called by the source chain when a callbacks-enabled IBC message +/// is acknowledged or times out. +#[entry_point] +pub fn ibc_source_callback( + deps: DepsMut, + _env: Env, + msg: IbcSourceCallbackMsg, +) -> StdResult { + let mut counts = load_stats(deps.storage)?; + + match msg { + IbcSourceCallbackMsg::Acknowledgement(ack) => { + // save the ack + counts.ibc_ack_callbacks.push(ack); + } + IbcSourceCallbackMsg::Timeout(timeout) => { + // save the timeout + counts.ibc_timeout_callbacks.push(timeout); + } + } + + save_stats(deps.storage, &counts)?; + + Ok(IbcBasicResponse::new().add_attribute("action", "ibc_source_callback")) +} + +#[entry_point] +pub fn ibc_destination_callback( + deps: DepsMut, + _env: Env, + msg: IbcDestinationCallbackMsg, +) -> StdResult { + let mut counts = load_stats(deps.storage)?; + + // save the receive + counts.ibc_destination_callbacks.push(msg); + + save_stats(deps.storage, &counts)?; + + Ok(IbcBasicResponse::new().add_attribute("action", "ibc_destination_callback")) +} diff --git a/contracts/ibc-callbacks/src/lib.rs b/contracts/ibc-callbacks/src/lib.rs new file mode 100644 index 0000000000..4934c19d5b --- /dev/null +++ b/contracts/ibc-callbacks/src/lib.rs @@ -0,0 +1,3 @@ +pub mod contract; +pub mod msg; +pub mod state; diff --git a/contracts/ibc-callbacks/src/msg.rs b/contracts/ibc-callbacks/src/msg.rs new file mode 100644 index 0000000000..d5cdb38f96 --- /dev/null +++ b/contracts/ibc-callbacks/src/msg.rs @@ -0,0 +1,36 @@ +use cosmwasm_schema::{cw_serde, QueryResponses}; + +#[cw_serde] +#[derive(QueryResponses)] +pub enum QueryMsg { + /// Returns stats about what callbacks have been received + #[returns(crate::state::CallbackStats)] + CallbackStats {}, +} + +#[cw_serde] +pub enum ExecuteMsg { + Transfer { + /// Address on the destination chain + to_address: String, + /// The channel to send the packet through + channel_id: String, + /// The amount of seconds from now the transfer should timeout at + timeout_seconds: u32, + /// Who should receive callbacks for the message + #[serde(default)] + callback_type: CallbackType, + }, +} + +#[cw_serde] +#[derive(Default)] +pub enum CallbackType { + /// Only this contract on the source chain should receive callbacks + Src, + /// Only the destination address should receive callbacks + Dst, + /// Both the source contract and the destination address should receive callbacks + #[default] + Both, +} diff --git a/contracts/ibc-callbacks/src/state.rs b/contracts/ibc-callbacks/src/state.rs new file mode 100644 index 0000000000..ece4fb1ac9 --- /dev/null +++ b/contracts/ibc-callbacks/src/state.rs @@ -0,0 +1,39 @@ +use std::any::type_name; + +use cosmwasm_schema::cw_serde; +use cosmwasm_std::{ + from_json, storage_keys::to_length_prefixed, to_json_vec, IbcAckCallbackMsg, + IbcDestinationCallbackMsg, IbcTimeoutCallbackMsg, StdError, StdResult, Storage, +}; +use serde::{de::DeserializeOwned, Serialize}; + +pub const KEY_STATS: &[u8] = b"counts"; + +/// A counter for the number of times the respective callback has been called +#[cw_serde] +#[derive(Default)] +pub struct CallbackStats { + pub ibc_ack_callbacks: Vec, + pub ibc_timeout_callbacks: Vec, + pub ibc_destination_callbacks: Vec, +} + +pub fn load_stats(storage: &dyn Storage) -> StdResult { + load_item(storage, KEY_STATS) +} + +pub fn save_stats(storage: &mut dyn Storage, counts: &CallbackStats) -> StdResult<()> { + save_item(storage, KEY_STATS, counts) +} + +fn load_item(storage: &dyn Storage, key: &[u8]) -> StdResult { + storage + .get(&to_length_prefixed(key)) + .ok_or_else(|| StdError::not_found(type_name::())) + .and_then(from_json) +} + +fn save_item(storage: &mut dyn Storage, key: &[u8], item: &T) -> StdResult<()> { + storage.set(&to_length_prefixed(key), &to_json_vec(item)?); + Ok(()) +} diff --git a/contracts/ibc-callbacks/tests/integration.rs b/contracts/ibc-callbacks/tests/integration.rs new file mode 100644 index 0000000000..7d7ebe9f4b --- /dev/null +++ b/contracts/ibc-callbacks/tests/integration.rs @@ -0,0 +1,30 @@ +//! This integration test tries to run and call the generated wasm. +//! It depends on a Wasm build being available, which you can create with `cargo wasm`. +//! Then running `cargo integration-test` will validate we can properly call into that generated Wasm. +//! +//! You can easily convert unit tests to integration tests. +//! 1. First copy them over verbatum, +//! 2. Then change +//! let mut deps = mock_dependencies(20, &[]); +//! to +//! let mut deps = mock_instance(WASM, &[]); +//! 3. If you access raw storage, where ever you see something like: +//! deps.storage.get(CONFIG_KEY).expect("no data stored"); +//! replace it with: +//! deps.with_storage(|store| { +//! let data = store.get(CONFIG_KEY).expect("no data stored"); +//! //... +//! }); +//! 4. Anywhere you see query(&deps, ...) you must replace it with query(&mut deps, ...) + +use cosmwasm_vm::testing::mock_instance; + +// This line will test the output of cargo wasm +static WASM: &[u8] = include_bytes!("../target/wasm32-unknown-unknown/release/ibc_callbacks.wasm"); +// You can uncomment this line instead to test productionified build from rust-optimizer +// static WASM: &[u8] = include_bytes!("../../artifacts/ibc_callbacks.wasm"); + +#[test] +fn validation_succeeds() { + mock_instance(WASM, &[]); +} diff --git a/packages/std/src/exports.rs b/packages/std/src/exports.rs index 3d9e445c3a..66fac9c961 100644 --- a/packages/std/src/exports.rs +++ b/packages/std/src/exports.rs @@ -13,10 +13,11 @@ use core::marker::PhantomData; use serde::de::DeserializeOwned; use crate::deps::OwnedDeps; +use crate::ibc::{IbcBasicResponse, IbcDestinationCallbackMsg, IbcSourceCallbackMsg}; #[cfg(feature = "stargate")] use crate::ibc::{ - IbcBasicResponse, IbcChannelCloseMsg, IbcChannelConnectMsg, IbcPacketAckMsg, - IbcPacketReceiveMsg, IbcPacketTimeoutMsg, IbcReceiveResponse, + IbcChannelCloseMsg, IbcChannelConnectMsg, IbcPacketAckMsg, IbcPacketReceiveMsg, + IbcPacketTimeoutMsg, IbcReceiveResponse, }; use crate::ibc::{IbcChannelOpenMsg, IbcChannelOpenResponse}; use crate::imports::{ExternalApi, ExternalQuerier, ExternalStorage}; @@ -446,6 +447,52 @@ where Region::from_vec(v).to_heap_ptr() as u32 } +pub fn do_ibc_source_callback( + contract_fn: &dyn Fn(DepsMut, Env, IbcSourceCallbackMsg) -> Result, E>, + env_ptr: u32, + msg_ptr: u32, +) -> u32 +where + Q: CustomQuery, + C: CustomMsg, + E: ToString, +{ + #[cfg(feature = "abort")] + install_panic_handler(); + let res = _do_ibc_source_callback( + contract_fn, + env_ptr as *mut Region, + msg_ptr as *mut Region, + ); + let v = to_json_vec(&res).unwrap(); + Region::from_vec(v).to_heap_ptr() as u32 +} + +pub fn do_ibc_destination_callback( + contract_fn: &dyn Fn( + DepsMut, + Env, + IbcDestinationCallbackMsg, + ) -> Result, E>, + env_ptr: u32, + msg_ptr: u32, +) -> u32 +where + Q: CustomQuery, + C: CustomMsg, + E: ToString, +{ + #[cfg(feature = "abort")] + install_panic_handler(); + let res = _do_ibc_destination_callback( + contract_fn, + env_ptr as *mut Region, + msg_ptr as *mut Region, + ); + let v = to_json_vec(&res).unwrap(); + Region::from_vec(v).to_heap_ptr() as u32 +} + fn _do_instantiate( instantiate_fn: &dyn Fn(DepsMut, Env, MessageInfo, M) -> Result, E>, env_ptr: *mut Region, @@ -700,6 +747,50 @@ where contract_fn(deps.as_mut(), env, msg).into() } +fn _do_ibc_source_callback( + contract_fn: &dyn Fn(DepsMut, Env, IbcSourceCallbackMsg) -> Result, E>, + env_ptr: *mut Region, + msg_ptr: *mut Region, +) -> ContractResult> +where + Q: CustomQuery, + C: CustomMsg, + E: ToString, +{ + let env: Vec = unsafe { Region::from_heap_ptr(env_ptr).into_vec() }; + let msg: Vec = unsafe { Region::from_heap_ptr(msg_ptr).into_vec() }; + + let env: Env = try_into_contract_result!(from_json(env)); + let msg: IbcSourceCallbackMsg = try_into_contract_result!(from_json(msg)); + + let mut deps = make_dependencies(); + contract_fn(deps.as_mut(), env, msg).into() +} + +fn _do_ibc_destination_callback( + contract_fn: &dyn Fn( + DepsMut, + Env, + IbcDestinationCallbackMsg, + ) -> Result, E>, + env_ptr: *mut Region, + msg_ptr: *mut Region, +) -> ContractResult> +where + Q: CustomQuery, + C: CustomMsg, + E: ToString, +{ + let env: Vec = unsafe { Region::from_heap_ptr(env_ptr).into_vec() }; + let msg: Vec = unsafe { Region::from_heap_ptr(msg_ptr).into_vec() }; + + let env: Env = try_into_contract_result!(from_json(env)); + let msg: IbcDestinationCallbackMsg = try_into_contract_result!(from_json(msg)); + + let mut deps = make_dependencies(); + contract_fn(deps.as_mut(), env, msg).into() +} + /// Makes all bridges to external dependencies (i.e. Wasm imports) that are injected by the VM pub(crate) fn make_dependencies() -> OwnedDeps where diff --git a/packages/std/src/ibc.rs b/packages/std/src/ibc.rs index 29c3c3bf45..cec3b790d7 100644 --- a/packages/std/src/ibc.rs +++ b/packages/std/src/ibc.rs @@ -12,6 +12,9 @@ use crate::results::{Attribute, CosmosMsg, Empty, Event, SubMsg}; use crate::StdResult; use crate::{to_json_binary, Binary}; +mod callbacks; +pub use callbacks::*; + /// These are messages in the IBC lifecycle. Only usable by IBC-enabled contracts /// (contracts that directly speak the IBC protocol via 6 entry points) #[non_exhaustive] diff --git a/packages/std/src/ibc/callbacks.rs b/packages/std/src/ibc/callbacks.rs new file mode 100644 index 0000000000..86b59bcc0b --- /dev/null +++ b/packages/std/src/ibc/callbacks.rs @@ -0,0 +1,216 @@ +//! This module contains types for the IBC callbacks defined in +//! [ADR-8](https://github.com/cosmos/ibc-go/blob/main/docs/architecture/adr-008-app-caller-cbs.md). + +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use crate::{Addr, IbcAcknowledgement, IbcPacket, Uint64}; + +/// This is just a type representing the data that has to be sent with the IBC message to receive +/// callbacks. It should be serialized and sent with the IBC message. +/// The specific field and format to send it in can vary depending on the IBC message, +/// but is usually the `memo` field by convention. +/// +/// See [`IbcSourceCallbackMsg`] and [`IbcDestinationCallbackMsg`] for more details. +/// +/// # Example +/// +/// ```rust +/// use cosmwasm_std::{ +/// to_json_string, Coin, IbcCallbackRequest, IbcMsg, IbcSrcCallback, IbcTimeout, Response, +/// Timestamp, +/// }; +/// +/// # use cosmwasm_std::testing::mock_env; +/// # let env = mock_env(); +/// +/// let _transfer = IbcMsg::Transfer { +/// to_address: "cosmos1example".to_string(), +/// channel_id: "channel-0".to_string(), +/// amount: Coin::new(10u32, "ucoin"), +/// timeout: Timestamp::from_seconds(12345).into(), +/// memo: Some(to_json_string(&IbcCallbackRequest::source(IbcSrcCallback { +/// address: env.contract.address, +/// gas_limit: None, +/// })).unwrap()), +/// }; +/// ``` +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +pub struct IbcCallbackRequest { + // using private fields to force use of the constructors + #[serde(skip_serializing_if = "Option::is_none")] + src_callback: Option, + #[serde(skip_serializing_if = "Option::is_none")] + dest_callback: Option, +} + +impl IbcCallbackRequest { + /// Use this if you want to execute callbacks on both the source and destination chain. + pub fn both(src_callback: IbcSrcCallback, dest_callback: IbcDstCallback) -> Self { + IbcCallbackRequest { + src_callback: Some(src_callback), + dest_callback: Some(dest_callback), + } + } + + /// Use this if you want to execute callbacks on the source chain, but not the destination chain. + pub fn source(src_callback: IbcSrcCallback) -> Self { + IbcCallbackRequest { + src_callback: Some(src_callback), + dest_callback: None, + } + } + + /// Use this if you want to execute callbacks on the destination chain, but not the source chain. + pub fn destination(dest_callback: IbcDstCallback) -> Self { + IbcCallbackRequest { + src_callback: None, + dest_callback: Some(dest_callback), + } + } +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +pub struct IbcSrcCallback { + /// The source chain address that should receive the callback. + /// For CosmWasm contracts, this *must* be `env.contract.address`. + /// Other addresses are not allowed and will effectively be ignored. + pub address: Addr, + /// Optional gas limit for the callback (in Cosmos SDK gas units) + #[serde(skip_serializing_if = "Option::is_none")] + pub gas_limit: Option, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +pub struct IbcDstCallback { + /// The destination chain address that should receive the callback. + pub address: String, + /// Optional gas limit for the callback (in Cosmos SDK gas units) + #[serde(skip_serializing_if = "Option::is_none")] + pub gas_limit: Option, +} + +/// The type of IBC source callback that is being called. +/// +/// IBC source callbacks are needed for cases where your contract triggers the sending of an +/// IBC packet through some other message (i.e. not through [`crate::IbcMsg::SendPacket`]) and needs to +/// know whether or not the packet was successfully received on the other chain. +/// A prominent example is the [`crate::IbcMsg::Transfer`] message. Without callbacks, you cannot know +/// whether the transfer was successful or not. +/// +/// Note that there are some prerequisites that need to be fulfilled to receive source callbacks: +/// - The contract must implement the `ibc_source_callback` entrypoint. +/// - The IBC application in the source chain must have support for the callbacks middleware. +/// - You have to add serialized [`IbcCallbackRequest`] to a specific field of the message. +/// For `IbcMsg::Transfer`, this is the `memo` field and it needs to be json-encoded. +/// - The receiver of the callback must also be the sender of the message. +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum IbcSourceCallbackMsg { + Acknowledgement(IbcAckCallbackMsg), + Timeout(IbcTimeoutCallbackMsg), +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +#[non_exhaustive] +pub struct IbcAckCallbackMsg { + acknowledgement: IbcAcknowledgement, + original_packet: IbcPacket, + relayer: Addr, +} + +impl IbcAckCallbackMsg { + pub fn new( + acknowledgement: IbcAcknowledgement, + original_packet: IbcPacket, + relayer: Addr, + ) -> Self { + Self { + acknowledgement, + original_packet, + relayer, + } + } +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +#[non_exhaustive] +pub struct IbcTimeoutCallbackMsg { + packet: IbcPacket, + relayer: Addr, +} + +impl IbcTimeoutCallbackMsg { + pub fn new(packet: IbcPacket, relayer: Addr) -> Self { + Self { packet, relayer } + } +} + +/// The message type of the IBC destination callback. +/// +/// The IBC destination callback is needed for cases where someone triggers the sending of an +/// IBC packet through some other message (i.e. not through [`crate::IbcMsg::SendPacket`]) and +/// your contract needs to know that it received this. +/// A prominent example is the [`crate::IbcMsg::Transfer`] message. Without callbacks, you cannot know +/// that someone sent you IBC coins. +/// +/// It is important to validate that the packet and acknowledgement are what you expect them to be. +/// For example for a transfer message, the receiver is not necessarily the contract itself. +/// +/// The callback is called after the packet was acknowledged on the destination chain, as follows: +/// - If the acknowledgement is synchronous (i.e. returned immediately when the packet is received), +/// the callback is called only if the acknowledgement was successful. +/// - If the acknowledgement is asynchronous (i.e. written later using `WriteAcknowledgement`), +/// the callback is called regardless of the success of the acknowledgement. +/// +/// Note that there are some prerequisites that need to be fulfilled to receive destination callbacks: +/// - The contract must implement the `ibc_destination_callback` entrypoint. +/// - The IBC application in the destination chain must have support for the callbacks middleware. +/// - You have to add serialized [`IbcCallbackRequest`] to a specific field of the message. +/// For `IbcMsg::Transfer`, this is the `memo` field and it needs to be json-encoded. +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +pub struct IbcDestinationCallbackMsg { + pub packet: IbcPacket, + pub ack: IbcAcknowledgement, +} + +#[cfg(test)] +mod tests { + use crate::to_json_string; + + use super::*; + + #[test] + fn ibc_callback_data_serialization() { + let mut data = IbcCallbackRequest::both( + IbcSrcCallback { + address: Addr::unchecked("src_address"), + gas_limit: Some(123u64.into()), + }, + IbcDstCallback { + address: "dst_address".to_string(), + gas_limit: Some(1234u64.into()), + }, + ); + + // both + let json = to_json_string(&data).unwrap(); + assert_eq!( + json, + r#"{"src_callback":{"address":"src_address","gas_limit":"123"},"dest_callback":{"address":"dst_address","gas_limit":"1234"}}"# + ); + + // dst only, without gas limit + let mut src = data.src_callback.take().unwrap(); + data.dest_callback.as_mut().unwrap().gas_limit = None; + let json = to_json_string(&data).unwrap(); + assert_eq!(json, r#"{"dest_callback":{"address":"dst_address"}}"#); + + // source only, without gas limit + src.gas_limit = None; + data.src_callback = Some(src); + data.dest_callback = None; + let json = to_json_string(&data).unwrap(); + assert_eq!(json, r#"{"src_callback":{"address":"src_address"}}"#); + } +} diff --git a/packages/std/src/lib.rs b/packages/std/src/lib.rs index c668b28783..d83774e750 100644 --- a/packages/std/src/lib.rs +++ b/packages/std/src/lib.rs @@ -40,10 +40,11 @@ pub use crate::coins::Coins; pub use crate::deps::{Deps, DepsMut, OwnedDeps}; pub use crate::ibc::IbcChannelOpenResponse; pub use crate::ibc::{ - Ibc3ChannelOpenResponse, IbcAcknowledgement, IbcBasicResponse, IbcChannel, IbcChannelCloseMsg, - IbcChannelConnectMsg, IbcChannelOpenMsg, IbcEndpoint, IbcMsg, IbcOrder, IbcPacket, - IbcPacketAckMsg, IbcPacketReceiveMsg, IbcPacketTimeoutMsg, IbcReceiveResponse, IbcTimeout, - IbcTimeoutBlock, + Ibc3ChannelOpenResponse, IbcAckCallbackMsg, IbcAcknowledgement, IbcBasicResponse, + IbcCallbackRequest, IbcChannel, IbcChannelCloseMsg, IbcChannelConnectMsg, IbcChannelOpenMsg, + IbcDestinationCallbackMsg, IbcDstCallback, IbcEndpoint, IbcMsg, IbcOrder, IbcPacket, + IbcPacketAckMsg, IbcPacketReceiveMsg, IbcPacketTimeoutMsg, IbcReceiveResponse, + IbcSourceCallbackMsg, IbcSrcCallback, IbcTimeout, IbcTimeoutBlock, IbcTimeoutCallbackMsg, }; #[cfg(feature = "iterator")] pub use crate::iterator::{Order, Record}; @@ -90,7 +91,10 @@ mod imports; mod memory; // Used by exports and imports only. This assumes pointers are 32 bit long, which makes it untestable on dev machines. #[cfg(target_arch = "wasm32")] -pub use crate::exports::{do_execute, do_instantiate, do_migrate, do_query, do_reply, do_sudo}; +pub use crate::exports::{ + do_execute, do_ibc_destination_callback, do_ibc_source_callback, do_instantiate, do_migrate, + do_query, do_reply, do_sudo, +}; #[cfg(all(feature = "stargate", target_arch = "wasm32"))] pub use crate::exports::{ do_ibc_channel_close, do_ibc_channel_connect, do_ibc_channel_open, do_ibc_packet_ack, diff --git a/packages/vm/README.md b/packages/vm/README.md index aa440a7960..3dbcff7e51 100644 --- a/packages/vm/README.md +++ b/packages/vm/README.md @@ -42,10 +42,8 @@ compatibility list: There are demo files in `testdata/*.wasm`. Those are compiled and optimized versions of -[contracts/hackatom](https://github.com/CosmWasm/cosmwasm/tree/main/contracts/hackatom) -and -[contracts/staking](https://github.com/CosmWasm/cosmwasm/tree/main/contracts/staking) -run through [rust-optimizer](https://github.com/CosmWasm/rust-optimizer). +[contracts/\*](https://github.com/CosmWasm/cosmwasm/tree/main/contracts/) run +through [cosmwasm/optimizer](https://github.com/CosmWasm/optimizer). To rebuild the test contracts, go to the repo root and do @@ -73,6 +71,12 @@ docker run --rm -v "$(pwd)":/code \ --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \ cosmwasm/optimizer:0.15.0 ./contracts/empty \ && cp artifacts/empty.wasm packages/vm/testdata/empty.wasm + +docker run --rm -v "$(pwd)":/code \ + --mount type=volume,source="devcontract_cache_ibc_callback",target=/target \ + --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \ + cosmwasm/optimizer:0.15.0 ./contracts/ibc-callbacks \ + && cp artifacts/ibc_callbacks.wasm packages/vm/testdata/ibc_callbacks.wasm ``` The `cyberpunk_rust170.wasm` for diff --git a/packages/vm/src/calls.rs b/packages/vm/src/calls.rs index c56d738f5b..dde9e634a1 100644 --- a/packages/vm/src/calls.rs +++ b/packages/vm/src/calls.rs @@ -1,12 +1,14 @@ use serde::de::DeserializeOwned; use wasmer::Value; -use cosmwasm_std::{ContractResult, CustomMsg, Env, MessageInfo, QueryResponse, Reply, Response}; +use cosmwasm_std::{ + ContractResult, CustomMsg, Env, IbcBasicResponse, IbcDestinationCallbackMsg, + IbcSourceCallbackMsg, MessageInfo, QueryResponse, Reply, Response, +}; #[cfg(feature = "stargate")] use cosmwasm_std::{ - Ibc3ChannelOpenResponse, IbcBasicResponse, IbcChannelCloseMsg, IbcChannelConnectMsg, - IbcChannelOpenMsg, IbcPacketAckMsg, IbcPacketReceiveMsg, IbcPacketTimeoutMsg, - IbcReceiveResponse, + Ibc3ChannelOpenResponse, IbcChannelCloseMsg, IbcChannelConnectMsg, IbcChannelOpenMsg, + IbcPacketAckMsg, IbcPacketReceiveMsg, IbcPacketTimeoutMsg, IbcReceiveResponse, }; use crate::backend::{BackendApi, Querier, Storage}; @@ -54,6 +56,10 @@ mod read_limits { /// Max length (in bytes) of the result data from a ibc_packet_timeout call. #[cfg(feature = "stargate")] pub const RESULT_IBC_PACKET_TIMEOUT: usize = 64 * MI; + /// Max length (in bytes) of the result data from a ibc_source_callback call. + pub const RESULT_IBC_SOURCE_CALLBACK: usize = 64 * MI; + /// Max length (in bytes) of the result data from a ibc_destination_callback call. + pub const RESULT_IBC_DESTINATION_CALLBACK: usize = 64 * MI; } /// The limits for the JSON deserialization. @@ -93,6 +99,10 @@ mod deserialization_limits { /// Max length (in bytes) of the result data from a ibc_packet_timeout call. #[cfg(feature = "stargate")] pub const RESULT_IBC_PACKET_TIMEOUT: usize = 256 * KI; + /// Max length (in bytes) of the result data from a ibc_source_callback call. + pub const RESULT_IBC_SOURCE_CALLBACK: usize = 256 * KI; + /// Max length (in bytes) of the result data from a ibc_destination_callback call. + pub const RESULT_IBC_DESTINATION_CALLBACK: usize = 256 * KI; } pub fn call_instantiate( @@ -327,6 +337,45 @@ where Ok(result) } +pub fn call_ibc_source_callback( + instance: &mut Instance, + env: &Env, + msg: &IbcSourceCallbackMsg, +) -> VmResult>> +where + A: BackendApi + 'static, + S: Storage + 'static, + Q: Querier + 'static, + U: DeserializeOwned + CustomMsg, +{ + let env = to_vec(env)?; + let msg = to_vec(msg)?; + let data = call_ibc_source_callback_raw(instance, &env, &msg)?; + let result = from_slice(&data, deserialization_limits::RESULT_IBC_SOURCE_CALLBACK)?; + Ok(result) +} + +pub fn call_ibc_destination_callback( + instance: &mut Instance, + env: &Env, + msg: &IbcDestinationCallbackMsg, +) -> VmResult>> +where + A: BackendApi + 'static, + S: Storage + 'static, + Q: Querier + 'static, + U: DeserializeOwned + CustomMsg, +{ + let env = to_vec(env)?; + let msg = to_vec(msg)?; + let data = call_ibc_destination_callback_raw(instance, &env, &msg)?; + let result = from_slice( + &data, + deserialization_limits::RESULT_IBC_DESTINATION_CALLBACK, + )?; + Ok(result) +} + /// Calls Wasm export "instantiate" and returns raw data from the contract. /// The result is length limited to prevent abuse but otherwise unchecked. pub fn call_instantiate_raw( @@ -560,6 +609,44 @@ where ) } +pub fn call_ibc_source_callback_raw( + instance: &mut Instance, + env: &[u8], + msg: &[u8], +) -> VmResult> +where + A: BackendApi + 'static, + S: Storage + 'static, + Q: Querier + 'static, +{ + instance.set_storage_readonly(false); + call_raw( + instance, + "ibc_source_callback", + &[env, msg], + read_limits::RESULT_IBC_SOURCE_CALLBACK, + ) +} + +pub fn call_ibc_destination_callback_raw( + instance: &mut Instance, + env: &[u8], + msg: &[u8], +) -> VmResult> +where + A: BackendApi + 'static, + S: Storage + 'static, + Q: Querier + 'static, +{ + instance.set_storage_readonly(false); + call_raw( + instance, + "ibc_destination_callback", + &[env, msg], + read_limits::RESULT_IBC_DESTINATION_CALLBACK, + ) +} + /// Calls a function with the given arguments. /// The exported function must return exactly one result (an offset to the result Region). pub(crate) fn call_raw( @@ -866,10 +953,13 @@ mod tests { mock_ibc_packet_ack, mock_ibc_packet_recv, mock_wasmd_attr, }; use cosmwasm_std::{ - Event, IbcAcknowledgement, IbcOrder, ReplyOn, SubMsgResponse, SubMsgResult, + Event, IbcAckCallbackMsg, IbcAcknowledgement, IbcOrder, IbcTimeoutCallbackMsg, ReplyOn, + SubMsgResponse, SubMsgResult, }; - static CONTRACT: &[u8] = include_bytes!("../testdata/ibc_reflect.wasm"); + const CONTRACT: &[u8] = include_bytes!("../testdata/ibc_reflect.wasm"); + const IBC_CALLBACKS: &[u8] = include_bytes!("../testdata/ibc_callbacks.wasm"); const IBC_VERSION: &str = "ibc-reflect-v1"; + fn setup( instance: &mut Instance, channel_id: &str, @@ -923,13 +1013,16 @@ mod tests { }; call_reply::<_, _, _, Empty>(instance, &mock_env(), &response).unwrap(); } + const CHANNEL_ID: &str = "channel-123"; const ACCOUNT: &str = "account-456"; + #[test] fn call_ibc_channel_open_and_connect_works() { let mut instance = mock_instance(CONTRACT, &[]); setup(&mut instance, CHANNEL_ID, ACCOUNT); } + #[test] fn call_ibc_channel_close_works() { let mut instance = mock_instance(CONTRACT, &[]); @@ -941,6 +1034,7 @@ mod tests { .unwrap() .unwrap(); } + #[test] fn call_ibc_packet_ack_works() { let mut instance = mock_instance(CONTRACT, &[]); @@ -951,6 +1045,7 @@ mod tests { .unwrap() .unwrap(); } + #[test] fn call_ibc_packet_timeout_works() { let mut instance = mock_instance(CONTRACT, &[]); @@ -960,6 +1055,7 @@ mod tests { .unwrap() .unwrap(); } + #[test] fn call_ibc_packet_receive_works() { let mut instance = mock_instance(CONTRACT, &[]); @@ -970,5 +1066,64 @@ mod tests { .unwrap() .unwrap(); } + + #[test] + fn call_ibc_source_callback_works() { + let mut instance = mock_instance(IBC_CALLBACKS, &[]); + + // init + let creator = instance.api().addr_make("creator"); + let info = mock_info(&creator, &[]); + call_instantiate::<_, _, _, Empty>(&mut instance, &mock_env(), &info, br#"{}"#) + .unwrap() + .unwrap(); + + /// Response type for the `callback_stats` query + #[derive(serde::Serialize, serde::Deserialize)] + struct CallbackStats { + pub ibc_ack_callbacks: Vec, + pub ibc_timeout_callbacks: Vec, + } + + // send ack callback + let ack = mock_ibc_packet_ack(CHANNEL_ID, br#"{}"#, IbcAcknowledgement::new(br#"{}"#)) + .unwrap(); + let msg = IbcSourceCallbackMsg::Acknowledgement(IbcAckCallbackMsg::new( + ack.acknowledgement, + ack.original_packet, + ack.relayer, + )); + call_ibc_source_callback::<_, _, _, Empty>(&mut instance, &mock_env(), &msg) + .unwrap() + .unwrap(); + // query the CallbackStats + let stats: CallbackStats = serde_json::from_slice( + &call_query::<_, _, _>(&mut instance, &mock_env(), br#"{"callback_stats":{}}"#) + .unwrap() + .unwrap(), + ) + .unwrap(); + assert_eq!(1, stats.ibc_ack_callbacks.len()); + assert_eq!(0, stats.ibc_timeout_callbacks.len()); + + // send timeout callback + let timeout = mock_ibc_packet_timeout(CHANNEL_ID, br#"{}"#).unwrap(); + let msg = IbcSourceCallbackMsg::Timeout(IbcTimeoutCallbackMsg::new( + timeout.packet, + timeout.relayer, + )); + call_ibc_source_callback::<_, _, _, Empty>(&mut instance, &mock_env(), &msg) + .unwrap() + .unwrap(); + // query the CallbackStats + let stats: CallbackStats = serde_json::from_slice( + &call_query::<_, _, _>(&mut instance, &mock_env(), br#"{"callback_stats":{}}"#) + .unwrap() + .unwrap(), + ) + .unwrap(); + assert_eq!(1, stats.ibc_ack_callbacks.len()); + assert_eq!(1, stats.ibc_timeout_callbacks.len()); + } } } diff --git a/packages/vm/src/lib.rs b/packages/vm/src/lib.rs index 7fe798e7ec..699c03735f 100644 --- a/packages/vm/src/lib.rs +++ b/packages/vm/src/lib.rs @@ -27,9 +27,10 @@ pub use crate::cache::{ AnalysisReport, Cache, CacheOptions, Metrics, PerModuleMetrics, PinnedMetrics, Stats, }; pub use crate::calls::{ - call_execute, call_execute_raw, call_instantiate, call_instantiate_raw, call_migrate, - call_migrate_raw, call_query, call_query_raw, call_reply, call_reply_raw, call_sudo, - call_sudo_raw, + call_execute, call_execute_raw, call_ibc_destination_callback, + call_ibc_destination_callback_raw, call_ibc_source_callback, call_ibc_source_callback_raw, + call_instantiate, call_instantiate_raw, call_migrate, call_migrate_raw, call_query, + call_query_raw, call_reply, call_reply_raw, call_sudo, call_sudo_raw, }; #[cfg(feature = "stargate")] pub use crate::calls::{ diff --git a/packages/vm/testdata/ibc_callbacks.wasm b/packages/vm/testdata/ibc_callbacks.wasm new file mode 100644 index 0000000000..63519505aa Binary files /dev/null and b/packages/vm/testdata/ibc_callbacks.wasm differ