From 5657df951172d9e2c43beeab52936406e5dace9c Mon Sep 17 00:00:00 2001 From: Kayanski Date: Thu, 28 Sep 2023 15:20:20 +0200 Subject: [PATCH 01/81] Merged with cw-multi-test advances --- .gitignore | 3 + Cargo.lock | 4828 ++++++++++++++++++-- Cargo.toml | 41 +- examples/abstract_test_app.rs | 338 ++ examples/cavern_test_app.rs | 188 + examples/local_test_app.rs | 184 + examples/test_app.rs | 72 + src/app.rs | 2158 +-------- src/bank.rs | 349 +- src/error.rs | 3 + src/gov.rs | 119 - src/ibc.rs | 57 - src/lib.rs | 4 +- src/prefixed_storage.rs | 2 +- src/prefixed_storage/length_prefixed.rs | 21 + src/staking.rs | 1515 +----- src/test_helpers.rs | 17 - src/test_helpers/contracts.rs | 9 - src/test_helpers/contracts/caller.rs | 42 - src/test_helpers/contracts/echo.rs | 140 - src/test_helpers/contracts/error.rs | 49 - src/test_helpers/contracts/hackatom.rs | 86 - src/test_helpers/contracts/payout.rs | 85 - src/test_helpers/contracts/reflect.rs | 73 - src/test_helpers/contracts/stargate.rs | 43 - src/wasm.rs | 975 +--- src/wasm_emulation/api/mod.rs | 116 + src/wasm_emulation/channel.rs | 14 + src/wasm_emulation/contract.rs | 443 ++ src/wasm_emulation/input.rs | 177 + src/wasm_emulation/mod.rs | 9 + src/wasm_emulation/output.rs | 25 + src/wasm_emulation/query/bank.rs | 151 + src/wasm_emulation/query/gas.rs | 21 + src/wasm_emulation/query/mock_querier.rs | 152 + src/wasm_emulation/query/mod.rs | 17 + src/wasm_emulation/query/staking.rs | 100 + src/wasm_emulation/query/wasm.rs | 146 + src/wasm_emulation/storage/analyzer.rs | 191 + src/wasm_emulation/storage/dual_storage.rs | 268 ++ src/wasm_emulation/storage/mock_storage.rs | 347 ++ src/wasm_emulation/storage/mod.rs | 7 + 42 files changed, 7832 insertions(+), 5753 deletions(-) create mode 100644 examples/abstract_test_app.rs create mode 100644 examples/cavern_test_app.rs create mode 100644 examples/local_test_app.rs create mode 100644 examples/test_app.rs delete mode 100644 src/test_helpers.rs delete mode 100644 src/test_helpers/contracts.rs delete mode 100644 src/test_helpers/contracts/caller.rs delete mode 100644 src/test_helpers/contracts/echo.rs delete mode 100644 src/test_helpers/contracts/error.rs delete mode 100644 src/test_helpers/contracts/hackatom.rs delete mode 100644 src/test_helpers/contracts/payout.rs delete mode 100644 src/test_helpers/contracts/reflect.rs delete mode 100644 src/test_helpers/contracts/stargate.rs create mode 100644 src/wasm_emulation/api/mod.rs create mode 100644 src/wasm_emulation/channel.rs create mode 100644 src/wasm_emulation/contract.rs create mode 100644 src/wasm_emulation/input.rs create mode 100644 src/wasm_emulation/mod.rs create mode 100644 src/wasm_emulation/output.rs create mode 100644 src/wasm_emulation/query/bank.rs create mode 100644 src/wasm_emulation/query/gas.rs create mode 100644 src/wasm_emulation/query/mock_querier.rs create mode 100644 src/wasm_emulation/query/mod.rs create mode 100644 src/wasm_emulation/query/staking.rs create mode 100644 src/wasm_emulation/query/wasm.rs create mode 100644 src/wasm_emulation/storage/analyzer.rs create mode 100644 src/wasm_emulation/storage/dual_storage.rs create mode 100644 src/wasm_emulation/storage/mock_storage.rs create mode 100644 src/wasm_emulation/storage/mod.rs diff --git a/.gitignore b/.gitignore index 62abf6fb..df455888 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,6 @@ tarpaulin-report.* packages/*/schema contracts/*/schema + +.env +state.json diff --git a/Cargo.lock b/Cargo.lock index f0f025e7..90168fcb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,13 +2,38 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "abstract-cw-multi-test" +version = "0.16.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "220367785f98ac307fdeac9810164678ceea454d1298aa780503e907776a892c" +dependencies = [ + "anyhow", + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 1.1.0", + "cw-utils 1.0.1", + "cw20-ics20", + "derivative", + "hex", + "itertools 0.11.0", + "log", + "prost", + "schemars", + "serde", + "serde_json", + "sha2 0.10.7", + "sha256", + "thiserror", +] + [[package]] name = "addr2line" version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ - "gimli", + "gimli 0.28.0", ] [[package]] @@ -28,6 +53,30 @@ dependencies = [ "version_check", ] +[[package]] +name = "aho-corasick" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" +dependencies = [ + "memchr", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anyhow" version = "1.0.75" @@ -37,6 +86,106 @@ dependencies = [ "backtrace", ] +[[package]] +name = "async-stream" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.29", +] + +[[package]] +name = "async-trait" +version = "0.1.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.29", +] + +[[package]] +name = "async-tungstenite" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0388bb7a400072bbb41ceb75d65c3baefb2ea99672fa22e85278452cd9b58b" +dependencies = [ + "futures-io", + "futures-util", + "log", + "pin-project-lite", + "rustls-native-certs 0.6.3", + "tokio", + "tokio-rustls 0.23.4", + "tungstenite", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "axum" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" +dependencies = [ + "async-trait", + "axum-core", + "bitflags 1.3.2", + "bytes", + "futures-util", + "http", + "http-body", + "hyper", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "mime", + "rustversion", + "tower-layer", + "tower-service", +] + [[package]] name = "backtrace" version = "0.3.69" @@ -48,28 +197,131 @@ dependencies = [ "cfg-if", "libc", "miniz_oxide", - "object", + "object 0.32.0", "rustc-demangle", ] +[[package]] +name = "base16" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d27c3610c36aee21ce8ac510e6224498de4228ad772a171ed65643a24693a5a8" + [[package]] name = "base16ct" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base64" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[package]] +name = "base64" +version = "0.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" + [[package]] name = "base64ct" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bip32" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e141fb0f8be1c7b45887af94c88b182472b57c96b56773250ae00cd6a14a164" +dependencies = [ + "bs58", + "hmac", + "k256 0.13.1", + "once_cell", + "pbkdf2 0.12.2", + "rand_core 0.6.4", + "ripemd", + "sha2 0.10.7", + "subtle", + "zeroize", +] + +[[package]] +name = "bitcoin" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e99ff7289b20a7385f66a0feda78af2fc119d28fb56aea8886a9cd0a4abdd75" +dependencies = [ + "bech32", + "bitcoin-private", + "bitcoin_hashes", + "hex_lit", + "secp256k1", +] + +[[package]] +name = "bitcoin-private" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73290177011694f38ec25e165d0387ab7ea749a4b81cd4c80dae5988229f7a57" + +[[package]] +name = "bitcoin_hashes" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d7066118b13d4b20b23645932dfb3a81ce7e29f95726c2036fa33cd7b092501" +dependencies = [ + "bitcoin-private", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" + +[[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.9.0" @@ -94,6 +346,43 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "845141a4fade3f790628b7daaaa298a25b204fb28907eb54febe5142db6ce653" +[[package]] +name = "bs58" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" +dependencies = [ + "sha2 0.10.7", +] + +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[package]] +name = "bytecheck" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "byteorder" version = "1.4.3" @@ -105,6 +394,9 @@ name = "bytes" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +dependencies = [ + "serde", +] [[package]] name = "cc" @@ -121,12 +413,104 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets", +] + +[[package]] +name = "clru" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "591ff76ca0691bd91c1b0b5b987e5cf93b21ec810ad96665c5a569c60846dd93" + [[package]] name = "const-oid" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[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 = "cosmos-sdk-proto" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73c9d2043a9e617b0d602fbc0a0ecd621568edbf3a9774890a6d562389bd8e1c" +dependencies = [ + "prost", + "prost-types", + "tendermint-proto", + "tonic", +] + +[[package]] +name = "cosmrs" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af13955d6f356272e6def9ff5e2450a7650df536d8934f47052a20c76513d2f6" +dependencies = [ + "bip32", + "cosmos-sdk-proto", + "ecdsa 0.16.8", + "eyre", + "getrandom", + "k256 0.13.1", + "rand_core 0.6.4", + "serde", + "serde_json", + "subtle-encoding", + "tendermint", + "tendermint-rpc", + "thiserror", + "tokio", +] + [[package]] name = "cosmwasm-crypto" version = "1.3.3" @@ -135,7 +519,7 @@ checksum = "871ce1d5a4b00ed1741f84b377eec19fadd81a904a227bc1e268d76539d26f5e" dependencies = [ "digest 0.10.7", "ed25519-zebra", - "k256", + "k256 0.11.6", "rand_core 0.6.4", "thiserror", ] @@ -179,7 +563,7 @@ version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da78abcf059181e8cb01e95e5003cf64fe95dde6c72b3fe37e5cabc75cdba32a" dependencies = [ - "base64", + "base64 0.13.1", "bnum", "cosmwasm-crypto", "cosmwasm-derive", @@ -193,6 +577,41 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cosmwasm-storage" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b52be0d56b78f502f3acb75e40908a0d04d9f265b6beb0f86b36ec2ece048748" +dependencies = [ + "cosmwasm-std", + "serde", +] + +[[package]] +name = "cosmwasm-vm" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a922b9ca7d09f71d8305a2658ecd4092c342ee578a0a9d3a7d4229043c4d8fa8" +dependencies = [ + "bitflags 1.3.2", + "bytecheck", + "clru", + "cosmwasm-crypto", + "cosmwasm-std", + "crc32fast", + "enumset", + "hex", + "loupe", + "parity-wasm", + "schemars", + "serde", + "serde_json", + "sha2 0.10.7", + "thiserror", + "wasmer", + "wasmer-middlewares", +] + [[package]] name = "cpufeatures" version = "0.2.9" @@ -203,656 +622,4365 @@ dependencies = [ ] [[package]] -name = "crypto-bigint" -version = "0.4.9" +name = "cranelift-bforest" +version = "0.82.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +checksum = "38faa2a16616c8e78a18d37b4726b98bfd2de192f2fdc8a39ddf568a408a0f75" dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", + "cranelift-entity", ] [[package]] -name = "crypto-common" -version = "0.1.6" +name = "cranelift-codegen" +version = "0.82.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "26f192472a3ba23860afd07d2b0217dc628f21fcc72617aa1336d98e1671f33b" dependencies = [ - "generic-array", - "typenum", + "cranelift-bforest", + "cranelift-codegen-meta", + "cranelift-codegen-shared", + "cranelift-entity", + "gimli 0.26.2", + "log", + "regalloc", + "smallvec", + "target-lexicon", ] [[package]] -name = "curve25519-dalek" -version = "3.2.0" +name = "cranelift-codegen-meta" +version = "0.82.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +checksum = "0f32ddb89e9b89d3d9b36a5b7d7ea3261c98235a76ac95ba46826b8ec40b1a24" dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core 0.5.1", - "subtle", - "zeroize", + "cranelift-codegen-shared", ] [[package]] -name = "cw-multi-test" -version = "0.16.5" -dependencies = [ - "anyhow", - "cosmwasm-std", - "cw-storage-plus", - "cw-utils", - "derivative", - "itertools 0.11.0", +name = "cranelift-codegen-shared" +version = "0.82.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01fd0d9f288cc1b42d9333b7a776b17e278fc888c28e6a0f09b5573d45a150bc" + +[[package]] +name = "cranelift-entity" +version = "0.82.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e3bfe172b83167604601faf9dc60453e0d0a93415b57a9c4d1a7ae6849185cf" + +[[package]] +name = "cranelift-frontend" +version = "0.82.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a006e3e32d80ce0e4ba7f1f9ddf66066d052a8c884a110b91d05404d6ce26dce" +dependencies = [ + "cranelift-codegen", + "log", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset 0.9.0", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-bigint" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "740fe28e594155f10cfc383984cbefd529d7396050557148f79cb0f621204124" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "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 = "ct-logs" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1a816186fa68d9e426e3cb4ae4dff1fcd8e4a2c34b781bf7a822574a0d0aac8" +dependencies = [ + "sct 0.6.1", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "platforms", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.29", +] + +[[package]] +name = "curve25519-dalek-ng" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c359b7249347e46fb28804470d071c921156ad62b3eef5d34e2ba867533dec8" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.6.4", + "subtle-ng", + "zeroize", +] + +[[package]] +name = "cw-address-like" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "451a4691083a88a3c0630a8a88799e9d4cd6679b7ce8ff22b8da2873ff31d380" +dependencies = [ + "cosmwasm-std", +] + +[[package]] +name = "cw-asset" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e2cf17accdcafe71859a683b6ed3f18311634a769550aacf4829b50151b221" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-address-like", + "cw-storage-plus 1.1.0", + "cw20 1.1.0", + "thiserror", +] + +[[package]] +name = "cw-controllers" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5d8edce4b78785f36413f67387e4be7d0cb7d032b5d4164bcc024f9c3f3f2ea" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 1.1.0", + "cw-utils 1.0.1", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "cw-multi-test" +version = "0.16.5" +dependencies = [ + "anyhow", + "base64 0.21.4", + "bech32", + "bincode", + "cosmrs", + "cosmwasm-crypto", + "cosmwasm-schema", + "cosmwasm-std", + "cosmwasm-vm", + "cw-asset", + "cw-orch-daemon", + "cw-orch-networks", + "cw-storage-plus 1.1.0", + "cw-utils 1.0.1", + "cw20 1.1.0", + "derivative", + "dotenv", + "env_logger", + "generic_static", + "hex", + "ibc-chain-registry", + "ibc-relayer-types", + "itertools 0.11.0", + "k256 0.11.6", + "lazy_static", + "log", + "moneymarket", + "num-bigint", + "num-traits", + "once_cell", "prost", + "rustc-serialize", "schemars", "serde", "serde_json", "sha2 0.10.7", "thiserror", + "tokio", + "tonic", + "treediff", +] + +[[package]] +name = "cw-orch-contract-derive" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1b46bb61c32f521c65cf445a1ebaf92fb2d9ecc93fca69da9a21cb62712aabe" +dependencies = [ + "convert_case", + "log", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "cw-orch-core" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13258e0fad1fd79b01d794877810963e908dab0e0899e7a8a65ae7a9eba3217f" +dependencies = [ + "abstract-cw-multi-test", + "anyhow", + "cosmwasm-std", + "log", + "serde", + "serde_json", + "sha256", + "thiserror", +] + +[[package]] +name = "cw-orch-daemon" +version = "0.16.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3575b1303d0e7bce902f2bec4b54f249d8a50841eae8a442cdaad0a370ae913f" +dependencies = [ + "abstract-cw-multi-test", + "anyhow", + "base16", + "base64 0.21.4", + "bitcoin", + "chrono", + "cosmrs", + "cosmwasm-std", + "cw-orch-contract-derive", + "cw-orch-core", + "cw-orch-fns-derive", + "cw-orch-networks", + "cw-orch-traits", + "derive_builder", + "ed25519-dalek", + "eyre", + "flate2", + "hex", + "hkd32", + "ibc-chain-registry", + "ibc-relayer-types", + "log", + "prost", + "prost-types", + "rand_core 0.6.4", + "reqwest", + "ring", + "ripemd", + "schemars", + "secp256k1", + "serde", + "serde_json", + "sha256", + "shellexpand", + "thiserror", + "tokio", + "tonic", +] + +[[package]] +name = "cw-orch-fns-derive" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db7242ad1ad0436acb8521f8063b76355172912f058aa6e6b986669ca35b5c4f" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "cw-orch-networks" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5a4ad254bda4d5af6631b7b2342941d720b31c2eaadb3c9f746b46940ee3f4f" +dependencies = [ + "ibc-chain-registry", + "serde", +] + +[[package]] +name = "cw-orch-traits" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a81a36ac603e49eecbaca0c76ed02d05bf793bd64ef303fb4bf2d8b0b152efd" +dependencies = [ + "cw-orch-core", + "prost", + "prost-types", +] + +[[package]] +name = "cw-storage-plus" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6cf70ef7686e2da9ad7b067c5942cd3e88dd9453f7af42f54557f8af300fb0" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", +] + +[[package]] +name = "cw-storage-plus" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f0e92a069d62067f3472c62e30adedb4cab1754725c0f2a682b3128d2bf3c79" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", +] + +[[package]] +name = "cw-utils" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae0b69fa7679de78825b4edeeec045066aa2b2c4b6e063d80042e565bb4da5c" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw2 0.15.1", + "schemars", + "semver", + "serde", + "thiserror", +] + +[[package]] +name = "cw-utils" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c80e93d1deccb8588db03945016a292c3c631e6325d349ebb35d2db6f4f946f7" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw2 1.1.0", + "schemars", + "semver", + "serde", + "thiserror", +] + +[[package]] +name = "cw2" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5abb8ecea72e09afff830252963cb60faf945ce6cef2c20a43814516082653da" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 0.15.1", + "schemars", + "serde", +] + +[[package]] +name = "cw2" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29ac2dc7a55ad64173ca1e0a46697c31b7a5c51342f55a1e84a724da4eb99908" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 1.1.0", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "cw20" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6025276fb6e603e974c21f3e4606982cdc646080e8fba3198816605505e1d9a" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-utils 0.15.1", + "schemars", + "serde", +] + +[[package]] +name = "cw20" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "011c45920f8200bd5d32d4fe52502506f64f2f75651ab408054d4cfc75ca3a9b" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-utils 1.0.1", + "schemars", + "serde", +] + +[[package]] +name = "cw20-ics20" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3402434ee8619725d211bc982c4486569ce3b58cb2be3f73b495175269ce9b2" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-controllers", + "cw-storage-plus 1.1.0", + "cw-utils 1.0.1", + "cw2 1.1.0", + "cw20 1.1.0", + "schemars", + "semver", + "serde", + "thiserror", +] + +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core 0.14.4", + "darling_macro 0.14.4", +] + +[[package]] +name = "darling" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +dependencies = [ + "darling_core 0.20.3", + "darling_macro 0.20.3", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", +] + +[[package]] +name = "darling_core" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "syn 2.0.29", +] + +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core 0.14.4", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +dependencies = [ + "darling_core 0.20.3", + "quote", + "syn 2.0.29", +] + +[[package]] +name = "der" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "der" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +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_builder" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" +dependencies = [ + "darling 0.14.4", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_builder_macro" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" +dependencies = [ + "derive_builder_core", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + +[[package]] +name = "dyn-clone" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbfc4744c1b8f2a09adc0e55242f60b1af195d88596bd8700be74418c056c555" + +[[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", +] + +[[package]] +name = "ecdsa" +version = "0.14.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +dependencies = [ + "der 0.6.1", + "elliptic-curve 0.12.3", + "rfc6979 0.3.1", + "signature 1.6.4", +] + +[[package]] +name = "ecdsa" +version = "0.16.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4" +dependencies = [ + "der 0.7.8", + "digest 0.10.7", + "elliptic-curve 0.13.5", + "rfc6979 0.4.0", + "signature 2.1.0", + "spki 0.7.2", +] + +[[package]] +name = "ed25519" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60f6d271ca33075c88028be6f04d502853d63a5ece419d269c15315d4fc1cf1d" +dependencies = [ + "pkcs8 0.10.2", + "serde", + "signature 2.1.0", +] + +[[package]] +name = "ed25519-consensus" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c8465edc8ee7436ffea81d21a019b16676ee3db267aa8d5a8d729581ecf998b" +dependencies = [ + "curve25519-dalek-ng", + "hex", + "rand_core 0.6.4", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "ed25519-dalek" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7277392b266383ef8396db7fdeb1e77b6c52fed775f5df15bb24f35b72156980" +dependencies = [ + "curve25519-dalek 4.1.1", + "ed25519", + "serde", + "sha2 0.10.7", + "zeroize", +] + +[[package]] +name = "ed25519-zebra" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" +dependencies = [ + "curve25519-dalek 3.2.0", + "hashbrown 0.12.3", + "hex", + "rand_core 0.6.4", + "serde", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "elliptic-curve" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +dependencies = [ + "base16ct 0.1.1", + "crypto-bigint 0.4.9", + "der 0.6.1", + "digest 0.10.7", + "ff 0.12.1", + "generic-array", + "group 0.12.1", + "pkcs8 0.9.0", + "rand_core 0.6.4", + "sec1 0.3.0", + "subtle", + "zeroize", +] + +[[package]] +name = "elliptic-curve" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" +dependencies = [ + "base16ct 0.2.0", + "crypto-bigint 0.5.3", + "digest 0.10.7", + "ff 0.13.0", + "generic-array", + "group 0.13.0", + "pkcs8 0.10.2", + "rand_core 0.6.4", + "sec1 0.7.3", + "subtle", + "zeroize", +] + +[[package]] +name = "encoding_rs" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +dependencies = [ + "cfg-if", +] + +[[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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e875f1719c16de097dee81ed675e2d9bb63096823ed3f0ca827b7dea3028bbbb" +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 0.20.3", + "proc-macro2", + "quote", + "syn 2.0.29", +] + +[[package]] +name = "env_logger" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "erased-serde" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c138974f9d5e7fe373eb04df7cae98833802ae4b11c24ac7039a21d5af4b26c" +dependencies = [ + "serde", +] + +[[package]] +name = "errno" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "eyre" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] +name = "ff" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0870c84016d4b481be5c9f323c24f65e31e901ae618f0e80f4308fb00de1d2d" + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "static_assertions", +] + +[[package]] +name = "flate2" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "flex-error" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c606d892c9de11507fa0dcffc116434f94e105d0bbdc4e405b61519464c49d7b" +dependencies = [ + "anyhow", + "eyre", + "paste", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "forward_ref" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" + +[[package]] +name = "futures-executor" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" + +[[package]] +name = "futures-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.29", +] + +[[package]] +name = "futures-sink" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + +[[package]] +name = "futures-task" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" + +[[package]] +name = "futures-util" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[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 = "generic_static" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28ccff179d8070317671db09aee6d20affc26e88c5394714553b04f509b43a60" +dependencies = [ + "once_cell", +] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" +dependencies = [ + "fallible-iterator", + "indexmap", + "stable_deref_trait", +] + +[[package]] +name = "gimli" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" + +[[package]] +name = "group" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +dependencies = [ + "ff 0.12.1", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff 0.13.0", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "h2" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[package]] +name = "headers" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" +dependencies = [ + "base64 0.21.4", + "bytes", + "headers-core", + "http", + "httpdate", + "mime", + "sha1", +] + +[[package]] +name = "headers-core" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" +dependencies = [ + "http", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex_lit" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" + +[[package]] +name = "hkd32" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e013a4f0b8772418eee1fc462e74017aba13c364a7b61bd3df1ddcbfe47b065" +dependencies = [ + "hmac", + "once_cell", + "pbkdf2 0.11.0", + "rand_core 0.6.4", + "sha2 0.10.7", + "subtle-encoding", + "zeroize", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "http" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyper" +version = "0.14.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2 0.4.9", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-proxy" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca815a891b24fdfb243fa3239c86154392b0953ee584aa1a2a1f66d20cbe75cc" +dependencies = [ + "bytes", + "futures", + "headers", + "http", + "hyper", + "hyper-rustls 0.22.1", + "rustls-native-certs 0.5.0", + "tokio", + "tokio-rustls 0.22.0", + "tower-service", + "webpki 0.21.4", +] + +[[package]] +name = "hyper-rustls" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f9f7a97316d44c0af9b0301e65010573a853a9fc97046d7331d7f6bc0fd5a64" +dependencies = [ + "ct-logs", + "futures-util", + "hyper", + "log", + "rustls 0.19.1", + "rustls-native-certs 0.5.0", + "tokio", + "tokio-rustls 0.22.0", + "webpki 0.21.4", + "webpki-roots 0.21.1", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" +dependencies = [ + "futures-util", + "http", + "hyper", + "rustls 0.21.7", + "tokio", + "tokio-rustls 0.24.1", +] + +[[package]] +name = "hyper-timeout" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +dependencies = [ + "hyper", + "pin-project-lite", + "tokio", + "tokio-io-timeout", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ibc-chain-registry" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e550fe9592ad7096831442b38c45837c6385f683a55cf5eb32460e468ecddb4" +dependencies = [ + "async-trait", + "flex-error", + "futures", + "http", + "ibc-proto", + "ibc-relayer-types", + "itertools 0.10.5", + "reqwest", + "serde", + "serde_json", + "tendermint-rpc", + "tokio", + "tracing", +] + +[[package]] +name = "ibc-proto" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11c352715b36685c2543556a77091fb16af5d26257d5ce9c28e6756c1ccd71aa" +dependencies = [ + "base64 0.21.4", + "bytes", + "flex-error", + "ics23", + "prost", + "serde", + "subtle-encoding", + "tendermint-proto", + "tonic", +] + +[[package]] +name = "ibc-relayer-types" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fa9269c050d20b36a9e61955a5526345df1508f396f7f3a9acb4c03cdb572f3" +dependencies = [ + "bytes", + "derive_more", + "dyn-clone", + "erased-serde", + "flex-error", + "ibc-proto", + "ics23", + "itertools 0.10.5", + "num-rational", + "primitive-types", + "prost", + "regex", + "serde", + "serde_derive", + "serde_json", + "subtle-encoding", + "tendermint", + "tendermint-light-client-verifier", + "tendermint-proto", + "time", + "uint", +] + +[[package]] +name = "ics23" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "442d4bab37956e76f739c864f246c825d87c0bb7f9afa65660c57833c91bf6d4" +dependencies = [ + "anyhow", + "bytes", + "hex", + "informalsystems-pbjson", + "prost", + "ripemd", + "serde", + "sha2 0.10.7", + "sha3", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + +[[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", + "serde", +] + +[[package]] +name = "informalsystems-pbjson" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4eecd90f87bea412eac91c6ef94f6b1e390128290898cbe14f2b926787ae1fb" +dependencies = [ + "base64 0.13.1", + "serde", +] + +[[package]] +name = "ipnet" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" + +[[package]] +name = "is-terminal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi", + "rustix", + "windows-sys 0.48.0", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "js-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "k256" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" +dependencies = [ + "cfg-if", + "ecdsa 0.14.8", + "elliptic-curve 0.12.3", + "sha2 0.10.7", +] + +[[package]] +name = "k256" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" +dependencies = [ + "cfg-if", + "ecdsa 0.16.8", + "elliptic-curve 0.13.5", + "once_cell", + "sha2 0.10.7", + "signature 2.1.0", +] + +[[package]] +name = "keccak" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +dependencies = [ + "cpufeatures", +] + +[[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.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128" + +[[package]] +name = "lock_api" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "loupe" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6a72dfa44fe15b5e76b94307eeb2ff995a8c5b283b55008940c02e0c5b634d" +dependencies = [ + "indexmap", + "loupe-derive", + "rustversion", +] + +[[package]] +name = "loupe-derive" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fbfc88337168279f2e9ae06e157cfed4efd3316e14dc96ed074d4f2e6c5952" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "mach" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +dependencies = [ + "libc", +] + +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + +[[package]] +name = "memchr" +version = "2.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5486aed0026218e61b8a01d5fbd5a0a134649abb71a0e53b7bc088529dced86e" + +[[package]] +name = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "moneymarket" +version = "0.3.1" +source = "git+https://github.com/CavernPerson/money-market-contracts#0ab1ddefb0cee27587f3d54cea78b3d259fe60c5" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cosmwasm-storage", + "cw20 0.15.1", + "schemars", + "serde", + "strum", + "strum_macros", +] + +[[package]] +name = "more-asserts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389" + +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.28.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" +dependencies = [ + "crc32fast", + "hashbrown 0.11.2", + "indexmap", + "memchr", +] + +[[package]] +name = "object" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "openssl" +version = "0.10.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" +dependencies = [ + "bitflags 2.4.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.29", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "parity-wasm" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1ad0aff30c1da14b1254fcb2af73e1fa9a28670e584a626f53a369d0e157304" + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.3.5", + "smallvec", + "windows-targets", +] + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest 0.10.7", + "hmac", +] + +[[package]] +name = "peg" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07c0b841ea54f523f7aa556956fbd293bcbe06f2e67d2eb732b7278aaf1d166a" +dependencies = [ + "peg-macros", + "peg-runtime", +] + +[[package]] +name = "peg-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aa52829b8decbef693af90202711348ab001456803ba2a98eb4ec8fb70844c" +dependencies = [ + "peg-runtime", + "proc-macro2", + "quote", +] + +[[package]] +name = "peg-runtime" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c719dcf55f09a3a7e764c6649ab594c18a177e3599c467983cdf644bfc0a4088" + +[[package]] +name = "percent-encoding" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" + +[[package]] +name = "pin-project" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.29", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" +dependencies = [ + "der 0.6.1", + "spki 0.6.0", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der 0.7.8", + "spki 0.7.2", +] + +[[package]] +name = "pkg-config" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" + +[[package]] +name = "platforms" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4503fa043bf02cee09a9582e9554b4c6403b2ef55e4612e96561d294419429f8" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "primitive-types" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f3486ccba82358b11a77516035647c34ba167dfa53312630de83b12bd4f3d66" +dependencies = [ + "fixed-hash", + "impl-serde", + "uint", +] + +[[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.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +dependencies = [ + "anyhow", + "itertools 0.10.5", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "prost-types" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" +dependencies = [ + "prost", +] + +[[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.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +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 = [ + "libc", + "rand_chacha", + "rand_core 0.6.4", +] + +[[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 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" + +[[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.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall 0.2.16", + "thiserror", +] + +[[package]] +name = "regalloc" +version = "0.0.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62446b1d3ebf980bdc68837700af1d77b37bc430e524bf95319c6eada2a4cc02" +dependencies = [ + "log", + "rustc-hash", + "smallvec", +] + +[[package]] +name = "regex" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + +[[package]] +name = "region" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76e189c2369884dce920945e2ddf79b3dff49e071a167dd1817fa9c4c00d512e" +dependencies = [ + "bitflags 1.3.2", + "libc", + "mach", + "winapi", +] + +[[package]] +name = "rend" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2571463863a6bd50c32f94402933f03457a3fbaf697a707c5be741e459f08fd" +dependencies = [ + "bytecheck", +] + +[[package]] +name = "reqwest" +version = "0.11.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1" +dependencies = [ + "base64 0.21.4", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-rustls 0.24.1", + "hyper-tls", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls 0.21.7", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-native-tls", + "tokio-rustls 0.24.1", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots 0.25.2", + "winreg", +] + +[[package]] +name = "rfc6979" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +dependencies = [ + "crypto-bigint 0.4.9", + "hmac", + "zeroize", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "ripemd" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "rkyv" +version = "0.7.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0200c8230b013893c0b2d6213d6ec64ed2b9be2e0e016682b7224ff82cff5c58" +dependencies = [ + "bitvec", + "bytecheck", + "hashbrown 0.12.3", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", + "tinyvec", + "uuid 1.4.1", +] + +[[package]] +name = "rkyv_derive" +version = "0.7.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2e06b915b5c230a17d7a736d1e2e63ee753c256a8614ef3f5147b13a4f5541d" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-serialize" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7db8590df6dfcd144d22afd1b83b36c21a18d7cbc1dc4bb5295a8712e9eb662" +dependencies = [ + "bitflags 2.4.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustls" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" +dependencies = [ + "base64 0.13.1", + "log", + "ring", + "sct 0.6.1", + "webpki 0.21.4", +] + +[[package]] +name = "rustls" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" +dependencies = [ + "log", + "ring", + "sct 0.7.0", + "webpki 0.22.1", +] + +[[package]] +name = "rustls" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" +dependencies = [ + "log", + "ring", + "rustls-webpki", + "sct 0.7.0", +] + +[[package]] +name = "rustls-native-certs" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a07b7c1885bd8ed3831c289b7870b13ef46fe0e856d288c30d9cc17d75a2092" +dependencies = [ + "openssl-probe", + "rustls 0.19.1", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" +dependencies = [ + "base64 0.21.4", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c7d5dece342910d9ba34d259310cae3e0154b873b35408b787b59bce53d34fe" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "schemars" +version = "0.8.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "763f8cd0d4c71ed8389c90cb8100cba87e763bd01a8e614d4f0af97bcd50a161" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0f696e21e10fa546b7ffb1c9672c6de8fbc7a81acf59524386d8639bf12737" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 1.0.109", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sct" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + +[[package]] +name = "sec1" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +dependencies = [ + "base16ct 0.1.1", + "der 0.6.1", + "generic-array", + "pkcs8 0.9.0", + "subtle", + "zeroize", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct 0.2.0", + "der 0.7.8", + "generic-array", + "pkcs8 0.10.2", + "subtle", + "zeroize", +] + +[[package]] +name = "secp256k1" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" +dependencies = [ + "bitcoin_hashes", + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" +dependencies = [ + "cc", +] + +[[package]] +name = "security-framework" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" + +[[package]] +name = "serde" +version = "1.0.188" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-json-wasm" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16a62a1fad1e1828b24acac8f2b468971dade7b8c3c2e672bcadefefb1f8c137" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_bytes" +version = "0.11.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab33ec92f677585af6d88c65593ae2375adde54efdbf16d597f2cbc7a6d368ff" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.188" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.29", +] + +[[package]] +name = "serde_derive_internals" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "serde_json" +version = "1.0.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_repr" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.29", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha256" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7895c8ae88588ccead14ff438b939b0c569cd619116f14b4d13fdff7b8333386" +dependencies = [ + "async-trait", + "bytes", + "hex", + "sha2 0.10.7", + "tokio", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "shellexpand" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da03fa3b94cc19e3ebfc88c4229c49d8f08cdbd1228870a45f0ffdf84988e14b" +dependencies = [ + "dirs", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + +[[package]] +name = "signature" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + +[[package]] +name = "simdutf8" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" + +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "socket2" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spki" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +dependencies = [ + "base64ct", + "der 0.6.1", +] + +[[package]] +name = "spki" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +dependencies = [ + "base64ct", + "der 0.7.8", +] + +[[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 = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "strum" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" + +[[package]] +name = "strum_macros" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 1.0.109", +] + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "subtle-encoding" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dcb1ed7b8330c5eed5441052651dd7a12c75e2ed88f2ec024ae1fa3a5e59945" +dependencies = [ + "zeroize", +] + +[[package]] +name = "subtle-ng" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" + +[[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.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[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.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" + +[[package]] +name = "tempfile" +version = "3.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall 0.3.5", + "rustix", + "windows-sys 0.48.0", +] + +[[package]] +name = "tendermint" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f0a7d05cf78524782337f8edd55cbc578d159a16ad4affe2135c92f7dbac7f0" +dependencies = [ + "bytes", + "digest 0.10.7", + "ed25519", + "ed25519-consensus", + "flex-error", + "futures", + "k256 0.13.1", + "num-traits", + "once_cell", + "prost", + "prost-types", + "ripemd", + "serde", + "serde_bytes", + "serde_json", + "serde_repr", + "sha2 0.10.7", + "signature 2.1.0", + "subtle", + "subtle-encoding", + "tendermint-proto", + "time", + "zeroize", +] + +[[package]] +name = "tendermint-config" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71a72dbbea6dde12045d261f2c70c0de039125675e8a026c8d5ad34522756372" +dependencies = [ + "flex-error", + "serde", + "serde_json", + "tendermint", + "toml", + "url", +] + +[[package]] +name = "tendermint-light-client-verifier" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9875dce5c1b08201152eb0860f8fb1dce96c53e37532c310ffc4956d20f90def" +dependencies = [ + "derive_more", + "flex-error", + "serde", + "tendermint", + "time", +] + +[[package]] +name = "tendermint-proto" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cec054567d16d85e8c3f6a3139963d1a66d9d3051ed545d31562550e9bcc3d" +dependencies = [ + "bytes", + "flex-error", + "num-derive", + "num-traits", + "prost", + "prost-types", + "serde", + "serde_bytes", + "subtle-encoding", + "time", +] + +[[package]] +name = "tendermint-rpc" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d119d83a130537fc4a98c3c9eb6899ebe857fea4860400a61675bfb5f0b35129" +dependencies = [ + "async-trait", + "async-tungstenite", + "bytes", + "flex-error", + "futures", + "getrandom", + "http", + "hyper", + "hyper-proxy", + "hyper-rustls 0.22.1", + "peg", + "pin-project", + "semver", + "serde", + "serde_bytes", + "serde_json", + "subtle", + "subtle-encoding", + "tendermint", + "tendermint-config", + "tendermint-proto", + "thiserror", + "time", + "tokio", + "tracing", + "url", + "uuid 0.8.2", + "walkdir", +] + +[[package]] +name = "termcolor" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +dependencies = [ + "winapi-util", ] [[package]] -name = "cw-storage-plus" -version = "1.1.0" +name = "thiserror" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f0e92a069d62067f3472c62e30adedb4cab1754725c0f2a682b3128d2bf3c79" +checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f" dependencies = [ - "cosmwasm-std", - "schemars", - "serde", + "thiserror-impl", ] [[package]] -name = "cw-utils" -version = "1.0.1" +name = "thiserror-impl" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c80e93d1deccb8588db03945016a292c3c631e6325d349ebb35d2db6f4f946f7" +checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b" dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw2", - "schemars", - "semver", - "serde", - "thiserror", + "proc-macro2", + "quote", + "syn 2.0.29", ] [[package]] -name = "cw2" -version = "1.1.0" +name = "time" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ac2dc7a55ad64173ca1e0a46697c31b7a5c51342f55a1e84a724da4eb99908" +checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-storage-plus", - "schemars", "serde", - "thiserror", + "time-core", + "time-macros", ] [[package]] -name = "der" -version = "0.6.1" +name = "time-core" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + +[[package]] +name = "time-macros" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36" dependencies = [ - "const-oid", - "zeroize", + "time-core", ] [[package]] -name = "derivative" -version = "2.2.0" +name = "tinyvec" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +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 = "tokio" +version = "1.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2 0.5.4", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-io-timeout" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" +dependencies = [ + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-macros" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.29", ] [[package]] -name = "digest" -version = "0.9.0" +name = "tokio-native-tls" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ - "generic-array", + "native-tls", + "tokio", ] [[package]] -name = "digest" -version = "0.10.7" +name = "tokio-rustls" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" dependencies = [ - "block-buffer 0.10.4", - "crypto-common", - "subtle", + "rustls 0.19.1", + "tokio", + "webpki 0.21.4", ] [[package]] -name = "dyn-clone" -version = "1.0.13" +name = "tokio-rustls" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfc4744c1b8f2a09adc0e55242f60b1af195d88596bd8700be74418c056c555" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +dependencies = [ + "rustls 0.20.9", + "tokio", + "webpki 0.22.1", +] [[package]] -name = "ecdsa" -version = "0.14.8" +name = "tokio-rustls" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "der", - "elliptic-curve", - "rfc6979", - "signature", + "rustls 0.21.7", + "tokio", ] [[package]] -name = "ed25519-zebra" -version = "3.1.0" +name = "tokio-stream" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ - "curve25519-dalek", - "hashbrown", - "hex", - "rand_core 0.6.4", "serde", - "sha2 0.9.9", - "zeroize", ] [[package]] -name = "either" -version = "1.9.0" +name = "tonic" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "3082666a3a6433f7f511c7192923fa1fe07c69332d3c6a2e6bb040b569199d5a" +dependencies = [ + "async-stream", + "async-trait", + "axum", + "base64 0.21.4", + "bytes", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-timeout", + "percent-encoding", + "pin-project", + "prost", + "rustls-native-certs 0.6.3", + "rustls-pemfile", + "tokio", + "tokio-rustls 0.24.1", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] [[package]] -name = "elliptic-curve" -version = "0.12.3" +name = "tower" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ - "base16ct", - "crypto-bigint", - "der", - "digest 0.10.7", - "ff", - "generic-array", - "group", - "pkcs8", - "rand_core 0.6.4", - "sec1", - "subtle", - "zeroize", + "futures-core", + "futures-util", + "indexmap", + "pin-project", + "pin-project-lite", + "rand", + "slab", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", ] [[package]] -name = "ff" -version = "0.12.1" +name = "tower-layer" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ - "rand_core 0.6.4", - "subtle", + "cfg-if", + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", ] [[package]] -name = "forward_ref" -version = "1.0.0" +name = "tracing-attributes" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.29", +] [[package]] -name = "generic-array" -version = "0.14.7" +name = "tracing-core" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" dependencies = [ - "typenum", - "version_check", + "once_cell", ] [[package]] -name = "getrandom" -version = "0.2.10" +name = "treediff" +version = "4.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "52984d277bdf2a751072b5df30ec0377febdb02f7696d64c2d7d54630bac4303" dependencies = [ - "cfg-if", - "libc", - "wasi", + "rustc-serialize", ] [[package]] -name = "gimli" -version = "0.28.0" +name = "try-lock" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] -name = "group" -version = "0.12.1" +name = "tungstenite" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788" dependencies = [ - "ff", - "rand_core 0.6.4", - "subtle", + "base64 0.13.1", + "byteorder", + "bytes", + "http", + "httparse", + "log", + "rand", + "rustls 0.20.9", + "sha1", + "thiserror", + "url", + "utf-8", + "webpki 0.22.1", ] [[package]] -name = "hashbrown" -version = "0.12.3" +name = "typenum" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" dependencies = [ - "ahash", + "byteorder", + "crunchy", + "hex", + "static_assertions", ] [[package]] -name = "hex" -version = "0.4.3" +name = "unicode-bidi" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] -name = "hmac" -version = "0.12.1" +name = "unicode-ident" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ - "digest 0.10.7", + "tinyvec", ] [[package]] -name = "itertools" -version = "0.10.5" +name = "unicode-segmentation" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "url" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" dependencies = [ - "either", + "form_urlencoded", + "idna", + "percent-encoding", ] [[package]] -name = "itertools" -version = "0.11.0" +name = "utf-8" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" + +[[package]] +name = "uuid" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "walkdir" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" dependencies = [ - "either", + "same-file", + "winapi-util", ] [[package]] -name = "itoa" -version = "1.0.9" +name = "want" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] [[package]] -name = "k256" -version = "0.11.6" +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if", - "ecdsa", - "elliptic-curve", - "sha2 0.10.7", + "wasm-bindgen-macro", ] [[package]] -name = "libc" -version = "0.2.147" +name = "wasm-bindgen-backend" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.29", + "wasm-bindgen-shared", +] [[package]] -name = "memchr" -version = "2.6.2" +name = "wasm-bindgen-futures" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5486aed0026218e61b8a01d5fbd5a0a134649abb71a0e53b7bc088529dced86e" +checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] [[package]] -name = "miniz_oxide" -version = "0.7.1" +name = "wasm-bindgen-macro" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ - "adler", + "quote", + "wasm-bindgen-macro-support", ] [[package]] -name = "object" -version = "0.32.0" +name = "wasm-bindgen-macro-support" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ - "memchr", + "proc-macro2", + "quote", + "syn 2.0.29", + "wasm-bindgen-backend", + "wasm-bindgen-shared", ] [[package]] -name = "once_cell" -version = "1.18.0" +name = "wasm-bindgen-shared" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] -name = "opaque-debug" -version = "0.3.0" +name = "wasmer" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "ea8d8361c9d006ea3d7797de7bd6b1492ffd0f91a22430cfda6c1658ad57bedf" +dependencies = [ + "cfg-if", + "indexmap", + "js-sys", + "loupe", + "more-asserts", + "target-lexicon", + "thiserror", + "wasm-bindgen", + "wasmer-artifact", + "wasmer-compiler", + "wasmer-compiler-cranelift", + "wasmer-compiler-singlepass", + "wasmer-derive", + "wasmer-engine", + "wasmer-engine-dylib", + "wasmer-engine-universal", + "wasmer-types", + "wasmer-vm", + "winapi", +] [[package]] -name = "pkcs8" -version = "0.9.0" +name = "wasmer-artifact" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" +checksum = "7aaf9428c29c1d8ad2ac0e45889ba8a568a835e33fd058964e5e500f2f7ce325" dependencies = [ - "der", - "spki", + "enumset", + "loupe", + "thiserror", + "wasmer-compiler", + "wasmer-types", ] [[package]] -name = "proc-macro2" -version = "1.0.66" +name = "wasmer-compiler" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "e67a6cd866aed456656db2cfea96c18baabbd33f676578482b85c51e1ee19d2c" dependencies = [ - "unicode-ident", + "enumset", + "loupe", + "rkyv", + "serde", + "serde_bytes", + "smallvec", + "target-lexicon", + "thiserror", + "wasmer-types", + "wasmparser", ] [[package]] -name = "prost" -version = "0.11.9" +name = "wasmer-compiler-cranelift" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +checksum = "48be2f9f6495f08649e4f8b946a2cbbe119faf5a654aa1457f9504a99d23dae0" dependencies = [ - "bytes", - "prost-derive", + "cranelift-codegen", + "cranelift-entity", + "cranelift-frontend", + "gimli 0.26.2", + "loupe", + "more-asserts", + "rayon", + "smallvec", + "target-lexicon", + "tracing", + "wasmer-compiler", + "wasmer-types", ] [[package]] -name = "prost-derive" -version = "0.11.9" +name = "wasmer-compiler-singlepass" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +checksum = "29ca2a35204d8befa85062bc7aac259a8db8070b801b8a783770ba58231d729e" dependencies = [ - "anyhow", - "itertools 0.10.5", - "proc-macro2", - "quote", - "syn 1.0.109", + "byteorder", + "dynasm", + "dynasmrt", + "gimli 0.26.2", + "lazy_static", + "loupe", + "more-asserts", + "rayon", + "smallvec", + "wasmer-compiler", + "wasmer-types", ] [[package]] -name = "quote" -version = "1.0.33" +name = "wasmer-derive" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "00e50405cc2a2f74ff574584710a5f2c1d5c93744acce2ca0866084739284b51" dependencies = [ + "proc-macro-error", "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] -name = "rand_core" -version = "0.5.1" +name = "wasmer-engine" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +checksum = "3f98f010978c244db431b392aeab0661df7ea0822343334f8f2a920763548e45" +dependencies = [ + "backtrace", + "enumset", + "lazy_static", + "loupe", + "memmap2", + "more-asserts", + "rustc-demangle", + "serde", + "serde_bytes", + "target-lexicon", + "thiserror", + "wasmer-artifact", + "wasmer-compiler", + "wasmer-types", + "wasmer-vm", +] [[package]] -name = "rand_core" -version = "0.6.4" +name = "wasmer-engine-dylib" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +checksum = "ad0358af9c154724587731175553805648d9acb8f6657880d165e378672b7e53" dependencies = [ - "getrandom", + "cfg-if", + "enum-iterator", + "enumset", + "leb128", + "libloading", + "loupe", + "object 0.28.4", + "rkyv", + "serde", + "tempfile", + "tracing", + "wasmer-artifact", + "wasmer-compiler", + "wasmer-engine", + "wasmer-object", + "wasmer-types", + "wasmer-vm", + "which", ] [[package]] -name = "rfc6979" -version = "0.3.1" +name = "wasmer-engine-universal" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +checksum = "440dc3d93c9ca47865a4f4edd037ea81bf983b5796b59b3d712d844b32dbef15" dependencies = [ - "crypto-bigint", - "hmac", - "zeroize", + "cfg-if", + "enumset", + "leb128", + "loupe", + "region", + "rkyv", + "wasmer-compiler", + "wasmer-engine", + "wasmer-engine-universal-artifact", + "wasmer-types", + "wasmer-vm", + "winapi", ] [[package]] -name = "rustc-demangle" -version = "0.1.23" +name = "wasmer-engine-universal-artifact" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "68f1db3f54152657eb6e86c44b66525ff7801dad8328fe677da48dd06af9ad41" +dependencies = [ + "enum-iterator", + "enumset", + "loupe", + "rkyv", + "thiserror", + "wasmer-artifact", + "wasmer-compiler", + "wasmer-types", +] [[package]] -name = "ryu" -version = "1.0.15" +name = "wasmer-middlewares" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "d7812438ed2f37203a37007cdb5332b8475cb2b16e15d51299b2647894e9ed3a" +dependencies = [ + "loupe", + "wasmer", + "wasmer-types", + "wasmer-vm", +] [[package]] -name = "schemars" -version = "0.8.13" +name = "wasmer-object" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "763f8cd0d4c71ed8389c90cb8100cba87e763bd01a8e614d4f0af97bcd50a161" +checksum = "8d831335ff3a44ecf451303f6f891175c642488036b92ceceb24ac8623a8fa8b" dependencies = [ - "dyn-clone", - "schemars_derive", - "serde", - "serde_json", + "object 0.28.4", + "thiserror", + "wasmer-compiler", + "wasmer-types", ] [[package]] -name = "schemars_derive" -version = "0.8.13" +name = "wasmer-types" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0f696e21e10fa546b7ffb1c9672c6de8fbc7a81acf59524386d8639bf12737" +checksum = "39df01ea05dc0a9bab67e054c7cb01521e53b35a7bb90bd02eca564ed0b2667f" dependencies = [ - "proc-macro2", - "quote", - "serde_derive_internals", - "syn 1.0.109", + "backtrace", + "enum-iterator", + "indexmap", + "loupe", + "more-asserts", + "rkyv", + "serde", + "thiserror", ] [[package]] -name = "sec1" -version = "0.3.0" +name = "wasmer-vm" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +checksum = "30d965fa61f4dc4cdb35a54daaf7ecec3563fbb94154a6c35433f879466247dd" dependencies = [ - "base16ct", - "der", - "generic-array", - "pkcs8", - "subtle", - "zeroize", + "backtrace", + "cc", + "cfg-if", + "corosensei", + "enum-iterator", + "indexmap", + "lazy_static", + "libc", + "loupe", + "mach", + "memoffset 0.6.5", + "more-asserts", + "region", + "rkyv", + "scopeguard", + "serde", + "thiserror", + "wasmer-artifact", + "wasmer-types", + "winapi", ] [[package]] -name = "semver" -version = "1.0.18" +name = "wasmparser" +version = "0.83.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" +checksum = "718ed7c55c2add6548cca3ddd6383d738cd73b892df400e96b9aa876f0141d7a" [[package]] -name = "serde" -version = "1.0.188" +name = "web-sys" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" dependencies = [ - "serde_derive", + "js-sys", + "wasm-bindgen", ] [[package]] -name = "serde-json-wasm" -version = "0.5.1" +name = "webpki" +version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16a62a1fad1e1828b24acac8f2b468971dade7b8c3c2e672bcadefefb1f8c137" +checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" dependencies = [ - "serde", + "ring", + "untrusted", ] [[package]] -name = "serde_derive" -version = "1.0.188" +name = "webpki" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "f0e74f82d49d545ad128049b7e88f6576df2da6b02e9ce565c6f533be576957e" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.29", + "ring", + "untrusted", ] [[package]] -name = "serde_derive_internals" -version = "0.26.0" +name = "webpki-roots" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "webpki 0.21.4", ] [[package]] -name = "serde_json" -version = "1.0.105" +name = "webpki-roots" +version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" -dependencies = [ - "itoa", - "ryu", - "serde", -] +checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" [[package]] -name = "sha2" -version = "0.9.9" +name = "which" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", + "either", + "home", + "once_cell", + "rustix", ] [[package]] -name = "sha2" -version = "0.10.7" +name = "winapi" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", ] [[package]] -name = "signature" -version = "1.6.4" +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" -dependencies = [ - "digest 0.10.7", - "rand_core 0.6.4", -] +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] -name = "spki" -version = "0.6.0" +name = "winapi-util" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ - "base64ct", - "der", + "winapi", ] [[package]] -name = "subtle" -version = "2.5.0" +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "syn" -version = "1.0.109" +name = "windows" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "windows-targets", ] [[package]] -name = "syn" -version = "2.0.29" +name = "windows-sys" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +checksum = "43dbb096663629518eb1dfa72d80243ca5a6aca764cae62a2df70af760a9be75" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "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 = "thiserror" -version = "1.0.47" +name = "windows-sys" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "thiserror-impl", + "windows-targets", ] [[package]] -name = "thiserror-impl" -version = "1.0.47" +name = "windows-targets" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.29", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.48.5", ] [[package]] -name = "typenum" -version = "1.16.0" +name = "windows_aarch64_gnullvm" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] -name = "unicode-ident" -version = "1.0.11" +name = "windows_aarch64_msvc" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "cd761fd3eb9ab8cc1ed81e56e567f02dd82c4c837e48ac3b2181b9ffc5060807" [[package]] -name = "version_check" -version = "0.9.4" +name = "windows_aarch64_msvc" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +name = "windows_i686_gnu" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "cab0cf703a96bab2dc0c02c0fa748491294bf9b7feb27e1f4f96340f208ada0e" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] [[package]] name = "zeroize" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +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.29", +] diff --git a/Cargo.toml b/Cargo.toml index 7f1c1eef..0a5f5e3c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,46 @@ thiserror = "1.0" derivative = "2" sha2 = "0.10" +# We don't use the following dependencies directly. They're dependencies of our dependencies. +# We specify them to tighten their version requirements so that builds with `-Zminimal-versions` work. +# Once we bump `cosmwasm-*` deps to a version after `1.1.5`, we can remove these. +k256 = { version = "0.11.1", features = ["ecdsa"] } +cw-orch-daemon = { version = "0.16.0"} +cw-orch-networks = { version="0.16.0" } +tokio = "1.28.2" +ibc-chain-registry = "0.25.0" +cosmwasm-vm = { version = "1.2", features = ["staking", "stargate", "iterator"] } +bincode = "1.3.3" +base64 = "0.21.2" +cw20 = "1.0.1" +ibc-relayer-types = "0.25.1" +cosmrs = "0.14.0" +num-bigint = "0.4.3" +num-traits = "0.2.15" +cosmwasm-crypto = "1.2.7" +tonic = "0.9.2" +generic_static = "0.2.0" +once_cell = "1.18.0" +lazy_static = "1.4.0" +log = "0.4.19" +env_logger = "0.10.0" +cosmwasm-schema = "1.2.7" +bech32 = "0.9.1" +treediff = {version="4.0.2", features=["with-rustc-serialize"]} +rustc-serialize = "0.3.24" + [dev-dependencies] # We don't use the following dependency directly, # we tighten the version so that builds with `-Zminimal-versions` work. -serde_json = "1.0.105" \ No newline at end of file +serde_json = "1.0.105" + +dotenv = "0.15.0" + +# Abstract +# abstract-interface = {verion="0.16.1", git="https://github.com/AbstractSDK/contracts.git"} +# abstract-core = {verion="0.16.1", git="https://github.com/AbstractSDK/contracts.git"} +# abstract-dex-adapter = { git = "https://github.com/AbstractSDK/adapters.git", default-features = false } +hex = "0.4.3" +cw-asset = "3.0.0" + +moneymarket = {git="https://github.com/CavernPerson/money-market-contracts"} \ No newline at end of file diff --git a/examples/abstract_test_app.rs b/examples/abstract_test_app.rs new file mode 100644 index 00000000..e1b0c5d0 --- /dev/null +++ b/examples/abstract_test_app.rs @@ -0,0 +1,338 @@ +// use abstract_core::ans_host::AssetsResponse; +// use abstract_core::objects::pool_id::PoolAddressBase; +// use abstract_core::objects::PoolMetadata; +// use cosmwasm_std::coins; +// use cosmwasm_std::Timestamp; +// use cosmwasm_std::Uint128; +// use cw_orch::daemon::queriers::Node; +// use cw_orch_daemon::DaemonQuerier; +// use tokio::runtime::Runtime; + +// use abstract_core::adapter::AuthorizedAddressesResponse; +// use abstract_core::adapter::BaseQueryMsg; +// use cw_multi_test::wasm_emulation::storage::analyzer::StorageAnalyzer; + +// use abstract_core::adapter::AdapterRequestMsg; +// use abstract_core::adapter::BaseInstantiateMsg; +// use abstract_core::objects::module::Module; +// use abstract_core::objects::module_reference::ModuleReference; +// use abstract_core::objects::AnsAsset; +// use abstract_core::objects::AssetEntry; +// use abstract_dex_adapter::msg::InstantiateMsg; +// use abstract_dex_adapter::msg::{DexAction, DexExecuteMsg, DexInstantiateMsg}; +// use cosmwasm_std::Decimal; +// use cw_multi_test::wasm_emulation::contract::WasmContract; +// use cw_orch_daemon::CosmWasm; +// use std::path::Path; + +// use cw_asset::AssetInfo; + +// use abstract_core::version_control::{self}; + +// use abstract_core::objects::module::ModuleInfo; +// use abstract_core::objects::module::ModuleVersion; +// use cosmwasm_std::{to_binary, Addr}; +// use cw_multi_test::AppBuilder; +// use cw_multi_test::BankKeeper; +// use cw_multi_test::Executor; +// use cw_multi_test::FailingModule; + +// use abstract_interface::get_account_contracts; +// use abstract_interface::Abstract; +// use abstract_interface::ManagerQueryFns; +// use cosmwasm_std::Empty; +// use cw_multi_test::WasmKeeper; +// use cw_orch::daemon::Daemon; +// use cw_orch::deploy::Deploy; + +// use cw_orch_daemon::prelude::ContractInstance; +// use dotenv::dotenv; + +// use abstract_core::manager::ExecuteMsg; + +// // Abstract patch + +// #[cosmwasm_schema::cw_serde] +// pub struct ModulesResponse { +// pub modules: Vec, +// } + +// fn main() { +// dotenv().ok(); +// let runtime = tokio::runtime::Runtime::new().unwrap(); + +// let mut chain = cw_orch::daemon::networks::JUNO_1; +// chain.grpc_urls = &["http://juno-grpc.polkachu.com:12690"]; + +// let daemon = Daemon::builder() +// .chain(chain.clone()) +// .handle(runtime.handle()) +// .build() +// .unwrap(); + +// let abstract_ = Abstract::load_from(daemon.clone()).unwrap(); + +// // Query an account, its owner and install a module for + +// let (manager, proxy) = get_account_contracts(&abstract_.version_control, Some(1)); + +// let ownership = manager.ownership().unwrap(); + +// let owner = ownership.owner.unwrap(); +// // We use this owner to install and uninstall a module +// let owner_addr = Addr::unchecked(owner.clone()); + +// env_logger::init(); +// let mut wasm = WasmKeeper::::new(); +// wasm.set_chain(chain.clone().into()); + +// let mut bank = BankKeeper::new(); +// bank.set_chain(chain.clone().into()); + +// let node_querier = daemon.query_client::(); +// let block = runtime.block_on(node_querier.latest_block()).unwrap(); + +// // First we instantiate a new app +// let app = AppBuilder::default() +// .with_wasm::, _>(wasm) +// .with_bank(bank) +// .with_block(cosmwasm_std::BlockInfo { +// height: block.header.height.into(), +// time: Timestamp::from_seconds(block.header.time.unix_timestamp().try_into().unwrap()), +// chain_id: block.header.chain_id.to_string(), +// }); +// let mut app = app.build(|_, _, _| {}); + +// log::info!("Built App Environment"); + +// // We need to register a pool pairing on the ans host +// app.execute_contract( +// Addr::unchecked(owner.clone()), +// abstract_.ans_host.address().unwrap(), +// &abstract_core::ans_host::ExecuteMsg::UpdateDexes { +// to_add: vec!["wyndex".to_string()], +// to_remove: vec![], +// }, +// &[], +// ) +// .unwrap(); + +// app.execute_contract( +// Addr::unchecked(owner.clone()), +// abstract_.ans_host.address().unwrap(), +// &abstract_core::ans_host::ExecuteMsg::UpdatePools { +// to_add: vec![( +// PoolAddressBase::contract( +// "juno1gqy6rzary8vwnslmdavqre6jdhakcd4n2z4r803ajjmdq08r66hq7zcwrj".to_string(), +// ), +// PoolMetadata { +// dex: "wyndex".to_string(), +// pool_type: abstract_core::objects::PoolType::ConstantProduct, +// assets: vec!["axelar>usdc".into(), "juno>juno".into()], +// }, +// )], +// to_remove: vec![], +// }, +// &[], +// ) +// .unwrap(); +// // End registering the pool pairing + +// // test +// let rt = Runtime::new().unwrap(); +// let test = rt +// .block_on( +// CosmWasm::new(daemon.channel()).contract_raw_state( +// "juno13q8rv8w9ew5cn6wecr2p4scegzu9nac0hv2dx807l4vz60h0ldns0ksvz0", +// hex::decode( +// "0008706f6f6c5f69647300096a756e6f3e6a756e6f00096a756e6f3e77796e6477796e646578", +// ) +// .unwrap(), +// ), +// ) +// .unwrap(); +// log::info!("{:x?}", test); + +// // We deploy the adapter : +// // 1. upload the code +// let code = std::fs::read( +// Path::new(env!("CARGO_MANIFEST_DIR")) +// .join("artifacts") +// .join("abstract_dex_adapter-juno.wasm"), +// ) +// .unwrap(); +// let dex_code = WasmContract::new_local(code, chain.clone()); +// let code_id = app.store_code(dex_code); + +// // 2. Instantiate the code +// let dex_addr = app +// .instantiate_contract( +// code_id, +// owner_addr.clone(), +// &InstantiateMsg { +// module: DexInstantiateMsg { +// swap_fee: Decimal::percent(1), +// recipient_account: 0, +// }, +// base: BaseInstantiateMsg { +// ans_host_address: abstract_.ans_host.address().unwrap().to_string(), +// version_control_address: abstract_ +// .version_control +// .address() +// .unwrap() +// .to_string(), +// }, +// }, +// &[], +// "Dex adapter", +// None, +// ) +// .unwrap(); + +// log::info!("Instantiated Dex adapter"); + +// // 3. Register the adapter in version control +// let module = +// ModuleInfo::from_id("abstract:dex", ModuleVersion::Version("0.17.1".to_string())).unwrap(); +// app.execute_contract( +// owner_addr.clone(), +// abstract_.version_control.address().unwrap(), +// &version_control::ExecuteMsg::ProposeModules { +// modules: vec![(module.clone(), ModuleReference::Adapter(dex_addr.clone()))], +// }, +// &[], +// ) +// .unwrap(); + +// log::info!("Proposed and registered Dex adapter"); +// // We install the module on the account +// app.execute_contract( +// Addr::unchecked(owner.clone()), +// manager.address().unwrap(), +// &ExecuteMsg::InstallModule { +// init_msg: Some(to_binary(&Empty {}).unwrap()), +// module, +// }, +// &[], +// ) +// .unwrap(); + +// log::info!("Installed Dex adapter"); +// // Let's see what registered in the ans as assets + +// /* +// let assets = abstract_.ans_host.asset_list(None, Some(30), Some("juno>future".to_string())).unwrap(); +// log::info!("{:?}", assets); + +// let pools = abstract_.ans_host.pool_list(None, Some(30), None).unwrap(); +// log::info!("{:?}", pools); +// */ +// // We need to get the authorized addresses on the adapter + +// /* +// app.execute_contract(Addr::unchecked(owner.clone()), manager.address().unwrap(),&ExecuteMsg::ExecOnModule { module_id: "abstract:dex".to_string(), +// exec_msg: to_binary(&abstract_dex_adapter::msg::ExecuteMsg::Base( +// abstract_core::adapter::BaseExecuteMsg::UpdateAuthorizedAddresses { +// to_add: vec![manager.address().unwrap().to_string()], +// to_remove: vec![] +// } +// )).unwrap()}, &[]).unwrap(); +// */ +// log::info!("Updated authorized address on the Dex adapter"); +// /* Query to verify that the manager was authorized to execute on the adapter */ +// let addresses: AuthorizedAddressesResponse = app +// .wrap() +// .query_wasm_smart( +// dex_addr, +// &abstract_dex_adapter::msg::QueryMsg::Base(BaseQueryMsg::AuthorizedAddresses { +// proxy_address: proxy.address().unwrap().to_string(), +// }), +// ) +// .unwrap(); +// log::info!("AuthorizedAddresses on dex {:?}", addresses); + +// let analysis = StorageAnalyzer::new(&app).unwrap(); +// analysis.compare_all_readable_contract_storage(chain.into()); +// //log::info!("analysis, dex {:x?}", analysis.get_contract_storage(dex_addr)); +// /* End query */ +// log::info!("Some queries to check everything is alright"); + +// // We deposit funds on the proxy + +// app.execute( +// owner_addr, +// cosmwasm_std::CosmosMsg::Bank(cosmwasm_std::BankMsg::Send { +// to_address: proxy.address().unwrap().to_string(), +// amount: coins(100_000u128, "ujuno"), +// }), +// ) +// .unwrap(); + +// // We get the balances (for asserting) +// let usdc: AssetsResponse = app +// .wrap() +// .query_wasm_smart( +// abstract_.ans_host.address().unwrap(), +// &abstract_core::ans_host::QueryMsg::Assets { +// names: vec!["axelar>usdc".to_string()], +// }, +// ) +// .unwrap(); +// let usdc = match &usdc.assets[0].1 { +// AssetInfo::Native(denom) => denom, +// _ => panic!("Expected native denom"), +// }; +// let old_balance = app +// .wrap() +// .query_balance(proxy.address().unwrap(), "ujuno") +// .unwrap(); +// let old_usdc_balance = app +// .wrap() +// .query_balance(proxy.address().unwrap(), usdc) +// .unwrap(); + +// // We test a swap interaction +// app.execute_contract( +// Addr::unchecked(owner), +// manager.address().unwrap(), +// &ExecuteMsg::ExecOnModule { +// module_id: "abstract:dex".to_string(), +// exec_msg: to_binary(&abstract_dex_adapter::msg::ExecuteMsg::Module( +// AdapterRequestMsg { +// proxy_address: None, +// request: DexExecuteMsg::Action { +// action: DexAction::Swap { +// ask_asset: AssetEntry::new("axelar>usdc"), +// offer_asset: AnsAsset::new(AssetEntry::new("juno>juno"), 100_000u128), +// belief_price: None, +// max_spread: None, +// }, +// dex: "wyndex".to_string(), +// }, +// }, +// )) +// .unwrap(), +// }, +// &[], +// ) +// .unwrap(); +// log::info!("Execute the swap"); + +// // We get the juno balance (should be lower) +// let new_balance = app +// .wrap() +// .query_balance(proxy.address().unwrap(), "ujuno") +// .unwrap(); +// assert_eq!( +// old_balance.amount - new_balance.amount, +// Uint128::from(100_000u128) +// ); + +// let new_usdc_balance = app +// .wrap() +// .query_balance(proxy.address().unwrap(), usdc) +// .unwrap(); +// assert!(old_usdc_balance.amount < new_usdc_balance.amount); +// } + +fn main() {} diff --git a/examples/cavern_test_app.rs b/examples/cavern_test_app.rs new file mode 100644 index 00000000..c17e7cdb --- /dev/null +++ b/examples/cavern_test_app.rs @@ -0,0 +1,188 @@ +use cosmwasm_schema::cw_serde; +use cosmwasm_schema::QueryResponses; +use cosmwasm_std::coins; +use cosmwasm_std::Addr; +use cosmwasm_std::ContractInfoResponse; +use cosmwasm_std::QueryRequest; +use cosmwasm_std::WasmQuery; +use cw20::BalanceResponse; +use cw_multi_test::wasm_emulation::contract::WasmContract; +use cw_multi_test::wasm_emulation::storage::analyzer::StorageAnalyzer; +use cw_multi_test::BankKeeper; +use cw_multi_test::Executor; +use std::path::Path; + +use cw20::Cw20QueryMsg; +use cw_multi_test::AppBuilder; +use cw_multi_test::FailingModule; +use cw_orch_networks::networks::PHOENIX_1; + +use cosmwasm_std::Empty; +use cw_multi_test::WasmKeeper; +use moneymarket::market::ExecuteMsg; + +/// COUNTER CONTRACT MSGs +#[cw_serde] +#[cfg_attr(feature = "interface", derive(cw_orch::QueryFns))] // Function generation +#[derive(QueryResponses)] +pub enum QueryMsg { + // GetCount returns the current count as a json-encoded number + #[returns(GetCountResponse)] + GetCount {}, + // GetCount returns the current count of the cousin contract + #[returns(GetCountResponse)] + GetCousinCount {}, +} + +// Custom response for the query +#[cw_serde] +pub struct GetCountResponse { + pub count: i32, +} + +#[cw_serde] +pub struct MigrateMsg { + pub t: String, +} + +/// END CONTRACT MSGs + +pub fn main() { + env_logger::init(); + let mut wasm = WasmKeeper::::new(); + wasm.set_chain(PHOENIX_1.into()); + + let mut bank = BankKeeper::new(); + bank.set_chain(PHOENIX_1.into()); + + // First we instantiate a new app + let app = AppBuilder::default() + .with_wasm::, _>(wasm) + .with_bank(bank); + let mut app = app.build(|_, _, _| {}); + + // Then we send a message to the blockchain through the app + let sender = "terra1ytj0hhw39j88qsx4yapsr6ker83jv3aj354gmj"; + let market = "terra1zqlcp3aty4p4rjv96h6qdascdn953v6crhwedu5vddxjnp349upscluex6"; + let currency = "ibc/B3504E092456BA618CC28AC671A71FB08C6CA0FD0BE7C8A5B5A3E2DD933CC9E4"; + let a_currency = "terra1gwdxyqtu75es0x5l6cd9flqhh87zjtj7qdankayyr0vtt7s9w4ssm7ds8m"; + + // We add some funds to the sender, because they need some. + app.init_modules(|router, _, storage| { + router + .bank + .init_balance(storage, &Addr::unchecked(sender), coins(10_000_000, "uusd")) + }).unwrap(); + + // We query to verify the state changed + let response: BalanceResponse = app + .wrap() + .query_wasm_smart( + a_currency, + &Cw20QueryMsg::Balance { + address: sender.to_string(), + }, + ) + .unwrap(); + log::info!("Before deposit : {:?}", response); + + app.execute_contract( + Addr::unchecked(sender), + Addr::unchecked(market), + &ExecuteMsg::DepositStable {}, + &coins(10_000, currency), + ) + .unwrap(); + + // We query to verify the state changed + let response: BalanceResponse = app + .wrap() + .query_wasm_smart( + a_currency, + &Cw20QueryMsg::Balance { + address: sender.to_string(), + }, + ) + .unwrap(); + log::info!("After deposit : {:?}", response); + + // Now we try to migrate the contract + + let code = std::fs::read( + Path::new(env!("CARGO_MANIFEST_DIR")) + .join("artifacts") + .join("counter_contract.wasm"), + ) + .unwrap(); + let counter_contract = WasmContract::new_local(code, PHOENIX_1); + + let code_id = app.store_code(counter_contract); + + let contract_info: ContractInfoResponse = app + .wrap() + .query(&QueryRequest::Wasm(WasmQuery::ContractInfo { + contract_addr: market.to_string(), + })) + .unwrap(); + + app.migrate_contract( + Addr::unchecked(contract_info.admin.clone().unwrap()), + Addr::unchecked(market), + &MigrateMsg { t: "t".to_string() }, + code_id, + ) + .unwrap(); + + // The query count message should error with a specific storage error + + let err = app + .wrap() + .query_wasm_smart::(market, &QueryMsg::GetCount {}) + .unwrap_err(); + + if !err + .to_string() + .contains("counter_contract::state::State not found") + { + panic!( + "Error {} should contain counter_contract::state::State not found", + err + ); + } + + // Now we migrate back and deposit again + app.migrate_contract( + Addr::unchecked(contract_info.admin.unwrap()), + Addr::unchecked(market), + &Empty {}, + contract_info.code_id, + ) + .unwrap(); + app.execute_contract( + Addr::unchecked(sender), + Addr::unchecked(market), + &ExecuteMsg::DepositStable {}, + &coins(10_000, currency), + ) + .unwrap(); + + // We query to verify the state changed + let response: BalanceResponse = app + .wrap() + .query_wasm_smart( + a_currency, + &Cw20QueryMsg::Balance { + address: sender.to_string(), + }, + ) + .unwrap(); + log::info!("After migrate and deposit : {:?}", response); + + let analysis = StorageAnalyzer::new(&app, PHOENIX_1).unwrap(); + log::info!( + "All contracts storage {:?}", + analysis.all_readable_contract_storage() + ); + + analysis.compare_all_readable_contract_storage(); +} diff --git a/examples/local_test_app.rs b/examples/local_test_app.rs new file mode 100644 index 00000000..d0d2adde --- /dev/null +++ b/examples/local_test_app.rs @@ -0,0 +1,184 @@ +use ibc_chain_registry::chain::ChainData; +use std::path::Path; + +use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::Empty; + +use cw_multi_test::wasm_emulation::contract::WasmContract; +use cw_multi_test::wasm_emulation::storage::analyzer::StorageAnalyzer; +use cw_multi_test::AppBuilder; +use cw_multi_test::Executor; +use cw_multi_test::FailingModule; +use cw_multi_test::WasmKeeper; + +use cw_orch_daemon::networks::PHOENIX_1; + +#[cw_serde] +pub struct InstantiateMsg { + pub count: i32, +} + +// ANCHOR: exec_msg +#[cw_serde] +#[cfg_attr(feature = "interface", derive(cw_orch::ExecuteFns))] // Function generation +pub enum ExecuteMsg { + Increment {}, + IncrementAndQuery {}, + SetCousin { addr: String }, + Reset { count: i32 }, +} +// ANCHOR_END: exec_msg + +// ANCHOR: query_msg +#[cw_serde] +#[cfg_attr(feature = "interface", derive(cw_orch::QueryFns))] // Function generation +#[derive(QueryResponses)] +pub enum QueryMsg { + // GetCount returns the current count as a json-encoded number + #[returns(GetCountResponse)] + GetCount {}, + // GetCount returns the current count of the cousin contract + #[returns(GetCountResponse)] + GetCousinCount {}, +} + +// Custom response for the query +#[cw_serde] +pub struct GetCountResponse { + pub count: i32, +} +#[cw_serde] +pub struct GetCousinCountResponse { + pub raw: i32, + pub smart: i32, +} +// ANCHOR_END: query_msg + +#[cw_serde] +pub struct MigrateMsg { + pub t: String, +} + +pub fn main() { + env_logger::init(); + + let chain: ChainData = PHOENIX_1.into(); + + let mut wasm = WasmKeeper::::new(); + wasm.set_chain(chain.clone()); + + // First we instantiate a new app + let app = AppBuilder::default() + .with_chain(chain.clone()) + .with_wasm::, _>(wasm); + let mut app = app.build(|_, _, _| {}); + + // Then we send a message to the blockchain through the app + let sender = app.next_address(); + + let code = std::fs::read( + Path::new(env!("CARGO_MANIFEST_DIR")) + .join("artifacts") + .join("counter_contract.wasm"), + ) + .unwrap(); + let counter_contract = WasmContract::new_local(code, chain.clone()); + + let code_id = app.store_code(counter_contract); + + let counter1 = app + .instantiate_contract( + code_id, + sender.clone(), + &InstantiateMsg { count: 1 }, + &[], + "cousin-counter", + Some(sender.to_string()), + ) + .unwrap(); + let counter2 = app + .instantiate_contract( + code_id, + sender.clone(), + &InstantiateMsg { count: 1 }, + &[], + "cousin-counter", + Some(sender.to_string()), + ) + .unwrap(); + + app.execute_contract( + sender.clone(), + counter1.clone(), + &ExecuteMsg::Increment {}, + &[], + ) + .unwrap(); + app.execute_contract( + sender.clone(), + counter1.clone(), + &ExecuteMsg::Increment {}, + &[], + ) + .unwrap(); + app.execute_contract( + sender.clone(), + counter2.clone(), + &ExecuteMsg::Increment {}, + &[], + ) + .unwrap(); + + app.execute_contract( + sender.clone(), + counter1.clone(), + &ExecuteMsg::SetCousin { + addr: counter2.to_string(), + }, + &[], + ) + .unwrap(); + app.execute_contract( + sender, + counter2.clone(), + &ExecuteMsg::SetCousin { + addr: counter1.to_string(), + }, + &[], + ) + .unwrap(); + + let cousin_count: GetCousinCountResponse = app + .wrap() + .query_wasm_smart(counter2.clone(), &QueryMsg::GetCousinCount {}) + .unwrap(); + assert_eq!(cousin_count.raw, cousin_count.smart); + assert_eq!(cousin_count.raw, 3); + + let cousin_count: GetCousinCountResponse = app + .wrap() + .query_wasm_smart(counter1.clone(), &QueryMsg::GetCousinCount {}) + .unwrap(); + assert_eq!(cousin_count.raw, cousin_count.smart); + assert_eq!(cousin_count.raw, 2); + + // Analyze the storage + + let analysis = StorageAnalyzer::new(&app, chain).unwrap(); + + log::info!( + "analysis, wasm1 {:?}", + analysis.get_contract_storage(counter1.clone()) + ); + log::info!("analysis, wasm1 {:?}", analysis.readable_storage(counter1)); + log::info!( + "analysis, wasm2 {:?}", + analysis.get_contract_storage(counter2.clone()) + ); + log::info!("analysis, wasm2 {:?}", analysis.readable_storage(counter2)); + log::info!( + "All contracts storage {:?}", + analysis.all_readable_contract_storage() + ); + analysis.compare_all_readable_contract_storage(); +} diff --git a/examples/test_app.rs b/examples/test_app.rs new file mode 100644 index 00000000..3b9d2562 --- /dev/null +++ b/examples/test_app.rs @@ -0,0 +1,72 @@ +use cosmwasm_std::Addr; +use cw20::AllAccountsResponse; +use cw20::Cw20ExecuteMsg; +use cw_multi_test::Executor; + +use cw20::Cw20QueryMsg; +use cw_multi_test::AppBuilder; +use cw_multi_test::BankKeeper; +use cw_multi_test::FailingModule; +use cw_orch_daemon::networks::PHOENIX_1; + +use cw_multi_test::WasmKeeper; + +use cosmwasm_std::Empty; + +pub fn main() { + env_logger::init(); + let mut wasm = WasmKeeper::::new(); + wasm.set_chain(PHOENIX_1.into()); + + let mut bank = BankKeeper::new(); + bank.set_chain(PHOENIX_1.into()); + + // First we instantiate a new app + let app = AppBuilder::default() + .with_wasm::, _>(wasm) + .with_bank(bank); + let mut app = app.build(|_, _, _| {}); + + // Then we send a message to the blockchain through the app + let sender = "terra17c6ts8grcfrgquhj3haclg44le8s7qkx6l2yx33acguxhpf000xqhnl3je"; + let recipient = "terra1e9lqmv3egtgps9nux04vw8gd4pr3qp9h00y8um"; + let contract_addr = "terra1lxx40s29qvkrcj8fsa3yzyehy7w50umdvvnls2r830rys6lu2zns63eelv"; + let query = "terra1e8lqmv3egtgps9nux04vw8gd4pr3qp9h00y7um"; + + let response: AllAccountsResponse = app + .wrap() + .query_wasm_smart( + contract_addr, + &Cw20QueryMsg::AllAccounts { + start_after: Some(query.to_string()), + limit: Some(30), + }, + ) + .unwrap(); + log::info!("Before transfer : {:?}", response); + + // We execute a transfer + app.execute_contract( + Addr::unchecked(sender), + Addr::unchecked(contract_addr), + &Cw20ExecuteMsg::Transfer { + recipient: recipient.to_string(), + amount: 1_000_000u128.into(), + }, + &[], + ) + .unwrap(); + + // We query to verify the state changed + let response: AllAccountsResponse = app + .wrap() + .query_wasm_smart( + contract_addr, + &Cw20QueryMsg::AllAccounts { + start_after: Some(query.to_string()), + limit: Some(30), + }, + ) + .unwrap(); + log::info!("After transfer : {:?}", response); +} diff --git a/src/app.rs b/src/app.rs index 43d8b5c7..c1c32a62 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,3 +1,8 @@ +use crate::wasm_emulation::api::RealApi; +use cosmwasm_std::CustomMsg; +use cw_storage_plus::Item; +use ibc_chain_registry::chain::ChainData; + use std::fmt::Debug; use std::marker::PhantomData; @@ -14,7 +19,6 @@ use serde::de::DeserializeOwned; use serde::Serialize; use crate::bank::{Bank, BankKeeper, BankSudo}; -use crate::contracts::Contract; use crate::executor::{AppResponse, Executor}; use crate::gov::Gov; use crate::ibc::Ibc; @@ -22,6 +26,12 @@ use crate::module::{FailingModule, Module}; use crate::staking::{Distribution, DistributionKeeper, StakeKeeper, Staking, StakingSudo}; use crate::transactions::transactional; use crate::wasm::{ContractData, Wasm, WasmKeeper, WasmSudo}; +use crate::wasm_emulation::contract::WasmContract; + +use crate::wasm_emulation::input::STARGATE_ALL_BANK_QUERY_URL; +use crate::wasm_emulation::input::STARGATE_ALL_WASM_QUERY_URL; + +const ADDRESSES: Item> = Item::new("addresses"); pub fn next_block(block: &mut BlockInfo) { block.time = block.time.plus_seconds(5); @@ -58,6 +68,7 @@ pub struct App< api: Api, storage: Storage, block: BlockInfo, + pub chain: Option, } fn no_init( @@ -99,7 +110,7 @@ impl BasicApp { /// Outside of `App` implementation to make type elision better. pub fn custom_app(init_fn: F) -> BasicApp where - ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static, + ExecC: CustomMsg + DeserializeOwned + 'static, QueryC: Debug + CustomQuery + DeserializeOwned + 'static, F: FnOnce( &mut Router< @@ -188,6 +199,7 @@ pub struct AppBuilder, } impl Default @@ -234,6 +246,7 @@ impl distribution: DistributionKeeper::new(), ibc: FailingModule::new(), gov: FailingModule::new(), + chain: None, } } } @@ -251,7 +264,7 @@ impl FailingModule, > where - ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static, + ExecC: CustomMsg + DeserializeOwned + 'static, QueryC: Debug + CustomQuery + DeserializeOwned + 'static, { /// Creates builder with default components designed to work with custom exec and query @@ -268,6 +281,7 @@ where distribution: DistributionKeeper::new(), ibc: FailingModule::new(), gov: FailingModule::new(), + chain: None, } } } @@ -298,6 +312,7 @@ impl distribution, ibc, gov, + chain, .. } = self; @@ -312,6 +327,7 @@ impl distribution, ibc, gov, + chain, } } @@ -330,6 +346,7 @@ impl distribution, ibc, gov, + chain, .. } = self; @@ -344,6 +361,7 @@ impl distribution, ibc, gov, + chain, } } @@ -362,6 +380,7 @@ impl distribution, ibc, gov, + chain, .. } = self; @@ -376,6 +395,7 @@ impl distribution, ibc, gov, + chain, } } @@ -394,6 +414,7 @@ impl distribution, ibc, gov, + chain, .. } = self; @@ -408,6 +429,7 @@ impl distribution, ibc, gov, + chain, } } @@ -434,6 +456,7 @@ impl distribution, ibc, gov, + chain, .. } = self; @@ -448,6 +471,7 @@ impl distribution, ibc, gov, + chain, } } @@ -466,6 +490,7 @@ impl distribution, ibc, gov, + chain, .. } = self; @@ -480,6 +505,7 @@ impl distribution, ibc, gov, + chain, } } @@ -499,6 +525,7 @@ impl bank, ibc, gov, + chain, .. } = self; @@ -513,6 +540,7 @@ impl distribution, ibc, gov, + chain, } } @@ -534,6 +562,7 @@ impl bank, distribution, gov, + chain, .. } = self; @@ -548,6 +577,7 @@ impl distribution, ibc, gov, + chain, } } @@ -566,6 +596,40 @@ impl bank, distribution, ibc, + chain, + .. + } = self; + + AppBuilder { + api, + block, + storage, + bank, + wasm, + custom, + staking, + distribution, + ibc, + gov, + chain, + } + } + /// Sets the chain of the app + pub fn with_chain( + self, + chain: ChainData, + ) -> AppBuilder { + let AppBuilder { + wasm, + api, + storage, + custom, + block, + staking, + bank, + distribution, + ibc, + gov, .. } = self; @@ -579,6 +643,7 @@ impl staking, distribution, ibc, + chain: Some(chain), gov, } } @@ -627,6 +692,7 @@ impl api: self.api, block: self.block, storage: self.storage, + chain: self.chain, }; app.init_modules(init_fn); app @@ -692,24 +758,20 @@ where DistrT: Distribution, IbcT: Ibc, GovT: Gov, - CustomT::ExecT: Clone + Debug + PartialEq + JsonSchema + DeserializeOwned + 'static, + CustomT::ExecT: CustomMsg + DeserializeOwned + 'static, CustomT::QueryT: CustomQuery + DeserializeOwned + 'static, { /// Registers contract code (like uploading wasm bytecode on a chain), /// so it can later be used to instantiate a contract. #[cfg(feature = "multitest_api_1_0")] - pub fn store_code( - &mut self, - creator: Addr, - code: Box>, - ) -> u64 { + pub fn store_code(&mut self, creator: Addr, code: WasmContract) -> u64 { self.init_modules(|router, _, _| router.wasm.store_code(creator, code)) } /// Registers contract code (like uploading wasm bytecode on a chain), /// so it can later be used to instantiate a contract. #[cfg(not(feature = "multitest_api_1_0"))] - pub fn store_code(&mut self, code: Box>) -> u64 { + pub fn store_code(&mut self, code: WasmContract) -> u64 { self.init_modules(|router, _, _| { router .wasm @@ -720,11 +782,7 @@ where /// Registers contract code (like [store_code](Self::store_code)), /// takes the code creator address as an additional argument. #[cfg(not(feature = "multitest_api_1_0"))] - pub fn store_code_with_creator( - &mut self, - creator: Addr, - code: Box>, - ) -> u64 { + pub fn store_code_with_creator(&mut self, creator: Addr, code: WasmContract) -> u64 { self.init_modules(|router, _, _| router.wasm.store_code(creator, code)) } @@ -824,6 +882,20 @@ where self.block.clone() } + /// Returns a new account address + pub fn next_address(&mut self) -> Addr { + let Self { storage, chain, .. } = self; + + let mut addresses = ADDRESSES.may_load(storage).unwrap().unwrap_or(vec![]); + + let new_address = + RealApi::new(&chain.clone().unwrap().bech32_prefix).next_address(addresses.len()); + addresses.push(new_address.clone()); + ADDRESSES.save(storage, &addresses).unwrap(); + + new_address + } + /// Simple helper so we get access to all the QuerierWrapper helpers, /// eg. wrap().query_wasm_smart, query_all_balances, ... pub fn wrap(&self) -> QuerierWrapper { @@ -847,6 +919,7 @@ where router, api, storage, + .. } = self; transactional(&mut *storage, |write_cache, _| { @@ -871,6 +944,7 @@ where router, api, storage, + .. } = self; transactional(&mut *storage, |write_cache, _| { @@ -892,6 +966,7 @@ where router, api, storage, + .. } = self; transactional(&mut *storage, |write_cache, _| { @@ -1053,6 +1128,12 @@ where QueryRequest::Custom(req) => self.custom.query(api, storage, &querier, block, req), QueryRequest::Staking(req) => self.staking.query(api, storage, &querier, block, req), QueryRequest::Ibc(req) => self.ibc.query(api, storage, &querier, block, req), + // We add those custom local stargate queries to mock querying all the local storage in order to propagate for the in-contract-querier + QueryRequest::Stargate { path, data: _ } => match path.as_str() { + STARGATE_ALL_WASM_QUERY_URL => Ok(to_binary(&self.wasm.query_all(storage)?)?), + STARGATE_ALL_BANK_QUERY_URL => Ok(to_binary(&self.bank.query_all(storage)?)?), + _ => unimplemented!(), + }, _ => unimplemented!(), } } @@ -1177,2050 +1258,3 @@ where SystemResult::Ok(contract_result) } } - -#[cfg(test)] -mod test { - use super::*; - use cosmwasm_std::testing::MockQuerier; - use cosmwasm_std::{ - coin, coins, to_binary, AllBalanceResponse, Attribute, BankMsg, BankQuery, Coin, Event, - OverflowError, OverflowOperation, Reply, StdError, StdResult, SubMsg, WasmMsg, - }; - - use crate::error::Error; - use crate::test_helpers::contracts::{caller, echo, error, hackatom, payout, reflect}; - use crate::test_helpers::CustomMsg; - use crate::transactions::StorageTransaction; - - #[test] - #[cfg(feature = "cosmwasm_1_2")] - fn duplicate_contract_code() { - // set up application - let mut app = App::default(); - - // store original contract code - #[cfg(not(feature = "multitest_api_1_0"))] - let original_code_id = app.store_code(payout::contract()); - #[cfg(feature = "multitest_api_1_0")] - let original_code_id = app.store_code(Addr::unchecked("creator"), payout::contract()); - - // duplicate contract code - let duplicate_code_id = app.duplicate_code(original_code_id).unwrap(); - assert_ne!(original_code_id, duplicate_code_id); - - // query and compare code info of both contracts - let original_response = app.wrap().query_wasm_code_info(original_code_id).unwrap(); - let duplicate_response = app.wrap().query_wasm_code_info(duplicate_code_id).unwrap(); - assert_ne!(original_response.code_id, duplicate_response.code_id); - assert_eq!(original_response.creator, duplicate_response.creator); - assert_eq!(original_response.checksum, duplicate_response.checksum); - } - - fn get_balance( - app: &App, - addr: &Addr, - ) -> Vec - where - CustomT::ExecT: Clone + Debug + PartialEq + JsonSchema + DeserializeOwned + 'static, - CustomT::QueryT: CustomQuery + DeserializeOwned + 'static, - WasmT: Wasm, - BankT: Bank, - ApiT: Api, - StorageT: Storage, - CustomT: Module, - { - app.wrap().query_all_balances(addr).unwrap() - } - - #[test] - fn update_block() { - let mut app = App::default(); - - let BlockInfo { time, height, .. } = app.block; - app.update_block(next_block); - - assert_eq!(time.plus_seconds(5), app.block.time); - assert_eq!(height + 1, app.block.height); - } - - #[test] - fn send_tokens() { - let owner = Addr::unchecked("owner"); - let rcpt = Addr::unchecked("receiver"); - let init_funds = vec![coin(20, "btc"), coin(100, "eth")]; - let rcpt_funds = vec![coin(5, "btc")]; - - let mut app = App::new(|router, _, storage| { - // initialization moved to App construction - router - .bank - .init_balance(storage, &owner, init_funds) - .unwrap(); - router - .bank - .init_balance(storage, &rcpt, rcpt_funds) - .unwrap(); - }); - - // send both tokens - let to_send = vec![coin(30, "eth"), coin(5, "btc")]; - let msg: CosmosMsg = BankMsg::Send { - to_address: rcpt.clone().into(), - amount: to_send, - } - .into(); - app.execute(owner.clone(), msg.clone()).unwrap(); - let rich = get_balance(&app, &owner); - assert_eq!(vec![coin(15, "btc"), coin(70, "eth")], rich); - let poor = get_balance(&app, &rcpt); - assert_eq!(vec![coin(10, "btc"), coin(30, "eth")], poor); - - // can send from other account (but funds will be deducted from sender) - app.execute(rcpt.clone(), msg).unwrap(); - - // cannot send too much - let msg = BankMsg::Send { - to_address: rcpt.into(), - amount: coins(20, "btc"), - } - .into(); - app.execute(owner.clone(), msg).unwrap_err(); - - let rich = get_balance(&app, &owner); - assert_eq!(vec![coin(15, "btc"), coin(70, "eth")], rich); - } - - #[test] - fn simple_contract() { - // set personal balance - let owner = Addr::unchecked("owner"); - let init_funds = vec![coin(20, "btc"), coin(100, "eth")]; - - let mut app = App::new(|router, _, storage| { - router - .bank - .init_balance(storage, &owner, init_funds) - .unwrap(); - }); - - // set up contract - #[cfg(not(feature = "multitest_api_1_0"))] - let code_id = app.store_code(payout::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code_id = app.store_code(Addr::unchecked("creator"), payout::contract()); - - let msg = payout::InstantiateMessage { - payout: coin(5, "eth"), - }; - let contract_addr = app - .instantiate_contract( - code_id, - owner.clone(), - &msg, - &coins(23, "eth"), - "Payout", - None, - ) - .unwrap(); - - let contract_data = app.contract_data(&contract_addr).unwrap(); - assert_eq!( - contract_data, - ContractData { - code_id, - creator: owner.clone(), - admin: None, - label: "Payout".to_owned(), - created: app.block_info().height - } - ); - - // sender funds deducted - let sender = get_balance(&app, &owner); - assert_eq!(sender, vec![coin(20, "btc"), coin(77, "eth")]); - // get contract address, has funds - let funds = get_balance(&app, &contract_addr); - assert_eq!(funds, coins(23, "eth")); - - // create empty account - let random = Addr::unchecked("random"); - let funds = get_balance(&app, &random); - assert_eq!(funds, vec![]); - - // do one payout and see money coming in - let res = app - .execute_contract(random.clone(), contract_addr.clone(), &Empty {}, &[]) - .unwrap(); - assert_eq!(3, res.events.len()); - - // the call to payout does emit this as well as custom attributes - let payout_exec = &res.events[0]; - assert_eq!(payout_exec.ty.as_str(), "execute"); - assert_eq!( - payout_exec.attributes, - [("_contract_address", &contract_addr)] - ); - - // next is a custom wasm event - let custom_attrs = res.custom_attrs(1); - assert_eq!(custom_attrs, [("action", "payout")]); - - // then the transfer event - let expected_transfer = Event::new("transfer") - .add_attribute("recipient", "random") - .add_attribute("sender", &contract_addr) - .add_attribute("amount", "5eth"); - assert_eq!(&expected_transfer, &res.events[2]); - - // random got cash - let funds = get_balance(&app, &random); - assert_eq!(funds, coins(5, "eth")); - // contract lost it - let funds = get_balance(&app, &contract_addr); - assert_eq!(funds, coins(18, "eth")); - } - - #[test] - fn reflect_success() { - // set personal balance - let owner = Addr::unchecked("owner"); - let init_funds = vec![coin(20, "btc"), coin(100, "eth")]; - - let mut app = custom_app::(|router, _, storage| { - router - .bank - .init_balance(storage, &owner, init_funds) - .unwrap(); - }); - - // set up payout contract - #[cfg(not(feature = "multitest_api_1_0"))] - let payout_id = app.store_code(payout::contract()); - #[cfg(feature = "multitest_api_1_0")] - let payout_id = app.store_code(Addr::unchecked("creator"), payout::contract()); - - let msg = payout::InstantiateMessage { - payout: coin(5, "eth"), - }; - let payout_addr = app - .instantiate_contract( - payout_id, - owner.clone(), - &msg, - &coins(23, "eth"), - "Payout", - None, - ) - .unwrap(); - - // set up reflect contract - #[cfg(not(feature = "multitest_api_1_0"))] - let reflect_id = app.store_code(reflect::contract()); - #[cfg(feature = "multitest_api_1_0")] - let reflect_id = app.store_code(Addr::unchecked("creator"), reflect::contract()); - - let reflect_addr = app - .instantiate_contract(reflect_id, owner, &Empty {}, &[], "Reflect", None) - .unwrap(); - - // reflect account is empty - let funds = get_balance(&app, &reflect_addr); - assert_eq!(funds, vec![]); - // reflect count is 1 - let query_res: payout::CountResponse = app - .wrap() - .query_wasm_smart(&reflect_addr, &reflect::QueryMsg::Count {}) - .unwrap(); - assert_eq!(0, query_res.count); - - // reflecting payout message pays reflect contract - let msg = SubMsg::new(WasmMsg::Execute { - contract_addr: payout_addr.clone().into(), - msg: b"{}".into(), - funds: vec![], - }); - let msgs = reflect::Message { - messages: vec![msg], - }; - let res = app - .execute_contract(Addr::unchecked("random"), reflect_addr.clone(), &msgs, &[]) - .unwrap(); - - // ensure the attributes were relayed from the sub-message - assert_eq!(4, res.events.len(), "{:?}", res.events); - - // reflect only returns standard wasm-execute event - let ref_exec = &res.events[0]; - assert_eq!(ref_exec.ty.as_str(), "execute"); - assert_eq!(ref_exec.attributes, [("_contract_address", &reflect_addr)]); - - // the call to payout does emit this as well as custom attributes - let payout_exec = &res.events[1]; - assert_eq!(payout_exec.ty.as_str(), "execute"); - assert_eq!( - payout_exec.attributes, - [("_contract_address", &payout_addr)] - ); - - let payout = &res.events[2]; - assert_eq!(payout.ty.as_str(), "wasm"); - assert_eq!( - payout.attributes, - [ - ("_contract_address", payout_addr.as_str()), - ("action", "payout") - ] - ); - - // final event is the transfer from bank - let second = &res.events[3]; - assert_eq!(second.ty.as_str(), "transfer"); - assert_eq!(3, second.attributes.len()); - assert_eq!(second.attributes[0], ("recipient", &reflect_addr)); - assert_eq!(second.attributes[1], ("sender", &payout_addr)); - assert_eq!(second.attributes[2], ("amount", "5eth")); - - // ensure transfer was executed with reflect as sender - let funds = get_balance(&app, &reflect_addr); - assert_eq!(funds, coins(5, "eth")); - - // reflect count updated - let query_res: payout::CountResponse = app - .wrap() - .query_wasm_smart(&reflect_addr, &reflect::QueryMsg::Count {}) - .unwrap(); - assert_eq!(1, query_res.count); - } - - #[test] - fn reflect_error() { - // set personal balance - let owner = Addr::unchecked("owner"); - let init_funds = vec![coin(20, "btc"), coin(100, "eth")]; - - let mut app = custom_app::(|router, _, storage| { - router - .bank - .init_balance(storage, &owner, init_funds) - .unwrap(); - }); - - // set up reflect contract - #[cfg(not(feature = "multitest_api_1_0"))] - let reflect_id = app.store_code(reflect::contract()); - #[cfg(feature = "multitest_api_1_0")] - let reflect_id = app.store_code(Addr::unchecked("creator"), reflect::contract()); - - let reflect_addr = app - .instantiate_contract( - reflect_id, - owner, - &Empty {}, - &coins(40, "eth"), - "Reflect", - None, - ) - .unwrap(); - - // reflect has 40 eth - let funds = get_balance(&app, &reflect_addr); - assert_eq!(funds, coins(40, "eth")); - let random = Addr::unchecked("random"); - - // sending 7 eth works - let msg = SubMsg::new(BankMsg::Send { - to_address: random.clone().into(), - amount: coins(7, "eth"), - }); - let msgs = reflect::Message { - messages: vec![msg], - }; - let res = app - .execute_contract(random.clone(), reflect_addr.clone(), &msgs, &[]) - .unwrap(); - // no wasm events as no attributes - assert_eq!(2, res.events.len()); - // standard wasm-execute event - let exec = &res.events[0]; - assert_eq!(exec.ty.as_str(), "execute"); - assert_eq!(exec.attributes, [("_contract_address", &reflect_addr)]); - // only transfer event from bank - let transfer = &res.events[1]; - assert_eq!(transfer.ty.as_str(), "transfer"); - - // ensure random got paid - let funds = get_balance(&app, &random); - assert_eq!(funds, coins(7, "eth")); - - // reflect count should be updated to 1 - let query_res: payout::CountResponse = app - .wrap() - .query_wasm_smart(&reflect_addr, &reflect::QueryMsg::Count {}) - .unwrap(); - assert_eq!(1, query_res.count); - - // sending 8 eth, then 3 btc should fail both - let msg = SubMsg::new(BankMsg::Send { - to_address: random.clone().into(), - amount: coins(8, "eth"), - }); - let msg2 = SubMsg::new(BankMsg::Send { - to_address: random.clone().into(), - amount: coins(3, "btc"), - }); - let msgs = reflect::Message { - messages: vec![msg, msg2], - }; - let err = app - .execute_contract(random.clone(), reflect_addr.clone(), &msgs, &[]) - .unwrap_err(); - assert_eq!( - StdError::overflow(OverflowError::new(OverflowOperation::Sub, 0, 3)), - err.downcast().unwrap() - ); - - // first one should have been rolled-back on error (no second payment) - let funds = get_balance(&app, &random); - assert_eq!(funds, coins(7, "eth")); - - // failure should not update reflect count - let query_res: payout::CountResponse = app - .wrap() - .query_wasm_smart(&reflect_addr, &reflect::QueryMsg::Count {}) - .unwrap(); - assert_eq!(1, query_res.count); - } - - #[test] - fn sudo_works() { - let owner = Addr::unchecked("owner"); - let init_funds = vec![coin(100, "eth")]; - - let mut app = App::new(|router, _, storage| { - router - .bank - .init_balance(storage, &owner, init_funds) - .unwrap(); - }); - - #[cfg(not(feature = "multitest_api_1_0"))] - let payout_id = app.store_code(payout::contract()); - #[cfg(feature = "multitest_api_1_0")] - let payout_id = app.store_code(Addr::unchecked("creator"), payout::contract()); - - let msg = payout::InstantiateMessage { - payout: coin(5, "eth"), - }; - let payout_addr = app - .instantiate_contract(payout_id, owner, &msg, &coins(23, "eth"), "Payout", None) - .unwrap(); - - // count is 1 - let payout::CountResponse { count } = app - .wrap() - .query_wasm_smart(&payout_addr, &payout::QueryMsg::Count {}) - .unwrap(); - assert_eq!(1, count); - - // wasm_sudo call - let msg = payout::SudoMsg { set_count: 25 }; - app.wasm_sudo(payout_addr.clone(), &msg).unwrap(); - - // count is 25 - let payout::CountResponse { count } = app - .wrap() - .query_wasm_smart(&payout_addr, &payout::QueryMsg::Count {}) - .unwrap(); - assert_eq!(25, count); - - // we can do the same with sudo call - let msg = payout::SudoMsg { set_count: 49 }; - let sudo_msg = WasmSudo { - contract_addr: payout_addr.clone(), - msg: to_binary(&msg).unwrap(), - }; - app.sudo(sudo_msg.into()).unwrap(); - - let payout::CountResponse { count } = app - .wrap() - .query_wasm_smart(&payout_addr, &payout::QueryMsg::Count {}) - .unwrap(); - assert_eq!(49, count); - } - - // this demonstrates that we can mint tokens and send from other accounts via a custom module, - // as an example of ability to do privileged actions - mod custom_handler { - use super::*; - - use anyhow::{bail, Result as AnyResult}; - use cw_storage_plus::Item; - use serde::{Deserialize, Serialize}; - - use crate::Executor; - - const LOTTERY: Item = Item::new("lottery"); - const PITY: Item = Item::new("pity"); - - #[derive(Clone, Debug, PartialEq, JsonSchema, Serialize, Deserialize)] - struct CustomMsg { - // we mint LOTTERY tokens to this one - lucky_winner: String, - // we transfer PITY from lucky_winner to runner_up - runner_up: String, - } - - struct CustomHandler {} - - impl Module for CustomHandler { - type ExecT = CustomMsg; - type QueryT = Empty; - type SudoT = Empty; - - fn execute( - &self, - api: &dyn Api, - storage: &mut dyn Storage, - router: &dyn CosmosRouter, - block: &BlockInfo, - _sender: Addr, - msg: Self::ExecT, - ) -> AnyResult - where - ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static, - QueryC: CustomQuery + DeserializeOwned + 'static, - { - let lottery = LOTTERY.load(storage)?; - let pity = PITY.load(storage)?; - - // mint new tokens - let mint = BankSudo::Mint { - to_address: msg.lucky_winner.clone(), - amount: vec![lottery], - }; - router.sudo(api, storage, block, mint.into())?; - - // send from an arbitrary account (not the module) - let transfer = BankMsg::Send { - to_address: msg.runner_up, - amount: vec![pity], - }; - let rcpt = api.addr_validate(&msg.lucky_winner)?; - router.execute(api, storage, block, rcpt, transfer.into())?; - - Ok(AppResponse::default()) - } - - fn sudo( - &self, - _api: &dyn Api, - _storage: &mut dyn Storage, - _router: &dyn CosmosRouter, - _block: &BlockInfo, - _msg: Self::SudoT, - ) -> AnyResult - where - ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static, - QueryC: CustomQuery + DeserializeOwned + 'static, - { - bail!("sudo not implemented for CustomHandler") - } - - fn query( - &self, - _api: &dyn Api, - _storage: &dyn Storage, - _querier: &dyn Querier, - _block: &BlockInfo, - _request: Self::QueryT, - ) -> AnyResult { - bail!("query not implemented for CustomHandler") - } - } - - impl CustomHandler { - // this is a custom initialization method - pub fn set_payout( - &self, - storage: &mut dyn Storage, - lottery: Coin, - pity: Coin, - ) -> AnyResult<()> { - LOTTERY.save(storage, &lottery)?; - PITY.save(storage, &pity)?; - Ok(()) - } - } - - // let's call this custom handler - #[test] - fn dispatches_messages() { - let winner = "winner".to_string(); - let second = "second".to_string(); - - // payments. note 54321 - 12321 = 42000 - let denom = "tix"; - let lottery = coin(54321, denom); - let bonus = coin(12321, denom); - - let mut app = BasicAppBuilder::::new_custom() - .with_custom(CustomHandler {}) - .build(|router, _, storage| { - router - .custom - .set_payout(storage, lottery.clone(), bonus.clone()) - .unwrap(); - }); - - // query that balances are empty - let start = app.wrap().query_balance(&winner, denom).unwrap(); - assert_eq!(start, coin(0, denom)); - - // trigger the custom module - let msg = CosmosMsg::Custom(CustomMsg { - lucky_winner: winner.clone(), - runner_up: second.clone(), - }); - app.execute(Addr::unchecked("anyone"), msg).unwrap(); - - // see if coins were properly added - let big_win = app.wrap().query_balance(&winner, denom).unwrap(); - assert_eq!(big_win, coin(42000, denom)); - let little_win = app.wrap().query_balance(&second, denom).unwrap(); - assert_eq!(little_win, bonus); - } - } - - #[test] - fn reflect_sub_message_reply_works() { - // set personal balance - let owner = Addr::unchecked("owner"); - let random = Addr::unchecked("random"); - let init_funds = vec![coin(20, "btc"), coin(100, "eth")]; - - let mut app = custom_app::(|router, _, storage| { - router - .bank - .init_balance(storage, &owner, init_funds) - .unwrap(); - }); - - // set up reflect contract - #[cfg(not(feature = "multitest_api_1_0"))] - let reflect_id = app.store_code(reflect::contract()); - #[cfg(feature = "multitest_api_1_0")] - let reflect_id = app.store_code(Addr::unchecked("creator"), reflect::contract()); - - let reflect_addr = app - .instantiate_contract( - reflect_id, - owner, - &Empty {}, - &coins(40, "eth"), - "Reflect", - None, - ) - .unwrap(); - - // no reply writen beforehand - let query = reflect::QueryMsg::Reply { id: 123 }; - let res: StdResult = app.wrap().query_wasm_smart(&reflect_addr, &query); - res.unwrap_err(); - - // reflect sends 7 eth, success - let msg = SubMsg::reply_always( - BankMsg::Send { - to_address: random.clone().into(), - amount: coins(7, "eth"), - }, - 123, - ); - let msgs = reflect::Message { - messages: vec![msg], - }; - let res = app - .execute_contract(random.clone(), reflect_addr.clone(), &msgs, &[]) - .unwrap(); - - // expected events: execute, transfer, reply, custom wasm (set in reply) - assert_eq!(4, res.events.len(), "{:?}", res.events); - res.assert_event(&Event::new("execute").add_attribute("_contract_address", &reflect_addr)); - res.assert_event(&Event::new("transfer").add_attribute("amount", "7eth")); - res.assert_event( - &Event::new("reply") - .add_attribute("_contract_address", reflect_addr.as_str()) - .add_attribute("mode", "handle_success"), - ); - res.assert_event(&Event::new("wasm-custom").add_attribute("from", "reply")); - - // ensure success was written - let res: Reply = app.wrap().query_wasm_smart(&reflect_addr, &query).unwrap(); - assert_eq!(res.id, 123); - // validate the events written in the reply blob...should just be bank transfer - let reply = res.result.unwrap(); - assert_eq!(1, reply.events.len()); - AppResponse::from(reply) - .assert_event(&Event::new("transfer").add_attribute("amount", "7eth")); - - // reflect sends 300 btc, failure, but error caught by sub-message (so shows success) - let msg = SubMsg::reply_always( - BankMsg::Send { - to_address: random.clone().into(), - amount: coins(300, "btc"), - }, - 456, - ); - let msgs = reflect::Message { - messages: vec![msg], - }; - let _res = app - .execute_contract(random, reflect_addr.clone(), &msgs, &[]) - .unwrap(); - - // ensure error was written - let query = reflect::QueryMsg::Reply { id: 456 }; - let res: Reply = app.wrap().query_wasm_smart(&reflect_addr, &query).unwrap(); - assert_eq!(res.id, 456); - assert!(res.result.is_err()); - // TODO: check error? - } - - fn query_router( - router: &Router, - api: &dyn Api, - storage: &dyn Storage, - rcpt: &Addr, - ) -> Vec - where - CustomT::ExecT: Clone + Debug + PartialEq + JsonSchema, - CustomT::QueryT: CustomQuery + DeserializeOwned, - WasmT: Wasm, - BankT: Bank, - CustomT: Module, - StakingT: Staking, - DistrT: Distribution, - { - let query = BankQuery::AllBalances { - address: rcpt.into(), - }; - let block = mock_env().block; - let querier: MockQuerier = MockQuerier::new(&[]); - let res = router - .bank - .query(api, storage, &querier, &block, query) - .unwrap(); - let val: AllBalanceResponse = from_slice(&res).unwrap(); - val.amount - } - - fn query_app( - app: &App, - rcpt: &Addr, - ) -> Vec - where - CustomT::ExecT: Debug + PartialEq + Clone + JsonSchema + DeserializeOwned + 'static, - CustomT::QueryT: CustomQuery + DeserializeOwned + 'static, - WasmT: Wasm, - BankT: Bank, - ApiT: Api, - StorageT: Storage, - CustomT: Module, - StakingT: Staking, - DistrT: Distribution, - { - let query = BankQuery::AllBalances { - address: rcpt.into(), - } - .into(); - let val: AllBalanceResponse = app.wrap().query(&query).unwrap(); - val.amount - } - - #[test] - fn multi_level_bank_cache() { - // set personal balance - let owner = Addr::unchecked("owner"); - let rcpt = Addr::unchecked("recipient"); - let init_funds = vec![coin(20, "btc"), coin(100, "eth")]; - - let mut app = App::new(|router, _, storage| { - router - .bank - .init_balance(storage, &owner, init_funds) - .unwrap(); - }); - - // cache 1 - send some tokens - let mut cache = StorageTransaction::new(&app.storage); - let msg = BankMsg::Send { - to_address: rcpt.clone().into(), - amount: coins(25, "eth"), - }; - app.router - .execute(&app.api, &mut cache, &app.block, owner.clone(), msg.into()) - .unwrap(); - - // shows up in cache - let cached_rcpt = query_router(&app.router, &app.api, &cache, &rcpt); - assert_eq!(coins(25, "eth"), cached_rcpt); - let router_rcpt = query_app(&app, &rcpt); - assert_eq!(router_rcpt, vec![]); - - // now, second level cache - transactional(&mut cache, |cache2, read| { - let msg = BankMsg::Send { - to_address: rcpt.clone().into(), - amount: coins(12, "eth"), - }; - app.router - .execute(&app.api, cache2, &app.block, owner, msg.into()) - .unwrap(); - - // shows up in 2nd cache - let cached_rcpt = query_router(&app.router, &app.api, read, &rcpt); - assert_eq!(coins(25, "eth"), cached_rcpt); - let cached2_rcpt = query_router(&app.router, &app.api, cache2, &rcpt); - assert_eq!(coins(37, "eth"), cached2_rcpt); - Ok(()) - }) - .unwrap(); - - // apply first to router - cache.prepare().commit(&mut app.storage); - - let committed = query_app(&app, &rcpt); - assert_eq!(coins(37, "eth"), committed); - } - - #[test] - fn sent_funds_properly_visible_on_execution() { - // Testing if funds on contract are properly visible on contract. - // Hackatom contract is initialized with 10btc. Then, the contract is executed, with - // additional 20btc. Then beneficiary balance is checked - expected value is 30btc. 10btc - // would mean that sending tokens with message is not visible for this very message, and - // 20btc means, that only such just send funds are visible. - let owner = Addr::unchecked("owner"); - let beneficiary = Addr::unchecked("beneficiary"); - let init_funds = coins(30, "btc"); - - let mut app = App::new(|router, _, storage| { - router - .bank - .init_balance(storage, &owner, init_funds) - .unwrap(); - }); - - #[cfg(not(feature = "multitest_api_1_0"))] - let code_id = app.store_code(hackatom::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code_id = app.store_code(Addr::unchecked("creator"), hackatom::contract()); - - let contract = app - .instantiate_contract( - code_id, - owner.clone(), - &hackatom::InstantiateMsg { - beneficiary: beneficiary.as_str().to_owned(), - }, - &coins(10, "btc"), - "Hackatom", - None, - ) - .unwrap(); - - app.execute_contract( - owner.clone(), - contract.clone(), - &Empty {}, - &coins(20, "btc"), - ) - .unwrap(); - - // Check balance of all accounts to ensure no tokens where burned or created, and they are - // in correct places - assert_eq!(get_balance(&app, &owner), &[]); - assert_eq!(get_balance(&app, &contract), &[]); - assert_eq!(get_balance(&app, &beneficiary), coins(30, "btc")); - } - - #[test] - fn sent_wasm_migration_works() { - // The plan: - // create a hackatom contract with some funds - // check admin set properly - // check beneficiary set properly - // migrate fails if not admin - // migrate succeeds if admin - // check beneficiary updated - let owner = Addr::unchecked("owner"); - let beneficiary = Addr::unchecked("beneficiary"); - let init_funds = coins(30, "btc"); - - let mut app = App::new(|router, _, storage| { - router - .bank - .init_balance(storage, &owner, init_funds) - .unwrap(); - }); - - // create a hackatom contract with some funds - #[cfg(not(feature = "multitest_api_1_0"))] - let code_id = app.store_code(hackatom::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code_id = app.store_code(Addr::unchecked("creator"), hackatom::contract()); - - let contract = app - .instantiate_contract( - code_id, - owner.clone(), - &hackatom::InstantiateMsg { - beneficiary: beneficiary.as_str().to_owned(), - }, - &coins(20, "btc"), - "Hackatom", - Some(owner.to_string()), - ) - .unwrap(); - - // check admin set properly - let info = app.contract_data(&contract).unwrap(); - assert_eq!(info.admin, Some(owner.clone())); - // check beneficiary set properly - let state: hackatom::InstantiateMsg = app - .wrap() - .query_wasm_smart(&contract, &hackatom::QueryMsg::Beneficiary {}) - .unwrap(); - assert_eq!(state.beneficiary, beneficiary); - - // migrate fails if not admin - let random = Addr::unchecked("random"); - let migrate_msg = hackatom::MigrateMsg { - new_guy: random.to_string(), - }; - app.migrate_contract(beneficiary, contract.clone(), &migrate_msg, code_id) - .unwrap_err(); - - // migrate fails if unregistered code id - app.migrate_contract(owner.clone(), contract.clone(), &migrate_msg, code_id + 7) - .unwrap_err(); - - // migrate succeeds when the stars align - app.migrate_contract(owner, contract.clone(), &migrate_msg, code_id) - .unwrap(); - - // check beneficiary updated - let state: hackatom::InstantiateMsg = app - .wrap() - .query_wasm_smart(&contract, &hackatom::QueryMsg::Beneficiary {}) - .unwrap(); - assert_eq!(state.beneficiary, random); - } - - #[test] - fn send_update_admin_works() { - // The plan: - // create a hackatom contract - // check admin set properly - // update admin succeeds if admin - // update admin fails if not (new) admin - // check admin set properly - let owner = Addr::unchecked("owner"); - let owner2 = Addr::unchecked("owner2"); - let beneficiary = Addr::unchecked("beneficiary"); - - let mut app = App::default(); - - // create a hackatom contract with some funds - #[cfg(not(feature = "multitest_api_1_0"))] - let code_id = app.store_code(hackatom::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code_id = app.store_code(Addr::unchecked("creator"), hackatom::contract()); - - let contract = app - .instantiate_contract( - code_id, - owner.clone(), - &hackatom::InstantiateMsg { - beneficiary: beneficiary.as_str().to_owned(), - }, - &[], - "Hackatom", - Some(owner.to_string()), - ) - .unwrap(); - - // check admin set properly - let info = app.contract_data(&contract).unwrap(); - assert_eq!(info.admin, Some(owner.clone())); - - // transfer admin permissions to owner2 - app.execute( - owner.clone(), - CosmosMsg::Wasm(WasmMsg::UpdateAdmin { - contract_addr: contract.to_string(), - admin: owner2.to_string(), - }), - ) - .unwrap(); - - // check admin set properly - let info = app.contract_data(&contract).unwrap(); - assert_eq!(info.admin, Some(owner2.clone())); - - // update admin fails if not owner2 - app.execute( - owner.clone(), - CosmosMsg::Wasm(WasmMsg::UpdateAdmin { - contract_addr: contract.to_string(), - admin: owner.to_string(), - }), - ) - .unwrap_err(); - - // check admin still the same - let info = app.contract_data(&contract).unwrap(); - assert_eq!(info.admin, Some(owner2)); - } - - mod reply_data_overwrite { - use super::*; - - use echo::EXECUTE_REPLY_BASE_ID; - - fn make_echo_submsg( - contract: Addr, - data: impl Into>, - sub_msg: Vec, - id: u64, - ) -> SubMsg { - let data = data.into().map(|s| s.to_owned()); - SubMsg::reply_always( - CosmosMsg::Wasm(WasmMsg::Execute { - contract_addr: contract.into(), - msg: to_binary(&echo::Message { - data, - sub_msg, - ..echo::Message::default() - }) - .unwrap(), - funds: vec![], - }), - id, - ) - } - - fn make_echo_submsg_no_reply( - contract: Addr, - data: impl Into>, - sub_msg: Vec, - ) -> SubMsg { - let data = data.into().map(|s| s.to_owned()); - SubMsg::new(CosmosMsg::Wasm(WasmMsg::Execute { - contract_addr: contract.into(), - msg: to_binary(&echo::Message { - data, - sub_msg, - ..echo::Message::default() - }) - .unwrap(), - funds: vec![], - })) - } - - #[test] - fn no_submsg() { - let mut app = App::default(); - - let owner = Addr::unchecked("owner"); - - #[cfg(not(feature = "multitest_api_1_0"))] - let code_id = app.store_code(echo::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code_id = app.store_code(Addr::unchecked("creator"), echo::contract()); - - let contract = app - .instantiate_contract(code_id, owner.clone(), &Empty {}, &[], "Echo", None) - .unwrap(); - - let response = app - .execute_contract( - owner, - contract, - &echo::Message:: { - data: Some("Data".to_owned()), - ..echo::Message::default() - }, - &[], - ) - .unwrap(); - - assert_eq!(response.data, Some(b"Data".into())); - } - - #[test] - fn single_submsg() { - let mut app = App::default(); - - let owner = Addr::unchecked("owner"); - - #[cfg(not(feature = "multitest_api_1_0"))] - let code_id = app.store_code(echo::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code_id = app.store_code(Addr::unchecked("creator"), echo::contract()); - - let contract = app - .instantiate_contract(code_id, owner.clone(), &Empty {}, &[], "Echo", None) - .unwrap(); - - let response = app - .execute_contract( - owner, - contract.clone(), - &echo::Message { - data: Some("First".to_owned()), - sub_msg: vec![make_echo_submsg( - contract, - "Second", - vec![], - EXECUTE_REPLY_BASE_ID, - )], - ..echo::Message::default() - }, - &[], - ) - .unwrap(); - - assert_eq!(response.data, Some(b"Second".into())); - } - - #[test] - fn single_submsg_no_reply() { - let mut app = App::default(); - - let owner = Addr::unchecked("owner"); - - #[cfg(not(feature = "multitest_api_1_0"))] - let code_id = app.store_code(echo::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code_id = app.store_code(Addr::unchecked("creator"), echo::contract()); - - let contract = app - .instantiate_contract(code_id, owner.clone(), &Empty {}, &[], "Echo", None) - .unwrap(); - - let response = app - .execute_contract( - owner, - contract.clone(), - &echo::Message { - data: Some("First".to_owned()), - sub_msg: vec![make_echo_submsg_no_reply(contract, "Second", vec![])], - ..echo::Message::default() - }, - &[], - ) - .unwrap(); - - assert_eq!(response.data, Some(b"First".into())); - } - - #[test] - fn single_no_submsg_data() { - let mut app = App::default(); - - let owner = Addr::unchecked("owner"); - - #[cfg(not(feature = "multitest_api_1_0"))] - let code_id = app.store_code(echo::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code_id = app.store_code(Addr::unchecked("creator"), echo::contract()); - - let contract = app - .instantiate_contract(code_id, owner.clone(), &Empty {}, &[], "Echo", None) - .unwrap(); - - let response = app - .execute_contract( - owner, - contract.clone(), - &echo::Message { - data: Some("First".to_owned()), - sub_msg: vec![make_echo_submsg(contract, None, vec![], 1)], - ..echo::Message::default() - }, - &[], - ) - .unwrap(); - - assert_eq!(response.data, Some(b"First".into())); - } - - #[test] - fn single_no_top_level_data() { - let mut app = App::default(); - - let owner = Addr::unchecked("owner"); - - #[cfg(not(feature = "multitest_api_1_0"))] - let code_id = app.store_code(echo::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code_id = app.store_code(Addr::unchecked("creator"), echo::contract()); - - let contract = app - .instantiate_contract(code_id, owner.clone(), &Empty {}, &[], "Echo", None) - .unwrap(); - - let response = app - .execute_contract( - owner, - contract.clone(), - &echo::Message { - sub_msg: vec![make_echo_submsg( - contract, - "Second", - vec![], - EXECUTE_REPLY_BASE_ID, - )], - ..echo::Message::default() - }, - &[], - ) - .unwrap(); - - assert_eq!(response.data, Some(b"Second".into())); - } - - #[test] - fn single_submsg_reply_returns_none() { - // set personal balance - let owner = Addr::unchecked("owner"); - let init_funds = coins(100, "tgd"); - - let mut app = custom_app::(|router, _, storage| { - router - .bank - .init_balance(storage, &owner, init_funds) - .unwrap(); - }); - - // set up reflect contract - #[cfg(not(feature = "multitest_api_1_0"))] - let reflect_id = app.store_code(reflect::contract()); - #[cfg(feature = "multitest_api_1_0")] - let reflect_id = app.store_code(Addr::unchecked("creator"), reflect::contract()); - - let reflect_addr = app - .instantiate_contract(reflect_id, owner.clone(), &Empty {}, &[], "Reflect", None) - .unwrap(); - - // set up echo contract - #[cfg(not(feature = "multitest_api_1_0"))] - let echo_id = app.store_code(echo::custom_contract()); - #[cfg(feature = "multitest_api_1_0")] - let echo_id = app.store_code(Addr::unchecked("creator"), echo::custom_contract()); - - let echo_addr = app - .instantiate_contract(echo_id, owner.clone(), &Empty {}, &[], "Echo", None) - .unwrap(); - - // reflect will call echo - // echo will set the data - // top-level app will not display the data - let echo_msg = echo::Message:: { - data: Some("my echo".into()), - events: vec![Event::new("echo").add_attribute("called", "true")], - ..echo::Message::default() - }; - let reflect_msg = reflect::Message { - messages: vec![SubMsg::new(WasmMsg::Execute { - contract_addr: echo_addr.to_string(), - msg: to_binary(&echo_msg).unwrap(), - funds: vec![], - })], - }; - - let res = app - .execute_contract(owner, reflect_addr.clone(), &reflect_msg, &[]) - .unwrap(); - - // ensure data is empty - assert_eq!(res.data, None); - // ensure expected events - assert_eq!(res.events.len(), 3, "{:?}", res.events); - res.assert_event( - &Event::new("execute").add_attribute("_contract_address", &reflect_addr), - ); - res.assert_event(&Event::new("execute").add_attribute("_contract_address", &echo_addr)); - res.assert_event(&Event::new("wasm-echo")); - } - - #[test] - fn multiple_submsg() { - let mut app = App::default(); - - let owner = Addr::unchecked("owner"); - - #[cfg(not(feature = "multitest_api_1_0"))] - let code_id = app.store_code(echo::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code_id = app.store_code(Addr::unchecked("creator"), echo::contract()); - - let contract = app - .instantiate_contract(code_id, owner.clone(), &Empty {}, &[], "Echo", None) - .unwrap(); - - let response = app - .execute_contract( - owner, - contract.clone(), - &echo::Message { - data: Some("Orig".to_owned()), - sub_msg: vec![ - make_echo_submsg( - contract.clone(), - None, - vec![], - EXECUTE_REPLY_BASE_ID + 1, - ), - make_echo_submsg( - contract.clone(), - "First", - vec![], - EXECUTE_REPLY_BASE_ID + 2, - ), - make_echo_submsg( - contract.clone(), - "Second", - vec![], - EXECUTE_REPLY_BASE_ID + 3, - ), - make_echo_submsg(contract, None, vec![], EXECUTE_REPLY_BASE_ID + 4), - ], - ..echo::Message::default() - }, - &[], - ) - .unwrap(); - - assert_eq!(response.data, Some(b"Second".into())); - } - - #[test] - fn multiple_submsg_no_reply() { - let mut app = App::default(); - - let owner = Addr::unchecked("owner"); - - #[cfg(not(feature = "multitest_api_1_0"))] - let code_id = app.store_code(echo::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code_id = app.store_code(Addr::unchecked("creator"), echo::contract()); - - let contract = app - .instantiate_contract(code_id, owner.clone(), &Empty {}, &[], "Echo", None) - .unwrap(); - - let response = app - .execute_contract( - owner, - contract.clone(), - &echo::Message { - data: Some("Orig".to_owned()), - sub_msg: vec![ - make_echo_submsg_no_reply(contract.clone(), None, vec![]), - make_echo_submsg_no_reply(contract.clone(), "First", vec![]), - make_echo_submsg_no_reply(contract.clone(), "Second", vec![]), - make_echo_submsg_no_reply(contract, None, vec![]), - ], - ..echo::Message::default() - }, - &[], - ) - .unwrap(); - - assert_eq!(response.data, Some(b"Orig".into())); - } - - #[test] - fn multiple_submsg_mixed() { - let mut app = App::default(); - - let owner = Addr::unchecked("owner"); - - #[cfg(not(feature = "multitest_api_1_0"))] - let code_id = app.store_code(echo::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code_id = app.store_code(Addr::unchecked("creator"), echo::contract()); - - let contract = app - .instantiate_contract(code_id, owner.clone(), &Empty {}, &[], "Echo", None) - .unwrap(); - - let response = app - .execute_contract( - owner, - contract.clone(), - &echo::Message { - sub_msg: vec![ - make_echo_submsg( - contract.clone(), - None, - vec![], - EXECUTE_REPLY_BASE_ID + 1, - ), - make_echo_submsg_no_reply(contract.clone(), "Hidden", vec![]), - make_echo_submsg( - contract.clone(), - "Shown", - vec![], - EXECUTE_REPLY_BASE_ID + 2, - ), - make_echo_submsg( - contract.clone(), - None, - vec![], - EXECUTE_REPLY_BASE_ID + 3, - ), - make_echo_submsg_no_reply(contract, "Lost", vec![]), - ], - ..echo::Message::default() - }, - &[], - ) - .unwrap(); - - assert_eq!(response.data, Some(b"Shown".into())); - } - - #[test] - fn nested_submsg() { - let mut app = App::default(); - - let owner = Addr::unchecked("owner"); - - #[cfg(not(feature = "multitest_api_1_0"))] - let code_id = app.store_code(echo::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code_id = app.store_code(Addr::unchecked("creator"), echo::contract()); - - let contract = app - .instantiate_contract(code_id, owner.clone(), &Empty {}, &[], "Echo", None) - .unwrap(); - - let response = app - .execute_contract( - owner, - contract.clone(), - &echo::Message { - data: Some("Orig".to_owned()), - sub_msg: vec![make_echo_submsg( - contract.clone(), - None, - vec![make_echo_submsg( - contract.clone(), - "First", - vec![make_echo_submsg( - contract.clone(), - "Second", - vec![make_echo_submsg( - contract, - None, - vec![], - EXECUTE_REPLY_BASE_ID + 4, - )], - EXECUTE_REPLY_BASE_ID + 3, - )], - EXECUTE_REPLY_BASE_ID + 2, - )], - EXECUTE_REPLY_BASE_ID + 1, - )], - ..echo::Message::default() - }, - &[], - ) - .unwrap(); - - assert_eq!(response.data, Some(b"Second".into())); - } - } - - mod response_validation { - use super::*; - - #[test] - fn empty_attribute_key() { - let mut app = App::default(); - - let owner = Addr::unchecked("owner"); - - #[cfg(not(feature = "multitest_api_1_0"))] - let code_id = app.store_code(echo::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code_id = app.store_code(Addr::unchecked("creator"), echo::contract()); - - let contract = app - .instantiate_contract(code_id, owner.clone(), &Empty {}, &[], "Echo", None) - .unwrap(); - - let err = app - .execute_contract( - owner, - contract, - &echo::Message:: { - data: None, - attributes: vec![ - Attribute::new(" ", "value"), - Attribute::new("proper", "proper_val"), - ], - ..echo::Message::default() - }, - &[], - ) - .unwrap_err(); - - assert_eq!(Error::empty_attribute_key("value"), err.downcast().unwrap(),); - } - - #[test] - fn empty_attribute_value() { - let mut app = App::default(); - - let owner = Addr::unchecked("owner"); - - #[cfg(not(feature = "multitest_api_1_0"))] - let code_id = app.store_code(echo::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code_id = app.store_code(Addr::unchecked("creator"), echo::contract()); - - let contract = app - .instantiate_contract(code_id, owner.clone(), &Empty {}, &[], "Echo", None) - .unwrap(); - - let err = app - .execute_contract( - owner, - contract, - &echo::Message:: { - data: None, - attributes: vec![ - Attribute::new("key", " "), - Attribute::new("proper", "proper_val"), - ], - ..echo::Message::default() - }, - &[], - ) - .unwrap_err(); - - assert_eq!(Error::empty_attribute_value("key"), err.downcast().unwrap()); - } - - #[test] - fn empty_event_attribute_key() { - let mut app = App::default(); - - let owner = Addr::unchecked("owner"); - - #[cfg(not(feature = "multitest_api_1_0"))] - let code_id = app.store_code(echo::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code_id = app.store_code(Addr::unchecked("creator"), echo::contract()); - - let contract = app - .instantiate_contract(code_id, owner.clone(), &Empty {}, &[], "Echo", None) - .unwrap(); - - let err = app - .execute_contract( - owner, - contract, - &echo::Message:: { - data: None, - events: vec![Event::new("event") - .add_attribute(" ", "value") - .add_attribute("proper", "proper_val")], - ..echo::Message::default() - }, - &[], - ) - .unwrap_err(); - - assert_eq!(Error::empty_attribute_key("value"), err.downcast().unwrap()); - } - - #[test] - fn empty_event_attribute_value() { - let mut app = App::default(); - - let owner = Addr::unchecked("owner"); - - #[cfg(not(feature = "multitest_api_1_0"))] - let code_id = app.store_code(echo::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code_id = app.store_code(Addr::unchecked("creator"), echo::contract()); - - let contract = app - .instantiate_contract(code_id, owner.clone(), &Empty {}, &[], "Echo", None) - .unwrap(); - - let err = app - .execute_contract( - owner, - contract, - &echo::Message:: { - data: None, - events: vec![Event::new("event") - .add_attribute("key", " ") - .add_attribute("proper", "proper_val")], - ..echo::Message::default() - }, - &[], - ) - .unwrap_err(); - - assert_eq!(Error::empty_attribute_value("key"), err.downcast().unwrap()); - } - - #[test] - fn too_short_event_type() { - let mut app = App::default(); - - let owner = Addr::unchecked("owner"); - - #[cfg(not(feature = "multitest_api_1_0"))] - let code_id = app.store_code(echo::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code_id = app.store_code(Addr::unchecked("creator"), echo::contract()); - - let contract = app - .instantiate_contract(code_id, owner.clone(), &Empty {}, &[], "Echo", None) - .unwrap(); - - let err = app - .execute_contract( - owner, - contract, - &echo::Message:: { - data: None, - events: vec![Event::new(" e "), Event::new("event")], - ..echo::Message::default() - }, - &[], - ) - .unwrap_err(); - - assert_eq!(Error::event_type_too_short("e"), err.downcast().unwrap()); - } - } - - mod wasm_queries { - - #[test] - #[cfg(feature = "cosmwasm_1_2")] - fn query_existing_code_info() { - use super::*; - let mut app = App::default(); - #[cfg(not(feature = "multitest_api_1_0"))] - let code_id = app.store_code_with_creator(Addr::unchecked("creator"), echo::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code_id = app.store_code(Addr::unchecked("creator"), echo::contract()); - let code_info_response = app.wrap().query_wasm_code_info(code_id).unwrap(); - assert_eq!(code_id, code_info_response.code_id); - assert_eq!("creator", code_info_response.creator); - assert!(!code_info_response.checksum.is_empty()); - } - - #[test] - #[cfg(feature = "cosmwasm_1_2")] - fn query_non_existing_code_info() { - use super::*; - let app = App::default(); - assert_eq!( - "Generic error: Querier contract error: code id: invalid", - app.wrap().query_wasm_code_info(0).unwrap_err().to_string() - ); - assert_eq!( - "Generic error: Querier contract error: code id 1: no such code", - app.wrap().query_wasm_code_info(1).unwrap_err().to_string() - ); - } - } - - mod custom_messages { - use super::*; - use crate::custom_handler::CachingCustomHandler; - - #[test] - fn triggering_custom_msg() { - let api = MockApi::default(); - let sender = api.addr_validate("sender").unwrap(); - let owner = api.addr_validate("owner").unwrap(); - - let custom_handler = CachingCustomHandler::::new(); - let custom_handler_state = custom_handler.state(); - - let mut app = AppBuilder::new_custom() - .with_api(api) - .with_custom(custom_handler) - .build(no_init); - - #[cfg(not(feature = "multitest_api_1_0"))] - let contract_id = app.store_code(echo::custom_contract()); - #[cfg(feature = "multitest_api_1_0")] - let contract_id = app.store_code(Addr::unchecked("creator"), echo::custom_contract()); - - let contract = app - .instantiate_contract(contract_id, owner, &Empty {}, &[], "Echo", None) - .unwrap(); - - app.execute_contract( - sender, - contract, - &echo::Message { - sub_msg: vec![SubMsg::new(CosmosMsg::Custom(CustomMsg::SetAge { - age: 20, - }))], - ..Default::default() - }, - &[], - ) - .unwrap(); - - assert_eq!( - custom_handler_state.execs().to_owned(), - vec![CustomMsg::SetAge { age: 20 }] - ); - - assert!(custom_handler_state.queries().is_empty()); - } - } - - mod protobuf_wrapped_data { - use super::*; - use crate::test_helpers::contracts::echo::EXECUTE_REPLY_BASE_ID; - use cw_utils::parse_instantiate_response_data; - - #[test] - fn instantiate_wrapped_properly() { - // set personal balance - let owner = Addr::unchecked("owner"); - let init_funds = vec![coin(20, "btc")]; - - let mut app = custom_app::(|router, _, storage| { - router - .bank - .init_balance(storage, &owner, init_funds) - .unwrap(); - }); - - // set up reflect contract - #[cfg(not(feature = "multitest_api_1_0"))] - let code_id = app.store_code(reflect::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code_id = app.store_code(Addr::unchecked("creator"), reflect::contract()); - - let init_msg = to_binary(&Empty {}).unwrap(); - let msg = WasmMsg::Instantiate { - admin: None, - code_id, - msg: init_msg, - funds: vec![], - label: "label".into(), - }; - let res = app.execute(owner, msg.into()).unwrap(); - - // assert we have a proper instantiate result - let parsed = parse_instantiate_response_data(res.data.unwrap().as_slice()).unwrap(); - assert!(parsed.data.is_none()); - // check the address is right - - let count: payout::CountResponse = app - .wrap() - .query_wasm_smart(&parsed.contract_address, &reflect::QueryMsg::Count {}) - .unwrap(); - assert_eq!(count.count, 0); - } - - #[test] - fn instantiate_with_data_works() { - let owner = Addr::unchecked("owner"); - let mut app = BasicApp::new(|_, _, _| {}); - - // set up echo contract - #[cfg(not(feature = "multitest_api_1_0"))] - let code_id = app.store_code(echo::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code_id = app.store_code(Addr::unchecked("creator"), echo::contract()); - - let msg = echo::InitMessage:: { - data: Some("food".into()), - sub_msg: None, - }; - let init_msg = to_binary(&msg).unwrap(); - let msg = WasmMsg::Instantiate { - admin: None, - code_id, - msg: init_msg, - funds: vec![], - label: "label".into(), - }; - let res = app.execute(owner, msg.into()).unwrap(); - - // assert we have a proper instantiate result - let parsed = parse_instantiate_response_data(res.data.unwrap().as_slice()).unwrap(); - assert!(parsed.data.is_some()); - assert_eq!(parsed.data.unwrap(), Binary::from(b"food")); - assert!(!parsed.contract_address.is_empty()); - } - - #[test] - fn instantiate_with_reply_works() { - let owner = Addr::unchecked("owner"); - let mut app = BasicApp::new(|_, _, _| {}); - - // set up echo contract - #[cfg(not(feature = "multitest_api_1_0"))] - let code_id = app.store_code(echo::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code_id = app.store_code(Addr::unchecked("creator"), echo::contract()); - - let msg = echo::InitMessage:: { - data: Some("food".into()), - ..Default::default() - }; - let addr1 = app - .instantiate_contract(code_id, owner.clone(), &msg, &[], "first", None) - .unwrap(); - - // another echo contract - let msg = echo::Message:: { - data: Some("Passed to contract instantiation, returned as reply, and then returned as response".into()), - ..Default::default() - }; - let sub_msg = SubMsg::reply_on_success( - WasmMsg::Execute { - contract_addr: addr1.to_string(), - msg: to_binary(&msg).unwrap(), - funds: vec![], - }, - EXECUTE_REPLY_BASE_ID, - ); - let init_msg = echo::InitMessage:: { - data: Some("Overwrite me".into()), - sub_msg: Some(vec![sub_msg]), - }; - let init_msg = to_binary(&init_msg).unwrap(); - let msg = WasmMsg::Instantiate { - admin: None, - code_id, - msg: init_msg, - funds: vec![], - label: "label".into(), - }; - let res = app.execute(owner, msg.into()).unwrap(); - - // assert we have a proper instantiate result - let parsed = parse_instantiate_response_data(res.data.unwrap().as_slice()).unwrap(); - assert!(parsed.data.is_some()); - // Result is from the reply, not the original one - assert_eq!(parsed.data.unwrap(), Binary::from(b"Passed to contract instantiation, returned as reply, and then returned as response")); - assert!(!parsed.contract_address.is_empty()); - assert_ne!(parsed.contract_address, addr1.to_string()); - } - - #[test] - fn execute_wrapped_properly() { - let owner = Addr::unchecked("owner"); - let mut app = BasicApp::new(|_, _, _| {}); - - // set up reflect contract - #[cfg(not(feature = "multitest_api_1_0"))] - let code_id = app.store_code(echo::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code_id = app.store_code(Addr::unchecked("creator"), echo::contract()); - - let echo_addr = app - .instantiate_contract(code_id, owner.clone(), &Empty {}, &[], "label", None) - .unwrap(); - - // ensure the execute has the same wrapper as it should - let msg = echo::Message:: { - data: Some("hello".into()), - ..echo::Message::default() - }; - // execute_contract now decodes a protobuf wrapper, so we get the top-level response - let exec_res = app.execute_contract(owner, echo_addr, &msg, &[]).unwrap(); - assert_eq!(exec_res.data, Some(Binary::from(b"hello"))); - } - } - - mod errors { - use super::*; - - #[test] - fn simple_instantiation() { - let owner = Addr::unchecked("owner"); - let mut app = App::default(); - - // set up contract - #[cfg(not(feature = "multitest_api_1_0"))] - let code_id = app.store_code(error::contract(false)); - #[cfg(feature = "multitest_api_1_0")] - let code_id = app.store_code(Addr::unchecked("creator"), error::contract(false)); - - let msg = Empty {}; - let err = app - .instantiate_contract(code_id, owner, &msg, &[], "error", None) - .unwrap_err(); - - // we should be able to retrieve the original error by downcasting - let source: &StdError = err.downcast_ref().unwrap(); - if let StdError::GenericErr { msg } = source { - assert_eq!(msg, "Init failed"); - } else { - panic!("wrong StdError variant"); - } - - // We're expecting exactly 2 nested error types - // (the original error, WasmMsg context) - assert_eq!(err.chain().count(), 2); - } - - #[test] - fn simple_call() { - let owner = Addr::unchecked("owner"); - let mut app = App::default(); - - // set up contract - #[cfg(not(feature = "multitest_api_1_0"))] - let code_id = app.store_code(error::contract(true)); - #[cfg(feature = "multitest_api_1_0")] - let code_id = app.store_code(Addr::unchecked("creator"), error::contract(true)); - - let msg = Empty {}; - let contract_addr = app - .instantiate_contract(code_id, owner, &msg, &[], "error", None) - .unwrap(); - - // execute should error - let err = app - .execute_contract(Addr::unchecked("random"), contract_addr, &msg, &[]) - .unwrap_err(); - - // we should be able to retrieve the original error by downcasting - let source: &StdError = err.downcast_ref().unwrap(); - if let StdError::GenericErr { msg } = source { - assert_eq!(msg, "Handle failed"); - } else { - panic!("wrong StdError variant"); - } - - // We're expecting exactly 2 nested error types - // (the original error, WasmMsg context) - assert_eq!(err.chain().count(), 2); - } - - #[test] - fn nested_call() { - let owner = Addr::unchecked("owner"); - let mut app = App::default(); - - #[cfg(not(feature = "multitest_api_1_0"))] - let error_code_id = app.store_code(error::contract(true)); - #[cfg(feature = "multitest_api_1_0")] - let error_code_id = app.store_code(Addr::unchecked("creator"), error::contract(true)); - #[cfg(not(feature = "multitest_api_1_0"))] - let caller_code_id = app.store_code(caller::contract()); - #[cfg(feature = "multitest_api_1_0")] - let caller_code_id = app.store_code(Addr::unchecked("creator"), caller::contract()); - - // set up contracts - let msg = Empty {}; - let caller_addr = app - .instantiate_contract(caller_code_id, owner.clone(), &msg, &[], "caller", None) - .unwrap(); - let error_addr = app - .instantiate_contract(error_code_id, owner, &msg, &[], "error", None) - .unwrap(); - - // execute should error - let msg = WasmMsg::Execute { - contract_addr: error_addr.into(), - msg: to_binary(&Empty {}).unwrap(), - funds: vec![], - }; - let err = app - .execute_contract(Addr::unchecked("random"), caller_addr, &msg, &[]) - .unwrap_err(); - - // we can downcast to get the original error - let source: &StdError = err.downcast_ref().unwrap(); - if let StdError::GenericErr { msg } = source { - assert_eq!(msg, "Handle failed"); - } else { - panic!("wrong StdError variant"); - } - - // We're expecting exactly 3 nested error types - // (the original error, 2 WasmMsg contexts) - assert_eq!(err.chain().count(), 3); - } - - #[test] - fn double_nested_call() { - let owner = Addr::unchecked("owner"); - let mut app = App::default(); - - #[cfg(not(feature = "multitest_api_1_0"))] - let error_code_id = app.store_code(error::contract(true)); - #[cfg(feature = "multitest_api_1_0")] - let error_code_id = app.store_code(Addr::unchecked("creator"), error::contract(true)); - #[cfg(not(feature = "multitest_api_1_0"))] - let caller_code_id = app.store_code(caller::contract()); - #[cfg(feature = "multitest_api_1_0")] - let caller_code_id = app.store_code(Addr::unchecked("creator"), caller::contract()); - - // set up contracts - let msg = Empty {}; - let caller_addr1 = app - .instantiate_contract(caller_code_id, owner.clone(), &msg, &[], "caller", None) - .unwrap(); - let caller_addr2 = app - .instantiate_contract(caller_code_id, owner.clone(), &msg, &[], "caller", None) - .unwrap(); - let error_addr = app - .instantiate_contract(error_code_id, owner, &msg, &[], "error", None) - .unwrap(); - - // caller1 calls caller2, caller2 calls error - let msg = WasmMsg::Execute { - contract_addr: caller_addr2.into(), - msg: to_binary(&WasmMsg::Execute { - contract_addr: error_addr.into(), - msg: to_binary(&Empty {}).unwrap(), - funds: vec![], - }) - .unwrap(), - funds: vec![], - }; - let err = app - .execute_contract(Addr::unchecked("random"), caller_addr1, &msg, &[]) - .unwrap_err(); - - // uncomment to have the test fail and see how the error stringifies - // panic!("{:?}", err); - - // we can downcast to get the original error - let source: &StdError = err.downcast_ref().unwrap(); - if let StdError::GenericErr { msg } = source { - assert_eq!(msg, "Handle failed"); - } else { - panic!("wrong StdError variant"); - } - - // We're expecting exactly 4 nested error types - // (the original error, 3 WasmMsg contexts) - assert_eq!(err.chain().count(), 4); - } - } -} diff --git a/src/bank.rs b/src/bank.rs index f9c9a96a..542c624c 100644 --- a/src/bank.rs +++ b/src/bank.rs @@ -1,3 +1,9 @@ +use crate::wasm_emulation::input::BankStorage; +use cw_orch_daemon::queriers::DaemonQuerier; +use std::str::FromStr; + +use ibc_chain_registry::chain::ChainData; + use anyhow::{bail, Result as AnyResult}; use itertools::Itertools; use schemars::JsonSchema; @@ -14,6 +20,9 @@ use crate::executor::AppResponse; use crate::module::Module; use crate::prefixed_storage::{prefixed, prefixed_read}; +use crate::wasm_emulation::channel::get_channel; +use crate::wasm_emulation::query::AllQuerier; + const BALANCES: Map<&Addr, NativeBalance> = Map::new("balances"); pub const NAMESPACE_BANK: &[u8] = b"bank"; @@ -26,14 +35,20 @@ pub enum BankSudo { }, } -pub trait Bank: Module {} +pub trait Bank: Module + AllQuerier {} #[derive(Default)] -pub struct BankKeeper {} +pub struct BankKeeper { + chain: Option, +} impl BankKeeper { pub fn new() -> Self { - BankKeeper {} + BankKeeper::default() + } + + pub fn set_chain(&mut self, chain: ChainData) { + self.chain = Some(chain) } // this is an "admin" function to let us adjust bank accounts in genesis @@ -62,8 +77,27 @@ impl BankKeeper { } fn get_balance(&self, bank_storage: &dyn Storage, account: &Addr) -> AnyResult> { - let val = BALANCES.may_load(bank_storage, account)?; - Ok(val.unwrap_or_default().into_vec()) + // If there is no balance present, we query it on the distant chain + if !BALANCES.has(bank_storage, account) { + let (rt, channel) = get_channel(self.chain.clone().unwrap())?; + let querier = cw_orch_daemon::queriers::Bank::new(channel); + let distant_amounts: Vec = rt + .block_on(querier.balance(account, None)) + .map(|result| { + result + .into_iter() + .map(|c| Coin { + amount: Uint128::from_str(&c.amount).unwrap(), + denom: c.denom, + }) + .collect() + }) + .unwrap(); + Ok(distant_amounts) + } else { + let val = BALANCES.may_load(bank_storage, account)?; + Ok(val.unwrap_or_default().into_vec()) + } } fn get_supply(&self, bank_storage: &dyn Storage, denom: String) -> AnyResult { @@ -139,6 +173,17 @@ fn coins_to_string(coins: &[Coin]) -> String { impl Bank for BankKeeper {} +impl AllQuerier for BankKeeper { + type Output = BankStorage; + fn query_all(&self, storage: &dyn Storage) -> AnyResult { + let bank_storage = prefixed_read(storage, NAMESPACE_BANK); + let balances: Result, _> = BALANCES + .range(&bank_storage, None, None, Order::Ascending) + .collect(); + Ok(BankStorage { storage: balances? }) + } +} + impl Module for BankKeeper { type ExecT = BankMsg; type QueryT = BankQuery; @@ -232,297 +277,3 @@ impl Module for BankKeeper { } } } - -#[cfg(test)] -mod test { - use super::*; - - use crate::app::MockRouter; - use cosmwasm_std::testing::{mock_env, MockApi, MockQuerier, MockStorage}; - use cosmwasm_std::{coins, from_slice, Empty, StdError}; - - fn query_balance( - bank: &BankKeeper, - api: &dyn Api, - store: &dyn Storage, - rcpt: &Addr, - ) -> Vec { - let req = BankQuery::AllBalances { - address: rcpt.clone().into(), - }; - let block = mock_env().block; - let querier: MockQuerier = MockQuerier::new(&[]); - - let raw = bank.query(api, store, &querier, &block, req).unwrap(); - let res: AllBalanceResponse = from_slice(&raw).unwrap(); - res.amount - } - - #[test] - fn get_set_balance() { - let api = MockApi::default(); - let mut store = MockStorage::new(); - let block = mock_env().block; - let querier: MockQuerier = MockQuerier::new(&[]); - let router = MockRouter::default(); - - let owner = Addr::unchecked("owner"); - let rcpt = Addr::unchecked("receiver"); - let init_funds = vec![coin(100, "eth"), coin(20, "btc")]; - let norm = vec![coin(20, "btc"), coin(100, "eth")]; - - // set money - let bank = BankKeeper::new(); - bank.init_balance(&mut store, &owner, init_funds).unwrap(); - let bank_storage = prefixed_read(&store, NAMESPACE_BANK); - - // get balance work - let rich = bank.get_balance(&bank_storage, &owner).unwrap(); - assert_eq!(rich, norm); - let poor = bank.get_balance(&bank_storage, &rcpt).unwrap(); - assert_eq!(poor, vec![]); - - // proper queries work - let req = BankQuery::AllBalances { - address: owner.clone().into(), - }; - let raw = bank.query(&api, &store, &querier, &block, req).unwrap(); - let res: AllBalanceResponse = from_slice(&raw).unwrap(); - assert_eq!(res.amount, norm); - - let req = BankQuery::AllBalances { - address: rcpt.clone().into(), - }; - let raw = bank.query(&api, &store, &querier, &block, req).unwrap(); - let res: AllBalanceResponse = from_slice(&raw).unwrap(); - assert_eq!(res.amount, vec![]); - - let req = BankQuery::Balance { - address: owner.clone().into(), - denom: "eth".into(), - }; - let raw = bank.query(&api, &store, &querier, &block, req).unwrap(); - let res: BalanceResponse = from_slice(&raw).unwrap(); - assert_eq!(res.amount, coin(100, "eth")); - - let req = BankQuery::Balance { - address: owner.into(), - denom: "foobar".into(), - }; - let raw = bank.query(&api, &store, &querier, &block, req).unwrap(); - let res: BalanceResponse = from_slice(&raw).unwrap(); - assert_eq!(res.amount, coin(0, "foobar")); - - let req = BankQuery::Balance { - address: rcpt.clone().into(), - denom: "eth".into(), - }; - let raw = bank.query(&api, &store, &querier, &block, req).unwrap(); - let res: BalanceResponse = from_slice(&raw).unwrap(); - assert_eq!(res.amount, coin(0, "eth")); - - // Query total supply of a denom - let req = BankQuery::Supply { - denom: "eth".into(), - }; - let raw = bank.query(&api, &store, &querier, &block, req).unwrap(); - let res: SupplyResponse = from_slice(&raw).unwrap(); - assert_eq!(res.amount, coin(100, "eth")); - - // Mint tokens for recipient account - let msg = BankSudo::Mint { - to_address: rcpt.to_string(), - amount: norm.clone(), - }; - bank.sudo(&api, &mut store, &router, &block, msg).unwrap(); - - // Check that the recipient account has the expected balance - let req = BankQuery::AllBalances { - address: rcpt.into(), - }; - let raw = bank.query(&api, &store, &querier, &block, req).unwrap(); - let res: AllBalanceResponse = from_slice(&raw).unwrap(); - assert_eq!(res.amount, norm); - - // Check that the total supply of a denom is updated - let req = BankQuery::Supply { - denom: "eth".into(), - }; - let raw = bank.query(&api, &store, &querier, &block, req).unwrap(); - let res: SupplyResponse = from_slice(&raw).unwrap(); - assert_eq!(res.amount, coin(200, "eth")); - } - - #[test] - fn send_coins() { - let api = MockApi::default(); - let mut store = MockStorage::new(); - let block = mock_env().block; - let router = MockRouter::default(); - - let owner = Addr::unchecked("owner"); - let rcpt = Addr::unchecked("receiver"); - let init_funds = vec![coin(20, "btc"), coin(100, "eth")]; - let rcpt_funds = vec![coin(5, "btc")]; - - // set money - let bank = BankKeeper::new(); - bank.init_balance(&mut store, &owner, init_funds).unwrap(); - bank.init_balance(&mut store, &rcpt, rcpt_funds).unwrap(); - - // send both tokens - let to_send = vec![coin(30, "eth"), coin(5, "btc")]; - let msg = BankMsg::Send { - to_address: rcpt.clone().into(), - amount: to_send, - }; - bank.execute( - &api, - &mut store, - &router, - &block, - owner.clone(), - msg.clone(), - ) - .unwrap(); - let rich = query_balance(&bank, &api, &store, &owner); - assert_eq!(vec![coin(15, "btc"), coin(70, "eth")], rich); - let poor = query_balance(&bank, &api, &store, &rcpt); - assert_eq!(vec![coin(10, "btc"), coin(30, "eth")], poor); - - // can send from any account with funds - bank.execute(&api, &mut store, &router, &block, rcpt.clone(), msg) - .unwrap(); - - // cannot send too much - let msg = BankMsg::Send { - to_address: rcpt.into(), - amount: coins(20, "btc"), - }; - bank.execute(&api, &mut store, &router, &block, owner.clone(), msg) - .unwrap_err(); - - let rich = query_balance(&bank, &api, &store, &owner); - assert_eq!(vec![coin(15, "btc"), coin(70, "eth")], rich); - } - - #[test] - fn burn_coins() { - let api = MockApi::default(); - let mut store = MockStorage::new(); - let block = mock_env().block; - let router = MockRouter::default(); - - let owner = Addr::unchecked("owner"); - let rcpt = Addr::unchecked("recipient"); - let init_funds = vec![coin(20, "btc"), coin(100, "eth")]; - - // set money - let bank = BankKeeper::new(); - bank.init_balance(&mut store, &owner, init_funds).unwrap(); - - // burn both tokens - let to_burn = vec![coin(30, "eth"), coin(5, "btc")]; - let msg = BankMsg::Burn { amount: to_burn }; - bank.execute(&api, &mut store, &router, &block, owner.clone(), msg) - .unwrap(); - let rich = query_balance(&bank, &api, &store, &owner); - assert_eq!(vec![coin(15, "btc"), coin(70, "eth")], rich); - - // cannot burn too much - let msg = BankMsg::Burn { - amount: coins(20, "btc"), - }; - let err = bank - .execute(&api, &mut store, &router, &block, owner.clone(), msg) - .unwrap_err(); - assert!(matches!(err.downcast().unwrap(), StdError::Overflow { .. })); - - let rich = query_balance(&bank, &api, &store, &owner); - assert_eq!(vec![coin(15, "btc"), coin(70, "eth")], rich); - - // cannot burn from empty account - let msg = BankMsg::Burn { - amount: coins(1, "btc"), - }; - let err = bank - .execute(&api, &mut store, &router, &block, rcpt, msg) - .unwrap_err(); - assert!(matches!(err.downcast().unwrap(), StdError::Overflow { .. })); - } - - #[test] - fn fail_on_zero_values() { - let api = MockApi::default(); - let mut store = MockStorage::new(); - let block = mock_env().block; - let router = MockRouter::default(); - - let owner = Addr::unchecked("owner"); - let rcpt = Addr::unchecked("recipient"); - let init_funds = vec![coin(5000, "atom"), coin(100, "eth")]; - - // set money - let bank = BankKeeper::new(); - bank.init_balance(&mut store, &owner, init_funds).unwrap(); - - // can send normal amounts - let msg = BankMsg::Send { - to_address: rcpt.to_string(), - amount: coins(100, "atom"), - }; - bank.execute(&api, &mut store, &router, &block, owner.clone(), msg) - .unwrap(); - - // fails send on no coins - let msg = BankMsg::Send { - to_address: rcpt.to_string(), - amount: vec![], - }; - bank.execute(&api, &mut store, &router, &block, owner.clone(), msg) - .unwrap_err(); - - // fails send on 0 coins - let msg = BankMsg::Send { - to_address: rcpt.to_string(), - amount: coins(0, "atom"), - }; - bank.execute(&api, &mut store, &router, &block, owner.clone(), msg) - .unwrap_err(); - - // fails burn on no coins - let msg = BankMsg::Burn { amount: vec![] }; - bank.execute(&api, &mut store, &router, &block, owner.clone(), msg) - .unwrap_err(); - - // fails burn on 0 coins - let msg = BankMsg::Burn { - amount: coins(0, "atom"), - }; - bank.execute(&api, &mut store, &router, &block, owner, msg) - .unwrap_err(); - - // can mint via sudo - let msg = BankSudo::Mint { - to_address: rcpt.to_string(), - amount: coins(4321, "atom"), - }; - bank.sudo(&api, &mut store, &router, &block, msg).unwrap(); - - // mint fails with 0 tokens - let msg = BankSudo::Mint { - to_address: rcpt.to_string(), - amount: coins(0, "atom"), - }; - bank.sudo(&api, &mut store, &router, &block, msg) - .unwrap_err(); - - // mint fails with no tokens - let msg = BankSudo::Mint { - to_address: rcpt.to_string(), - amount: vec![], - }; - bank.sudo(&api, &mut store, &router, &block, msg) - .unwrap_err(); - } -} diff --git a/src/error.rs b/src/error.rs index 626b792c..cd47529c 100644 --- a/src/error.rs +++ b/src/error.rs @@ -26,6 +26,9 @@ pub enum Error { #[error("code id {0}: no such code")] UnregisteredCodeId(u64), + + #[error("Unregistered contract address, not present loccaly or on-chain")] + UnregisteredContractAddress(String), } impl Error { diff --git a/src/gov.rs b/src/gov.rs index 333dbb50..0569cb41 100644 --- a/src/gov.rs +++ b/src/gov.rs @@ -5,122 +5,3 @@ use crate::{FailingModule, Module}; pub trait Gov: Module {} impl Gov for FailingModule {} - -#[cfg(test)] -mod test { - use cosmwasm_std::{Addr, Binary, Empty, GovMsg}; - - use crate::test_helpers::contracts::stargate; - use crate::test_helpers::contracts::stargate::ExecMsg; - use crate::{App, AppBuilder, AppResponse, Executor, Module}; - - use super::Gov; - - struct AcceptingModule; - - impl Module for AcceptingModule { - type ExecT = GovMsg; - type QueryT = Empty; - type SudoT = Empty; - - fn execute( - &self, - _api: &dyn cosmwasm_std::Api, - _storage: &mut dyn cosmwasm_std::Storage, - _router: &dyn crate::CosmosRouter, - _block: &cosmwasm_std::BlockInfo, - _sender: cosmwasm_std::Addr, - _msg: Self::ExecT, - ) -> anyhow::Result - where - ExecC: std::fmt::Debug - + Clone - + PartialEq - + schemars::JsonSchema - + serde::de::DeserializeOwned - + 'static, - QueryC: cosmwasm_std::CustomQuery + serde::de::DeserializeOwned + 'static, - { - Ok(AppResponse::default()) - } - - fn sudo( - &self, - _api: &dyn cosmwasm_std::Api, - _storage: &mut dyn cosmwasm_std::Storage, - _router: &dyn crate::CosmosRouter, - _block: &cosmwasm_std::BlockInfo, - _msg: Self::SudoT, - ) -> anyhow::Result - where - ExecC: std::fmt::Debug - + Clone - + PartialEq - + schemars::JsonSchema - + serde::de::DeserializeOwned - + 'static, - QueryC: cosmwasm_std::CustomQuery + serde::de::DeserializeOwned + 'static, - { - Ok(AppResponse::default()) - } - - fn query( - &self, - _api: &dyn cosmwasm_std::Api, - _storage: &dyn cosmwasm_std::Storage, - _querier: &dyn cosmwasm_std::Querier, - _block: &cosmwasm_std::BlockInfo, - _request: Self::QueryT, - ) -> anyhow::Result { - Ok(Binary::default()) - } - } - - impl Gov for AcceptingModule {} - - #[test] - fn default_gov() { - let mut app = App::default(); - #[cfg(not(feature = "multitest_api_1_0"))] - let code = app.store_code(stargate::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code = app.store_code(Addr::unchecked("creator"), stargate::contract()); - let contract = app - .instantiate_contract( - code, - Addr::unchecked("owner"), - &Empty {}, - &[], - "contract", - None, - ) - .unwrap(); - - app.execute_contract(Addr::unchecked("owner"), contract, &ExecMsg::Gov {}, &[]) - .unwrap_err(); - } - - #[test] - fn substituting_gov() { - let mut app = AppBuilder::new() - .with_gov(AcceptingModule) - .build(|_, _, _| ()); - #[cfg(not(feature = "multitest_api_1_0"))] - let code = app.store_code(stargate::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code = app.store_code(Addr::unchecked("creator"), stargate::contract()); - let contract = app - .instantiate_contract( - code, - Addr::unchecked("owner"), - &Empty {}, - &[], - "contract", - None, - ) - .unwrap(); - - app.execute_contract(Addr::unchecked("owner"), contract, &ExecMsg::Gov {}, &[]) - .unwrap(); - } -} diff --git a/src/ibc.rs b/src/ibc.rs index 790aeccf..797a60f6 100644 --- a/src/ibc.rs +++ b/src/ibc.rs @@ -67,60 +67,3 @@ impl Module for IbcAcceptingModule { } impl Ibc for IbcAcceptingModule {} - -#[cfg(test)] -mod test { - use cosmwasm_std::{Addr, Empty}; - - use crate::test_helpers::contracts::stargate; - use crate::test_helpers::contracts::stargate::ExecMsg; - use crate::{App, AppBuilder, Executor}; - - use super::*; - - #[test] - fn default_ibc() { - let mut app = App::default(); - #[cfg(not(feature = "multitest_api_1_0"))] - let code = app.store_code(stargate::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code = app.store_code(Addr::unchecked("creator"), stargate::contract()); - let contract = app - .instantiate_contract( - code, - Addr::unchecked("owner"), - &Empty {}, - &[], - "contract", - None, - ) - .unwrap(); - - app.execute_contract(Addr::unchecked("owner"), contract, &ExecMsg::Ibc {}, &[]) - .unwrap_err(); - } - - #[test] - fn substituting_ibc() { - let mut app = AppBuilder::new() - .with_ibc(IbcAcceptingModule) - .build(|_, _, _| ()); - #[cfg(not(feature = "multitest_api_1_0"))] - let code = app.store_code(stargate::contract()); - #[cfg(feature = "multitest_api_1_0")] - let code = app.store_code(Addr::unchecked("creator"), stargate::contract()); - let contract = app - .instantiate_contract( - code, - Addr::unchecked("owner"), - &Empty {}, - &[], - "contract", - None, - ) - .unwrap(); - - app.execute_contract(Addr::unchecked("owner"), contract, &ExecMsg::Ibc {}, &[]) - .unwrap(); - } -} diff --git a/src/lib.rs b/src/lib.rs index 4c843e72..05bd6bed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,11 +16,11 @@ mod executor; mod gov; mod ibc; mod module; -mod prefixed_storage; +pub(crate) mod prefixed_storage; mod staking; -mod test_helpers; mod transactions; mod wasm; +pub mod wasm_emulation; pub use crate::app::{ custom_app, next_block, App, AppBuilder, BasicApp, BasicAppBuilder, CosmosRouter, Router, diff --git a/src/prefixed_storage.rs b/src/prefixed_storage.rs index b74e4d76..2a1c817d 100644 --- a/src/prefixed_storage.rs +++ b/src/prefixed_storage.rs @@ -5,7 +5,7 @@ use cosmwasm_std::Storage; #[cfg(feature = "iterator")] use cosmwasm_std::{Order, Record}; -use length_prefixed::{to_length_prefixed, to_length_prefixed_nested}; +pub use length_prefixed::*; #[cfg(feature = "iterator")] use namespace_helpers::range_with_prefix; use namespace_helpers::{get_with_prefix, remove_with_prefix, set_with_prefix}; diff --git a/src/prefixed_storage/length_prefixed.rs b/src/prefixed_storage/length_prefixed.rs index 18543f50..39bcee98 100644 --- a/src/prefixed_storage/length_prefixed.rs +++ b/src/prefixed_storage/length_prefixed.rs @@ -6,6 +6,11 @@ //! Everything in this file is only responsible for building such keys //! and is not specific to any kind of storage. +use cosmwasm_std::Addr; + +use crate::wasm::NAMESPACE_WASM; + +pub const CONTRACT_STORAGE_PREFIX: &str = "contract_data/"; /// Calculates the raw key prefix for a given namespace. /// /// See @@ -44,6 +49,22 @@ fn encode_length(namespace: &[u8]) -> [u8; 2] { [length_bytes[2], length_bytes[3]] } +/// Decodes the length of a given namespace from a 2 byte big endian encoded integer +pub fn decode_length(bytes: [u8; 2]) -> u32 { + u32::from_be_bytes([0, 0, bytes[0], bytes[1]]) +} + +pub fn contract_namespace(contract: &Addr) -> Vec { + let mut name = CONTRACT_STORAGE_PREFIX.as_bytes().to_vec(); + name.extend_from_slice(contract.as_bytes()); + name +} + +pub fn get_full_contract_storage_namespace(contract_addr: &Addr) -> Vec { + let namespace = contract_namespace(contract_addr); + to_length_prefixed_nested(&[NAMESPACE_WASM, &namespace]) +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/staking.rs b/src/staking.rs index 53a68b1d..d3edcfff 100644 --- a/src/staking.rs +++ b/src/staking.rs @@ -13,9 +13,10 @@ use cw_storage_plus::{Deque, Item, Map}; use serde::{Deserialize, Serialize}; use crate::app::CosmosRouter; +use crate::bank::BankSudo; use crate::executor::AppResponse; use crate::prefixed_storage::{prefixed, prefixed_read}; -use crate::{BankSudo, Module}; +use crate::Module; // Contains some general staking parameters #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] @@ -987,1515 +988,3 @@ impl Module for DistributionKeeper { bail!("Something went wrong - Distribution doesn't have query messages") } } - -#[cfg(test)] -mod test { - use crate::{app::MockRouter, BankKeeper, FailingModule, Router, WasmKeeper}; - - use super::*; - - use cosmwasm_std::{ - from_slice, - testing::{mock_env, MockApi, MockStorage}, - BalanceResponse, BankQuery, GovMsg, IbcMsg, IbcQuery, - }; - - /// Type alias for default build `Router` to make its reference in typical scenario - type BasicRouter = Router< - BankKeeper, - FailingModule, - WasmKeeper, - StakeKeeper, - DistributionKeeper, - FailingModule, - FailingModule, - >; - - fn mock_router() -> BasicRouter { - Router { - wasm: WasmKeeper::new(), - bank: BankKeeper::new(), - custom: FailingModule::new(), - staking: StakeKeeper::new(), - distribution: DistributionKeeper::new(), - ibc: FailingModule::new(), - gov: FailingModule::new(), - } - } - - fn setup_test_env( - apr: Decimal, - validator_commission: Decimal, - ) -> (MockApi, MockStorage, BasicRouter, BlockInfo, Addr) { - let api = MockApi::default(); - let router = mock_router(); - let mut store = MockStorage::new(); - let block = mock_env().block; - - let validator = api.addr_validate("testvaloper1").unwrap(); - - router - .staking - .setup( - &mut store, - StakingInfo { - bonded_denom: "TOKEN".to_string(), - unbonding_time: 60, - apr, - }, - ) - .unwrap(); - - // add validator - let valoper1 = Validator { - address: "testvaloper1".to_string(), - commission: validator_commission, - max_commission: Decimal::percent(100), - max_change_rate: Decimal::percent(1), - }; - router - .staking - .add_validator(&api, &mut store, &block, valoper1) - .unwrap(); - - (api, store, router, block, validator) - } - - #[test] - fn add_get_validators() { - let api = MockApi::default(); - let mut store = MockStorage::new(); - let stake = StakeKeeper::default(); - let block = mock_env().block; - - // add validator - let valoper1 = Validator { - address: "testvaloper1".to_string(), - commission: Decimal::percent(10), - max_commission: Decimal::percent(20), - max_change_rate: Decimal::percent(1), - }; - stake - .add_validator(&api, &mut store, &block, valoper1.clone()) - .unwrap(); - - // get it - let staking_storage = prefixed_read(&store, NAMESPACE_STAKING); - let val = stake - .get_validator( - &staking_storage, - &api.addr_validate("testvaloper1").unwrap(), - ) - .unwrap() - .unwrap(); - assert_eq!(val, valoper1); - - // try to add with same address - let valoper1_fake = Validator { - address: "testvaloper1".to_string(), - commission: Decimal::percent(1), - max_commission: Decimal::percent(10), - max_change_rate: Decimal::percent(100), - }; - stake - .add_validator(&api, &mut store, &block, valoper1_fake) - .unwrap_err(); - - // should still be original value - let staking_storage = prefixed_read(&store, NAMESPACE_STAKING); - let val = stake - .get_validator( - &staking_storage, - &api.addr_validate("testvaloper1").unwrap(), - ) - .unwrap() - .unwrap(); - assert_eq!(val, valoper1); - } - - #[test] - fn validator_slashing() { - let api = MockApi::default(); - let router = MockRouter::default(); - let mut store = MockStorage::new(); - let stake = StakeKeeper::new(); - let block = mock_env().block; - - let delegator = Addr::unchecked("delegator"); - let validator = api.addr_validate("testvaloper1").unwrap(); - - // add validator - let valoper1 = Validator { - address: "testvaloper1".to_string(), - commission: Decimal::percent(10), - max_commission: Decimal::percent(20), - max_change_rate: Decimal::percent(1), - }; - stake - .add_validator(&api, &mut store, &block, valoper1) - .unwrap(); - - // stake 100 tokens - let mut staking_storage = prefixed(&mut store, NAMESPACE_STAKING); - stake - .add_stake( - &api, - &mut staking_storage, - &block, - &delegator, - &validator, - coin(100, "TOKEN"), - ) - .unwrap(); - - // slash 50% - stake - .sudo( - &api, - &mut store, - &router, - &block, - StakingSudo::Slash { - validator: "testvaloper1".to_string(), - percentage: Decimal::percent(50), - }, - ) - .unwrap(); - - // check stake - let staking_storage = prefixed(&mut store, NAMESPACE_STAKING); - let stake_left = stake - .get_stake(&staking_storage, &delegator, &validator) - .unwrap(); - assert_eq!( - stake_left.unwrap().amount.u128(), - 50, - "should have slashed 50%" - ); - - // slash all - stake - .sudo( - &api, - &mut store, - &router, - &block, - StakingSudo::Slash { - validator: "testvaloper1".to_string(), - percentage: Decimal::percent(100), - }, - ) - .unwrap(); - - // check stake - let staking_storage = prefixed(&mut store, NAMESPACE_STAKING); - let stake_left = stake - .get_stake(&staking_storage, &delegator, &validator) - .unwrap(); - assert_eq!(stake_left, None, "should have slashed whole stake"); - } - - #[test] - fn rewards_work_for_single_delegator() { - let (api, mut store, router, mut block, validator) = - setup_test_env(Decimal::percent(10), Decimal::percent(10)); - let stake = &router.staking; - let distr = &router.distribution; - let delegator = Addr::unchecked("delegator"); - - let mut staking_storage = prefixed(&mut store, NAMESPACE_STAKING); - // stake 200 tokens - stake - .add_stake( - &api, - &mut staking_storage, - &block, - &delegator, - &validator, - coin(200, "TOKEN"), - ) - .unwrap(); - - // wait 1/2 year - block.time = block.time.plus_seconds(60 * 60 * 24 * 365 / 2); - - // should now have 200 * 10% / 2 - 10% commission = 9 tokens reward - let rewards = stake - .get_rewards(&store, &block, &delegator, &validator) - .unwrap() - .unwrap(); - assert_eq!(rewards.amount.u128(), 9, "should have 9 tokens reward"); - - // withdraw rewards - distr - .execute( - &api, - &mut store, - &router, - &block, - delegator.clone(), - DistributionMsg::WithdrawDelegatorReward { - validator: validator.to_string(), - }, - ) - .unwrap(); - - // should have no rewards left - let rewards = stake - .get_rewards(&store, &block, &delegator, &validator) - .unwrap() - .unwrap(); - assert_eq!(rewards.amount.u128(), 0); - - // wait another 1/2 year - block.time = block.time.plus_seconds(60 * 60 * 24 * 365 / 2); - // should now have 9 tokens again - let rewards = stake - .get_rewards(&store, &block, &delegator, &validator) - .unwrap() - .unwrap(); - assert_eq!(rewards.amount.u128(), 9); - } - - #[test] - fn rewards_work_for_multiple_delegators() { - let (api, mut store, router, mut block, validator) = - setup_test_env(Decimal::percent(10), Decimal::percent(10)); - let stake = &router.staking; - let distr = &router.distribution; - let bank = &router.bank; - let delegator1 = Addr::unchecked("delegator1"); - let delegator2 = Addr::unchecked("delegator2"); - - let mut staking_storage = prefixed(&mut store, NAMESPACE_STAKING); - - // add 100 stake to delegator1 and 200 to delegator2 - stake - .add_stake( - &api, - &mut staking_storage, - &block, - &delegator1, - &validator, - coin(100, "TOKEN"), - ) - .unwrap(); - stake - .add_stake( - &api, - &mut staking_storage, - &block, - &delegator2, - &validator, - coin(200, "TOKEN"), - ) - .unwrap(); - - // wait 1 year - block.time = block.time.plus_seconds(60 * 60 * 24 * 365); - - // delegator1 should now have 100 * 10% - 10% commission = 9 tokens - let rewards = stake - .get_rewards(&store, &block, &delegator1, &validator) - .unwrap() - .unwrap(); - assert_eq!(rewards.amount.u128(), 9); - - // delegator2 should now have 200 * 10% - 10% commission = 18 tokens - let rewards = stake - .get_rewards(&store, &block, &delegator2, &validator) - .unwrap() - .unwrap(); - assert_eq!(rewards.amount.u128(), 18); - - // delegator1 stakes 100 more - let mut staking_storage = prefixed(&mut store, NAMESPACE_STAKING); - stake - .add_stake( - &api, - &mut staking_storage, - &block, - &delegator1, - &validator, - coin(100, "TOKEN"), - ) - .unwrap(); - - // wait another year - block.time = block.time.plus_seconds(60 * 60 * 24 * 365); - - // delegator1 should now have 9 + 200 * 10% - 10% commission = 27 tokens - let rewards = stake - .get_rewards(&store, &block, &delegator1, &validator) - .unwrap() - .unwrap(); - assert_eq!(rewards.amount.u128(), 27); - - // delegator2 should now have 18 + 200 * 10% - 10% commission = 36 tokens - let rewards = stake - .get_rewards(&store, &block, &delegator2, &validator) - .unwrap() - .unwrap(); - assert_eq!(rewards.amount.u128(), 36); - - // delegator2 unstakes 100 (has 100 left after that) - let mut staking_storage = prefixed(&mut store, NAMESPACE_STAKING); - stake - .remove_stake( - &api, - &mut staking_storage, - &block, - &delegator2, - &validator, - coin(100, "TOKEN"), - ) - .unwrap(); - - // and delegator1 withdraws rewards - distr - .execute( - &api, - &mut store, - &router, - &block, - delegator1.clone(), - DistributionMsg::WithdrawDelegatorReward { - validator: validator.to_string(), - }, - ) - .unwrap(); - - let balance: BalanceResponse = from_slice( - &bank - .query( - &api, - &store, - &router.querier(&api, &store, &block), - &block, - BankQuery::Balance { - address: delegator1.to_string(), - denom: "TOKEN".to_string(), - }, - ) - .unwrap(), - ) - .unwrap(); - assert_eq!( - balance.amount.amount.u128(), - 27, - "withdraw should change bank balance" - ); - let rewards = stake - .get_rewards(&store, &block, &delegator1, &validator) - .unwrap() - .unwrap(); - assert_eq!( - rewards.amount.u128(), - 0, - "withdraw should reduce rewards to 0" - ); - - // wait another year - block.time = block.time.plus_seconds(60 * 60 * 24 * 365); - - // delegator1 should now have 0 + 200 * 10% - 10% commission = 18 tokens - let rewards = stake - .get_rewards(&store, &block, &delegator1, &validator) - .unwrap() - .unwrap(); - assert_eq!(rewards.amount.u128(), 18); - - // delegator2 should now have 36 + 100 * 10% - 10% commission = 45 tokens - let rewards = stake - .get_rewards(&store, &block, &delegator2, &validator) - .unwrap() - .unwrap(); - assert_eq!(rewards.amount.u128(), 45); - } - - mod msg { - use cosmwasm_std::{ - coins, from_slice, Addr, BondedDenomResponse, Decimal, QuerierWrapper, StakingQuery, - }; - use serde::de::DeserializeOwned; - - use super::*; - - // shortens tests a bit - struct TestEnv { - api: MockApi, - store: MockStorage, - router: BasicRouter, - block: BlockInfo, - } - - impl TestEnv { - fn wrap(tuple: (MockApi, MockStorage, BasicRouter, BlockInfo, Addr)) -> (Self, Addr) { - ( - Self { - api: tuple.0, - store: tuple.1, - router: tuple.2, - block: tuple.3, - }, - tuple.4, - ) - } - } - - fn execute_stake( - env: &mut TestEnv, - sender: Addr, - msg: StakingMsg, - ) -> AnyResult { - env.router.staking.execute( - &env.api, - &mut env.store, - &env.router, - &env.block, - sender, - msg, - ) - } - - fn query_stake(env: &TestEnv, msg: StakingQuery) -> AnyResult { - Ok(from_slice(&env.router.staking.query( - &env.api, - &env.store, - &env.router.querier(&env.api, &env.store, &env.block), - &env.block, - msg, - )?)?) - } - - fn execute_distr( - env: &mut TestEnv, - sender: Addr, - msg: DistributionMsg, - ) -> AnyResult { - env.router.distribution.execute( - &env.api, - &mut env.store, - &env.router, - &env.block, - sender, - msg, - ) - } - - fn query_bank(env: &TestEnv, msg: BankQuery) -> AnyResult { - Ok(from_slice(&env.router.bank.query( - &env.api, - &env.store, - &env.router.querier(&env.api, &env.store, &env.block), - &env.block, - msg, - )?)?) - } - - fn assert_balances(env: &TestEnv, balances: impl IntoIterator) { - for (addr, amount) in balances { - let balance: BalanceResponse = query_bank( - env, - BankQuery::Balance { - address: addr.to_string(), - denom: "TOKEN".to_string(), - }, - ) - .unwrap(); - assert_eq!(balance.amount.amount.u128(), amount); - } - } - - #[test] - fn execute() { - // test all execute msgs - let (mut test_env, validator1) = - TestEnv::wrap(setup_test_env(Decimal::percent(10), Decimal::percent(10))); - - let delegator1 = Addr::unchecked("delegator1"); - let reward_receiver = Addr::unchecked("rewardreceiver"); - - // fund delegator1 account - test_env - .router - .bank - .init_balance(&mut test_env.store, &delegator1, vec![coin(1000, "TOKEN")]) - .unwrap(); - - // add second validator - let validator2 = Addr::unchecked("validator2"); - test_env - .router - .staking - .add_validator( - &test_env.api, - &mut test_env.store, - &test_env.block, - Validator { - address: validator2.to_string(), - commission: Decimal::zero(), - max_commission: Decimal::percent(20), - max_change_rate: Decimal::percent(1), - }, - ) - .unwrap(); - - // delegate 100 tokens to validator1 - execute_stake( - &mut test_env, - delegator1.clone(), - StakingMsg::Delegate { - validator: validator1.to_string(), - amount: coin(100, "TOKEN"), - }, - ) - .unwrap(); - - // should now have 100 tokens less - assert_balances(&test_env, vec![(delegator1.clone(), 900)]); - - // wait a year - test_env.block.time = test_env.block.time.plus_seconds(60 * 60 * 24 * 365); - - // change the withdrawal address - execute_distr( - &mut test_env, - delegator1.clone(), - DistributionMsg::SetWithdrawAddress { - address: reward_receiver.to_string(), - }, - ) - .unwrap(); - - // withdraw rewards - execute_distr( - &mut test_env, - delegator1.clone(), - DistributionMsg::WithdrawDelegatorReward { - validator: validator1.to_string(), - }, - ) - .unwrap(); - - // withdrawal address received rewards. - assert_balances( - &test_env, - // one year, 10%apr, 10%commision, 100 tokens staked - vec![(reward_receiver, 100 / 10 * 9 / 10)], - ); - - // redelegate to validator2 - execute_stake( - &mut test_env, - delegator1.clone(), - StakingMsg::Redelegate { - src_validator: validator1.to_string(), - dst_validator: validator2.to_string(), - amount: coin(100, "TOKEN"), - }, - ) - .unwrap(); - - // should have same amount as before (rewards receiver received rewards). - assert_balances(&test_env, vec![(delegator1.clone(), 900)]); - - let delegations: AllDelegationsResponse = query_stake( - &test_env, - StakingQuery::AllDelegations { - delegator: delegator1.to_string(), - }, - ) - .unwrap(); - assert_eq!( - delegations.delegations, - [Delegation { - delegator: delegator1.clone(), - validator: validator2.to_string(), - amount: coin(100, "TOKEN"), - }] - ); - - // undelegate all tokens - execute_stake( - &mut test_env, - delegator1.clone(), - StakingMsg::Undelegate { - validator: validator2.to_string(), - amount: coin(100, "TOKEN"), - }, - ) - .unwrap(); - - // wait for unbonding period (60 seconds in default config) - test_env.block.time = test_env.block.time.plus_seconds(60); - - // need to manually cause queue to get processed - test_env - .router - .staking - .sudo( - &test_env.api, - &mut test_env.store, - &test_env.router, - &test_env.block, - StakingSudo::ProcessQueue {}, - ) - .unwrap(); - - // check bank balance - assert_balances(&test_env, vec![(delegator1.clone(), 1000)]); - } - - #[test] - fn can_set_withdraw_address() { - let (mut test_env, validator) = - TestEnv::wrap(setup_test_env(Decimal::percent(10), Decimal::percent(10))); - - let delegator = Addr::unchecked("delegator"); - let reward_receiver = Addr::unchecked("rewardreceiver"); - - test_env - .router - .bank - .init_balance(&mut test_env.store, &delegator, coins(100, "TOKEN")) - .unwrap(); - - // Stake 100 tokens to the validator. - execute_stake( - &mut test_env, - delegator.clone(), - StakingMsg::Delegate { - validator: validator.to_string(), - amount: coin(100, "TOKEN"), - }, - ) - .unwrap(); - - // Change rewards receiver. - execute_distr( - &mut test_env, - delegator.clone(), - DistributionMsg::SetWithdrawAddress { - address: reward_receiver.to_string(), - }, - ) - .unwrap(); - - // A year passes. - test_env.block.time = test_env.block.time.plus_seconds(60 * 60 * 24 * 365); - - // Withdraw rewards to reward receiver. - execute_distr( - &mut test_env, - delegator.clone(), - DistributionMsg::WithdrawDelegatorReward { - validator: validator.to_string(), - }, - ) - .unwrap(); - - // Change reward receiver back to delegator. - execute_distr( - &mut test_env, - delegator.clone(), - DistributionMsg::SetWithdrawAddress { - address: delegator.to_string(), - }, - ) - .unwrap(); - - // Another year passes. - test_env.block.time = test_env.block.time.plus_seconds(60 * 60 * 24 * 365); - - // Withdraw rewards to delegator. - execute_distr( - &mut test_env, - delegator.clone(), - DistributionMsg::WithdrawDelegatorReward { - validator: validator.to_string(), - }, - ) - .unwrap(); - - // one year, 10%apr, 10%commision, 100 tokens staked - let rewards_yr = 100 / 10 * 9 / 10; - - assert_balances( - &test_env, - vec![(reward_receiver, rewards_yr), (delegator, rewards_yr)], - ); - } - - #[test] - fn cannot_steal() { - let (mut test_env, validator1) = - TestEnv::wrap(setup_test_env(Decimal::percent(10), Decimal::percent(10))); - - let delegator1 = Addr::unchecked("delegator1"); - - // fund delegator1 account - test_env - .router - .bank - .init_balance(&mut test_env.store, &delegator1, vec![coin(100, "TOKEN")]) - .unwrap(); - - // delegate 100 tokens to validator1 - execute_stake( - &mut test_env, - delegator1.clone(), - StakingMsg::Delegate { - validator: validator1.to_string(), - amount: coin(100, "TOKEN"), - }, - ) - .unwrap(); - - // undelegate more tokens than we have - let e = execute_stake( - &mut test_env, - delegator1.clone(), - StakingMsg::Undelegate { - validator: validator1.to_string(), - amount: coin(200, "TOKEN"), - }, - ) - .unwrap_err(); - - assert_eq!(e.to_string(), "invalid shares amount"); - - // add second validator - let validator2 = Addr::unchecked("validator2"); - test_env - .router - .staking - .add_validator( - &test_env.api, - &mut test_env.store, - &test_env.block, - Validator { - address: validator2.to_string(), - commission: Decimal::zero(), - max_commission: Decimal::percent(20), - max_change_rate: Decimal::percent(1), - }, - ) - .unwrap(); - - // redelegate more tokens than we have - let e = execute_stake( - &mut test_env, - delegator1.clone(), - StakingMsg::Redelegate { - src_validator: validator1.to_string(), - dst_validator: validator2.to_string(), - amount: coin(200, "TOKEN"), - }, - ) - .unwrap_err(); - assert_eq!(e.to_string(), "invalid shares amount"); - - // undelegate from non-existing delegation - let e = execute_stake( - &mut test_env, - delegator1.clone(), - StakingMsg::Undelegate { - validator: validator2.to_string(), - amount: coin(100, "TOKEN"), - }, - ) - .unwrap_err(); - assert_eq!( - e.to_string(), - "no delegation for (address, validator) tuple" - ); - } - - #[test] - fn denom_validation() { - let (mut test_env, validator) = - TestEnv::wrap(setup_test_env(Decimal::percent(10), Decimal::percent(10))); - - let delegator1 = Addr::unchecked("delegator1"); - - // fund delegator1 account - test_env - .router - .bank - .init_balance(&mut test_env.store, &delegator1, vec![coin(100, "FAKE")]) - .unwrap(); - - // try to delegate 100 to validator1 - let e = execute_stake( - &mut test_env, - delegator1.clone(), - StakingMsg::Delegate { - validator: validator.to_string(), - amount: coin(100, "FAKE"), - }, - ) - .unwrap_err(); - - assert_eq!( - e.to_string(), - "cannot delegate coins of denominator FAKE, only of TOKEN", - ); - } - - #[test] - fn cannot_slash_nonexistent() { - let (mut test_env, _) = - TestEnv::wrap(setup_test_env(Decimal::percent(10), Decimal::percent(10))); - - let delegator1 = Addr::unchecked("delegator1"); - - // fund delegator1 account - test_env - .router - .bank - .init_balance(&mut test_env.store, &delegator1, vec![coin(100, "FAKE")]) - .unwrap(); - - // try to delegate 100 to validator1 - let e = test_env - .router - .staking - .sudo( - &test_env.api, - &mut test_env.store, - &test_env.router, - &test_env.block, - StakingSudo::Slash { - validator: "nonexistingvaloper".to_string(), - percentage: Decimal::percent(50), - }, - ) - .unwrap_err(); - assert_eq!(e.to_string(), "validator does not exist"); - } - - #[test] - fn non_existent_validator() { - let (mut test_env, _) = - TestEnv::wrap(setup_test_env(Decimal::percent(10), Decimal::percent(10))); - - let delegator = Addr::unchecked("delegator1"); - let validator = "testvaloper2"; - - // init balances - test_env - .router - .bank - .init_balance(&mut test_env.store, &delegator, vec![coin(100, "TOKEN")]) - .unwrap(); - - // try to delegate - let err = execute_stake( - &mut test_env, - delegator.clone(), - StakingMsg::Delegate { - validator: validator.to_string(), - amount: coin(100, "TOKEN"), - }, - ) - .unwrap_err(); - assert_eq!(err.to_string(), "validator does not exist"); - - // try to undelegate - let err = execute_stake( - &mut test_env, - delegator.clone(), - StakingMsg::Undelegate { - validator: validator.to_string(), - amount: coin(100, "TOKEN"), - }, - ) - .unwrap_err(); - assert_eq!(err.to_string(), "validator does not exist"); - } - - #[test] - fn zero_staking_forbidden() { - let (mut test_env, validator) = - TestEnv::wrap(setup_test_env(Decimal::percent(10), Decimal::percent(10))); - - let delegator = Addr::unchecked("delegator1"); - - // delegate 0 - let err = execute_stake( - &mut test_env, - delegator.clone(), - StakingMsg::Delegate { - validator: validator.to_string(), - amount: coin(0, "TOKEN"), - }, - ) - .unwrap_err(); - assert_eq!(err.to_string(), "invalid delegation amount"); - - // undelegate 0 - let err = execute_stake( - &mut test_env, - delegator, - StakingMsg::Undelegate { - validator: validator.to_string(), - amount: coin(0, "TOKEN"), - }, - ) - .unwrap_err(); - assert_eq!(err.to_string(), "invalid shares amount"); - } - - #[test] - fn query_staking() { - // run all staking queries - let (mut test_env, validator1) = - TestEnv::wrap(setup_test_env(Decimal::percent(10), Decimal::percent(10))); - let delegator1 = Addr::unchecked("delegator1"); - let delegator2 = Addr::unchecked("delegator2"); - - // init balances - test_env - .router - .bank - .init_balance(&mut test_env.store, &delegator1, vec![coin(260, "TOKEN")]) - .unwrap(); - test_env - .router - .bank - .init_balance(&mut test_env.store, &delegator2, vec![coin(150, "TOKEN")]) - .unwrap(); - - // add another validator - let validator2 = test_env.api.addr_validate("testvaloper2").unwrap(); - let valoper2 = Validator { - address: "testvaloper2".to_string(), - commission: Decimal::percent(0), - max_commission: Decimal::percent(1), - max_change_rate: Decimal::percent(1), - }; - test_env - .router - .staking - .add_validator( - &test_env.api, - &mut test_env.store, - &test_env.block, - valoper2.clone(), - ) - .unwrap(); - - // query validators - let valoper1: ValidatorResponse = query_stake( - &test_env, - StakingQuery::Validator { - address: validator1.to_string(), - }, - ) - .unwrap(); - let validators: AllValidatorsResponse = - query_stake(&test_env, StakingQuery::AllValidators {}).unwrap(); - assert_eq!( - validators.validators, - [valoper1.validator.unwrap(), valoper2] - ); - // query non-existent validator - let response = query_stake::( - &test_env, - StakingQuery::Validator { - address: "notvaloper".to_string(), - }, - ) - .unwrap(); - assert_eq!(response.validator, None); - - // query bonded denom - let response: BondedDenomResponse = - query_stake(&test_env, StakingQuery::BondedDenom {}).unwrap(); - assert_eq!(response.denom, "TOKEN"); - - // delegate some tokens with delegator1 and delegator2 - execute_stake( - &mut test_env, - delegator1.clone(), - StakingMsg::Delegate { - validator: validator1.to_string(), - amount: coin(100, "TOKEN"), - }, - ) - .unwrap(); - execute_stake( - &mut test_env, - delegator1.clone(), - StakingMsg::Delegate { - validator: validator2.to_string(), - amount: coin(160, "TOKEN"), - }, - ) - .unwrap(); - execute_stake( - &mut test_env, - delegator2.clone(), - StakingMsg::Delegate { - validator: validator1.to_string(), - amount: coin(150, "TOKEN"), - }, - ) - .unwrap(); - // unstake some again - execute_stake( - &mut test_env, - delegator1.clone(), - StakingMsg::Undelegate { - validator: validator1.to_string(), - amount: coin(50, "TOKEN"), - }, - ) - .unwrap(); - execute_stake( - &mut test_env, - delegator2.clone(), - StakingMsg::Undelegate { - validator: validator1.to_string(), - amount: coin(50, "TOKEN"), - }, - ) - .unwrap(); - - // query all delegations - let response1: AllDelegationsResponse = query_stake( - &test_env, - StakingQuery::AllDelegations { - delegator: delegator1.to_string(), - }, - ) - .unwrap(); - assert_eq!( - response1.delegations, - vec![ - Delegation { - delegator: delegator1.clone(), - validator: validator1.to_string(), - amount: coin(50, "TOKEN"), - }, - Delegation { - delegator: delegator1.clone(), - validator: validator2.to_string(), - amount: coin(160, "TOKEN"), - }, - ] - ); - let response2: DelegationResponse = query_stake( - &test_env, - StakingQuery::Delegation { - delegator: delegator2.to_string(), - validator: validator1.to_string(), - }, - ) - .unwrap(); - assert_eq!( - response2.delegation.unwrap(), - FullDelegation { - delegator: delegator2.clone(), - validator: validator1.to_string(), - amount: coin(100, "TOKEN"), - accumulated_rewards: vec![], - can_redelegate: coin(100, "TOKEN"), - }, - ); - } - - #[test] - fn delegation_queries_unbonding() { - // run all staking queries - let (mut test_env, validator) = - TestEnv::wrap(setup_test_env(Decimal::percent(10), Decimal::percent(10))); - let delegator1 = Addr::unchecked("delegator1"); - let delegator2 = Addr::unchecked("delegator2"); - - // init balances - test_env - .router - .bank - .init_balance(&mut test_env.store, &delegator1, vec![coin(100, "TOKEN")]) - .unwrap(); - test_env - .router - .bank - .init_balance(&mut test_env.store, &delegator2, vec![coin(150, "TOKEN")]) - .unwrap(); - - // delegate some tokens with delegator1 and delegator2 - execute_stake( - &mut test_env, - delegator1.clone(), - StakingMsg::Delegate { - validator: validator.to_string(), - amount: coin(100, "TOKEN"), - }, - ) - .unwrap(); - execute_stake( - &mut test_env, - delegator2.clone(), - StakingMsg::Delegate { - validator: validator.to_string(), - amount: coin(150, "TOKEN"), - }, - ) - .unwrap(); - // unstake some of delegator1's stake - execute_stake( - &mut test_env, - delegator1.clone(), - StakingMsg::Undelegate { - validator: validator.to_string(), - amount: coin(50, "TOKEN"), - }, - ) - .unwrap(); - // unstake all of delegator2's stake - execute_stake( - &mut test_env, - delegator2.clone(), - StakingMsg::Undelegate { - validator: validator.to_string(), - amount: coin(150, "TOKEN"), - }, - ) - .unwrap(); - - // query all delegations - let response1: AllDelegationsResponse = query_stake( - &test_env, - StakingQuery::AllDelegations { - delegator: delegator1.to_string(), - }, - ) - .unwrap(); - assert_eq!( - response1.delegations, - vec![Delegation { - delegator: delegator1.clone(), - validator: validator.to_string(), - amount: coin(50, "TOKEN"), - }] - ); - let response2: DelegationResponse = query_stake( - &test_env, - StakingQuery::Delegation { - delegator: delegator2.to_string(), - validator: validator.to_string(), - }, - ) - .unwrap(); - assert_eq!(response2.delegation, None); - - // unstake rest of delegator1's stake in two steps - execute_stake( - &mut test_env, - delegator1.clone(), - StakingMsg::Undelegate { - validator: validator.to_string(), - amount: coin(25, "TOKEN"), - }, - ) - .unwrap(); - test_env.block.time = test_env.block.time.plus_seconds(10); - execute_stake( - &mut test_env, - delegator1.clone(), - StakingMsg::Undelegate { - validator: validator.to_string(), - amount: coin(25, "TOKEN"), - }, - ) - .unwrap(); - - // query all delegations again - let response1: DelegationResponse = query_stake( - &test_env, - StakingQuery::Delegation { - delegator: delegator1.to_string(), - validator: validator.to_string(), - }, - ) - .unwrap(); - let response2: AllDelegationsResponse = query_stake( - &test_env, - StakingQuery::AllDelegations { - delegator: delegator1.to_string(), - }, - ) - .unwrap(); - assert_eq!( - response1.delegation, None, - "delegator1 should have no delegations left" - ); - assert_eq!(response2.delegations, vec![]); - } - - #[test] - fn partial_unbonding_reduces_stake() { - let (mut test_env, validator) = - TestEnv::wrap(setup_test_env(Decimal::percent(10), Decimal::percent(10))); - let delegator = Addr::unchecked("delegator1"); - - // init balance - test_env - .router - .bank - .init_balance(&mut test_env.store, &delegator, vec![coin(100, "TOKEN")]) - .unwrap(); - - // delegate all tokens - execute_stake( - &mut test_env, - delegator.clone(), - StakingMsg::Delegate { - validator: validator.to_string(), - amount: coin(100, "TOKEN"), - }, - ) - .unwrap(); - // unstake in multiple steps - execute_stake( - &mut test_env, - delegator.clone(), - StakingMsg::Undelegate { - validator: validator.to_string(), - amount: coin(50, "TOKEN"), - }, - ) - .unwrap(); - test_env.block.time = test_env.block.time.plus_seconds(10); - execute_stake( - &mut test_env, - delegator.clone(), - StakingMsg::Undelegate { - validator: validator.to_string(), - amount: coin(30, "TOKEN"), - }, - ) - .unwrap(); - test_env.block.time = test_env.block.time.plus_seconds(10); - execute_stake( - &mut test_env, - delegator.clone(), - StakingMsg::Undelegate { - validator: validator.to_string(), - amount: coin(20, "TOKEN"), - }, - ) - .unwrap(); - - // wait for first unbonding to complete (but not the others) and process queue - test_env.block.time = test_env.block.time.plus_seconds(40); - test_env - .router - .staking - .sudo( - &test_env.api, - &mut test_env.store, - &test_env.router, - &test_env.block, - StakingSudo::ProcessQueue {}, - ) - .unwrap(); - - // query delegations - // we now have 0 stake, 50 unbonding and 50 completed unbonding - let response1: DelegationResponse = query_stake( - &test_env, - StakingQuery::Delegation { - delegator: delegator.to_string(), - validator: validator.to_string(), - }, - ) - .unwrap(); - let response2: AllDelegationsResponse = query_stake( - &test_env, - StakingQuery::AllDelegations { - delegator: delegator.to_string(), - }, - ) - .unwrap(); - assert_eq!(response1.delegation, None); - assert_eq!(response2.delegations, vec![]); - - // wait for the rest to complete - test_env.block.time = test_env.block.time.plus_seconds(20); - test_env - .router - .staking - .sudo( - &test_env.api, - &mut test_env.store, - &test_env.router, - &test_env.block, - StakingSudo::ProcessQueue {}, - ) - .unwrap(); - - // query delegations again - let response1: DelegationResponse = query_stake( - &test_env, - StakingQuery::Delegation { - delegator: delegator.to_string(), - validator: validator.to_string(), - }, - ) - .unwrap(); - let response2: AllDelegationsResponse = query_stake( - &test_env, - StakingQuery::AllDelegations { - delegator: delegator.to_string(), - }, - ) - .unwrap(); - assert_eq!( - response1.delegation, None, - "delegator should have nothing left" - ); - assert!(response2.delegations.is_empty()); - } - - #[test] - fn delegations_slashed() { - // run all staking queries - let (mut test_env, validator) = - TestEnv::wrap(setup_test_env(Decimal::percent(10), Decimal::percent(10))); - let delegator = Addr::unchecked("delegator"); - - // init balance - test_env - .router - .bank - .init_balance(&mut test_env.store, &delegator, vec![coin(333, "TOKEN")]) - .unwrap(); - - // delegate some tokens - execute_stake( - &mut test_env, - delegator.clone(), - StakingMsg::Delegate { - validator: validator.to_string(), - amount: coin(333, "TOKEN"), - }, - ) - .unwrap(); - // unstake some - execute_stake( - &mut test_env, - delegator.clone(), - StakingMsg::Undelegate { - validator: validator.to_string(), - amount: coin(111, "TOKEN"), - }, - ) - .unwrap(); - - // slash validator - test_env - .router - .staking - .sudo( - &test_env.api, - &mut test_env.store, - &test_env.router, - &test_env.block, - StakingSudo::Slash { - validator: "testvaloper1".to_string(), - percentage: Decimal::percent(50), - }, - ) - .unwrap(); - - // query all delegations - let response1: AllDelegationsResponse = query_stake( - &test_env, - StakingQuery::AllDelegations { - delegator: delegator.to_string(), - }, - ) - .unwrap(); - assert_eq!( - response1.delegations[0], - Delegation { - delegator: delegator.clone(), - validator: validator.to_string(), - amount: coin(111, "TOKEN"), - } - ); - - // wait until unbonding is complete and check if amount was slashed - test_env.block.time = test_env.block.time.plus_seconds(60); - test_env - .router - .staking - .sudo( - &test_env.api, - &mut test_env.store, - &test_env.router, - &test_env.block, - StakingSudo::ProcessQueue {}, - ) - .unwrap(); - let balance = QuerierWrapper::::new(&test_env.router.querier( - &test_env.api, - &test_env.store, - &test_env.block, - )) - .query_balance(delegator, "TOKEN") - .unwrap(); - assert_eq!(balance.amount.u128(), 55); - } - - #[test] - fn rewards_initial_wait() { - let (mut test_env, validator) = - TestEnv::wrap(setup_test_env(Decimal::percent(10), Decimal::zero())); - let delegator = Addr::unchecked("delegator"); - - // init balance - test_env - .router - .bank - .init_balance(&mut test_env.store, &delegator, vec![coin(100, "TOKEN")]) - .unwrap(); - - // wait a year before staking - const YEAR: u64 = 60 * 60 * 24 * 365; - test_env.block.time = test_env.block.time.plus_seconds(YEAR); - - // delegate some tokens - execute_stake( - &mut test_env, - delegator.clone(), - StakingMsg::Delegate { - validator: validator.to_string(), - amount: coin(100, "TOKEN"), - }, - ) - .unwrap(); - - // wait another year - test_env.block.time = test_env.block.time.plus_seconds(YEAR); - - // query rewards - let response: DelegationResponse = query_stake( - &test_env, - StakingQuery::Delegation { - delegator: delegator.to_string(), - validator: validator.to_string(), - }, - ) - .unwrap(); - assert_eq!( - response.delegation.unwrap().accumulated_rewards, - vec![coin(10, "TOKEN")] // 10% of 100 - ); - } - } -} diff --git a/src/test_helpers.rs b/src/test_helpers.rs deleted file mode 100644 index db0318f5..00000000 --- a/src/test_helpers.rs +++ /dev/null @@ -1,17 +0,0 @@ -#![cfg(test)] -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; - -use cw_storage_plus::Item; - -pub mod contracts; - -/// This is just a demo place so we can test custom message handling -#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] -#[serde(rename = "snake_case")] -pub enum CustomMsg { - SetName { name: String }, - SetAge { age: u32 }, -} - -const COUNT: Item = Item::new("count"); diff --git a/src/test_helpers/contracts.rs b/src/test_helpers/contracts.rs deleted file mode 100644 index 3b495e06..00000000 --- a/src/test_helpers/contracts.rs +++ /dev/null @@ -1,9 +0,0 @@ -//! Module for simple contracts to be used in tests - -pub mod caller; -pub mod echo; -pub mod error; -pub mod hackatom; -pub mod payout; -pub mod reflect; -pub mod stargate; diff --git a/src/test_helpers/contracts/caller.rs b/src/test_helpers/contracts/caller.rs deleted file mode 100644 index 929d497f..00000000 --- a/src/test_helpers/contracts/caller.rs +++ /dev/null @@ -1,42 +0,0 @@ -use std::fmt; - -use cosmwasm_std::{ - Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response, StdError, SubMsg, WasmMsg, -}; -use schemars::JsonSchema; - -use crate::{Contract, ContractWrapper}; - -fn instantiate( - _deps: DepsMut, - _env: Env, - _info: MessageInfo, - _msg: Empty, -) -> Result { - Ok(Response::default()) -} - -fn execute( - _deps: DepsMut, - _env: Env, - _info: MessageInfo, - msg: WasmMsg, -) -> Result { - let message = SubMsg::new(msg); - - Ok(Response::new().add_submessage(message)) -} - -fn query(_deps: Deps, _env: Env, _msg: Empty) -> Result { - Err(StdError::generic_err( - "query not implemented for the `caller` contract", - )) -} - -pub fn contract() -> Box> -where - C: Clone + fmt::Debug + PartialEq + JsonSchema + 'static, -{ - let contract = ContractWrapper::new_with_empty(execute, instantiate, query); - Box::new(contract) -} diff --git a/src/test_helpers/contracts/echo.rs b/src/test_helpers/contracts/echo.rs deleted file mode 100644 index f9f8b430..00000000 --- a/src/test_helpers/contracts/echo.rs +++ /dev/null @@ -1,140 +0,0 @@ -//! Very simple echoing contract which just returns incoming string if any, -//! but performing sub call of given message to test response. -//! -//! Additionally it bypasses all events and attributes send to it. - -use cosmwasm_std::{ - to_binary, Attribute, Binary, Deps, DepsMut, Empty, Env, Event, MessageInfo, Reply, Response, - StdError, SubMsg, SubMsgResponse, SubMsgResult, -}; -use serde::{de::DeserializeOwned, Deserialize, Serialize}; - -use crate::{Contract, ContractWrapper}; -use schemars::JsonSchema; -use std::fmt::Debug; - -use cw_utils::{parse_execute_response_data, parse_instantiate_response_data}; -use derivative::Derivative; - -// Choosing a reply id less than ECHO_EXECUTE_BASE_ID indicates an Instantiate message reply by convention. -// An Execute message reply otherwise. -pub(crate) const EXECUTE_REPLY_BASE_ID: u64 = i64::MAX as u64; - -#[derive(Debug, Clone, Serialize, Deserialize, Derivative)] -#[derivative(Default(bound = "", new = "true"))] -pub struct Message -where - ExecC: Debug + PartialEq + Clone + JsonSchema + 'static, -{ - pub data: Option, - pub sub_msg: Vec>, - pub attributes: Vec, - pub events: Vec, -} - -// This can take some data... but happy to accept {} -#[derive(Debug, Clone, Serialize, Deserialize, Derivative)] -#[derivative(Default(bound = "", new = "true"))] -pub struct InitMessage -where - ExecC: Debug + PartialEq + Clone + JsonSchema + 'static, -{ - pub data: Option, - pub sub_msg: Option>>, -} - -#[allow(clippy::unnecessary_wraps)] -fn instantiate( - _deps: DepsMut, - _env: Env, - _info: MessageInfo, - msg: InitMessage, -) -> Result, StdError> -where - ExecC: Debug + PartialEq + Clone + JsonSchema + 'static, -{ - let mut res = Response::new(); - if let Some(data) = msg.data { - res = res.set_data(data.into_bytes()); - } - if let Some(msgs) = msg.sub_msg { - res = res.add_submessages(msgs); - } - Ok(res) -} - -#[allow(clippy::unnecessary_wraps)] -fn execute( - _deps: DepsMut, - _env: Env, - _info: MessageInfo, - msg: Message, -) -> Result, StdError> -where - ExecC: Debug + PartialEq + Clone + JsonSchema + 'static, -{ - let mut resp = Response::new(); - - if let Some(data) = msg.data { - resp = resp.set_data(data.into_bytes()); - } - - Ok(resp - .add_submessages(msg.sub_msg) - .add_attributes(msg.attributes) - .add_events(msg.events)) -} - -fn query(_deps: Deps, _env: Env, msg: Empty) -> Result { - to_binary(&msg) -} - -#[allow(clippy::unnecessary_wraps)] -fn reply(_deps: DepsMut, _env: Env, msg: Reply) -> Result, StdError> -where - ExecC: Debug + PartialEq + Clone + JsonSchema + 'static, -{ - let res = Response::new(); - if let Reply { - id, - result: SubMsgResult::Ok(SubMsgResponse { - data: Some(data), .. - }), - } = msg - { - // We parse out the WasmMsg::Execute wrapper... - // TODO: Handle all of Execute, Instantiate, and BankMsg replies differently. - let parsed_data = if id < EXECUTE_REPLY_BASE_ID { - parse_instantiate_response_data(data.as_slice()) - .map_err(|e| StdError::generic_err(e.to_string()))? - .data - } else { - parse_execute_response_data(data.as_slice()) - .map_err(|e| StdError::generic_err(e.to_string()))? - .data - }; - - if let Some(data) = parsed_data { - Ok(res.set_data(data)) - } else { - Ok(res) - } - } else { - Ok(res) - } -} - -pub fn contract() -> Box> { - let contract = ContractWrapper::new(execute::, instantiate::, query) - .with_reply(reply::); - Box::new(contract) -} - -pub fn custom_contract() -> Box> -where - C: Clone + Debug + PartialEq + JsonSchema + DeserializeOwned + 'static, -{ - let contract = - ContractWrapper::new(execute::, instantiate::, query).with_reply(reply::); - Box::new(contract) -} diff --git a/src/test_helpers/contracts/error.rs b/src/test_helpers/contracts/error.rs deleted file mode 100644 index ac86bcf9..00000000 --- a/src/test_helpers/contracts/error.rs +++ /dev/null @@ -1,49 +0,0 @@ -use std::fmt; - -use cosmwasm_std::{Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response, StdError}; -use schemars::JsonSchema; - -use crate::{Contract, ContractWrapper}; - -fn instantiate_err( - _deps: DepsMut, - _env: Env, - _info: MessageInfo, - _msg: Empty, -) -> Result { - Err(StdError::generic_err("Init failed")) -} - -fn instantiate_ok( - _deps: DepsMut, - _env: Env, - _info: MessageInfo, - _msg: Empty, -) -> Result { - Ok(Response::default()) -} - -fn execute( - _deps: DepsMut, - _env: Env, - _info: MessageInfo, - _msg: Empty, -) -> Result { - Err(StdError::generic_err("Handle failed")) -} - -fn query(_deps: Deps, _env: Env, _msg: Empty) -> Result { - Err(StdError::generic_err("Query failed")) -} - -pub fn contract(instantiable: bool) -> Box> -where - C: Clone + fmt::Debug + PartialEq + JsonSchema + 'static, -{ - let contract = if instantiable { - ContractWrapper::new_with_empty(execute, instantiate_ok, query) - } else { - ContractWrapper::new_with_empty(execute, instantiate_err, query) - }; - Box::new(contract) -} diff --git a/src/test_helpers/contracts/hackatom.rs b/src/test_helpers/contracts/hackatom.rs deleted file mode 100644 index d0f3f87e..00000000 --- a/src/test_helpers/contracts/hackatom.rs +++ /dev/null @@ -1,86 +0,0 @@ -//! Simplified contract which when executed releases the funds to beneficiary - -use cosmwasm_std::{ - to_binary, BankMsg, Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response, StdError, -}; -use cw_storage_plus::Item; -use serde::{Deserialize, Serialize}; - -use crate::{Contract, ContractWrapper}; -use schemars::JsonSchema; -use std::fmt; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct InstantiateMsg { - pub beneficiary: String, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct MigrateMsg { - // just use some other string so we see there are other types - pub new_guy: String, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -pub enum QueryMsg { - // returns InstantiateMsg - Beneficiary {}, -} - -const HACKATOM: Item = Item::new("hackatom"); - -fn instantiate( - deps: DepsMut, - _env: Env, - _info: MessageInfo, - msg: InstantiateMsg, -) -> Result { - HACKATOM.save(deps.storage, &msg)?; - Ok(Response::default()) -} - -fn execute(deps: DepsMut, env: Env, _info: MessageInfo, _msg: Empty) -> Result { - let init = HACKATOM.load(deps.storage)?; - let balance = deps.querier.query_all_balances(env.contract.address)?; - - let resp = Response::new().add_message(BankMsg::Send { - to_address: init.beneficiary, - amount: balance, - }); - - Ok(resp) -} - -fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result { - match msg { - QueryMsg::Beneficiary {} => { - let res = HACKATOM.load(deps.storage)?; - to_binary(&res) - } - } -} - -fn migrate(deps: DepsMut, _env: Env, msg: MigrateMsg) -> Result { - HACKATOM.update::<_, StdError>(deps.storage, |mut state| { - state.beneficiary = msg.new_guy; - Ok(state) - })?; - let resp = Response::new().add_attribute("migrate", "successful"); - Ok(resp) -} - -pub fn contract() -> Box> { - let contract = ContractWrapper::new(execute, instantiate, query).with_migrate(migrate); - Box::new(contract) -} - -#[allow(dead_code)] -pub fn custom_contract() -> Box> -where - C: Clone + fmt::Debug + PartialEq + JsonSchema + 'static, -{ - let contract = - ContractWrapper::new_with_empty(execute, instantiate, query).with_migrate_empty(migrate); - Box::new(contract) -} diff --git a/src/test_helpers/contracts/payout.rs b/src/test_helpers/contracts/payout.rs deleted file mode 100644 index fb95e2d4..00000000 --- a/src/test_helpers/contracts/payout.rs +++ /dev/null @@ -1,85 +0,0 @@ -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; -use std::fmt; - -use cosmwasm_std::{ - to_binary, BankMsg, Binary, Coin, Deps, DepsMut, Empty, Env, MessageInfo, Response, StdError, -}; -use cw_storage_plus::Item; - -use crate::contracts::{Contract, ContractWrapper}; -use crate::test_helpers::COUNT; - -#[derive(Debug, Clone, Serialize, Deserialize, Default)] -pub struct InstantiateMessage { - pub payout: Coin, -} - -#[derive(Debug, Clone, Serialize, Deserialize, Default)] -pub struct SudoMsg { - pub set_count: u32, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum QueryMsg { - Count {}, - Payout {}, -} - -#[derive(Debug, Clone, Serialize, Deserialize, Default)] -pub struct CountResponse { - pub count: u32, -} - -const PAYOUT: Item = Item::new("payout"); - -fn instantiate( - deps: DepsMut, - _env: Env, - _info: MessageInfo, - msg: InstantiateMessage, -) -> Result { - PAYOUT.save(deps.storage, &msg)?; - COUNT.save(deps.storage, &1)?; - Ok(Response::default()) -} - -fn execute(deps: DepsMut, _env: Env, info: MessageInfo, _msg: Empty) -> Result { - // always try to payout what was set originally - let payout = PAYOUT.load(deps.storage)?; - let msg = BankMsg::Send { - to_address: info.sender.into(), - amount: vec![payout.payout], - }; - Ok(Response::new() - .add_message(msg) - .add_attribute("action", "payout")) -} - -fn sudo(deps: DepsMut, _env: Env, msg: SudoMsg) -> Result { - COUNT.save(deps.storage, &msg.set_count)?; - Ok(Response::default()) -} - -fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result { - match msg { - QueryMsg::Count {} => { - let count = COUNT.load(deps.storage)?; - let res = CountResponse { count }; - to_binary(&res) - } - QueryMsg::Payout {} => { - let payout = PAYOUT.load(deps.storage)?; - to_binary(&payout) - } - } -} - -pub fn contract() -> Box> -where - C: Clone + fmt::Debug + PartialEq + JsonSchema + 'static, -{ - let contract = - ContractWrapper::new_with_empty(execute, instantiate, query).with_sudo_empty(sudo); - Box::new(contract) -} diff --git a/src/test_helpers/contracts/reflect.rs b/src/test_helpers/contracts/reflect.rs deleted file mode 100644 index 28e6aabb..00000000 --- a/src/test_helpers/contracts/reflect.rs +++ /dev/null @@ -1,73 +0,0 @@ -use serde::{Deserialize, Serialize}; - -use cosmwasm_std::{ - to_binary, Binary, Deps, DepsMut, Empty, Env, Event, MessageInfo, Reply, Response, StdError, - SubMsg, -}; -use cw_storage_plus::Map; - -use crate::contracts::{Contract, ContractWrapper}; -use crate::test_helpers::contracts::payout; -use crate::test_helpers::{CustomMsg, COUNT}; - -#[derive(Debug, Clone, Serialize, Deserialize, Default)] -pub struct Message { - pub messages: Vec>, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum QueryMsg { - Count {}, - Reply { id: u64 }, -} - -const REFLECT: Map = Map::new("reflect"); - -fn instantiate( - deps: DepsMut, - _env: Env, - _info: MessageInfo, - _msg: Empty, -) -> Result, StdError> { - COUNT.save(deps.storage, &0)?; - Ok(Response::default()) -} - -fn execute( - deps: DepsMut, - _env: Env, - _info: MessageInfo, - msg: Message, -) -> Result, StdError> { - COUNT.update::<_, StdError>(deps.storage, |old| Ok(old + 1))?; - - Ok(Response::new().add_submessages(msg.messages)) -} - -fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result { - match msg { - QueryMsg::Count {} => { - let count = COUNT.load(deps.storage)?; - let res = payout::CountResponse { count }; - to_binary(&res) - } - QueryMsg::Reply { id } => { - let reply = REFLECT.load(deps.storage, id)?; - to_binary(&reply) - } - } -} - -fn reply(deps: DepsMut, _env: Env, msg: Reply) -> Result, StdError> { - REFLECT.save(deps.storage, msg.id, &msg)?; - // add custom event here to test - let event = Event::new("custom") - .add_attribute("from", "reply") - .add_attribute("to", "test"); - Ok(Response::new().add_event(event)) -} - -pub fn contract() -> Box> { - let contract = ContractWrapper::new(execute, instantiate, query).with_reply(reply); - Box::new(contract) -} diff --git a/src/test_helpers/contracts/stargate.rs b/src/test_helpers/contracts/stargate.rs deleted file mode 100644 index d5f4f2e7..00000000 --- a/src/test_helpers/contracts/stargate.rs +++ /dev/null @@ -1,43 +0,0 @@ -use cosmwasm_std::{ - Binary, CosmosMsg, Deps, DepsMut, Empty, Env, GovMsg, IbcMsg, MessageInfo, Response, StdResult, -}; -use serde::{Deserialize, Serialize}; - -use crate::{Contract, ContractWrapper}; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum ExecMsg { - Ibc {}, - Gov {}, -} - -fn instantiate(_deps: DepsMut, _env: Env, _info: MessageInfo, _msg: Empty) -> StdResult { - Ok(Response::new()) -} - -fn execute(_deps: DepsMut, _env: Env, _info: MessageInfo, msg: ExecMsg) -> StdResult { - let msg: CosmosMsg = if let ExecMsg::Ibc {} = msg { - IbcMsg::CloseChannel { - channel_id: "channel".to_string(), - } - .into() - } else { - GovMsg::Vote { - proposal_id: 1, - vote: cosmwasm_std::VoteOption::No, - } - .into() - }; - - let resp = Response::new().add_message(msg); - Ok(resp) -} - -fn query(_deps: Deps, _env: Env, _msg: Empty) -> StdResult { - Ok(Binary::default()) -} - -pub fn contract() -> Box> { - let contract = ContractWrapper::new(execute, instantiate, query); - Box::new(contract) -} diff --git a/src/wasm.rs b/src/wasm.rs index 1e80e9de..9a966e4d 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -1,4 +1,12 @@ -use std::borrow::Borrow; +use crate::prefixed_storage::contract_namespace; +use crate::wasm_emulation::api::RealApi; +use cosmwasm_std::CustomMsg; +use cw_orch_daemon::queriers::CosmWasm; +use cw_orch_daemon::queriers::DaemonQuerier; + +use ibc_chain_registry::chain::ChainData; + +use std::collections::HashMap; use std::fmt::Debug; use cosmwasm_std::{ @@ -27,12 +35,18 @@ use anyhow::{bail, Context, Result as AnyResult}; #[cfg(feature = "cosmwasm_1_2")] use sha2::{Digest, Sha256}; +use crate::wasm_emulation::channel::get_channel; +use crate::wasm_emulation::contract::WasmContract; +use crate::wasm_emulation::input::{SerChainData, WasmStorage}; +use crate::wasm_emulation::query::AllQuerier; + // Contract state is kept in Storage, separate from the contracts themselves const CONTRACTS: Map<&Addr, ContractData> = Map::new("contracts"); pub const NAMESPACE_WASM: &[u8] = b"wasm"; /// See const CONTRACT_ATTR: &str = "_contract_address"; +const LOCAL_CODE_OFFFSET: usize = 5_000_000; #[derive(Clone, Debug, PartialEq, Eq, JsonSchema)] pub struct WasmSudo { @@ -79,7 +93,7 @@ struct CodeData { code_base_id: usize, } -pub trait Wasm { +pub trait Wasm: AllQuerier { /// Handles all WasmQuery requests fn query( &self, @@ -113,24 +127,30 @@ pub trait Wasm { ) -> AnyResult; } +// pub struct WasmKeeper { pub struct WasmKeeper { /// Contract codes that stand for wasm code in real-life blockchain. - code_base: Vec>>, + code_base: HashMap, /// Code data with code base identifier and additional attributes. - code_data: Vec, + code_data: HashMap, + /// Just markers to make type elision fork when using it as `Wasm` trait + _e: std::marker::PhantomData, /// Just markers to make type elision fork when using it as `Wasm` trait - _p: std::marker::PhantomData, + _q: std::marker::PhantomData, generator: Box, + + // chain on which the contract should be queried/tested against + chain: Option, } pub trait AddressGenerator { - fn next_address(&self, storage: &mut dyn Storage) -> Addr; + fn next_contract_address(&self, storage: &mut dyn Storage, chain_name: Option) -> Addr; } struct SimpleAddressGenerator(); impl AddressGenerator for SimpleAddressGenerator { - fn next_address(&self, storage: &mut dyn Storage) -> Addr { + fn next_contract_address(&self, storage: &mut dyn Storage, prefix: Option) -> Addr { let count = CONTRACTS .range_raw( &prefixed_read(storage, NAMESPACE_WASM), @@ -139,25 +159,55 @@ impl AddressGenerator for SimpleAddressGenerator { Order::Ascending, ) .count(); - Addr::unchecked(format!("contract{}", count)) + + let prefix = prefix.unwrap_or("cosmos".to_string()); + + RealApi::new(&prefix).next_contract_address(count) } } impl Default for WasmKeeper { - /// Returns the default value for [WasmKeeper]. - fn default() -> Self { + fn default() -> WasmKeeper { Self { - code_base: Vec::default(), - code_data: Vec::default(), - _p: std::marker::PhantomData, + code_base: HashMap::new(), + code_data: HashMap::new(), + _e: std::marker::PhantomData, + _q: std::marker::PhantomData, generator: Box::new(SimpleAddressGenerator()), + chain: None, } } } +impl AllQuerier for WasmKeeper { + type Output = WasmStorage; + fn query_all(&self, storage: &dyn Storage) -> AnyResult { + let all_local_state: Vec<_> = storage.range(None, None, Order::Ascending).collect(); + + let contracts = CONTRACTS + .range( + &prefixed_read(storage, NAMESPACE_WASM), + None, + None, + Order::Ascending, + ) + .map(|res| match res { + Ok((key, value)) => Ok((key.to_string(), value)), + Err(e) => Err(e), + }) + .collect::, _>>()?; + + Ok(WasmStorage { + contracts, + storage: all_local_state, + codes: self.code_base.clone(), + }) + } +} + impl Wasm for WasmKeeper where - ExecC: Clone + Debug + PartialEq + JsonSchema + DeserializeOwned + 'static, + ExecC: CustomMsg + DeserializeOwned + 'static, QueryC: CustomQuery + DeserializeOwned + 'static, { fn query( @@ -237,33 +287,49 @@ where impl WasmKeeper { /// Stores contract code in the in-memory lookup table. /// Returns an identifier of the stored contract code. - pub fn store_code(&mut self, creator: Addr, code: Box>) -> u64 { - let code_base_id = self.code_base.len(); - self.code_base.push(code); - let code_id = self.code_data.len() + 1; - self.code_data.push(CodeData { - creator, - seed: code_id, - code_base_id, - }); + pub fn store_code(&mut self, creator: Addr, code: WasmContract) -> u64 { + let code_id = self.code_base.len() + 1 + LOCAL_CODE_OFFFSET; + self.code_base.insert(code_id, code); + self.code_data.insert( + code_id, + CodeData { + creator, + seed: code_id, + code_base_id: code_id, + }, + ); code_id as u64 } /// Duplicates contract code with specified identifier. pub fn duplicate_code(&mut self, code_id: u64) -> AnyResult { let code_data = self.code_data(code_id)?; - self.code_data.push(CodeData { - creator: code_data.creator.clone(), - seed: code_data.seed, - code_base_id: code_data.code_base_id, - }); - Ok(code_id + 1) + let code = self + .code_base + .get(&(code_id as usize)) + .ok_or(Error::UnregisteredCodeId(code_id))?; + let code_id = self.code_base.len() + 1 + LOCAL_CODE_OFFFSET; + self.code_data.insert( + code_id, + CodeData { + creator: code_data.creator.clone(), + seed: code_data.seed, + code_base_id: code_id, + }, + ); + self.code_base.insert(code_id, code.clone()); + + Ok(code_id as u64) } /// Returns a handler to code of the contract with specified code id. - pub fn contract_code(&self, code_id: u64) -> AnyResult<&dyn Contract> { + pub fn contract_code(&self, code_id: u64) -> AnyResult { let code_data = self.code_data(code_id)?; - Ok(self.code_base[code_data.code_base_id].borrow()) + Ok(self + .code_base + .get(&code_data.code_base_id) + .ok_or(Error::UnregisteredCodeId(code_id))? + .clone()) } /// Returns code data of the contract with specified code id. @@ -273,14 +339,60 @@ impl WasmKeeper { } Ok(self .code_data - .get((code_id - 1) as usize) + .get(&(code_id as usize)) .ok_or(Error::UnregisteredCodeId(code_id))?) } + /// This function won't error if it doesn't find the contract + /// This allows for querying an online contract struct without having to check if it exists just there + /// Upon execution, it will fail if the contract doesn't exist + fn get_code(&self, storage: &dyn Storage, address: &Addr) -> WasmContract { + if let Ok(handler) = self.load_contract(storage, address) { + let code = self.code_base.get(&(handler.code_id as usize)); + if let Some(code) = code { + return code.clone(); + } else { + return WasmContract::new_distant_code_id( + handler.code_id.try_into().unwrap(), + self.chain.clone().unwrap(), + ); + } + } + + WasmContract::new_distant_contract(address.to_string(), self.chain.clone().unwrap()) + } + + pub fn load_distant_contract( + chain: impl Into, + address: &Addr, + ) -> AnyResult { + let (rt, channel) = get_channel(chain)?; + + let wasm_querier = CosmWasm::new(channel); + + let code_info = rt.block_on(wasm_querier.contract_info(address.clone()))?; + + Ok(ContractData { + admin: { + match code_info.admin.as_str() { + "" => None, + a => Some(Addr::unchecked(a)), + } + }, + code_id: code_info.code_id.try_into()?, + created: code_info.created.unwrap().block_height, + creator: Addr::unchecked(code_info.creator), + label: code_info.label, + }) + } + pub fn load_contract(&self, storage: &dyn Storage, address: &Addr) -> AnyResult { - CONTRACTS - .load(&prefixed_read(storage, NAMESPACE_WASM), address) - .map_err(Into::into) + if let Ok(local_contract) = CONTRACTS.load(&prefixed_read(storage, NAMESPACE_WASM), address) + { + return Ok(local_contract); + } + + Self::load_distant_contract(self.chain.clone().unwrap(), address) } pub fn dump_wasm_raw(&self, storage: &dyn Storage, address: &Addr) -> Vec { @@ -288,12 +400,6 @@ impl WasmKeeper { storage.range(None, None, Order::Ascending).collect() } - fn contract_namespace(&self, contract: &Addr) -> Vec { - let mut name = b"contract_data/".to_vec(); - name.extend_from_slice(contract.as_bytes()); - name - } - fn contract_storage<'a>( &self, storage: &'a mut dyn Storage, @@ -301,7 +407,7 @@ impl WasmKeeper { ) -> Box { // We double-namespace this, once from global storage -> wasm_storage // then from wasm_storage -> the contracts subspace - let namespace = self.contract_namespace(address); + let namespace = contract_namespace(address); let storage = PrefixedStorage::multilevel(storage, &[NAMESPACE_WASM, &namespace]); Box::new(storage) } @@ -314,7 +420,7 @@ impl WasmKeeper { ) -> Box { // We double-namespace this, once from global storage -> wasm_storage // then from wasm_storage -> the contracts subspace - let namespace = self.contract_namespace(address); + let namespace = contract_namespace(address); let storage = ReadonlyPrefixedStorage::multilevel(storage, &[NAMESPACE_WASM, &namespace]); Box::new(storage) } @@ -360,7 +466,7 @@ impl WasmKeeper { impl WasmKeeper where - ExecC: Clone + Debug + PartialEq + JsonSchema + DeserializeOwned + 'static, + ExecC: CustomMsg + DeserializeOwned + 'static, QueryC: CustomQuery + DeserializeOwned + 'static, { pub fn new() -> Self { @@ -374,6 +480,10 @@ where } } + pub fn set_chain(&mut self, chain: ChainData) { + self.chain = Some(chain); + } + pub fn query_smart( &self, address: Addr, @@ -389,7 +499,9 @@ where querier, block, address, - |handler, deps, env| handler.query(deps, env, msg), + |handler, deps, env| { + >::query(&handler, deps, env, msg) + }, ) } @@ -569,10 +681,9 @@ where } => { let contract_addr = api.addr_validate(&contract_addr)?; - // check admin status and update the stored code_id - if new_code_id as usize > self.code_data.len() { - bail!("Cannot migrate contract to unregistered code id"); - } + // We don't check if the code exists here, the call_migrate hook, will take care of that + // This allows migrating to an on-chain code_id + let mut data = self.load_contract(storage, &contract_addr)?; if data.admin != Some(sender) { bail!("Only admin can migrate contract: {:?}", data.admin); @@ -770,6 +881,7 @@ where /// You must call init after this to set up the contract properly. /// These are separated into two steps to have cleaner return values. pub fn register_contract( + // TODO &self, storage: &mut dyn Storage, code_id: u64, @@ -778,11 +890,9 @@ where label: String, created: u64, ) -> AnyResult { - if code_id as usize > self.code_data.len() { - bail!("Cannot init contract with unregistered code id"); - } - - let addr = self.generator.next_address(storage); + let addr = self + .generator + .next_contract_address(storage, self.chain.clone().map(|c| c.bech32_prefix)); let info = ContractData { code_id, @@ -912,10 +1022,10 @@ where action: F, ) -> AnyResult where - F: FnOnce(&dyn Contract, Deps, Env) -> AnyResult, + F: FnOnce(WasmContract, Deps, Env) -> AnyResult, { - let contract = self.load_contract(storage, &address)?; - let handler = self.contract_code(contract.code_id)?; + let handler = self.get_code(storage, &address); + let storage = self.contract_storage_readonly(storage, &address); let env = self.get_env(address, block); @@ -937,11 +1047,10 @@ where action: F, ) -> AnyResult where - F: FnOnce(&dyn Contract, DepsMut, Env) -> AnyResult, + F: FnOnce(WasmContract, DepsMut, Env) -> AnyResult, ExecC: DeserializeOwned, { - let contract = self.load_contract(storage, &address)?; - let handler = self.contract_code(contract.code_id)?; + let handler = self.get_code(storage, &address); // We don't actually need a transaction here, as it is already embedded in a transactional. // execute_submsg or App.execute_multi. @@ -957,7 +1066,7 @@ where api, querier: QuerierWrapper::new(&querier), }; - action(handler, deps, env) + action(handler.clone(), deps, env) }) } @@ -1012,747 +1121,3 @@ fn execute_response(data: Option) -> Option { new_data.into() }) } - -#[cfg(test)] -mod test { - use cosmwasm_std::testing::{mock_env, mock_info, MockApi, MockQuerier, MockStorage}; - use cosmwasm_std::{ - coin, from_slice, to_vec, BankMsg, Coin, CosmosMsg, Empty, GovMsg, IbcMsg, IbcQuery, - StdError, - }; - - use crate::app::Router; - use crate::bank::BankKeeper; - use crate::module::FailingModule; - use crate::staking::{DistributionKeeper, StakeKeeper}; - use crate::test_helpers::contracts::{caller, error, payout}; - use crate::transactions::StorageTransaction; - - use super::*; - - /// Type alias for default build `Router` to make its reference in typical scenario - type BasicRouter = Router< - BankKeeper, - FailingModule, - WasmKeeper, - StakeKeeper, - DistributionKeeper, - FailingModule, - FailingModule, - >; - - fn wasm_keeper() -> WasmKeeper { - WasmKeeper::new() - } - - fn mock_router() -> BasicRouter { - Router { - wasm: WasmKeeper::new(), - bank: BankKeeper::new(), - custom: FailingModule::new(), - staking: StakeKeeper::new(), - distribution: DistributionKeeper::new(), - ibc: FailingModule::new(), - gov: FailingModule::new(), - } - } - - #[test] - fn register_contract() { - let api = MockApi::default(); - let mut wasm_storage = MockStorage::new(); - let mut wasm_keeper = wasm_keeper(); - let block = mock_env().block; - let code_id = wasm_keeper.store_code(Addr::unchecked("creator"), error::contract(false)); - - transactional(&mut wasm_storage, |cache, _| { - // cannot register contract with unregistered codeId - wasm_keeper.register_contract( - cache, - code_id + 1, - Addr::unchecked("foobar"), - Addr::unchecked("admin"), - "label".to_owned(), - 1000, - ) - }) - .unwrap_err(); - - let contract_addr = transactional(&mut wasm_storage, |cache, _| { - // we can register a new instance of this code - wasm_keeper.register_contract( - cache, - code_id, - Addr::unchecked("foobar"), - Addr::unchecked("admin"), - "label".to_owned(), - 1000, - ) - }) - .unwrap(); - - // verify contract data are as expected - let contract_data = wasm_keeper - .load_contract(&wasm_storage, &contract_addr) - .unwrap(); - - assert_eq!( - contract_data, - ContractData { - code_id, - creator: Addr::unchecked("foobar"), - admin: Some(Addr::unchecked("admin")), - label: "label".to_owned(), - created: 1000, - } - ); - - let err = transactional(&mut wasm_storage, |cache, _| { - // now, we call this contract and see the error message from the contract - let info = mock_info("foobar", &[]); - wasm_keeper.call_instantiate( - contract_addr.clone(), - &api, - cache, - &mock_router(), - &block, - info, - b"{}".to_vec(), - ) - }) - .unwrap_err(); - - // StdError from contract_error auto-converted to string - assert_eq!( - StdError::generic_err("Init failed"), - err.downcast().unwrap() - ); - - let err = transactional(&mut wasm_storage, |cache, _| { - // and the error for calling an unregistered contract - let info = mock_info("foobar", &[]); - wasm_keeper.call_instantiate( - Addr::unchecked("unregistered"), - &api, - cache, - &mock_router(), - &block, - info, - b"{}".to_vec(), - ) - }) - .unwrap_err(); - - // Default error message from router when not found - assert_eq!( - StdError::not_found("cw_multi_test::wasm::ContractData"), - err.downcast().unwrap() - ); - } - - #[test] - fn query_contract_info() { - let api = MockApi::default(); - let mut wasm_storage = MockStorage::new(); - let mut wasm_keeper = wasm_keeper(); - let block = mock_env().block; - let code_id = wasm_keeper.store_code(Addr::unchecked("buzz"), payout::contract()); - assert_eq!(1, code_id); - - let creator = "foobar"; - let admin = "admin"; - - let contract_addr = wasm_keeper - .register_contract( - &mut wasm_storage, - code_id, - Addr::unchecked(creator), - Addr::unchecked(admin), - "label".to_owned(), - 1000, - ) - .unwrap(); - - let querier: MockQuerier = MockQuerier::new(&[]); - let query = WasmQuery::ContractInfo { - contract_addr: contract_addr.into(), - }; - - let contract_info = wasm_keeper - .query(&api, &wasm_storage, &querier, &block, query) - .unwrap(); - - let actual: ContractInfoResponse = from_slice(&contract_info).unwrap(); - let mut expected = ContractInfoResponse::default(); - expected.code_id = code_id; - expected.creator = creator.into(); - expected.admin = Some(admin.into()); - assert_eq!(expected, actual); - } - - #[test] - #[cfg(feature = "cosmwasm_1_2")] - fn query_code_info() { - let api = MockApi::default(); - let wasm_storage = MockStorage::new(); - let mut wasm_keeper = wasm_keeper(); - let block = mock_env().block; - let code_id = wasm_keeper.store_code(Addr::unchecked("creator"), payout::contract()); - let querier: MockQuerier = MockQuerier::new(&[]); - let query = WasmQuery::CodeInfo { code_id }; - let code_info = wasm_keeper - .query(&api, &wasm_storage, &querier, &block, query) - .unwrap(); - let actual: cosmwasm_std::CodeInfoResponse = from_slice(&code_info).unwrap(); - assert_eq!(code_id, actual.code_id); - assert_eq!("creator", actual.creator); - assert!(!actual.checksum.is_empty()); - } - - #[test] - #[cfg(feature = "cosmwasm_1_2")] - fn different_contracts_must_have_different_checksum() { - let api = MockApi::default(); - let wasm_storage = MockStorage::new(); - let mut wasm_keeper = wasm_keeper(); - let block = mock_env().block; - let code_id_payout = wasm_keeper.store_code(Addr::unchecked("creator"), payout::contract()); - let code_id_caller = wasm_keeper.store_code(Addr::unchecked("creator"), caller::contract()); - let querier: MockQuerier = MockQuerier::new(&[]); - let query_payout = WasmQuery::CodeInfo { - code_id: code_id_payout, - }; - let query_caller = WasmQuery::CodeInfo { - code_id: code_id_caller, - }; - let code_info_payout = wasm_keeper - .query(&api, &wasm_storage, &querier, &block, query_payout) - .unwrap(); - let code_info_caller = wasm_keeper - .query(&api, &wasm_storage, &querier, &block, query_caller) - .unwrap(); - let info_payout: cosmwasm_std::CodeInfoResponse = from_slice(&code_info_payout).unwrap(); - let info_caller: cosmwasm_std::CodeInfoResponse = from_slice(&code_info_caller).unwrap(); - assert_eq!(code_id_payout, info_payout.code_id); - assert_eq!(code_id_caller, info_caller.code_id); - assert_ne!(info_caller.code_id, info_payout.code_id); - assert_eq!(info_caller.creator, info_payout.creator); - assert_ne!(info_caller.checksum, info_payout.checksum); - } - - #[test] - #[cfg(feature = "cosmwasm_1_2")] - fn querying_invalid_code_info_must_fail() { - let api = MockApi::default(); - let wasm_storage = MockStorage::new(); - let wasm_keeper = wasm_keeper(); - let block = mock_env().block; - - let querier: MockQuerier = MockQuerier::new(&[]); - let query = WasmQuery::CodeInfo { code_id: 100 }; - - wasm_keeper - .query(&api, &wasm_storage, &querier, &block, query) - .unwrap_err(); - } - - #[test] - fn can_dump_raw_wasm_state() { - let api = MockApi::default(); - let mut wasm_keeper = wasm_keeper(); - let block = mock_env().block; - let code_id = wasm_keeper.store_code(Addr::unchecked("buzz"), payout::contract()); - - let mut wasm_storage = MockStorage::new(); - - let contract_addr = wasm_keeper - .register_contract( - &mut wasm_storage, - code_id, - Addr::unchecked("foobar"), - Addr::unchecked("admin"), - "label".to_owned(), - 1000, - ) - .unwrap(); - - // make a contract with state - let payout = coin(1500, "mlg"); - let msg = payout::InstantiateMessage { - payout: payout.clone(), - }; - wasm_keeper - .call_instantiate( - contract_addr.clone(), - &api, - &mut wasm_storage, - &mock_router(), - &block, - mock_info("foobar", &[]), - to_vec(&msg).unwrap(), - ) - .unwrap(); - - // dump state - let state = wasm_keeper.dump_wasm_raw(&wasm_storage, &contract_addr); - assert_eq!(state.len(), 2); - // check contents - let (k, v) = &state[0]; - assert_eq!(k.as_slice(), b"count"); - let count: u32 = from_slice(v).unwrap(); - assert_eq!(count, 1); - let (k, v) = &state[1]; - assert_eq!(k.as_slice(), b"payout"); - let stored_pay: payout::InstantiateMessage = from_slice(v).unwrap(); - assert_eq!(stored_pay.payout, payout); - } - - #[test] - fn contract_send_coins() { - let api = MockApi::default(); - let mut wasm_keeper = wasm_keeper(); - let block = mock_env().block; - let code_id = wasm_keeper.store_code(Addr::unchecked("buzz"), payout::contract()); - - let mut wasm_storage = MockStorage::new(); - let mut cache = StorageTransaction::new(&wasm_storage); - - let contract_addr = wasm_keeper - .register_contract( - &mut cache, - code_id, - Addr::unchecked("foobar"), - None, - "label".to_owned(), - 1000, - ) - .unwrap(); - - let payout = coin(100, "TGD"); - - // init the contract - let info = mock_info("foobar", &[]); - let init_msg = to_vec(&payout::InstantiateMessage { - payout: payout.clone(), - }) - .unwrap(); - let res = wasm_keeper - .call_instantiate( - contract_addr.clone(), - &api, - &mut cache, - &mock_router(), - &block, - info, - init_msg, - ) - .unwrap(); - assert_eq!(0, res.messages.len()); - - // execute the contract - let info = mock_info("foobar", &[]); - let res = wasm_keeper - .call_execute( - &api, - &mut cache, - contract_addr.clone(), - &mock_router(), - &block, - info, - b"{}".to_vec(), - ) - .unwrap(); - assert_eq!(1, res.messages.len()); - match &res.messages[0].msg { - CosmosMsg::Bank(BankMsg::Send { to_address, amount }) => { - assert_eq!(to_address.as_str(), "foobar"); - assert_eq!(amount.as_slice(), &[payout.clone()]); - } - m => panic!("Unexpected message {:?}", m), - } - - // and flush before query - cache.prepare().commit(&mut wasm_storage); - - // query the contract - let query = to_vec(&payout::QueryMsg::Payout {}).unwrap(); - let querier: MockQuerier = MockQuerier::new(&[]); - let data = wasm_keeper - .query_smart(contract_addr, &api, &wasm_storage, &querier, &block, query) - .unwrap(); - let res: payout::InstantiateMessage = from_slice(&data).unwrap(); - assert_eq!(res.payout, payout); - } - - fn assert_payout( - router: &WasmKeeper, - storage: &mut dyn Storage, - contract_addr: &Addr, - payout: &Coin, - ) { - let api = MockApi::default(); - let info = mock_info("silly", &[]); - let res = router - .call_execute( - &api, - storage, - contract_addr.clone(), - &mock_router(), - &mock_env().block, - info, - b"{}".to_vec(), - ) - .unwrap(); - assert_eq!(1, res.messages.len()); - match &res.messages[0].msg { - CosmosMsg::Bank(BankMsg::Send { to_address, amount }) => { - assert_eq!(to_address.as_str(), "silly"); - assert_eq!(amount.as_slice(), &[payout.clone()]); - } - m => panic!("Unexpected message {:?}", m), - } - } - - fn assert_no_contract(storage: &dyn Storage, contract_addr: &Addr) { - let contract = CONTRACTS.may_load(storage, contract_addr).unwrap(); - assert!(contract.is_none(), "{:?}", contract_addr); - } - - #[test] - fn multi_level_wasm_cache() { - let api = MockApi::default(); - let mut wasm_keeper = wasm_keeper(); - let block = mock_env().block; - let code_id = wasm_keeper.store_code(Addr::unchecked("buzz"), payout::contract()); - - let mut wasm_storage = MockStorage::new(); - - let payout1 = coin(100, "TGD"); - - // set contract 1 and commit (on router) - let contract1 = transactional(&mut wasm_storage, |cache, _| { - let contract = wasm_keeper - .register_contract( - cache, - code_id, - Addr::unchecked("foobar"), - None, - "".to_string(), - 1000, - ) - .unwrap(); - let info = mock_info("foobar", &[]); - let init_msg = to_vec(&payout::InstantiateMessage { - payout: payout1.clone(), - }) - .unwrap(); - wasm_keeper - .call_instantiate( - contract.clone(), - &api, - cache, - &mock_router(), - &block, - info, - init_msg, - ) - .unwrap(); - - Ok(contract) - }) - .unwrap(); - - let payout2 = coin(50, "BTC"); - let payout3 = coin(1234, "ATOM"); - - // create a new cache and check we can use contract 1 - let (contract2, contract3) = transactional(&mut wasm_storage, |cache, wasm_reader| { - assert_payout(&wasm_keeper, cache, &contract1, &payout1); - - // create contract 2 and use it - let contract2 = wasm_keeper - .register_contract( - cache, - code_id, - Addr::unchecked("foobar"), - None, - "".to_owned(), - 1000, - ) - .unwrap(); - let info = mock_info("foobar", &[]); - let init_msg = to_vec(&payout::InstantiateMessage { - payout: payout2.clone(), - }) - .unwrap(); - let _res = wasm_keeper - .call_instantiate( - contract2.clone(), - &api, - cache, - &mock_router(), - &block, - info, - init_msg, - ) - .unwrap(); - assert_payout(&wasm_keeper, cache, &contract2, &payout2); - - // create a level2 cache and check we can use contract 1 and contract 2 - let contract3 = transactional(cache, |cache2, read| { - assert_payout(&wasm_keeper, cache2, &contract1, &payout1); - assert_payout(&wasm_keeper, cache2, &contract2, &payout2); - - // create a contract on level 2 - let contract3 = wasm_keeper - .register_contract( - cache2, - code_id, - Addr::unchecked("foobar"), - None, - "".to_owned(), - 1000, - ) - .unwrap(); - let info = mock_info("johnny", &[]); - let init_msg = to_vec(&payout::InstantiateMessage { - payout: payout3.clone(), - }) - .unwrap(); - let _res = wasm_keeper - .call_instantiate( - contract3.clone(), - &api, - cache2, - &mock_router(), - &block, - info, - init_msg, - ) - .unwrap(); - assert_payout(&wasm_keeper, cache2, &contract3, &payout3); - - // ensure first cache still doesn't see this contract - assert_no_contract(read, &contract3); - Ok(contract3) - }) - .unwrap(); - - // after applying transaction, all contracts present on cache - assert_payout(&wasm_keeper, cache, &contract1, &payout1); - assert_payout(&wasm_keeper, cache, &contract2, &payout2); - assert_payout(&wasm_keeper, cache, &contract3, &payout3); - - // but not yet the root router - assert_no_contract(wasm_reader, &contract1); - assert_no_contract(wasm_reader, &contract2); - assert_no_contract(wasm_reader, &contract3); - - Ok((contract2, contract3)) - }) - .unwrap(); - - // ensure that it is now applied to the router - assert_payout(&wasm_keeper, &mut wasm_storage, &contract1, &payout1); - assert_payout(&wasm_keeper, &mut wasm_storage, &contract2, &payout2); - assert_payout(&wasm_keeper, &mut wasm_storage, &contract3, &payout3); - } - - fn assert_admin( - storage: &dyn Storage, - wasm_keeper: &WasmKeeper, - contract_addr: &impl ToString, - admin: Option, - ) { - let api = MockApi::default(); - let querier: MockQuerier = MockQuerier::new(&[]); - // query - let data = wasm_keeper - .query( - &api, - storage, - &querier, - &mock_env().block, - WasmQuery::ContractInfo { - contract_addr: contract_addr.to_string(), - }, - ) - .unwrap(); - let res: ContractInfoResponse = from_slice(&data).unwrap(); - assert_eq!(res.admin, admin.as_ref().map(Addr::to_string)); - } - - #[test] - fn update_clear_admin_works() { - let api = MockApi::default(); - let mut wasm_keeper = wasm_keeper(); - let block = mock_env().block; - let code_id = wasm_keeper.store_code(Addr::unchecked("creator"), caller::contract()); - - let mut wasm_storage = MockStorage::new(); - - let admin: Addr = Addr::unchecked("admin"); - let new_admin: Addr = Addr::unchecked("new_admin"); - let normal_user: Addr = Addr::unchecked("normal_user"); - - let contract_addr = wasm_keeper - .register_contract( - &mut wasm_storage, - code_id, - Addr::unchecked("creator"), - admin.clone(), - "label".to_owned(), - 1000, - ) - .unwrap(); - - // init the contract - let info = mock_info("admin", &[]); - let init_msg = to_vec(&Empty {}).unwrap(); - let res = wasm_keeper - .call_instantiate( - contract_addr.clone(), - &api, - &mut wasm_storage, - &mock_router(), - &block, - info, - init_msg, - ) - .unwrap(); - assert_eq!(0, res.messages.len()); - - assert_admin( - &wasm_storage, - &wasm_keeper, - &contract_addr, - Some(admin.clone()), - ); - - // non-admin should not be allowed to become admin on their own - wasm_keeper - .execute_wasm( - &api, - &mut wasm_storage, - &mock_router(), - &block, - normal_user.clone(), - WasmMsg::UpdateAdmin { - contract_addr: contract_addr.to_string(), - admin: normal_user.to_string(), - }, - ) - .unwrap_err(); - - // should still be admin - assert_admin( - &wasm_storage, - &wasm_keeper, - &contract_addr, - Some(admin.clone()), - ); - - // admin should be allowed to transfer administration permissions - let res = wasm_keeper - .execute_wasm( - &api, - &mut wasm_storage, - &mock_router(), - &block, - admin, - WasmMsg::UpdateAdmin { - contract_addr: contract_addr.to_string(), - admin: new_admin.to_string(), - }, - ) - .unwrap(); - assert_eq!(res.events.len(), 0); - - // new_admin should now be admin - assert_admin( - &wasm_storage, - &wasm_keeper, - &contract_addr, - Some(new_admin.clone()), - ); - - // new_admin should now be able to clear to admin - let res = wasm_keeper - .execute_wasm( - &api, - &mut wasm_storage, - &mock_router(), - &block, - new_admin, - WasmMsg::ClearAdmin { - contract_addr: contract_addr.to_string(), - }, - ) - .unwrap(); - assert_eq!(res.events.len(), 0); - - // should have no admin now - assert_admin(&wasm_storage, &wasm_keeper, &contract_addr, None); - } - - #[test] - fn by_default_uses_simple_address_generator() { - let mut wasm_keeper = wasm_keeper(); - let code_id = wasm_keeper.store_code(Addr::unchecked("creator"), payout::contract()); - - let mut wasm_storage = MockStorage::new(); - - let contract_addr = wasm_keeper - .register_contract( - &mut wasm_storage, - code_id, - Addr::unchecked("foobar"), - Addr::unchecked("admin"), - "label".to_owned(), - 1000, - ) - .unwrap(); - - assert_eq!( - "contract0", contract_addr, - "default address generator returned incorrect address" - ) - } - - struct TestAddressGenerator { - addr_to_return: Addr, - } - impl AddressGenerator for TestAddressGenerator { - fn next_address(&self, _: &mut dyn Storage) -> Addr { - self.addr_to_return.clone() - } - } - - #[test] - fn can_use_custom_address_generator() { - let expected_addr = Addr::unchecked("new_test_addr"); - let mut wasm_keeper: WasmKeeper = - WasmKeeper::new_with_custom_address_generator(TestAddressGenerator { - addr_to_return: expected_addr.clone(), - }); - let code_id = wasm_keeper.store_code(Addr::unchecked("creator"), payout::contract()); - - let mut wasm_storage = MockStorage::new(); - - let contract_addr = wasm_keeper - .register_contract( - &mut wasm_storage, - code_id, - Addr::unchecked("foobar"), - Addr::unchecked("admin"), - "label".to_owned(), - 1000, - ) - .unwrap(); - - assert_eq!( - expected_addr, contract_addr, - "custom address generator returned incorrect address" - ) - } -} diff --git a/src/wasm_emulation/api/mod.rs b/src/wasm_emulation/api/mod.rs new file mode 100644 index 00000000..5dbf2cd6 --- /dev/null +++ b/src/wasm_emulation/api/mod.rs @@ -0,0 +1,116 @@ +use crate::wasm_emulation::query::gas::{GAS_COST_CANONICALIZE, GAS_COST_HUMANIZE}; +use bech32::{FromBase32, ToBase32, Variant}; +use cosmwasm_std::Addr; +use cosmwasm_vm::{BackendApi, BackendError, GasInfo}; + +const SHORT_CANON_LEN: usize = 20; +const LONG_CANON_LEN: usize = 32; + +pub fn bytes_from_bech32(address: &str, prefix: &str) -> Result, BackendError> { + if address.is_empty() { + return Err(BackendError::Unknown { + msg: "empty address string is not allowed".to_string(), + }); + } + + let (hrp, data, _variant) = bech32::decode(address).map_err(|e| BackendError::Unknown { + msg: format!("Invalid Bech32 address : Err {}", e), + })?; + if hrp != prefix { + return Err(BackendError::Unknown { + msg: format!("invalid Bech32 prefix; expected {}, got {}", prefix, hrp), + }); + } + + Ok(Vec::::from_base32(&data).unwrap()) +} + +// Prefixes are limited to 6 chars +// This allows one to specify a string prefix and still implement Copy +#[derive(Clone, Copy)] +pub struct RealApi { + pub prefix1: Option, + pub prefix2: Option, + pub prefix3: Option, + pub prefix4: Option, + pub prefix5: Option, + pub prefix6: Option, +} + +impl RealApi { + pub fn new(prefix: &str) -> RealApi { + let mut chars = prefix.chars(); + Self { + prefix1: chars.next(), + prefix2: chars.next(), + prefix3: chars.next(), + prefix4: chars.next(), + prefix5: chars.next(), + prefix6: chars.next(), + } + } + + pub fn get_prefix(&self) -> String { + let collection = [ + self.prefix1, + self.prefix2, + self.prefix3, + self.prefix4, + self.prefix5, + self.prefix6, + ]; + + collection.iter().filter_map(|e| *e).collect() + } + + pub fn next_address(&self, count: usize) -> Addr { + let mut canon = format!("ADDRESS_{}", count).as_bytes().to_vec(); + canon.resize(SHORT_CANON_LEN, 0); + Addr::unchecked(self.human_address(&canon).0.unwrap()) + } + + pub fn next_contract_address(&self, count: usize) -> Addr { + let mut canon = format!("CONTRACT_{}", count).as_bytes().to_vec(); + canon.resize(LONG_CANON_LEN, 0); + Addr::unchecked(self.human_address(&canon).0.unwrap()) + } +} + +impl BackendApi for RealApi { + fn canonical_address(&self, address: &str) -> (Result, BackendError>, GasInfo) { + let gas_cost = GasInfo::with_externally_used(GAS_COST_CANONICALIZE); + if address.trim().is_empty() { + return ( + Err(BackendError::Unknown { + msg: "empty address string is not allowed".to_string(), + }), + gas_cost, + ); + } + + (bytes_from_bech32(address, &self.get_prefix()), gas_cost) + } + fn human_address(&self, canon: &[u8]) -> (Result, GasInfo) { + let gas_cost = GasInfo::with_externally_used(GAS_COST_HUMANIZE); + + log::info!("address {:?}", canon); + + if canon.len() != SHORT_CANON_LEN && canon.len() != LONG_CANON_LEN { + return ( + Err(BackendError::Unknown { + msg: "Canon address doesn't have the right length".to_string(), + }), + gas_cost, + ); + } + + if canon.is_empty() { + return (Ok("".to_string()), gas_cost); + } + + let human = bech32::encode(&self.get_prefix(), canon.to_base32(), Variant::Bech32) + .map_err(|e| BackendError::Unknown { msg: e.to_string() }); + + (human, gas_cost) + } +} diff --git a/src/wasm_emulation/channel.rs b/src/wasm_emulation/channel.rs new file mode 100644 index 00000000..b749bcbd --- /dev/null +++ b/src/wasm_emulation/channel.rs @@ -0,0 +1,14 @@ +use crate::wasm_emulation::input::SerChainData; +use anyhow::Result as AnyResult; +use cw_orch_daemon::GrpcChannel; +use tokio::runtime::Runtime; +use tonic::transport::Channel; + +pub fn get_channel(chain: impl Into) -> AnyResult<(Runtime, Channel)> { + let rt = Runtime::new()?; + let chain = chain.into(); + // We create an instance from a code_id, an address, and we run the code in it + let channel = rt.block_on(GrpcChannel::connect(&chain.apis.grpc, &chain.chain_id))?; + + Ok((rt, channel)) +} diff --git a/src/wasm_emulation/contract.rs b/src/wasm_emulation/contract.rs new file mode 100644 index 00000000..7a04ddbd --- /dev/null +++ b/src/wasm_emulation/contract.rs @@ -0,0 +1,443 @@ +use crate::wasm_emulation::api::RealApi; +use crate::wasm_emulation::input::get_querier_storage; +use crate::wasm_emulation::input::ReplyArgs; +use crate::wasm_emulation::input::SerChainData; +use crate::wasm_emulation::output::StorageChanges; +use crate::wasm_emulation::query::MockQuerier; +use crate::wasm_emulation::storage::DualStorage; +use cosmwasm_std::CustomMsg; +use cosmwasm_std::StdError; +use cosmwasm_vm::call_execute; +use cosmwasm_vm::call_instantiate; +use cosmwasm_vm::call_migrate; +use cosmwasm_vm::call_query; +use cosmwasm_vm::call_reply; +use cosmwasm_vm::call_sudo; +use cosmwasm_vm::Backend; +use cosmwasm_vm::BackendApi; +use cosmwasm_vm::Checksum; +use cosmwasm_vm::Instance; +use cosmwasm_vm::InstanceOptions; +use cosmwasm_vm::Querier; +use cosmwasm_vm::Size; +use cw_orch_daemon::queriers::CosmWasm; +use cw_orch_daemon::queriers::DaemonQuerier; + +use cosmwasm_std::Empty; +use cosmwasm_std::Order; +use cosmwasm_std::Storage; + +use serde::de::DeserializeOwned; +use serde::Deserialize; +use serde::Serialize; + +use crate::wasm_emulation::input::InstanceArguments; +use crate::wasm_emulation::output::WasmRunnerOutput; + +use std::collections::HashSet; + +use cosmwasm_vm::internals::check_wasm; + +use crate::Contract; + +use cosmwasm_std::{Binary, CustomQuery, Deps, DepsMut, Env, MessageInfo, Reply, Response}; + +use anyhow::Result as AnyResult; + +use super::channel::get_channel; +use super::input::ExecuteArgs; +use super::input::InstantiateArgs; +use super::input::MigrateArgs; +use super::input::QueryArgs; +use super::input::SudoArgs; +use super::input::WasmFunction; +use super::output::WasmOutput; + +fn apply_storage_changes(storage: &mut dyn Storage, output: &WasmRunnerOutput) { + // We change all the values with the output + for (key, value) in &output.storage.current_keys { + storage.set(key, value); + } + + // We remove all values that need to be removed from it + for key in &output.storage.removed_keys { + storage.remove(key); + } +} + +/// Taken from cosmwasm_vm::testing +/// This gas limit is used in integration tests and should be high enough to allow a reasonable +/// number of contract executions and queries on one instance. For this reason it is significatly +/// higher than the limit for a single execution that we have in the production setup. +const DEFAULT_GAS_LIMIT: u64 = 500_000_000_000; // ~0.5ms +const DEFAULT_MEMORY_LIMIT: Option = Some(Size::mebi(16)); +const DEFAULT_PRINT_DEBUG: bool = true; + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct DistantContract { + pub contract_addr: String, + pub chain: SerChainData, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct DistantCodeId { + pub code_id: u64, + pub chain: SerChainData, +} + +#[derive(Serialize, Deserialize, Clone)] +pub struct LocalContract { + pub code: Vec, + pub chain: SerChainData, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub enum WasmContract { + Local(LocalContract), + DistantContract(DistantContract), + DistantCodeId(DistantCodeId), +} + +impl std::fmt::Debug for LocalContract { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + write!( + f, + "LocalContract {{ checksum: {}, chain: {:?} }}", + Checksum::generate(&self.code), + self.chain + ) + } +} + +impl WasmContract { + pub fn new_local(code: Vec, chain: impl Into) -> Self { + check_wasm( + &code, + &HashSet::from([ + "iterator".to_string(), + "staking".to_string(), + "stargate".to_string(), + ]), + ) + .unwrap(); + Self::Local(LocalContract { + code, + chain: chain.into(), + }) + } + + pub fn new_distant_contract(contract_addr: String, chain: impl Into) -> Self { + Self::DistantContract(DistantContract { + contract_addr, + chain: chain.into(), + }) + } + + pub fn new_distant_code_id(code_id: u64, chain: impl Into) -> Self { + Self::DistantCodeId(DistantCodeId { + code_id, + chain: chain.into(), + }) + } + + pub fn get_chain(&self) -> SerChainData { + match self { + WasmContract::Local(LocalContract { chain, .. }) => chain.clone(), + WasmContract::DistantContract(DistantContract { chain, .. }) => chain.clone(), + WasmContract::DistantCodeId(DistantCodeId { chain, .. }) => chain.clone(), + } + } + + pub fn get_code(&self) -> AnyResult> { + match self { + WasmContract::Local(LocalContract { code, .. }) => Ok(code.clone()), + WasmContract::DistantContract(DistantContract { + chain, + contract_addr, + }) => { + let (rt, channel) = get_channel(chain.clone())?; + let wasm_querier = CosmWasm::new(channel); + + let code_info = rt.block_on(wasm_querier.contract_info(contract_addr))?; + let code = rt.block_on(wasm_querier.code_data(code_info.code_id))?; + Ok(code) + } + WasmContract::DistantCodeId(DistantCodeId { chain, code_id }) => { + let (rt, channel) = get_channel(chain.clone())?; + let wasm_querier = CosmWasm::new(channel); + + let code = rt.block_on(wasm_querier.code_data(*code_id))?; + Ok(code) + } + } + } + + pub fn run_contract( + &self, + args: InstanceArguments, + ) -> AnyResult> { + let InstanceArguments { + function, + init_storage, + querier_storage, + } = args; + let chain: SerChainData = self.get_chain(); + let address = function.get_address(); + let code = self.get_code()?; + + let api = RealApi::new(&chain.bech32_prefix); + + // We create the backend here from outside information; + let backend = Backend { + api, + storage: DualStorage::new(chain.clone(), address.to_string(), Some(init_storage))?, + querier: MockQuerier::::new(chain, Some(querier_storage)), + }; + let options = InstanceOptions { + gas_limit: DEFAULT_GAS_LIMIT, + print_debug: DEFAULT_PRINT_DEBUG, + }; + let memory_limit = DEFAULT_MEMORY_LIMIT; + + // Then we create the instance + let mut instance = Instance::from_code(&code, backend, options, memory_limit)?; + + let gas_before = instance.get_gas_left(); + + // Then we call the function that we wanted to call + let result = execute_function(&mut instance, function)?; + + let gas_after = instance.get_gas_left(); + + // We return the code response + any storage change (or the whole local storage object), with serializing + let mut recycled_instance = instance.recycle().unwrap(); + + let wasm_result = WasmRunnerOutput { + storage: StorageChanges { + current_keys: recycled_instance.storage.get_all_storage()?, + removed_keys: recycled_instance.storage.removed_keys.into_iter().collect(), + }, + gas_used: gas_before - gas_after, + wasm: result, + }; + + Ok(wasm_result) + } + + pub fn after_execution_callback(&self, output: &WasmRunnerOutput) { + // We log the gas used + print!("Gas used {:?} for ", output.gas_used); + match output.wasm { + WasmOutput::Execute(_) => print!("execution"), + WasmOutput::Query(_) => print!("query"), + WasmOutput::Instantiate(_) => print!("instantiation"), + WasmOutput::Migrate(_) => print!("migration"), + WasmOutput::Sudo(_) => print!("sudo"), + WasmOutput::Reply(_) => print!("reply"), + } + println!(" on contract {:?}. ", self); + } +} + +impl Contract for WasmContract +where + ExecC: CustomMsg + DeserializeOwned, + QueryC: CustomQuery, +{ + fn execute( + &self, + deps: DepsMut, + mut env: Env, + info: MessageInfo, + msg: Vec, + ) -> AnyResult> { + env.block.chain_id = self.get_chain().chain_id.to_string(); + + // We start by building the dependencies we will pass through the wasm executer + let execute_args = InstanceArguments { + function: WasmFunction::Execute(ExecuteArgs { env, info, msg }), + init_storage: deps.storage.range(None, None, Order::Ascending).collect(), + querier_storage: get_querier_storage(&deps.querier)?, + }; + + let decoded_result = self.run_contract(execute_args)?; + + apply_storage_changes(deps.storage, &decoded_result); + self.after_execution_callback(&decoded_result); + + match decoded_result.wasm { + WasmOutput::Execute(x) => Ok(x), + _ => panic!("Wrong kind of answer from wasm container"), + } + } + + fn instantiate( + &self, + deps: DepsMut, + mut env: Env, + info: MessageInfo, + msg: Vec, + ) -> AnyResult> { + env.block.chain_id = self.get_chain().chain_id.to_string(); + // We start by building the dependencies we will pass through the wasm executer + let instantiate_arguments = InstanceArguments { + function: WasmFunction::Instantiate(InstantiateArgs { env, info, msg }), + init_storage: deps.storage.range(None, None, Order::Ascending).collect(), + querier_storage: get_querier_storage(&deps.querier)?, + }; + + let decoded_result = self.run_contract(instantiate_arguments)?; + + apply_storage_changes(deps.storage, &decoded_result); + self.after_execution_callback(&decoded_result); + + match decoded_result.wasm { + WasmOutput::Instantiate(x) => Ok(x), + _ => panic!("Wrong kind of answer from wasm container"), + } + } + + fn query(&self, deps: Deps, mut env: Env, msg: Vec) -> AnyResult { + env.block.chain_id = self.get_chain().chain_id.to_string(); + + // We start by building the dependencies we will pass through the wasm executer + let query_arguments = InstanceArguments { + function: WasmFunction::Query(QueryArgs { env, msg }), + init_storage: deps.storage.range(None, None, Order::Ascending).collect(), + querier_storage: get_querier_storage(&deps.querier)?, + }; + + let decoded_result: WasmRunnerOutput = self.run_contract(query_arguments)?; + + self.after_execution_callback(&decoded_result); + + match decoded_result.wasm { + WasmOutput::Query(x) => Ok(x), + _ => panic!("Wrong kind of answer from wasm container"), + } + } + + // this returns an error if the contract doesn't implement sudo + fn sudo( + &self, + deps: DepsMut, + mut env: Env, + msg: Vec, + ) -> AnyResult> { + env.block.chain_id = self.get_chain().chain_id.to_string(); + let sudo_args = InstanceArguments { + function: WasmFunction::Sudo(SudoArgs { env, msg }), + init_storage: deps.storage.range(None, None, Order::Ascending).collect(), + querier_storage: get_querier_storage(&deps.querier)?, + }; + + let decoded_result = self.run_contract(sudo_args)?; + + apply_storage_changes(deps.storage, &decoded_result); + self.after_execution_callback(&decoded_result); + + match decoded_result.wasm { + WasmOutput::Sudo(x) => Ok(x), + _ => panic!("Wrong kind of answer from wasm container"), + } + } + + // this returns an error if the contract doesn't implement reply + fn reply( + &self, + deps: DepsMut, + mut env: Env, + reply: Reply, + ) -> AnyResult> { + env.block.chain_id = self.get_chain().chain_id.to_string(); + let reply_args = InstanceArguments { + function: WasmFunction::Reply(ReplyArgs { env, reply }), + init_storage: deps.storage.range(None, None, Order::Ascending).collect(), + querier_storage: get_querier_storage(&deps.querier)?, + }; + + let decoded_result = self.run_contract(reply_args)?; + + apply_storage_changes(deps.storage, &decoded_result); + self.after_execution_callback(&decoded_result); + + match decoded_result.wasm { + WasmOutput::Reply(x) => Ok(x), + _ => panic!("Wrong kind of answer from wasm container"), + } + } + + // this returns an error if the contract doesn't implement migrate + fn migrate( + &self, + deps: DepsMut, + mut env: Env, + msg: Vec, + ) -> AnyResult> { + env.block.chain_id = self.get_chain().chain_id.to_string(); + let migrate_args = InstanceArguments { + function: WasmFunction::Migrate(MigrateArgs { env, msg }), + init_storage: deps.storage.range(None, None, Order::Ascending).collect(), + querier_storage: get_querier_storage(&deps.querier)?, + }; + + let decoded_result = self.run_contract(migrate_args)?; + + apply_storage_changes(deps.storage, &decoded_result); + self.after_execution_callback(&decoded_result); + + match decoded_result.wasm { + WasmOutput::Migrate(x) => Ok(x), + _ => panic!("Wrong kind of answer from wasm container"), + } + } +} + +pub fn execute_function< + A: BackendApi + 'static, + B: cosmwasm_vm::Storage + 'static, + C: Querier + 'static, + ExecC: CustomMsg + DeserializeOwned, +>( + instance: &mut Instance, + function: WasmFunction, +) -> AnyResult> { + match function { + WasmFunction::Execute(args) => { + let result = call_execute(instance, &args.env, &args.info, &args.msg)? + .into_result() + .map_err(StdError::generic_err)?; + Ok(WasmOutput::Execute(result)) + } + WasmFunction::Query(args) => { + let result = call_query(instance, &args.env, &args.msg)? + .into_result() + .map_err(StdError::generic_err)?; + Ok(WasmOutput::Query(result)) + } + WasmFunction::Instantiate(args) => { + let result = call_instantiate(instance, &args.env, &args.info, &args.msg)? + .into_result() + .map_err(StdError::generic_err)?; + Ok(WasmOutput::Instantiate(result)) + } + WasmFunction::Reply(args) => { + let result = call_reply(instance, &args.env, &args.reply)? + .into_result() + .map_err(StdError::generic_err)?; + Ok(WasmOutput::Reply(result)) + } + WasmFunction::Migrate(args) => { + let result = call_migrate(instance, &args.env, &args.msg)? + .into_result() + .map_err(StdError::generic_err)?; + Ok(WasmOutput::Migrate(result)) + } + WasmFunction::Sudo(args) => { + let result = call_sudo(instance, &args.env, &args.msg)? + .into_result() + .map_err(StdError::generic_err)?; + Ok(WasmOutput::Sudo(result)) + } + } +} diff --git a/src/wasm_emulation/input.rs b/src/wasm_emulation/input.rs new file mode 100644 index 00000000..b2f3ad8e --- /dev/null +++ b/src/wasm_emulation/input.rs @@ -0,0 +1,177 @@ +use std::collections::HashMap; + +use anyhow::Result as AnyResult; +use cw_orch_networks::ChainInfo; +use serde::{Deserialize, Serialize}; + +use cosmwasm_std::Addr; +use cosmwasm_std::Binary; +use cosmwasm_std::CustomQuery; +use cosmwasm_std::QuerierWrapper; +use cosmwasm_std::QueryRequest; +use cosmwasm_std::{Env, MessageInfo, Reply}; + +use cw_utils::NativeBalance; +use ibc_chain_registry::chain::Apis; +use ibc_chain_registry::chain::ChainData; +use ibc_relayer_types::core::ics24_host::identifier::ChainId; + +use crate::bank::BankKeeper; +use crate::prefixed_storage::get_full_contract_storage_namespace; +use crate::wasm::ContractData; + +use super::contract::WasmContract; +use super::query::AllQuerier; + +#[derive(Serialize, Deserialize, Clone)] +pub struct SerChainData { + pub chain_id: ChainId, + pub apis: Apis, + pub bech32_prefix: String, +} + +impl std::fmt::Debug for SerChainData { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + write!(f, "Chain {{ chain_id: {:?} }}", self.chain_id) + } +} + +impl From for SerChainData { + fn from(c: ChainData) -> SerChainData { + Self { + chain_id: c.chain_id, + apis: c.apis, + bech32_prefix: c.bech32_prefix, + } + } +} + +impl<'c> From> for SerChainData { + fn from(c: ChainInfo) -> SerChainData { + let chain_data: ChainData = c.into(); + chain_data.into() + } +} + +#[derive(Serialize, Deserialize, Debug, Clone, Default)] +pub struct WasmStorage { + pub contracts: HashMap, + pub codes: HashMap, + pub storage: Vec<(Vec, Vec)>, +} + +impl WasmStorage { + pub fn get_contract_storage(&self, contract_addr: &Addr) -> Vec<(Vec, Vec)> { + let namespace = + get_full_contract_storage_namespace(&Addr::unchecked(contract_addr)).to_vec(); + let namespace_len = namespace.len(); + let keys: Vec<(Vec, Vec)> = self + .storage + .iter() + // We filter only value in this namespace + .filter(|(k, _)| k.len() >= namespace_len && k[..namespace_len] == namespace) + .cloned() + // We remove the namespace prefix from the key + .map(|(k, value)| (k[namespace_len..].to_vec(), value)) + .collect(); + + keys + } +} + +#[derive(Serialize, Deserialize, Debug, Clone, Default)] +pub struct BankStorage { + pub storage: Vec<(Addr, NativeBalance)>, +} + +#[derive(Serialize, Clone, Deserialize, Default, Debug)] +pub struct QuerierStorage { + pub wasm: WasmStorage, + pub bank: ::Output, +} + +pub const STARGATE_ALL_WASM_QUERY_URL: &str = "/local.wasm.all"; +pub const STARGATE_ALL_BANK_QUERY_URL: &str = "/local.bank.all"; + +pub fn get_querier_storage( + q: &QuerierWrapper, +) -> AnyResult { + // We get the wasm storage for all wasm contract to make sure we dispatch everything (with the mock Querier) + let wasm = q.query(&QueryRequest::Stargate { + path: STARGATE_ALL_WASM_QUERY_URL.to_string(), + data: Binary(vec![]), + })?; + let bank = q.query(&QueryRequest::Stargate { + path: STARGATE_ALL_BANK_QUERY_URL.to_string(), + data: Binary(vec![]), + })?; + Ok(QuerierStorage { wasm, bank }) +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct InstanceArguments { + pub function: WasmFunction, + pub init_storage: Vec<(Vec, Vec)>, + pub querier_storage: QuerierStorage, +} + +#[derive(Serialize, Deserialize, Debug)] +pub enum WasmFunction { + Execute(ExecuteArgs), + Instantiate(InstantiateArgs), + Query(QueryArgs), + Sudo(SudoArgs), + Reply(ReplyArgs), + Migrate(MigrateArgs), +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct ExecuteArgs { + pub env: Env, + pub info: MessageInfo, + pub msg: Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct InstantiateArgs { + pub env: Env, + pub info: MessageInfo, + pub msg: Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct QueryArgs { + pub env: Env, + pub msg: Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct SudoArgs { + pub env: Env, + pub msg: Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct ReplyArgs { + pub env: Env, + pub reply: Reply, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct MigrateArgs { + pub env: Env, + pub msg: Vec, +} + +impl WasmFunction { + pub fn get_address(&self) -> Addr { + match self { + WasmFunction::Execute(ExecuteArgs { env, .. }) => env.contract.address.clone(), + WasmFunction::Instantiate(InstantiateArgs { env, .. }) => env.contract.address.clone(), + WasmFunction::Query(QueryArgs { env, .. }) => env.contract.address.clone(), + WasmFunction::Reply(ReplyArgs { env, .. }) => env.contract.address.clone(), + WasmFunction::Sudo(SudoArgs { env, .. }) => env.contract.address.clone(), + WasmFunction::Migrate(MigrateArgs { env, .. }) => env.contract.address.clone(), + } + } +} diff --git a/src/wasm_emulation/mod.rs b/src/wasm_emulation/mod.rs new file mode 100644 index 00000000..33379254 --- /dev/null +++ b/src/wasm_emulation/mod.rs @@ -0,0 +1,9 @@ +pub mod input; +pub mod output; +pub mod query; +pub mod storage; + +pub mod channel; +pub mod contract; + +pub mod api; diff --git a/src/wasm_emulation/output.rs b/src/wasm_emulation/output.rs new file mode 100644 index 00000000..7dd9596e --- /dev/null +++ b/src/wasm_emulation/output.rs @@ -0,0 +1,25 @@ +use cosmwasm_std::{Binary, Response}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug)] +pub enum WasmOutput { + Execute(Response), + Instantiate(Response), + Query(Binary), + Sudo(Response), + Reply(Response), + Migrate(Response), +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct StorageChanges { + pub current_keys: Vec<(Vec, Vec)>, + pub removed_keys: Vec>, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct WasmRunnerOutput { + pub wasm: WasmOutput, + pub storage: StorageChanges, + pub gas_used: u64, +} diff --git a/src/wasm_emulation/query/bank.rs b/src/wasm_emulation/query/bank.rs new file mode 100644 index 00000000..df23c5be --- /dev/null +++ b/src/wasm_emulation/query/bank.rs @@ -0,0 +1,151 @@ +use crate::wasm_emulation::input::SerChainData; +use crate::wasm_emulation::query::gas::{GAS_COST_ALL_BALANCE_QUERY, GAS_COST_BALANCE_QUERY}; +use crate::wasm_emulation::query::mock_querier::QueryResultWithGas; +use cosmwasm_std::Addr; +use cosmwasm_vm::GasInfo; +use std::str::FromStr; + +use cw_orch_daemon::queriers::DaemonQuerier; +use cw_utils::NativeBalance; + +use cw_orch_daemon::queriers::Bank; + +use cosmwasm_std::Binary; +use cosmwasm_std::Coin; +use std::collections::HashMap; + +use cosmwasm_std::Uint128; +use cosmwasm_std::{AllBalanceResponse, BalanceResponse, BankQuery}; + +use cosmwasm_std::to_binary; +use cosmwasm_std::{ContractResult, SystemResult}; + +use crate::wasm_emulation::channel::get_channel; + +#[derive(Clone)] +pub struct BankQuerier { + #[allow(dead_code)] + /// HashMap + supplies: HashMap, + /// HashMap + balances: HashMap>, + chain: SerChainData, +} + +impl BankQuerier { + pub fn new(chain: impl Into, init: Option>) -> Self { + let chain = chain.into(); + let balances: HashMap<_, _> = init + .unwrap_or(vec![]) + .iter() + .map(|(s, c)| (s.to_string(), c.clone().into_vec())) + .collect(); + + BankQuerier { + supplies: Self::calculate_supplies(&balances), + balances, + chain, + } + } + + pub fn update_balance( + &mut self, + addr: impl Into, + balance: Vec, + ) -> Option> { + let result = self.balances.insert(addr.into(), balance); + self.supplies = Self::calculate_supplies(&self.balances); + + result + } + + fn calculate_supplies(balances: &HashMap>) -> HashMap { + let mut supplies = HashMap::new(); + + let all_coins = balances.iter().flat_map(|(_, coins)| coins); + + for coin in all_coins { + *supplies + .entry(coin.denom.clone()) + .or_insert_with(Uint128::zero) += coin.amount; + } + + supplies + } + + pub fn query(&self, request: &BankQuery) -> QueryResultWithGas { + let contract_result: ContractResult = match request { + BankQuery::Balance { address, denom } => { + // proper error on not found, serialize result on found + let mut amount = self + .balances + .get(address) + .and_then(|v| v.iter().find(|c| &c.denom == denom).map(|c| c.amount)); + + // If the amount is not available, we query it from the distant chain + if amount.is_none() { + let (rt, channel) = get_channel(self.chain.clone()).unwrap(); + let querier = Bank::new(channel); + + let query_result = rt + .block_on(querier.balance(address, Some(denom.clone()))) + .map(|result| Uint128::from_str(&result[0].amount).unwrap()); + + if let Ok(distant_amount) = query_result { + amount = Some(distant_amount) + } + } + + let bank_res = BalanceResponse { + amount: Coin { + amount: amount.unwrap(), + denom: denom.to_string(), + }, + }; + to_binary(&bank_res).into() + } + BankQuery::AllBalances { address } => { + // proper error on not found, serialize result on found + let mut amount = self.balances.get(address).cloned(); + + // We query only if the bank balance doesn't exist + if amount.is_none() { + let (rt, channel) = get_channel(self.chain.clone()).unwrap(); + let querier = Bank::new(channel); + let query_result: Result, _> = + rt.block_on(querier.balance(address, None)).map(|result| { + result + .into_iter() + .map(|c| Coin { + amount: Uint128::from_str(&c.amount).unwrap(), + denom: c.denom, + }) + .collect() + }); + if let Ok(distant_amount) = query_result { + amount = Some(distant_amount) + } + } + + let bank_res = AllBalanceResponse { + amount: amount.unwrap(), + }; + to_binary(&bank_res).into() + } + &_ => panic!("Not implemented {:?}", request), + }; + + // We handle the gas_info + let gas_info = match request { + BankQuery::Balance { .. } => GAS_COST_BALANCE_QUERY, + BankQuery::AllBalances { .. } => GAS_COST_ALL_BALANCE_QUERY, + &_ => panic!("Not implemented {:?}", request), + }; + + // system result is always ok in the mock implementation + ( + SystemResult::Ok(contract_result), + GasInfo::with_externally_used(gas_info), + ) + } +} diff --git a/src/wasm_emulation/query/gas.rs b/src/wasm_emulation/query/gas.rs new file mode 100644 index 00000000..5f1d6e9f --- /dev/null +++ b/src/wasm_emulation/query/gas.rs @@ -0,0 +1,21 @@ +// Bank +pub const GAS_COST_BALANCE_QUERY: u64 = 1000; +pub const GAS_COST_ALL_BALANCE_QUERY: u64 = 10000; + +// Staking +pub const GAS_COST_BONDED_DENOM: u64 = 100; +pub const GAS_COST_ALL_VALIDATORS: u64 = 10000; +pub const GAS_COST_VALIDATOR: u64 = 1000; +pub const GAS_COST_ALL_DELEGATIONS: u64 = 10000; +pub const GAS_COST_DELEGATIONS: u64 = 1000; + +// Wasm +pub const GAS_COST_CONTRACT_INFO: u64 = 1000; +pub const GAS_COST_RAW_COSMWASM_QUERY: u64 = 10000; + +// ERROR +pub const GAS_COST_QUERY_ERROR: u64 = 1000; + +// API (from cosmwasm_vm directly) +pub const GAS_COST_HUMANIZE: u64 = 44; +pub const GAS_COST_CANONICALIZE: u64 = 55; diff --git a/src/wasm_emulation/query/mock_querier.rs b/src/wasm_emulation/query/mock_querier.rs new file mode 100644 index 00000000..87b8e190 --- /dev/null +++ b/src/wasm_emulation/query/mock_querier.rs @@ -0,0 +1,152 @@ +use crate::wasm_emulation::input::SerChainData; +use crate::wasm_emulation::query::bank::BankQuerier; +use crate::wasm_emulation::query::staking::StakingQuerier; +use crate::wasm_emulation::query::wasm::WasmQuerier; + +use cosmwasm_vm::BackendResult; +use cosmwasm_vm::GasInfo; + +use serde::de::DeserializeOwned; + +use cosmwasm_std::Binary; +use cosmwasm_std::Coin; + +use cosmwasm_std::SystemError; + +use cosmwasm_std::from_slice; +use cosmwasm_std::{ContractResult, Empty, SystemResult}; +use cosmwasm_std::{CustomQuery, QueryRequest}; +use cosmwasm_std::{FullDelegation, Validator}; + +use cosmwasm_std::Attribute; +use cosmwasm_std::QuerierResult; + +use crate::wasm_emulation::input::QuerierStorage; + +use super::gas::GAS_COST_QUERY_ERROR; + +pub type QueryResultWithGas = (QuerierResult, GasInfo); + +/// The same type as cosmwasm-std's QuerierResult, but easier to reuse in +/// cosmwasm-vm. It might diverge from QuerierResult at some point. +pub type MockQuerierCustomHandlerResult = SystemResult>; + +/// MockQuerier holds an immutable table of bank balances +/// and configurable handlers for Wasm queries and custom queries. +pub struct MockQuerier { + bank: BankQuerier, + + staking: StakingQuerier, + wasm: WasmQuerier, + /// A handler to handle custom queries. This is set to a dummy handler that + /// always errors by default. Update it via `with_custom_handler`. + /// + /// Use box to avoid the need of another generic type + custom_handler: Box Fn(&'a C) -> QueryResultWithGas>, +} + +impl MockQuerier { + pub fn new(chain: impl Into, storage: Option) -> Self { + let chain = chain.into(); + MockQuerier { + bank: BankQuerier::new( + chain.clone(), + storage.as_ref().map(|storage| storage.bank.storage.clone()), + ), + + staking: StakingQuerier::default(), + wasm: WasmQuerier::new(chain, storage), + // strange argument notation suggested as a workaround here: https://github.com/rust-lang/rust/issues/41078#issuecomment-294296365 + custom_handler: Box::from(|_: &_| -> QueryResultWithGas { + ( + SystemResult::Err(SystemError::UnsupportedRequest { + kind: "custom".to_string(), + }), + GasInfo::free(), + ) + }), + } + } + + // set a new balance for the given address and return the old balance + pub fn update_balance( + &mut self, + addr: impl Into, + balance: Vec, + ) -> Option> { + self.bank.update_balance(addr, balance) + } + + pub fn update_staking( + &mut self, + denom: &str, + validators: &[Validator], + delegations: &[FullDelegation], + ) { + self.staking = StakingQuerier::new(denom, validators, delegations); + } + + pub fn with_custom_handler(mut self, handler: CH) -> Self + where + CH: Fn(&C) -> QueryResultWithGas, + { + self.custom_handler = Box::from(handler); + self + } +} + +impl cosmwasm_vm::Querier for MockQuerier { + fn query_raw( + &self, + bin_request: &[u8], + _gas_limit: u64, + ) -> BackendResult>> { + let request: QueryRequest = match from_slice(bin_request) { + Ok(v) => v, + Err(e) => { + return ( + Ok(SystemResult::Err(SystemError::InvalidRequest { + error: format!("Parsing query request: {}", e), + request: bin_request.into(), + })), + GasInfo::with_externally_used(GAS_COST_QUERY_ERROR), + ) + } + }; + let result = self.handle_query(&request); + + (Ok(result.0), result.1) + } +} + +impl MockQuerier { + pub fn handle_query(&self, request: &QueryRequest) -> QueryResultWithGas { + match &request { + QueryRequest::Bank(bank_query) => self.bank.query(bank_query), + QueryRequest::Custom(custom_query) => (*self.custom_handler)(custom_query), + + QueryRequest::Staking(staking_query) => self.staking.query(staking_query), + QueryRequest::Wasm(msg) => self.wasm.query(msg), + QueryRequest::Stargate { .. } => ( + SystemResult::Err(SystemError::UnsupportedRequest { + kind: "Stargate".to_string(), + }), + GasInfo::with_externally_used(GAS_COST_QUERY_ERROR), + ), + &_ => panic!("Query Type Not implemented"), + } + } +} + +pub fn digit_sum(input: &[u8]) -> usize { + input.iter().fold(0, |sum, val| sum + (*val as usize)) +} + +/// Only for test code. This bypasses assertions in new, allowing us to create _* +/// Attributes to simulate responses from the blockchain +pub fn mock_wasmd_attr(key: impl Into, value: impl Into) -> Attribute { + Attribute { + key: key.into(), + value: value.into(), + } +} diff --git a/src/wasm_emulation/query/mod.rs b/src/wasm_emulation/query/mod.rs new file mode 100644 index 00000000..6bb3f1fe --- /dev/null +++ b/src/wasm_emulation/query/mod.rs @@ -0,0 +1,17 @@ +pub mod bank; +pub mod mock_querier; +pub mod staking; +pub mod wasm; +use cosmwasm_std::Storage; +use serde::de::DeserializeOwned; + +pub use mock_querier::MockQuerier; +pub mod gas; + +use anyhow::Result as AnyResult; +use serde::Serialize; + +pub trait AllQuerier { + type Output: Serialize + Clone + DeserializeOwned + Default; + fn query_all(&self, storage: &dyn Storage) -> AnyResult; +} diff --git a/src/wasm_emulation/query/staking.rs b/src/wasm_emulation/query/staking.rs new file mode 100644 index 00000000..58acabe4 --- /dev/null +++ b/src/wasm_emulation/query/staking.rs @@ -0,0 +1,100 @@ +use crate::wasm_emulation::query::gas::{ + GAS_COST_ALL_DELEGATIONS, GAS_COST_ALL_VALIDATORS, GAS_COST_BONDED_DENOM, GAS_COST_DELEGATIONS, + GAS_COST_VALIDATOR, +}; +use crate::wasm_emulation::query::mock_querier::QueryResultWithGas; +use cosmwasm_std::Binary; +use cosmwasm_vm::GasInfo; + +use cosmwasm_std::to_binary; +use cosmwasm_std::{ + AllDelegationsResponse, AllValidatorsResponse, BondedDenomResponse, DelegationResponse, + FullDelegation, StakingQuery, Validator, ValidatorResponse, +}; +use cosmwasm_std::{ContractResult, SystemResult}; + +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone, Default)] +pub struct StakingQuerier { + denom: String, + validators: Vec, + delegations: Vec, +} + +impl StakingQuerier { + pub fn new(denom: &str, validators: &[Validator], delegations: &[FullDelegation]) -> Self { + StakingQuerier { + denom: denom.to_string(), + validators: validators.to_vec(), + delegations: delegations.to_vec(), + } + } + + pub fn query(&self, request: &StakingQuery) -> QueryResultWithGas { + let contract_result: ContractResult = match request { + StakingQuery::BondedDenom {} => { + let res = BondedDenomResponse { + denom: self.denom.clone(), + }; + to_binary(&res).into() + } + StakingQuery::AllValidators {} => { + let res = AllValidatorsResponse { + validators: self.validators.clone(), + }; + to_binary(&res).into() + } + StakingQuery::Validator { address } => { + let validator: Option = self + .validators + .iter() + .find(|validator| validator.address == *address) + .cloned(); + let res = ValidatorResponse { validator }; + to_binary(&res).into() + } + StakingQuery::AllDelegations { delegator } => { + let delegations: Vec<_> = self + .delegations + .iter() + .filter(|d| d.delegator.as_str() == delegator) + .cloned() + .map(|d| d.into()) + .collect(); + let res = AllDelegationsResponse { delegations }; + to_binary(&res).into() + } + StakingQuery::Delegation { + delegator, + validator, + } => { + let delegation = self + .delegations + .iter() + .find(|d| d.delegator.as_str() == delegator && d.validator == *validator); + let res = DelegationResponse { + delegation: delegation.cloned(), + }; + to_binary(&res).into() + } + &_ => panic!("Not implemented {:?}", request), + }; + + // We handle the gas_info + let gas_info = match request { + StakingQuery::BondedDenom { .. } => GAS_COST_BONDED_DENOM, + StakingQuery::AllValidators { .. } => GAS_COST_ALL_VALIDATORS, + StakingQuery::Validator { .. } => GAS_COST_VALIDATOR, + StakingQuery::AllDelegations { .. } => GAS_COST_ALL_DELEGATIONS, + StakingQuery::Delegation { .. } => GAS_COST_DELEGATIONS, + &_ => panic!("Not implemented {:?}", request), + }; + + // system result is always ok in the mock implementation + ( + SystemResult::Ok(contract_result), + GasInfo::with_externally_used(gas_info), + ) + } +} diff --git a/src/wasm_emulation/query/wasm.rs b/src/wasm_emulation/query/wasm.rs new file mode 100644 index 00000000..783f1a34 --- /dev/null +++ b/src/wasm_emulation/query/wasm.rs @@ -0,0 +1,146 @@ +use crate::prefixed_storage::get_full_contract_storage_namespace; +use crate::wasm_emulation::query::gas::{GAS_COST_CONTRACT_INFO, GAS_COST_RAW_COSMWASM_QUERY}; +use crate::wasm_emulation::query::mock_querier::QueryResultWithGas; + +use crate::wasm_emulation::contract::WasmContract; +use crate::wasm_emulation::input::QuerierStorage; +use crate::wasm_emulation::input::SerChainData; +use crate::wasm_emulation::input::WasmFunction; +use crate::wasm_emulation::output::WasmOutput; +use crate::wasm_emulation::output::WasmRunnerOutput; +use cosmwasm_std::testing::mock_env; +use cosmwasm_vm::GasInfo; +use cw_orch_daemon::queriers::DaemonQuerier; + +use cosmwasm_std::{to_binary, Addr, ContractInfoResponse, SystemResult}; +use cosmwasm_std::{ContractResult, Empty}; +use cw_orch_daemon::queriers::CosmWasm; + +use cosmwasm_std::WasmQuery; + +use crate::wasm_emulation::channel::get_channel; +use crate::WasmKeeper; + +use crate::wasm_emulation::input::{InstanceArguments, QueryArgs}; + +pub struct WasmQuerier { + chain: SerChainData, + current_storage: QuerierStorage, +} + +impl WasmQuerier { + pub fn new(chain: impl Into, storage: Option) -> Self { + let chain = chain.into(); + Self { + chain, + current_storage: storage.unwrap_or(Default::default()), + } + } + + pub fn query(&self, request: &WasmQuery) -> QueryResultWithGas { + match request { + WasmQuery::ContractInfo { contract_addr } => { + let addr = Addr::unchecked(contract_addr); + let data = if let Some(local_contract) = + self.current_storage.wasm.contracts.get(contract_addr) + { + local_contract.clone() + } else { + WasmKeeper::::load_distant_contract(self.chain.clone(), &addr) + .unwrap() + }; + let mut response = ContractInfoResponse::default(); + response.code_id = data.code_id.try_into().unwrap(); + response.creator = data.creator.to_string(); + response.admin = data.admin.map(|a| a.to_string()); + ( + SystemResult::Ok(to_binary(&response).into()), + GasInfo::with_externally_used(GAS_COST_CONTRACT_INFO), + ) + } + WasmQuery::Raw { contract_addr, key } => { + // We first try to load that information locally + let mut total_key = + get_full_contract_storage_namespace(&Addr::unchecked(contract_addr)).to_vec(); + total_key.extend_from_slice(key); + + let value: Vec = if let Some(value) = self + .current_storage + .wasm + .storage + .iter() + .find(|e| e.0 == total_key) + { + value.1.clone() + } else { + let (rt, channel) = get_channel(self.chain.clone()).unwrap(); + let wasm_querier = CosmWasm::new(channel); + let query_result = rt + .block_on( + wasm_querier + .contract_raw_state(contract_addr.to_string(), key.to_vec()), + ) + .map(|query_result| query_result.data); + query_result.unwrap() + }; + + ( + SystemResult::Ok(ContractResult::Ok(value.into())), + GasInfo::with_externally_used(GAS_COST_RAW_COSMWASM_QUERY), + ) + } + WasmQuery::Smart { contract_addr, msg } => { + let addr = Addr::unchecked(contract_addr); + // If the contract is already defined in our storage, we load it from there + let contract = if let Some(local_contract) = + self.current_storage.wasm.contracts.get(contract_addr) + { + if let Some(code_info) = self + .current_storage + .wasm + .codes + .get(&(local_contract.code_id as usize)) + { + // We execute the query + code_info.clone() + } else { + WasmContract::new_distant_code_id( + local_contract.code_id.try_into().unwrap(), + self.chain.clone(), + ) + } + } else { + WasmContract::new_distant_contract( + contract_addr.to_string(), + self.chain.clone(), + ) + }; + + let mut env = mock_env(); + env.contract.address = addr.clone(); + // Here we specify empty because we only car about the query result + let result: WasmRunnerOutput = contract + .run_contract(InstanceArguments { + function: WasmFunction::Query(QueryArgs { + env, + msg: msg.to_vec(), + }), + querier_storage: self.current_storage.clone(), + init_storage: self.current_storage.wasm.get_contract_storage(&addr), + }) + .unwrap(); + + let bin = match result.wasm { + WasmOutput::Query(bin) => bin, + _ => panic!("Unexpected contract response, not possible"), + }; + + ( + SystemResult::Ok(ContractResult::Ok(bin)), + GasInfo::with_externally_used(result.gas_used), + ) + } + _ => unimplemented!(), + } + } +} diff --git a/src/wasm_emulation/storage/analyzer.rs b/src/wasm_emulation/storage/analyzer.rs new file mode 100644 index 00000000..25c256f2 --- /dev/null +++ b/src/wasm_emulation/storage/analyzer.rs @@ -0,0 +1,191 @@ +use crate::prefixed_storage::decode_length; +use crate::prefixed_storage::to_length_prefixed; +use crate::prefixed_storage::CONTRACT_STORAGE_PREFIX; +use crate::wasm_emulation::channel::get_channel; +use crate::wasm_emulation::input::get_querier_storage; +use cosmwasm_std::Addr; +use cosmwasm_std::Coin; +use cw_orch_daemon::queriers::CosmWasm; +use cw_orch_daemon::queriers::DaemonQuerier; +use ibc_chain_registry::chain::ChainData; +use rustc_serialize::json::Json; +use serde::__private::from_utf8_lossy; +use treediff::diff; +use treediff::tools::Recorder; + +use crate::wasm::NAMESPACE_WASM; + +use crate::{wasm_emulation::input::QuerierStorage, App}; + +use anyhow::Result as AnyResult; + +pub struct StorageAnalyzer { + pub storage: QuerierStorage, + pub chain: ChainData, +} + +impl StorageAnalyzer { + pub fn new(app: &App, c: impl Into) -> AnyResult { + Ok(Self { + storage: get_querier_storage(&app.wrap())?, + chain: c.into(), + }) + } + + pub fn get_contract_storage( + &self, + contract_addr: impl Into, + ) -> Vec<(Vec, Vec)> { + self.storage + .wasm + .get_contract_storage(&Addr::unchecked(contract_addr.into())) + } + + pub fn readable_storage(&self, contract_addr: impl Into) -> Vec<(String, String)> { + self.storage + .wasm + .get_contract_storage(&Addr::unchecked(contract_addr.into())) + .into_iter() + .map(|(key, value)| { + ( + from_utf8_lossy(&key).to_string(), + from_utf8_lossy(&value).to_string(), + ) + }) + .collect() + } + + /// We leverage the data structure we introduced for contracts to get their storage easily + pub fn all_contract_storage(&self) -> Vec<(String, Vec, Vec)> { + // In all wasm storage keys, we look for the `contract_addr/(...)/` pattern in the key + self.storage + .wasm + .storage + .iter() + .filter(|(key, _)| { + // The key must contain the NAMESPACE_WASM prefix + let prefix = to_length_prefixed(NAMESPACE_WASM); + key.len() >= prefix.len() && key[..prefix.len()] == prefix + }) + .filter_map(|(key, value)| { + // Now we need to get the contract addr from the namespace + + let prefix_len = to_length_prefixed(NAMESPACE_WASM).len(); + let resulting_key = &key[prefix_len..]; + let addr_len: usize = decode_length([resulting_key[0], resulting_key[1]]) + .try_into() + .unwrap(); + let contract_addr_addr = + from_utf8_lossy(&resulting_key[2..(addr_len + 2)]).to_string(); + + let split: Vec<_> = contract_addr_addr.split('/').collect(); + if split.len() != 2 || format!("{}/", split[0]) != CONTRACT_STORAGE_PREFIX { + return None; + } + + Some(( + split[1].to_string(), + resulting_key[addr_len + 2..].to_vec(), + value.clone(), + )) + }) + .collect() + } + + pub fn all_readable_contract_storage(&self) -> Vec<(String, String, String)> { + self.all_contract_storage() + .into_iter() + .map(|(contract, key, value)| { + ( + contract, + from_utf8_lossy(&key).to_string(), + from_utf8_lossy(&value).to_string(), + ) + }) + .collect() + } + + pub fn compare_all_readable_contract_storage(&self) { + let (rt, channel) = get_channel(self.chain.clone()).unwrap(); + let wasm_querier = CosmWasm::new(channel); + self.all_contract_storage() + .into_iter() + .for_each(|(contract_addr, key, value)| { + // We look for the data at that key on the contract + let distant_data = rt + .block_on(wasm_querier.contract_raw_state(contract_addr.clone(), key.clone())); + + if let Ok(data) = distant_data { + let local_json: Json = + if let Ok(v) = from_utf8_lossy(&value).to_string().parse() { + v + } else { + log::info!( + "Storage at {}, and key {}, was : {:x?}, now {:x?}", + contract_addr, + from_utf8_lossy(&key).to_string(), + data.data, + value + ); + return; + }; + let distant_json: Json = + if let Ok(v) = from_utf8_lossy(&data.data).to_string().parse() { + v + } else { + log::info!( + "Storage at {}, and key {}, was : {:x?}, now {:x?}", + contract_addr, + from_utf8_lossy(&key).to_string(), + data.data, + value + ); + return; + }; + + let mut d = Recorder::default(); + diff(&distant_json, &local_json, &mut d); + + let changes: Vec<_> = d + .calls + .iter() + .filter(|change| { + !matches!(change, treediff::tools::ChangeType::Unchanged(..)) + }) + .collect(); + + log::info!( + "Storage at {}, and key {}, changed like so : {:?}", + contract_addr, + from_utf8_lossy(&key).to_string(), + changes + ); + } else if let Ok(v) = from_utf8_lossy(&value).to_string().parse::() { + log::info!( + "Storage at {}, and key {}, is new : {}", + contract_addr, + from_utf8_lossy(&key).to_string(), + v + ); + } else { + log::info!( + "Storage at {}, and key {}, is new : {:?}", + contract_addr, + from_utf8_lossy(&key).to_string(), + value + ); + } + }); + } + + pub fn get_balance(&self, addr: impl Into) -> Vec { + let addr: String = addr.into(); + self.storage + .bank + .storage + .iter() + .find(|(a, _)| a.as_str() == addr) + .map(|(_, b)| b.0.clone()) + .unwrap_or(vec![]) + } +} diff --git a/src/wasm_emulation/storage/dual_storage.rs b/src/wasm_emulation/storage/dual_storage.rs new file mode 100644 index 00000000..15cbf5e9 --- /dev/null +++ b/src/wasm_emulation/storage/dual_storage.rs @@ -0,0 +1,268 @@ +use crate::wasm_emulation::channel::get_channel; +use crate::wasm_emulation::input::SerChainData; +use crate::wasm_emulation::storage::mock_storage::{GAS_COST_LAST_ITERATION, GAS_COST_RANGE}; + +use super::mock_storage::MockStorage; +use cosmrs::proto::cosmos::base::query::v1beta1::PageRequest; +use cosmrs::proto::cosmwasm::wasm::v1::Model; +use cosmwasm_std::Order; +use cosmwasm_std::Record; +use cosmwasm_vm::BackendError; +use cosmwasm_vm::BackendResult; +use cosmwasm_vm::GasInfo; +use cosmwasm_vm::Storage; +use cw_orch_daemon::queriers::DaemonQuerier; +use num_bigint::{BigInt, Sign}; +use std::collections::HashMap; +use std::iter; + +use cw_orch_daemon::queriers::CosmWasm; + +fn get_key_bigint(mut key1: Vec, mut key2: Vec) -> (BigInt, BigInt) { + if key1.len() >= key2.len() { + key2.extend(iter::repeat(0).take(key1.len() - key2.len())) + } else { + key1.extend(iter::repeat(0).take(key2.len() - key1.len())) + } + + ( + BigInt::from_bytes_be(Sign::Plus, &key1), + BigInt::from_bytes_be(Sign::Plus, &key2), + ) +} + +fn gte(key1: Vec, key2: Vec) -> bool { + let ints = get_key_bigint(key1, key2); + + ints.0 >= ints.1 +} + +fn _gt(key1: Vec, key2: Vec) -> bool { + let ints = get_key_bigint(key1, key2); + ints.0 > ints.1 +} + +use std::collections::HashSet; + +use anyhow::Result as AnyResult; +const DISTANT_LIMIT: u64 = 5u64; + +#[derive(Default, Debug)] +struct DistantIter { + data: Vec, + position: usize, + key: Option>, // if set to None, there is no more keys to investigate in the distant container + start: Option>, + end: Option>, + reverse: bool, +} + +/// Iterator to get multiple keys +#[derive(Default, Debug)] +struct Iter { + distant_iter: DistantIter, + local_iter: u32, +} + +pub struct DualStorage { + pub local_storage: MockStorage, + pub removed_keys: HashSet>, + pub chain: SerChainData, + pub contract_addr: String, + iterators: HashMap, +} + +impl DualStorage { + pub fn new( + chain: impl Into, + contract_addr: String, + init: Option, Vec)>>, + ) -> AnyResult { + // We create an instance from a code_id, an address, and we run the code in it + + let mut local_storage = MockStorage::default(); + for (key, value) in init.unwrap() { + local_storage.set(&key, &value).0?; + } + + Ok(Self { + local_storage, + chain: chain.into(), + removed_keys: HashSet::default(), + contract_addr, + iterators: HashMap::new(), + }) + } + + pub fn get_all_storage(&mut self) -> AnyResult, Vec)>> { + let iterator_id = self.local_storage.scan(None, None, Order::Ascending).0?; + let all_records = self.local_storage.all(iterator_id); + + Ok(all_records.0?) + } +} + +impl Storage for DualStorage { + fn get(&self, key: &[u8]) -> BackendResult>> { + // First we try to get the value locally + let (mut value, gas_info) = self.local_storage.get(key); + // If it's not available, we query it online if it was not removed locally + if !self.removed_keys.contains(key) && value.as_ref().unwrap().is_none() { + let (rt, channel) = get_channel(self.chain.clone()).unwrap(); + let wasm_querier = CosmWasm::new(channel); + + let distant_result = rt.block_on( + wasm_querier.contract_raw_state(self.contract_addr.clone(), key.to_vec()), + ); + + if let Ok(result) = distant_result { + if !result.data.is_empty() { + value = Ok(Some(result.data)) + } + } + } + (value, gas_info) + } + + fn scan( + &mut self, + start: Option<&[u8]>, + end: Option<&[u8]>, + order: Order, + ) -> BackendResult { + let gas_info = GasInfo::with_externally_used(GAS_COST_RANGE); + let iterator_id = self.local_storage.scan(start, end, order).0.unwrap(); + + let order_i32: i32 = order.try_into().unwrap(); + let descending_order: i32 = Order::Descending.try_into().unwrap(); + + let querier_start = if order_i32 == descending_order { + end.map(|s| s.to_vec()).unwrap_or(vec![]) + } else { + start.map(|s| s.to_vec()).unwrap_or(vec![]) + }; + + let iter = Iter { + local_iter: iterator_id, + distant_iter: DistantIter { + data: vec![], + position: 0, + key: Some(querier_start), + end: end.map(|e| e.to_vec()), + start: start.map(|e| e.to_vec()), + reverse: order_i32 == descending_order, + }, + }; + + let last_id: u32 = self + .iterators + .len() + .try_into() + .expect("Found more iterator IDs than supported"); + let new_id = last_id + 1; + self.iterators.insert(new_id, iter); + + (Ok(new_id), gas_info) + } + + fn next(&mut self, iterator_id: u32) -> BackendResult> { + // In order to get the next element on the iterator, we need to compose with the two iterators we have + let iterator = match self.iterators.get_mut(&iterator_id) { + Some(i) => i, + None => { + return ( + Err(BackendError::iterator_does_not_exist(iterator_id)), + GasInfo::free(), + ) + } + }; + + // 1. We verify that there is enough elements in the distant iterator + if iterator.distant_iter.position == iterator.distant_iter.data.len() + && iterator.distant_iter.key.is_some() + { + let (rt, channel) = get_channel(self.chain.clone()).unwrap(); + let wasm_querier = CosmWasm::new(channel); + let new_keys = rt + .block_on(wasm_querier.all_contract_state( + self.contract_addr.clone(), + Some(PageRequest { + key: iterator.distant_iter.key.clone().unwrap(), + offset: 0, + limit: DISTANT_LIMIT, + count_total: false, + reverse: iterator.distant_iter.reverse, + }), + )) + .unwrap(); + + iterator.distant_iter.data.extend(new_keys.models); + iterator.distant_iter.key = Some(new_keys.pagination.unwrap().next_key); + } + + // 2. We find the first key in order between distant and local storage + let next_local = self.local_storage.peak(iterator.local_iter).unwrap(); + let next_distant = iterator + .distant_iter + .data + .get(iterator.distant_iter.position); + + // We select the distant storage only if the keys are valid (inside the start, end range) + let is_valid_distant_key = next_distant.is_some() + && (iterator.distant_iter.end.is_none() || // If there is end no bound + iterator.distant_iter.reverse || // if the iterator is reversed, + !gte(next_distant.unwrap().key.clone(), iterator.distant_iter.end.clone().unwrap())) + && (iterator.distant_iter.start.is_none() + || !iterator.distant_iter.reverse + || gte( + next_distant.unwrap().key.clone(), + iterator.distant_iter.start.clone().unwrap(), + )); + + let key_value = if let Some(local) = next_local { + if is_valid_distant_key { + let distant = next_distant.unwrap(); + // We compare the two keys with the order and return the higher key + let key_local = BigInt::from_bytes_be(Sign::Plus, &local.0); + let key_distant = BigInt::from_bytes_be(Sign::Plus, &distant.key); + if (key_local < key_distant) == iterator.distant_iter.reverse { + iterator.distant_iter.position += 1; + Some((distant.key.clone(), distant.value.clone())) + } else { + self.local_storage.next(iterator.local_iter).0.unwrap() + } + } else { + self.local_storage.next(iterator.local_iter).0.unwrap() + } + } else if is_valid_distant_key { + let distant = next_distant.unwrap(); + iterator.distant_iter.position += 1; + Some((distant.key.clone(), distant.value.clone())) + } else { + None + }; + + // We add the gas cost + if let Some((key, value)) = key_value { + ( + Ok(Some((key.clone(), value.clone()))), + GasInfo::with_externally_used((key.len() + value.len()) as u64), + ) + } else { + ( + Ok(None), + GasInfo::with_externally_used(GAS_COST_LAST_ITERATION), + ) + } + } + + fn set(&mut self, key: &[u8], value: &[u8]) -> BackendResult<()> { + self.removed_keys.remove(key); // It's not locally removed anymore, because we set it locally + self.local_storage.set(key, value) + } + + fn remove(&mut self, key: &[u8]) -> BackendResult<()> { + self.removed_keys.insert(key.to_vec()); // We indicate locally if it's removed. So that we can remove keys and not query them on the distant chain + self.local_storage.remove(key) + } +} diff --git a/src/wasm_emulation/storage/mock_storage.rs b/src/wasm_emulation/storage/mock_storage.rs new file mode 100644 index 00000000..b79c3b5b --- /dev/null +++ b/src/wasm_emulation/storage/mock_storage.rs @@ -0,0 +1,347 @@ +use std::collections::BTreeMap; +use std::collections::HashMap; +use std::ops::{Bound, RangeBounds}; + +use cosmwasm_std::{Order, Record}; + +use cosmwasm_vm::BackendError; +use cosmwasm_vm::{BackendResult, GasInfo, Storage}; + +pub const GAS_COST_LAST_ITERATION: u64 = 37; + +pub const GAS_COST_RANGE: u64 = 11; + +// We needed to add the peak function on the cosmwasm-vm code +// This is used for making sure we have the right order between distant and local storage + +#[derive(Default, Debug)] +struct Iter { + data: Vec, + position: usize, +} + +#[derive(Default, Debug)] +pub struct MockStorage { + data: BTreeMap, Vec>, + iterators: HashMap, +} + +impl MockStorage { + pub fn new() -> Self { + MockStorage::default() + } + + pub fn all(&mut self, iterator_id: u32) -> BackendResult> { + let mut out: Vec = Vec::new(); + let mut total = GasInfo::free(); + loop { + let (result, info) = self.next(iterator_id); + total += info; + match result { + Err(err) => return (Err(err), total), + Ok(ok) => { + if let Some(v) = ok { + out.push(v); + } else { + break; + } + } + } + } + (Ok(out), total) + } + + pub fn peak(&mut self, iterator_id: u32) -> Result, BackendError> { + let iterator = match self.iterators.get(&iterator_id) { + Some(i) => i, + None => return Err(BackendError::iterator_does_not_exist(iterator_id)), + }; + + let value: Option = if iterator.data.len() > iterator.position { + let item = iterator.data[iterator.position].clone(); + Some(item) + } else { + None + }; + + Ok(value) + } +} + +impl Storage for MockStorage { + fn get(&self, key: &[u8]) -> BackendResult>> { + let gas_info = GasInfo::with_externally_used(key.len() as u64); + (Ok(self.data.get(key).cloned()), gas_info) + } + + fn scan( + &mut self, + start: Option<&[u8]>, + end: Option<&[u8]>, + order: Order, + ) -> BackendResult { + let gas_info = GasInfo::with_externally_used(GAS_COST_RANGE); + let bounds = range_bounds(start, end); + + let values: Vec = match (bounds.start_bound(), bounds.end_bound()) { + // BTreeMap.range panics if range is start > end. + // However, this cases represent just empty range and we treat it as such. + (Bound::Included(start), Bound::Excluded(end)) if start > end => Vec::new(), + _ => match order { + Order::Ascending => self.data.range(bounds).map(clone_item).collect(), + Order::Descending => self.data.range(bounds).rev().map(clone_item).collect(), + }, + }; + + let last_id: u32 = self + .iterators + .len() + .try_into() + .expect("Found more iterator IDs than supported"); + let new_id = last_id + 1; + let iter = Iter { + data: values, + position: 0, + }; + self.iterators.insert(new_id, iter); + + (Ok(new_id), gas_info) + } + + fn next(&mut self, iterator_id: u32) -> BackendResult> { + let iterator = match self.iterators.get_mut(&iterator_id) { + Some(i) => i, + None => { + return ( + Err(BackendError::iterator_does_not_exist(iterator_id)), + GasInfo::free(), + ) + } + }; + + let (value, gas_info): (Option, GasInfo) = + if iterator.data.len() > iterator.position { + let item = iterator.data[iterator.position].clone(); + iterator.position += 1; + let gas_cost = (item.0.len() + item.1.len()) as u64; + (Some(item), GasInfo::with_cost(gas_cost)) + } else { + (None, GasInfo::with_externally_used(GAS_COST_LAST_ITERATION)) + }; + + (Ok(value), gas_info) + } + + fn set(&mut self, key: &[u8], value: &[u8]) -> BackendResult<()> { + self.data.insert(key.to_vec(), value.to_vec()); + let gas_info = GasInfo::with_externally_used((key.len() + value.len()) as u64); + (Ok(()), gas_info) + } + + fn remove(&mut self, key: &[u8]) -> BackendResult<()> { + self.data.remove(key); + let gas_info = GasInfo::with_externally_used(key.len() as u64); + (Ok(()), gas_info) + } +} + +fn range_bounds(start: Option<&[u8]>, end: Option<&[u8]>) -> impl RangeBounds> { + ( + start.map_or(Bound::Unbounded, |x| Bound::Included(x.to_vec())), + end.map_or(Bound::Unbounded, |x| Bound::Excluded(x.to_vec())), + ) +} + +/// The BTreeMap specific key-value pair reference type, as returned by BTreeMap, Vec>::range. +/// This is internal as it can change any time if the map implementation is swapped out. +type BTreeMapRecordRef<'a> = (&'a Vec, &'a Vec); + +fn clone_item(item_ref: BTreeMapRecordRef) -> Record { + let (key, value) = item_ref; + (key.clone(), value.clone()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn get_and_set() { + let mut store = MockStorage::new(); + assert_eq!(None, store.get(b"foo").0.unwrap()); + store.set(b"foo", b"bar").0.unwrap(); + assert_eq!(Some(b"bar".to_vec()), store.get(b"foo").0.unwrap()); + assert_eq!(None, store.get(b"food").0.unwrap()); + } + + #[test] + fn delete() { + let mut store = MockStorage::new(); + store.set(b"foo", b"bar").0.unwrap(); + store.set(b"food", b"bank").0.unwrap(); + store.remove(b"foo").0.unwrap(); + + assert_eq!(None, store.get(b"foo").0.unwrap()); + assert_eq!(Some(b"bank".to_vec()), store.get(b"food").0.unwrap()); + } + + #[test] + + fn iterator() { + let mut store = MockStorage::new(); + store.set(b"foo", b"bar").0.expect("error setting value"); + + // ensure we had previously set "foo" = "bar" + assert_eq!(store.get(b"foo").0.unwrap(), Some(b"bar".to_vec())); + let iter_id = store.scan(None, None, Order::Ascending).0.unwrap(); + assert_eq!(store.all(iter_id).0.unwrap().len(), 1); + + // setup - add some data, and delete part of it as well + store.set(b"ant", b"hill").0.expect("error setting value"); + store.set(b"ze", b"bra").0.expect("error setting value"); + + // noise that should be ignored + store.set(b"bye", b"bye").0.expect("error setting value"); + store.remove(b"bye").0.expect("error removing key"); + + // unbounded + { + let iter_id = store.scan(None, None, Order::Ascending).0.unwrap(); + let elements = store.all(iter_id).0.unwrap(); + assert_eq!( + elements, + vec![ + (b"ant".to_vec(), b"hill".to_vec()), + (b"foo".to_vec(), b"bar".to_vec()), + (b"ze".to_vec(), b"bra".to_vec()), + ] + ); + } + + // unbounded (descending) + { + let iter_id = store.scan(None, None, Order::Descending).0.unwrap(); + let elements = store.all(iter_id).0.unwrap(); + assert_eq!( + elements, + vec![ + (b"ze".to_vec(), b"bra".to_vec()), + (b"foo".to_vec(), b"bar".to_vec()), + (b"ant".to_vec(), b"hill".to_vec()), + ] + ); + } + + // bounded + { + let iter_id = store + .scan(Some(b"f"), Some(b"n"), Order::Ascending) + .0 + .unwrap(); + let elements = store.all(iter_id).0.unwrap(); + assert_eq!(elements, vec![(b"foo".to_vec(), b"bar".to_vec())]); + } + + // bounded (descending) + { + let iter_id = store + .scan(Some(b"air"), Some(b"loop"), Order::Descending) + .0 + .unwrap(); + let elements = store.all(iter_id).0.unwrap(); + assert_eq!( + elements, + vec![ + (b"foo".to_vec(), b"bar".to_vec()), + (b"ant".to_vec(), b"hill".to_vec()), + ] + ); + } + + // bounded empty [a, a) + { + let iter_id = store + .scan(Some(b"foo"), Some(b"foo"), Order::Ascending) + .0 + .unwrap(); + let elements = store.all(iter_id).0.unwrap(); + assert_eq!(elements, vec![]); + } + + // bounded empty [a, a) (descending) + { + let iter_id = store + .scan(Some(b"foo"), Some(b"foo"), Order::Descending) + .0 + .unwrap(); + let elements = store.all(iter_id).0.unwrap(); + assert_eq!(elements, vec![]); + } + + // bounded empty [a, b) with b < a + { + let iter_id = store + .scan(Some(b"z"), Some(b"a"), Order::Ascending) + .0 + .unwrap(); + let elements = store.all(iter_id).0.unwrap(); + assert_eq!(elements, vec![]); + } + + // bounded empty [a, b) with b < a (descending) + { + let iter_id = store + .scan(Some(b"z"), Some(b"a"), Order::Descending) + .0 + .unwrap(); + let elements = store.all(iter_id).0.unwrap(); + assert_eq!(elements, vec![]); + } + + // right unbounded + { + let iter_id = store.scan(Some(b"f"), None, Order::Ascending).0.unwrap(); + let elements = store.all(iter_id).0.unwrap(); + assert_eq!( + elements, + vec![ + (b"foo".to_vec(), b"bar".to_vec()), + (b"ze".to_vec(), b"bra".to_vec()), + ] + ); + } + + // right unbounded (descending) + { + let iter_id = store.scan(Some(b"f"), None, Order::Descending).0.unwrap(); + let elements = store.all(iter_id).0.unwrap(); + assert_eq!( + elements, + vec![ + (b"ze".to_vec(), b"bra".to_vec()), + (b"foo".to_vec(), b"bar".to_vec()), + ] + ); + } + + // left unbounded + { + let iter_id = store.scan(None, Some(b"f"), Order::Ascending).0.unwrap(); + let elements = store.all(iter_id).0.unwrap(); + assert_eq!(elements, vec![(b"ant".to_vec(), b"hill".to_vec()),]); + } + + // left unbounded (descending) + { + let iter_id = store.scan(None, Some(b"no"), Order::Descending).0.unwrap(); + let elements = store.all(iter_id).0.unwrap(); + assert_eq!( + elements, + vec![ + (b"foo".to_vec(), b"bar".to_vec()), + (b"ant".to_vec(), b"hill".to_vec()), + ] + ); + } + } +} diff --git a/src/wasm_emulation/storage/mod.rs b/src/wasm_emulation/storage/mod.rs new file mode 100644 index 00000000..990ea085 --- /dev/null +++ b/src/wasm_emulation/storage/mod.rs @@ -0,0 +1,7 @@ +pub mod dual_storage; +pub mod mock_storage; +pub use dual_storage::DualStorage; + +pub use mock_storage::MockStorage; + +pub mod analyzer; From f6100d520bb2e39c58e492fb9955059488dbcdcb Mon Sep 17 00:00:00 2001 From: Kayanski Date: Thu, 28 Sep 2023 16:04:22 +0200 Subject: [PATCH 02/81] Changed variable name --- src/wasm.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wasm.rs b/src/wasm.rs index 9a966e4d..6ae3c058 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -46,7 +46,7 @@ const CONTRACTS: Map<&Addr, ContractData> = Map::new("contracts"); pub const NAMESPACE_WASM: &[u8] = b"wasm"; /// See const CONTRACT_ATTR: &str = "_contract_address"; -const LOCAL_CODE_OFFFSET: usize = 5_000_000; +pub const LOCAL_CODE_OFFSET: usize = 5_000_000; #[derive(Clone, Debug, PartialEq, Eq, JsonSchema)] pub struct WasmSudo { @@ -288,7 +288,7 @@ impl WasmKeeper { /// Stores contract code in the in-memory lookup table. /// Returns an identifier of the stored contract code. pub fn store_code(&mut self, creator: Addr, code: WasmContract) -> u64 { - let code_id = self.code_base.len() + 1 + LOCAL_CODE_OFFFSET; + let code_id = self.code_base.len() + 1 + LOCAL_CODE_OFFSET; self.code_base.insert(code_id, code); self.code_data.insert( code_id, @@ -308,7 +308,7 @@ impl WasmKeeper { .code_base .get(&(code_id as usize)) .ok_or(Error::UnregisteredCodeId(code_id))?; - let code_id = self.code_base.len() + 1 + LOCAL_CODE_OFFFSET; + let code_id = self.code_base.len() + 1 + LOCAL_CODE_OFFSET; self.code_data.insert( code_id, CodeData { From 86691005c4cd0cd8bb12446ef8dd3c531547ebda Mon Sep 17 00:00:00 2001 From: Kayanski Date: Thu, 28 Sep 2023 16:07:34 +0200 Subject: [PATCH 03/81] Expose constant --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 05bd6bed..61f6ce8c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,4 +35,4 @@ pub use crate::module::{FailingModule, Module}; pub use crate::staking::{ Distribution, DistributionKeeper, StakeKeeper, Staking, StakingInfo, StakingSudo, }; -pub use crate::wasm::{AddressGenerator, Wasm, WasmKeeper, WasmSudo}; +pub use crate::wasm::{AddressGenerator, Wasm, WasmKeeper, WasmSudo, LOCAL_CODE_OFFSET}; From 1c4f8f8a04492960c2b6afedbf61dd146d24fa87 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Wed, 18 Oct 2023 11:45:41 +0200 Subject: [PATCH 04/81] Commented tests --- examples/cavern_test_app.rs | 378 ++++++++++++++++++------------------ examples/local_test_app.rs | 370 ++++++++++++++++++----------------- 2 files changed, 378 insertions(+), 370 deletions(-) diff --git a/examples/cavern_test_app.rs b/examples/cavern_test_app.rs index c17e7cdb..635007ca 100644 --- a/examples/cavern_test_app.rs +++ b/examples/cavern_test_app.rs @@ -1,188 +1,192 @@ -use cosmwasm_schema::cw_serde; -use cosmwasm_schema::QueryResponses; -use cosmwasm_std::coins; -use cosmwasm_std::Addr; -use cosmwasm_std::ContractInfoResponse; -use cosmwasm_std::QueryRequest; -use cosmwasm_std::WasmQuery; -use cw20::BalanceResponse; -use cw_multi_test::wasm_emulation::contract::WasmContract; -use cw_multi_test::wasm_emulation::storage::analyzer::StorageAnalyzer; -use cw_multi_test::BankKeeper; -use cw_multi_test::Executor; -use std::path::Path; - -use cw20::Cw20QueryMsg; -use cw_multi_test::AppBuilder; -use cw_multi_test::FailingModule; -use cw_orch_networks::networks::PHOENIX_1; - -use cosmwasm_std::Empty; -use cw_multi_test::WasmKeeper; -use moneymarket::market::ExecuteMsg; - -/// COUNTER CONTRACT MSGs -#[cw_serde] -#[cfg_attr(feature = "interface", derive(cw_orch::QueryFns))] // Function generation -#[derive(QueryResponses)] -pub enum QueryMsg { - // GetCount returns the current count as a json-encoded number - #[returns(GetCountResponse)] - GetCount {}, - // GetCount returns the current count of the cousin contract - #[returns(GetCountResponse)] - GetCousinCount {}, -} - -// Custom response for the query -#[cw_serde] -pub struct GetCountResponse { - pub count: i32, -} - -#[cw_serde] -pub struct MigrateMsg { - pub t: String, -} - -/// END CONTRACT MSGs - -pub fn main() { - env_logger::init(); - let mut wasm = WasmKeeper::::new(); - wasm.set_chain(PHOENIX_1.into()); - - let mut bank = BankKeeper::new(); - bank.set_chain(PHOENIX_1.into()); - - // First we instantiate a new app - let app = AppBuilder::default() - .with_wasm::, _>(wasm) - .with_bank(bank); - let mut app = app.build(|_, _, _| {}); - - // Then we send a message to the blockchain through the app - let sender = "terra1ytj0hhw39j88qsx4yapsr6ker83jv3aj354gmj"; - let market = "terra1zqlcp3aty4p4rjv96h6qdascdn953v6crhwedu5vddxjnp349upscluex6"; - let currency = "ibc/B3504E092456BA618CC28AC671A71FB08C6CA0FD0BE7C8A5B5A3E2DD933CC9E4"; - let a_currency = "terra1gwdxyqtu75es0x5l6cd9flqhh87zjtj7qdankayyr0vtt7s9w4ssm7ds8m"; - - // We add some funds to the sender, because they need some. - app.init_modules(|router, _, storage| { - router - .bank - .init_balance(storage, &Addr::unchecked(sender), coins(10_000_000, "uusd")) - }).unwrap(); - - // We query to verify the state changed - let response: BalanceResponse = app - .wrap() - .query_wasm_smart( - a_currency, - &Cw20QueryMsg::Balance { - address: sender.to_string(), - }, - ) - .unwrap(); - log::info!("Before deposit : {:?}", response); - - app.execute_contract( - Addr::unchecked(sender), - Addr::unchecked(market), - &ExecuteMsg::DepositStable {}, - &coins(10_000, currency), - ) - .unwrap(); - - // We query to verify the state changed - let response: BalanceResponse = app - .wrap() - .query_wasm_smart( - a_currency, - &Cw20QueryMsg::Balance { - address: sender.to_string(), - }, - ) - .unwrap(); - log::info!("After deposit : {:?}", response); - - // Now we try to migrate the contract - - let code = std::fs::read( - Path::new(env!("CARGO_MANIFEST_DIR")) - .join("artifacts") - .join("counter_contract.wasm"), - ) - .unwrap(); - let counter_contract = WasmContract::new_local(code, PHOENIX_1); - - let code_id = app.store_code(counter_contract); - - let contract_info: ContractInfoResponse = app - .wrap() - .query(&QueryRequest::Wasm(WasmQuery::ContractInfo { - contract_addr: market.to_string(), - })) - .unwrap(); - - app.migrate_contract( - Addr::unchecked(contract_info.admin.clone().unwrap()), - Addr::unchecked(market), - &MigrateMsg { t: "t".to_string() }, - code_id, - ) - .unwrap(); - - // The query count message should error with a specific storage error - - let err = app - .wrap() - .query_wasm_smart::(market, &QueryMsg::GetCount {}) - .unwrap_err(); - - if !err - .to_string() - .contains("counter_contract::state::State not found") - { - panic!( - "Error {} should contain counter_contract::state::State not found", - err - ); - } - - // Now we migrate back and deposit again - app.migrate_contract( - Addr::unchecked(contract_info.admin.unwrap()), - Addr::unchecked(market), - &Empty {}, - contract_info.code_id, - ) - .unwrap(); - app.execute_contract( - Addr::unchecked(sender), - Addr::unchecked(market), - &ExecuteMsg::DepositStable {}, - &coins(10_000, currency), - ) - .unwrap(); - - // We query to verify the state changed - let response: BalanceResponse = app - .wrap() - .query_wasm_smart( - a_currency, - &Cw20QueryMsg::Balance { - address: sender.to_string(), - }, - ) - .unwrap(); - log::info!("After migrate and deposit : {:?}", response); - - let analysis = StorageAnalyzer::new(&app, PHOENIX_1).unwrap(); - log::info!( - "All contracts storage {:?}", - analysis.all_readable_contract_storage() - ); - - analysis.compare_all_readable_contract_storage(); +// use cosmwasm_schema::cw_serde; +// use cosmwasm_schema::QueryResponses; +// use cosmwasm_std::coins; +// use cosmwasm_std::Addr; +// use cosmwasm_std::ContractInfoResponse; +// use cosmwasm_std::QueryRequest; +// use cosmwasm_std::WasmQuery; +// use cw20::BalanceResponse; +// use cw_multi_test::wasm_emulation::contract::WasmContract; +// use cw_multi_test::wasm_emulation::storage::analyzer::StorageAnalyzer; +// use cw_multi_test::BankKeeper; +// use cw_multi_test::Executor; +// use std::path::Path; + +// use cw20::Cw20QueryMsg; +// use cw_multi_test::AppBuilder; +// use cw_multi_test::FailingModule; +// use cw_orch_networks::networks::PHOENIX_1; + +// use cosmwasm_std::Empty; +// use cw_multi_test::WasmKeeper; +// use moneymarket::market::ExecuteMsg; + +// /// COUNTER CONTRACT MSGs +// #[cw_serde] +// #[cfg_attr(feature = "interface", derive(cw_orch::QueryFns))] // Function generation +// #[derive(QueryResponses)] +// pub enum QueryMsg { +// // GetCount returns the current count as a json-encoded number +// #[returns(GetCountResponse)] +// GetCount {}, +// // GetCount returns the current count of the cousin contract +// #[returns(GetCountResponse)] +// GetCousinCount {}, +// } + +// // Custom response for the query +// #[cw_serde] +// pub struct GetCountResponse { +// pub count: i32, +// } + +// #[cw_serde] +// pub struct MigrateMsg { +// pub t: String, +// } + +// /// END CONTRACT MSGs + +// pub fn main() { +// env_logger::init(); +// let mut wasm = WasmKeeper::::new(); +// wasm.set_chain(PHOENIX_1.into()); + +// let mut bank = BankKeeper::new(); +// bank.set_chain(PHOENIX_1.into()); + +// // First we instantiate a new app +// let app = AppBuilder::default() +// .with_wasm::, _>(wasm) +// .with_bank(bank); +// let mut app = app.build(|_, _, _| {}); + +// // Then we send a message to the blockchain through the app +// let sender = "terra1ytj0hhw39j88qsx4yapsr6ker83jv3aj354gmj"; +// let market = "terra1zqlcp3aty4p4rjv96h6qdascdn953v6crhwedu5vddxjnp349upscluex6"; +// let currency = "ibc/B3504E092456BA618CC28AC671A71FB08C6CA0FD0BE7C8A5B5A3E2DD933CC9E4"; +// let a_currency = "terra1gwdxyqtu75es0x5l6cd9flqhh87zjtj7qdankayyr0vtt7s9w4ssm7ds8m"; + +// // We add some funds to the sender, because they need some. +// app.init_modules(|router, _, storage| { +// router +// .bank +// .init_balance(storage, &Addr::unchecked(sender), coins(10_000_000, "uusd")) +// }).unwrap(); + +// // We query to verify the state changed +// let response: BalanceResponse = app +// .wrap() +// .query_wasm_smart( +// a_currency, +// &Cw20QueryMsg::Balance { +// address: sender.to_string(), +// }, +// ) +// .unwrap(); +// log::info!("Before deposit : {:?}", response); + +// app.execute_contract( +// Addr::unchecked(sender), +// Addr::unchecked(market), +// &ExecuteMsg::DepositStable {}, +// &coins(10_000, currency), +// ) +// .unwrap(); + +// // We query to verify the state changed +// let response: BalanceResponse = app +// .wrap() +// .query_wasm_smart( +// a_currency, +// &Cw20QueryMsg::Balance { +// address: sender.to_string(), +// }, +// ) +// .unwrap(); +// log::info!("After deposit : {:?}", response); + +// // Now we try to migrate the contract + +// let code = std::fs::read( +// Path::new(env!("CARGO_MANIFEST_DIR")) +// .join("artifacts") +// .join("counter_contract.wasm"), +// ) +// .unwrap(); +// let counter_contract = WasmContract::new_local(code, PHOENIX_1); + +// let code_id = app.store_code(counter_contract); + +// let contract_info: ContractInfoResponse = app +// .wrap() +// .query(&QueryRequest::Wasm(WasmQuery::ContractInfo { +// contract_addr: market.to_string(), +// })) +// .unwrap(); + +// app.migrate_contract( +// Addr::unchecked(contract_info.admin.clone().unwrap()), +// Addr::unchecked(market), +// &MigrateMsg { t: "t".to_string() }, +// code_id, +// ) +// .unwrap(); + +// // The query count message should error with a specific storage error + +// let err = app +// .wrap() +// .query_wasm_smart::(market, &QueryMsg::GetCount {}) +// .unwrap_err(); + +// if !err +// .to_string() +// .contains("counter_contract::state::State not found") +// { +// panic!( +// "Error {} should contain counter_contract::state::State not found", +// err +// ); +// } + +// // Now we migrate back and deposit again +// app.migrate_contract( +// Addr::unchecked(contract_info.admin.unwrap()), +// Addr::unchecked(market), +// &Empty {}, +// contract_info.code_id, +// ) +// .unwrap(); +// app.execute_contract( +// Addr::unchecked(sender), +// Addr::unchecked(market), +// &ExecuteMsg::DepositStable {}, +// &coins(10_000, currency), +// ) +// .unwrap(); + +// // We query to verify the state changed +// let response: BalanceResponse = app +// .wrap() +// .query_wasm_smart( +// a_currency, +// &Cw20QueryMsg::Balance { +// address: sender.to_string(), +// }, +// ) +// .unwrap(); +// log::info!("After migrate and deposit : {:?}", response); + +// let analysis = StorageAnalyzer::new(&app, PHOENIX_1).unwrap(); +// log::info!( +// "All contracts storage {:?}", +// analysis.all_readable_contract_storage() +// ); + +// analysis.compare_all_readable_contract_storage(); +// } + +fn main(){ + } diff --git a/examples/local_test_app.rs b/examples/local_test_app.rs index d0d2adde..bd152ee2 100644 --- a/examples/local_test_app.rs +++ b/examples/local_test_app.rs @@ -1,184 +1,188 @@ -use ibc_chain_registry::chain::ChainData; -use std::path::Path; - -use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::Empty; - -use cw_multi_test::wasm_emulation::contract::WasmContract; -use cw_multi_test::wasm_emulation::storage::analyzer::StorageAnalyzer; -use cw_multi_test::AppBuilder; -use cw_multi_test::Executor; -use cw_multi_test::FailingModule; -use cw_multi_test::WasmKeeper; - -use cw_orch_daemon::networks::PHOENIX_1; - -#[cw_serde] -pub struct InstantiateMsg { - pub count: i32, -} - -// ANCHOR: exec_msg -#[cw_serde] -#[cfg_attr(feature = "interface", derive(cw_orch::ExecuteFns))] // Function generation -pub enum ExecuteMsg { - Increment {}, - IncrementAndQuery {}, - SetCousin { addr: String }, - Reset { count: i32 }, -} -// ANCHOR_END: exec_msg - -// ANCHOR: query_msg -#[cw_serde] -#[cfg_attr(feature = "interface", derive(cw_orch::QueryFns))] // Function generation -#[derive(QueryResponses)] -pub enum QueryMsg { - // GetCount returns the current count as a json-encoded number - #[returns(GetCountResponse)] - GetCount {}, - // GetCount returns the current count of the cousin contract - #[returns(GetCountResponse)] - GetCousinCount {}, -} - -// Custom response for the query -#[cw_serde] -pub struct GetCountResponse { - pub count: i32, -} -#[cw_serde] -pub struct GetCousinCountResponse { - pub raw: i32, - pub smart: i32, -} -// ANCHOR_END: query_msg - -#[cw_serde] -pub struct MigrateMsg { - pub t: String, -} - -pub fn main() { - env_logger::init(); - - let chain: ChainData = PHOENIX_1.into(); - - let mut wasm = WasmKeeper::::new(); - wasm.set_chain(chain.clone()); - - // First we instantiate a new app - let app = AppBuilder::default() - .with_chain(chain.clone()) - .with_wasm::, _>(wasm); - let mut app = app.build(|_, _, _| {}); - - // Then we send a message to the blockchain through the app - let sender = app.next_address(); - - let code = std::fs::read( - Path::new(env!("CARGO_MANIFEST_DIR")) - .join("artifacts") - .join("counter_contract.wasm"), - ) - .unwrap(); - let counter_contract = WasmContract::new_local(code, chain.clone()); - - let code_id = app.store_code(counter_contract); - - let counter1 = app - .instantiate_contract( - code_id, - sender.clone(), - &InstantiateMsg { count: 1 }, - &[], - "cousin-counter", - Some(sender.to_string()), - ) - .unwrap(); - let counter2 = app - .instantiate_contract( - code_id, - sender.clone(), - &InstantiateMsg { count: 1 }, - &[], - "cousin-counter", - Some(sender.to_string()), - ) - .unwrap(); - - app.execute_contract( - sender.clone(), - counter1.clone(), - &ExecuteMsg::Increment {}, - &[], - ) - .unwrap(); - app.execute_contract( - sender.clone(), - counter1.clone(), - &ExecuteMsg::Increment {}, - &[], - ) - .unwrap(); - app.execute_contract( - sender.clone(), - counter2.clone(), - &ExecuteMsg::Increment {}, - &[], - ) - .unwrap(); - - app.execute_contract( - sender.clone(), - counter1.clone(), - &ExecuteMsg::SetCousin { - addr: counter2.to_string(), - }, - &[], - ) - .unwrap(); - app.execute_contract( - sender, - counter2.clone(), - &ExecuteMsg::SetCousin { - addr: counter1.to_string(), - }, - &[], - ) - .unwrap(); - - let cousin_count: GetCousinCountResponse = app - .wrap() - .query_wasm_smart(counter2.clone(), &QueryMsg::GetCousinCount {}) - .unwrap(); - assert_eq!(cousin_count.raw, cousin_count.smart); - assert_eq!(cousin_count.raw, 3); - - let cousin_count: GetCousinCountResponse = app - .wrap() - .query_wasm_smart(counter1.clone(), &QueryMsg::GetCousinCount {}) - .unwrap(); - assert_eq!(cousin_count.raw, cousin_count.smart); - assert_eq!(cousin_count.raw, 2); - - // Analyze the storage - - let analysis = StorageAnalyzer::new(&app, chain).unwrap(); - - log::info!( - "analysis, wasm1 {:?}", - analysis.get_contract_storage(counter1.clone()) - ); - log::info!("analysis, wasm1 {:?}", analysis.readable_storage(counter1)); - log::info!( - "analysis, wasm2 {:?}", - analysis.get_contract_storage(counter2.clone()) - ); - log::info!("analysis, wasm2 {:?}", analysis.readable_storage(counter2)); - log::info!( - "All contracts storage {:?}", - analysis.all_readable_contract_storage() - ); - analysis.compare_all_readable_contract_storage(); +// use ibc_chain_registry::chain::ChainData; +// use std::path::Path; + +// use cosmwasm_schema::{cw_serde, QueryResponses}; +// use cosmwasm_std::Empty; + +// use cw_multi_test::wasm_emulation::contract::WasmContract; +// use cw_multi_test::wasm_emulation::storage::analyzer::StorageAnalyzer; +// use cw_multi_test::AppBuilder; +// use cw_multi_test::Executor; +// use cw_multi_test::FailingModule; +// use cw_multi_test::WasmKeeper; + +// use cw_orch_daemon::networks::PHOENIX_1; + +// #[cw_serde] +// pub struct InstantiateMsg { +// pub count: i32, +// } + +// // ANCHOR: exec_msg +// #[cw_serde] +// #[cfg_attr(feature = "interface", derive(cw_orch::ExecuteFns))] // Function generation +// pub enum ExecuteMsg { +// Increment {}, +// IncrementAndQuery {}, +// SetCousin { addr: String }, +// Reset { count: i32 }, +// } +// // ANCHOR_END: exec_msg + +// // ANCHOR: query_msg +// #[cw_serde] +// #[cfg_attr(feature = "interface", derive(cw_orch::QueryFns))] // Function generation +// #[derive(QueryResponses)] +// pub enum QueryMsg { +// // GetCount returns the current count as a json-encoded number +// #[returns(GetCountResponse)] +// GetCount {}, +// // GetCount returns the current count of the cousin contract +// #[returns(GetCountResponse)] +// GetCousinCount {}, +// } + +// // Custom response for the query +// #[cw_serde] +// pub struct GetCountResponse { +// pub count: i32, +// } +// #[cw_serde] +// pub struct GetCousinCountResponse { +// pub raw: i32, +// pub smart: i32, +// } +// // ANCHOR_END: query_msg + +// #[cw_serde] +// pub struct MigrateMsg { +// pub t: String, +// } + +// pub fn main() { +// env_logger::init(); + +// let chain: ChainData = PHOENIX_1.into(); + +// let mut wasm = WasmKeeper::::new(); +// wasm.set_chain(chain.clone()); + +// // First we instantiate a new app +// let app = AppBuilder::default() +// .with_chain(chain.clone()) +// .with_wasm::, _>(wasm); +// let mut app = app.build(|_, _, _| {}); + +// // Then we send a message to the blockchain through the app +// let sender = app.next_address(); + +// let code = std::fs::read( +// Path::new(env!("CARGO_MANIFEST_DIR")) +// .join("artifacts") +// .join("counter_contract.wasm"), +// ) +// .unwrap(); +// let counter_contract = WasmContract::new_local(code, chain.clone()); + +// let code_id = app.store_code(counter_contract); + +// let counter1 = app +// .instantiate_contract( +// code_id, +// sender.clone(), +// &InstantiateMsg { count: 1 }, +// &[], +// "cousin-counter", +// Some(sender.to_string()), +// ) +// .unwrap(); +// let counter2 = app +// .instantiate_contract( +// code_id, +// sender.clone(), +// &InstantiateMsg { count: 1 }, +// &[], +// "cousin-counter", +// Some(sender.to_string()), +// ) +// .unwrap(); + +// app.execute_contract( +// sender.clone(), +// counter1.clone(), +// &ExecuteMsg::Increment {}, +// &[], +// ) +// .unwrap(); +// app.execute_contract( +// sender.clone(), +// counter1.clone(), +// &ExecuteMsg::Increment {}, +// &[], +// ) +// .unwrap(); +// app.execute_contract( +// sender.clone(), +// counter2.clone(), +// &ExecuteMsg::Increment {}, +// &[], +// ) +// .unwrap(); + +// app.execute_contract( +// sender.clone(), +// counter1.clone(), +// &ExecuteMsg::SetCousin { +// addr: counter2.to_string(), +// }, +// &[], +// ) +// .unwrap(); +// app.execute_contract( +// sender, +// counter2.clone(), +// &ExecuteMsg::SetCousin { +// addr: counter1.to_string(), +// }, +// &[], +// ) +// .unwrap(); + +// let cousin_count: GetCousinCountResponse = app +// .wrap() +// .query_wasm_smart(counter2.clone(), &QueryMsg::GetCousinCount {}) +// .unwrap(); +// assert_eq!(cousin_count.raw, cousin_count.smart); +// assert_eq!(cousin_count.raw, 3); + +// let cousin_count: GetCousinCountResponse = app +// .wrap() +// .query_wasm_smart(counter1.clone(), &QueryMsg::GetCousinCount {}) +// .unwrap(); +// assert_eq!(cousin_count.raw, cousin_count.smart); +// assert_eq!(cousin_count.raw, 2); + +// // Analyze the storage + +// let analysis = StorageAnalyzer::new(&app, chain).unwrap(); + +// log::info!( +// "analysis, wasm1 {:?}", +// analysis.get_contract_storage(counter1.clone()) +// ); +// log::info!("analysis, wasm1 {:?}", analysis.readable_storage(counter1)); +// log::info!( +// "analysis, wasm2 {:?}", +// analysis.get_contract_storage(counter2.clone()) +// ); +// log::info!("analysis, wasm2 {:?}", analysis.readable_storage(counter2)); +// log::info!( +// "All contracts storage {:?}", +// analysis.all_readable_contract_storage() +// ); +// analysis.compare_all_readable_contract_storage(); +// } + +fn main(){ + } From 40e3e876e04a1a25c74ca8350f6c1c79b81c7769 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Sat, 4 Nov 2023 12:35:59 +0100 Subject: [PATCH 05/81] Changed prefix impl --- src/wasm_emulation/api/mod.rs | 33 +++++++++------------------------ 1 file changed, 9 insertions(+), 24 deletions(-) diff --git a/src/wasm_emulation/api/mod.rs b/src/wasm_emulation/api/mod.rs index 5dbf2cd6..e1b525b3 100644 --- a/src/wasm_emulation/api/mod.rs +++ b/src/wasm_emulation/api/mod.rs @@ -25,42 +25,27 @@ pub fn bytes_from_bech32(address: &str, prefix: &str) -> Result, Backend Ok(Vec::::from_base32(&data).unwrap()) } -// Prefixes are limited to 6 chars +pub const MAX_PREFIX_CHARS: usize = 10; +// Prefixes are limited to MAX_PREFIX_CHARS chars // This allows one to specify a string prefix and still implement Copy #[derive(Clone, Copy)] pub struct RealApi { - pub prefix1: Option, - pub prefix2: Option, - pub prefix3: Option, - pub prefix4: Option, - pub prefix5: Option, - pub prefix6: Option, + pub prefix: [char; MAX_PREFIX_CHARS] } impl RealApi { pub fn new(prefix: &str) -> RealApi { - let mut chars = prefix.chars(); + let chars: Vec = prefix.chars().collect(); + if chars.len() > MAX_PREFIX_CHARS{ + panic!("More chars in the prefix than {}", MAX_PREFIX_CHARS); + } Self { - prefix1: chars.next(), - prefix2: chars.next(), - prefix3: chars.next(), - prefix4: chars.next(), - prefix5: chars.next(), - prefix6: chars.next(), + prefix: chars[0..10].try_into().unwrap() } } pub fn get_prefix(&self) -> String { - let collection = [ - self.prefix1, - self.prefix2, - self.prefix3, - self.prefix4, - self.prefix5, - self.prefix6, - ]; - - collection.iter().filter_map(|e| *e).collect() + self.prefix.iter().collect() } pub fn next_address(&self, count: usize) -> Addr { From 79be3b87f5935de3ea2fe2b1023aba18293ac91e Mon Sep 17 00:00:00 2001 From: Kayanski Date: Sat, 4 Nov 2023 12:44:11 +0100 Subject: [PATCH 06/81] Fixed tests --- src/wasm_emulation/api/mod.rs | 43 +++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/src/wasm_emulation/api/mod.rs b/src/wasm_emulation/api/mod.rs index e1b525b3..9e30b15c 100644 --- a/src/wasm_emulation/api/mod.rs +++ b/src/wasm_emulation/api/mod.rs @@ -35,17 +35,29 @@ pub struct RealApi { impl RealApi { pub fn new(prefix: &str) -> RealApi { - let chars: Vec = prefix.chars().collect(); - if chars.len() > MAX_PREFIX_CHARS{ + + if prefix.len() > MAX_PREFIX_CHARS{ panic!("More chars in the prefix than {}", MAX_PREFIX_CHARS); } + + let mut api_prefix = ['\0'; 10]; + for (i, c) in prefix.chars().enumerate() { + api_prefix[i] = c; + } Self { - prefix: chars[0..10].try_into().unwrap() + prefix: api_prefix } } pub fn get_prefix(&self) -> String { - self.prefix.iter().collect() + let mut prefix = Vec::new(); + + for &c in self.prefix.iter() { + if c != '\0' { + prefix.push(c); + } + } + prefix.iter().collect() } pub fn next_address(&self, count: usize) -> Addr { @@ -99,3 +111,26 @@ impl BackendApi for RealApi { (human, gas_cost) } } + + +#[cfg(test)] +mod test{ + use super::RealApi; + + #[test] + fn prefix(){ + let prefix = "migaloo"; + + let api = RealApi::new(prefix); + + let final_prefix = api.get_prefix(); + assert_eq!(prefix, final_prefix); + } + + #[test] + #[should_panic] + fn too_long_prefix(){ + let prefix = "migaloowithotherchars"; + RealApi::new(prefix); + } +} \ No newline at end of file From 253385b9ebf63a0ddb01adf61409c56150bc6aab Mon Sep 17 00:00:00 2001 From: Kayanski Date: Sat, 4 Nov 2023 14:04:14 +0100 Subject: [PATCH 07/81] Solved query error panic --- src/wasm_emulation/query/wasm.rs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/wasm_emulation/query/wasm.rs b/src/wasm_emulation/query/wasm.rs index 783f1a34..4c31fbe8 100644 --- a/src/wasm_emulation/query/wasm.rs +++ b/src/wasm_emulation/query/wasm.rs @@ -12,7 +12,7 @@ use cosmwasm_std::testing::mock_env; use cosmwasm_vm::GasInfo; use cw_orch_daemon::queriers::DaemonQuerier; -use cosmwasm_std::{to_binary, Addr, ContractInfoResponse, SystemResult}; +use cosmwasm_std::{to_binary, Addr, ContractInfoResponse, SystemResult, SystemError}; use cosmwasm_std::{ContractResult, Empty}; use cw_orch_daemon::queriers::CosmWasm; @@ -119,7 +119,7 @@ impl WasmQuerier { let mut env = mock_env(); env.contract.address = addr.clone(); // Here we specify empty because we only car about the query result - let result: WasmRunnerOutput = contract + let result: Result, _> = contract .run_contract(InstanceArguments { function: WasmFunction::Query(QueryArgs { env, @@ -127,8 +127,19 @@ impl WasmQuerier { }), querier_storage: self.current_storage.clone(), init_storage: self.current_storage.wasm.get_contract_storage(&addr), - }) - .unwrap(); + }); + + let result = if let Err(e) = result{ + return ( + SystemResult::Err(SystemError::InvalidRequest{ + error: format!("Error querying a contract: {}", e), + request: msg.clone() + }), + GasInfo::with_externally_used(0), + ) + }else{ + result.unwrap() + }; let bin = match result.wasm { WasmOutput::Query(bin) => bin, From 2b3b60e5da8d38fba1fcc5848291beb5f0729a0a Mon Sep 17 00:00:00 2001 From: Kayanski Date: Sat, 4 Nov 2023 15:40:04 +0100 Subject: [PATCH 08/81] =?UTF-8?q?Format=20+=20bank=20query=20storage=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/cavern_test_app.rs | 4 +--- examples/local_test_app.rs | 4 +--- src/wasm_emulation/api/mod.rs | 20 ++++++++------------ src/wasm_emulation/query/wasm.rs | 16 ++++++++-------- src/wasm_emulation/storage/analyzer.rs | 5 +++++ 5 files changed, 23 insertions(+), 26 deletions(-) diff --git a/examples/cavern_test_app.rs b/examples/cavern_test_app.rs index 635007ca..47073038 100644 --- a/examples/cavern_test_app.rs +++ b/examples/cavern_test_app.rs @@ -187,6 +187,4 @@ // analysis.compare_all_readable_contract_storage(); // } -fn main(){ - -} +fn main() {} diff --git a/examples/local_test_app.rs b/examples/local_test_app.rs index bd152ee2..523e9adf 100644 --- a/examples/local_test_app.rs +++ b/examples/local_test_app.rs @@ -183,6 +183,4 @@ // analysis.compare_all_readable_contract_storage(); // } -fn main(){ - -} +fn main() {} diff --git a/src/wasm_emulation/api/mod.rs b/src/wasm_emulation/api/mod.rs index 9e30b15c..41001919 100644 --- a/src/wasm_emulation/api/mod.rs +++ b/src/wasm_emulation/api/mod.rs @@ -30,13 +30,12 @@ pub const MAX_PREFIX_CHARS: usize = 10; // This allows one to specify a string prefix and still implement Copy #[derive(Clone, Copy)] pub struct RealApi { - pub prefix: [char; MAX_PREFIX_CHARS] + pub prefix: [char; MAX_PREFIX_CHARS], } impl RealApi { pub fn new(prefix: &str) -> RealApi { - - if prefix.len() > MAX_PREFIX_CHARS{ + if prefix.len() > MAX_PREFIX_CHARS { panic!("More chars in the prefix than {}", MAX_PREFIX_CHARS); } @@ -44,14 +43,12 @@ impl RealApi { for (i, c) in prefix.chars().enumerate() { api_prefix[i] = c; } - Self { - prefix: api_prefix - } + Self { prefix: api_prefix } } pub fn get_prefix(&self) -> String { let mut prefix = Vec::new(); - + for &c in self.prefix.iter() { if c != '\0' { prefix.push(c); @@ -112,13 +109,12 @@ impl BackendApi for RealApi { } } - #[cfg(test)] -mod test{ +mod test { use super::RealApi; #[test] - fn prefix(){ + fn prefix() { let prefix = "migaloo"; let api = RealApi::new(prefix); @@ -129,8 +125,8 @@ mod test{ #[test] #[should_panic] - fn too_long_prefix(){ + fn too_long_prefix() { let prefix = "migaloowithotherchars"; RealApi::new(prefix); } -} \ No newline at end of file +} diff --git a/src/wasm_emulation/query/wasm.rs b/src/wasm_emulation/query/wasm.rs index 4c31fbe8..3d4e2392 100644 --- a/src/wasm_emulation/query/wasm.rs +++ b/src/wasm_emulation/query/wasm.rs @@ -12,7 +12,7 @@ use cosmwasm_std::testing::mock_env; use cosmwasm_vm::GasInfo; use cw_orch_daemon::queriers::DaemonQuerier; -use cosmwasm_std::{to_binary, Addr, ContractInfoResponse, SystemResult, SystemError}; +use cosmwasm_std::{to_binary, Addr, ContractInfoResponse, SystemError, SystemResult}; use cosmwasm_std::{ContractResult, Empty}; use cw_orch_daemon::queriers::CosmWasm; @@ -119,8 +119,8 @@ impl WasmQuerier { let mut env = mock_env(); env.contract.address = addr.clone(); // Here we specify empty because we only car about the query result - let result: Result, _> = contract - .run_contract(InstanceArguments { + let result: Result, _> = + contract.run_contract(InstanceArguments { function: WasmFunction::Query(QueryArgs { env, msg: msg.to_vec(), @@ -129,15 +129,15 @@ impl WasmQuerier { init_storage: self.current_storage.wasm.get_contract_storage(&addr), }); - let result = if let Err(e) = result{ + let result = if let Err(e) = result { return ( - SystemResult::Err(SystemError::InvalidRequest{ + SystemResult::Err(SystemError::InvalidRequest { error: format!("Error querying a contract: {}", e), - request: msg.clone() + request: msg.clone(), }), GasInfo::with_externally_used(0), - ) - }else{ + ); + } else { result.unwrap() }; diff --git a/src/wasm_emulation/storage/analyzer.rs b/src/wasm_emulation/storage/analyzer.rs index 25c256f2..7a3dcbed 100644 --- a/src/wasm_emulation/storage/analyzer.rs +++ b/src/wasm_emulation/storage/analyzer.rs @@ -7,6 +7,7 @@ use cosmwasm_std::Addr; use cosmwasm_std::Coin; use cw_orch_daemon::queriers::CosmWasm; use cw_orch_daemon::queriers::DaemonQuerier; +use cw_utils::NativeBalance; use ibc_chain_registry::chain::ChainData; use rustc_serialize::json::Json; use serde::__private::from_utf8_lossy; @@ -188,4 +189,8 @@ impl StorageAnalyzer { .map(|(_, b)| b.0.clone()) .unwrap_or(vec![]) } + + pub fn get_all_local_balances(&self) -> Vec<(Addr, NativeBalance)> { + self.storage.bank.storage.clone() + } } From 4ced77b15a7422605e4fead7c7429354e7180f6c Mon Sep 17 00:00:00 2001 From: Kayanski Date: Sat, 4 Nov 2023 16:07:45 +0100 Subject: [PATCH 09/81] Adde balance diff --- Cargo.toml | 3 +- src/wasm_emulation/storage/analyzer.rs | 47 ++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 0a5f5e3c..fb23db81 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,6 +64,7 @@ cosmwasm-schema = "1.2.7" bech32 = "0.9.1" treediff = {version="4.0.2", features=["with-rustc-serialize"]} rustc-serialize = "0.3.24" +serde_json = "1.0.105" [dev-dependencies] # We don't use the following dependency directly, @@ -79,4 +80,4 @@ dotenv = "0.15.0" hex = "0.4.3" cw-asset = "3.0.0" -moneymarket = {git="https://github.com/CavernPerson/money-market-contracts"} \ No newline at end of file +moneymarket = {git="https://github.com/CavernPerson/money-market-contracts"} diff --git a/src/wasm_emulation/storage/analyzer.rs b/src/wasm_emulation/storage/analyzer.rs index 7a3dcbed..27800dc6 100644 --- a/src/wasm_emulation/storage/analyzer.rs +++ b/src/wasm_emulation/storage/analyzer.rs @@ -10,6 +10,7 @@ use cw_orch_daemon::queriers::DaemonQuerier; use cw_utils::NativeBalance; use ibc_chain_registry::chain::ChainData; use rustc_serialize::json::Json; +use serde::Serialize; use serde::__private::from_utf8_lossy; use treediff::diff; use treediff::tools::Recorder; @@ -20,6 +21,12 @@ use crate::{wasm_emulation::input::QuerierStorage, App}; use anyhow::Result as AnyResult; +#[derive(Serialize)] +pub struct SerializableCoin { + amount: String, + denom: String, +} + pub struct StorageAnalyzer { pub storage: QuerierStorage, pub chain: ChainData, @@ -190,6 +197,46 @@ impl StorageAnalyzer { .unwrap_or(vec![]) } + pub fn compare_all_balances(&self) { + let (rt, channel) = get_channel(self.chain.clone()).unwrap(); + let bank_querier = cw_orch_daemon::queriers::Bank::new(channel); + self.get_all_local_balances() + .into_iter() + .for_each(|(addr, balances)| { + // We look for the data at that key on the contract + let distant_data = rt.block_on(bank_querier.balance(addr.clone(), None)); + + if let Ok(data) = distant_data { + let distant_coins: Vec = data + .iter() + .map(|c| Coin { + amount: c.amount.parse().unwrap(), + denom: c.denom.clone(), + }) + .collect(); + + let distant_coins = serde_json::to_string(&distant_coins).unwrap(); + let distant_coins: Json = distant_coins.parse().unwrap(); + + let local_coins = serde_json::to_string(&balances.0).unwrap(); + let local_coins: Json = local_coins.parse().unwrap(); + + let mut d = Recorder::default(); + diff(&distant_coins, &local_coins, &mut d); + + let changes: Vec<_> = d + .calls + .iter() + .filter(|change| { + !matches!(change, treediff::tools::ChangeType::Unchanged(..)) + }) + .collect(); + + log::info!("Bank balance for {} changed like so : {:?}", addr, changes); + } + }); + } + pub fn get_all_local_balances(&self) -> Vec<(Addr, NativeBalance)> { self.storage.bank.storage.clone() } From fd3f63e26c206323dca31e28cfce750476c735f7 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Mon, 6 Nov 2023 10:50:31 +0100 Subject: [PATCH 10/81] Changed default gas limit --- src/wasm_emulation/contract.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wasm_emulation/contract.rs b/src/wasm_emulation/contract.rs index 7a04ddbd..7d2438f0 100644 --- a/src/wasm_emulation/contract.rs +++ b/src/wasm_emulation/contract.rs @@ -69,7 +69,7 @@ fn apply_storage_changes(storage: &mut dyn Storage, output: &WasmRunnerOu /// This gas limit is used in integration tests and should be high enough to allow a reasonable /// number of contract executions and queries on one instance. For this reason it is significatly /// higher than the limit for a single execution that we have in the production setup. -const DEFAULT_GAS_LIMIT: u64 = 500_000_000_000; // ~0.5ms +const DEFAULT_GAS_LIMIT: u64 = 500_000_000_000_000; // ~0.5s const DEFAULT_MEMORY_LIMIT: Option = Some(Size::mebi(16)); const DEFAULT_PRINT_DEBUG: bool = true; From 1649e6a96d9400af6201a62a6f24ceecd61ad29c Mon Sep 17 00:00:00 2001 From: Kayanski Date: Mon, 6 Nov 2023 10:53:36 +0100 Subject: [PATCH 11/81] Removed useless logging --- src/wasm_emulation/api/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/wasm_emulation/api/mod.rs b/src/wasm_emulation/api/mod.rs index 41001919..0b98c665 100644 --- a/src/wasm_emulation/api/mod.rs +++ b/src/wasm_emulation/api/mod.rs @@ -87,8 +87,6 @@ impl BackendApi for RealApi { fn human_address(&self, canon: &[u8]) -> (Result, GasInfo) { let gas_cost = GasInfo::with_externally_used(GAS_COST_HUMANIZE); - log::info!("address {:?}", canon); - if canon.len() != SHORT_CANON_LEN && canon.len() != LONG_CANON_LEN { return ( Err(BackendError::Unknown { From edb5a999d8177e645062839bcf2a97cdadc275d4 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Thu, 16 Nov 2023 23:08:23 +0100 Subject: [PATCH 12/81] Removed some GRPC connections --- src/bank.rs | 18 ++++++++++++------ src/wasm.rs | 8 ++++++-- src/wasm_emulation/channel.rs | 10 +++++++++- src/wasm_emulation/contract.rs | 5 +++-- src/wasm_emulation/query/bank.rs | 7 ++++--- src/wasm_emulation/query/mock_querier.rs | 7 +++++-- src/wasm_emulation/query/wasm.rs | 7 ++++--- src/wasm_emulation/storage/analyzer.rs | 5 +++-- src/wasm_emulation/storage/dual_storage.rs | 6 +++--- 9 files changed, 49 insertions(+), 24 deletions(-) diff --git a/src/bank.rs b/src/bank.rs index 542c624c..f3b93b8c 100644 --- a/src/bank.rs +++ b/src/bank.rs @@ -1,5 +1,7 @@ use crate::wasm_emulation::input::BankStorage; use cw_orch_daemon::queriers::DaemonQuerier; +use tokio::runtime::Runtime; +use tonic::transport::Channel; use std::str::FromStr; use ibc_chain_registry::chain::ChainData; @@ -37,18 +39,22 @@ pub enum BankSudo { pub trait Bank: Module + AllQuerier {} -#[derive(Default)] pub struct BankKeeper { - chain: Option, + rt: Runtime, + channel: Option } impl BankKeeper { pub fn new() -> Self { - BankKeeper::default() + BankKeeper{ + rt: Runtime::new().unwrap(), + channel: None + } } pub fn set_chain(&mut self, chain: ChainData) { - self.chain = Some(chain) + let channel = get_channel(chain, &self.rt).unwrap(); + self.channel = Some(channel); } // this is an "admin" function to let us adjust bank accounts in genesis @@ -79,9 +85,9 @@ impl BankKeeper { fn get_balance(&self, bank_storage: &dyn Storage, account: &Addr) -> AnyResult> { // If there is no balance present, we query it on the distant chain if !BALANCES.has(bank_storage, account) { - let (rt, channel) = get_channel(self.chain.clone().unwrap())?; + let channel = self.channel.clone().unwrap(); let querier = cw_orch_daemon::queriers::Bank::new(channel); - let distant_amounts: Vec = rt + let distant_amounts: Vec = self.rt .block_on(querier.balance(account, None)) .map(|result| { result diff --git a/src/wasm.rs b/src/wasm.rs index 6ae3c058..92a705df 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -5,6 +5,7 @@ use cw_orch_daemon::queriers::CosmWasm; use cw_orch_daemon::queriers::DaemonQuerier; use ibc_chain_registry::chain::ChainData; +use tokio::runtime::Runtime; use std::collections::HashMap; use std::fmt::Debug; @@ -141,6 +142,7 @@ pub struct WasmKeeper { // chain on which the contract should be queried/tested against chain: Option, + rt: Runtime } pub trait AddressGenerator { @@ -175,6 +177,7 @@ impl Default for WasmKeeper { _q: std::marker::PhantomData, generator: Box::new(SimpleAddressGenerator()), chain: None, + rt: Runtime::new().unwrap() } } } @@ -365,8 +368,9 @@ impl WasmKeeper { pub fn load_distant_contract( chain: impl Into, address: &Addr, + rt: &Runtime ) -> AnyResult { - let (rt, channel) = get_channel(chain)?; + let channel = get_channel(chain, &rt)?; let wasm_querier = CosmWasm::new(channel); @@ -392,7 +396,7 @@ impl WasmKeeper { return Ok(local_contract); } - Self::load_distant_contract(self.chain.clone().unwrap(), address) + Self::load_distant_contract(self.chain.clone().unwrap(), address, &self.rt) } pub fn dump_wasm_raw(&self, storage: &dyn Storage, address: &Addr) -> Vec { diff --git a/src/wasm_emulation/channel.rs b/src/wasm_emulation/channel.rs index b749bcbd..46ffb31a 100644 --- a/src/wasm_emulation/channel.rs +++ b/src/wasm_emulation/channel.rs @@ -4,7 +4,7 @@ use cw_orch_daemon::GrpcChannel; use tokio::runtime::Runtime; use tonic::transport::Channel; -pub fn get_channel(chain: impl Into) -> AnyResult<(Runtime, Channel)> { +pub fn get_rt_and_channel(chain: impl Into) -> AnyResult<(Runtime, Channel)> { let rt = Runtime::new()?; let chain = chain.into(); // We create an instance from a code_id, an address, and we run the code in it @@ -12,3 +12,11 @@ pub fn get_channel(chain: impl Into) -> AnyResult<(Runtime, Channe Ok((rt, channel)) } + +pub fn get_channel(chain: impl Into, rt: &Runtime) -> AnyResult { + let chain = chain.into(); + // We create an instance from a code_id, an address, and we run the code in it + let channel = rt.block_on(GrpcChannel::connect(&chain.apis.grpc, &chain.chain_id))?; + + Ok(channel) +} diff --git a/src/wasm_emulation/contract.rs b/src/wasm_emulation/contract.rs index 7d2438f0..9e7a77c6 100644 --- a/src/wasm_emulation/contract.rs +++ b/src/wasm_emulation/contract.rs @@ -45,6 +45,7 @@ use cosmwasm_std::{Binary, CustomQuery, Deps, DepsMut, Env, MessageInfo, Reply, use anyhow::Result as AnyResult; use super::channel::get_channel; +use super::channel::get_rt_and_channel; use super::input::ExecuteArgs; use super::input::InstantiateArgs; use super::input::MigrateArgs; @@ -155,7 +156,7 @@ impl WasmContract { chain, contract_addr, }) => { - let (rt, channel) = get_channel(chain.clone())?; + let (rt, channel) = get_rt_and_channel(chain.clone())?; let wasm_querier = CosmWasm::new(channel); let code_info = rt.block_on(wasm_querier.contract_info(contract_addr))?; @@ -163,7 +164,7 @@ impl WasmContract { Ok(code) } WasmContract::DistantCodeId(DistantCodeId { chain, code_id }) => { - let (rt, channel) = get_channel(chain.clone())?; + let (rt, channel) = get_rt_and_channel(chain.clone())?; let wasm_querier = CosmWasm::new(channel); let code = rt.block_on(wasm_querier.code_data(*code_id))?; diff --git a/src/wasm_emulation/query/bank.rs b/src/wasm_emulation/query/bank.rs index df23c5be..b1e7458a 100644 --- a/src/wasm_emulation/query/bank.rs +++ b/src/wasm_emulation/query/bank.rs @@ -3,6 +3,7 @@ use crate::wasm_emulation::query::gas::{GAS_COST_ALL_BALANCE_QUERY, GAS_COST_BAL use crate::wasm_emulation::query::mock_querier::QueryResultWithGas; use cosmwasm_std::Addr; use cosmwasm_vm::GasInfo; +use tokio::runtime::Runtime; use std::str::FromStr; use cw_orch_daemon::queriers::DaemonQuerier; @@ -73,7 +74,7 @@ impl BankQuerier { supplies } - pub fn query(&self, request: &BankQuery) -> QueryResultWithGas { + pub fn query(&self, rt: &Runtime, request: &BankQuery) -> QueryResultWithGas { let contract_result: ContractResult = match request { BankQuery::Balance { address, denom } => { // proper error on not found, serialize result on found @@ -84,7 +85,7 @@ impl BankQuerier { // If the amount is not available, we query it from the distant chain if amount.is_none() { - let (rt, channel) = get_channel(self.chain.clone()).unwrap(); + let channel = get_channel(self.chain.clone(), &rt).unwrap(); let querier = Bank::new(channel); let query_result = rt @@ -110,7 +111,7 @@ impl BankQuerier { // We query only if the bank balance doesn't exist if amount.is_none() { - let (rt, channel) = get_channel(self.chain.clone()).unwrap(); + let channel = get_channel(self.chain.clone(), rt).unwrap(); let querier = Bank::new(channel); let query_result: Result, _> = rt.block_on(querier.balance(address, None)).map(|result| { diff --git a/src/wasm_emulation/query/mock_querier.rs b/src/wasm_emulation/query/mock_querier.rs index 87b8e190..ef024d44 100644 --- a/src/wasm_emulation/query/mock_querier.rs +++ b/src/wasm_emulation/query/mock_querier.rs @@ -20,6 +20,7 @@ use cosmwasm_std::{FullDelegation, Validator}; use cosmwasm_std::Attribute; use cosmwasm_std::QuerierResult; +use tokio::runtime::Runtime; use crate::wasm_emulation::input::QuerierStorage; @@ -43,6 +44,7 @@ pub struct MockQuerier { /// /// Use box to avoid the need of another generic type custom_handler: Box Fn(&'a C) -> QueryResultWithGas>, + rt: Runtime } impl MockQuerier { @@ -65,6 +67,7 @@ impl MockQuerier { GasInfo::free(), ) }), + rt: Runtime::new().unwrap() } } @@ -122,11 +125,11 @@ impl cosmwasm_vm::Querier for MockQuerier impl MockQuerier { pub fn handle_query(&self, request: &QueryRequest) -> QueryResultWithGas { match &request { - QueryRequest::Bank(bank_query) => self.bank.query(bank_query), + QueryRequest::Bank(bank_query) => self.bank.query(&self.rt, bank_query), QueryRequest::Custom(custom_query) => (*self.custom_handler)(custom_query), QueryRequest::Staking(staking_query) => self.staking.query(staking_query), - QueryRequest::Wasm(msg) => self.wasm.query(msg), + QueryRequest::Wasm(msg) => self.wasm.query(&self.rt, msg), QueryRequest::Stargate { .. } => ( SystemResult::Err(SystemError::UnsupportedRequest { kind: "Stargate".to_string(), diff --git a/src/wasm_emulation/query/wasm.rs b/src/wasm_emulation/query/wasm.rs index 3d4e2392..26ad43ca 100644 --- a/src/wasm_emulation/query/wasm.rs +++ b/src/wasm_emulation/query/wasm.rs @@ -17,6 +17,7 @@ use cosmwasm_std::{ContractResult, Empty}; use cw_orch_daemon::queriers::CosmWasm; use cosmwasm_std::WasmQuery; +use tokio::runtime::Runtime; use crate::wasm_emulation::channel::get_channel; use crate::WasmKeeper; @@ -37,7 +38,7 @@ impl WasmQuerier { } } - pub fn query(&self, request: &WasmQuery) -> QueryResultWithGas { + pub fn query(&self, rt: &Runtime, request: &WasmQuery) -> QueryResultWithGas { match request { WasmQuery::ContractInfo { contract_addr } => { let addr = Addr::unchecked(contract_addr); @@ -46,7 +47,7 @@ impl WasmQuerier { { local_contract.clone() } else { - WasmKeeper::::load_distant_contract(self.chain.clone(), &addr) + WasmKeeper::::load_distant_contract(self.chain.clone(), &addr, rt) .unwrap() }; let mut response = ContractInfoResponse::default(); @@ -73,7 +74,7 @@ impl WasmQuerier { { value.1.clone() } else { - let (rt, channel) = get_channel(self.chain.clone()).unwrap(); + let channel = get_channel(self.chain.clone(), rt).unwrap(); let wasm_querier = CosmWasm::new(channel); let query_result = rt .block_on( diff --git a/src/wasm_emulation/storage/analyzer.rs b/src/wasm_emulation/storage/analyzer.rs index 27800dc6..3085267f 100644 --- a/src/wasm_emulation/storage/analyzer.rs +++ b/src/wasm_emulation/storage/analyzer.rs @@ -2,6 +2,7 @@ use crate::prefixed_storage::decode_length; use crate::prefixed_storage::to_length_prefixed; use crate::prefixed_storage::CONTRACT_STORAGE_PREFIX; use crate::wasm_emulation::channel::get_channel; +use crate::wasm_emulation::channel::get_rt_and_channel; use crate::wasm_emulation::input::get_querier_storage; use cosmwasm_std::Addr; use cosmwasm_std::Coin; @@ -114,7 +115,7 @@ impl StorageAnalyzer { } pub fn compare_all_readable_contract_storage(&self) { - let (rt, channel) = get_channel(self.chain.clone()).unwrap(); + let (rt, channel) = get_rt_and_channel(self.chain.clone()).unwrap(); let wasm_querier = CosmWasm::new(channel); self.all_contract_storage() .into_iter() @@ -198,7 +199,7 @@ impl StorageAnalyzer { } pub fn compare_all_balances(&self) { - let (rt, channel) = get_channel(self.chain.clone()).unwrap(); + let (rt, channel) = get_rt_and_channel(self.chain.clone()).unwrap(); let bank_querier = cw_orch_daemon::queriers::Bank::new(channel); self.get_all_local_balances() .into_iter() diff --git a/src/wasm_emulation/storage/dual_storage.rs b/src/wasm_emulation/storage/dual_storage.rs index 15cbf5e9..7fc98c2f 100644 --- a/src/wasm_emulation/storage/dual_storage.rs +++ b/src/wasm_emulation/storage/dual_storage.rs @@ -1,4 +1,4 @@ -use crate::wasm_emulation::channel::get_channel; +use crate::wasm_emulation::channel::get_rt_and_channel; use crate::wasm_emulation::input::SerChainData; use crate::wasm_emulation::storage::mock_storage::{GAS_COST_LAST_ITERATION, GAS_COST_RANGE}; @@ -108,7 +108,7 @@ impl Storage for DualStorage { let (mut value, gas_info) = self.local_storage.get(key); // If it's not available, we query it online if it was not removed locally if !self.removed_keys.contains(key) && value.as_ref().unwrap().is_none() { - let (rt, channel) = get_channel(self.chain.clone()).unwrap(); + let (rt, channel) = get_rt_and_channel(self.chain.clone()).unwrap(); let wasm_querier = CosmWasm::new(channel); let distant_result = rt.block_on( @@ -181,7 +181,7 @@ impl Storage for DualStorage { if iterator.distant_iter.position == iterator.distant_iter.data.len() && iterator.distant_iter.key.is_some() { - let (rt, channel) = get_channel(self.chain.clone()).unwrap(); + let (rt, channel) = get_rt_and_channel(self.chain.clone()).unwrap(); let wasm_querier = CosmWasm::new(channel); let new_keys = rt .block_on(wasm_querier.all_contract_state( From c354ccb91acb97041d607e2e00a65a533e1f2bfc Mon Sep 17 00:00:00 2001 From: Kayanski Date: Fri, 17 Nov 2023 13:54:42 +0100 Subject: [PATCH 13/81] Removed useless grpc init, rationalized code --- examples/test_app.rs | 61 +++++----- src/app.rs | 88 +++++++------- src/bank.rs | 28 ++--- src/contracts.rs | 132 ++++++++++++++++----- src/wasm.rs | 67 ++++++----- src/wasm_emulation/channel.rs | 32 +++-- src/wasm_emulation/contract.rs | 119 ++++++++----------- src/wasm_emulation/input.rs | 34 ------ src/wasm_emulation/query/bank.rs | 31 +++-- src/wasm_emulation/query/mock_querier.rs | 18 ++- src/wasm_emulation/query/wasm.rs | 41 +++---- src/wasm_emulation/storage/analyzer.rs | 25 ++-- src/wasm_emulation/storage/dual_storage.rs | 21 ++-- 13 files changed, 352 insertions(+), 345 deletions(-) diff --git a/examples/test_app.rs b/examples/test_app.rs index 3b9d2562..de4b288b 100644 --- a/examples/test_app.rs +++ b/examples/test_app.rs @@ -4,6 +4,7 @@ use cw20::Cw20ExecuteMsg; use cw_multi_test::Executor; use cw20::Cw20QueryMsg; +use cw_multi_test::wasm_emulation::channel::RemoteChannel; use cw_multi_test::AppBuilder; use cw_multi_test::BankKeeper; use cw_multi_test::FailingModule; @@ -12,20 +13,31 @@ use cw_orch_daemon::networks::PHOENIX_1; use cw_multi_test::WasmKeeper; use cosmwasm_std::Empty; +use tokio::runtime::Runtime; pub fn main() { + test().unwrap() +} + +pub fn test() -> anyhow::Result<()> { env_logger::init(); + + let runtime = Runtime::new()?; + let chain = PHOENIX_1; + let remote_channel = RemoteChannel::new(&runtime, chain)?; + let mut wasm = WasmKeeper::::new(); - wasm.set_chain(PHOENIX_1.into()); + wasm.set_remote(remote_channel.clone()); let mut bank = BankKeeper::new(); - bank.set_chain(PHOENIX_1.into()); + bank.set_remote(remote_channel.clone()); // First we instantiate a new app - let app = AppBuilder::default() + let mut app = AppBuilder::default() .with_wasm::, _>(wasm) - .with_bank(bank); - let mut app = app.build(|_, _, _| {}); + .with_bank(bank) + .with_remote(remote_channel) + .build(|_, _, _| {})?; // Then we send a message to the blockchain through the app let sender = "terra17c6ts8grcfrgquhj3haclg44le8s7qkx6l2yx33acguxhpf000xqhnl3je"; @@ -33,16 +45,13 @@ pub fn main() { let contract_addr = "terra1lxx40s29qvkrcj8fsa3yzyehy7w50umdvvnls2r830rys6lu2zns63eelv"; let query = "terra1e8lqmv3egtgps9nux04vw8gd4pr3qp9h00y7um"; - let response: AllAccountsResponse = app - .wrap() - .query_wasm_smart( - contract_addr, - &Cw20QueryMsg::AllAccounts { - start_after: Some(query.to_string()), - limit: Some(30), - }, - ) - .unwrap(); + let response: AllAccountsResponse = app.wrap().query_wasm_smart( + contract_addr, + &Cw20QueryMsg::AllAccounts { + start_after: Some(query.to_string()), + limit: Some(30), + }, + )?; log::info!("Before transfer : {:?}", response); // We execute a transfer @@ -54,19 +63,17 @@ pub fn main() { amount: 1_000_000u128.into(), }, &[], - ) - .unwrap(); + )?; // We query to verify the state changed - let response: AllAccountsResponse = app - .wrap() - .query_wasm_smart( - contract_addr, - &Cw20QueryMsg::AllAccounts { - start_after: Some(query.to_string()), - limit: Some(30), - }, - ) - .unwrap(); + let response: AllAccountsResponse = app.wrap().query_wasm_smart( + contract_addr, + &Cw20QueryMsg::AllAccounts { + start_after: Some(query.to_string()), + limit: Some(30), + }, + )?; log::info!("After transfer : {:?}", response); + + Ok(()) } diff --git a/src/app.rs b/src/app.rs index c1c32a62..71271d08 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,7 +1,7 @@ use crate::wasm_emulation::api::RealApi; +use crate::wasm_emulation::channel::RemoteChannel; use cosmwasm_std::CustomMsg; use cw_storage_plus::Item; -use ibc_chain_registry::chain::ChainData; use std::fmt::Debug; use std::marker::PhantomData; @@ -68,25 +68,12 @@ pub struct App< api: Api, storage: Storage, block: BlockInfo, - pub chain: Option, -} - -fn no_init( - _: &mut Router, - _: &dyn Api, - _: &mut dyn Storage, -) { -} - -impl Default for BasicApp { - fn default() -> Self { - Self::new(no_init) - } + pub remote: RemoteChannel, } impl BasicApp { /// Creates new default `App` implementation working with Empty custom messages. - pub fn new(init_fn: F) -> Self + pub fn new(remote: RemoteChannel, init_fn: F) -> AnyResult where F: FnOnce( &mut Router< @@ -102,13 +89,16 @@ impl BasicApp { &mut dyn Storage, ), { - AppBuilder::new().build(init_fn) + AppBuilder::new().with_remote(remote).build(init_fn) } } /// Creates new default `App` implementation working with customized exec and query messages. /// Outside of `App` implementation to make type elision better. -pub fn custom_app(init_fn: F) -> BasicApp +pub fn custom_app( + remote: RemoteChannel, + init_fn: F, +) -> AnyResult> where ExecC: CustomMsg + DeserializeOwned + 'static, QueryC: Debug + CustomQuery + DeserializeOwned + 'static, @@ -126,7 +116,7 @@ where &mut dyn Storage, ), { - AppBuilder::new_custom().build(init_fn) + AppBuilder::new_custom().with_remote(remote).build(init_fn) } impl Querier @@ -199,7 +189,7 @@ pub struct AppBuilder, + remote: Option, } impl Default @@ -246,7 +236,7 @@ impl distribution: DistributionKeeper::new(), ibc: FailingModule::new(), gov: FailingModule::new(), - chain: None, + remote: None, } } } @@ -281,7 +271,7 @@ where distribution: DistributionKeeper::new(), ibc: FailingModule::new(), gov: FailingModule::new(), - chain: None, + remote: None, } } } @@ -312,7 +302,7 @@ impl distribution, ibc, gov, - chain, + remote, .. } = self; @@ -327,7 +317,7 @@ impl distribution, ibc, gov, - chain, + remote, } } @@ -346,7 +336,7 @@ impl distribution, ibc, gov, - chain, + remote, .. } = self; @@ -361,7 +351,7 @@ impl distribution, ibc, gov, - chain, + remote, } } @@ -380,7 +370,7 @@ impl distribution, ibc, gov, - chain, + remote, .. } = self; @@ -395,7 +385,7 @@ impl distribution, ibc, gov, - chain, + remote, } } @@ -414,7 +404,7 @@ impl distribution, ibc, gov, - chain, + remote, .. } = self; @@ -429,7 +419,7 @@ impl distribution, ibc, gov, - chain, + remote, } } @@ -456,7 +446,7 @@ impl distribution, ibc, gov, - chain, + remote, .. } = self; @@ -471,7 +461,7 @@ impl distribution, ibc, gov, - chain, + remote, } } @@ -490,7 +480,7 @@ impl distribution, ibc, gov, - chain, + remote, .. } = self; @@ -505,7 +495,7 @@ impl distribution, ibc, gov, - chain, + remote, } } @@ -525,7 +515,7 @@ impl bank, ibc, gov, - chain, + remote, .. } = self; @@ -540,7 +530,7 @@ impl distribution, ibc, gov, - chain, + remote, } } @@ -562,7 +552,7 @@ impl bank, distribution, gov, - chain, + remote, .. } = self; @@ -577,7 +567,7 @@ impl distribution, ibc, gov, - chain, + remote, } } @@ -596,7 +586,7 @@ impl bank, distribution, ibc, - chain, + remote, .. } = self; @@ -611,13 +601,13 @@ impl distribution, ibc, gov, - chain, + remote, } } /// Sets the chain of the app - pub fn with_chain( + pub fn with_remote( self, - chain: ChainData, + remote: RemoteChannel, ) -> AppBuilder { let AppBuilder { wasm, @@ -643,7 +633,7 @@ impl staking, distribution, ibc, - chain: Some(chain), + remote: Some(remote), gov, } } @@ -660,7 +650,7 @@ impl pub fn build( self, init_fn: F, - ) -> App + ) -> AnyResult> where BankT: Bank, ApiT: Api, @@ -692,10 +682,10 @@ impl api: self.api, block: self.block, storage: self.storage, - chain: self.chain, + remote: self.remote.unwrap(), }; app.init_modules(init_fn); - app + Ok(app) } } @@ -884,12 +874,14 @@ where /// Returns a new account address pub fn next_address(&mut self) -> Addr { - let Self { storage, chain, .. } = self; + let Self { + storage, remote, .. + } = self; let mut addresses = ADDRESSES.may_load(storage).unwrap().unwrap_or(vec![]); let new_address = - RealApi::new(&chain.clone().unwrap().bech32_prefix).next_address(addresses.len()); + RealApi::new(&remote.chain.bech32_prefix.clone()).next_address(addresses.len()); addresses.push(new_address.clone()); ADDRESSES.save(storage, &addresses).unwrap(); diff --git a/src/bank.rs b/src/bank.rs index f3b93b8c..e5d9d15e 100644 --- a/src/bank.rs +++ b/src/bank.rs @@ -1,11 +1,7 @@ use crate::wasm_emulation::input::BankStorage; use cw_orch_daemon::queriers::DaemonQuerier; -use tokio::runtime::Runtime; -use tonic::transport::Channel; use std::str::FromStr; -use ibc_chain_registry::chain::ChainData; - use anyhow::{bail, Result as AnyResult}; use itertools::Itertools; use schemars::JsonSchema; @@ -22,7 +18,7 @@ use crate::executor::AppResponse; use crate::module::Module; use crate::prefixed_storage::{prefixed, prefixed_read}; -use crate::wasm_emulation::channel::get_channel; +use crate::wasm_emulation::channel::RemoteChannel; use crate::wasm_emulation::query::AllQuerier; const BALANCES: Map<&Addr, NativeBalance> = Map::new("balances"); @@ -39,22 +35,18 @@ pub enum BankSudo { pub trait Bank: Module + AllQuerier {} +#[derive(Default)] pub struct BankKeeper { - rt: Runtime, - channel: Option + remote: Option, } impl BankKeeper { pub fn new() -> Self { - BankKeeper{ - rt: Runtime::new().unwrap(), - channel: None - } + BankKeeper::default() } - pub fn set_chain(&mut self, chain: ChainData) { - let channel = get_channel(chain, &self.rt).unwrap(); - self.channel = Some(channel); + pub fn set_remote(&mut self, remote: RemoteChannel) { + self.remote = Some(remote); } // this is an "admin" function to let us adjust bank accounts in genesis @@ -85,9 +77,13 @@ impl BankKeeper { fn get_balance(&self, bank_storage: &dyn Storage, account: &Addr) -> AnyResult> { // If there is no balance present, we query it on the distant chain if !BALANCES.has(bank_storage, account) { - let channel = self.channel.clone().unwrap(); + let channel = self.remote.clone().unwrap().channel; let querier = cw_orch_daemon::queriers::Bank::new(channel); - let distant_amounts: Vec = self.rt + let distant_amounts: Vec = self + .remote + .clone() + .unwrap() + .rt .block_on(querier.balance(account, None)) .map(|result| { result diff --git a/src/contracts.rs b/src/contracts.rs index 76f3d6e2..70a0c859 100644 --- a/src/contracts.rs +++ b/src/contracts.rs @@ -11,6 +11,8 @@ use cosmwasm_std::{ use anyhow::{anyhow, bail, Result as AnyResult}; +use crate::wasm_emulation::channel::RemoteChannel; + /// Interface to call into a [Contract]. pub trait Contract where @@ -23,6 +25,7 @@ where env: Env, info: MessageInfo, msg: Vec, + remote: RemoteChannel, ) -> AnyResult>; fn instantiate( @@ -31,28 +34,63 @@ where env: Env, info: MessageInfo, msg: Vec, + remote: RemoteChannel, ) -> AnyResult>; - fn query(&self, deps: Deps, env: Env, msg: Vec) -> AnyResult; + fn query( + &self, + deps: Deps, + env: Env, + msg: Vec, + remote: RemoteChannel, + ) -> AnyResult; - fn sudo(&self, deps: DepsMut, env: Env, msg: Vec) -> AnyResult>; + fn sudo( + &self, + deps: DepsMut, + env: Env, + msg: Vec, + remote: RemoteChannel, + ) -> AnyResult>; - fn reply(&self, deps: DepsMut, env: Env, msg: Reply) -> AnyResult>; + fn reply( + &self, + deps: DepsMut, + env: Env, + msg: Reply, + remote: RemoteChannel, + ) -> AnyResult>; - fn migrate(&self, deps: DepsMut, env: Env, msg: Vec) -> AnyResult>; + fn migrate( + &self, + deps: DepsMut, + env: Env, + msg: Vec, + remote: RemoteChannel, + ) -> AnyResult>; } -type ContractFn = - fn(deps: DepsMut, env: Env, info: MessageInfo, msg: T) -> Result, E>; -type PermissionedFn = fn(deps: DepsMut, env: Env, msg: T) -> Result, E>; -type ReplyFn = fn(deps: DepsMut, env: Env, msg: Reply) -> Result, E>; -type QueryFn = fn(deps: Deps, env: Env, msg: T) -> Result; +type ContractFn = fn( + deps: DepsMut, + env: Env, + info: MessageInfo, + msg: T, + remote: RemoteChannel, +) -> Result, E>; +type PermissionedFn = + fn(deps: DepsMut, env: Env, msg: T, remote: RemoteChannel) -> Result, E>; +type ReplyFn = + fn(deps: DepsMut, env: Env, msg: Reply, remote: RemoteChannel) -> Result, E>; +type QueryFn = + fn(deps: Deps, env: Env, msg: T, remote: RemoteChannel) -> Result; type ContractClosure = - Box, Env, MessageInfo, T) -> Result, E>>; -type PermissionedClosure = Box, Env, T) -> Result, E>>; -type ReplyClosure = Box, Env, Reply) -> Result, E>>; -type QueryClosure = Box, Env, T) -> Result>; + Box, Env, MessageInfo, T, RemoteChannel) -> Result, E>>; +type PermissionedClosure = + Box, Env, T, RemoteChannel) -> Result, E>>; +type ReplyClosure = + Box, Env, Reply, RemoteChannel) -> Result, E>>; +type QueryClosure = Box, Env, T, RemoteChannel) -> Result>; /// Wraps the exported functions from a contract and provides the normalized format /// Place T4 and E4 at the end, as we just want default placeholders for most contracts that don't have sudo @@ -272,10 +310,11 @@ where let customized = move |mut deps: DepsMut, env: Env, info: MessageInfo, - msg: T| + msg: T, + remote: RemoteChannel| -> Result, E> { let deps = decustomize_deps_mut(&mut deps); - raw_fn(deps, env, info, msg).map(customize_response::) + raw_fn(deps, env, info, msg, remote).map(customize_response::) }; Box::new(customized) } @@ -286,10 +325,11 @@ where E: Display + Debug + Send + Sync + 'static, Q: CustomQuery + DeserializeOwned + 'static, { - let customized = move |deps: Deps, env: Env, msg: T| -> Result { - let deps = decustomize_deps(&deps); - raw_fn(deps, env, msg) - }; + let customized = + move |deps: Deps, env: Env, msg: T, remote: RemoteChannel| -> Result { + let deps = decustomize_deps(&deps); + raw_fn(deps, env, msg, remote) + }; Box::new(customized) } @@ -324,8 +364,12 @@ where C: Clone + fmt::Debug + PartialEq + JsonSchema + 'static, Q: CustomQuery + DeserializeOwned + 'static, { - let customized = move |deps: DepsMut, env: Env, msg: T| -> Result, E> { - raw_fn(deps, env, msg).map(customize_response::) + let customized = move |deps: DepsMut, + env: Env, + msg: T, + remote: RemoteChannel| + -> Result, E> { + raw_fn(deps, env, msg, remote).map(customize_response::) }; Box::new(customized) } @@ -388,9 +432,10 @@ where env: Env, info: MessageInfo, msg: Vec, + remote: RemoteChannel, ) -> AnyResult> { let msg: T1 = from_slice(&msg)?; - (self.execute_fn)(deps, env, info, msg).map_err(|err| anyhow!(err)) + (self.execute_fn)(deps, env, info, msg, remote).map_err(|err| anyhow!(err)) } fn instantiate( @@ -399,38 +444,63 @@ where env: Env, info: MessageInfo, msg: Vec, + remote: RemoteChannel, ) -> AnyResult> { let msg: T2 = from_slice(&msg)?; - (self.instantiate_fn)(deps, env, info, msg).map_err(|err| anyhow!(err)) + (self.instantiate_fn)(deps, env, info, msg, remote).map_err(|err| anyhow!(err)) } - fn query(&self, deps: Deps, env: Env, msg: Vec) -> AnyResult { + fn query( + &self, + deps: Deps, + env: Env, + msg: Vec, + remote: RemoteChannel, + ) -> AnyResult { let msg: T3 = from_slice(&msg)?; - (self.query_fn)(deps, env, msg).map_err(|err| anyhow!(err)) + (self.query_fn)(deps, env, msg, remote).map_err(|err| anyhow!(err)) } // this returns an error if the contract doesn't implement sudo - fn sudo(&self, deps: DepsMut, env: Env, msg: Vec) -> AnyResult> { + fn sudo( + &self, + deps: DepsMut, + env: Env, + msg: Vec, + remote: RemoteChannel, + ) -> AnyResult> { let msg = from_slice(&msg)?; match &self.sudo_fn { - Some(sudo) => sudo(deps, env, msg).map_err(|err| anyhow!(err)), + Some(sudo) => sudo(deps, env, msg, remote).map_err(|err| anyhow!(err)), None => bail!("sudo not implemented for contract"), } } // this returns an error if the contract doesn't implement reply - fn reply(&self, deps: DepsMut, env: Env, reply_data: Reply) -> AnyResult> { + fn reply( + &self, + deps: DepsMut, + env: Env, + reply_data: Reply, + remote: RemoteChannel, + ) -> AnyResult> { match &self.reply_fn { - Some(reply) => reply(deps, env, reply_data).map_err(|err| anyhow!(err)), + Some(reply) => reply(deps, env, reply_data, remote).map_err(|err| anyhow!(err)), None => bail!("reply not implemented for contract"), } } // this returns an error if the contract doesn't implement migrate - fn migrate(&self, deps: DepsMut, env: Env, msg: Vec) -> AnyResult> { + fn migrate( + &self, + deps: DepsMut, + env: Env, + msg: Vec, + remote: RemoteChannel, + ) -> AnyResult> { let msg = from_slice(&msg)?; match &self.migrate_fn { - Some(migrate) => migrate(deps, env, msg).map_err(|err| anyhow!(err)), + Some(migrate) => migrate(deps, env, msg, remote).map_err(|err| anyhow!(err)), None => bail!("migrate not implemented for contract"), } } diff --git a/src/wasm.rs b/src/wasm.rs index 92a705df..fa80dae7 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -1,12 +1,10 @@ use crate::prefixed_storage::contract_namespace; use crate::wasm_emulation::api::RealApi; +use crate::wasm_emulation::channel::RemoteChannel; use cosmwasm_std::CustomMsg; use cw_orch_daemon::queriers::CosmWasm; use cw_orch_daemon::queriers::DaemonQuerier; -use ibc_chain_registry::chain::ChainData; -use tokio::runtime::Runtime; - use std::collections::HashMap; use std::fmt::Debug; @@ -36,9 +34,8 @@ use anyhow::{bail, Context, Result as AnyResult}; #[cfg(feature = "cosmwasm_1_2")] use sha2::{Digest, Sha256}; -use crate::wasm_emulation::channel::get_channel; use crate::wasm_emulation::contract::WasmContract; -use crate::wasm_emulation::input::{SerChainData, WasmStorage}; +use crate::wasm_emulation::input::WasmStorage; use crate::wasm_emulation::query::AllQuerier; // Contract state is kept in Storage, separate from the contracts themselves @@ -141,8 +138,7 @@ pub struct WasmKeeper { generator: Box, // chain on which the contract should be queried/tested against - chain: Option, - rt: Runtime + remote: Option, } pub trait AddressGenerator { @@ -176,8 +172,7 @@ impl Default for WasmKeeper { _e: std::marker::PhantomData, _q: std::marker::PhantomData, generator: Box::new(SimpleAddressGenerator()), - chain: None, - rt: Runtime::new().unwrap() + remote: None, } } } @@ -355,26 +350,19 @@ impl WasmKeeper { if let Some(code) = code { return code.clone(); } else { - return WasmContract::new_distant_code_id( - handler.code_id.try_into().unwrap(), - self.chain.clone().unwrap(), - ); + return WasmContract::new_distant_code_id(handler.code_id); } } - WasmContract::new_distant_contract(address.to_string(), self.chain.clone().unwrap()) + WasmContract::new_distant_contract(address.to_string()) } - pub fn load_distant_contract( - chain: impl Into, - address: &Addr, - rt: &Runtime - ) -> AnyResult { - let channel = get_channel(chain, &rt)?; - - let wasm_querier = CosmWasm::new(channel); + pub fn load_distant_contract(remote: RemoteChannel, address: &Addr) -> AnyResult { + let wasm_querier = CosmWasm::new(remote.channel); - let code_info = rt.block_on(wasm_querier.contract_info(address.clone()))?; + let code_info = remote + .rt + .block_on(wasm_querier.contract_info(address.clone()))?; Ok(ContractData { admin: { @@ -383,7 +371,7 @@ impl WasmKeeper { a => Some(Addr::unchecked(a)), } }, - code_id: code_info.code_id.try_into()?, + code_id: code_info.code_id, created: code_info.created.unwrap().block_height, creator: Addr::unchecked(code_info.creator), label: code_info.label, @@ -396,7 +384,8 @@ impl WasmKeeper { return Ok(local_contract); } - Self::load_distant_contract(self.chain.clone().unwrap(), address, &self.rt) + let remote_channel = self.remote.clone().unwrap(); + Self::load_distant_contract(remote_channel, address) } pub fn dump_wasm_raw(&self, storage: &dyn Storage, address: &Addr) -> Vec { @@ -484,8 +473,8 @@ where } } - pub fn set_chain(&mut self, chain: ChainData) { - self.chain = Some(chain); + pub fn set_remote(&mut self, remote: RemoteChannel) { + self.remote = Some(remote); } pub fn query_smart( @@ -504,7 +493,13 @@ where block, address, |handler, deps, env| { - >::query(&handler, deps, env, msg) + >::query( + &handler, + deps, + env, + msg, + self.remote.clone().unwrap(), + ) }, ) } @@ -896,7 +891,7 @@ where ) -> AnyResult { let addr = self .generator - .next_contract_address(storage, self.chain.clone().map(|c| c.bech32_prefix)); + .next_contract_address(storage, self.remote.clone().map(|c| c.chain.bech32_prefix)); let info = ContractData { code_id, @@ -925,7 +920,9 @@ where router, block, address, - |contract, deps, env| contract.execute(deps, env, info, msg), + |contract, deps, env| { + contract.execute(deps, env, info, msg, self.remote.clone().unwrap()) + }, )?) } @@ -945,7 +942,9 @@ where router, block, address, - |contract, deps, env| contract.instantiate(deps, env, info, msg), + |contract, deps, env| { + contract.instantiate(deps, env, info, msg, self.remote.clone().unwrap()) + }, )?) } @@ -964,7 +963,7 @@ where router, block, address, - |contract, deps, env| contract.reply(deps, env, reply), + |contract, deps, env| contract.reply(deps, env, reply, self.remote.clone().unwrap()), )?) } @@ -983,7 +982,7 @@ where router, block, address, - |contract, deps, env| contract.sudo(deps, env, msg), + |contract, deps, env| contract.sudo(deps, env, msg, self.remote.clone().unwrap()), )?) } @@ -1002,7 +1001,7 @@ where router, block, address, - |contract, deps, env| contract.migrate(deps, env, msg), + |contract, deps, env| contract.migrate(deps, env, msg, self.remote.clone().unwrap()), )?) } diff --git a/src/wasm_emulation/channel.rs b/src/wasm_emulation/channel.rs index 46ffb31a..c23504cc 100644 --- a/src/wasm_emulation/channel.rs +++ b/src/wasm_emulation/channel.rs @@ -1,22 +1,30 @@ -use crate::wasm_emulation::input::SerChainData; use anyhow::Result as AnyResult; use cw_orch_daemon::GrpcChannel; -use tokio::runtime::Runtime; +use ibc_chain_registry::chain::ChainData; +use tokio::runtime::{Handle, Runtime}; use tonic::transport::Channel; -pub fn get_rt_and_channel(chain: impl Into) -> AnyResult<(Runtime, Channel)> { - let rt = Runtime::new()?; +fn get_channel(chain: impl Into, rt: Handle) -> AnyResult { let chain = chain.into(); - // We create an instance from a code_id, an address, and we run the code in it let channel = rt.block_on(GrpcChannel::connect(&chain.apis.grpc, &chain.chain_id))?; - - Ok((rt, channel)) + Ok(channel) } -pub fn get_channel(chain: impl Into, rt: &Runtime) -> AnyResult { - let chain = chain.into(); - // We create an instance from a code_id, an address, and we run the code in it - let channel = rt.block_on(GrpcChannel::connect(&chain.apis.grpc, &chain.chain_id))?; +#[derive(Clone)] +pub struct RemoteChannel { + pub rt: Handle, + pub channel: Channel, + pub chain: ChainData, +} - Ok(channel) +impl RemoteChannel { + pub fn new(rt: &Runtime, chain: impl Into) -> AnyResult { + let chain = chain.into(); + let channel = get_channel(chain.clone(), rt.handle().clone())?; + Ok(Self { + rt: rt.handle().clone(), + channel, + chain, + }) + } } diff --git a/src/wasm_emulation/contract.rs b/src/wasm_emulation/contract.rs index 9e7a77c6..601ac344 100644 --- a/src/wasm_emulation/contract.rs +++ b/src/wasm_emulation/contract.rs @@ -1,7 +1,6 @@ use crate::wasm_emulation::api::RealApi; use crate::wasm_emulation::input::get_querier_storage; use crate::wasm_emulation::input::ReplyArgs; -use crate::wasm_emulation::input::SerChainData; use crate::wasm_emulation::output::StorageChanges; use crate::wasm_emulation::query::MockQuerier; use crate::wasm_emulation::storage::DualStorage; @@ -44,8 +43,7 @@ use cosmwasm_std::{Binary, CustomQuery, Deps, DepsMut, Env, MessageInfo, Reply, use anyhow::Result as AnyResult; -use super::channel::get_channel; -use super::channel::get_rt_and_channel; +use super::channel::RemoteChannel; use super::input::ExecuteArgs; use super::input::InstantiateArgs; use super::input::MigrateArgs; @@ -77,19 +75,16 @@ const DEFAULT_PRINT_DEBUG: bool = true; #[derive(Serialize, Deserialize, Debug, Clone)] pub struct DistantContract { pub contract_addr: String, - pub chain: SerChainData, } #[derive(Serialize, Deserialize, Debug, Clone)] pub struct DistantCodeId { pub code_id: u64, - pub chain: SerChainData, } #[derive(Serialize, Deserialize, Clone)] pub struct LocalContract { pub code: Vec, - pub chain: SerChainData, } #[derive(Serialize, Deserialize, Debug, Clone)] @@ -103,15 +98,14 @@ impl std::fmt::Debug for LocalContract { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { write!( f, - "LocalContract {{ checksum: {}, chain: {:?} }}", + "LocalContract {{ checksum: {} }}", Checksum::generate(&self.code), - self.chain ) } } impl WasmContract { - pub fn new_local(code: Vec, chain: impl Into) -> Self { + pub fn new_local(code: Vec) -> Self { check_wasm( &code, &HashSet::from([ @@ -121,53 +115,35 @@ impl WasmContract { ]), ) .unwrap(); - Self::Local(LocalContract { - code, - chain: chain.into(), - }) + Self::Local(LocalContract { code }) } - pub fn new_distant_contract(contract_addr: String, chain: impl Into) -> Self { - Self::DistantContract(DistantContract { - contract_addr, - chain: chain.into(), - }) + pub fn new_distant_contract(contract_addr: String) -> Self { + Self::DistantContract(DistantContract { contract_addr }) } - pub fn new_distant_code_id(code_id: u64, chain: impl Into) -> Self { - Self::DistantCodeId(DistantCodeId { - code_id, - chain: chain.into(), - }) + pub fn new_distant_code_id(code_id: u64) -> Self { + Self::DistantCodeId(DistantCodeId { code_id }) } - pub fn get_chain(&self) -> SerChainData { - match self { - WasmContract::Local(LocalContract { chain, .. }) => chain.clone(), - WasmContract::DistantContract(DistantContract { chain, .. }) => chain.clone(), - WasmContract::DistantCodeId(DistantCodeId { chain, .. }) => chain.clone(), - } - } - - pub fn get_code(&self) -> AnyResult> { + pub fn get_code(&self, remote: RemoteChannel) -> AnyResult> { match self { WasmContract::Local(LocalContract { code, .. }) => Ok(code.clone()), - WasmContract::DistantContract(DistantContract { - chain, - contract_addr, - }) => { - let (rt, channel) = get_rt_and_channel(chain.clone())?; - let wasm_querier = CosmWasm::new(channel); - - let code_info = rt.block_on(wasm_querier.contract_info(contract_addr))?; - let code = rt.block_on(wasm_querier.code_data(code_info.code_id))?; + WasmContract::DistantContract(DistantContract { contract_addr }) => { + let wasm_querier = CosmWasm::new(remote.channel); + + let code_info = remote + .rt + .block_on(wasm_querier.contract_info(contract_addr))?; + let code = remote + .rt + .block_on(wasm_querier.code_data(code_info.code_id))?; Ok(code) } - WasmContract::DistantCodeId(DistantCodeId { chain, code_id }) => { - let (rt, channel) = get_rt_and_channel(chain.clone())?; - let wasm_querier = CosmWasm::new(channel); + WasmContract::DistantCodeId(DistantCodeId { code_id }) => { + let wasm_querier = CosmWasm::new(remote.channel); - let code = rt.block_on(wasm_querier.code_data(*code_id))?; + let code = remote.rt.block_on(wasm_querier.code_data(*code_id))?; Ok(code) } } @@ -176,23 +152,23 @@ impl WasmContract { pub fn run_contract( &self, args: InstanceArguments, + remote: RemoteChannel, ) -> AnyResult> { let InstanceArguments { function, init_storage, querier_storage, } = args; - let chain: SerChainData = self.get_chain(); let address = function.get_address(); - let code = self.get_code()?; + let code = self.get_code(remote.clone())?; - let api = RealApi::new(&chain.bech32_prefix); + let api = RealApi::new(&remote.chain.bech32_prefix); // We create the backend here from outside information; let backend = Backend { api, - storage: DualStorage::new(chain.clone(), address.to_string(), Some(init_storage))?, - querier: MockQuerier::::new(chain, Some(querier_storage)), + storage: DualStorage::new(remote.clone(), address.to_string(), Some(init_storage))?, + querier: MockQuerier::::new(remote, Some(querier_storage)), }; let options = InstanceOptions { gas_limit: DEFAULT_GAS_LIMIT, @@ -248,12 +224,11 @@ where fn execute( &self, deps: DepsMut, - mut env: Env, + env: Env, info: MessageInfo, msg: Vec, + remote: RemoteChannel, ) -> AnyResult> { - env.block.chain_id = self.get_chain().chain_id.to_string(); - // We start by building the dependencies we will pass through the wasm executer let execute_args = InstanceArguments { function: WasmFunction::Execute(ExecuteArgs { env, info, msg }), @@ -261,7 +236,7 @@ where querier_storage: get_querier_storage(&deps.querier)?, }; - let decoded_result = self.run_contract(execute_args)?; + let decoded_result = self.run_contract(execute_args, remote)?; apply_storage_changes(deps.storage, &decoded_result); self.after_execution_callback(&decoded_result); @@ -275,11 +250,11 @@ where fn instantiate( &self, deps: DepsMut, - mut env: Env, + env: Env, info: MessageInfo, msg: Vec, + remote: RemoteChannel, ) -> AnyResult> { - env.block.chain_id = self.get_chain().chain_id.to_string(); // We start by building the dependencies we will pass through the wasm executer let instantiate_arguments = InstanceArguments { function: WasmFunction::Instantiate(InstantiateArgs { env, info, msg }), @@ -287,7 +262,7 @@ where querier_storage: get_querier_storage(&deps.querier)?, }; - let decoded_result = self.run_contract(instantiate_arguments)?; + let decoded_result = self.run_contract(instantiate_arguments, remote)?; apply_storage_changes(deps.storage, &decoded_result); self.after_execution_callback(&decoded_result); @@ -298,9 +273,13 @@ where } } - fn query(&self, deps: Deps, mut env: Env, msg: Vec) -> AnyResult { - env.block.chain_id = self.get_chain().chain_id.to_string(); - + fn query( + &self, + deps: Deps, + env: Env, + msg: Vec, + remote: RemoteChannel, + ) -> AnyResult { // We start by building the dependencies we will pass through the wasm executer let query_arguments = InstanceArguments { function: WasmFunction::Query(QueryArgs { env, msg }), @@ -308,7 +287,7 @@ where querier_storage: get_querier_storage(&deps.querier)?, }; - let decoded_result: WasmRunnerOutput = self.run_contract(query_arguments)?; + let decoded_result: WasmRunnerOutput = self.run_contract(query_arguments, remote)?; self.after_execution_callback(&decoded_result); @@ -322,17 +301,17 @@ where fn sudo( &self, deps: DepsMut, - mut env: Env, + env: Env, msg: Vec, + remote: RemoteChannel, ) -> AnyResult> { - env.block.chain_id = self.get_chain().chain_id.to_string(); let sudo_args = InstanceArguments { function: WasmFunction::Sudo(SudoArgs { env, msg }), init_storage: deps.storage.range(None, None, Order::Ascending).collect(), querier_storage: get_querier_storage(&deps.querier)?, }; - let decoded_result = self.run_contract(sudo_args)?; + let decoded_result = self.run_contract(sudo_args, remote)?; apply_storage_changes(deps.storage, &decoded_result); self.after_execution_callback(&decoded_result); @@ -347,17 +326,17 @@ where fn reply( &self, deps: DepsMut, - mut env: Env, + env: Env, reply: Reply, + remote: RemoteChannel, ) -> AnyResult> { - env.block.chain_id = self.get_chain().chain_id.to_string(); let reply_args = InstanceArguments { function: WasmFunction::Reply(ReplyArgs { env, reply }), init_storage: deps.storage.range(None, None, Order::Ascending).collect(), querier_storage: get_querier_storage(&deps.querier)?, }; - let decoded_result = self.run_contract(reply_args)?; + let decoded_result = self.run_contract(reply_args, remote)?; apply_storage_changes(deps.storage, &decoded_result); self.after_execution_callback(&decoded_result); @@ -372,17 +351,17 @@ where fn migrate( &self, deps: DepsMut, - mut env: Env, + env: Env, msg: Vec, + remote: RemoteChannel, ) -> AnyResult> { - env.block.chain_id = self.get_chain().chain_id.to_string(); let migrate_args = InstanceArguments { function: WasmFunction::Migrate(MigrateArgs { env, msg }), init_storage: deps.storage.range(None, None, Order::Ascending).collect(), querier_storage: get_querier_storage(&deps.querier)?, }; - let decoded_result = self.run_contract(migrate_args)?; + let decoded_result = self.run_contract(migrate_args, remote)?; apply_storage_changes(deps.storage, &decoded_result); self.after_execution_callback(&decoded_result); diff --git a/src/wasm_emulation/input.rs b/src/wasm_emulation/input.rs index b2f3ad8e..b5a880ee 100644 --- a/src/wasm_emulation/input.rs +++ b/src/wasm_emulation/input.rs @@ -1,7 +1,6 @@ use std::collections::HashMap; use anyhow::Result as AnyResult; -use cw_orch_networks::ChainInfo; use serde::{Deserialize, Serialize}; use cosmwasm_std::Addr; @@ -12,9 +11,6 @@ use cosmwasm_std::QueryRequest; use cosmwasm_std::{Env, MessageInfo, Reply}; use cw_utils::NativeBalance; -use ibc_chain_registry::chain::Apis; -use ibc_chain_registry::chain::ChainData; -use ibc_relayer_types::core::ics24_host::identifier::ChainId; use crate::bank::BankKeeper; use crate::prefixed_storage::get_full_contract_storage_namespace; @@ -23,36 +19,6 @@ use crate::wasm::ContractData; use super::contract::WasmContract; use super::query::AllQuerier; -#[derive(Serialize, Deserialize, Clone)] -pub struct SerChainData { - pub chain_id: ChainId, - pub apis: Apis, - pub bech32_prefix: String, -} - -impl std::fmt::Debug for SerChainData { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { - write!(f, "Chain {{ chain_id: {:?} }}", self.chain_id) - } -} - -impl From for SerChainData { - fn from(c: ChainData) -> SerChainData { - Self { - chain_id: c.chain_id, - apis: c.apis, - bech32_prefix: c.bech32_prefix, - } - } -} - -impl<'c> From> for SerChainData { - fn from(c: ChainInfo) -> SerChainData { - let chain_data: ChainData = c.into(); - chain_data.into() - } -} - #[derive(Serialize, Deserialize, Debug, Clone, Default)] pub struct WasmStorage { pub contracts: HashMap, diff --git a/src/wasm_emulation/query/bank.rs b/src/wasm_emulation/query/bank.rs index b1e7458a..885c26bd 100644 --- a/src/wasm_emulation/query/bank.rs +++ b/src/wasm_emulation/query/bank.rs @@ -1,9 +1,8 @@ -use crate::wasm_emulation::input::SerChainData; +use crate::wasm_emulation::channel::RemoteChannel; use crate::wasm_emulation::query::gas::{GAS_COST_ALL_BALANCE_QUERY, GAS_COST_BALANCE_QUERY}; use crate::wasm_emulation::query::mock_querier::QueryResultWithGas; use cosmwasm_std::Addr; use cosmwasm_vm::GasInfo; -use tokio::runtime::Runtime; use std::str::FromStr; use cw_orch_daemon::queriers::DaemonQuerier; @@ -21,8 +20,6 @@ use cosmwasm_std::{AllBalanceResponse, BalanceResponse, BankQuery}; use cosmwasm_std::to_binary; use cosmwasm_std::{ContractResult, SystemResult}; -use crate::wasm_emulation::channel::get_channel; - #[derive(Clone)] pub struct BankQuerier { #[allow(dead_code)] @@ -30,12 +27,11 @@ pub struct BankQuerier { supplies: HashMap, /// HashMap balances: HashMap>, - chain: SerChainData, + remote: RemoteChannel, } impl BankQuerier { - pub fn new(chain: impl Into, init: Option>) -> Self { - let chain = chain.into(); + pub fn new(remote: RemoteChannel, init: Option>) -> Self { let balances: HashMap<_, _> = init .unwrap_or(vec![]) .iter() @@ -45,7 +41,7 @@ impl BankQuerier { BankQuerier { supplies: Self::calculate_supplies(&balances), balances, - chain, + remote, } } @@ -74,7 +70,7 @@ impl BankQuerier { supplies } - pub fn query(&self, rt: &Runtime, request: &BankQuery) -> QueryResultWithGas { + pub fn query(&self, request: &BankQuery) -> QueryResultWithGas { let contract_result: ContractResult = match request { BankQuery::Balance { address, denom } => { // proper error on not found, serialize result on found @@ -85,10 +81,11 @@ impl BankQuerier { // If the amount is not available, we query it from the distant chain if amount.is_none() { - let channel = get_channel(self.chain.clone(), &rt).unwrap(); - let querier = Bank::new(channel); + let querier = Bank::new(self.remote.channel.clone()); - let query_result = rt + let query_result = self + .remote + .rt .block_on(querier.balance(address, Some(denom.clone()))) .map(|result| Uint128::from_str(&result[0].amount).unwrap()); @@ -111,10 +108,12 @@ impl BankQuerier { // We query only if the bank balance doesn't exist if amount.is_none() { - let channel = get_channel(self.chain.clone(), rt).unwrap(); - let querier = Bank::new(channel); - let query_result: Result, _> = - rt.block_on(querier.balance(address, None)).map(|result| { + let querier = Bank::new(self.remote.channel.clone()); + let query_result: Result, _> = self + .remote + .rt + .block_on(querier.balance(address, None)) + .map(|result| { result .into_iter() .map(|c| Coin { diff --git a/src/wasm_emulation/query/mock_querier.rs b/src/wasm_emulation/query/mock_querier.rs index ef024d44..4db6934f 100644 --- a/src/wasm_emulation/query/mock_querier.rs +++ b/src/wasm_emulation/query/mock_querier.rs @@ -1,4 +1,4 @@ -use crate::wasm_emulation::input::SerChainData; +use crate::wasm_emulation::channel::RemoteChannel; use crate::wasm_emulation::query::bank::BankQuerier; use crate::wasm_emulation::query::staking::StakingQuerier; use crate::wasm_emulation::query::wasm::WasmQuerier; @@ -20,7 +20,6 @@ use cosmwasm_std::{FullDelegation, Validator}; use cosmwasm_std::Attribute; use cosmwasm_std::QuerierResult; -use tokio::runtime::Runtime; use crate::wasm_emulation::input::QuerierStorage; @@ -44,20 +43,19 @@ pub struct MockQuerier { /// /// Use box to avoid the need of another generic type custom_handler: Box Fn(&'a C) -> QueryResultWithGas>, - rt: Runtime + remote: RemoteChannel, } impl MockQuerier { - pub fn new(chain: impl Into, storage: Option) -> Self { - let chain = chain.into(); + pub fn new(remote: RemoteChannel, storage: Option) -> Self { MockQuerier { bank: BankQuerier::new( - chain.clone(), + remote.clone(), storage.as_ref().map(|storage| storage.bank.storage.clone()), ), staking: StakingQuerier::default(), - wasm: WasmQuerier::new(chain, storage), + wasm: WasmQuerier::new(remote.clone(), storage), // strange argument notation suggested as a workaround here: https://github.com/rust-lang/rust/issues/41078#issuecomment-294296365 custom_handler: Box::from(|_: &_| -> QueryResultWithGas { ( @@ -67,7 +65,7 @@ impl MockQuerier { GasInfo::free(), ) }), - rt: Runtime::new().unwrap() + remote, } } @@ -125,11 +123,11 @@ impl cosmwasm_vm::Querier for MockQuerier impl MockQuerier { pub fn handle_query(&self, request: &QueryRequest) -> QueryResultWithGas { match &request { - QueryRequest::Bank(bank_query) => self.bank.query(&self.rt, bank_query), + QueryRequest::Bank(bank_query) => self.bank.query(bank_query), QueryRequest::Custom(custom_query) => (*self.custom_handler)(custom_query), QueryRequest::Staking(staking_query) => self.staking.query(staking_query), - QueryRequest::Wasm(msg) => self.wasm.query(&self.rt, msg), + QueryRequest::Wasm(msg) => self.wasm.query(self.remote.clone(), msg), QueryRequest::Stargate { .. } => ( SystemResult::Err(SystemError::UnsupportedRequest { kind: "Stargate".to_string(), diff --git a/src/wasm_emulation/query/wasm.rs b/src/wasm_emulation/query/wasm.rs index 26ad43ca..427477e8 100644 --- a/src/wasm_emulation/query/wasm.rs +++ b/src/wasm_emulation/query/wasm.rs @@ -4,7 +4,6 @@ use crate::wasm_emulation::query::mock_querier::QueryResultWithGas; use crate::wasm_emulation::contract::WasmContract; use crate::wasm_emulation::input::QuerierStorage; -use crate::wasm_emulation::input::SerChainData; use crate::wasm_emulation::input::WasmFunction; use crate::wasm_emulation::output::WasmOutput; use crate::wasm_emulation::output::WasmRunnerOutput; @@ -17,28 +16,26 @@ use cosmwasm_std::{ContractResult, Empty}; use cw_orch_daemon::queriers::CosmWasm; use cosmwasm_std::WasmQuery; -use tokio::runtime::Runtime; -use crate::wasm_emulation::channel::get_channel; +use crate::wasm_emulation::channel::RemoteChannel; use crate::WasmKeeper; use crate::wasm_emulation::input::{InstanceArguments, QueryArgs}; pub struct WasmQuerier { - chain: SerChainData, current_storage: QuerierStorage, + remote: RemoteChannel, } impl WasmQuerier { - pub fn new(chain: impl Into, storage: Option) -> Self { - let chain = chain.into(); + pub fn new(remote: RemoteChannel, storage: Option) -> Self { Self { - chain, current_storage: storage.unwrap_or(Default::default()), + remote, } } - pub fn query(&self, rt: &Runtime, request: &WasmQuery) -> QueryResultWithGas { + pub fn query(&self, remote: RemoteChannel, request: &WasmQuery) -> QueryResultWithGas { match request { WasmQuery::ContractInfo { contract_addr } => { let addr = Addr::unchecked(contract_addr); @@ -47,11 +44,11 @@ impl WasmQuerier { { local_contract.clone() } else { - WasmKeeper::::load_distant_contract(self.chain.clone(), &addr, rt) + WasmKeeper::::load_distant_contract(self.remote.clone(), &addr) .unwrap() }; let mut response = ContractInfoResponse::default(); - response.code_id = data.code_id.try_into().unwrap(); + response.code_id = data.code_id; response.creator = data.creator.to_string(); response.admin = data.admin.map(|a| a.to_string()); ( @@ -74,9 +71,9 @@ impl WasmQuerier { { value.1.clone() } else { - let channel = get_channel(self.chain.clone(), rt).unwrap(); - let wasm_querier = CosmWasm::new(channel); - let query_result = rt + let wasm_querier = CosmWasm::new(remote.channel); + let query_result = remote + .rt .block_on( wasm_querier .contract_raw_state(contract_addr.to_string(), key.to_vec()), @@ -105,30 +102,26 @@ impl WasmQuerier { // We execute the query code_info.clone() } else { - WasmContract::new_distant_code_id( - local_contract.code_id.try_into().unwrap(), - self.chain.clone(), - ) + WasmContract::new_distant_code_id(local_contract.code_id) } } else { - WasmContract::new_distant_contract( - contract_addr.to_string(), - self.chain.clone(), - ) + WasmContract::new_distant_contract(contract_addr.to_string()) }; let mut env = mock_env(); env.contract.address = addr.clone(); // Here we specify empty because we only car about the query result - let result: Result, _> = - contract.run_contract(InstanceArguments { + let result: Result, _> = contract.run_contract( + InstanceArguments { function: WasmFunction::Query(QueryArgs { env, msg: msg.to_vec(), }), querier_storage: self.current_storage.clone(), init_storage: self.current_storage.wasm.get_contract_storage(&addr), - }); + }, + self.remote.clone(), + ); let result = if let Err(e) = result { return ( diff --git a/src/wasm_emulation/storage/analyzer.rs b/src/wasm_emulation/storage/analyzer.rs index 3085267f..b75f10e2 100644 --- a/src/wasm_emulation/storage/analyzer.rs +++ b/src/wasm_emulation/storage/analyzer.rs @@ -1,15 +1,13 @@ use crate::prefixed_storage::decode_length; use crate::prefixed_storage::to_length_prefixed; use crate::prefixed_storage::CONTRACT_STORAGE_PREFIX; -use crate::wasm_emulation::channel::get_channel; -use crate::wasm_emulation::channel::get_rt_and_channel; +use crate::wasm_emulation::channel::RemoteChannel; use crate::wasm_emulation::input::get_querier_storage; use cosmwasm_std::Addr; use cosmwasm_std::Coin; use cw_orch_daemon::queriers::CosmWasm; use cw_orch_daemon::queriers::DaemonQuerier; use cw_utils::NativeBalance; -use ibc_chain_registry::chain::ChainData; use rustc_serialize::json::Json; use serde::Serialize; use serde::__private::from_utf8_lossy; @@ -30,14 +28,14 @@ pub struct SerializableCoin { pub struct StorageAnalyzer { pub storage: QuerierStorage, - pub chain: ChainData, + pub remote: RemoteChannel, } impl StorageAnalyzer { - pub fn new(app: &App, c: impl Into) -> AnyResult { + pub fn new(app: &App) -> AnyResult { Ok(Self { storage: get_querier_storage(&app.wrap())?, - chain: c.into(), + remote: app.remote.clone(), }) } @@ -115,13 +113,14 @@ impl StorageAnalyzer { } pub fn compare_all_readable_contract_storage(&self) { - let (rt, channel) = get_rt_and_channel(self.chain.clone()).unwrap(); - let wasm_querier = CosmWasm::new(channel); + let wasm_querier = CosmWasm::new(self.remote.channel.clone()); self.all_contract_storage() .into_iter() .for_each(|(contract_addr, key, value)| { // We look for the data at that key on the contract - let distant_data = rt + let distant_data = self + .remote + .rt .block_on(wasm_querier.contract_raw_state(contract_addr.clone(), key.clone())); if let Ok(data) = distant_data { @@ -199,13 +198,15 @@ impl StorageAnalyzer { } pub fn compare_all_balances(&self) { - let (rt, channel) = get_rt_and_channel(self.chain.clone()).unwrap(); - let bank_querier = cw_orch_daemon::queriers::Bank::new(channel); + let bank_querier = cw_orch_daemon::queriers::Bank::new(self.remote.channel.clone()); self.get_all_local_balances() .into_iter() .for_each(|(addr, balances)| { // We look for the data at that key on the contract - let distant_data = rt.block_on(bank_querier.balance(addr.clone(), None)); + let distant_data = self + .remote + .rt + .block_on(bank_querier.balance(addr.clone(), None)); if let Ok(data) = distant_data { let distant_coins: Vec = data diff --git a/src/wasm_emulation/storage/dual_storage.rs b/src/wasm_emulation/storage/dual_storage.rs index 7fc98c2f..2cf419a9 100644 --- a/src/wasm_emulation/storage/dual_storage.rs +++ b/src/wasm_emulation/storage/dual_storage.rs @@ -1,5 +1,4 @@ -use crate::wasm_emulation::channel::get_rt_and_channel; -use crate::wasm_emulation::input::SerChainData; +use crate::wasm_emulation::channel::RemoteChannel; use crate::wasm_emulation::storage::mock_storage::{GAS_COST_LAST_ITERATION, GAS_COST_RANGE}; use super::mock_storage::MockStorage; @@ -67,14 +66,14 @@ struct Iter { pub struct DualStorage { pub local_storage: MockStorage, pub removed_keys: HashSet>, - pub chain: SerChainData, + pub remote: RemoteChannel, pub contract_addr: String, iterators: HashMap, } impl DualStorage { pub fn new( - chain: impl Into, + remote: RemoteChannel, contract_addr: String, init: Option, Vec)>>, ) -> AnyResult { @@ -87,7 +86,7 @@ impl DualStorage { Ok(Self { local_storage, - chain: chain.into(), + remote, removed_keys: HashSet::default(), contract_addr, iterators: HashMap::new(), @@ -108,10 +107,9 @@ impl Storage for DualStorage { let (mut value, gas_info) = self.local_storage.get(key); // If it's not available, we query it online if it was not removed locally if !self.removed_keys.contains(key) && value.as_ref().unwrap().is_none() { - let (rt, channel) = get_rt_and_channel(self.chain.clone()).unwrap(); - let wasm_querier = CosmWasm::new(channel); + let wasm_querier = CosmWasm::new(self.remote.channel.clone()); - let distant_result = rt.block_on( + let distant_result = self.remote.rt.block_on( wasm_querier.contract_raw_state(self.contract_addr.clone(), key.to_vec()), ); @@ -181,9 +179,10 @@ impl Storage for DualStorage { if iterator.distant_iter.position == iterator.distant_iter.data.len() && iterator.distant_iter.key.is_some() { - let (rt, channel) = get_rt_and_channel(self.chain.clone()).unwrap(); - let wasm_querier = CosmWasm::new(channel); - let new_keys = rt + let wasm_querier = CosmWasm::new(self.remote.channel.clone()); + let new_keys = self + .remote + .rt .block_on(wasm_querier.all_contract_state( self.contract_addr.clone(), Some(PageRequest { From 59974bf6f124c05237425499e867260c18fd0353 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Thu, 23 Nov 2023 23:53:50 +0100 Subject: [PATCH 14/81] Added distant code info query --- Cargo.toml | 16 ++++++++++------ src/wasm.rs | 23 +++++++++++++++++------ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fb23db81..b67ca072 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/CosmWasm/cw-multi-test" homepage = "https://cosmwasm.com" [features] -default = ["iterator", "staking", "cosmwasm_1_1"] +default = ["iterator", "staking", "cosmwasm_1_2"] iterator = ["cosmwasm-std/iterator"] stargate = ["cosmwasm-std/stargate"] staking = ["cosmwasm-std/staking"] @@ -41,11 +41,15 @@ sha2 = "0.10" # We specify them to tighten their version requirements so that builds with `-Zminimal-versions` work. # Once we bump `cosmwasm-*` deps to a version after `1.1.5`, we can remove these. k256 = { version = "0.11.1", features = ["ecdsa"] } -cw-orch-daemon = { version = "0.16.0"} -cw-orch-networks = { version="0.16.0" } +cw-orch-daemon = { version = "0.16.0" } +cw-orch-networks = { version = "0.16.0" } tokio = "1.28.2" ibc-chain-registry = "0.25.0" -cosmwasm-vm = { version = "1.2", features = ["staking", "stargate", "iterator"] } +cosmwasm-vm = { version = "1.2", features = [ + "staking", + "stargate", + "iterator", +] } bincode = "1.3.3" base64 = "0.21.2" cw20 = "1.0.1" @@ -62,7 +66,7 @@ log = "0.4.19" env_logger = "0.10.0" cosmwasm-schema = "1.2.7" bech32 = "0.9.1" -treediff = {version="4.0.2", features=["with-rustc-serialize"]} +treediff = { version = "4.0.2", features = ["with-rustc-serialize"] } rustc-serialize = "0.3.24" serde_json = "1.0.105" @@ -80,4 +84,4 @@ dotenv = "0.15.0" hex = "0.4.3" cw-asset = "3.0.0" -moneymarket = {git="https://github.com/CavernPerson/money-market-contracts"} +moneymarket = { git = "https://github.com/CavernPerson/money-market-contracts" } diff --git a/src/wasm.rs b/src/wasm.rs index fa80dae7..693bb4e9 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -236,13 +236,24 @@ where } #[cfg(feature = "cosmwasm_1_2")] WasmQuery::CodeInfo { code_id } => { - let code_data = self.code_data(code_id)?; + let code_data = self.code_data(code_id); let mut res = cosmwasm_std::CodeInfoResponse::default(); - res.code_id = code_id; - res.creator = code_data.creator.to_string(); - res.checksum = cosmwasm_std::HexBinary::from( - Sha256::digest(format!("contract code {}", code_data.seed)).to_vec(), - ); + if let Ok(code_data) = code_data { + res.code_id = code_id; + res.creator = code_data.creator.to_string(); + res.checksum = cosmwasm_std::HexBinary::from( + Sha256::digest(format!("contract code {}", code_data.seed)).to_vec(), + ); + } else { + // Remote case + let remote = self.remote.clone().unwrap(); + let wasm_querier = CosmWasm::new(remote.channel); + + let code_info = remote.rt.block_on(wasm_querier.code(code_id))?; + res.code_id = code_id; + res.creator = code_info.creator.to_string(); + res.checksum = code_info.data_hash.into(); + }; to_binary(&res).map_err(Into::into) } other => bail!(Error::UnsupportedWasmQuery(other)), From a8066000318962e4a01584d6b8bdf46b13819544 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 28 Nov 2023 16:39:00 +0100 Subject: [PATCH 15/81] Added Code Info query inside contracts --- src/wasm.rs | 10 ++++++---- src/wasm_emulation/input.rs | 3 ++- src/wasm_emulation/query/wasm.rs | 31 +++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/wasm.rs b/src/wasm.rs index 693bb4e9..474c7f41 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -77,18 +77,19 @@ pub struct ContractData { pub created: u64, } +#[derive(Serialize, Deserialize, Debug, Clone)] /// Contract code base data. -struct CodeData { +pub struct CodeData { /// Address of an account that initially stored the contract code. //FIXME Remove this feature flag when the default flag is `cosmwasm_1_2` or higher. #[cfg_attr(feature = "cosmwasm_1_1", allow(dead_code))] - creator: Addr, + pub creator: Addr, /// Seed used to generate a checksum for underlying code base. //FIXME Remove this feature flag when the default flag is `cosmwasm_1_2` or higher. #[cfg_attr(feature = "cosmwasm_1_1", allow(dead_code))] - seed: usize, + pub seed: usize, /// Identifier of the code base where the contract code is stored in memory. - code_base_id: usize, + pub code_base_id: usize, } pub trait Wasm: AllQuerier { @@ -199,6 +200,7 @@ impl AllQuerier for WasmKeeper { contracts, storage: all_local_state, codes: self.code_base.clone(), + code_data: self.code_data.clone(), }) } } diff --git a/src/wasm_emulation/input.rs b/src/wasm_emulation/input.rs index b5a880ee..39584add 100644 --- a/src/wasm_emulation/input.rs +++ b/src/wasm_emulation/input.rs @@ -14,7 +14,7 @@ use cw_utils::NativeBalance; use crate::bank::BankKeeper; use crate::prefixed_storage::get_full_contract_storage_namespace; -use crate::wasm::ContractData; +use crate::wasm::{CodeData, ContractData}; use super::contract::WasmContract; use super::query::AllQuerier; @@ -23,6 +23,7 @@ use super::query::AllQuerier; pub struct WasmStorage { pub contracts: HashMap, pub codes: HashMap, + pub code_data: HashMap, pub storage: Vec<(Vec, Vec)>, } diff --git a/src/wasm_emulation/query/wasm.rs b/src/wasm_emulation/query/wasm.rs index 427477e8..93b0e16a 100644 --- a/src/wasm_emulation/query/wasm.rs +++ b/src/wasm_emulation/query/wasm.rs @@ -16,6 +16,8 @@ use cosmwasm_std::{ContractResult, Empty}; use cw_orch_daemon::queriers::CosmWasm; use cosmwasm_std::WasmQuery; +#[cfg(feature = "cosmwasm_1_2")] +use sha2::{Digest, Sha256}; use crate::wasm_emulation::channel::RemoteChannel; use crate::WasmKeeper; @@ -145,6 +147,35 @@ impl WasmQuerier { GasInfo::with_externally_used(result.gas_used), ) } + #[cfg(feature = "cosmwasm_1_2")] + WasmQuery::CodeInfo { code_id } => { + let code_data = self + .current_storage + .wasm + .code_data + .get(&(*code_id as usize)); + let mut res = cosmwasm_std::CodeInfoResponse::default(); + if let Some(code_data) = code_data { + res.code_id = *code_id; + res.creator = code_data.creator.to_string(); + res.checksum = cosmwasm_std::HexBinary::from( + Sha256::digest(format!("contract code {}", code_data.seed)).to_vec(), + ); + } else { + // Remote case + let remote = self.remote.clone(); + let wasm_querier = CosmWasm::new(remote.channel); + + let code_info = remote.rt.block_on(wasm_querier.code(*code_id)).unwrap(); + res.code_id = *code_id; + res.creator = code_info.creator.to_string(); + res.checksum = code_info.data_hash.into(); + }; + ( + SystemResult::Ok(to_binary(&res).into()), + GasInfo::with_externally_used(GAS_COST_CONTRACT_INFO), + ) + } _ => unimplemented!(), } } From 04f1d4f034a28cfa5eee75aa6ee325500278609f Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 28 Nov 2023 16:40:57 +0100 Subject: [PATCH 16/81] Updated version tag --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 90168fcb..e8f3718f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -865,7 +865,7 @@ dependencies = [ [[package]] name = "cw-multi-test" -version = "0.16.5" +version = "0.16.7" dependencies = [ "anyhow", "base64 0.21.4", diff --git a/Cargo.toml b/Cargo.toml index b67ca072..e78a2848 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cw-multi-test" -version = "0.16.5" +version = "0.16.7" authors = ["Ethan Frey "] edition = "2021" description = "Test helpers for multi-contract interactions" From c1f3405c512f0278d4d1b87fd5d282ed7a16bf92 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 28 Nov 2023 17:35:57 +0100 Subject: [PATCH 17/81] Simplified code --- src/bank.rs | 37 +-- src/contracts.rs | 449 +------------------------------ src/error.rs | 2 +- src/lib.rs | 3 +- src/prefixed_storage.rs | 7 +- src/queries/bank.rs | 44 +++ src/queries/mod.rs | 2 + src/queries/wasm.rs | 88 ++++++ src/staking.rs | 3 +- src/wasm.rs | 93 ++----- src/wasm_emulation/query/wasm.rs | 32 +-- 11 files changed, 177 insertions(+), 583 deletions(-) create mode 100644 src/queries/bank.rs create mode 100644 src/queries/mod.rs create mode 100644 src/queries/wasm.rs diff --git a/src/bank.rs b/src/bank.rs index e5d9d15e..9ec73d07 100644 --- a/src/bank.rs +++ b/src/bank.rs @@ -1,6 +1,4 @@ -use crate::wasm_emulation::input::BankStorage; -use cw_orch_daemon::queriers::DaemonQuerier; -use std::str::FromStr; +use crate::queries::bank::BankRemoteQuerier; use anyhow::{bail, Result as AnyResult}; use itertools::Itertools; @@ -21,7 +19,7 @@ use crate::prefixed_storage::{prefixed, prefixed_read}; use crate::wasm_emulation::channel::RemoteChannel; use crate::wasm_emulation::query::AllQuerier; -const BALANCES: Map<&Addr, NativeBalance> = Map::new("balances"); +pub(crate) const BALANCES: Map<&Addr, NativeBalance> = Map::new("balances"); pub const NAMESPACE_BANK: &[u8] = b"bank"; @@ -77,25 +75,7 @@ impl BankKeeper { fn get_balance(&self, bank_storage: &dyn Storage, account: &Addr) -> AnyResult> { // If there is no balance present, we query it on the distant chain if !BALANCES.has(bank_storage, account) { - let channel = self.remote.clone().unwrap().channel; - let querier = cw_orch_daemon::queriers::Bank::new(channel); - let distant_amounts: Vec = self - .remote - .clone() - .unwrap() - .rt - .block_on(querier.balance(account, None)) - .map(|result| { - result - .into_iter() - .map(|c| Coin { - amount: Uint128::from_str(&c.amount).unwrap(), - denom: c.denom, - }) - .collect() - }) - .unwrap(); - Ok(distant_amounts) + BankRemoteQuerier::get_balance(self.remote.clone().unwrap(), account) } else { let val = BALANCES.may_load(bank_storage, account)?; Ok(val.unwrap_or_default().into_vec()) @@ -175,17 +155,6 @@ fn coins_to_string(coins: &[Coin]) -> String { impl Bank for BankKeeper {} -impl AllQuerier for BankKeeper { - type Output = BankStorage; - fn query_all(&self, storage: &dyn Storage) -> AnyResult { - let bank_storage = prefixed_read(storage, NAMESPACE_BANK); - let balances: Result, _> = BALANCES - .range(&bank_storage, None, None, Order::Ascending) - .collect(); - Ok(BankStorage { storage: balances? }) - } -} - impl Module for BankKeeper { type ExecT = BankMsg; type QueryT = BankQuery; diff --git a/src/contracts.rs b/src/contracts.rs index 70a0c859..d5ee86a6 100644 --- a/src/contracts.rs +++ b/src/contracts.rs @@ -1,22 +1,15 @@ use schemars::JsonSchema; -use serde::de::DeserializeOwned; -use std::error::Error; -use std::fmt::{self, Debug, Display}; -use std::ops::Deref; -use cosmwasm_std::{ - from_slice, Binary, CosmosMsg, CustomQuery, Deps, DepsMut, Empty, Env, MessageInfo, - QuerierWrapper, Reply, Response, SubMsg, -}; +use cosmwasm_std::{Binary, CustomQuery, Deps, DepsMut, Empty, Env, MessageInfo, Reply, Response}; -use anyhow::{anyhow, bail, Result as AnyResult}; +use anyhow::Result as AnyResult; use crate::wasm_emulation::channel::RemoteChannel; /// Interface to call into a [Contract]. pub trait Contract where - T: Clone + fmt::Debug + PartialEq + JsonSchema, + T: Clone + std::fmt::Debug + PartialEq + JsonSchema, Q: CustomQuery, { fn execute( @@ -69,439 +62,3 @@ where remote: RemoteChannel, ) -> AnyResult>; } - -type ContractFn = fn( - deps: DepsMut, - env: Env, - info: MessageInfo, - msg: T, - remote: RemoteChannel, -) -> Result, E>; -type PermissionedFn = - fn(deps: DepsMut, env: Env, msg: T, remote: RemoteChannel) -> Result, E>; -type ReplyFn = - fn(deps: DepsMut, env: Env, msg: Reply, remote: RemoteChannel) -> Result, E>; -type QueryFn = - fn(deps: Deps, env: Env, msg: T, remote: RemoteChannel) -> Result; - -type ContractClosure = - Box, Env, MessageInfo, T, RemoteChannel) -> Result, E>>; -type PermissionedClosure = - Box, Env, T, RemoteChannel) -> Result, E>>; -type ReplyClosure = - Box, Env, Reply, RemoteChannel) -> Result, E>>; -type QueryClosure = Box, Env, T, RemoteChannel) -> Result>; - -/// Wraps the exported functions from a contract and provides the normalized format -/// Place T4 and E4 at the end, as we just want default placeholders for most contracts that don't have sudo -pub struct ContractWrapper< - T1, - T2, - T3, - E1, - E2, - E3, - C = Empty, - Q = Empty, - T4 = Empty, - E4 = anyhow::Error, - E5 = anyhow::Error, - T6 = Empty, - E6 = anyhow::Error, -> where - T1: DeserializeOwned + Debug, - T2: DeserializeOwned, - T3: DeserializeOwned, - T4: DeserializeOwned, - T6: DeserializeOwned, - E1: Display + Debug + Send + Sync + 'static, - E2: Display + Debug + Send + Sync + 'static, - E3: Display + Debug + Send + Sync + 'static, - E4: Display + Debug + Send + Sync + 'static, - E5: Display + Debug + Send + Sync + 'static, - E6: Display + Debug + Send + Sync + 'static, - C: Clone + fmt::Debug + PartialEq + JsonSchema, - Q: CustomQuery + DeserializeOwned + 'static, -{ - execute_fn: ContractClosure, - instantiate_fn: ContractClosure, - query_fn: QueryClosure, - sudo_fn: Option>, - reply_fn: Option>, - migrate_fn: Option>, -} - -impl ContractWrapper -where - T1: DeserializeOwned + Debug + 'static, - T2: DeserializeOwned + 'static, - T3: DeserializeOwned + 'static, - E1: Display + Debug + Send + Sync + 'static, - E2: Display + Debug + Send + Sync + 'static, - E3: Display + Debug + Send + Sync + 'static, - C: Clone + fmt::Debug + PartialEq + JsonSchema + 'static, - Q: CustomQuery + DeserializeOwned + 'static, -{ - pub fn new( - execute_fn: ContractFn, - instantiate_fn: ContractFn, - query_fn: QueryFn, - ) -> Self { - Self { - execute_fn: Box::new(execute_fn), - instantiate_fn: Box::new(instantiate_fn), - query_fn: Box::new(query_fn), - sudo_fn: None, - reply_fn: None, - migrate_fn: None, - } - } - - /// This will take a contract that returns `Response` and will "upgrade" it - /// to `Response` if needed to be compatible with a chain-specific extension. - pub fn new_with_empty( - execute_fn: ContractFn, - instantiate_fn: ContractFn, - query_fn: QueryFn, - ) -> Self { - Self { - execute_fn: customize_fn(execute_fn), - instantiate_fn: customize_fn(instantiate_fn), - query_fn: customize_query(query_fn), - sudo_fn: None, - reply_fn: None, - migrate_fn: None, - } - } -} - -impl - ContractWrapper -where - T1: DeserializeOwned + Debug + 'static, - T2: DeserializeOwned + 'static, - T3: DeserializeOwned + 'static, - T4: DeserializeOwned + 'static, - T6: DeserializeOwned + 'static, - E1: Display + Debug + Send + Sync + 'static, - E2: Display + Debug + Send + Sync + 'static, - E3: Display + Debug + Send + Sync + 'static, - E4: Display + Debug + Send + Sync + 'static, - E5: Display + Debug + Send + Sync + 'static, - E6: Display + Debug + Send + Sync + 'static, - C: Clone + fmt::Debug + PartialEq + JsonSchema + 'static, - Q: CustomQuery + DeserializeOwned + 'static, -{ - pub fn with_sudo( - self, - sudo_fn: PermissionedFn, - ) -> ContractWrapper - where - T4A: DeserializeOwned + 'static, - E4A: Display + Debug + Send + Sync + 'static, - { - ContractWrapper { - execute_fn: self.execute_fn, - instantiate_fn: self.instantiate_fn, - query_fn: self.query_fn, - sudo_fn: Some(Box::new(sudo_fn)), - reply_fn: self.reply_fn, - migrate_fn: self.migrate_fn, - } - } - - pub fn with_sudo_empty( - self, - sudo_fn: PermissionedFn, - ) -> ContractWrapper - where - T4A: DeserializeOwned + 'static, - E4A: Display + Debug + Send + Sync + 'static, - { - ContractWrapper { - execute_fn: self.execute_fn, - instantiate_fn: self.instantiate_fn, - query_fn: self.query_fn, - sudo_fn: Some(customize_permissioned_fn(sudo_fn)), - reply_fn: self.reply_fn, - migrate_fn: self.migrate_fn, - } - } - - pub fn with_reply( - self, - reply_fn: ReplyFn, - ) -> ContractWrapper - where - E5A: Display + Debug + Send + Sync + 'static, - { - ContractWrapper { - execute_fn: self.execute_fn, - instantiate_fn: self.instantiate_fn, - query_fn: self.query_fn, - sudo_fn: self.sudo_fn, - reply_fn: Some(Box::new(reply_fn)), - migrate_fn: self.migrate_fn, - } - } - - /// A correlate of new_with_empty - pub fn with_reply_empty( - self, - reply_fn: ReplyFn, - ) -> ContractWrapper - where - E5A: Display + Debug + Send + Sync + 'static, - { - ContractWrapper { - execute_fn: self.execute_fn, - instantiate_fn: self.instantiate_fn, - query_fn: self.query_fn, - sudo_fn: self.sudo_fn, - reply_fn: Some(customize_permissioned_fn(reply_fn)), - migrate_fn: self.migrate_fn, - } - } - - pub fn with_migrate( - self, - migrate_fn: PermissionedFn, - ) -> ContractWrapper - where - T6A: DeserializeOwned + 'static, - E6A: Display + Debug + Send + Sync + 'static, - { - ContractWrapper { - execute_fn: self.execute_fn, - instantiate_fn: self.instantiate_fn, - query_fn: self.query_fn, - sudo_fn: self.sudo_fn, - reply_fn: self.reply_fn, - migrate_fn: Some(Box::new(migrate_fn)), - } - } - - pub fn with_migrate_empty( - self, - migrate_fn: PermissionedFn, - ) -> ContractWrapper - where - T6A: DeserializeOwned + 'static, - E6A: Display + Debug + Send + Sync + 'static, - { - ContractWrapper { - execute_fn: self.execute_fn, - instantiate_fn: self.instantiate_fn, - query_fn: self.query_fn, - sudo_fn: self.sudo_fn, - reply_fn: self.reply_fn, - migrate_fn: Some(customize_permissioned_fn(migrate_fn)), - } - } -} - -fn customize_fn(raw_fn: ContractFn) -> ContractClosure -where - T: DeserializeOwned + 'static, - E: Display + Debug + Send + Sync + 'static, - C: Clone + fmt::Debug + PartialEq + JsonSchema + 'static, - Q: CustomQuery + DeserializeOwned + 'static, -{ - let customized = move |mut deps: DepsMut, - env: Env, - info: MessageInfo, - msg: T, - remote: RemoteChannel| - -> Result, E> { - let deps = decustomize_deps_mut(&mut deps); - raw_fn(deps, env, info, msg, remote).map(customize_response::) - }; - Box::new(customized) -} - -fn customize_query(raw_fn: QueryFn) -> QueryClosure -where - T: DeserializeOwned + 'static, - E: Display + Debug + Send + Sync + 'static, - Q: CustomQuery + DeserializeOwned + 'static, -{ - let customized = - move |deps: Deps, env: Env, msg: T, remote: RemoteChannel| -> Result { - let deps = decustomize_deps(&deps); - raw_fn(deps, env, msg, remote) - }; - Box::new(customized) -} - -fn decustomize_deps_mut<'a, Q>(deps: &'a mut DepsMut) -> DepsMut<'a, Empty> -where - Q: CustomQuery + DeserializeOwned + 'static, -{ - DepsMut { - storage: deps.storage, - api: deps.api, - querier: QuerierWrapper::new(deps.querier.deref()), - } -} - -fn decustomize_deps<'a, Q>(deps: &'a Deps<'a, Q>) -> Deps<'a, Empty> -where - Q: CustomQuery + DeserializeOwned + 'static, -{ - Deps { - storage: deps.storage, - api: deps.api, - querier: QuerierWrapper::new(deps.querier.deref()), - } -} - -fn customize_permissioned_fn( - raw_fn: PermissionedFn, -) -> PermissionedClosure -where - T: DeserializeOwned + 'static, - E: Display + Debug + Send + Sync + 'static, - C: Clone + fmt::Debug + PartialEq + JsonSchema + 'static, - Q: CustomQuery + DeserializeOwned + 'static, -{ - let customized = move |deps: DepsMut, - env: Env, - msg: T, - remote: RemoteChannel| - -> Result, E> { - raw_fn(deps, env, msg, remote).map(customize_response::) - }; - Box::new(customized) -} - -fn customize_response(resp: Response) -> Response -where - C: Clone + fmt::Debug + PartialEq + JsonSchema, -{ - let mut customized_resp = Response::::new() - .add_submessages(resp.messages.into_iter().map(customize_msg::)) - .add_events(resp.events) - .add_attributes(resp.attributes); - customized_resp.data = resp.data; - customized_resp -} - -fn customize_msg(msg: SubMsg) -> SubMsg -where - C: Clone + fmt::Debug + PartialEq + JsonSchema, -{ - SubMsg { - msg: match msg.msg { - CosmosMsg::Wasm(wasm) => CosmosMsg::Wasm(wasm), - CosmosMsg::Bank(bank) => CosmosMsg::Bank(bank), - CosmosMsg::Staking(staking) => CosmosMsg::Staking(staking), - CosmosMsg::Distribution(distribution) => CosmosMsg::Distribution(distribution), - CosmosMsg::Custom(_) => unreachable!(), - #[cfg(feature = "stargate")] - CosmosMsg::Ibc(ibc) => CosmosMsg::Ibc(ibc), - #[cfg(feature = "stargate")] - CosmosMsg::Stargate { type_url, value } => CosmosMsg::Stargate { type_url, value }, - _ => panic!("unknown message variant {:?}", msg), - }, - id: msg.id, - gas_limit: msg.gas_limit, - reply_on: msg.reply_on, - } -} - -impl Contract - for ContractWrapper -where - T1: DeserializeOwned + Debug + Clone, - T2: DeserializeOwned + Debug + Clone, - T3: DeserializeOwned + Debug + Clone, - T4: DeserializeOwned, - T6: DeserializeOwned, - E1: Display + Debug + Send + Sync + Error + 'static, - E2: Display + Debug + Send + Sync + Error + 'static, - E3: Display + Debug + Send + Sync + Error + 'static, - E4: Display + Debug + Send + Sync + 'static, - E5: Display + Debug + Send + Sync + 'static, - E6: Display + Debug + Send + Sync + 'static, - C: Clone + fmt::Debug + PartialEq + JsonSchema, - Q: CustomQuery + DeserializeOwned, -{ - fn execute( - &self, - deps: DepsMut, - env: Env, - info: MessageInfo, - msg: Vec, - remote: RemoteChannel, - ) -> AnyResult> { - let msg: T1 = from_slice(&msg)?; - (self.execute_fn)(deps, env, info, msg, remote).map_err(|err| anyhow!(err)) - } - - fn instantiate( - &self, - deps: DepsMut, - env: Env, - info: MessageInfo, - msg: Vec, - remote: RemoteChannel, - ) -> AnyResult> { - let msg: T2 = from_slice(&msg)?; - (self.instantiate_fn)(deps, env, info, msg, remote).map_err(|err| anyhow!(err)) - } - - fn query( - &self, - deps: Deps, - env: Env, - msg: Vec, - remote: RemoteChannel, - ) -> AnyResult { - let msg: T3 = from_slice(&msg)?; - (self.query_fn)(deps, env, msg, remote).map_err(|err| anyhow!(err)) - } - - // this returns an error if the contract doesn't implement sudo - fn sudo( - &self, - deps: DepsMut, - env: Env, - msg: Vec, - remote: RemoteChannel, - ) -> AnyResult> { - let msg = from_slice(&msg)?; - match &self.sudo_fn { - Some(sudo) => sudo(deps, env, msg, remote).map_err(|err| anyhow!(err)), - None => bail!("sudo not implemented for contract"), - } - } - - // this returns an error if the contract doesn't implement reply - fn reply( - &self, - deps: DepsMut, - env: Env, - reply_data: Reply, - remote: RemoteChannel, - ) -> AnyResult> { - match &self.reply_fn { - Some(reply) => reply(deps, env, reply_data, remote).map_err(|err| anyhow!(err)), - None => bail!("reply not implemented for contract"), - } - } - - // this returns an error if the contract doesn't implement migrate - fn migrate( - &self, - deps: DepsMut, - env: Env, - msg: Vec, - remote: RemoteChannel, - ) -> AnyResult> { - let msg = from_slice(&msg)?; - match &self.migrate_fn { - Some(migrate) => migrate(deps, env, msg, remote).map_err(|err| anyhow!(err)), - None => bail!("migrate not implemented for contract"), - } - } -} diff --git a/src/error.rs b/src/error.rs index cd47529c..75a854af 100644 --- a/src/error.rs +++ b/src/error.rs @@ -27,7 +27,7 @@ pub enum Error { #[error("code id {0}: no such code")] UnregisteredCodeId(u64), - #[error("Unregistered contract address, not present loccaly or on-chain")] + #[error("Unregistered contract address, not present locally or on-chain")] UnregisteredContractAddress(String), } diff --git a/src/lib.rs b/src/lib.rs index 61f6ce8c..da842ef1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,6 +17,7 @@ mod gov; mod ibc; mod module; pub(crate) mod prefixed_storage; +pub mod queries; mod staking; mod transactions; mod wasm; @@ -27,7 +28,7 @@ pub use crate::app::{ SudoMsg, }; pub use crate::bank::{Bank, BankKeeper, BankSudo}; -pub use crate::contracts::{Contract, ContractWrapper}; +pub use crate::contracts::Contract; pub use crate::executor::{AppResponse, Executor}; pub use crate::gov::Gov; pub use crate::ibc::{Ibc, IbcAcceptingModule}; diff --git a/src/prefixed_storage.rs b/src/prefixed_storage.rs index 2a1c817d..f65082a4 100644 --- a/src/prefixed_storage.rs +++ b/src/prefixed_storage.rs @@ -5,7 +5,12 @@ use cosmwasm_std::Storage; #[cfg(feature = "iterator")] use cosmwasm_std::{Order, Record}; -pub use length_prefixed::*; +use length_prefixed::to_length_prefixed_nested; +pub use length_prefixed::{ + contract_namespace, decode_length, get_full_contract_storage_namespace, to_length_prefixed, + CONTRACT_STORAGE_PREFIX, +}; + #[cfg(feature = "iterator")] use namespace_helpers::range_with_prefix; use namespace_helpers::{get_with_prefix, remove_with_prefix, set_with_prefix}; diff --git a/src/queries/bank.rs b/src/queries/bank.rs new file mode 100644 index 00000000..405df53b --- /dev/null +++ b/src/queries/bank.rs @@ -0,0 +1,44 @@ +use std::str::FromStr; + +use anyhow::Result as AnyResult; +use cosmwasm_std::{Addr, Coin, Uint128, Storage, Order}; +use cw_orch_daemon::queriers::DaemonQuerier; + +use crate::{ + wasm_emulation::{channel::RemoteChannel, input::BankStorage, query::AllQuerier}, + BankKeeper, prefixed_storage::prefixed_read, bank::{NAMESPACE_BANK, BALANCES}, +}; + +pub struct BankRemoteQuerier; + +impl BankRemoteQuerier { + pub fn get_balance(remote: RemoteChannel, account: &Addr) -> AnyResult> { + let channel = remote.channel; + let querier = cw_orch_daemon::queriers::Bank::new(channel); + let distant_amounts: Vec = remote + .rt + .block_on(querier.balance(account, None)) + .map(|result| { + result + .into_iter() + .map(|c| Coin { + amount: Uint128::from_str(&c.amount).unwrap(), + denom: c.denom, + }) + .collect() + }) + .unwrap(); + Ok(distant_amounts) + } +} + +impl AllQuerier for BankKeeper { + type Output = BankStorage; + fn query_all(&self, storage: &dyn Storage) -> AnyResult { + let bank_storage = prefixed_read(storage, NAMESPACE_BANK); + let balances: Result, _> = BALANCES + .range(&bank_storage, None, None, Order::Ascending) + .collect(); + Ok(BankStorage { storage: balances? }) + } +} diff --git a/src/queries/mod.rs b/src/queries/mod.rs new file mode 100644 index 00000000..31a22af0 --- /dev/null +++ b/src/queries/mod.rs @@ -0,0 +1,2 @@ +pub mod bank; +pub mod wasm; diff --git a/src/queries/wasm.rs b/src/queries/wasm.rs new file mode 100644 index 00000000..ca5e4206 --- /dev/null +++ b/src/queries/wasm.rs @@ -0,0 +1,88 @@ +use std::collections::HashMap; + +use anyhow::Result as AnyResult; +use cosmwasm_std::{Addr, CodeInfoResponse, Order, Storage, Binary}; +use cw_orch_daemon::queriers::{CosmWasm, DaemonQuerier}; + +use crate::{ + prefixed_storage::prefixed_read, + wasm::{ContractData, CONTRACTS, NAMESPACE_WASM}, + wasm_emulation::{channel::RemoteChannel, input::WasmStorage, query::AllQuerier}, + WasmKeeper, +}; + +pub struct WasmRemoteQuerier; + +impl WasmRemoteQuerier { + pub fn code_info(remote: RemoteChannel, code_id: u64) -> AnyResult { + let wasm_querier = CosmWasm::new(remote.channel); + + let code_info = remote.rt.block_on(wasm_querier.code(code_id))?; + let mut res = cosmwasm_std::CodeInfoResponse::default(); + res.code_id = code_id; + res.creator = code_info.creator.to_string(); + res.checksum = code_info.data_hash.into(); + Ok(res) + } + + pub fn load_distant_contract(remote: RemoteChannel, address: &Addr) -> AnyResult { + let wasm_querier = CosmWasm::new(remote.channel); + + let code_info = remote + .rt + .block_on(wasm_querier.contract_info(address.clone()))?; + + Ok(ContractData { + admin: { + match code_info.admin.as_str() { + "" => None, + a => Some(Addr::unchecked(a)), + } + }, + code_id: code_info.code_id, + created: code_info.created.unwrap().block_height, + creator: Addr::unchecked(code_info.creator), + label: code_info.label, + }) + } + + pub fn raw_query( + remote: RemoteChannel, + contract_addr: String, + key: Binary, + ) -> AnyResult> { + let wasm_querier = CosmWasm::new(remote.channel); + let query_result = remote + .rt + .block_on(wasm_querier.contract_raw_state(contract_addr, key.to_vec())) + .map(|query_result| query_result.data); + Ok(query_result?) + } +} + +impl AllQuerier for WasmKeeper { + type Output = WasmStorage; + fn query_all(&self, storage: &dyn Storage) -> AnyResult { + let all_local_state: Vec<_> = storage.range(None, None, Order::Ascending).collect(); + + let contracts = CONTRACTS + .range( + &prefixed_read(storage, NAMESPACE_WASM), + None, + None, + Order::Ascending, + ) + .map(|res| match res { + Ok((key, value)) => Ok((key.to_string(), value)), + Err(e) => Err(e), + }) + .collect::, _>>()?; + + Ok(WasmStorage { + contracts, + storage: all_local_state, + codes: self.code_base.clone(), + code_data: self.code_data.clone(), + }) + } +} diff --git a/src/staking.rs b/src/staking.rs index d3edcfff..65a08f33 100644 --- a/src/staking.rs +++ b/src/staking.rs @@ -13,10 +13,9 @@ use cw_storage_plus::{Deque, Item, Map}; use serde::{Deserialize, Serialize}; use crate::app::CosmosRouter; -use crate::bank::BankSudo; use crate::executor::AppResponse; use crate::prefixed_storage::{prefixed, prefixed_read}; -use crate::Module; +use crate::{BankSudo, Module}; // Contains some general staking parameters #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] diff --git a/src/wasm.rs b/src/wasm.rs index 474c7f41..86ced810 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -1,9 +1,8 @@ use crate::prefixed_storage::contract_namespace; +use crate::queries::wasm::WasmRemoteQuerier; use crate::wasm_emulation::api::RealApi; use crate::wasm_emulation::channel::RemoteChannel; use cosmwasm_std::CustomMsg; -use cw_orch_daemon::queriers::CosmWasm; -use cw_orch_daemon::queriers::DaemonQuerier; use std::collections::HashMap; use std::fmt::Debug; @@ -35,11 +34,10 @@ use anyhow::{bail, Context, Result as AnyResult}; use sha2::{Digest, Sha256}; use crate::wasm_emulation::contract::WasmContract; -use crate::wasm_emulation::input::WasmStorage; use crate::wasm_emulation::query::AllQuerier; // Contract state is kept in Storage, separate from the contracts themselves -const CONTRACTS: Map<&Addr, ContractData> = Map::new("contracts"); +pub(crate) const CONTRACTS: Map<&Addr, ContractData> = Map::new("contracts"); pub const NAMESPACE_WASM: &[u8] = b"wasm"; /// See @@ -129,9 +127,9 @@ pub trait Wasm: AllQuerier { // pub struct WasmKeeper { pub struct WasmKeeper { /// Contract codes that stand for wasm code in real-life blockchain. - code_base: HashMap, + pub code_base: HashMap, /// Code data with code base identifier and additional attributes. - code_data: HashMap, + pub code_data: HashMap, /// Just markers to make type elision fork when using it as `Wasm` trait _e: std::marker::PhantomData, /// Just markers to make type elision fork when using it as `Wasm` trait @@ -178,33 +176,6 @@ impl Default for WasmKeeper { } } -impl AllQuerier for WasmKeeper { - type Output = WasmStorage; - fn query_all(&self, storage: &dyn Storage) -> AnyResult { - let all_local_state: Vec<_> = storage.range(None, None, Order::Ascending).collect(); - - let contracts = CONTRACTS - .range( - &prefixed_read(storage, NAMESPACE_WASM), - None, - None, - Order::Ascending, - ) - .map(|res| match res { - Ok((key, value)) => Ok((key.to_string(), value)), - Err(e) => Err(e), - }) - .collect::, _>>()?; - - Ok(WasmStorage { - contracts, - storage: all_local_state, - codes: self.code_base.clone(), - code_data: self.code_data.clone(), - }) - } -} - impl Wasm for WasmKeeper where ExecC: CustomMsg + DeserializeOwned + 'static, @@ -239,22 +210,16 @@ where #[cfg(feature = "cosmwasm_1_2")] WasmQuery::CodeInfo { code_id } => { let code_data = self.code_data(code_id); - let mut res = cosmwasm_std::CodeInfoResponse::default(); - if let Ok(code_data) = code_data { + let res = if let Ok(code_data) = code_data { + let mut res = cosmwasm_std::CodeInfoResponse::default(); res.code_id = code_id; res.creator = code_data.creator.to_string(); res.checksum = cosmwasm_std::HexBinary::from( Sha256::digest(format!("contract code {}", code_data.seed)).to_vec(), ); + res } else { - // Remote case - let remote = self.remote.clone().unwrap(); - let wasm_querier = CosmWasm::new(remote.channel); - - let code_info = remote.rt.block_on(wasm_querier.code(code_id))?; - res.code_id = code_id; - res.creator = code_info.creator.to_string(); - res.checksum = code_info.data_hash.into(); + WasmRemoteQuerier::code_info(self.remote.clone().unwrap(), code_id)? }; to_binary(&res).map_err(Into::into) } @@ -370,41 +335,22 @@ impl WasmKeeper { WasmContract::new_distant_contract(address.to_string()) } - pub fn load_distant_contract(remote: RemoteChannel, address: &Addr) -> AnyResult { - let wasm_querier = CosmWasm::new(remote.channel); - - let code_info = remote - .rt - .block_on(wasm_querier.contract_info(address.clone()))?; - - Ok(ContractData { - admin: { - match code_info.admin.as_str() { - "" => None, - a => Some(Addr::unchecked(a)), - } - }, - code_id: code_info.code_id, - created: code_info.created.unwrap().block_height, - creator: Addr::unchecked(code_info.creator), - label: code_info.label, - }) - } - pub fn load_contract(&self, storage: &dyn Storage, address: &Addr) -> AnyResult { - if let Ok(local_contract) = CONTRACTS.load(&prefixed_read(storage, NAMESPACE_WASM), address) - { - return Ok(local_contract); + let contract = CONTRACTS.load(&prefixed_read(storage, NAMESPACE_WASM), address); + if let Ok(local_contract) = contract { + Ok(local_contract) + } else { + WasmRemoteQuerier::load_distant_contract(self.remote.clone().unwrap(), address) } - - let remote_channel = self.remote.clone().unwrap(); - Self::load_distant_contract(remote_channel, address) } pub fn dump_wasm_raw(&self, storage: &dyn Storage, address: &Addr) -> Vec { let storage = self.contract_storage_readonly(storage, address); storage.range(None, None, Order::Ascending).collect() } + fn contract_namespace(&self, contract: &Addr) -> Vec { + contract_namespace(contract) + } fn contract_storage<'a>( &self, @@ -413,7 +359,7 @@ impl WasmKeeper { ) -> Box { // We double-namespace this, once from global storage -> wasm_storage // then from wasm_storage -> the contracts subspace - let namespace = contract_namespace(address); + let namespace = self.contract_namespace(address); let storage = PrefixedStorage::multilevel(storage, &[NAMESPACE_WASM, &namespace]); Box::new(storage) } @@ -426,7 +372,7 @@ impl WasmKeeper { ) -> Box { // We double-namespace this, once from global storage -> wasm_storage // then from wasm_storage -> the contracts subspace - let namespace = contract_namespace(address); + let namespace = self.contract_namespace(address); let storage = ReadonlyPrefixedStorage::multilevel(storage, &[NAMESPACE_WASM, &namespace]); Box::new(storage) } @@ -893,7 +839,6 @@ where /// You must call init after this to set up the contract properly. /// These are separated into two steps to have cleaner return values. pub fn register_contract( - // TODO &self, storage: &mut dyn Storage, code_id: u64, @@ -1082,7 +1027,7 @@ where api, querier: QuerierWrapper::new(&querier), }; - action(handler.clone(), deps, env) + action(handler, deps, env) }) } diff --git a/src/wasm_emulation/query/wasm.rs b/src/wasm_emulation/query/wasm.rs index 93b0e16a..e6aecdf6 100644 --- a/src/wasm_emulation/query/wasm.rs +++ b/src/wasm_emulation/query/wasm.rs @@ -1,4 +1,5 @@ use crate::prefixed_storage::get_full_contract_storage_namespace; +use crate::queries::wasm::WasmRemoteQuerier; use crate::wasm_emulation::query::gas::{GAS_COST_CONTRACT_INFO, GAS_COST_RAW_COSMWASM_QUERY}; use crate::wasm_emulation::query::mock_querier::QueryResultWithGas; @@ -9,18 +10,15 @@ use crate::wasm_emulation::output::WasmOutput; use crate::wasm_emulation::output::WasmRunnerOutput; use cosmwasm_std::testing::mock_env; use cosmwasm_vm::GasInfo; -use cw_orch_daemon::queriers::DaemonQuerier; use cosmwasm_std::{to_binary, Addr, ContractInfoResponse, SystemError, SystemResult}; use cosmwasm_std::{ContractResult, Empty}; -use cw_orch_daemon::queriers::CosmWasm; use cosmwasm_std::WasmQuery; #[cfg(feature = "cosmwasm_1_2")] use sha2::{Digest, Sha256}; use crate::wasm_emulation::channel::RemoteChannel; -use crate::WasmKeeper; use crate::wasm_emulation::input::{InstanceArguments, QueryArgs}; @@ -46,8 +44,7 @@ impl WasmQuerier { { local_contract.clone() } else { - WasmKeeper::::load_distant_contract(self.remote.clone(), &addr) - .unwrap() + WasmRemoteQuerier::load_distant_contract(self.remote.clone(), &addr).unwrap() }; let mut response = ContractInfoResponse::default(); response.code_id = data.code_id; @@ -73,15 +70,8 @@ impl WasmQuerier { { value.1.clone() } else { - let wasm_querier = CosmWasm::new(remote.channel); - let query_result = remote - .rt - .block_on( - wasm_querier - .contract_raw_state(contract_addr.to_string(), key.to_vec()), - ) - .map(|query_result| query_result.data); - query_result.unwrap() + WasmRemoteQuerier::raw_query(remote, contract_addr.clone(), key.clone()) + .unwrap() }; ( @@ -154,22 +144,16 @@ impl WasmQuerier { .wasm .code_data .get(&(*code_id as usize)); - let mut res = cosmwasm_std::CodeInfoResponse::default(); - if let Some(code_data) = code_data { + let res = if let Some(code_data) = code_data { + let mut res = cosmwasm_std::CodeInfoResponse::default(); res.code_id = *code_id; res.creator = code_data.creator.to_string(); res.checksum = cosmwasm_std::HexBinary::from( Sha256::digest(format!("contract code {}", code_data.seed)).to_vec(), ); + res } else { - // Remote case - let remote = self.remote.clone(); - let wasm_querier = CosmWasm::new(remote.channel); - - let code_info = remote.rt.block_on(wasm_querier.code(*code_id)).unwrap(); - res.code_id = *code_id; - res.creator = code_info.creator.to_string(); - res.checksum = code_info.data_hash.into(); + WasmRemoteQuerier::code_info(self.remote.clone(), *code_id).unwrap() }; ( SystemResult::Ok(to_binary(&res).into()), From 6d4c7fccb26bc9c406b47fc0e696724d8f06cdd6 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Wed, 29 Nov 2023 11:58:55 +0100 Subject: [PATCH 18/81] Closer to actual cw-multi-test --- src/app.rs | 32 +++--- src/bank.rs | 33 +++--- src/error.rs | 5 +- src/lib.rs | 2 - src/prefixed_storage/length_prefixed.rs | 10 +- src/wasm.rs | 127 ++++++++++-------------- 6 files changed, 83 insertions(+), 126 deletions(-) diff --git a/src/app.rs b/src/app.rs index 16f99502..37d49d5c 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,28 +1,10 @@ use crate::wasm_emulation::api::RealApi; use crate::wasm_emulation::channel::RemoteChannel; -use crate::AppBuilder; -use crate::GovFailingModule; -use crate::IbcFailingModule; -use cosmwasm_std::from_json; -use cosmwasm_std::to_json_binary; use cosmwasm_std::CustomMsg; use cw_storage_plus::Item; -use std::fmt::Debug; -use std::marker::PhantomData; - -use anyhow::bail; -use anyhow::Result as AnyResult; -use cosmwasm_std::testing::{MockApi, MockStorage}; -use cosmwasm_std::{ - Addr, Api, Binary, BlockInfo, ContractResult, CosmosMsg, CustomQuery, Empty, Querier, - QuerierResult, QuerierWrapper, QueryRequest, Record, Storage, SystemError, SystemResult, -}; -use schemars::JsonSchema; -use serde::de::DeserializeOwned; -use serde::Serialize; - use crate::bank::{Bank, BankKeeper, BankSudo}; +use crate::error::{bail, AnyResult}; use crate::executor::{AppResponse, Executor}; use crate::gov::Gov; use crate::ibc::Ibc; @@ -31,6 +13,17 @@ use crate::staking::{Distribution, DistributionKeeper, StakeKeeper, Staking, Sta use crate::transactions::transactional; use crate::wasm::{ContractData, Wasm, WasmKeeper, WasmSudo}; use crate::wasm_emulation::contract::WasmContract; +use crate::{AppBuilder, GovFailingModule, IbcFailingModule}; +use cosmwasm_std::testing::{MockApi, MockStorage}; +use cosmwasm_std::{ + from_json, to_json_binary, Addr, Api, Binary, BlockInfo, ContractResult, CosmosMsg, + CustomQuery, Empty, Querier, QuerierResult, QuerierWrapper, QueryRequest, Record, Storage, + SystemError, SystemResult, +}; +use schemars::JsonSchema; +use serde::{de::DeserializeOwned, Serialize}; +use std::fmt::Debug; +use std::marker::PhantomData; use crate::wasm_emulation::input::STARGATE_ALL_BANK_QUERY_URL; use crate::wasm_emulation::input::STARGATE_ALL_WASM_QUERY_URL; @@ -253,7 +246,6 @@ where } /// Registers contract code (like [store_code](Self::store_code)), - /// but takes the address of the code creator as an additional argument. pub fn store_code_with_creator(&mut self, creator: Addr, code: WasmContract) -> u64 { self.init_modules(|router, _, _| router.wasm.store_code(creator, code)) diff --git a/src/bank.rs b/src/bank.rs index c437da2e..68a488a8 100644 --- a/src/bank.rs +++ b/src/bank.rs @@ -1,25 +1,21 @@ +use crate::app::CosmosRouter; +use crate::error::{bail, AnyResult}; +use crate::executor::AppResponse; +use crate::module::Module; +use crate::prefixed_storage::{prefixed, prefixed_read}; use crate::queries::bank::BankRemoteQuerier; - -use anyhow::{bail, Result as AnyResult}; -use itertools::Itertools; -use schemars::JsonSchema; - +use crate::wasm_emulation::channel::RemoteChannel; +use crate::wasm_emulation::query::AllQuerier; use cosmwasm_std::{ coin, to_json_binary, Addr, AllBalanceResponse, Api, BalanceResponse, BankMsg, BankQuery, Binary, BlockInfo, Coin, Event, Querier, Storage, }; -use cw_storage_plus::Map; -use cw_utils::NativeBalance; - -use crate::app::CosmosRouter; -use crate::executor::AppResponse; -use crate::module::Module; -use crate::prefixed_storage::{prefixed, prefixed_read}; #[cfg(feature = "cosmwasm_1_1")] use cosmwasm_std::{Order, StdResult, SupplyResponse, Uint128}; - -use crate::wasm_emulation::channel::RemoteChannel; -use crate::wasm_emulation::query::AllQuerier; +use cw_storage_plus::Map; +use cw_utils::NativeBalance; +use itertools::Itertools; +use schemars::JsonSchema; pub(crate) const BALANCES: Map<&Addr, NativeBalance> = Map::new("balances"); @@ -77,11 +73,10 @@ impl BankKeeper { fn get_balance(&self, bank_storage: &dyn Storage, account: &Addr) -> AnyResult> { // If there is no balance present, we query it on the distant chain - if !BALANCES.has(bank_storage, account) { - BankRemoteQuerier::get_balance(self.remote.clone().unwrap(), account) + if let Some(val) = BALANCES.may_load(bank_storage, account)? { + Ok(val.into_vec()) } else { - let val = BALANCES.may_load(bank_storage, account)?; - Ok(val.unwrap_or_default().into_vec()) + BankRemoteQuerier::get_balance(self.remote.clone().unwrap(), account) } } diff --git a/src/error.rs b/src/error.rs index e6cace03..289a7949 100644 --- a/src/error.rs +++ b/src/error.rs @@ -28,10 +28,11 @@ pub enum Error { #[error("code id {0}: no such code")] UnregisteredCodeId(u64), - #[error("Unregistered contract address, not present locally or on-chain")] - UnregisteredContractAddress(String), #[error("Contract with this address already exists: {0}")] DuplicatedContractAddress(String), + + #[error("Unregistered contract address, not present locally or on-chain")] + UnregisteredContractAddress(String), } impl Error { diff --git a/src/lib.rs b/src/lib.rs index 429a223a..a6a47059 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,7 +33,6 @@ pub use crate::app_builder::{AppBuilder, BasicAppBuilder}; pub use crate::bank::{Bank, BankKeeper, BankSudo}; pub use crate::checksums::ChecksumGenerator; pub use crate::contracts::Contract; - pub use crate::executor::{AppResponse, Executor}; pub use crate::gov::{Gov, GovAcceptingModule, GovFailingModule}; pub use crate::ibc::{Ibc, IbcAcceptingModule, IbcFailingModule}; @@ -41,5 +40,4 @@ pub use crate::module::{AcceptingModule, FailingModule, Module}; pub use crate::staking::{ Distribution, DistributionKeeper, StakeKeeper, Staking, StakingInfo, StakingSudo, }; - pub use crate::wasm::{ContractData, Wasm, WasmKeeper, WasmSudo, LOCAL_CODE_OFFSET}; diff --git a/src/prefixed_storage/length_prefixed.rs b/src/prefixed_storage/length_prefixed.rs index 39bcee98..82eaf23b 100644 --- a/src/prefixed_storage/length_prefixed.rs +++ b/src/prefixed_storage/length_prefixed.rs @@ -6,10 +6,6 @@ //! Everything in this file is only responsible for building such keys //! and is not specific to any kind of storage. -use cosmwasm_std::Addr; - -use crate::wasm::NAMESPACE_WASM; - pub const CONTRACT_STORAGE_PREFIX: &str = "contract_data/"; /// Calculates the raw key prefix for a given namespace. /// @@ -54,15 +50,15 @@ pub fn decode_length(bytes: [u8; 2]) -> u32 { u32::from_be_bytes([0, 0, bytes[0], bytes[1]]) } -pub fn contract_namespace(contract: &Addr) -> Vec { +pub fn contract_namespace(contract: &cosmwasm_std::Addr) -> Vec { let mut name = CONTRACT_STORAGE_PREFIX.as_bytes().to_vec(); name.extend_from_slice(contract.as_bytes()); name } -pub fn get_full_contract_storage_namespace(contract_addr: &Addr) -> Vec { +pub fn get_full_contract_storage_namespace(contract_addr: &cosmwasm_std::Addr) -> Vec { let namespace = contract_namespace(contract_addr); - to_length_prefixed_nested(&[NAMESPACE_WASM, &namespace]) + to_length_prefixed_nested(&[crate::wasm::NAMESPACE_WASM, &namespace]) } #[cfg(test)] diff --git a/src/wasm.rs b/src/wasm.rs index c529de38..fe798ac6 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -1,42 +1,36 @@ +use crate::addresses::{AddressGenerator, SimpleAddressGenerator}; +use crate::app::{CosmosRouter, RouterQuerier}; +use crate::checksums::{ChecksumGenerator, SimpleChecksumGenerator}; +use crate::contracts::Contract; +use crate::error::{bail, AnyContext, AnyError, AnyResult, Error}; +use crate::executor::AppResponse; use crate::prefixed_storage::contract_namespace; +use crate::prefixed_storage::{prefixed, prefixed_read, PrefixedStorage, ReadonlyPrefixedStorage}; use crate::queries::wasm::WasmRemoteQuerier; +use crate::transactions::transactional; use crate::wasm_emulation::channel::RemoteChannel; -use cosmwasm_std::{CustomMsg, HexBinary}; - -use std::collections::HashMap; -use std::fmt::Debug; - +use crate::wasm_emulation::contract::WasmContract; +use crate::wasm_emulation::query::AllQuerier; +use cosmwasm_std::testing::mock_wasmd_attr; +use cosmwasm_std::CustomMsg; use cosmwasm_std::{ to_json_binary, Addr, Api, Attribute, BankMsg, Binary, BlockInfo, Coin, ContractInfo, - ContractInfoResponse, CustomQuery, Deps, DepsMut, Env, Event, MessageInfo, Order, Querier, - QuerierWrapper, Record, Reply, ReplyOn, Response, StdResult, Storage, SubMsg, SubMsgResponse, - SubMsgResult, TransactionInfo, WasmMsg, WasmQuery, + ContractInfoResponse, CustomQuery, Deps, DepsMut, Env, Event, HexBinary, MessageInfo, Order, + Querier, QuerierWrapper, Record, Reply, ReplyOn, Response, StdResult, Storage, SubMsg, + SubMsgResponse, SubMsgResult, TransactionInfo, WasmMsg, WasmQuery, }; - +use cw_storage_plus::Map; use prost::Message; use schemars::JsonSchema; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; - -use crate::addresses::{AddressGenerator, SimpleAddressGenerator}; -use cw_storage_plus::Map; - -use crate::app::{CosmosRouter, RouterQuerier}; -use crate::checksums::{ChecksumGenerator, SimpleChecksumGenerator}; -use crate::contracts::Contract; -use crate::error::{bail, AnyContext, AnyError, AnyResult, Error}; -use crate::executor::AppResponse; -use crate::prefixed_storage::{prefixed, prefixed_read, PrefixedStorage, ReadonlyPrefixedStorage}; -use crate::transactions::transactional; -use cosmwasm_std::testing::mock_wasmd_attr; +use std::collections::HashMap; +use std::fmt::Debug; //TODO Make `CONTRACTS` private in version 1.0 when the function AddressGenerator::next_address will be removed. /// Contract state kept in storage, separate from the contracts themselves (contract code). pub(crate) const CONTRACTS: Map<&Addr, ContractData> = Map::new("contracts"); -use crate::wasm_emulation::contract::WasmContract; -use crate::wasm_emulation::query::AllQuerier; - //TODO Make `NAMESPACE_WASM` private in version 1.0 when the function AddressGenerator::next_address will be removed. pub(crate) const NAMESPACE_WASM: &[u8] = b"wasm"; /// See @@ -138,15 +132,14 @@ pub struct WasmKeeper { pub code_base: HashMap, /// Code data with code base identifier and additional attributes. pub code_data: HashMap, - /// Just markers to make type elision fork when using it as `Wasm` trait - _e: std::marker::PhantomData, - /// Just markers to make type elision fork when using it as `Wasm` trait - _q: std::marker::PhantomData, + /// Contract's address generator. address_generator: Box, + /// Contract's code checksum generator. checksum_generator: Box, - // chain on which the contract should be queried/tested against remote: Option, + /// Just markers to make type elision fork when using it as `Wasm` trait + _p: std::marker::PhantomData<(ExecC, QueryC)>, } impl Default for WasmKeeper { @@ -154,10 +147,9 @@ impl Default for WasmKeeper { Self { code_base: HashMap::new(), code_data: HashMap::new(), - _e: std::marker::PhantomData, - _q: std::marker::PhantomData, address_generator: Box::new(SimpleAddressGenerator), checksum_generator: Box::new(SimpleChecksumGenerator), + _p: std::marker::PhantomData, remote: None, } } @@ -196,16 +188,11 @@ where } #[cfg(feature = "cosmwasm_1_2")] WasmQuery::CodeInfo { code_id } => { - let code_data = self.code_data(code_id); - let res = if let Ok(code_data) = code_data { - let mut res = cosmwasm_std::CodeInfoResponse::default(); - res.code_id = code_id; - res.creator = code_data.creator.to_string(); - res.checksum = code_data.checksum.clone(); - res - } else { - WasmRemoteQuerier::code_info(self.remote.clone().unwrap(), code_id)? - }; + let code_data = self.code_data(code_id)?; + let mut res = cosmwasm_std::CodeInfoResponse::default(); + res.code_id = code_id; + res.creator = code_data.creator.to_string(); + res.checksum = code_data.checksum.clone(); to_json_binary(&res).map_err(Into::into) } other => bail!(Error::UnsupportedWasmQuery(other)), @@ -308,38 +295,30 @@ where /// Returns a handler to code of the contract with specified code id. pub fn contract_code(&self, code_id: u64) -> AnyResult { let code_data = self.code_data(code_id)?; - Ok(self - .code_base - .get(&code_data.code_base_id) - .ok_or(Error::UnregisteredCodeId(code_id))? - .clone()) + let code = self.code_base.get(&code_data.code_base_id); + if let Some(code) = code { + Ok(code.clone()) + } else { + Ok(WasmContract::new_distant_code_id(code_id)) + } } /// Returns code data of the contract with specified code id. - fn code_data(&self, code_id: u64) -> AnyResult<&CodeData> { + fn code_data(&self, code_id: u64) -> AnyResult { if code_id < 1 { bail!(Error::InvalidCodeId); } - Ok(self - .code_data - .get(&(code_id as usize)) - .ok_or(Error::UnregisteredCodeId(code_id))?) - } - - /// This function won't error if it doesn't find the contract - /// This allows for querying an online contract struct without having to check if it exists just there - /// Upon execution, it will fail if the contract doesn't exist - fn get_code(&self, storage: &dyn Storage, address: &Addr) -> WasmContract { - if let Ok(handler) = self.contract_data(storage, address) { - let code = self.code_base.get(&(handler.code_id as usize)); - if let Some(code) = code { - return code.clone(); - } else { - return WasmContract::new_distant_code_id(handler.code_id); - } + if let Some(code_data) = self.code_data.get(&(code_id as usize)) { + Ok(code_data.clone()) + } else { + let code_info_response = + WasmRemoteQuerier::code_info(self.remote.clone().unwrap(), code_id)?; + Ok(CodeData { + creator: Addr::unchecked(code_info_response.creator), + checksum: code_info_response.checksum, + code_base_id: code_id as usize, + }) } - - WasmContract::new_distant_contract(address.to_string()) } pub fn dump_wasm_raw(&self, storage: &dyn Storage, address: &Addr) -> Vec { @@ -930,13 +909,8 @@ where )? } else { // generate non-predictable contract address - self.address_generator.contract_address( - api, - storage, - code_id, - instance_id, - //self.remote.clone().map(|c| c.chain.bech32_prefix), - )? + self.address_generator + .contract_address(api, storage, code_id, instance_id)? }; // contract with the same address must not already exist @@ -1079,8 +1053,8 @@ where where F: FnOnce(WasmContract, Deps, Env) -> AnyResult, { - let handler = self.get_code(storage, &address); - + let contract = self.contract_data(storage, &address)?; + let handler = self.contract_code(contract.code_id)?; let storage = self.contract_storage_readonly(storage, &address); let env = self.get_env(address, block); @@ -1105,7 +1079,8 @@ where F: FnOnce(WasmContract, DepsMut, Env) -> AnyResult, ExecC: DeserializeOwned, { - let handler = self.get_code(storage, &address); + let contract = self.contract_data(storage, &address)?; + let handler = self.contract_code(contract.code_id)?; // We don't actually need a transaction here, as it is already embedded in a transactional. // execute_submsg or App.execute_multi. From de437f2fd4da7dbd15505f54cc6f4a5627b263bd Mon Sep 17 00:00:00 2001 From: Kayanski Date: Wed, 29 Nov 2023 11:59:24 +0100 Subject: [PATCH 19/81] Format --- src/queries/bank.rs | 6 ++++-- src/queries/wasm.rs | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/queries/bank.rs b/src/queries/bank.rs index 405df53b..e0fe3b14 100644 --- a/src/queries/bank.rs +++ b/src/queries/bank.rs @@ -1,12 +1,14 @@ use std::str::FromStr; use anyhow::Result as AnyResult; -use cosmwasm_std::{Addr, Coin, Uint128, Storage, Order}; +use cosmwasm_std::{Addr, Coin, Order, Storage, Uint128}; use cw_orch_daemon::queriers::DaemonQuerier; use crate::{ + bank::{BALANCES, NAMESPACE_BANK}, + prefixed_storage::prefixed_read, wasm_emulation::{channel::RemoteChannel, input::BankStorage, query::AllQuerier}, - BankKeeper, prefixed_storage::prefixed_read, bank::{NAMESPACE_BANK, BALANCES}, + BankKeeper, }; pub struct BankRemoteQuerier; diff --git a/src/queries/wasm.rs b/src/queries/wasm.rs index ca5e4206..6d1ca06f 100644 --- a/src/queries/wasm.rs +++ b/src/queries/wasm.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use anyhow::Result as AnyResult; -use cosmwasm_std::{Addr, CodeInfoResponse, Order, Storage, Binary}; +use cosmwasm_std::{Addr, Binary, CodeInfoResponse, Order, Storage}; use cw_orch_daemon::queriers::{CosmWasm, DaemonQuerier}; use crate::{ From b2fd2b030fcde04bca765473878b4f4187e83928 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Wed, 29 Nov 2023 12:14:31 +0100 Subject: [PATCH 20/81] Fixed local test app, cousins missing --- Cargo.lock | 399 ++++++------------------------------- Cargo.toml | 40 ++-- examples/local_test_app.rs | 25 ++- 3 files changed, 90 insertions(+), 374 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 22e79686..50f536d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -92,6 +92,17 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +[[package]] +name = "async-recursion" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + [[package]] name = "async-stream" version = "0.3.5" @@ -213,12 +224,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d27c3610c36aee21ce8ac510e6224498de4228ad772a171ed65643a24693a5a8" -[[package]] -name = "base16ct" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" - [[package]] name = "base16ct" version = "0.2.0" @@ -249,15 +254,6 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - [[package]] name = "bip32" version = "0.5.1" @@ -266,7 +262,7 @@ checksum = "7e141fb0f8be1c7b45887af94c88b182472b57c96b56773250ae00cd6a14a164" dependencies = [ "bs58", "hmac", - "k256 0.13.2", + "k256", "once_cell", "pbkdf2 0.12.2", "rand_core 0.6.4", @@ -445,15 +441,6 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" -[[package]] -name = "convert_case" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" -dependencies = [ - "unicode-segmentation", -] - [[package]] name = "core-foundation" version = "0.9.3" @@ -503,10 +490,10 @@ checksum = "af13955d6f356272e6def9ff5e2450a7650df536d8934f47052a20c76513d2f6" dependencies = [ "bip32", "cosmos-sdk-proto", - "ecdsa 0.16.9", + "ecdsa", "eyre", "getrandom", - "k256 0.13.2", + "k256", "rand_core 0.6.4", "serde", "serde_json", @@ -524,9 +511,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8bb3c77c3b7ce472056968c745eb501c440fbc07be5004eba02782c35bfbbe3" dependencies = [ "digest 0.10.7", - "ecdsa 0.16.9", + "ecdsa", "ed25519-zebra", - "k256 0.13.2", + "k256", "rand_core 0.6.4", "thiserror", ] @@ -771,18 +758,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" -[[package]] -name = "crypto-bigint" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" -dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", -] - [[package]] name = "crypto-bigint" version = "0.5.5" @@ -911,11 +886,8 @@ name = "cw-multi-test" version = "0.19.0" dependencies = [ "anyhow", - "base64 0.21.5", "bech32", - "bincode", "cosmrs", - "cosmwasm-crypto", "cosmwasm-schema", "cosmwasm-std", "cosmwasm-vm", @@ -928,18 +900,13 @@ dependencies = [ "derivative", "dotenv", "env_logger", - "generic_static", "hex", "hex-literal", "ibc-chain-registry", - "ibc-relayer-types", "itertools 0.12.0", - "k256 0.11.6", - "lazy_static", "log", "moneymarket", "num-bigint", - "num-traits", "once_cell", "prost 0.12.3", "rustc-serialize", @@ -953,27 +920,16 @@ dependencies = [ "treediff", ] -[[package]] -name = "cw-orch-contract-derive" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1b46bb61c32f521c65cf445a1ebaf92fb2d9ecc93fca69da9a21cb62712aabe" -dependencies = [ - "convert_case", - "log", - "quote", - "syn 1.0.109", -] - [[package]] name = "cw-orch-core" -version = "0.16.2" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13258e0fad1fd79b01d794877810963e908dab0e0899e7a8a65ae7a9eba3217f" +checksum = "fad948ad25e5032d8422722455ccea11165cb7179ba7eea23755cb4575d20395" dependencies = [ "abstract-cw-multi-test", "anyhow", "cosmwasm-std", + "dirs", "log", "serde", "serde_json", @@ -983,24 +939,23 @@ dependencies = [ [[package]] name = "cw-orch-daemon" -version = "0.16.5" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3575b1303d0e7bce902f2bec4b54f249d8a50841eae8a442cdaad0a370ae913f" +checksum = "ba3b27b19c80156b5e51db481e9a9a034e59449ecf74bde687b0f2e5ba73dfbb" dependencies = [ "abstract-cw-multi-test", "anyhow", + "async-recursion", "base16", "base64 0.21.5", "bitcoin", "chrono", "cosmrs", "cosmwasm-std", - "cw-orch-contract-derive", "cw-orch-core", - "cw-orch-fns-derive", "cw-orch-networks", "cw-orch-traits", - "derive_builder", + "dirs", "ed25519-dalek", "eyre", "flate2", @@ -1013,46 +968,34 @@ dependencies = [ "prost-types", "rand_core 0.6.4", "reqwest", - "ring 0.16.20", + "ring 0.17.5", "ripemd", "schemars", "secp256k1", "serde", "serde_json", "sha256", - "shellexpand", "thiserror", "tokio", "tonic", ] -[[package]] -name = "cw-orch-fns-derive" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db7242ad1ad0436acb8521f8063b76355172912f058aa6e6b986669ca35b5c4f" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "cw-orch-networks" -version = "0.16.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5a4ad254bda4d5af6631b7b2342941d720b31c2eaadb3c9f746b46940ee3f4f" +checksum = "ac3154369d45874abd908af736a675fc2530bcf2836a7840684554caa6532336" dependencies = [ + "cw-orch-core", "ibc-chain-registry", "serde", ] [[package]] name = "cw-orch-traits" -version = "0.16.2" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a81a36ac603e49eecbaca0c76ed02d05bf793bd64ef303fb4bf2d8b0b152efd" +checksum = "e3a5d92716089d3673ce416b7068766b33a918f55b37f2210e386f6ff4c1c1ec" dependencies = [ "cw-orch-core", "prost 0.11.9", @@ -1184,38 +1127,14 @@ dependencies = [ "thiserror", ] -[[package]] -name = "darling" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" -dependencies = [ - "darling_core 0.14.4", - "darling_macro 0.14.4", -] - [[package]] name = "darling" version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" dependencies = [ - "darling_core 0.20.3", - "darling_macro 0.20.3", -] - -[[package]] -name = "darling_core" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 1.0.109", + "darling_core", + "darling_macro", ] [[package]] @@ -1231,24 +1150,13 @@ dependencies = [ "syn 2.0.39", ] -[[package]] -name = "darling_macro" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" -dependencies = [ - "darling_core 0.14.4", - "quote", - "syn 1.0.109", -] - [[package]] name = "darling_macro" version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ - "darling_core 0.20.3", + "darling_core", "quote", "syn 2.0.39", ] @@ -1266,16 +1174,6 @@ dependencies = [ "parking_lot_core", ] -[[package]] -name = "der" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" -dependencies = [ - "const-oid", - "zeroize", -] - [[package]] name = "der" version = "0.7.8" @@ -1306,37 +1204,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "derive_builder" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" -dependencies = [ - "derive_builder_macro", -] - -[[package]] -name = "derive_builder_core" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" -dependencies = [ - "darling 0.14.4", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "derive_builder_macro" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" -dependencies = [ - "derive_builder_core", - "syn 1.0.109", -] - [[package]] name = "derive_more" version = "0.99.17" @@ -1428,30 +1295,18 @@ dependencies = [ "memmap2 0.5.10", ] -[[package]] -name = "ecdsa" -version = "0.14.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" -dependencies = [ - "der 0.6.1", - "elliptic-curve 0.12.3", - "rfc6979 0.3.1", - "signature 1.6.4", -] - [[package]] name = "ecdsa" version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ - "der 0.7.8", + "der", "digest 0.10.7", - "elliptic-curve 0.13.8", - "rfc6979 0.4.0", - "signature 2.2.0", - "spki 0.7.2", + "elliptic-curve", + "rfc6979", + "signature", + "spki", ] [[package]] @@ -1460,9 +1315,9 @@ version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ - "pkcs8 0.10.2", + "pkcs8", "serde", - "signature 2.2.0", + "signature", ] [[package]] @@ -1513,41 +1368,21 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" -[[package]] -name = "elliptic-curve" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" -dependencies = [ - "base16ct 0.1.1", - "crypto-bigint 0.4.9", - "der 0.6.1", - "digest 0.10.7", - "ff 0.12.1", - "generic-array", - "group 0.12.1", - "pkcs8 0.9.0", - "rand_core 0.6.4", - "sec1 0.3.0", - "subtle", - "zeroize", -] - [[package]] name = "elliptic-curve" version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ - "base16ct 0.2.0", - "crypto-bigint 0.5.5", + "base16ct", + "crypto-bigint", "digest 0.10.7", - "ff 0.13.0", + "ff", "generic-array", - "group 0.13.0", - "pkcs8 0.10.2", + "group", + "pkcs8", "rand_core 0.6.4", - "sec1 0.7.3", + "sec1", "subtle", "zeroize", ] @@ -1596,7 +1431,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af" dependencies = [ - "darling 0.20.3", + "darling", "proc-macro2", "quote", "syn 2.0.39", @@ -1662,16 +1497,6 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" -[[package]] -name = "ff" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" -dependencies = [ - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "ff" version = "0.13.0" @@ -1869,15 +1694,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "generic_static" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28ccff179d8070317671db09aee6d20affc26e88c5394714553b04f509b43a60" -dependencies = [ - "once_cell", -] - [[package]] name = "getrandom" version = "0.2.11" @@ -1908,24 +1724,13 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" -[[package]] -name = "group" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" -dependencies = [ - "ff 0.12.1", - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "group" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ - "ff 0.13.0", + "ff", "rand_core 0.6.4", "subtle", ] @@ -2409,18 +2214,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "k256" -version = "0.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" -dependencies = [ - "cfg-if", - "ecdsa 0.14.8", - "elliptic-curve 0.12.3", - "sha2 0.10.8", -] - [[package]] name = "k256" version = "0.13.2" @@ -2428,11 +2221,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f01b677d82ef7a676aa37e099defd83a28e15687112cafdd112d60236b6115b" dependencies = [ "cfg-if", - "ecdsa 0.16.9", - "elliptic-curve 0.13.8", + "ecdsa", + "elliptic-curve", "once_cell", "sha2 0.10.8", - "signature 2.2.0", + "signature", ] [[package]] @@ -2864,24 +2657,14 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "pkcs8" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" -dependencies = [ - "der 0.6.1", - "spki 0.6.0", -] - [[package]] name = "pkcs8" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der 0.7.8", - "spki 0.7.2", + "der", + "spki", ] [[package]] @@ -3223,17 +3006,6 @@ dependencies = [ "winreg", ] -[[package]] -name = "rfc6979" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" -dependencies = [ - "crypto-bigint 0.4.9", - "hmac", - "zeroize", -] - [[package]] name = "rfc6979" version = "0.4.0" @@ -3511,30 +3283,16 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" -[[package]] -name = "sec1" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" -dependencies = [ - "base16ct 0.1.1", - "der 0.6.1", - "generic-array", - "pkcs8 0.9.0", - "subtle", - "zeroize", -] - [[package]] name = "sec1" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ - "base16ct 0.2.0", - "der 0.7.8", + "base16ct", + "der", "generic-array", - "pkcs8 0.10.2", + "pkcs8", "subtle", "zeroize", ] @@ -3755,15 +3513,6 @@ dependencies = [ "memmap2 0.6.2", ] -[[package]] -name = "shellexpand" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da03fa3b94cc19e3ebfc88c4229c49d8f08cdbd1228870a45f0ffdf84988e14b" -dependencies = [ - "dirs", -] - [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -3773,16 +3522,6 @@ dependencies = [ "libc", ] -[[package]] -name = "signature" -version = "1.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" -dependencies = [ - "digest 0.10.7", - "rand_core 0.6.4", -] - [[package]] name = "signature" version = "2.2.0" @@ -3852,16 +3591,6 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -[[package]] -name = "spki" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" -dependencies = [ - "base64ct", - "der 0.6.1", -] - [[package]] name = "spki" version = "0.7.2" @@ -3869,7 +3598,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" dependencies = [ "base64ct", - "der 0.7.8", + "der", ] [[package]] @@ -3884,12 +3613,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "strum" version = "0.24.1" @@ -4016,7 +3739,7 @@ dependencies = [ "ed25519-consensus", "flex-error", "futures", - "k256 0.13.2", + "k256", "num-traits", "once_cell", "prost 0.11.9", @@ -4027,7 +3750,7 @@ dependencies = [ "serde_json", "serde_repr", "sha2 0.10.8", - "signature 2.2.0", + "signature", "subtle", "subtle-encoding", "tendermint-proto", @@ -4474,12 +4197,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-segmentation" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" - [[package]] name = "untrusted" version = "0.7.1" diff --git a/Cargo.toml b/Cargo.toml index c8a8694f..22ade676 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,42 +34,32 @@ serde = "1.0.193" sha2 = "0.10.8" thiserror = "1.0.50" -# We don't use the following dependencies directly. They're dependencies of our dependencies. -# We specify them to tighten their version requirements so that builds with `-Zminimal-versions` work. -# Once we bump `cosmwasm-*` deps to a version after `1.1.5`, we can remove these. -k256 = { version = "0.11.1", features = ["ecdsa"] } -cw-orch-daemon = { version = "0.16.0" } -cw-orch-networks = { version = "0.16.0" } +# Clone testing deps +## Network +cw-orch-daemon = { version = "0.18.0" } +cw-orch-networks = { version = "0.18.0" } tokio = "1.28.2" ibc-chain-registry = "0.25.0" +tonic = "0.9.2" + +## Emulation cosmwasm-vm = { version = "1.2", features = [ "staking", "stargate", "iterator", ] } -bincode = "1.3.3" -base64 = "0.21.2" -cw20 = "1.0.1" -ibc-relayer-types = "0.25.1" + +## Dual Storage cosmrs = "0.14.0" num-bigint = "0.4.3" -num-traits = "0.2.15" -cosmwasm-crypto = "1.2.7" -tonic = "0.9.2" -generic_static = "0.2.0" -once_cell = "1.18.0" -lazy_static = "1.4.0" -log = "0.4.19" -env_logger = "0.10.0" -cosmwasm-schema = "1.2.7" + +# Analyzer treediff = { version = "4.0.2", features = ["with-rustc-serialize"] } rustc-serialize = "0.3.24" serde_json = "1.0.105" +log = "0.4.19" [dev-dependencies] -# We don't use the following dependency directly, -# we tighten the version so that builds with `-Zminimal-versions` work. -serde_json = "1.0.105" dotenv = "0.15.0" cw-asset = "3.0.0" @@ -77,4 +67,10 @@ hex = "0.4.3" hex-literal = "0.4.1" once_cell = "1.18.0" +# General +env_logger = "0.10.0" +cosmwasm-schema = "1.2.7" + +# Cavern Test App +cw20 = "1.0.1" moneymarket = { git = "https://github.com/CavernPerson/money-market-contracts" } diff --git a/examples/local_test_app.rs b/examples/local_test_app.rs index 523e9adf..4077c7ab 100644 --- a/examples/local_test_app.rs +++ b/examples/local_test_app.rs @@ -1,14 +1,15 @@ -// use ibc_chain_registry::chain::ChainData; +// use cw_multi_test::wasm_emulation::channel::RemoteChannel; // use std::path::Path; +// use tokio::runtime::Runtime; // use cosmwasm_schema::{cw_serde, QueryResponses}; // use cosmwasm_std::Empty; +// use cw_multi_test::error::AnyResult; // use cw_multi_test::wasm_emulation::contract::WasmContract; // use cw_multi_test::wasm_emulation::storage::analyzer::StorageAnalyzer; // use cw_multi_test::AppBuilder; // use cw_multi_test::Executor; -// use cw_multi_test::FailingModule; // use cw_multi_test::WasmKeeper; // use cw_orch_daemon::networks::PHOENIX_1; @@ -59,19 +60,20 @@ // pub t: String, // } -// pub fn main() { +// pub fn test() -> AnyResult<()> { // env_logger::init(); -// let chain: ChainData = PHOENIX_1.into(); +// let runtime = Runtime::new()?; +// let chain = PHOENIX_1; +// let remote_channel = RemoteChannel::new(&runtime, chain)?; -// let mut wasm = WasmKeeper::::new(); -// wasm.set_chain(chain.clone()); +// let wasm = WasmKeeper::::new().with_remote(remote_channel.clone()); // // First we instantiate a new app // let app = AppBuilder::default() -// .with_chain(chain.clone()) -// .with_wasm::, _>(wasm); -// let mut app = app.build(|_, _, _| {}); +// .with_remote(remote_channel.clone()) +// .with_wasm(wasm); +// let mut app = app.build(|_, _, _| {})?; // // Then we send a message to the blockchain through the app // let sender = app.next_address(); @@ -82,7 +84,7 @@ // .join("counter_contract.wasm"), // ) // .unwrap(); -// let counter_contract = WasmContract::new_local(code, chain.clone()); +// let counter_contract = WasmContract::new_local(code); // let code_id = app.store_code(counter_contract); @@ -164,7 +166,7 @@ // // Analyze the storage -// let analysis = StorageAnalyzer::new(&app, chain).unwrap(); +// let analysis = StorageAnalyzer::new(&app).unwrap(); // log::info!( // "analysis, wasm1 {:?}", @@ -181,6 +183,7 @@ // analysis.all_readable_contract_storage() // ); // analysis.compare_all_readable_contract_storage(); +// Ok(()) // } fn main() {} From 60e19e934f5915d51f220b8c199f9a42cb39848f Mon Sep 17 00:00:00 2001 From: Kayanski Date: Wed, 29 Nov 2023 13:43:03 +0100 Subject: [PATCH 21/81] =?UTF-8?q?Less=20dependencies=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 31 ------------------------------- Cargo.toml | 3 --- 2 files changed, 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 50f536d0..e17edb72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -843,29 +843,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "cw-address-like" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451a4691083a88a3c0630a8a88799e9d4cd6679b7ce8ff22b8da2873ff31d380" -dependencies = [ - "cosmwasm-std", -] - -[[package]] -name = "cw-asset" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e2cf17accdcafe71859a683b6ed3f18311634a769550aacf4829b50151b221" -dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-address-like", - "cw-storage-plus 1.2.0", - "cw20 1.1.2", - "thiserror", -] - [[package]] name = "cw-controllers" version = "1.1.2" @@ -891,14 +868,12 @@ dependencies = [ "cosmwasm-schema", "cosmwasm-std", "cosmwasm-vm", - "cw-asset", "cw-orch-daemon", "cw-orch-networks", "cw-storage-plus 1.2.0", "cw-utils 1.0.3", "cw20 1.1.2", "derivative", - "dotenv", "env_logger", "hex", "hex-literal", @@ -1257,12 +1232,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "dotenv" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" - [[package]] name = "dyn-clone" version = "1.0.16" diff --git a/Cargo.toml b/Cargo.toml index 22ade676..eaba048b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,9 +60,6 @@ serde_json = "1.0.105" log = "0.4.19" [dev-dependencies] - -dotenv = "0.15.0" -cw-asset = "3.0.0" hex = "0.4.3" hex-literal = "0.4.1" once_cell = "1.18.0" From a9f94cf7d10cae9ae11fd5d08a089b2cf8e2c08c Mon Sep 17 00:00:00 2001 From: Kayanski Date: Wed, 29 Nov 2023 17:37:43 +0100 Subject: [PATCH 22/81] Updated for cw-orch-interchain --- Cargo.toml | 2 +- src/addons/api/bech32.rs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index eaba048b..e90a8bf8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ cosmwasm-std = { version = "1.5.0", features = [ "staking", "stargate", ] } -cw-storage-plus = "1.2.0" +cw-storage-plus = "1.1.0" cw-utils = "1.0.3" derivative = "2.2.0" itertools = "0.12.0" diff --git a/src/addons/api/bech32.rs b/src/addons/api/bech32.rs index f2fd739f..55b21cc3 100644 --- a/src/addons/api/bech32.rs +++ b/src/addons/api/bech32.rs @@ -11,7 +11,7 @@ use sha2::{Digest, Sha256}; /// [`Bech32`]:https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki pub struct MockApiBech32 { api: MockApi, - prefix: &'static str, + prefix: String, variant: Variant, } @@ -29,16 +29,16 @@ impl MockApiBech32 { /// assert_eq!(addr.as_str(), /// "juno1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqsksmtyp"); /// ``` - pub fn new(prefix: &'static str) -> Self { + pub fn new(prefix: &str) -> Self { Self::new_with_variant(prefix, Variant::Bech32) } /// Creates `Api` implementation that uses specified prefix /// to generate addresses in format defined by provided Bech32 variant. - pub(crate) fn new_with_variant(prefix: &'static str, variant: Variant) -> Self { + pub(crate) fn new_with_variant(prefix: &str, variant: Variant) -> Self { Self { api: MockApi::default(), - prefix, + prefix: prefix.to_string(), variant, } } @@ -108,7 +108,7 @@ impl Api for MockApiBech32 { /// addr.as_str()); /// ``` fn addr_humanize(&self, canonical: &CanonicalAddr) -> StdResult { - if let Ok(encoded) = encode(self.prefix, canonical.as_slice().to_base32(), self.variant) { + if let Ok(encoded) = encode(&self.prefix, canonical.as_slice().to_base32(), self.variant) { Ok(Addr::unchecked(encoded)) } else { Err(StdError::generic_err("Invalid canonical address")) @@ -179,7 +179,7 @@ impl MockApiBech32 { /// format is not possible, especially when prefix is too long or empty. pub fn addr_make(&self, input: &str) -> Addr { let digest = Sha256::digest(input).to_vec(); - match encode(self.prefix, digest.to_base32(), self.variant) { + match encode(&self.prefix, digest.to_base32(), self.variant) { Ok(address) => Addr::unchecked(address), Err(reason) => panic!("Generating address failed with reason: {}", reason), } From aa588fd816d2a8e7f2b9c1a7920158289fc3b41d Mon Sep 17 00:00:00 2001 From: Kayanski Date: Fri, 1 Dec 2023 00:25:53 +0100 Subject: [PATCH 23/81] Corrected ley querying for storage --- src/wasm_emulation/storage/dual_storage.rs | 30 ++++++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/wasm_emulation/storage/dual_storage.rs b/src/wasm_emulation/storage/dual_storage.rs index 2cf419a9..fc72087c 100644 --- a/src/wasm_emulation/storage/dual_storage.rs +++ b/src/wasm_emulation/storage/dual_storage.rs @@ -46,7 +46,7 @@ use std::collections::HashSet; use anyhow::Result as AnyResult; const DISTANT_LIMIT: u64 = 5u64; -#[derive(Default, Debug)] +#[derive(Default, Debug, Clone)] struct DistantIter { data: Vec, position: usize, @@ -57,7 +57,7 @@ struct DistantIter { } /// Iterator to get multiple keys -#[derive(Default, Debug)] +#[derive(Default, Debug, Clone)] struct Iter { distant_iter: DistantIter, local_iter: u32, @@ -158,7 +158,7 @@ impl Storage for DualStorage { .try_into() .expect("Found more iterator IDs than supported"); let new_id = last_id + 1; - self.iterators.insert(new_id, iter); + self.iterators.insert(new_id, iter.clone()); (Ok(new_id), gas_info) } @@ -168,10 +168,11 @@ impl Storage for DualStorage { let iterator = match self.iterators.get_mut(&iterator_id) { Some(i) => i, None => { + println!("End next premature"); return ( Err(BackendError::iterator_does_not_exist(iterator_id)), GasInfo::free(), - ) + ); } }; @@ -195,7 +196,26 @@ impl Storage for DualStorage { )) .unwrap(); - iterator.distant_iter.data.extend(new_keys.models); + // We make sure the data queried correspond to all the keys we need + iterator + .distant_iter + .data + .extend(new_keys.models.into_iter().filter(|m| { + let lower_than_end = if let Some(end) = iterator.distant_iter.end.clone() { + !gte(m.key.clone(), end) + } else { + true + }; + + let higher_than_start = if let Some(start) = iterator.distant_iter.start.clone() + { + gte(m.key.clone(), start) + } else { + true + }; + + lower_than_end && higher_than_start + })); iterator.distant_iter.key = Some(new_keys.pagination.unwrap().next_key); } From c65e669578df467377148251f3f922b2c41950de Mon Sep 17 00:00:00 2001 From: Kayanski Date: Fri, 1 Dec 2023 09:32:07 +0100 Subject: [PATCH 24/81] Distant contract state query never fails --- src/wasm_emulation/storage/dual_storage.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wasm_emulation/storage/dual_storage.rs b/src/wasm_emulation/storage/dual_storage.rs index fc72087c..93185cec 100644 --- a/src/wasm_emulation/storage/dual_storage.rs +++ b/src/wasm_emulation/storage/dual_storage.rs @@ -194,7 +194,7 @@ impl Storage for DualStorage { reverse: iterator.distant_iter.reverse, }), )) - .unwrap(); + .unwrap_or_default(); // We make sure the data queried correspond to all the keys we need iterator @@ -216,7 +216,7 @@ impl Storage for DualStorage { lower_than_end && higher_than_start })); - iterator.distant_iter.key = Some(new_keys.pagination.unwrap().next_key); + iterator.distant_iter.key = new_keys.pagination.map(|p| p.next_key); } // 2. We find the first key in order between distant and local storage From 30528e911ce3d18cfc20f188a754c6caa7136739 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Wed, 13 Dec 2023 11:11:37 +0100 Subject: [PATCH 25/81] Updated cw-orch to 0.19 --- Cargo.lock | 226 ++++++++++++++++++++++++++++++++++++++++------------- Cargo.toml | 10 +-- 2 files changed, 177 insertions(+), 59 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e17edb72..e30f7724 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -263,8 +263,6 @@ dependencies = [ "bs58", "hmac", "k256", - "once_cell", - "pbkdf2 0.12.2", "rand_core 0.6.4", "ripemd", "sha2 0.10.8", @@ -472,34 +470,34 @@ dependencies = [ [[package]] name = "cosmos-sdk-proto" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73c9d2043a9e617b0d602fbc0a0ecd621568edbf3a9774890a6d562389bd8e1c" +checksum = "32560304ab4c365791fd307282f76637213d8083c1a98490c35159cd67852237" dependencies = [ - "prost 0.11.9", - "prost-types", - "tendermint-proto", - "tonic", + "prost 0.12.3", + "prost-types 0.12.3", + "tendermint-proto 0.34.0", + "tonic 0.10.2", ] [[package]] name = "cosmrs" -version = "0.14.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af13955d6f356272e6def9ff5e2450a7650df536d8934f47052a20c76513d2f6" +checksum = "47126f5364df9387b9d8559dcef62e99010e1d4098f39eb3f7ee4b5c254e40ea" dependencies = [ "bip32", "cosmos-sdk-proto", "ecdsa", "eyre", - "getrandom", "k256", "rand_core 0.6.4", "serde", "serde_json", + "signature", "subtle-encoding", - "tendermint", - "tendermint-rpc", + "tendermint 0.34.0", + "tendermint-rpc 0.34.0", "thiserror", "tokio", ] @@ -860,7 +858,7 @@ dependencies = [ [[package]] name = "cw-multi-test" -version = "0.19.0" +version = "0.19.3" dependencies = [ "anyhow", "bech32", @@ -891,19 +889,20 @@ dependencies = [ "sha2 0.10.8", "thiserror", "tokio", - "tonic", + "tonic 0.10.2", "treediff", ] [[package]] name = "cw-orch-core" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fad948ad25e5032d8422722455ccea11165cb7179ba7eea23755cb4575d20395" +checksum = "90742906d091e509f185bb26c07706c037949ddaaa522bb3f3927b53835cc1fd" dependencies = [ "abstract-cw-multi-test", "anyhow", "cosmwasm-std", + "cw-utils 1.0.3", "dirs", "log", "serde", @@ -914,11 +913,10 @@ dependencies = [ [[package]] name = "cw-orch-daemon" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3b27b19c80156b5e51db481e9a9a034e59449ecf74bde687b0f2e5ba73dfbb" +checksum = "95104f4caf23482ac067d67a787dce34391c548fae496210c4b36bb14c9397d9" dependencies = [ - "abstract-cw-multi-test", "anyhow", "async-recursion", "base16", @@ -939,8 +937,8 @@ dependencies = [ "ibc-chain-registry", "ibc-relayer-types", "log", - "prost 0.11.9", - "prost-types", + "prost 0.12.3", + "prost-types 0.11.9", "rand_core 0.6.4", "reqwest", "ring 0.17.5", @@ -952,14 +950,14 @@ dependencies = [ "sha256", "thiserror", "tokio", - "tonic", + "tonic 0.10.2", ] [[package]] name = "cw-orch-networks" -version = "0.18.1" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3154369d45874abd908af736a675fc2530bcf2836a7840684554caa6532336" +checksum = "6a08ab813c374ef74560c661c1c444c3ea0425d14938671fa1c529d6efa348b7" dependencies = [ "cw-orch-core", "ibc-chain-registry", @@ -968,13 +966,13 @@ dependencies = [ [[package]] name = "cw-orch-traits" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a5d92716089d3673ce416b7068766b33a918f55b37f2210e386f6ff4c1c1ec" +checksum = "f786295d8d9754466f8bdb94a67d6c9c647937450bcb4bb12403174800ae1ae7" dependencies = [ "cw-orch-core", "prost 0.11.9", - "prost-types", + "prost-types 0.11.9", ] [[package]] @@ -1800,7 +1798,7 @@ checksum = "1e013a4f0b8772418eee1fc462e74017aba13c364a7b61bd3df1ddcbfe47b065" dependencies = [ "hmac", "once_cell", - "pbkdf2 0.11.0", + "pbkdf2", "rand_core 0.6.4", "sha2 0.10.8", "subtle-encoding", @@ -1995,7 +1993,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "tendermint-rpc", + "tendermint-rpc 0.32.2", "tokio", "tracing", ] @@ -2013,8 +2011,8 @@ dependencies = [ "prost 0.11.9", "serde", "subtle-encoding", - "tendermint-proto", - "tonic", + "tendermint-proto 0.32.2", + "tonic 0.9.2", ] [[package]] @@ -2039,9 +2037,9 @@ dependencies = [ "serde_derive", "serde_json", "subtle-encoding", - "tendermint", + "tendermint 0.32.2", "tendermint-light-client-verifier", - "tendermint-proto", + "tendermint-proto 0.32.2", "time", "uint", ] @@ -2551,16 +2549,6 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "pbkdf2" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" -dependencies = [ - "digest 0.10.7", - "hmac", -] - [[package]] name = "peg" version = "0.7.0" @@ -2759,6 +2747,15 @@ dependencies = [ "prost 0.11.9", ] +[[package]] +name = "prost-types" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" +dependencies = [ + "prost 0.12.3", +] + [[package]] name = "ptr_meta" version = "0.1.4" @@ -2958,6 +2955,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "rustls 0.21.9", + "rustls-native-certs 0.6.3", "rustls-pemfile", "serde", "serde_json", @@ -3708,11 +3706,40 @@ dependencies = [ "ed25519-consensus", "flex-error", "futures", - "k256", "num-traits", "once_cell", "prost 0.11.9", - "prost-types", + "prost-types 0.11.9", + "serde", + "serde_bytes", + "serde_json", + "serde_repr", + "sha2 0.10.8", + "signature", + "subtle", + "subtle-encoding", + "tendermint-proto 0.32.2", + "time", + "zeroize", +] + +[[package]] +name = "tendermint" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc2294fa667c8b548ee27a9ba59115472d0a09c2ba255771092a7f1dcf03a789" +dependencies = [ + "bytes", + "digest 0.10.7", + "ed25519", + "ed25519-consensus", + "flex-error", + "futures", + "k256", + "num-traits", + "once_cell", + "prost 0.12.3", + "prost-types 0.12.3", "ripemd", "serde", "serde_bytes", @@ -3722,7 +3749,7 @@ dependencies = [ "signature", "subtle", "subtle-encoding", - "tendermint-proto", + "tendermint-proto 0.34.0", "time", "zeroize", ] @@ -3736,7 +3763,21 @@ dependencies = [ "flex-error", "serde", "serde_json", - "tendermint", + "tendermint 0.32.2", + "toml", + "url", +] + +[[package]] +name = "tendermint-config" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a25dbe8b953e80f3d61789fbdb83bf9ad6c0ef16df5ca6546f49912542cc137" +dependencies = [ + "flex-error", + "serde", + "serde_json", + "tendermint 0.34.0", "toml", "url", ] @@ -3750,7 +3791,7 @@ dependencies = [ "derive_more", "flex-error", "serde", - "tendermint", + "tendermint 0.32.2", "time", ] @@ -3765,7 +3806,25 @@ dependencies = [ "num-derive", "num-traits", "prost 0.11.9", - "prost-types", + "prost-types 0.11.9", + "serde", + "serde_bytes", + "subtle-encoding", + "time", +] + +[[package]] +name = "tendermint-proto" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cc728a4f9e891d71adf66af6ecaece146f9c7a11312288a3107b3e1d6979aaf" +dependencies = [ + "bytes", + "flex-error", + "num-derive", + "num-traits", + "prost 0.12.3", + "prost-types 0.12.3", "serde", "serde_bytes", "subtle-encoding", @@ -3796,9 +3855,41 @@ dependencies = [ "serde_json", "subtle", "subtle-encoding", - "tendermint", - "tendermint-config", - "tendermint-proto", + "tendermint 0.32.2", + "tendermint-config 0.32.2", + "tendermint-proto 0.32.2", + "thiserror", + "time", + "tokio", + "tracing", + "url", + "uuid 0.8.2", + "walkdir", +] + +[[package]] +name = "tendermint-rpc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbf0a4753b46a190f367337e0163d0b552a2674a6bac54e74f9f2cdcde2969b" +dependencies = [ + "async-trait", + "bytes", + "flex-error", + "futures", + "getrandom", + "peg", + "pin-project", + "reqwest", + "semver", + "serde", + "serde_bytes", + "serde_json", + "subtle", + "subtle-encoding", + "tendermint 0.34.0", + "tendermint-config 0.34.0", + "tendermint-proto 0.34.0", "thiserror", "time", "tokio", @@ -4002,7 +4093,6 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3082666a3a6433f7f511c7192923fa1fe07c69332d3c6a2e6bb040b569199d5a" dependencies = [ - "async-stream", "async-trait", "axum", "base64 0.21.5", @@ -4017,6 +4107,34 @@ dependencies = [ "percent-encoding", "pin-project", "prost 0.11.9", + "tokio", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d560933a0de61cf715926b9cac824d4c883c2c43142f787595e48280c40a1d0e" +dependencies = [ + "async-stream", + "async-trait", + "axum", + "base64 0.21.5", + "bytes", + "h2", + "http", + "http-body", + "hyper", + "hyper-timeout", + "percent-encoding", + "pin-project", + "prost 0.12.3", + "rustls 0.21.9", "rustls-native-certs 0.6.3", "rustls-pemfile", "tokio", diff --git a/Cargo.toml b/Cargo.toml index e90a8bf8..4d391a8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cw-multi-test" -version = "0.19.0" +version = "0.19.3" authors = ["Ethan Frey "] edition = "2021" description = "Testing tools for multi-contract interactions" @@ -36,11 +36,11 @@ thiserror = "1.0.50" # Clone testing deps ## Network -cw-orch-daemon = { version = "0.18.0" } -cw-orch-networks = { version = "0.18.0" } +cw-orch-daemon = { version = "0.19.0" } +cw-orch-networks = { version = "0.19.0" } tokio = "1.28.2" ibc-chain-registry = "0.25.0" -tonic = "0.9.2" +tonic = "0.10.2" ## Emulation cosmwasm-vm = { version = "1.2", features = [ @@ -50,7 +50,7 @@ cosmwasm-vm = { version = "1.2", features = [ ] } ## Dual Storage -cosmrs = "0.14.0" +cosmrs = "0.15.0" num-bigint = "0.4.3" # Analyzer From e38ad44a3b6c08b303acef1cf4cb207cdf3786c9 Mon Sep 17 00:00:00 2001 From: Kayanski <44806566+Kayanski@users.noreply.github.com> Date: Tue, 19 Dec 2023 13:43:58 +0100 Subject: [PATCH 26/81] Update/add rust contracts (#3) * Integrated rust contracts * Some clippy fixes ? * Less unsafe code * Fixed with features * Added dual storage for cosmwas-std * Added dual storage for wrappers as well * Added storage and querier inside rust code contracts * Modified storage accessor to just wrap * Fixed contract address when querying contract * Fixed raw query return * Updated deps * Corrected querier storage after funds transfer on execute * Removed prints * Fixed minor print error * Updated api in wasm-emulation querier * Fix clippy --- Cargo.lock | 20 +- Cargo.toml | 5 + examples/cavern_test_app.rs | 12 +- examples/counter/contract.rs | 134 ++++++ examples/counter/error.rs | 16 + examples/counter/execute.rs | 39 ++ examples/counter/interface.rs | 65 +++ examples/counter/mod.rs | 8 + examples/counter/msg.rs | 62 +++ examples/counter/query.rs | 30 ++ examples/counter/state.rs | 14 + examples/cousin_test.rs | 154 ++++++ src/app.rs | 113 ++--- src/app_builder.rs | 1 + src/bank.rs | 22 +- src/contracts.rs | 455 +++++++++++++++++- src/lib.rs | 8 +- src/queries/bank.rs | 20 +- src/queries/wasm.rs | 7 +- src/wasm.rs | 251 ++++++++-- src/wasm_emulation/contract.rs | 133 ++--- src/wasm_emulation/input.rs | 52 +- src/wasm_emulation/query/bank.rs | 3 +- src/wasm_emulation/query/gas.rs | 3 + src/wasm_emulation/query/mock_querier.rs | 93 +++- src/wasm_emulation/query/mod.rs | 13 +- src/wasm_emulation/query/wasm.rs | 198 +++++--- src/wasm_emulation/storage/analyzer.rs | 29 +- .../storage/dual_std_storage.rs | 216 +++++++++ src/wasm_emulation/storage/dual_storage.rs | 24 +- src/wasm_emulation/storage/mock_storage.rs | 10 +- src/wasm_emulation/storage/mod.rs | 2 + .../storage/storage_wrappers.rs | 71 +++ 33 files changed, 1884 insertions(+), 399 deletions(-) create mode 100644 examples/counter/contract.rs create mode 100644 examples/counter/error.rs create mode 100644 examples/counter/execute.rs create mode 100644 examples/counter/interface.rs create mode 100644 examples/counter/mod.rs create mode 100644 examples/counter/msg.rs create mode 100644 examples/counter/query.rs create mode 100644 examples/counter/state.rs create mode 100644 examples/cousin_test.rs create mode 100644 src/wasm_emulation/storage/dual_std_storage.rs create mode 100644 src/wasm_emulation/storage/storage_wrappers.rs diff --git a/Cargo.lock b/Cargo.lock index e30f7724..e969fa99 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -870,6 +870,7 @@ dependencies = [ "cw-orch-networks", "cw-storage-plus 1.2.0", "cw-utils 1.0.3", + "cw2 1.1.2", "cw20 1.1.2", "derivative", "env_logger", @@ -891,6 +892,7 @@ dependencies = [ "tokio", "tonic 0.10.2", "treediff", + "wasmer", ] [[package]] @@ -941,7 +943,7 @@ dependencies = [ "prost-types 0.11.9", "rand_core 0.6.4", "reqwest", - "ring 0.17.5", + "ring 0.17.6", "ripemd", "schemars", "secp256k1", @@ -3000,9 +3002,9 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.5" +version = "0.17.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b" +checksum = "684d5e6e18f669ccebf64a92236bb7db9a34f07be010e3627368182027180866" dependencies = [ "cc", "getrandom", @@ -3116,7 +3118,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "629648aced5775d558af50b2b4c7b02983a04b312126d45eeead26e7caa498b9" dependencies = [ "log", - "ring 0.17.5", + "ring 0.17.6", "rustls-webpki", "sct 0.7.1", ] @@ -3160,7 +3162,7 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.5", + "ring 0.17.6", "untrusted 0.9.0", ] @@ -3240,7 +3242,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.5", + "ring 0.17.6", "untrusted 0.9.0", ] @@ -3560,9 +3562,9 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "spki" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", "der", @@ -4648,7 +4650,7 @@ version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" dependencies = [ - "ring 0.17.5", + "ring 0.17.6", "untrusted 0.9.0", ] diff --git a/Cargo.toml b/Cargo.toml index 4d391a8f..0271745e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,6 +58,10 @@ treediff = { version = "4.0.2", features = ["with-rustc-serialize"] } rustc-serialize = "0.3.24" serde_json = "1.0.105" log = "0.4.19" +wasmer = { version = "=4.2.2", default-features = false, features = [ + "cranelift", + "singlepass", +] } [dev-dependencies] hex = "0.4.3" @@ -71,3 +75,4 @@ cosmwasm-schema = "1.2.7" # Cavern Test App cw20 = "1.0.1" moneymarket = { git = "https://github.com/CavernPerson/money-market-contracts" } +cw2 = "1.1.2" diff --git a/examples/cavern_test_app.rs b/examples/cavern_test_app.rs index 77b49ac1..ef083f2e 100644 --- a/examples/cavern_test_app.rs +++ b/examples/cavern_test_app.rs @@ -61,6 +61,11 @@ pub struct InstantiateMsg { pub fn test() -> anyhow::Result<()> { env_logger::init(); + let sender = "terra1ytj0hhw39j88qsx4yapsr6ker83jv3aj354gmj"; + let market = "terra1zqlcp3aty4p4rjv96h6qdascdn953v6crhwedu5vddxjnp349upscluex6"; + let currency = "ibc/B3504E092456BA618CC28AC671A71FB08C6CA0FD0BE7C8A5B5A3E2DD933CC9E4"; + let a_currency = "terra1gwdxyqtu75es0x5l6cd9flqhh87zjtj7qdankayyr0vtt7s9w4ssm7ds8m"; + let runtime = Runtime::new()?; let chain = PHOENIX_1; let remote_channel = RemoteChannel::new(&runtime, chain.clone())?; @@ -84,12 +89,7 @@ pub fn test() -> anyhow::Result<()> { }) .with_api(MockApiBech32::new(chain.network_info.pub_address_prefix)); let mut app = app.build(|_, _, _| {})?; - // Then we send a message to the blockchain through the app - let sender = "terra1ytj0hhw39j88qsx4yapsr6ker83jv3aj354gmj"; - let market = "terra1zqlcp3aty4p4rjv96h6qdascdn953v6crhwedu5vddxjnp349upscluex6"; - let currency = "ibc/B3504E092456BA618CC28AC671A71FB08C6CA0FD0BE7C8A5B5A3E2DD933CC9E4"; - let a_currency = "terra1gwdxyqtu75es0x5l6cd9flqhh87zjtj7qdankayyr0vtt7s9w4ssm7ds8m"; // We query to verify the state changed let response: BalanceResponse = app @@ -133,7 +133,7 @@ pub fn test() -> anyhow::Result<()> { .unwrap(); let counter_contract = WasmContract::new_local(code); - let code_id = app.store_code(counter_contract); + let code_id = app.store_wasm_code(counter_contract); // We try to instantiate a new contract. Should work ok ! let contract_addr = app.instantiate_contract( diff --git a/examples/counter/contract.rs b/examples/counter/contract.rs new file mode 100644 index 00000000..59bbaeba --- /dev/null +++ b/examples/counter/contract.rs @@ -0,0 +1,134 @@ +use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult}; +use cw2::set_contract_version; + +use crate::counter::{error::*, execute, msg::*, query, state::*}; + +// version info for migration info +pub const CONTRACT_NAME: &str = "crates.io:counter"; +const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); + +// ANCHOR: interface_entry +// ANCHOR: entry_point_line +#[cfg_attr(feature = "export", entry_point)] +// ANCHOR_END: entry_point_line +pub fn instantiate( + deps: DepsMut, + _env: Env, + info: MessageInfo, + msg: InstantiateMsg, +) -> Result { + let state = State { + count: msg.count, + owner: info.sender.clone(), + cousin: None, + }; + set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + STATE.save(deps.storage, &state)?; + + Ok(Response::new() + .add_attribute("method", "instantiate") + .add_attribute("owner", info.sender) + .add_attribute("count", msg.count.to_string())) +} + +#[cfg_attr(feature = "export", entry_point)] +pub fn execute( + deps: DepsMut, + _env: Env, + info: MessageInfo, + msg: ExecuteMsg, +) -> Result { + match msg { + ExecuteMsg::Increment {} => execute::increment(deps), + ExecuteMsg::Reset { count } => execute::reset(deps, info, count), + ExecuteMsg::SetCousin { cousin } => execute::set_cousin(deps, info, cousin), + } +} + +#[cfg_attr(feature = "export", entry_point)] +pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { + match msg { + QueryMsg::GetCount {} => to_json_binary(&query::count(deps)?), + QueryMsg::GetCousinCount {} => to_json_binary(&query::cousin_count(deps)?), + QueryMsg::GetRawCousinCount {} => to_json_binary(&query::raw_cousin_count(deps)?), + } +} + +#[cfg_attr(feature = "export", entry_point)] +pub fn migrate(_deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result { + Ok(Response::default().add_attribute("action", "migrate")) +} +// ANCHOR_END: interface_entry + +#[cfg(test)] +mod tests { + use super::*; + use cosmwasm_std::{ + coins, from_json, + testing::{mock_dependencies, mock_env, mock_info}, + }; + + #[test] + fn proper_initialization() { + let mut deps = mock_dependencies(); + + let msg = InstantiateMsg { count: 17 }; + let info = mock_info("creator", &coins(1000, "earth")); + + // we can just call .unwrap() to assert this was a success + let res = instantiate(deps.as_mut(), mock_env(), info, msg).unwrap(); + assert_eq!(0, res.messages.len()); + + // it worked, let's query the state + let res = query(deps.as_ref(), mock_env(), QueryMsg::GetCount {}).unwrap(); + let value: GetCountResponse = from_json(res).unwrap(); + assert_eq!(17, value.count); + } + + #[test] + fn increment() { + let mut deps = mock_dependencies(); + + let msg = InstantiateMsg { count: 17 }; + let info = mock_info("creator", &coins(2, "token")); + let _res = instantiate(deps.as_mut(), mock_env(), info, msg).unwrap(); + + // beneficiary can release it + let info = mock_info("anyone", &coins(2, "token")); + let msg = ExecuteMsg::Increment {}; + let _res = execute(deps.as_mut(), mock_env(), info, msg).unwrap(); + + // should increase counter by 1 + let res = query(deps.as_ref(), mock_env(), QueryMsg::GetCount {}).unwrap(); + let value: GetCountResponse = from_json(res).unwrap(); + assert_eq!(18, value.count); + } + + #[test] + fn reset() { + let mut deps = mock_dependencies(); + + let msg = InstantiateMsg { count: 17 }; + let info = mock_info("creator", &coins(2, "token")); + let _res = instantiate(deps.as_mut(), mock_env(), info, msg).unwrap(); + + // beneficiary can release it + let unauth_info = mock_info("anyone", &coins(2, "token")); + let msg = ExecuteMsg::Reset { count: 5 }; + let res = execute(deps.as_mut(), mock_env(), unauth_info, msg); + match res { + Err(ContractError::Unauthorized {}) => {} + _ => panic!("Must return unauthorized error"), + } + + // only the original creator can reset the counter + let auth_info = mock_info("creator", &coins(2, "token")); + let msg = ExecuteMsg::Reset { count: 5 }; + let _res = execute(deps.as_mut(), mock_env(), auth_info, msg).unwrap(); + + // should now be 5 + let res = query(deps.as_ref(), mock_env(), QueryMsg::GetCount {}).unwrap(); + let value: GetCountResponse = from_json(res).unwrap(); + assert_eq!(5, value.count); + } +} diff --git a/examples/counter/error.rs b/examples/counter/error.rs new file mode 100644 index 00000000..7b724723 --- /dev/null +++ b/examples/counter/error.rs @@ -0,0 +1,16 @@ +use cosmwasm_std::StdError; +use thiserror::Error; + +#[derive(Error, PartialEq, Debug)] +pub enum ContractError { + #[error("{0}")] + Std(#[from] StdError), + + #[error("Unauthorized")] + Unauthorized {}, + + #[error("Custom Error val: {val:?}")] + CustomError { val: String }, + // Add any other custom errors you like here. + // Look at https://docs.rs/thiserror/1.0.21/thiserror/ for details. +} diff --git a/examples/counter/execute.rs b/examples/counter/execute.rs new file mode 100644 index 00000000..c1c94bfc --- /dev/null +++ b/examples/counter/execute.rs @@ -0,0 +1,39 @@ +use cosmwasm_std::{DepsMut, MessageInfo, Response}; + +use crate::counter::{error::*, state::*}; + +pub fn increment(deps: DepsMut) -> Result { + STATE.update(deps.storage, |mut state| -> Result<_, ContractError> { + state.count += 1; + Ok(state) + })?; + + Ok(Response::new().add_attribute("action", "increment")) +} + +pub fn reset(deps: DepsMut, info: MessageInfo, count: i32) -> Result { + STATE.update(deps.storage, |mut state| -> Result<_, ContractError> { + if info.sender != state.owner { + return Err(ContractError::Unauthorized {}); + } + state.count = count; + Ok(state) + })?; + Ok(Response::new().add_attribute("action", "reset")) +} + +pub fn set_cousin( + deps: DepsMut, + info: MessageInfo, + cousin: String, +) -> Result { + let cousin_addr = deps.api.addr_validate(&cousin)?; + STATE.update(deps.storage, |mut state| -> Result<_, ContractError> { + if info.sender != state.owner { + return Err(ContractError::Unauthorized {}); + } + state.cousin = Some(cousin_addr); + Ok(state) + })?; + Ok(Response::new().add_attribute("action", "set_cousin")) +} diff --git a/examples/counter/interface.rs b/examples/counter/interface.rs new file mode 100644 index 00000000..89e15635 --- /dev/null +++ b/examples/counter/interface.rs @@ -0,0 +1,65 @@ +// ANCHOR: custom_interface +use cw_orch::{interface, prelude::*}; + +use crate::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg}; + +#[interface(InstantiateMsg, ExecuteMsg, QueryMsg, MigrateMsg)] +pub struct CounterContract; + +impl Uploadable for CounterContract { + /// Return the path to the wasm file corresponding to the contract + fn wasm(&self) -> WasmPath { + artifacts_dir_from_workspace!() + .find_wasm_path("counter_contract") + .unwrap() + } + /// Returns a CosmWasm contract wrapper + fn wrapper(&self) -> Box> { + Box::new( + ContractWrapper::new_with_empty( + crate::contract::execute, + crate::contract::instantiate, + crate::contract::query, + ) + .with_migrate(crate::contract::migrate), + ) + } +} +// ANCHOR_END: custom_interface + +use crate::contract::CONTRACT_NAME; +use cw_orch::anyhow::Result; +use cw_orch::prelude::queriers::Node; + +// ANCHOR: daemon +impl CounterContract { + /// Deploys the counter contract at a specific block height + pub fn await_launch(&self) -> Result<()> { + let daemon = self.get_chain(); + let rt = daemon.rt_handle.clone(); + + rt.block_on(async { + // Get the node query client, there are a lot of other clients available. + let node = daemon.query_client::(); + let mut latest_block = node.latest_block().await.unwrap(); + + while latest_block.header.height.value() < 100 { + // wait for the next block + daemon.next_block().unwrap(); + latest_block = node.latest_block().await.unwrap(); + } + }); + + let contract = CounterContract::new(CONTRACT_NAME, daemon.clone()); + + // Upload the contract + contract.upload().unwrap(); + + // Instantiate the contract + let msg = InstantiateMsg { count: 1i32 }; + contract.instantiate(&msg, None, None).unwrap(); + + Ok(()) + } +} +// ANCHOR_END: daemon diff --git a/examples/counter/mod.rs b/examples/counter/mod.rs new file mode 100644 index 00000000..2dcd29ac --- /dev/null +++ b/examples/counter/mod.rs @@ -0,0 +1,8 @@ +pub mod contract; +mod error; +pub(crate) mod execute; +pub mod msg; +pub(crate) mod query; +pub mod state; + +pub use crate::counter::error::ContractError; diff --git a/examples/counter/msg.rs b/examples/counter/msg.rs new file mode 100644 index 00000000..bfd81a99 --- /dev/null +++ b/examples/counter/msg.rs @@ -0,0 +1,62 @@ +#![warn(missing_docs)] +//! # Counter contract + +use cosmwasm_schema::{cw_serde, QueryResponses}; + +#[cw_serde] +/// Instantiate method for counter +pub struct InstantiateMsg { + /// Initial count + pub count: i32, +} + +// ANCHOR: exec_msg +#[cw_serde] +#[cfg_attr(feature = "interface", derive(cw_orch::ExecuteFns))] // Function generation +/// Execute methods for counter +pub enum ExecuteMsg { + /// Increment count by one + Increment {}, + /// Reset count + Reset { + /// Count value after reset + count: i32, + }, + SetCousin { + cousin: String, + }, +} +// ANCHOR_END: exec_msg + +// ANCHOR: query_msg +#[cw_serde] +#[cfg_attr(feature = "interface", derive(cw_orch::QueryFns))] // Function generation +#[derive(QueryResponses)] +/// Query methods for counter +pub enum QueryMsg { + /// GetCount returns the current count as a json-encoded number + #[returns(GetCountResponse)] + GetCount {}, + /// GetCount returns the current count as a json-encoded number + #[returns(GetCountResponse)] + GetCousinCount {}, + /// GetCount returns the current count as a json-encoded number + #[returns(GetCountResponse)] + GetRawCousinCount {}, +} + +// Custom response for the query +#[cw_serde] +/// Response from get_count query +pub struct GetCountResponse { + /// Current count in the state + pub count: i32, +} +// ANCHOR_END: query_msg + +#[cw_serde] +/// Migrate message for count contract +pub struct MigrateMsg { + /// Your favorite type of tea + pub t: String, +} diff --git a/examples/counter/query.rs b/examples/counter/query.rs new file mode 100644 index 00000000..d06ab68a --- /dev/null +++ b/examples/counter/query.rs @@ -0,0 +1,30 @@ +use cosmwasm_std::{to_json_binary, Deps, QueryRequest, StdResult, WasmQuery}; + +use crate::counter::{ + msg::{GetCountResponse, QueryMsg}, + state::STATE, +}; + +pub fn count(deps: Deps) -> StdResult { + let state = STATE.load(deps.storage)?; + println!("Getting the rust code count please"); + Ok(GetCountResponse { count: state.count }) +} + +pub fn cousin_count(deps: Deps) -> StdResult { + let state = STATE.load(deps.storage)?; + let cousin_count: GetCountResponse = + deps.querier.query(&QueryRequest::Wasm(WasmQuery::Smart { + contract_addr: state.cousin.unwrap().to_string(), + msg: to_json_binary(&QueryMsg::GetCount {})?, + }))?; + Ok(cousin_count) +} + +pub fn raw_cousin_count(deps: Deps) -> StdResult { + let state = STATE.load(deps.storage)?; + let cousin_state = STATE.query(&deps.querier, state.cousin.unwrap())?; + Ok(GetCountResponse { + count: cousin_state.count, + }) +} diff --git a/examples/counter/state.rs b/examples/counter/state.rs new file mode 100644 index 00000000..7fe15222 --- /dev/null +++ b/examples/counter/state.rs @@ -0,0 +1,14 @@ +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use cosmwasm_std::Addr; +use cw_storage_plus::Item; + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +pub struct State { + pub count: i32, + pub owner: Addr, + pub cousin: Option, +} + +pub const STATE: Item = Item::new("state"); diff --git a/examples/cousin_test.rs b/examples/cousin_test.rs new file mode 100644 index 00000000..3dc12490 --- /dev/null +++ b/examples/cousin_test.rs @@ -0,0 +1,154 @@ +fn main() { + test().unwrap() +} +use std::path::Path; + +use anyhow::Result as AnyResult; +use cosmwasm_std::{Addr, Empty}; +use counter::msg::{ExecuteMsg, GetCountResponse, QueryMsg}; +use cw_multi_test::{ + addons::{MockAddressGenerator, MockApiBech32}, + wasm_emulation::{channel::RemoteChannel, contract::WasmContract}, + App, AppBuilder, BankKeeper, ContractWrapper, Executor, WasmKeeper, +}; +use cw_orch_networks::networks::PHOENIX_1; +use tokio::runtime::Runtime; + +mod counter; + +pub const SENDER: &str = "terra17c6ts8grcfrgquhj3haclg44le8s7qkx6l2yx33acguxhpf000xqhnl3je"; +fn increment(app: &mut App, contract: Addr) -> AnyResult<()> { + let sender = Addr::unchecked(SENDER); + app.execute_contract( + sender.clone(), + contract.clone(), + &ExecuteMsg::Increment {}, + &[], + )?; + Ok(()) +} + +fn count(app: &App, contract: Addr) -> AnyResult { + Ok(app + .wrap() + .query_wasm_smart(contract.clone(), &QueryMsg::GetCount {})?) +} + +fn raw_cousin_count( + app: &App, + contract: Addr, +) -> AnyResult { + Ok(app + .wrap() + .query_wasm_smart(contract.clone(), &QueryMsg::GetRawCousinCount {})?) +} + +fn cousin_count( + app: &App, + contract: Addr, +) -> AnyResult { + Ok(app + .wrap() + .query_wasm_smart(contract.clone(), &QueryMsg::GetCousinCount {})?) +} + +fn test() -> AnyResult<()> { + env_logger::init(); + let rust_contract = ContractWrapper::new( + counter::contract::execute, + counter::contract::instantiate, + counter::contract::query, + ); + + let code = std::fs::read( + Path::new(env!("CARGO_MANIFEST_DIR")) + .join("artifacts") + .join("counter_contract_with_cousin.wasm"), + ) + .unwrap(); + let wasm_contract = WasmContract::new_local(code); + + let runtime = Runtime::new()?; + let chain = PHOENIX_1; + let remote_channel = RemoteChannel::new(&runtime, chain.clone())?; + + let wasm = WasmKeeper::::new() + .with_remote(remote_channel.clone()) + .with_address_generator(MockAddressGenerator); + + let bank = BankKeeper::new().with_remote(remote_channel.clone()); + + // First we instantiate a new app + let mut app = AppBuilder::default() + .with_wasm(wasm) + .with_bank(bank) + .with_remote(remote_channel) + .with_api(MockApiBech32::new(chain.network_info.pub_address_prefix)) + .build(|_, _, _| {})?; + + let sender = Addr::unchecked(SENDER); + let rust_code_id = app.store_code(Box::new(rust_contract)); + let wasm_code_id = app.store_wasm_code(wasm_contract); + + let counter_rust = app + .instantiate_contract( + rust_code_id, + sender.clone(), + &counter::msg::InstantiateMsg { count: 1 }, + &[], + "cousin-counter", + Some(sender.to_string()), + ) + .unwrap(); + + let counter_wasm = app + .instantiate_contract( + wasm_code_id, + sender.clone(), + &counter::msg::InstantiateMsg { count: 1 }, + &[], + "cousin-counter", + Some(sender.to_string()), + ) + .unwrap(); + + println!("Rust contract {}", counter_rust); + println!("Wasm contract {}", counter_wasm); + + app.execute_contract( + sender.clone(), + counter_rust.clone(), + &ExecuteMsg::SetCousin { + cousin: counter_wasm.to_string(), + }, + &[], + )?; + + app.execute_contract( + sender.clone(), + counter_wasm.clone(), + &ExecuteMsg::SetCousin { + cousin: counter_rust.to_string(), + }, + &[], + )?; + + // Increment the count on both and see what's what + increment(&mut app, counter_rust.clone())?; + increment(&mut app, counter_rust.clone())?; + increment(&mut app, counter_wasm.clone())?; + + // Assert the count + assert_eq!(count(&app, counter_rust.clone())?.count, 3); + assert_eq!(count(&app, counter_wasm.clone())?.count, 2); + + // Assert the raw cousin count + assert_eq!(raw_cousin_count(&app, counter_rust.clone())?.count, 2); + assert_eq!(raw_cousin_count(&app, counter_wasm.clone())?.count, 3); + + // Assert the cousin count + assert_eq!(cousin_count(&app, counter_rust.clone())?.count, 2); + assert_eq!(cousin_count(&app, counter_wasm.clone())?.count, 3); + + Ok(()) +} diff --git a/src/app.rs b/src/app.rs index 37d49d5c..7ffababa 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,5 +1,6 @@ use crate::wasm_emulation::api::RealApi; use crate::wasm_emulation::channel::RemoteChannel; +use crate::wasm_emulation::input::QuerierStorage; use cosmwasm_std::CustomMsg; use cw_storage_plus::Item; @@ -13,7 +14,7 @@ use crate::staking::{Distribution, DistributionKeeper, StakeKeeper, Staking, Sta use crate::transactions::transactional; use crate::wasm::{ContractData, Wasm, WasmKeeper, WasmSudo}; use crate::wasm_emulation::contract::WasmContract; -use crate::{AppBuilder, GovFailingModule, IbcFailingModule}; +use crate::{AppBuilder, Contract, GovFailingModule, IbcFailingModule}; use cosmwasm_std::testing::{MockApi, MockStorage}; use cosmwasm_std::{ from_json, to_json_binary, Addr, Api, Binary, BlockInfo, ContractResult, CosmosMsg, @@ -25,9 +26,6 @@ use serde::{de::DeserializeOwned, Serialize}; use std::fmt::Debug; use std::marker::PhantomData; -use crate::wasm_emulation::input::STARGATE_ALL_BANK_QUERY_URL; -use crate::wasm_emulation::input::STARGATE_ALL_WASM_QUERY_URL; - const ADDRESSES: Item> = Item::new("addresses"); pub fn next_block(block: &mut BlockInfo) { @@ -174,6 +172,7 @@ where DistrT: Distribution, IbcT: Ibc, GovT: Gov, + CustomT::QueryT: CustomQuery, { /// Returns a shared reference to application's router. pub fn router(&self) -> &Router { @@ -237,7 +236,18 @@ where { /// Registers contract code (like uploading wasm bytecode on a chain), /// so it can later be used to instantiate a contract. - pub fn store_code(&mut self, code: WasmContract) -> u64 { + /// Only for wasm codes + pub fn store_wasm_code(&mut self, code: WasmContract) -> u64 { + self.init_modules(|router, _, _| { + router + .wasm + .store_wasm_code(Addr::unchecked("code-creator"), code) + }) + } + + /// Registers contract code (like uploading wasm bytecode on a chain), + /// so it can later be used to instantiate a contract. + pub fn store_code(&mut self, code: Box>) -> u64 { self.init_modules(|router, _, _| { router .wasm @@ -247,61 +257,18 @@ where /// Registers contract code (like [store_code](Self::store_code)), /// but takes the address of the code creator as an additional argument. - pub fn store_code_with_creator(&mut self, creator: Addr, code: WasmContract) -> u64 { - self.init_modules(|router, _, _| router.wasm.store_code(creator, code)) + pub fn store_wasm_code_with_creator(&mut self, creator: Addr, code: WasmContract) -> u64 { + self.init_modules(|router, _, _| router.wasm.store_wasm_code(creator, code)) } - /// Duplicates the contract code identified by `code_id` and returns - /// the identifier of the newly created copy of the contract code. - /// - /// # Examples - /// - /// ``` - /// use cosmwasm_std::Addr; - /// use cw_multi_test::App; - /// - /// // contract implementation - /// mod echo { - /// // contract entry points not shown here - /// # use std::todo; - /// # use cosmwasm_std::{Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response, StdError, SubMsg, WasmMsg}; - /// # use serde::{Deserialize, Serialize}; - /// # use cw_multi_test::{Contract, ContractWrapper}; - /// # - /// # fn instantiate(_: DepsMut, _: Env, _: MessageInfo, _: Empty) -> Result { - /// # todo!() - /// # } - /// # - /// # fn execute(_: DepsMut, _: Env, _info: MessageInfo, msg: WasmMsg) -> Result { - /// # todo!() - /// # } - /// # - /// # fn query(_deps: Deps, _env: Env, _msg: Empty) -> Result { - /// # todo!() - /// # } - /// # - /// pub fn contract() -> Box> { - /// // should return the contract - /// # Box::new(ContractWrapper::new(execute, instantiate, query)) - /// } - /// } - /// - /// let mut app = App::default(); - /// - /// // store a new contract, save the code id - /// let code_id = app.store_code(echo::contract()); - /// - /// // duplicate the existing contract, duplicated contract has different code id - /// assert_ne!(code_id, app.duplicate_code(code_id).unwrap()); - /// - /// // zero is an invalid identifier for contract code, returns an error - /// assert_eq!("code id: invalid", app.duplicate_code(0).unwrap_err().to_string()); - /// - /// // there is no contract code with identifier 100 stored yet, returns an error - /// assert_eq!("code id 100: no such code", app.duplicate_code(100).unwrap_err().to_string()); - /// ``` - pub fn duplicate_code(&mut self, code_id: u64) -> AnyResult { - self.init_modules(|router, _, _| router.wasm.duplicate_code(code_id)) + /// Registers contract code (like [store_code](Self::store_code)), + /// but takes the address of the code creator as an additional argument. + pub fn store_code_with_creator( + &mut self, + creator: Addr, + code: Box>, + ) -> u64 { + self.init_modules(|router, _, _| router.wasm.store_code(creator, code)) } /// Returns `ContractData` for the contract with specified address. @@ -358,7 +325,7 @@ where storage, remote, .. } = self; - let mut addresses = ADDRESSES.may_load(storage).unwrap().unwrap_or(vec![]); + let mut addresses = ADDRESSES.may_load(storage).unwrap().unwrap_or_default(); let new_address = RealApi::new(&remote.chain.bech32_prefix.clone()).next_address(addresses.len()); @@ -374,6 +341,13 @@ where QuerierWrapper::new(self) } + pub fn get_querier_storage(&self) -> AnyResult { + // We get the wasm storage for all wasm contract to make sure we dispatch everything (with the mock Querier) + let wasm = self.router.wasm.query_all(&self.storage)?; + let bank = self.router.bank.query_all(&self.storage)?; + Ok(QuerierStorage { wasm, bank }) + } + /// Runs multiple CosmosMsg in one atomic operation. /// This will create a cache before the execution, so no state changes are persisted if any of them /// return an error. But all writes are persisted on success. @@ -544,6 +518,8 @@ pub trait CosmosRouter { block: &BlockInfo, msg: SudoMsg, ) -> AnyResult; + + fn get_querier_storage(&self, storage: &dyn Storage) -> AnyResult; } impl CosmosRouter @@ -596,17 +572,11 @@ where ) -> AnyResult { let querier = self.querier(api, storage, block); match request { - QueryRequest::Wasm(req) => self.wasm.query(api, storage, &querier, block, req), + QueryRequest::Wasm(req) => self.wasm.query(api, storage, self, &querier, block, req), QueryRequest::Bank(req) => self.bank.query(api, storage, &querier, block, req), QueryRequest::Custom(req) => self.custom.query(api, storage, &querier, block, req), QueryRequest::Staking(req) => self.staking.query(api, storage, &querier, block, req), QueryRequest::Ibc(req) => self.ibc.query(api, storage, &querier, block, req), - // We add those custom local stargate queries to mock querying all the local storage in order to propagate for the in-contract-querier - QueryRequest::Stargate { path, data: _ } => match path.as_str() { - STARGATE_ALL_WASM_QUERY_URL => Ok(to_json_binary(&self.wasm.query_all(storage)?)?), - STARGATE_ALL_BANK_QUERY_URL => Ok(to_json_binary(&self.bank.query_all(storage)?)?), - _ => unimplemented!(), - }, _ => unimplemented!(), } } @@ -628,6 +598,13 @@ where SudoMsg::Custom(_) => unimplemented!(), } } + + fn get_querier_storage(&self, storage: &dyn Storage) -> AnyResult { + // We get the wasm storage for all wasm contract to make sure we dispatch everything (with the mock Querier) + let wasm = self.wasm.query_all(storage)?; + let bank = self.bank.query_all(storage)?; + Ok(QuerierStorage { wasm, bank }) + } } pub struct MockRouter(PhantomData<(ExecC, QueryC)>); @@ -684,6 +661,10 @@ where ) -> AnyResult { panic!("Cannot sudo MockRouters"); } + + fn get_querier_storage(&self, _storage: &dyn Storage) -> AnyResult { + Ok(QuerierStorage::default()) + } } pub struct RouterQuerier<'a, ExecC, QueryC> { diff --git a/src/app_builder.rs b/src/app_builder.rs index f509739d..22fe6dac 100644 --- a/src/app_builder.rs +++ b/src/app_builder.rs @@ -143,6 +143,7 @@ impl where CustomT: Module, WasmT: Wasm, + CustomT::QueryT: CustomQuery, { /// Overwrites the default wasm executor. /// diff --git a/src/bank.rs b/src/bank.rs index 68a488a8..acf5d7ec 100644 --- a/src/bank.rs +++ b/src/bank.rs @@ -5,13 +5,14 @@ use crate::module::Module; use crate::prefixed_storage::{prefixed, prefixed_read}; use crate::queries::bank::BankRemoteQuerier; use crate::wasm_emulation::channel::RemoteChannel; -use crate::wasm_emulation::query::AllQuerier; +use crate::wasm_emulation::input::BankStorage; +use crate::wasm_emulation::query::AllBankQuerier; use cosmwasm_std::{ coin, to_json_binary, Addr, AllBalanceResponse, Api, BalanceResponse, BankMsg, BankQuery, - Binary, BlockInfo, Coin, Event, Querier, Storage, + Binary, BlockInfo, Coin, Event, Order, Querier, Storage, }; #[cfg(feature = "cosmwasm_1_1")] -use cosmwasm_std::{Order, StdResult, SupplyResponse, Uint128}; +use cosmwasm_std::{StdResult, SupplyResponse, Uint128}; use cw_storage_plus::Map; use cw_utils::NativeBalance; use itertools::Itertools; @@ -29,7 +30,10 @@ pub enum BankSudo { }, } -pub trait Bank: Module + AllQuerier {} +pub trait Bank: + Module + AllBankQuerier +{ +} #[derive(Default)] pub struct BankKeeper { @@ -248,3 +252,13 @@ impl Module for BankKeeper { } } } + +impl AllBankQuerier for BankKeeper { + fn query_all(&self, storage: &dyn Storage) -> AnyResult { + let bank_storage = prefixed_read(storage, NAMESPACE_BANK); + let balances: Result, _> = BALANCES + .range(&bank_storage, None, None, Order::Ascending) + .collect(); + Ok(BankStorage { storage: balances? }) + } +} diff --git a/src/contracts.rs b/src/contracts.rs index d5ee86a6..804d3726 100644 --- a/src/contracts.rs +++ b/src/contracts.rs @@ -1,16 +1,32 @@ +use std::{ + error::Error, + fmt::{self, Debug, Display}, + ops::Deref, +}; + use schemars::JsonSchema; -use cosmwasm_std::{Binary, CustomQuery, Deps, DepsMut, Empty, Env, MessageInfo, Reply, Response}; +use cosmwasm_std::{ + from_json, Binary, CosmosMsg, CustomMsg, CustomQuery, Deps, DepsMut, Empty, Env, MessageInfo, + QuerierWrapper, Reply, Response, StdError, SubMsg, +}; use anyhow::Result as AnyResult; +use serde::de::DeserializeOwned; -use crate::wasm_emulation::channel::RemoteChannel; - +use crate::wasm_emulation::{ + query::{mock_querier::ForkState, MockQuerier}, + storage::{ + dual_std_storage::DualStorage, + storage_wrappers::{ReadonlyStorageWrapper, StorageWrapper}, + }, +}; +use anyhow::{anyhow, bail}; /// Interface to call into a [Contract]. pub trait Contract where - T: Clone + std::fmt::Debug + PartialEq + JsonSchema, - Q: CustomQuery, + T: CustomMsg + DeserializeOwned + Clone + std::fmt::Debug + PartialEq + JsonSchema, + Q: CustomQuery + DeserializeOwned, { fn execute( &self, @@ -18,7 +34,7 @@ where env: Env, info: MessageInfo, msg: Vec, - remote: RemoteChannel, + fork_state: ForkState, ) -> AnyResult>; fn instantiate( @@ -27,7 +43,7 @@ where env: Env, info: MessageInfo, msg: Vec, - remote: RemoteChannel, + fork_state: ForkState, ) -> AnyResult>; fn query( @@ -35,7 +51,7 @@ where deps: Deps, env: Env, msg: Vec, - remote: RemoteChannel, + fork_state: ForkState, ) -> AnyResult; fn sudo( @@ -43,7 +59,7 @@ where deps: DepsMut, env: Env, msg: Vec, - remote: RemoteChannel, + fork_state: ForkState, ) -> AnyResult>; fn reply( @@ -51,7 +67,7 @@ where deps: DepsMut, env: Env, msg: Reply, - remote: RemoteChannel, + fork_state: ForkState, ) -> AnyResult>; fn migrate( @@ -59,6 +75,423 @@ where deps: DepsMut, env: Env, msg: Vec, - remote: RemoteChannel, + fork_state: ForkState, ) -> AnyResult>; } + +type ContractFn = + fn(deps: DepsMut, env: Env, info: MessageInfo, msg: T) -> Result, E>; +type PermissionedFn = fn(deps: DepsMut, env: Env, msg: T) -> Result, E>; +type ReplyFn = fn(deps: DepsMut, env: Env, msg: Reply) -> Result, E>; +type QueryFn = fn(deps: Deps, env: Env, msg: T) -> Result; + +type ContractClosure = fn(DepsMut, Env, MessageInfo, T) -> Result, E>; +type PermissionedClosure = fn(DepsMut, Env, T) -> Result, E>; +type ReplyClosure = fn(DepsMut, Env, Reply) -> Result, E>; +type QueryClosure = fn(Deps, Env, T) -> Result; + +#[derive(Clone, Copy)] +/// Wraps the exported functions from a contract and provides the normalized format +/// Place T4 and E4 at the end, as we just want default placeholders for most contracts that don't have sudo +pub struct ContractWrapper< + T1, + T2, + T3, + E1, + E2, + E3, + C = Empty, + Q = Empty, + T4 = Empty, + E4 = StdError, + E5 = StdError, + T6 = Empty, + E6 = StdError, +> where + T1: DeserializeOwned + Debug, + T2: DeserializeOwned, + T3: DeserializeOwned, + T4: DeserializeOwned, + T6: DeserializeOwned, + E1: Display + Debug + Send + Sync + 'static, + E2: Display + Debug + Send + Sync + 'static, + E3: Display + Debug + Send + Sync + 'static, + E4: Display + Debug + Send + Sync + 'static, + E5: Display + Debug + Send + Sync + 'static, + E6: Display + Debug + Send + Sync + 'static, + C: Clone + fmt::Debug + PartialEq + JsonSchema, + Q: CustomQuery + DeserializeOwned + 'static, +{ + execute_fn: ContractClosure, + instantiate_fn: ContractClosure, + pub query_fn: QueryClosure, + sudo_fn: Option>, + reply_fn: Option>, + migrate_fn: Option>, +} + +impl ContractWrapper +where + T1: DeserializeOwned + Debug + 'static, + T2: DeserializeOwned + 'static, + T3: DeserializeOwned + 'static, + E1: Display + Debug + Send + Sync + 'static, + E2: Display + Debug + Send + Sync + 'static, + E3: Display + Debug + Send + Sync + 'static, + C: Clone + fmt::Debug + PartialEq + JsonSchema + 'static, + Q: CustomQuery + DeserializeOwned + 'static, +{ + pub fn new( + execute_fn: ContractFn, + instantiate_fn: ContractFn, + query_fn: QueryFn, + ) -> Self { + Self { + execute_fn, + instantiate_fn, + query_fn, + sudo_fn: None, + reply_fn: None, + migrate_fn: None, + } + } +} + +impl + ContractWrapper +where + T1: DeserializeOwned + Debug + 'static, + T2: DeserializeOwned + 'static, + T3: DeserializeOwned + 'static, + T4: DeserializeOwned + 'static, + T6: DeserializeOwned + 'static, + E1: Display + Debug + Send + Sync + 'static, + E2: Display + Debug + Send + Sync + 'static, + E3: Display + Debug + Send + Sync + 'static, + E4: Display + Debug + Send + Sync + 'static, + E5: Display + Debug + Send + Sync + 'static, + E6: Display + Debug + Send + Sync + 'static, + C: Clone + fmt::Debug + PartialEq + JsonSchema + 'static, + Q: CustomQuery + DeserializeOwned + 'static, +{ + pub fn with_sudo( + self, + sudo_fn: PermissionedFn, + ) -> ContractWrapper + where + T4A: DeserializeOwned + 'static, + E4A: Display + Debug + Send + Sync + 'static, + { + ContractWrapper { + execute_fn: self.execute_fn, + instantiate_fn: self.instantiate_fn, + query_fn: self.query_fn, + sudo_fn: Some(sudo_fn), + reply_fn: self.reply_fn, + migrate_fn: self.migrate_fn, + } + } + + pub fn with_reply( + self, + reply_fn: ReplyFn, + ) -> ContractWrapper + where + E5A: Display + Debug + Send + Sync + 'static, + { + ContractWrapper { + execute_fn: self.execute_fn, + instantiate_fn: self.instantiate_fn, + query_fn: self.query_fn, + sudo_fn: self.sudo_fn, + reply_fn: Some(reply_fn), + migrate_fn: self.migrate_fn, + } + } + + pub fn with_migrate( + self, + migrate_fn: PermissionedFn, + ) -> ContractWrapper + where + T6A: DeserializeOwned + 'static, + E6A: Display + Debug + Send + Sync + 'static, + { + ContractWrapper { + execute_fn: self.execute_fn, + instantiate_fn: self.instantiate_fn, + query_fn: self.query_fn, + sudo_fn: self.sudo_fn, + reply_fn: self.reply_fn, + migrate_fn: Some(migrate_fn), + } + } +} + +fn decustomize_deps_mut<'a, Q>(deps: &'a mut DepsMut) -> DepsMut<'a, Empty> +where + Q: CustomQuery + DeserializeOwned + 'static, +{ + DepsMut { + storage: deps.storage, + api: deps.api, + querier: QuerierWrapper::new(deps.querier.deref()), + } +} + +fn decustomize_deps<'a, Q>(deps: &'a Deps<'a, Q>) -> Deps<'a, Empty> +where + Q: CustomQuery + DeserializeOwned + 'static, +{ + Deps { + storage: deps.storage, + api: deps.api, + querier: QuerierWrapper::new(deps.querier.deref()), + } +} + +fn customize_response(resp: Response) -> Response +where + C: Clone + fmt::Debug + PartialEq + JsonSchema, +{ + let mut customized_resp = Response::::new() + .add_submessages(resp.messages.into_iter().map(customize_msg::)) + .add_events(resp.events) + .add_attributes(resp.attributes); + customized_resp.data = resp.data; + customized_resp +} + +fn customize_msg(msg: SubMsg) -> SubMsg +where + C: Clone + fmt::Debug + PartialEq + JsonSchema, +{ + SubMsg { + msg: match msg.msg { + CosmosMsg::Wasm(wasm) => CosmosMsg::Wasm(wasm), + CosmosMsg::Bank(bank) => CosmosMsg::Bank(bank), + CosmosMsg::Staking(staking) => CosmosMsg::Staking(staking), + CosmosMsg::Distribution(distribution) => CosmosMsg::Distribution(distribution), + CosmosMsg::Custom(_) => unreachable!(), + #[cfg(feature = "stargate")] + CosmosMsg::Ibc(ibc) => CosmosMsg::Ibc(ibc), + #[cfg(feature = "stargate")] + CosmosMsg::Stargate { type_url, value } => CosmosMsg::Stargate { type_url, value }, + _ => panic!("unknown message variant {:?}", msg), + }, + id: msg.id, + gas_limit: msg.gas_limit, + reply_on: msg.reply_on, + } +} + +impl Contract + for ContractWrapper +where + T1: DeserializeOwned + Debug + Clone, + T2: DeserializeOwned + Debug + Clone, + T3: DeserializeOwned + Debug + Clone, + T4: DeserializeOwned, + T6: DeserializeOwned, + E1: Display + Debug + Send + Sync + Error + 'static, + E2: Display + Debug + Send + Sync + Error + 'static, + E3: Display + Debug + Send + Sync + Error + 'static, + E4: Display + Debug + Send + Sync + 'static, + E5: Display + Debug + Send + Sync + 'static, + E6: Display + Debug + Send + Sync + 'static, + C: CustomMsg + DeserializeOwned + Clone + fmt::Debug + PartialEq + JsonSchema, + Q: CustomQuery + DeserializeOwned, +{ + fn execute( + &self, + deps: DepsMut, + env: Env, + info: MessageInfo, + msg: Vec, + fork_state: ForkState, + ) -> AnyResult> { + let querier = MockQuerier::new(fork_state.clone()); + let mut storage = DualStorage::new( + fork_state.remote, + env.contract.address.to_string(), + Box::new(StorageWrapper::new(deps.storage)), + )?; + let deps = DepsMut { + storage: &mut storage, + api: deps.api, + querier: QuerierWrapper::new(&querier), + }; + + let msg: T1 = from_json(msg)?; + (self.execute_fn)(deps, env, info, msg).map_err(|err| anyhow!(err)) + } + + fn instantiate( + &self, + deps: DepsMut, + env: Env, + info: MessageInfo, + msg: Vec, + fork_state: ForkState, + ) -> AnyResult> { + let querier = MockQuerier::new(fork_state.clone()); + let mut storage = DualStorage::new( + fork_state.remote, + env.contract.address.to_string(), + Box::new(StorageWrapper::new(deps.storage)), + )?; + let deps = DepsMut { + storage: &mut storage, + api: deps.api, + querier: QuerierWrapper::new(&querier), + }; + let msg: T2 = from_json(msg)?; + (self.instantiate_fn)(deps, env, info, msg).map_err(|err| anyhow!(err)) + } + + fn query( + &self, + deps: Deps, + env: Env, + msg: Vec, + fork_state: ForkState, + ) -> AnyResult { + let querier = MockQuerier::new(fork_state.clone()); + let mut storage = DualStorage::new( + fork_state.remote, + env.contract.address.to_string(), + Box::new(ReadonlyStorageWrapper::new(deps.storage)), + )?; + let deps = Deps { + storage: &mut storage, + api: deps.api, + querier: QuerierWrapper::new(&querier), + }; + let msg: T3 = from_json(msg)?; + (self.query_fn)(deps, env, msg).map_err(|err| anyhow!(err)) + } + + // this returns an error if the contract doesn't implement sudo + fn sudo( + &self, + deps: DepsMut, + env: Env, + msg: Vec, + fork_state: ForkState, + ) -> AnyResult> { + let querier = MockQuerier::new(fork_state.clone()); + let mut storage = DualStorage::new( + fork_state.remote, + env.contract.address.to_string(), + Box::new(StorageWrapper::new(deps.storage)), + )?; + let deps = DepsMut { + storage: &mut storage, + api: deps.api, + querier: QuerierWrapper::new(&querier), + }; + let msg = from_json(msg)?; + match &self.sudo_fn { + Some(sudo) => sudo(deps, env, msg).map_err(|err| anyhow!(err)), + None => bail!("sudo not implemented for contract"), + } + } + + // this returns an error if the contract doesn't implement reply + fn reply( + &self, + deps: DepsMut, + env: Env, + reply_data: Reply, + fork_state: ForkState, + ) -> AnyResult> { + let querier = MockQuerier::new(fork_state.clone()); + let mut storage = DualStorage::new( + fork_state.remote, + env.contract.address.to_string(), + Box::new(StorageWrapper::new(deps.storage)), + )?; + let deps = DepsMut { + storage: &mut storage, + api: deps.api, + querier: QuerierWrapper::new(&querier), + }; + match &self.reply_fn { + Some(reply) => reply(deps, env, reply_data).map_err(|err| anyhow!(err)), + None => bail!("reply not implemented for contract"), + } + } + + // this returns an error if the contract doesn't implement migrate + fn migrate( + &self, + deps: DepsMut, + env: Env, + msg: Vec, + fork_state: ForkState, + ) -> AnyResult> { + let querier = MockQuerier::new(fork_state.clone()); + let mut storage = DualStorage::new( + fork_state.remote, + env.contract.address.to_string(), + Box::new(StorageWrapper::new(deps.storage)), + )?; + let deps = DepsMut { + storage: &mut storage, + api: deps.api, + querier: QuerierWrapper::new(&querier), + }; + let msg = from_json(msg)?; + match &self.migrate_fn { + Some(migrate) => migrate(deps, env, msg).map_err(|err| anyhow!(err)), + None => bail!("migrate not implemented for contract"), + } + } +} + +#[cfg(test)] +pub mod test { + + use cosmwasm_std::{ + testing::{mock_dependencies, mock_env, mock_info}, + to_json_binary, Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response, StdResult, + }; + + use super::ContractWrapper; + + fn execute(deps: DepsMut, env: Env, info: MessageInfo, _msg: Empty) -> StdResult { + Ok(Response::new()) + } + + fn query(deps: Deps, env: Env, _msg: Empty) -> StdResult { + to_json_binary("resp") + } + + fn instantiate(deps: DepsMut, env: Env, info: MessageInfo, _msg: Empty) -> StdResult { + Ok(Response::new()) + } + + #[test] + fn mock_contract() -> anyhow::Result<()> { + let contract = ContractWrapper::new(execute, instantiate, query); + + let clone = contract.execute_fn; + let second_clone = clone; + + clone( + mock_dependencies().as_mut(), + mock_env(), + mock_info("sender", &[]), + Empty {}, + )?; + + second_clone( + mock_dependencies().as_mut(), + mock_env(), + mock_info("sender", &[]), + Empty {}, + )?; + + Ok(()) + } +} diff --git a/src/lib.rs b/src/lib.rs index a6a47059..99a926b7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,7 +32,7 @@ pub use crate::app::{custom_app, next_block, App, BasicApp, CosmosRouter, Router pub use crate::app_builder::{AppBuilder, BasicAppBuilder}; pub use crate::bank::{Bank, BankKeeper, BankSudo}; pub use crate::checksums::ChecksumGenerator; -pub use crate::contracts::Contract; +pub use crate::contracts::{Contract, ContractWrapper}; pub use crate::executor::{AppResponse, Executor}; pub use crate::gov::{Gov, GovAcceptingModule, GovFailingModule}; pub use crate::ibc::{Ibc, IbcAcceptingModule, IbcFailingModule}; @@ -40,4 +40,8 @@ pub use crate::module::{AcceptingModule, FailingModule, Module}; pub use crate::staking::{ Distribution, DistributionKeeper, StakeKeeper, Staking, StakingInfo, StakingSudo, }; -pub use crate::wasm::{ContractData, Wasm, WasmKeeper, WasmSudo, LOCAL_CODE_OFFSET}; +pub use crate::wasm::{ + ContractData, Wasm, WasmKeeper, WasmSudo, LOCAL_RUST_CODE_OFFSET, LOCAL_WASM_CODE_OFFSET, +}; + +pub use prefixed_storage::{PrefixedStorage, ReadonlyPrefixedStorage}; diff --git a/src/queries/bank.rs b/src/queries/bank.rs index e0fe3b14..84eead60 100644 --- a/src/queries/bank.rs +++ b/src/queries/bank.rs @@ -1,15 +1,10 @@ use std::str::FromStr; use anyhow::Result as AnyResult; -use cosmwasm_std::{Addr, Coin, Order, Storage, Uint128}; +use cosmwasm_std::{Addr, Coin, Uint128}; use cw_orch_daemon::queriers::DaemonQuerier; -use crate::{ - bank::{BALANCES, NAMESPACE_BANK}, - prefixed_storage::prefixed_read, - wasm_emulation::{channel::RemoteChannel, input::BankStorage, query::AllQuerier}, - BankKeeper, -}; +use crate::wasm_emulation::channel::RemoteChannel; pub struct BankRemoteQuerier; @@ -33,14 +28,3 @@ impl BankRemoteQuerier { Ok(distant_amounts) } } - -impl AllQuerier for BankKeeper { - type Output = BankStorage; - fn query_all(&self, storage: &dyn Storage) -> AnyResult { - let bank_storage = prefixed_read(storage, NAMESPACE_BANK); - let balances: Result, _> = BALANCES - .range(&bank_storage, None, None, Order::Ascending) - .collect(); - Ok(BankStorage { storage: balances? }) - } -} diff --git a/src/queries/wasm.rs b/src/queries/wasm.rs index 6d1ca06f..02b272f6 100644 --- a/src/queries/wasm.rs +++ b/src/queries/wasm.rs @@ -1,13 +1,13 @@ use std::collections::HashMap; use anyhow::Result as AnyResult; -use cosmwasm_std::{Addr, Binary, CodeInfoResponse, Order, Storage}; +use cosmwasm_std::{Addr, Binary, CodeInfoResponse, CustomQuery, Order, Storage}; use cw_orch_daemon::queriers::{CosmWasm, DaemonQuerier}; use crate::{ prefixed_storage::prefixed_read, wasm::{ContractData, CONTRACTS, NAMESPACE_WASM}, - wasm_emulation::{channel::RemoteChannel, input::WasmStorage, query::AllQuerier}, + wasm_emulation::{channel::RemoteChannel, input::WasmStorage, query::AllWasmQuerier}, WasmKeeper, }; @@ -60,8 +60,7 @@ impl WasmRemoteQuerier { } } -impl AllQuerier for WasmKeeper { - type Output = WasmStorage; +impl AllWasmQuerier for WasmKeeper { fn query_all(&self, storage: &dyn Storage) -> AnyResult { let all_local_state: Vec<_> = storage.range(None, None, Order::Ascending).collect(); diff --git a/src/wasm.rs b/src/wasm.rs index fe798ac6..95baad20 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -10,7 +10,9 @@ use crate::queries::wasm::WasmRemoteQuerier; use crate::transactions::transactional; use crate::wasm_emulation::channel::RemoteChannel; use crate::wasm_emulation::contract::WasmContract; -use crate::wasm_emulation::query::AllQuerier; +use crate::wasm_emulation::input::QuerierStorage; +use crate::wasm_emulation::query::mock_querier::{ForkState, LocalForkedState}; +use crate::wasm_emulation::query::AllWasmQuerier; use cosmwasm_std::testing::mock_wasmd_attr; use cosmwasm_std::CustomMsg; use cosmwasm_std::{ @@ -35,7 +37,8 @@ pub(crate) const CONTRACTS: Map<&Addr, ContractData> = Map::new("contracts"); pub(crate) const NAMESPACE_WASM: &[u8] = b"wasm"; /// See const CONTRACT_ATTR: &str = "_contract_address"; -pub const LOCAL_CODE_OFFSET: usize = 5_000_000; +pub const LOCAL_WASM_CODE_OFFSET: usize = 5_000_000; +pub const LOCAL_RUST_CODE_OFFSET: usize = 10_000_000; #[derive(Clone, Debug, PartialEq, Eq, JsonSchema)] pub struct WasmSudo { @@ -79,12 +82,13 @@ pub struct CodeData { pub code_base_id: usize, } -pub trait Wasm: AllQuerier { +pub trait Wasm: AllWasmQuerier { /// Handles all WasmQuery requests fn query( &self, api: &dyn Api, storage: &dyn Storage, + router: &dyn CosmosRouter, querier: &dyn Querier, block: &BlockInfo, request: WasmQuery, @@ -113,11 +117,10 @@ pub trait Wasm: AllQuerier { ) -> AnyResult; /// Stores the contract's code and returns an identifier of the stored contract's code. - fn store_code(&mut self, creator: Addr, code: WasmContract) -> u64; + fn store_code(&mut self, creator: Addr, code: Box>) -> u64; - /// Duplicates the contract's code with specified identifier - /// and returns an identifier of the copy of the contract's code. - fn duplicate_code(&mut self, code_id: u64) -> AnyResult; + /// Stores the contract's code and returns an identifier of the stored contract's code. + fn store_wasm_code(&mut self, creator: Addr, code: WasmContract) -> u64; /// Returns `ContractData` for the contract with specified address. fn contract_data(&self, storage: &dyn Storage, address: &Addr) -> AnyResult; @@ -126,10 +129,13 @@ pub trait Wasm: AllQuerier { fn dump_wasm_raw(&self, storage: &dyn Storage, address: &Addr) -> Vec; } -// pub struct WasmKeeper { -pub struct WasmKeeper { +pub type LocalRustContract = *mut dyn Contract; +pub struct WasmKeeper { /// Contract codes that stand for wasm code in real-life blockchain. pub code_base: HashMap, + /// Contract codes that stand for rust code living in the current instance + /// We also associate the queries to them to make sure we are able to use them with the vm instance + pub rust_codes: HashMap>, /// Code data with code base identifier and additional attributes. pub code_data: HashMap, /// Contract's address generator. @@ -142,7 +148,7 @@ pub struct WasmKeeper { _p: std::marker::PhantomData<(ExecC, QueryC)>, } -impl Default for WasmKeeper { +impl Default for WasmKeeper { fn default() -> WasmKeeper { Self { code_base: HashMap::new(), @@ -151,6 +157,7 @@ impl Default for WasmKeeper { checksum_generator: Box::new(SimpleChecksumGenerator), _p: std::marker::PhantomData, remote: None, + rust_codes: HashMap::new(), } } } @@ -164,6 +171,7 @@ where &self, api: &dyn Api, storage: &dyn Storage, + router: &dyn CosmosRouter, querier: &dyn Querier, block: &BlockInfo, request: WasmQuery, @@ -171,7 +179,15 @@ where match request { WasmQuery::Smart { contract_addr, msg } => { let addr = api.addr_validate(&contract_addr)?; - self.query_smart(addr, api, storage, querier, block, msg.into()) + self.query_smart( + addr, + api, + storage, + querier, + block, + msg.into(), + router.get_querier_storage(storage)?, + ) } WasmQuery::Raw { contract_addr, key } => { let addr = api.addr_validate(&contract_addr)?; @@ -226,15 +242,25 @@ where ) -> AnyResult { let custom_event = Event::new("sudo").add_attribute(CONTRACT_ATTR, &contract); - let res = self.call_sudo(contract.clone(), api, storage, router, block, msg.to_vec())?; + let querier_storage = router.get_querier_storage(storage)?; + + let res = self.call_sudo( + contract.clone(), + api, + storage, + router, + block, + msg.to_vec(), + querier_storage, + )?; let (res, msgs) = self.build_app_response(&contract, custom_event, res); self.process_response(api, router, storage, block, contract, res, msgs) } /// Stores the contract's code in the in-memory lookup table. /// Returns an identifier of the stored contract code. - fn store_code(&mut self, creator: Addr, code: WasmContract) -> u64 { - let code_id = self.code_base.len() + 1 + LOCAL_CODE_OFFSET; + fn store_wasm_code(&mut self, creator: Addr, code: WasmContract) -> u64 { + let code_id = self.code_base.len() + 1 + LOCAL_WASM_CODE_OFFSET; self.code_base.insert(code_id, code); let checksum = self.checksum_generator.checksum(&creator, code_id as u64); self.code_data.insert( @@ -248,26 +274,24 @@ where code_id as u64 } - /// Duplicates the contract's code with specified identifier. - /// Returns an identifier of the copy of the contract's code. - fn duplicate_code(&mut self, code_id: u64) -> AnyResult { - let code_data = self.code_data(code_id)?; - let code = self - .code_base - .get(&(code_id as usize)) - .ok_or(Error::UnregisteredCodeId(code_id))?; - let code_id = self.code_base.len() + 1 + LOCAL_CODE_OFFSET; + /// Stores the contract's code in the in-memory lookup table. + /// Returns an identifier of the stored contract code. + fn store_code(&mut self, creator: Addr, code: Box>) -> u64 { + let static_ref = Box::leak(code); + + let code_id = self.rust_codes.len() + 1 + LOCAL_RUST_CODE_OFFSET; + let raw_pointer = static_ref as *mut dyn Contract; + self.rust_codes.insert(code_id, raw_pointer); + let checksum = self.checksum_generator.checksum(&creator, code_id as u64); self.code_data.insert( code_id, CodeData { - creator: code_data.creator.clone(), - checksum: code_data.checksum.clone(), + creator, + checksum, code_base_id: code_id, }, ); - self.code_base.insert(code_id, code.clone()); - - Ok(code_id as u64) + code_id as u64 } /// Returns `ContractData` for the contract with specified address. @@ -287,19 +311,55 @@ where } } +pub enum ContractBox<'a, ExecC, QueryC> { + Borrowed(&'a dyn Contract), + Owned(Box>), +} + impl WasmKeeper where ExecC: CustomMsg + DeserializeOwned + 'static, QueryC: CustomQuery + DeserializeOwned + 'static, { + /// Only for Clone-testing + fn fork_state( + &self, + querier_storage: QuerierStorage, + env: &Env, + ) -> AnyResult> { + Ok(ForkState { + remote: self.remote.clone().unwrap(), + querier_storage, + local_state: LocalForkedState { + contracts: self + .rust_codes + .iter() + .map(|(id, &code)| (*id, code)) + .collect(), + env: env.clone(), + }, + }) + } + /// Returns a handler to code of the contract with specified code id. - pub fn contract_code(&self, code_id: u64) -> AnyResult { + pub fn contract_code<'a, 'b>( + &'a self, + code_id: u64, + ) -> AnyResult> + where + 'a: 'b, + { let code_data = self.code_data(code_id)?; let code = self.code_base.get(&code_data.code_base_id); if let Some(code) = code { - Ok(code.clone()) + Ok(ContractBox::Borrowed(code)) + } else if let Some(&rust_code) = self.rust_codes.get(&code_data.code_base_id) { + Ok(ContractBox::Borrowed(unsafe { + rust_code.as_ref().unwrap() + })) } else { - Ok(WasmContract::new_distant_code_id(code_id)) + let wasm_contract = WasmContract::new_distant_code_id(code_id); + Ok(ContractBox::Owned(Box::new(wasm_contract))) } } @@ -339,6 +399,7 @@ where // then from wasm_storage -> the contracts subspace let namespace = self.contract_namespace(address); let storage = PrefixedStorage::multilevel(storage, &[NAMESPACE_WASM, &namespace]); + Box::new(storage) } @@ -444,6 +505,7 @@ where querier: &dyn Querier, block: &BlockInfo, msg: Vec, + querier_storage: QuerierStorage, ) -> AnyResult { self.with_storage_readonly( api, @@ -451,14 +513,19 @@ where querier, block, address, - |handler, deps, env| { - >::query( - &handler, + |handler, deps, env| match handler { + ContractBox::Borrowed(contract) => contract.query( deps, - env, + env.clone(), msg, - self.remote.clone().unwrap(), - ) + self.fork_state(querier_storage, &env)?, + ), + ContractBox::Owned(contract) => contract.query( + deps, + env.clone(), + msg, + self.fork_state(querier_storage, &env)?, + ), }, ) } @@ -553,6 +620,8 @@ where // then call the contract let info = MessageInfo { sender, funds }; + let querier_storage = router.get_querier_storage(storage)?; + let res = self.call_execute( api, storage, @@ -561,12 +630,14 @@ where block, info, msg.to_vec(), + querier_storage, )?; let custom_event = Event::new("execute").add_attribute(CONTRACT_ATTR, &contract_addr); let (res, msgs) = self.build_app_response(&contract_addr, custom_event, res); + let mut res = self.process_response(api, router, storage, block, contract_addr, res, msgs)?; res.data = execute_response(res.data); @@ -619,6 +690,7 @@ where self.save_contract(storage, &contract_addr, &data)?; // then call migrate + let querier_storage = router.get_querier_storage(storage)?; let res = self.call_migrate( contract_addr.clone(), api, @@ -626,6 +698,7 @@ where router, block, msg.to_vec(), + querier_storage, )?; let custom_event = Event::new("migrate") @@ -691,6 +764,7 @@ where // then call the contract let info = MessageInfo { sender, funds }; + let querier_storage = router.get_querier_storage(storage)?; let res = self.call_instantiate( contract_addr.clone(), api, @@ -699,6 +773,7 @@ where block, info, msg.to_vec(), + querier_storage, )?; let custom_event = Event::new("instantiate") @@ -706,6 +781,7 @@ where .add_attribute("code_id", code_id.to_string()); let (res, msgs) = self.build_app_response(&contract_addr, custom_event, res); + let mut res = self.process_response( api, router, @@ -803,6 +879,7 @@ where let res = self.call_reply(contract.clone(), api, storage, router, block, reply)?; let (res, msgs) = self.build_app_response(&contract, custom_event, res); + self.process_response(api, router, storage, block, contract, res, msgs) } @@ -939,6 +1016,7 @@ where block: &BlockInfo, info: MessageInfo, msg: Vec, + querier_storage: QuerierStorage, ) -> AnyResult> { Self::verify_response(self.with_storage( api, @@ -946,8 +1024,21 @@ where router, block, address, - |contract, deps, env| { - contract.execute(deps, env, info, msg, self.remote.clone().unwrap()) + |contract, deps, env| match contract { + ContractBox::Borrowed(contract) => contract.execute( + deps, + env.clone(), + info, + msg, + self.fork_state(querier_storage, &env)?, + ), + ContractBox::Owned(contract) => contract.execute( + deps, + env.clone(), + info, + msg, + self.fork_state(querier_storage, &env)?, + ), }, )?) } @@ -961,6 +1052,7 @@ where block: &BlockInfo, info: MessageInfo, msg: Vec, + querier_storage: QuerierStorage, ) -> AnyResult> { Self::verify_response(self.with_storage( api, @@ -968,8 +1060,21 @@ where router, block, address, - |contract, deps, env| { - contract.instantiate(deps, env, info, msg, self.remote.clone().unwrap()) + |contract, deps, env| match contract { + ContractBox::Borrowed(contract) => contract.instantiate( + deps, + env.clone(), + info, + msg, + self.fork_state(querier_storage, &env)?, + ), + ContractBox::Owned(contract) => contract.instantiate( + deps, + env.clone(), + info, + msg, + self.fork_state(querier_storage, &env)?, + ), }, )?) } @@ -983,13 +1088,27 @@ where block: &BlockInfo, reply: Reply, ) -> AnyResult> { + let querier_storage = router.get_querier_storage(storage)?; Self::verify_response(self.with_storage( api, storage, router, block, address, - |contract, deps, env| contract.reply(deps, env, reply, self.remote.clone().unwrap()), + |contract, deps, env| match contract { + ContractBox::Borrowed(contract) => contract.reply( + deps, + env.clone(), + reply, + self.fork_state(querier_storage, &env)?, + ), + ContractBox::Owned(contract) => contract.reply( + deps, + env.clone(), + reply, + self.fork_state(querier_storage, &env)?, + ), + }, )?) } @@ -1001,6 +1120,7 @@ where router: &dyn CosmosRouter, block: &BlockInfo, msg: Vec, + querier_storage: QuerierStorage, ) -> AnyResult> { Self::verify_response(self.with_storage( api, @@ -1008,7 +1128,20 @@ where router, block, address, - |contract, deps, env| contract.sudo(deps, env, msg, self.remote.clone().unwrap()), + |contract, deps, env| match contract { + ContractBox::Borrowed(contract) => contract.sudo( + deps, + env.clone(), + msg, + self.fork_state(querier_storage, &env)?, + ), + ContractBox::Owned(contract) => contract.sudo( + deps, + env.clone(), + msg, + self.fork_state(querier_storage, &env)?, + ), + }, )?) } @@ -1020,6 +1153,7 @@ where router: &dyn CosmosRouter, block: &BlockInfo, msg: Vec, + querier_storage: QuerierStorage, ) -> AnyResult> { Self::verify_response(self.with_storage( api, @@ -1027,7 +1161,20 @@ where router, block, address, - |contract, deps, env| contract.migrate(deps, env, msg, self.remote.clone().unwrap()), + |contract, deps, env| match contract { + ContractBox::Borrowed(contract) => contract.migrate( + deps, + env.clone(), + msg, + self.fork_state(querier_storage, &env)?, + ), + ContractBox::Owned(contract) => contract.migrate( + deps, + env.clone(), + msg, + self.fork_state(querier_storage, &env)?, + ), + }, )?) } @@ -1041,8 +1188,8 @@ where } } - fn with_storage_readonly( - &self, + fn with_storage_readonly<'a, 'b, F, T>( + &'a self, api: &dyn Api, storage: &dyn Storage, querier: &dyn Querier, @@ -1051,10 +1198,11 @@ where action: F, ) -> AnyResult where - F: FnOnce(WasmContract, Deps, Env) -> AnyResult, + F: FnOnce(ContractBox<'b, ExecC, QueryC>, Deps, Env) -> AnyResult, + 'a: 'b, { let contract = self.contract_data(storage, &address)?; - let handler = self.contract_code(contract.code_id)?; + let handler = self.contract_code::<'a, 'b>(contract.code_id)?; let storage = self.contract_storage_readonly(storage, &address); let env = self.get_env(address, block); @@ -1066,8 +1214,8 @@ where action(handler, deps, env) } - fn with_storage( - &self, + fn with_storage<'a, 'b, F, T>( + &'a self, api: &dyn Api, storage: &mut dyn Storage, router: &dyn CosmosRouter, @@ -1076,7 +1224,8 @@ where action: F, ) -> AnyResult where - F: FnOnce(WasmContract, DepsMut, Env) -> AnyResult, + F: FnOnce(ContractBox<'b, ExecC, QueryC>, DepsMut, Env) -> AnyResult, + 'a: 'b, ExecC: DeserializeOwned, { let contract = self.contract_data(storage, &address)?; diff --git a/src/wasm_emulation/contract.rs b/src/wasm_emulation/contract.rs index 601ac344..f2abf1c5 100644 --- a/src/wasm_emulation/contract.rs +++ b/src/wasm_emulation/contract.rs @@ -1,28 +1,17 @@ use crate::wasm_emulation::api::RealApi; -use crate::wasm_emulation::input::get_querier_storage; use crate::wasm_emulation::input::ReplyArgs; use crate::wasm_emulation::output::StorageChanges; use crate::wasm_emulation::query::MockQuerier; use crate::wasm_emulation::storage::DualStorage; use cosmwasm_std::CustomMsg; use cosmwasm_std::StdError; -use cosmwasm_vm::call_execute; -use cosmwasm_vm::call_instantiate; -use cosmwasm_vm::call_migrate; -use cosmwasm_vm::call_query; -use cosmwasm_vm::call_reply; -use cosmwasm_vm::call_sudo; -use cosmwasm_vm::Backend; -use cosmwasm_vm::BackendApi; -use cosmwasm_vm::Checksum; -use cosmwasm_vm::Instance; -use cosmwasm_vm::InstanceOptions; -use cosmwasm_vm::Querier; -use cosmwasm_vm::Size; +use cosmwasm_vm::{ + call_execute, call_instantiate, call_migrate, call_query, call_reply, call_sudo, Backend, + BackendApi, Checksum, Instance, InstanceOptions, Querier, Size, +}; use cw_orch_daemon::queriers::CosmWasm; use cw_orch_daemon::queriers::DaemonQuerier; -use cosmwasm_std::Empty; use cosmwasm_std::Order; use cosmwasm_std::Storage; @@ -33,9 +22,8 @@ use serde::Serialize; use crate::wasm_emulation::input::InstanceArguments; use crate::wasm_emulation::output::WasmRunnerOutput; -use std::collections::HashSet; - use cosmwasm_vm::internals::check_wasm; +use std::collections::HashSet; use crate::Contract; @@ -43,7 +31,6 @@ use cosmwasm_std::{Binary, CustomQuery, Deps, DepsMut, Env, MessageInfo, Reply, use anyhow::Result as AnyResult; -use super::channel::RemoteChannel; use super::input::ExecuteArgs; use super::input::InstantiateArgs; use super::input::MigrateArgs; @@ -51,6 +38,7 @@ use super::input::QueryArgs; use super::input::SudoArgs; use super::input::WasmFunction; use super::output::WasmOutput; +use super::query::mock_querier::ForkState; fn apply_storage_changes(storage: &mut dyn Storage, output: &WasmRunnerOutput) { // We change all the values with the output @@ -83,18 +71,18 @@ pub struct DistantCodeId { } #[derive(Serialize, Deserialize, Clone)] -pub struct LocalContract { +pub struct LocalWasmContract { pub code: Vec, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Debug, Clone)] pub enum WasmContract { - Local(LocalContract), + Local(LocalWasmContract), DistantContract(DistantContract), DistantCodeId(DistantCodeId), } -impl std::fmt::Debug for LocalContract { +impl std::fmt::Debug for LocalWasmContract { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { write!( f, @@ -115,7 +103,7 @@ impl WasmContract { ]), ) .unwrap(); - Self::Local(LocalContract { code }) + Self::Local(LocalWasmContract { code }) } pub fn new_distant_contract(contract_addr: String) -> Self { @@ -126,49 +114,63 @@ impl WasmContract { Self::DistantCodeId(DistantCodeId { code_id }) } - pub fn get_code(&self, remote: RemoteChannel) -> AnyResult> { + pub fn get_code( + &self, + fork_state: ForkState, + ) -> AnyResult> { match self { - WasmContract::Local(LocalContract { code, .. }) => Ok(code.clone()), + WasmContract::Local(LocalWasmContract { code, .. }) => Ok(code.clone()), WasmContract::DistantContract(DistantContract { contract_addr }) => { - let wasm_querier = CosmWasm::new(remote.channel); + let wasm_querier = CosmWasm::new(fork_state.remote.channel); - let code_info = remote + let code_info = fork_state + .remote .rt .block_on(wasm_querier.contract_info(contract_addr))?; - let code = remote + let code = fork_state + .remote .rt .block_on(wasm_querier.code_data(code_info.code_id))?; Ok(code) } WasmContract::DistantCodeId(DistantCodeId { code_id }) => { - let wasm_querier = CosmWasm::new(remote.channel); + let wasm_querier = CosmWasm::new(fork_state.remote.channel); - let code = remote.rt.block_on(wasm_querier.code_data(*code_id))?; + let code = fork_state + .remote + .rt + .block_on(wasm_querier.code_data(*code_id))?; Ok(code) } } } - pub fn run_contract( + pub fn run_contract< + QueryC: CustomQuery + DeserializeOwned + 'static, + ExecC: CustomMsg + DeserializeOwned, + >( &self, args: InstanceArguments, - remote: RemoteChannel, + fork_state: ForkState, ) -> AnyResult> { let InstanceArguments { function, init_storage, - querier_storage, } = args; let address = function.get_address(); - let code = self.get_code(remote.clone())?; + let code = self.get_code(fork_state.clone())?; - let api = RealApi::new(&remote.chain.bech32_prefix); + let api = RealApi::new(&fork_state.remote.chain.bech32_prefix); // We create the backend here from outside information; let backend = Backend { api, - storage: DualStorage::new(remote.clone(), address.to_string(), Some(init_storage))?, - querier: MockQuerier::::new(remote, Some(querier_storage)), + storage: DualStorage::new( + fork_state.remote.clone(), + address.to_string(), + Some(init_storage), + )?, + querier: MockQuerier::::new(fork_state), }; let options = InstanceOptions { gas_limit: DEFAULT_GAS_LIMIT, @@ -203,23 +205,27 @@ impl WasmContract { pub fn after_execution_callback(&self, output: &WasmRunnerOutput) { // We log the gas used - print!("Gas used {:?} for ", output.gas_used); - match output.wasm { - WasmOutput::Execute(_) => print!("execution"), - WasmOutput::Query(_) => print!("query"), - WasmOutput::Instantiate(_) => print!("instantiation"), - WasmOutput::Migrate(_) => print!("migration"), - WasmOutput::Sudo(_) => print!("sudo"), - WasmOutput::Reply(_) => print!("reply"), - } - println!(" on contract {:?}. ", self); + let operation = match output.wasm { + WasmOutput::Execute(_) => "execution", + WasmOutput::Query(_) => "query", + WasmOutput::Instantiate(_) => "instantiation", + WasmOutput::Migrate(_) => "migration", + WasmOutput::Sudo(_) => "sudo", + WasmOutput::Reply(_) => "reply", + }; + log::debug!( + "Gas used {:?} for {:} on contract {:?}", + output.gas_used, + operation, + self + ); } } impl Contract for WasmContract where ExecC: CustomMsg + DeserializeOwned, - QueryC: CustomQuery, + QueryC: CustomQuery + DeserializeOwned, { fn execute( &self, @@ -227,16 +233,15 @@ where env: Env, info: MessageInfo, msg: Vec, - remote: RemoteChannel, + fork_state: ForkState, ) -> AnyResult> { // We start by building the dependencies we will pass through the wasm executer let execute_args = InstanceArguments { function: WasmFunction::Execute(ExecuteArgs { env, info, msg }), init_storage: deps.storage.range(None, None, Order::Ascending).collect(), - querier_storage: get_querier_storage(&deps.querier)?, }; - let decoded_result = self.run_contract(execute_args, remote)?; + let decoded_result = self.run_contract(execute_args, fork_state)?; apply_storage_changes(deps.storage, &decoded_result); self.after_execution_callback(&decoded_result); @@ -253,16 +258,15 @@ where env: Env, info: MessageInfo, msg: Vec, - remote: RemoteChannel, + fork_state: ForkState, ) -> AnyResult> { // We start by building the dependencies we will pass through the wasm executer let instantiate_arguments = InstanceArguments { function: WasmFunction::Instantiate(InstantiateArgs { env, info, msg }), init_storage: deps.storage.range(None, None, Order::Ascending).collect(), - querier_storage: get_querier_storage(&deps.querier)?, }; - let decoded_result = self.run_contract(instantiate_arguments, remote)?; + let decoded_result = self.run_contract(instantiate_arguments, fork_state)?; apply_storage_changes(deps.storage, &decoded_result); self.after_execution_callback(&decoded_result); @@ -278,16 +282,16 @@ where deps: Deps, env: Env, msg: Vec, - remote: RemoteChannel, + fork_state: ForkState, ) -> AnyResult { // We start by building the dependencies we will pass through the wasm executer let query_arguments = InstanceArguments { function: WasmFunction::Query(QueryArgs { env, msg }), init_storage: deps.storage.range(None, None, Order::Ascending).collect(), - querier_storage: get_querier_storage(&deps.querier)?, }; - let decoded_result: WasmRunnerOutput = self.run_contract(query_arguments, remote)?; + let decoded_result: WasmRunnerOutput = + self.run_contract(query_arguments, fork_state)?; self.after_execution_callback(&decoded_result); @@ -303,15 +307,14 @@ where deps: DepsMut, env: Env, msg: Vec, - remote: RemoteChannel, + fork_state: ForkState, ) -> AnyResult> { let sudo_args = InstanceArguments { function: WasmFunction::Sudo(SudoArgs { env, msg }), init_storage: deps.storage.range(None, None, Order::Ascending).collect(), - querier_storage: get_querier_storage(&deps.querier)?, }; - let decoded_result = self.run_contract(sudo_args, remote)?; + let decoded_result = self.run_contract(sudo_args, fork_state)?; apply_storage_changes(deps.storage, &decoded_result); self.after_execution_callback(&decoded_result); @@ -328,15 +331,14 @@ where deps: DepsMut, env: Env, reply: Reply, - remote: RemoteChannel, + fork_state: ForkState, ) -> AnyResult> { let reply_args = InstanceArguments { function: WasmFunction::Reply(ReplyArgs { env, reply }), init_storage: deps.storage.range(None, None, Order::Ascending).collect(), - querier_storage: get_querier_storage(&deps.querier)?, }; - let decoded_result = self.run_contract(reply_args, remote)?; + let decoded_result = self.run_contract(reply_args, fork_state)?; apply_storage_changes(deps.storage, &decoded_result); self.after_execution_callback(&decoded_result); @@ -353,15 +355,14 @@ where deps: DepsMut, env: Env, msg: Vec, - remote: RemoteChannel, + fork_state: ForkState, ) -> AnyResult> { let migrate_args = InstanceArguments { function: WasmFunction::Migrate(MigrateArgs { env, msg }), init_storage: deps.storage.range(None, None, Order::Ascending).collect(), - querier_storage: get_querier_storage(&deps.querier)?, }; - let decoded_result = self.run_contract(migrate_args, remote)?; + let decoded_result = self.run_contract(migrate_args, fork_state)?; apply_storage_changes(deps.storage, &decoded_result); self.after_execution_callback(&decoded_result); diff --git a/src/wasm_emulation/input.rs b/src/wasm_emulation/input.rs index 39584add..2580b591 100644 --- a/src/wasm_emulation/input.rs +++ b/src/wasm_emulation/input.rs @@ -1,25 +1,16 @@ use std::collections::HashMap; -use anyhow::Result as AnyResult; -use serde::{Deserialize, Serialize}; - use cosmwasm_std::Addr; -use cosmwasm_std::Binary; -use cosmwasm_std::CustomQuery; -use cosmwasm_std::QuerierWrapper; -use cosmwasm_std::QueryRequest; use cosmwasm_std::{Env, MessageInfo, Reply}; use cw_utils::NativeBalance; -use crate::bank::BankKeeper; use crate::prefixed_storage::get_full_contract_storage_namespace; use crate::wasm::{CodeData, ContractData}; use super::contract::WasmContract; -use super::query::AllQuerier; -#[derive(Serialize, Deserialize, Debug, Clone, Default)] +#[derive(Debug, Clone, Default)] pub struct WasmStorage { pub contracts: HashMap, pub codes: HashMap, @@ -46,43 +37,24 @@ impl WasmStorage { } } -#[derive(Serialize, Deserialize, Debug, Clone, Default)] +#[derive(Debug, Clone, Default)] pub struct BankStorage { pub storage: Vec<(Addr, NativeBalance)>, } -#[derive(Serialize, Clone, Deserialize, Default, Debug)] +#[derive(Clone, Default)] pub struct QuerierStorage { pub wasm: WasmStorage, - pub bank: ::Output, -} - -pub const STARGATE_ALL_WASM_QUERY_URL: &str = "/local.wasm.all"; -pub const STARGATE_ALL_BANK_QUERY_URL: &str = "/local.bank.all"; - -pub fn get_querier_storage( - q: &QuerierWrapper, -) -> AnyResult { - // We get the wasm storage for all wasm contract to make sure we dispatch everything (with the mock Querier) - let wasm = q.query(&QueryRequest::Stargate { - path: STARGATE_ALL_WASM_QUERY_URL.to_string(), - data: Binary(vec![]), - })?; - let bank = q.query(&QueryRequest::Stargate { - path: STARGATE_ALL_BANK_QUERY_URL.to_string(), - data: Binary(vec![]), - })?; - Ok(QuerierStorage { wasm, bank }) + pub bank: BankStorage, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Debug)] pub struct InstanceArguments { pub function: WasmFunction, pub init_storage: Vec<(Vec, Vec)>, - pub querier_storage: QuerierStorage, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Debug)] pub enum WasmFunction { Execute(ExecuteArgs), Instantiate(InstantiateArgs), @@ -92,39 +64,39 @@ pub enum WasmFunction { Migrate(MigrateArgs), } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Debug)] pub struct ExecuteArgs { pub env: Env, pub info: MessageInfo, pub msg: Vec, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Debug)] pub struct InstantiateArgs { pub env: Env, pub info: MessageInfo, pub msg: Vec, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Debug)] pub struct QueryArgs { pub env: Env, pub msg: Vec, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Debug)] pub struct SudoArgs { pub env: Env, pub msg: Vec, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Debug)] pub struct ReplyArgs { pub env: Env, pub reply: Reply, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Debug)] pub struct MigrateArgs { pub env: Env, pub msg: Vec, diff --git a/src/wasm_emulation/query/bank.rs b/src/wasm_emulation/query/bank.rs index aa830770..0771d183 100644 --- a/src/wasm_emulation/query/bank.rs +++ b/src/wasm_emulation/query/bank.rs @@ -31,9 +31,8 @@ pub struct BankQuerier { } impl BankQuerier { - pub fn new(remote: RemoteChannel, init: Option>) -> Self { + pub fn new(remote: RemoteChannel, init: Vec<(Addr, NativeBalance)>) -> Self { let balances: HashMap<_, _> = init - .unwrap_or(vec![]) .iter() .map(|(s, c)| (s.to_string(), c.clone().into_vec())) .collect(); diff --git a/src/wasm_emulation/query/gas.rs b/src/wasm_emulation/query/gas.rs index 5f1d6e9f..9dd7b9b3 100644 --- a/src/wasm_emulation/query/gas.rs +++ b/src/wasm_emulation/query/gas.rs @@ -19,3 +19,6 @@ pub const GAS_COST_QUERY_ERROR: u64 = 1000; // API (from cosmwasm_vm directly) pub const GAS_COST_HUMANIZE: u64 = 44; pub const GAS_COST_CANONICALIZE: u64 = 55; + +// All queries (test) +pub const GAS_COST_ALL_QUERIES: u64 = 10_000; diff --git a/src/wasm_emulation/query/mock_querier.rs b/src/wasm_emulation/query/mock_querier.rs index d570e382..386bda23 100644 --- a/src/wasm_emulation/query/mock_querier.rs +++ b/src/wasm_emulation/query/mock_querier.rs @@ -1,8 +1,12 @@ +use std::collections::HashMap; + use crate::wasm_emulation::channel::RemoteChannel; use crate::wasm_emulation::query::bank::BankQuerier; use crate::wasm_emulation::query::staking::StakingQuerier; use crate::wasm_emulation::query::wasm::WasmQuerier; +use cosmwasm_std::CustomMsg; +use cosmwasm_std::Env; use cosmwasm_vm::BackendResult; use cosmwasm_vm::GasInfo; @@ -14,7 +18,7 @@ use cosmwasm_std::Coin; use cosmwasm_std::SystemError; use cosmwasm_std::from_json; -use cosmwasm_std::{ContractResult, Empty, SystemResult}; +use cosmwasm_std::{ContractResult, SystemResult}; use cosmwasm_std::{CustomQuery, QueryRequest}; use cosmwasm_std::{FullDelegation, Validator}; @@ -22,9 +26,28 @@ use cosmwasm_std::Attribute; use cosmwasm_std::QuerierResult; use crate::wasm_emulation::input::QuerierStorage; +use crate::Contract; use super::gas::GAS_COST_QUERY_ERROR; +#[derive(Clone)] +pub struct LocalForkedState { + pub contracts: HashMap>, + pub env: Env, +} + +#[derive(Clone)] +pub struct ForkState +where + QueryC: CustomQuery + DeserializeOwned + 'static, + ExecC: CustomMsg + 'static, +{ + pub remote: RemoteChannel, + /// Only query function right now, but we might pass along the whole application state to avoid stargate queries + pub local_state: LocalForkedState, + pub querier_storage: QuerierStorage, +} + pub type QueryResultWithGas = (QuerierResult, GasInfo); /// The same type as cosmwasm-std's QuerierResult, but easier to reuse in @@ -33,29 +56,40 @@ pub type MockQuerierCustomHandlerResult = SystemResult>; /// MockQuerier holds an immutable table of bank balances /// and configurable handlers for Wasm queries and custom queries. -pub struct MockQuerier { +pub struct MockQuerier< + ExecC: CustomMsg + DeserializeOwned + 'static, + QueryC: CustomQuery + DeserializeOwned + 'static, +> { bank: BankQuerier, staking: StakingQuerier, - wasm: WasmQuerier, + wasm: WasmQuerier, + + //Box, Env, Vec) -> Result>, //fn(deps: Deps, env: Env, msg: Vec) -> Result, /// A handler to handle custom queries. This is set to a dummy handler that /// always errors by default. Update it via `with_custom_handler`. /// /// Use box to avoid the need of another generic type - custom_handler: Box Fn(&'a C) -> QueryResultWithGas>, + custom_handler: Box Fn(&'a QueryC) -> QueryResultWithGas>, remote: RemoteChannel, } -impl MockQuerier { - pub fn new(remote: RemoteChannel, storage: Option) -> Self { +impl< + ExecC: CustomMsg + DeserializeOwned + 'static, + QueryC: CustomQuery + DeserializeOwned + 'static, + > MockQuerier +{ + pub fn new(fork_state: ForkState) -> Self { + // We create query_closures for all local_codes + MockQuerier { bank: BankQuerier::new( - remote.clone(), - storage.as_ref().map(|storage| storage.bank.storage.clone()), + fork_state.remote.clone(), + fork_state.querier_storage.bank.storage.clone(), ), staking: StakingQuerier::default(), - wasm: WasmQuerier::new(remote.clone(), storage), + wasm: WasmQuerier::new(fork_state.clone()), // strange argument notation suggested as a workaround here: https://github.com/rust-lang/rust/issues/41078#issuecomment-294296365 custom_handler: Box::from(|_: &_| -> QueryResultWithGas { ( @@ -65,7 +99,7 @@ impl MockQuerier { GasInfo::free(), ) }), - remote, + remote: fork_state.remote, } } @@ -89,20 +123,24 @@ impl MockQuerier { pub fn with_custom_handler(mut self, handler: CH) -> Self where - CH: Fn(&C) -> QueryResultWithGas, + CH: Fn(&QueryC) -> QueryResultWithGas, { self.custom_handler = Box::from(handler); self } } -impl cosmwasm_vm::Querier for MockQuerier { +impl< + ExecC: CustomMsg + DeserializeOwned + 'static, + QueryC: CustomQuery + DeserializeOwned + 'static, + > cosmwasm_vm::Querier for MockQuerier +{ fn query_raw( &self, bin_request: &[u8], _gas_limit: u64, ) -> BackendResult>> { - let request: QueryRequest = match from_json(bin_request) { + let request: QueryRequest = match from_json(bin_request) { Ok(v) => v, Err(e) => { return ( @@ -120,8 +158,33 @@ impl cosmwasm_vm::Querier for MockQuerier } } -impl MockQuerier { - pub fn handle_query(&self, request: &QueryRequest) -> QueryResultWithGas { +impl< + ExecC: CustomMsg + DeserializeOwned + 'static, + QueryC: CustomQuery + DeserializeOwned + 'static, + > cosmwasm_std::Querier for MockQuerier +{ + fn raw_query(&self, bin_request: &[u8]) -> SystemResult> { + let request: QueryRequest = match from_json(bin_request) { + Ok(v) => v, + Err(e) => { + return SystemResult::Err(SystemError::InvalidRequest { + error: format!("Parsing query request: {}", e), + request: bin_request.into(), + }) + } + }; + let result = self.handle_query(&request); + + result.0 + } +} + +impl< + ExecC: CustomMsg + DeserializeOwned + 'static, + QueryC: CustomQuery + DeserializeOwned + 'static, + > MockQuerier +{ + pub fn handle_query(&self, request: &QueryRequest) -> QueryResultWithGas { match &request { QueryRequest::Bank(bank_query) => self.bank.query(bank_query), QueryRequest::Custom(custom_query) => (*self.custom_handler)(custom_query), diff --git a/src/wasm_emulation/query/mod.rs b/src/wasm_emulation/query/mod.rs index 6bb3f1fe..258bc0b7 100644 --- a/src/wasm_emulation/query/mod.rs +++ b/src/wasm_emulation/query/mod.rs @@ -3,15 +3,18 @@ pub mod mock_querier; pub mod staking; pub mod wasm; use cosmwasm_std::Storage; -use serde::de::DeserializeOwned; pub use mock_querier::MockQuerier; pub mod gas; use anyhow::Result as AnyResult; -use serde::Serialize; -pub trait AllQuerier { - type Output: Serialize + Clone + DeserializeOwned + Default; - fn query_all(&self, storage: &dyn Storage) -> AnyResult; +use super::input::{BankStorage, WasmStorage}; + +pub trait AllWasmQuerier { + fn query_all(&self, storage: &dyn Storage) -> AnyResult; +} + +pub trait AllBankQuerier { + fn query_all(&self, storage: &dyn Storage) -> AnyResult; } diff --git a/src/wasm_emulation/query/wasm.rs b/src/wasm_emulation/query/wasm.rs index 9e966656..147701ee 100644 --- a/src/wasm_emulation/query/wasm.rs +++ b/src/wasm_emulation/query/wasm.rs @@ -1,48 +1,63 @@ +use std::marker::PhantomData; + +use crate::addons::MockApiBech32; use crate::prefixed_storage::get_full_contract_storage_namespace; use crate::queries::wasm::WasmRemoteQuerier; -use crate::wasm_emulation::query::gas::{GAS_COST_CONTRACT_INFO, GAS_COST_RAW_COSMWASM_QUERY}; +use crate::wasm_emulation::query::gas::{ + GAS_COST_ALL_QUERIES, GAS_COST_CONTRACT_INFO, GAS_COST_RAW_COSMWASM_QUERY, +}; use crate::wasm_emulation::query::mock_querier::QueryResultWithGas; +use crate::wasm_emulation::query::MockQuerier; +use crate::Contract; use crate::wasm_emulation::contract::WasmContract; -use crate::wasm_emulation::input::QuerierStorage; -use crate::wasm_emulation::input::WasmFunction; -use crate::wasm_emulation::output::WasmOutput; -use crate::wasm_emulation::output::WasmRunnerOutput; -use cosmwasm_std::testing::mock_env; +use cosmwasm_std::testing::MockStorage; use cosmwasm_vm::GasInfo; -use cosmwasm_std::{to_json_binary, Addr, ContractInfoResponse, SystemError, SystemResult}; -use cosmwasm_std::{ContractResult, Empty}; +use cosmwasm_std::{ + to_json_binary, Addr, ContractInfoResponse, CustomMsg, CustomQuery, OwnedDeps, Storage, + SystemError, SystemResult, +}; +use cosmwasm_std::{ContractInfo, ContractResult}; use cosmwasm_std::WasmQuery; +use serde::de::DeserializeOwned; use crate::wasm_emulation::channel::RemoteChannel; -use crate::wasm_emulation::input::{InstanceArguments, QueryArgs}; +use super::mock_querier::ForkState; -pub struct WasmQuerier { - current_storage: QuerierStorage, - remote: RemoteChannel, +pub struct WasmQuerier< + ExecC: CustomMsg + DeserializeOwned + 'static, + QueryC: CustomQuery + DeserializeOwned + 'static, +> { + fork_state: ForkState, } -impl WasmQuerier { - pub fn new(remote: RemoteChannel, storage: Option) -> Self { - Self { - current_storage: storage.unwrap_or(Default::default()), - remote, - } +impl< + ExecC: CustomMsg + DeserializeOwned + 'static, + QueryC: CustomQuery + DeserializeOwned + 'static, + > WasmQuerier +{ + pub fn new(fork_state: ForkState) -> Self { + Self { fork_state } } pub fn query(&self, remote: RemoteChannel, request: &WasmQuery) -> QueryResultWithGas { match request { WasmQuery::ContractInfo { contract_addr } => { let addr = Addr::unchecked(contract_addr); - let data = if let Some(local_contract) = - self.current_storage.wasm.contracts.get(contract_addr) + let data = if let Some(local_contract) = self + .fork_state + .querier_storage + .wasm + .contracts + .get(contract_addr) { local_contract.clone() } else { - WasmRemoteQuerier::load_distant_contract(self.remote.clone(), &addr).unwrap() + WasmRemoteQuerier::load_distant_contract(self.fork_state.remote.clone(), &addr) + .unwrap() }; let mut response = ContractInfoResponse::default(); response.code_id = data.code_id; @@ -59,60 +74,117 @@ impl WasmQuerier { get_full_contract_storage_namespace(&Addr::unchecked(contract_addr)).to_vec(); total_key.extend_from_slice(key); - let value: Vec = if let Some(value) = self - .current_storage + if let Some(value) = self + .fork_state + .querier_storage .wasm .storage .iter() .find(|e| e.0 == total_key) { - value.1.clone() + ( + SystemResult::Ok(ContractResult::Ok(value.1.clone().into())), + GasInfo::with_externally_used(GAS_COST_RAW_COSMWASM_QUERY), + ) } else { - WasmRemoteQuerier::raw_query(remote, contract_addr.clone(), key.clone()) - .unwrap() - }; - - ( - SystemResult::Ok(ContractResult::Ok(value.into())), - GasInfo::with_externally_used(GAS_COST_RAW_COSMWASM_QUERY), - ) + ( + SystemResult::Ok( + WasmRemoteQuerier::raw_query( + remote, + contract_addr.clone(), + key.clone(), + ) + .map(Into::into) + .into(), + ), + GasInfo::with_externally_used(GAS_COST_RAW_COSMWASM_QUERY), + ) + } } WasmQuery::Smart { contract_addr, msg } => { let addr = Addr::unchecked(contract_addr); - // If the contract is already defined in our storage, we load it from there - let contract = if let Some(local_contract) = - self.current_storage.wasm.contracts.get(contract_addr) + + let mut storage = MockStorage::default(); + // Set the storage + for (key, value) in self + .fork_state + .querier_storage + .wasm + .get_contract_storage(&addr) + { + storage.set(&key, &value); + } + + let deps = OwnedDeps { + storage, + api: MockApiBech32::new(&self.fork_state.remote.chain.bech32_prefix), + querier: MockQuerier::new(self.fork_state.clone()), + custom_query_type: PhantomData::, + }; + let mut env = self.fork_state.local_state.env.clone(); + env.contract = ContractInfo { + address: Addr::unchecked(contract_addr), + }; + + let result = if let Some(local_contract) = self + .fork_state + .querier_storage + .wasm + .contracts + .get(contract_addr) { - if let Some(code_info) = self - .current_storage + // If the contract data is already defined in our storage, we load it from there + if let Some(code) = self + .fork_state + .querier_storage .wasm .codes .get(&(local_contract.code_id as usize)) { - // We execute the query - code_info.clone() + // Local Wasm Contract case + >::query( + code, + deps.as_ref(), + env, + msg.to_vec(), + self.fork_state.clone(), + ) + } else if let Some(local_contract) = self + .fork_state + .local_state + .contracts + .get(&(local_contract.code_id as usize)) + { + // Local Rust Contract case + unsafe { + local_contract.as_ref().unwrap().query( + deps.as_ref(), + env, + msg.to_vec(), + self.fork_state.clone(), + ) + } } else { - WasmContract::new_distant_code_id(local_contract.code_id) + // Distant Registered Contract case + >::query( + &WasmContract::new_distant_code_id(local_contract.code_id), + deps.as_ref(), + env, + msg.to_vec(), + self.fork_state.clone(), + ) } } else { - WasmContract::new_distant_contract(contract_addr.to_string()) + // Distant UnRegistered Contract case + >::query( + &WasmContract::new_distant_contract(contract_addr.to_string()), + deps.as_ref(), + env, + msg.to_vec(), + self.fork_state.clone(), + ) }; - let mut env = mock_env(); - env.contract.address = addr.clone(); - // Here we specify empty because we only car about the query result - let result: Result, _> = contract.run_contract( - InstanceArguments { - function: WasmFunction::Query(QueryArgs { - env, - msg: msg.to_vec(), - }), - querier_storage: self.current_storage.clone(), - init_storage: self.current_storage.wasm.get_contract_storage(&addr), - }, - self.remote.clone(), - ); - let result = if let Err(e) = result { return ( SystemResult::Err(SystemError::InvalidRequest { @@ -125,20 +197,16 @@ impl WasmQuerier { result.unwrap() }; - let bin = match result.wasm { - WasmOutput::Query(bin) => bin, - _ => panic!("Unexpected contract response, not possible"), - }; - ( - SystemResult::Ok(ContractResult::Ok(bin)), - GasInfo::with_externally_used(result.gas_used), + SystemResult::Ok(ContractResult::Ok(result)), + GasInfo::with_externally_used(GAS_COST_ALL_QUERIES), ) } #[cfg(feature = "cosmwasm_1_2")] WasmQuery::CodeInfo { code_id } => { let code_data = self - .current_storage + .fork_state + .querier_storage .wasm .code_data .get(&(*code_id as usize)); @@ -149,7 +217,7 @@ impl WasmQuerier { res.checksum = code_data.checksum.clone(); res } else { - WasmRemoteQuerier::code_info(self.remote.clone(), *code_id).unwrap() + WasmRemoteQuerier::code_info(self.fork_state.remote.clone(), *code_id).unwrap() }; ( SystemResult::Ok(to_json_binary(&res).into()), diff --git a/src/wasm_emulation/storage/analyzer.rs b/src/wasm_emulation/storage/analyzer.rs index 2b83e257..1a8fb4a9 100644 --- a/src/wasm_emulation/storage/analyzer.rs +++ b/src/wasm_emulation/storage/analyzer.rs @@ -2,24 +2,23 @@ use crate::prefixed_storage::decode_length; use crate::prefixed_storage::to_length_prefixed; use crate::prefixed_storage::CONTRACT_STORAGE_PREFIX; use crate::wasm_emulation::channel::RemoteChannel; -use crate::wasm_emulation::input::get_querier_storage; -use crate::Bank; +use crate::BankKeeper; use crate::Distribution; use crate::Gov; use crate::Ibc; use crate::Module; use crate::Staking; -use crate::Wasm; +use crate::WasmKeeper; use cosmwasm_std::Addr; use cosmwasm_std::Api; use cosmwasm_std::Coin; +use cosmwasm_std::CustomMsg; use cosmwasm_std::CustomQuery; use cosmwasm_std::Storage; use cw_orch_daemon::queriers::CosmWasm; use cw_orch_daemon::queriers::DaemonQuerier; use cw_utils::NativeBalance; use rustc_serialize::json::Json; -use schemars::JsonSchema; use serde::Serialize; use serde::__private::from_utf8_lossy; use serde::de::DeserializeOwned; @@ -44,15 +43,23 @@ pub struct StorageAnalyzer { } impl StorageAnalyzer { - pub fn new( - app: &App, + pub fn new( + app: &App< + BankKeeper, + ApiT, + StorageT, + CustomT, + WasmKeeper, + StakingT, + DistrT, + IbcT, + GovT, + >, ) -> AnyResult where - CustomT::ExecT: - std::fmt::Debug + PartialEq + Clone + JsonSchema + DeserializeOwned + 'static, + CustomT::ExecT: CustomMsg + DeserializeOwned + 'static, CustomT::QueryT: CustomQuery + DeserializeOwned + 'static, - WasmT: Wasm, - BankT: Bank, + ApiT: Api, StorageT: Storage, CustomT: Module, @@ -62,7 +69,7 @@ impl StorageAnalyzer { GovT: Gov, { Ok(Self { - storage: get_querier_storage(&app.wrap())?, + storage: app.get_querier_storage()?, remote: app.remote.clone(), }) } diff --git a/src/wasm_emulation/storage/dual_std_storage.rs b/src/wasm_emulation/storage/dual_std_storage.rs new file mode 100644 index 00000000..2aeb33c4 --- /dev/null +++ b/src/wasm_emulation/storage/dual_std_storage.rs @@ -0,0 +1,216 @@ +use crate::wasm_emulation::channel::RemoteChannel; + +use cosmrs::proto::cosmos::base::query::v1beta1::PageRequest; +use cosmrs::proto::cosmwasm::wasm::v1::Model; +use cosmwasm_std::Record; +use cosmwasm_std::{Order, Storage}; +use cw_orch_daemon::queriers::DaemonQuerier; +use num_bigint::{BigInt, Sign}; +use std::iter::{self, Peekable}; + +use cw_orch_daemon::queriers::CosmWasm; + +fn get_key_bigint(mut key1: Vec, mut key2: Vec) -> (BigInt, BigInt) { + if key1.len() >= key2.len() { + key2.extend(iter::repeat(0).take(key1.len() - key2.len())) + } else { + key1.extend(iter::repeat(0).take(key2.len() - key1.len())) + } + + ( + BigInt::from_bytes_be(Sign::Plus, &key1), + BigInt::from_bytes_be(Sign::Plus, &key2), + ) +} + +fn gte(key1: Vec, key2: Vec) -> bool { + let ints = get_key_bigint(key1, key2); + + ints.0 >= ints.1 +} + +fn _gt(key1: Vec, key2: Vec) -> bool { + let ints = get_key_bigint(key1, key2); + ints.0 > ints.1 +} + +use std::collections::HashSet; + +use anyhow::Result as AnyResult; +const DISTANT_LIMIT: u64 = 5u64; + +struct DistantIter { + remote: RemoteChannel, + contract_addr: String, + data: Vec, + position: usize, + key: Option>, // if set to None, there is no more keys to investigate in the distant container + start: Option>, + end: Option>, + reverse: bool, +} + +/// Iterator to get multiple keys +struct Iter<'a> { + distant_iter: DistantIter, + local_iter: Peekable + 'a>>, +} + +impl<'i> Iterator for Iter<'i> { + type Item = Record; + + fn next(&mut self) -> Option { + // 1. We verify that there is enough elements in the distant iterator + if self.distant_iter.position == self.distant_iter.data.len() + && self.distant_iter.key.is_some() + && (self.distant_iter.position == 0 + || !self.distant_iter.key.clone().unwrap().is_empty()) + { + let wasm_querier = CosmWasm::new(self.distant_iter.remote.channel.clone()); + let new_keys = self + .distant_iter + .remote + .rt + .block_on(wasm_querier.all_contract_state( + self.distant_iter.contract_addr.clone(), + Some(PageRequest { + key: self.distant_iter.key.clone().unwrap(), + offset: 0, + limit: DISTANT_LIMIT, + count_total: false, + reverse: self.distant_iter.reverse, + }), + )) + .unwrap_or_default(); + + // We make sure the data queried correspond to all the keys we need + self.distant_iter + .data + .extend(new_keys.models.into_iter().filter(|m| { + let lower_than_end = if let Some(end) = self.distant_iter.end.clone() { + !gte(m.key.clone(), end) + } else { + true + }; + + let higher_than_start = if let Some(start) = self.distant_iter.start.clone() { + gte(m.key.clone(), start) + } else { + true + }; + + lower_than_end && higher_than_start + })); + self.distant_iter.key = new_keys.pagination.map(|p| p.next_key); + } + + // 2. We find the first key in order between distant and local storage + let next_local = self.local_iter.peek(); + let next_distant = self.distant_iter.data.get(self.distant_iter.position); + + if let Some(local) = next_local { + if let Some(distant) = next_distant { + // We compare the two keys with the order and return the higher key + let key_local = BigInt::from_bytes_be(Sign::Plus, &local.0); + let key_distant = BigInt::from_bytes_be(Sign::Plus, &distant.key); + if (key_local < key_distant) == self.distant_iter.reverse { + self.distant_iter.position += 1; + Some((distant.key.clone(), distant.value.clone())) + } else { + self.local_iter.next() + } + } else { + self.local_iter.next() + } + } else if let Some(distant) = next_distant { + self.distant_iter.position += 1; + Some((distant.key.clone(), distant.value.clone())) + } else { + None + } + } +} + +pub struct DualStorage<'a> { + pub local_storage: Box, + pub removed_keys: HashSet>, + pub remote: RemoteChannel, + pub contract_addr: String, +} + +impl<'a> DualStorage<'a> { + pub fn new( + remote: RemoteChannel, + contract_addr: String, + local_storage: Box, + ) -> AnyResult { + Ok(Self { + local_storage, + remote, + removed_keys: HashSet::default(), + contract_addr, + }) + } +} + +impl<'a> Storage for DualStorage<'a> { + fn get(&self, key: &[u8]) -> Option> { + // First we try to get the value locally + let mut value = self.local_storage.get(key); + // If it's not available, we query it online if it was not removed locally + if !self.removed_keys.contains(key) && value.as_ref().is_none() { + let wasm_querier = CosmWasm::new(self.remote.channel.clone()); + + let distant_result = self.remote.rt.block_on( + wasm_querier.contract_raw_state(self.contract_addr.clone(), key.to_vec()), + ); + + if let Ok(result) = distant_result { + if !result.data.is_empty() { + value = Some(result.data) + } + } + } + value + } + + fn set(&mut self, key: &[u8], value: &[u8]) { + self.removed_keys.remove(key); // It's not locally removed anymore, because we set it locally + self.local_storage.set(key, value) + } + + fn remove(&mut self, key: &[u8]) { + self.removed_keys.insert(key.to_vec()); // We indicate locally if it's removed. So that we can remove keys and not query them on the distant chain + self.local_storage.remove(key) + } + + fn range<'b>( + &'b self, + start: Option<&[u8]>, + end: Option<&[u8]>, + order: Order, + ) -> Box + 'b> { + let order_i32: i32 = order.try_into().unwrap(); + let descending_order: i32 = Order::Descending.try_into().unwrap(); + + let querier_start = if order_i32 == descending_order { + end.map(|s| s.to_vec()).unwrap_or_default() + } else { + start.map(|s| s.to_vec()).unwrap_or_default() + }; + + return Box::new(Iter { + distant_iter: DistantIter { + remote: self.remote.clone(), + contract_addr: self.contract_addr.clone(), + data: vec![], + position: 0, + key: Some(querier_start), + end: end.map(|e| e.to_vec()), + start: start.map(|e| e.to_vec()), + reverse: order_i32 == descending_order, + }, + local_iter: self.local_storage.range(start, end, order).peekable(), + }); + } +} diff --git a/src/wasm_emulation/storage/dual_storage.rs b/src/wasm_emulation/storage/dual_storage.rs index 93185cec..7bfd0e16 100644 --- a/src/wasm_emulation/storage/dual_storage.rs +++ b/src/wasm_emulation/storage/dual_storage.rs @@ -135,9 +135,9 @@ impl Storage for DualStorage { let descending_order: i32 = Order::Descending.try_into().unwrap(); let querier_start = if order_i32 == descending_order { - end.map(|s| s.to_vec()).unwrap_or(vec![]) + end.map(|s| s.to_vec()).unwrap_or_default() } else { - start.map(|s| s.to_vec()).unwrap_or(vec![]) + start.map(|s| s.to_vec()).unwrap_or_default() }; let iter = Iter { @@ -168,13 +168,13 @@ impl Storage for DualStorage { let iterator = match self.iterators.get_mut(&iterator_id) { Some(i) => i, None => { - println!("End next premature"); return ( Err(BackendError::iterator_does_not_exist(iterator_id)), GasInfo::free(), ); } }; + // TODO, work with removed keys and don't take them // 1. We verify that there is enough elements in the distant iterator if iterator.distant_iter.position == iterator.distant_iter.data.len() @@ -226,21 +226,8 @@ impl Storage for DualStorage { .data .get(iterator.distant_iter.position); - // We select the distant storage only if the keys are valid (inside the start, end range) - let is_valid_distant_key = next_distant.is_some() - && (iterator.distant_iter.end.is_none() || // If there is end no bound - iterator.distant_iter.reverse || // if the iterator is reversed, - !gte(next_distant.unwrap().key.clone(), iterator.distant_iter.end.clone().unwrap())) - && (iterator.distant_iter.start.is_none() - || !iterator.distant_iter.reverse - || gte( - next_distant.unwrap().key.clone(), - iterator.distant_iter.start.clone().unwrap(), - )); - let key_value = if let Some(local) = next_local { - if is_valid_distant_key { - let distant = next_distant.unwrap(); + if let Some(distant) = next_distant { // We compare the two keys with the order and return the higher key let key_local = BigInt::from_bytes_be(Sign::Plus, &local.0); let key_distant = BigInt::from_bytes_be(Sign::Plus, &distant.key); @@ -253,8 +240,7 @@ impl Storage for DualStorage { } else { self.local_storage.next(iterator.local_iter).0.unwrap() } - } else if is_valid_distant_key { - let distant = next_distant.unwrap(); + } else if let Some(distant) = next_distant { iterator.distant_iter.position += 1; Some((distant.key.clone(), distant.value.clone())) } else { diff --git a/src/wasm_emulation/storage/mock_storage.rs b/src/wasm_emulation/storage/mock_storage.rs index b79c3b5b..78b6b56e 100644 --- a/src/wasm_emulation/storage/mock_storage.rs +++ b/src/wasm_emulation/storage/mock_storage.rs @@ -14,16 +14,16 @@ pub const GAS_COST_RANGE: u64 = 11; // We needed to add the peak function on the cosmwasm-vm code // This is used for making sure we have the right order between distant and local storage -#[derive(Default, Debug)] -struct Iter { +#[derive(Default, Debug, Clone)] +pub struct Iter { data: Vec, position: usize, } -#[derive(Default, Debug)] +#[derive(Default, Debug, Clone)] pub struct MockStorage { - data: BTreeMap, Vec>, - iterators: HashMap, + pub data: BTreeMap, Vec>, + pub iterators: HashMap, } impl MockStorage { diff --git a/src/wasm_emulation/storage/mod.rs b/src/wasm_emulation/storage/mod.rs index 990ea085..8728e66a 100644 --- a/src/wasm_emulation/storage/mod.rs +++ b/src/wasm_emulation/storage/mod.rs @@ -1,5 +1,7 @@ +pub mod dual_std_storage; pub mod dual_storage; pub mod mock_storage; +pub mod storage_wrappers; pub use dual_storage::DualStorage; pub use mock_storage::MockStorage; diff --git a/src/wasm_emulation/storage/storage_wrappers.rs b/src/wasm_emulation/storage/storage_wrappers.rs new file mode 100644 index 00000000..33124f99 --- /dev/null +++ b/src/wasm_emulation/storage/storage_wrappers.rs @@ -0,0 +1,71 @@ +use cosmwasm_std::{Order, Record, Storage}; + +pub struct StorageWrapper<'a> { + storage: &'a mut dyn Storage, +} + +impl<'a> StorageWrapper<'a> { + pub fn new(storage: &'a mut dyn Storage) -> Self { + StorageWrapper { storage } + } +} + +impl<'a> Storage for StorageWrapper<'a> { + fn get(&self, key: &[u8]) -> Option> { + self.storage.get(key) + } + + fn set(&mut self, key: &[u8], value: &[u8]) { + self.storage.set(key, value) + } + + fn remove(&mut self, key: &[u8]) { + self.storage.remove(key) + } + + /// range allows iteration over a set of keys, either forwards or backwards + /// uses standard rust range notation, and eg db.range(b"foo"..b"bar") also works reverse + fn range<'b>( + &'b self, + start: Option<&[u8]>, + end: Option<&[u8]>, + order: Order, + ) -> Box + 'b> { + self.storage.range(start, end, order) + } +} + +pub struct ReadonlyStorageWrapper<'a> { + storage: &'a dyn Storage, +} + +impl<'a> ReadonlyStorageWrapper<'a> { + pub fn new(storage: &'a dyn Storage) -> Self { + ReadonlyStorageWrapper { storage } + } +} + +impl<'a> Storage for ReadonlyStorageWrapper<'a> { + fn get(&self, key: &[u8]) -> Option> { + self.storage.get(key) + } + + fn set(&mut self, _key: &[u8], _value: &[u8]) { + unimplemented!() + } + + fn remove(&mut self, _key: &[u8]) { + unimplemented!() + } + + /// range allows iteration over a set of keys, either forwards or backwards + /// uses standard rust range notation, and eg db.range(b"foo"..b"bar") also works reverse + fn range<'b>( + &'b self, + start: Option<&[u8]>, + end: Option<&[u8]>, + order: Order, + ) -> Box + 'b> { + self.storage.range(start, end, order) + } +} From bd3181e1cd7c485db67251f8c8826b0bd2efd362 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 19 Dec 2023 13:46:31 +0100 Subject: [PATCH 27/81] Update version --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e969fa99..7586945a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -858,7 +858,7 @@ dependencies = [ [[package]] name = "cw-multi-test" -version = "0.19.3" +version = "0.19.4" dependencies = [ "anyhow", "bech32", diff --git a/Cargo.toml b/Cargo.toml index 0271745e..434e4116 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cw-multi-test" -version = "0.19.3" +version = "0.19.4" authors = ["Ethan Frey "] edition = "2021" description = "Testing tools for multi-contract interactions" From 3af877dfcbc2ed89770a5fe20a85613c3b27b1a8 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Fri, 16 Feb 2024 10:07:52 +0100 Subject: [PATCH 28/81] Corrected distant wasm raw query --- src/contracts.rs | 62 +------------------ src/wasm.rs | 15 ++++- .../storage/dual_std_storage.rs | 7 +-- src/wasm_emulation/storage/dual_storage.rs | 7 +-- 4 files changed, 18 insertions(+), 73 deletions(-) diff --git a/src/contracts.rs b/src/contracts.rs index 804d3726..16857f4b 100644 --- a/src/contracts.rs +++ b/src/contracts.rs @@ -1,14 +1,13 @@ use std::{ error::Error, fmt::{self, Debug, Display}, - ops::Deref, }; use schemars::JsonSchema; use cosmwasm_std::{ - from_json, Binary, CosmosMsg, CustomMsg, CustomQuery, Deps, DepsMut, Empty, Env, MessageInfo, - QuerierWrapper, Reply, Response, StdError, SubMsg, + from_json, Binary, CustomMsg, CustomQuery, Deps, DepsMut, Empty, Env, MessageInfo, + QuerierWrapper, Reply, Response, StdError, }; use anyhow::Result as AnyResult; @@ -228,63 +227,6 @@ where } } -fn decustomize_deps_mut<'a, Q>(deps: &'a mut DepsMut) -> DepsMut<'a, Empty> -where - Q: CustomQuery + DeserializeOwned + 'static, -{ - DepsMut { - storage: deps.storage, - api: deps.api, - querier: QuerierWrapper::new(deps.querier.deref()), - } -} - -fn decustomize_deps<'a, Q>(deps: &'a Deps<'a, Q>) -> Deps<'a, Empty> -where - Q: CustomQuery + DeserializeOwned + 'static, -{ - Deps { - storage: deps.storage, - api: deps.api, - querier: QuerierWrapper::new(deps.querier.deref()), - } -} - -fn customize_response(resp: Response) -> Response -where - C: Clone + fmt::Debug + PartialEq + JsonSchema, -{ - let mut customized_resp = Response::::new() - .add_submessages(resp.messages.into_iter().map(customize_msg::)) - .add_events(resp.events) - .add_attributes(resp.attributes); - customized_resp.data = resp.data; - customized_resp -} - -fn customize_msg(msg: SubMsg) -> SubMsg -where - C: Clone + fmt::Debug + PartialEq + JsonSchema, -{ - SubMsg { - msg: match msg.msg { - CosmosMsg::Wasm(wasm) => CosmosMsg::Wasm(wasm), - CosmosMsg::Bank(bank) => CosmosMsg::Bank(bank), - CosmosMsg::Staking(staking) => CosmosMsg::Staking(staking), - CosmosMsg::Distribution(distribution) => CosmosMsg::Distribution(distribution), - CosmosMsg::Custom(_) => unreachable!(), - #[cfg(feature = "stargate")] - CosmosMsg::Ibc(ibc) => CosmosMsg::Ibc(ibc), - #[cfg(feature = "stargate")] - CosmosMsg::Stargate { type_url, value } => CosmosMsg::Stargate { type_url, value }, - _ => panic!("unknown message variant {:?}", msg), - }, - id: msg.id, - gas_limit: msg.gas_limit, - reply_on: msg.reply_on, - } -} - impl Contract for ContractWrapper where diff --git a/src/wasm.rs b/src/wasm.rs index 95baad20..8d84dc61 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -531,9 +531,18 @@ where } pub fn query_raw(&self, address: Addr, storage: &dyn Storage, key: &[u8]) -> Binary { - let storage = self.contract_storage_readonly(storage, &address); - let data = storage.get(key).unwrap_or_default(); - data.into() + let local_key = self.contract_storage_readonly(storage, &address).get(key); + if let Some(local_key) = local_key { + local_key.into() + } else { + WasmRemoteQuerier::raw_query( + self.remote.clone().unwrap(), + address.to_string(), + key.into(), + ) + .unwrap_or_default() + .into() + } } fn send( diff --git a/src/wasm_emulation/storage/dual_std_storage.rs b/src/wasm_emulation/storage/dual_std_storage.rs index 2aeb33c4..bb26a6c0 100644 --- a/src/wasm_emulation/storage/dual_std_storage.rs +++ b/src/wasm_emulation/storage/dual_std_storage.rs @@ -190,10 +190,7 @@ impl<'a> Storage for DualStorage<'a> { end: Option<&[u8]>, order: Order, ) -> Box + 'b> { - let order_i32: i32 = order.try_into().unwrap(); - let descending_order: i32 = Order::Descending.try_into().unwrap(); - - let querier_start = if order_i32 == descending_order { + let querier_start = if order == Order::Descending { end.map(|s| s.to_vec()).unwrap_or_default() } else { start.map(|s| s.to_vec()).unwrap_or_default() @@ -208,7 +205,7 @@ impl<'a> Storage for DualStorage<'a> { key: Some(querier_start), end: end.map(|e| e.to_vec()), start: start.map(|e| e.to_vec()), - reverse: order_i32 == descending_order, + reverse: order == Order::Descending, }, local_iter: self.local_storage.range(start, end, order).peekable(), }); diff --git a/src/wasm_emulation/storage/dual_storage.rs b/src/wasm_emulation/storage/dual_storage.rs index 7bfd0e16..6b630e43 100644 --- a/src/wasm_emulation/storage/dual_storage.rs +++ b/src/wasm_emulation/storage/dual_storage.rs @@ -131,10 +131,7 @@ impl Storage for DualStorage { let gas_info = GasInfo::with_externally_used(GAS_COST_RANGE); let iterator_id = self.local_storage.scan(start, end, order).0.unwrap(); - let order_i32: i32 = order.try_into().unwrap(); - let descending_order: i32 = Order::Descending.try_into().unwrap(); - - let querier_start = if order_i32 == descending_order { + let querier_start = if order == Order::Descending { end.map(|s| s.to_vec()).unwrap_or_default() } else { start.map(|s| s.to_vec()).unwrap_or_default() @@ -148,7 +145,7 @@ impl Storage for DualStorage { key: Some(querier_start), end: end.map(|e| e.to_vec()), start: start.map(|e| e.to_vec()), - reverse: order_i32 == descending_order, + reverse: order == Order::Descending, }, }; From 55f211d0e52eee6d2c2545d9ca59c34652f44706 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Fri, 16 Feb 2024 13:24:07 +0100 Subject: [PATCH 29/81] No panic on inexistent contract --- src/wasm_emulation/query/wasm.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/wasm_emulation/query/wasm.rs b/src/wasm_emulation/query/wasm.rs index 147701ee..b480d97b 100644 --- a/src/wasm_emulation/query/wasm.rs +++ b/src/wasm_emulation/query/wasm.rs @@ -56,8 +56,21 @@ impl< { local_contract.clone() } else { - WasmRemoteQuerier::load_distant_contract(self.fork_state.remote.clone(), &addr) - .unwrap() + let maybe_distant_contract = WasmRemoteQuerier::load_distant_contract( + self.fork_state.remote.clone(), + &addr, + ); + + if let Ok(contract) = maybe_distant_contract { + contract + } else { + return ( + SystemResult::Err(SystemError::NoSuchContract { + addr: contract_addr.to_string(), + }), + GasInfo::with_externally_used(GAS_COST_CONTRACT_INFO), + ); + } }; let mut response = ContractInfoResponse::default(); response.code_id = data.code_id; From 4af56c5e4451190e91022388374e9bb0db0b8e36 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Fri, 16 Feb 2024 13:26:57 +0100 Subject: [PATCH 30/81] Fixed wasm queries errors --- src/wasm_emulation/query/wasm.rs | 33 +++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/wasm_emulation/query/wasm.rs b/src/wasm_emulation/query/wasm.rs index b480d97b..dc0bc06b 100644 --- a/src/wasm_emulation/query/wasm.rs +++ b/src/wasm_emulation/query/wasm.rs @@ -198,16 +198,17 @@ impl< ) }; - let result = if let Err(e) = result { - return ( - SystemResult::Err(SystemError::InvalidRequest { - error: format!("Error querying a contract: {}", e), - request: msg.clone(), - }), - GasInfo::with_externally_used(0), - ); - } else { - result.unwrap() + let result = match result { + Err(e) => { + return ( + SystemResult::Err(SystemError::InvalidRequest { + error: format!("Error querying a contract: {}", e), + request: msg.clone(), + }), + GasInfo::with_externally_used(0), + ) + } + Ok(result) => result, }; ( @@ -230,7 +231,17 @@ impl< res.checksum = code_data.checksum.clone(); res } else { - WasmRemoteQuerier::code_info(self.fork_state.remote.clone(), *code_id).unwrap() + let maybe_code_info = + WasmRemoteQuerier::code_info(self.fork_state.remote.clone(), *code_id); + + if let Ok(code_info) = maybe_code_info { + code_info + } else { + return ( + SystemResult::Err(SystemError::NoSuchCode { code_id: *code_id }), + GasInfo::with_externally_used(GAS_COST_CONTRACT_INFO), + ); + } }; ( SystemResult::Ok(to_json_binary(&res).into()), From 62be09a46ce44657bb439dfb728bcb7161a36225 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Wed, 24 Apr 2024 09:55:55 +0000 Subject: [PATCH 31/81] Added failing modules types for simpler debugging --- src/app_builder.rs | 12 ++++++------ src/module.rs | 37 +++++++++++++++++++++++++------------ 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/src/app_builder.rs b/src/app_builder.rs index 22fe6dac..759efde8 100644 --- a/src/app_builder.rs +++ b/src/app_builder.rs @@ -93,11 +93,11 @@ impl storage: MockStorage::new(), bank: BankKeeper::new(), wasm: WasmKeeper::new(), - custom: FailingModule::new(), + custom: FailingModule::new("custom"), staking: StakeKeeper::new(), distribution: DistributionKeeper::new(), - ibc: IbcFailingModule::new(), - gov: GovFailingModule::new(), + ibc: IbcFailingModule::new("ibc"), + gov: GovFailingModule::new("gov"), remote: None, } } @@ -128,11 +128,11 @@ where storage: MockStorage::new(), bank: BankKeeper::new(), wasm: WasmKeeper::new(), - custom: FailingModule::new(), + custom: FailingModule::new("custom"), staking: StakeKeeper::new(), distribution: DistributionKeeper::new(), - ibc: IbcFailingModule::new(), - gov: GovFailingModule::new(), + ibc: IbcFailingModule::new("ibc"), + gov: GovFailingModule::new("gov"), remote: None, } } diff --git a/src/module.rs b/src/module.rs index 3bbe452c..88c77f34 100644 --- a/src/module.rs +++ b/src/module.rs @@ -57,17 +57,17 @@ pub trait Module { QueryC: CustomQuery + DeserializeOwned + 'static; } -pub struct FailingModule(PhantomData<(ExecT, QueryT, SudoT)>); - -impl FailingModule { - pub fn new() -> Self { - Self(PhantomData) - } +pub struct FailingModule { + module_type: String, + _t: PhantomData<(ExecT, QueryT, SudoT)>, } -impl Default for FailingModule { - fn default() -> Self { - Self::new() +impl FailingModule { + pub fn new(module_type: &str) -> Self { + Self { + module_type: module_type.to_string(), + _t: PhantomData, + } } } @@ -91,7 +91,12 @@ where sender: Addr, msg: Self::ExecT, ) -> AnyResult { - bail!("Unexpected exec msg {:?} from {:?}", msg, sender) + bail!( + "Unexpected exec msg {:?} from {:?} on module {}", + msg, + sender, + self.module_type + ) } /// Runs any [QueryT](Self::QueryT) message, always returns an error. @@ -103,7 +108,11 @@ where _block: &BlockInfo, request: Self::QueryT, ) -> AnyResult { - bail!("Unexpected custom query {:?}", request) + bail!( + "Unexpected custom query {:?} on module {}", + request, + self.module_type + ) } /// Runs any [SudoT](Self::SudoT) privileged action, always returns an error. @@ -115,7 +124,11 @@ where _block: &BlockInfo, msg: Self::SudoT, ) -> AnyResult { - bail!("Unexpected sudo msg {:?}", msg) + bail!( + "Unexpected sudo msg {:?} on module {}", + msg, + self.module_type + ) } } From 60ebaa49dd5aee388debedff82e2c97a05db184e Mon Sep 17 00:00:00 2001 From: Kayanski Date: Wed, 24 Apr 2024 09:57:52 +0000 Subject: [PATCH 32/81] Not --- src/module.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/module.rs b/src/module.rs index 88c77f34..470e8d97 100644 --- a/src/module.rs +++ b/src/module.rs @@ -92,7 +92,7 @@ where msg: Self::ExecT, ) -> AnyResult { bail!( - "Unexpected exec msg {:?} from {:?} on module {}", + "Unexpected exec msg {:?} from {:?} on {} module", msg, sender, self.module_type @@ -109,7 +109,7 @@ where request: Self::QueryT, ) -> AnyResult { bail!( - "Unexpected custom query {:?} on module {}", + "Unexpected custom query {:?} on {} module", request, self.module_type ) @@ -125,7 +125,7 @@ where msg: Self::SudoT, ) -> AnyResult { bail!( - "Unexpected sudo msg {:?} on module {}", + "Unexpected sudo msg {:?} on {} module", msg, self.module_type ) From c1f4a0d184c67831dee2f30f575a24a03c9a4cfc Mon Sep 17 00:00:00 2001 From: Kayanski Date: Thu, 25 Apr 2024 12:44:27 +0000 Subject: [PATCH 33/81] Updated cw-orch --- Cargo.lock | 1770 ++++++----------- Cargo.toml | 6 +- examples/cavern_test_app.rs | 13 +- examples/counter/error.rs | 3 - examples/counter/mod.rs | 2 - examples/cousin_test.rs | 2 +- examples/test_app.rs | 2 +- src/app.rs | 4 +- src/contracts.rs | 11 +- src/queries/bank.rs | 9 +- src/queries/wasm.rs | 23 +- src/wasm_emulation/channel.rs | 12 +- src/wasm_emulation/contract.rs | 21 +- src/wasm_emulation/query/bank.rs | 17 +- src/wasm_emulation/query/wasm.rs | 4 +- src/wasm_emulation/storage/analyzer.rs | 82 +- .../storage/dual_std_storage.rs | 18 +- src/wasm_emulation/storage/dual_storage.rs | 17 +- 18 files changed, 728 insertions(+), 1288 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7586945a..144ef942 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,11 +4,12 @@ version = 3 [[package]] name = "abstract-cw-multi-test" -version = "0.16.6" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "220367785f98ac307fdeac9810164678ceea454d1298aa780503e907776a892c" +checksum = "33d8a77cbdea0217c303f4909298260363bd80001120689449e58a409fac9072" dependencies = [ "anyhow", + "bech32 0.11.0", "cosmwasm-schema", "cosmwasm-std", "cw-storage-plus 1.2.0", @@ -16,14 +17,13 @@ dependencies = [ "cw20-ics20", "derivative", "hex", - "itertools 0.11.0", + "itertools", "log", - "prost 0.11.9", + "prost", "schemars", "serde", "serde_json", "sha2 0.10.8", - "sha256", "thiserror", ] @@ -44,9 +44,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ "getrandom", "once_cell", @@ -55,9 +55,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -79,9 +79,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" dependencies = [ "backtrace", ] @@ -94,13 +94,13 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "async-recursion" -version = "1.0.5" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" +checksum = "30c5ef0ede93efbf733c1a727f3b6b5a1060bbedd5600183e66f6e4be4af0ec5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.60", ] [[package]] @@ -122,41 +122,25 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.60", ] [[package]] name = "async-trait" -version = "0.1.74" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", -] - -[[package]] -name = "async-tungstenite" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0388bb7a400072bbb41ceb75d65c3baefb2ea99672fa22e85278452cd9b58b" -dependencies = [ - "futures-io", - "futures-util", - "log", - "pin-project-lite", - "rustls-native-certs 0.6.3", - "tokio", - "tokio-rustls 0.23.4", - "tungstenite", + "syn 2.0.60", ] [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "axum" @@ -205,9 +189,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -232,15 +216,9 @@ checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" [[package]] name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - -[[package]] -name = "base64" -version = "0.21.5" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64ct" @@ -254,6 +232,12 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" +[[package]] +name = "bech32" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" + [[package]] name = "bip32" version = "0.5.1" @@ -276,7 +260,7 @@ version = "0.30.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1945a5048598e4189e239d3f809b19bdad4845c4b2ba400d304d2dcf26d2c462" dependencies = [ - "bech32", + "bech32 0.9.1", "bitcoin-private", "bitcoin_hashes", "hex_lit", @@ -306,9 +290,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "bitvec" @@ -342,30 +326,30 @@ dependencies = [ [[package]] name = "bnum" -version = "0.8.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab9008b6bb9fc80b5277f2fe481c09e828743d9151203e804583eb4c9e15b31d" +checksum = "56953345e39537a3e18bdaeba4cb0c58a78c1f61f361dc0fa7c5c7340ae87c5f" [[package]] name = "bs58" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" dependencies = [ "sha2 0.10.8", ] [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytecheck" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" dependencies = [ "bytecheck_derive", "ptr_meta", @@ -374,9 +358,9 @@ dependencies = [ [[package]] name = "bytecheck_derive" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" dependencies = [ "proc-macro2", "quote", @@ -391,21 +375,18 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" dependencies = [ "serde", ] [[package]] name = "cc" -version = "1.0.83" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" [[package]] name = "cfg-if" @@ -415,16 +396,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", - "windows-targets 0.48.5", + "windows-targets 0.52.5", ] [[package]] @@ -435,15 +416,24 @@ checksum = "b8191fa7302e03607ff0e237d4246cc043ff5b3cb9409d995172ba3bea16b807" [[package]] name = "const-oid" -version = "0.9.5" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "convert_case" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -451,9 +441,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "corosensei" @@ -474,10 +464,21 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32560304ab4c365791fd307282f76637213d8083c1a98490c35159cd67852237" dependencies = [ - "prost 0.12.3", - "prost-types 0.12.3", - "tendermint-proto 0.34.0", - "tonic 0.10.2", + "prost", + "prost-types", + "tendermint-proto 0.34.1", + "tonic", +] + +[[package]] +name = "cosmos-sdk-proto" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e23f6ab56d5f031cde05b8b82a5fefd3a1a223595c79e32317a97189e612bc" +dependencies = [ + "prost", + "prost-types", + "tendermint-proto 0.35.0", ] [[package]] @@ -487,7 +488,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47126f5364df9387b9d8559dcef62e99010e1d4098f39eb3f7ee4b5c254e40ea" dependencies = [ "bip32", - "cosmos-sdk-proto", + "cosmos-sdk-proto 0.20.0", "ecdsa", "eyre", "k256", @@ -496,17 +497,17 @@ dependencies = [ "serde_json", "signature", "subtle-encoding", - "tendermint 0.34.0", - "tendermint-rpc 0.34.0", + "tendermint", + "tendermint-rpc", "thiserror", "tokio", ] [[package]] name = "cosmwasm-crypto" -version = "1.5.0" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8bb3c77c3b7ce472056968c745eb501c440fbc07be5004eba02782c35bfbbe3" +checksum = "e6b4c3f9c4616d6413d4b5fc4c270a4cc32a374b9be08671e80e1a019f805d8f" dependencies = [ "digest 0.10.7", "ecdsa", @@ -518,18 +519,18 @@ dependencies = [ [[package]] name = "cosmwasm-derive" -version = "1.5.0" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea73e9162e6efde00018d55ed0061e93a108b5d6ec4548b4f8ce3c706249687" +checksum = "c586ced10c3b00e809ee664a895025a024f60d65d34fe4c09daed4a4db68a3f3" dependencies = [ "syn 1.0.109", ] [[package]] name = "cosmwasm-schema" -version = "1.5.0" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df41ea55f2946b6b43579659eec048cc2f66e8c8e2e3652fc5e5e476f673856" +checksum = "8467874827d384c131955ff6f4d47d02e72a956a08eb3c0ff24f8c903a5517b4" dependencies = [ "cosmwasm-schema-derive", "schemars", @@ -540,9 +541,9 @@ dependencies = [ [[package]] name = "cosmwasm-schema-derive" -version = "1.5.0" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43609e92ce1b9368aa951b334dd354a2d0dd4d484931a5f83ae10e12a26c8ba9" +checksum = "f6db85d98ac80922aef465e564d5b21fa9cfac5058cb62df7f116c3682337393" dependencies = [ "proc-macro2", "quote", @@ -551,12 +552,12 @@ dependencies = [ [[package]] name = "cosmwasm-std" -version = "1.5.0" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04d6864742e3a7662d024b51a94ea81c9af21db6faea2f9a6d2232bb97c6e53e" +checksum = "712fe58f39d55c812f7b2c84e097cdede3a39d520f89b6dc3153837e31741927" dependencies = [ - "base64 0.21.5", - "bech32", + "base64", + "bech32 0.9.1", "bnum", "cosmwasm-crypto", "cosmwasm-derive", @@ -573,9 +574,9 @@ dependencies = [ [[package]] name = "cosmwasm-storage" -version = "1.5.0" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd2b4ae72a03e8f56c85df59d172d51d2d7dc9cec6e2bc811e3fb60c588032a4" +checksum = "66de2ab9db04757bcedef2b5984fbe536903ada4a8a9766717a4a71197ef34f6" dependencies = [ "cosmwasm-std", "serde", @@ -583,9 +584,9 @@ dependencies = [ [[package]] name = "cosmwasm-vm" -version = "1.5.0" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ce190445de4a64d1b046f453b1f52e1e3df1fb481ad5cb039f82d7d47375cb9" +checksum = "faf59efc75d03bb757612998e6b839675bff844871a7c9ec9f52ad4093f665cd" dependencies = [ "bitflags 1.3.2", "bytecheck", @@ -608,9 +609,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] @@ -700,61 +701,46 @@ checksum = "393bc73c451830ff8dbb3a07f61843d6cb41a084f9996319917c0b291ed785bb" [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset 0.9.0", - "scopeguard", ] [[package]] name = "crossbeam-queue" -version = "0.3.8" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crypto-bigint" @@ -778,15 +764,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "ct-logs" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1a816186fa68d9e426e3cb4ae4dff1fcd8e4a2c34b781bf7a822574a0d0aac8" -dependencies = [ - "sct 0.6.1", -] - [[package]] name = "curve25519-dalek" version = "3.2.0" @@ -802,9 +779,9 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.1" +version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" dependencies = [ "cfg-if", "cpufeatures", @@ -825,7 +802,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.60", ] [[package]] @@ -858,16 +835,15 @@ dependencies = [ [[package]] name = "cw-multi-test" -version = "0.19.4" +version = "0.20.0-rc" dependencies = [ "anyhow", - "bech32", + "bech32 0.9.1", "cosmrs", "cosmwasm-schema", "cosmwasm-std", "cosmwasm-vm", - "cw-orch-daemon", - "cw-orch-networks", + "cw-orch", "cw-storage-plus 1.2.0", "cw-utils 1.0.3", "cw2 1.1.2", @@ -876,13 +852,12 @@ dependencies = [ "env_logger", "hex", "hex-literal", - "ibc-chain-registry", - "itertools 0.12.0", + "itertools", "log", "moneymarket", "num-bigint", "once_cell", - "prost 0.12.3", + "prost", "rustc-serialize", "schemars", "serde", @@ -890,39 +865,76 @@ dependencies = [ "sha2 0.10.8", "thiserror", "tokio", - "tonic 0.10.2", + "tonic", "treediff", "wasmer", ] +[[package]] +name = "cw-orch" +version = "0.22.0-rc1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dadb0d3efe8116adde3a00e005d6bb8e6d5e61269ee298f16575137920789b" +dependencies = [ + "anyhow", + "cosmrs", + "cosmwasm-std", + "cw-orch-contract-derive", + "cw-orch-core", + "cw-orch-daemon", + "cw-orch-fns-derive", + "cw-orch-mock", + "cw-orch-networks", + "cw-orch-traits", + "cw-utils 1.0.3", + "hex", + "log", + "schemars", + "serde", + "thiserror", + "tokio", +] + +[[package]] +name = "cw-orch-contract-derive" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94e9c3e46e2511c26d07da1fb5fcb47f83fa6d169dbb6eeff42c1b899b849726" +dependencies = [ + "convert_case", + "quote", + "syn 2.0.60", +] + [[package]] name = "cw-orch-core" -version = "0.19.0" +version = "1.0.0-rc" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90742906d091e509f185bb26c07706c037949ddaaa522bb3f3927b53835cc1fd" +checksum = "ec6d4ff5ea61a14a73b9c480d2600a0e8fbb847ea3e6696741d0a4289e2b81a0" dependencies = [ "abstract-cw-multi-test", "anyhow", + "cosmos-sdk-proto 0.21.1", "cosmwasm-std", "cw-utils 1.0.3", "dirs", "log", "serde", "serde_json", - "sha256", + "sha2 0.10.8", "thiserror", ] [[package]] name = "cw-orch-daemon" -version = "0.19.0" +version = "0.22.0-rc" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95104f4caf23482ac067d67a787dce34391c548fae496210c4b36bb14c9397d9" +checksum = "fbc35a85bf5e7808bd076dae3704ce70670fb1194576a7a71f1ac5c2018e51a6" dependencies = [ "anyhow", "async-recursion", "base16", - "base64 0.21.5", + "base64", "bitcoin", "chrono", "cosmrs", @@ -936,45 +948,69 @@ dependencies = [ "flate2", "hex", "hkd32", - "ibc-chain-registry", - "ibc-relayer-types", + "lazy_static", "log", - "prost 0.12.3", - "prost-types 0.11.9", + "prost", + "prost-types", "rand_core 0.6.4", "reqwest", - "ring 0.17.6", + "ring", "ripemd", "schemars", - "secp256k1", "serde", "serde_json", - "sha256", + "sha2 0.10.8", "thiserror", "tokio", - "tonic 0.10.2", + "tonic", +] + +[[package]] +name = "cw-orch-fns-derive" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6423cd853c9a4aa07cc0a92a179b99bd8f8f6c696a468e3ca2ecd2575905db21" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "cw-orch-mock" +version = "0.22.0-rc" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdbe04cc54fa4559a6efb4e2dd20a921e064da36e274b440150d4b7e6a56ed45" +dependencies = [ + "abstract-cw-multi-test", + "cosmwasm-std", + "cw-orch-core", + "cw-utils 1.0.3", + "log", + "serde", + "sha2 0.10.8", ] [[package]] name = "cw-orch-networks" -version = "0.19.0" +version = "0.22.0-rc" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a08ab813c374ef74560c661c1c444c3ea0425d14938671fa1c529d6efa348b7" +checksum = "12107c5bbe6f80f5b30d617b6e5c2ab9a0131bce4940d44b7ca93626b4e64bdc" dependencies = [ "cw-orch-core", - "ibc-chain-registry", "serde", ] [[package]] name = "cw-orch-traits" -version = "0.19.0" +version = "0.22.0-rc" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f786295d8d9754466f8bdb94a67d6c9c647937450bcb4bb12403174800ae1ae7" +checksum = "4509406490b3682b7af9d7f0afac0021ffb54fbb8a4c7294218740498681e962" dependencies = [ "cw-orch-core", - "prost 0.11.9", - "prost-types 0.11.9", + "prost", + "prost-types", ] [[package]] @@ -1104,9 +1140,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.3" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" dependencies = [ "darling_core", "darling_macro", @@ -1114,26 +1150,26 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.3" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.60", ] [[package]] name = "darling_macro" -version = "0.20.3" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core", "quote", - "syn 2.0.39", + "syn 2.0.60", ] [[package]] @@ -1151,9 +1187,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", "zeroize", @@ -1161,9 +1197,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", ] @@ -1179,17 +1215,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "derive_more" -version = "0.99.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "digest" version = "0.9.0" @@ -1234,9 +1259,9 @@ dependencies = [ [[package]] name = "dyn-clone" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" [[package]] name = "dynasm" @@ -1304,11 +1329,11 @@ dependencies = [ [[package]] name = "ed25519-dalek" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ - "curve25519-dalek 4.1.1", + "curve25519-dalek 4.1.2", "ed25519", "serde", "sha2 0.10.8", @@ -1333,9 +1358,9 @@ dependencies = [ [[package]] name = "either" -version = "1.9.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" [[package]] name = "elliptic-curve" @@ -1358,9 +1383,9 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if", ] @@ -1403,14 +1428,14 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.60", ] [[package]] name = "env_logger" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" dependencies = [ "humantime", "is-terminal", @@ -1425,15 +1450,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" -[[package]] -name = "erased-serde" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c138974f9d5e7fe373eb04df7cae98833802ae4b11c24ac7039a21d5af4b26c" -dependencies = [ - "serde", -] - [[package]] name = "errno" version = "0.3.8" @@ -1446,9 +1462,9 @@ dependencies = [ [[package]] name = "eyre" -version = "0.6.9" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80f656be11ddf91bd709454d15d5bd896fbaf4cc3314e69349e4d1569f5b46cd" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" dependencies = [ "indenter", "once_cell", @@ -1462,9 +1478,9 @@ checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" [[package]] name = "fastrand" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" [[package]] name = "ff" @@ -1478,18 +1494,9 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27573eac26f4dd11e2b1916c3fe1baa56407c83c71a773a8ba17ec0bca03b6b7" - -[[package]] -name = "fixed-hash" -version = "0.8.0" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" -dependencies = [ - "static_assertions", -] +checksum = "38793c55593b33412e3ae40c2c9781ffaa6f438f6f8c10f24e71846fbd7ae01e" [[package]] name = "flate2" @@ -1507,7 +1514,6 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c606d892c9de11507fa0dcffc116434f94e105d0bbdc4e405b61519464c49d7b" dependencies = [ - "anyhow", "eyre", "paste", ] @@ -1556,13 +1562,12 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", - "futures-executor", "futures-io", "futures-sink", "futures-task", @@ -1571,9 +1576,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -1581,66 +1586,39 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" - -[[package]] -name = "futures-executor" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-io" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" - -[[package]] -name = "futures-macro" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", -] +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ - "futures-channel", "futures-core", - "futures-io", - "futures-macro", "futures-sink", "futures-task", - "memchr", "pin-project-lite", "pin-utils", - "slab", ] [[package]] @@ -1665,9 +1643,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" dependencies = [ "cfg-if", "js-sys", @@ -1706,9 +1684,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.22" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", @@ -1716,7 +1694,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.1.0", + "indexmap 2.2.6", "slab", "tokio", "tokio-util", @@ -1738,30 +1716,6 @@ version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" -[[package]] -name = "headers" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" -dependencies = [ - "base64 0.21.5", - "bytes", - "headers-core", - "http", - "httpdate", - "mime", - "sha1", -] - -[[package]] -name = "headers-core" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" -dependencies = [ - "http", -] - [[package]] name = "heck" version = "0.4.1" @@ -1770,9 +1724,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -1818,9 +1772,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -1829,9 +1783,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", @@ -1858,9 +1812,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", @@ -1873,50 +1827,13 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.10", + "socket2", "tokio", "tower-service", "tracing", "want", ] -[[package]] -name = "hyper-proxy" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca815a891b24fdfb243fa3239c86154392b0953ee584aa1a2a1f66d20cbe75cc" -dependencies = [ - "bytes", - "futures", - "headers", - "http", - "hyper", - "hyper-rustls 0.22.1", - "rustls-native-certs 0.5.0", - "tokio", - "tokio-rustls 0.22.0", - "tower-service", - "webpki 0.21.4", -] - -[[package]] -name = "hyper-rustls" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f9f7a97316d44c0af9b0301e65010573a853a9fc97046d7331d7f6bc0fd5a64" -dependencies = [ - "ct-logs", - "futures-util", - "hyper", - "log", - "rustls 0.19.1", - "rustls-native-certs 0.5.0", - "tokio", - "tokio-rustls 0.22.0", - "webpki 0.21.4", - "webpki-roots 0.21.1", -] - [[package]] name = "hyper-rustls" version = "0.24.2" @@ -1926,9 +1843,9 @@ dependencies = [ "futures-util", "http", "hyper", - "rustls 0.21.9", + "rustls", "tokio", - "tokio-rustls 0.24.1", + "tokio-rustls", ] [[package]] @@ -1958,9 +1875,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1980,117 +1897,24 @@ dependencies = [ ] [[package]] -name = "ibc-chain-registry" -version = "0.25.0" +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e550fe9592ad7096831442b38c45837c6385f683a55cf5eb32460e468ecddb4" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ - "async-trait", - "flex-error", - "futures", - "http", - "ibc-proto", - "ibc-relayer-types", - "itertools 0.10.5", - "reqwest", - "serde", - "serde_json", - "tendermint-rpc 0.32.2", - "tokio", - "tracing", + "unicode-bidi", + "unicode-normalization", ] [[package]] -name = "ibc-proto" -version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11c352715b36685c2543556a77091fb16af5d26257d5ce9c28e6756c1ccd71aa" -dependencies = [ - "base64 0.21.5", - "bytes", - "flex-error", - "ics23", - "prost 0.11.9", - "serde", - "subtle-encoding", - "tendermint-proto 0.32.2", - "tonic 0.9.2", -] - -[[package]] -name = "ibc-relayer-types" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fa9269c050d20b36a9e61955a5526345df1508f396f7f3a9acb4c03cdb572f3" -dependencies = [ - "bytes", - "derive_more", - "dyn-clone", - "erased-serde", - "flex-error", - "ibc-proto", - "ics23", - "itertools 0.10.5", - "num-rational", - "primitive-types", - "prost 0.11.9", - "regex", - "serde", - "serde_derive", - "serde_json", - "subtle-encoding", - "tendermint 0.32.2", - "tendermint-light-client-verifier", - "tendermint-proto 0.32.2", - "time", - "uint", -] - -[[package]] -name = "ics23" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "442d4bab37956e76f739c864f246c825d87c0bb7f9afa65660c57833c91bf6d4" -dependencies = [ - "anyhow", - "bytes", - "hex", - "informalsystems-pbjson", - "prost 0.11.9", - "ripemd", - "serde", - "sha2 0.10.8", - "sha3", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "impl-serde" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" -dependencies = [ - "serde", -] - -[[package]] -name = "indenter" -version = "0.3.3" +name = "indenter" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" @@ -2106,24 +1930,14 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown 0.14.3", ] -[[package]] -name = "informalsystems-pbjson" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4eecd90f87bea412eac91c6ef94f6b1e390128290898cbe14f2b926787ae1fb" -dependencies = [ - "base64 0.13.1", - "serde", -] - [[package]] name = "ipnet" version = "2.9.0" @@ -2132,62 +1946,44 @@ checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "is-terminal" -version = "0.4.9" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" dependencies = [ "hermit-abi", - "rustix", - "windows-sys 0.48.0", -] - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", + "libc", + "windows-sys 0.52.0", ] [[package]] name = "itertools" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] [[package]] name = "k256" -version = "0.13.2" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f01b677d82ef7a676aa37e099defd83a28e15687112cafdd112d60236b6115b" +checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" dependencies = [ "cfg-if", "ecdsa", @@ -2197,15 +1993,6 @@ dependencies = [ "signature", ] -[[package]] -name = "keccak" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" -dependencies = [ - "cpufeatures", -] - [[package]] name = "lazy_static" version = "1.4.0" @@ -2220,26 +2007,25 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libredox" -version = "0.0.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.5.0", "libc", - "redox_syscall", ] [[package]] name = "linux-raw-sys" -version = "0.4.11" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" @@ -2253,9 +2039,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "mach" @@ -2266,6 +2052,15 @@ 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 = "matchit" version = "0.7.3" @@ -2274,9 +2069,9 @@ checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "memmap2" @@ -2305,15 +2100,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] - [[package]] name = "mime" version = "0.3.17" @@ -2322,18 +2108,18 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.9" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi", @@ -2343,7 +2129,7 @@ dependencies = [ [[package]] name = "moneymarket" version = "0.3.1" -source = "git+https://github.com/CavernPerson/money-market-contracts#ea773bb78536799acde0e94c1fe996012ed3f831" +source = "git+https://github.com/CavernPerson/money-market-contracts#6a3b3f586cd085d434485bb13e2d12f95e8beef2" dependencies = [ "cosmwasm-schema", "cosmwasm-std", @@ -2390,6 +2176,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-derive" version = "0.3.3" @@ -2402,32 +2194,30 @@ dependencies = [ ] [[package]] -name = "num-integer" -version = "0.1.45" +name = "num-derive" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ - "autocfg", - "num-traits", + "proc-macro2", + "quote", + "syn 2.0.60", ] [[package]] -name = "num-rational" -version = "0.4.1" +name = "num-integer" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", - "num-bigint", - "num-integer", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", ] @@ -2444,32 +2234,32 @@ dependencies = [ [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.60" +version = "0.10.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79a4c6c3a2b158f7f8f2a2fc5a969fa3a068df6fc9dbb4a43845436e3af7c800" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.5.0", "cfg-if", "foreign-types", "libc", @@ -2486,7 +2276,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.60", ] [[package]] @@ -2497,9 +2287,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.96" +version = "0.9.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3812c071ba60da8b5677cc12bcb1d42989a65553772897a7e0355545a819838f" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" dependencies = [ "cc", "libc", @@ -2553,9 +2343,9 @@ dependencies = [ [[package]] name = "peg" -version = "0.7.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07c0b841ea54f523f7aa556956fbd293bcbe06f2e67d2eb732b7278aaf1d166a" +checksum = "400bcab7d219c38abf8bd7cc2054eb9bbbd4312d66f6a5557d572a203f646f61" dependencies = [ "peg-macros", "peg-runtime", @@ -2563,9 +2353,9 @@ dependencies = [ [[package]] name = "peg-macros" -version = "0.7.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aa52829b8decbef693af90202711348ab001456803ba2a98eb4ec8fb70844c" +checksum = "46e61cce859b76d19090f62da50a9fe92bab7c2a5f09e183763559a2ac392c90" dependencies = [ "peg-runtime", "proc-macro2", @@ -2574,9 +2364,9 @@ dependencies = [ [[package]] name = "peg-runtime" -version = "0.7.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c719dcf55f09a3a7e764c6649ab594c18a177e3599c467983cdf644bfc0a4088" +checksum = "36bae92c60fa2398ce4678b98b2c4b5a7c61099961ca1fa305aec04a9ad28922" [[package]] name = "percent-encoding" @@ -2586,29 +2376,29 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.60", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -2628,15 +2418,15 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "platforms" -version = "3.2.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14e6ab3f592e6fb464fc9712d8d6e6912de6473954635fd76a589d832cffcbb0" +checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7" [[package]] name = "powerfmt" @@ -2650,17 +2440,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" -[[package]] -name = "primitive-types" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" -dependencies = [ - "fixed-hash", - "impl-serde", - "uint", -] - [[package]] name = "proc-macro-error" version = "1.0.4" @@ -2687,75 +2466,43 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.70" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" dependencies = [ "unicode-ident", ] [[package]] name = "prost" -version = "0.11.9" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +checksum = "d0f5d036824e4761737860779c906171497f6d55681139d8312388f8fe398922" dependencies = [ "bytes", - "prost-derive 0.11.9", -] - -[[package]] -name = "prost" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" -dependencies = [ - "bytes", - "prost-derive 0.12.3", -] - -[[package]] -name = "prost-derive" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" -dependencies = [ - "anyhow", - "itertools 0.10.5", - "proc-macro2", - "quote", - "syn 1.0.109", + "prost-derive", ] [[package]] name = "prost-derive" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" +checksum = "19de2de2a00075bf566bee3bd4db014b11587e84184d3f7a791bc17f1a8e9e48" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.60", ] [[package]] name = "prost-types" -version = "0.11.9" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" +checksum = "3235c33eb02c1f1e212abdbe34c78b264b038fb58ca612664343271e36e55ffe" dependencies = [ - "prost 0.11.9", -] - -[[package]] -name = "prost-types" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" -dependencies = [ - "prost 0.12.3", + "prost", ] [[package]] @@ -2780,9 +2527,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -2831,9 +2578,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -2841,9 +2588,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -2860,9 +2607,9 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" dependencies = [ "getrandom", "libredox", @@ -2883,9 +2630,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", @@ -2895,9 +2642,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", @@ -2906,38 +2653,38 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "region" -version = "3.0.0" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76e189c2369884dce920945e2ddf79b3dff49e071a167dd1817fa9c4c00d512e" +checksum = "e6b6ebd13bc009aef9cd476c1310d49ac354d36e240cf1bd753290f3dc7199a7" dependencies = [ "bitflags 1.3.2", "libc", - "mach", - "winapi", + "mach2", + "windows-sys 0.52.0", ] [[package]] name = "rend" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2571463863a6bd50c32f94402933f03457a3fbaf697a707c5be741e459f08fd" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" dependencies = [ "bytecheck", ] [[package]] name = "reqwest" -version = "0.11.22" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ - "base64 0.21.5", + "base64", "bytes", "encoding_rs", "futures-core", @@ -2946,7 +2693,7 @@ dependencies = [ "http", "http-body", "hyper", - "hyper-rustls 0.24.2", + "hyper-rustls", "hyper-tls", "ipnet", "js-sys", @@ -2956,22 +2703,22 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.21.9", - "rustls-native-certs 0.6.3", + "rustls", + "rustls-native-certs", "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", + "sync_wrapper", "system-configuration", "tokio", "tokio-native-tls", - "tokio-rustls 0.24.1", + "tokio-rustls", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 0.25.3", "winreg", ] @@ -2987,31 +2734,17 @@ dependencies = [ [[package]] name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin 0.5.2", - "untrusted 0.7.1", - "web-sys", - "winapi", -] - -[[package]] -name = "ring" -version = "0.17.6" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "684d5e6e18f669ccebf64a92236bb7db9a34f07be010e3627368182027180866" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", "getrandom", "libc", - "spin 0.9.8", - "untrusted 0.9.0", - "windows-sys 0.48.0", + "spin", + "untrusted", + "windows-sys 0.52.0", ] [[package]] @@ -3025,12 +2758,13 @@ dependencies = [ [[package]] name = "rkyv" -version = "0.7.42" +version = "0.7.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0200c8230b013893c0b2d6213d6ec64ed2b9be2e0e016682b7224ff82cff5c58" +checksum = "5cba464629b3394fc4dbc6f940ff8f5b4ff5c7aef40f29166fd4ad12acbc99c0" dependencies = [ "bitvec", "bytecheck", + "bytes", "hashbrown 0.12.3", "indexmap 1.9.3", "ptr_meta", @@ -3038,14 +2772,14 @@ dependencies = [ "rkyv_derive", "seahash", "tinyvec", - "uuid 1.6.1", + "uuid", ] [[package]] name = "rkyv_derive" -version = "0.7.42" +version = "0.7.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2e06b915b5c230a17d7a736d1e2e63ee753c256a8614ef3f5147b13a4f5541d" +checksum = "a7dddfff8de25e6f62b9d64e6e432bf1c6736c57d20323e15ee10435fbda7c65" dependencies = [ "proc-macro2", "quote", @@ -3060,9 +2794,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustc-serialize" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" +checksum = "fe834bc780604f4674073badbad26d7219cadfb4a2275802db12cbae17498401" [[package]] name = "rustc_version" @@ -3075,64 +2809,27 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.25" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.48.0", -] - -[[package]] -name = "rustls" -version = "0.19.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" -dependencies = [ - "base64 0.13.1", - "log", - "ring 0.16.20", - "sct 0.6.1", - "webpki 0.21.4", -] - -[[package]] -name = "rustls" -version = "0.20.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" -dependencies = [ - "log", - "ring 0.16.20", - "sct 0.7.1", - "webpki 0.22.4", + "windows-sys 0.52.0", ] [[package]] name = "rustls" -version = "0.21.9" +version = "0.21.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "629648aced5775d558af50b2b4c7b02983a04b312126d45eeead26e7caa498b9" +checksum = "7fecbfb7b1444f477b345853b1fce097a2c6fb637b2bfb87e6bc5db0f043fae4" dependencies = [ "log", - "ring 0.17.6", + "ring", "rustls-webpki", - "sct 0.7.1", -] - -[[package]] -name = "rustls-native-certs" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a07b7c1885bd8ed3831c289b7870b13ef46fe0e856d288c30d9cc17d75a2092" -dependencies = [ - "openssl-probe", - "rustls 0.19.1", - "schannel", - "security-framework", + "sct", ] [[package]] @@ -3153,7 +2850,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.5", + "base64", ] [[package]] @@ -3162,21 +2859,21 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.6", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "same-file" @@ -3189,11 +2886,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -3226,24 +2923,14 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sct" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" -dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", -] - [[package]] name = "sct" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.6", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] @@ -3287,9 +2974,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.2" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -3300,9 +2987,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" dependencies = [ "core-foundation-sys", "libc", @@ -3310,30 +2997,30 @@ dependencies = [ [[package]] name = "self_cell" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e388332cd64eb80cd595a00941baf513caffae8dce9cfd0467fc9c66397dade6" +checksum = "58bf37232d3bb9a2c4e641ca2a11d83b5062066f88df7fed36c28772046d65ba" [[package]] name = "semver" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" dependencies = [ "serde_derive", ] [[package]] name = "serde-json-wasm" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16a62a1fad1e1828b24acac8f2b468971dade7b8c3c2e672bcadefefb1f8c137" +checksum = "9e9213a07d53faa0b8dd81e767a54a8188a242fdb9be99ab75ec576a774bfdd7" dependencies = [ "serde", ] @@ -3351,22 +3038,22 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.12" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab33ec92f677585af6d88c65593ae2375adde54efdbf16d597f2cbc7a6d368ff" +checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.60", ] [[package]] @@ -3382,9 +3069,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" dependencies = [ "itoa", "ryu", @@ -3393,13 +3080,13 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.17" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.60", ] [[package]] @@ -3414,17 +3101,6 @@ dependencies = [ "serde", ] -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - [[package]] name = "sha2" version = "0.9.9" @@ -3449,34 +3125,11 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "sha256" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7895c8ae88588ccead14ff438b939b0c569cd619116f14b4d13fdff7b8333386" -dependencies = [ - "async-trait", - "bytes", - "hex", - "sha2 0.10.8", - "tokio", -] - -[[package]] -name = "sha3" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" -dependencies = [ - "digest 0.10.7", - "keccak", -] - [[package]] name = "shared-buffer" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cf61602ee61e2f83dd016b3e6387245291cf728ea071c378b35088125b4d995" +checksum = "f6c99835bad52957e7aa241d3975ed17c1e5f8c92026377d117a606f36b84b16" dependencies = [ "bytes", "memmap2 0.6.2", @@ -3484,9 +3137,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -3524,36 +3177,20 @@ checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.4.10" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" dependencies = [ "libc", - "winapi", -] - -[[package]] -name = "socket2" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" -dependencies = [ - "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spin" version = "0.9.8" @@ -3635,9 +3272,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.39" +version = "2.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" dependencies = [ "proc-macro2", "quote", @@ -3679,57 +3316,27 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "target-lexicon" -version = "0.12.12" +version = "0.12.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" +checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" [[package]] name = "tempfile" -version = "3.8.1" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", - "redox_syscall", "rustix", - "windows-sys 0.48.0", -] - -[[package]] -name = "tendermint" -version = "0.32.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f0a7d05cf78524782337f8edd55cbc578d159a16ad4affe2135c92f7dbac7f0" -dependencies = [ - "bytes", - "digest 0.10.7", - "ed25519", - "ed25519-consensus", - "flex-error", - "futures", - "num-traits", - "once_cell", - "prost 0.11.9", - "prost-types 0.11.9", - "serde", - "serde_bytes", - "serde_json", - "serde_repr", - "sha2 0.10.8", - "signature", - "subtle", - "subtle-encoding", - "tendermint-proto 0.32.2", - "time", - "zeroize", + "windows-sys 0.52.0", ] [[package]] name = "tendermint" -version = "0.34.0" +version = "0.34.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc2294fa667c8b548ee27a9ba59115472d0a09c2ba255771092a7f1dcf03a789" +checksum = "15ab8f0a25d0d2ad49ac615da054d6a76aa6603ff95f7d18bafdd34450a1a04b" dependencies = [ "bytes", "digest 0.10.7", @@ -3740,8 +3347,8 @@ dependencies = [ "k256", "num-traits", "once_cell", - "prost 0.12.3", - "prost-types 0.12.3", + "prost", + "prost-types", "ripemd", "serde", "serde_bytes", @@ -3751,64 +3358,37 @@ dependencies = [ "signature", "subtle", "subtle-encoding", - "tendermint-proto 0.34.0", + "tendermint-proto 0.34.1", "time", "zeroize", ] [[package]] name = "tendermint-config" -version = "0.32.2" +version = "0.34.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71a72dbbea6dde12045d261f2c70c0de039125675e8a026c8d5ad34522756372" +checksum = "e1a02da769166e2052cd537b1a97c78017632c2d9e19266367b27e73910434fc" dependencies = [ "flex-error", "serde", "serde_json", - "tendermint 0.32.2", + "tendermint", "toml", "url", ] -[[package]] -name = "tendermint-config" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a25dbe8b953e80f3d61789fbdb83bf9ad6c0ef16df5ca6546f49912542cc137" -dependencies = [ - "flex-error", - "serde", - "serde_json", - "tendermint 0.34.0", - "toml", - "url", -] - -[[package]] -name = "tendermint-light-client-verifier" -version = "0.32.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9875dce5c1b08201152eb0860f8fb1dce96c53e37532c310ffc4956d20f90def" -dependencies = [ - "derive_more", - "flex-error", - "serde", - "tendermint 0.32.2", - "time", -] - [[package]] name = "tendermint-proto" -version = "0.32.2" +version = "0.34.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0cec054567d16d85e8c3f6a3139963d1a66d9d3051ed545d31562550e9bcc3d" +checksum = "b797dd3d2beaaee91d2f065e7bdf239dc8d80bba4a183a288bc1279dd5a69a1e" dependencies = [ "bytes", "flex-error", - "num-derive", + "num-derive 0.3.3", "num-traits", - "prost 0.11.9", - "prost-types 0.11.9", + "prost", + "prost-types", "serde", "serde_bytes", "subtle-encoding", @@ -3817,63 +3397,27 @@ dependencies = [ [[package]] name = "tendermint-proto" -version = "0.34.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cc728a4f9e891d71adf66af6ecaece146f9c7a11312288a3107b3e1d6979aaf" +checksum = "ff525d5540a9fc535c38dc0d92a98da3ee36fcdfbda99cecb9f3cce5cd4d41d7" dependencies = [ "bytes", "flex-error", - "num-derive", + "num-derive 0.4.2", "num-traits", - "prost 0.12.3", - "prost-types 0.12.3", - "serde", - "serde_bytes", - "subtle-encoding", - "time", -] - -[[package]] -name = "tendermint-rpc" -version = "0.32.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d119d83a130537fc4a98c3c9eb6899ebe857fea4860400a61675bfb5f0b35129" -dependencies = [ - "async-trait", - "async-tungstenite", - "bytes", - "flex-error", - "futures", - "getrandom", - "http", - "hyper", - "hyper-proxy", - "hyper-rustls 0.22.1", - "peg", - "pin-project", - "semver", + "prost", + "prost-types", "serde", "serde_bytes", - "serde_json", - "subtle", "subtle-encoding", - "tendermint 0.32.2", - "tendermint-config 0.32.2", - "tendermint-proto 0.32.2", - "thiserror", "time", - "tokio", - "tracing", - "url", - "uuid 0.8.2", - "walkdir", ] [[package]] name = "tendermint-rpc" -version = "0.34.0" +version = "0.34.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbf0a4753b46a190f367337e0163d0b552a2674a6bac54e74f9f2cdcde2969b" +checksum = "71afae8bb5f6b14ed48d4e1316a643b6c2c3cbad114f510be77b4ed20b7b3e42" dependencies = [ "async-trait", "bytes", @@ -3882,6 +3426,7 @@ dependencies = [ "getrandom", "peg", "pin-project", + "rand", "reqwest", "semver", "serde", @@ -3889,54 +3434,55 @@ dependencies = [ "serde_json", "subtle", "subtle-encoding", - "tendermint 0.34.0", - "tendermint-config 0.34.0", - "tendermint-proto 0.34.0", + "tendermint", + "tendermint-config", + "tendermint-proto 0.34.1", "thiserror", "time", "tokio", "tracing", "url", - "uuid 0.8.2", + "uuid", "walkdir", ] [[package]] name = "termcolor" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.60", ] [[package]] name = "time" -version = "0.3.30" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", + "num-conv", "powerfmt", "serde", "time-core", @@ -3951,10 +3497,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ + "num-conv", "time-core", ] @@ -3975,9 +3522,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.34.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", @@ -3987,7 +3534,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.5", + "socket2", "tokio-macros", "windows-sys 0.48.0", ] @@ -4010,7 +3557,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.60", ] [[package]] @@ -4023,43 +3570,21 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-rustls" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" -dependencies = [ - "rustls 0.19.1", - "tokio", - "webpki 0.21.4", -] - -[[package]] -name = "tokio-rustls" -version = "0.23.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" -dependencies = [ - "rustls 0.20.9", - "tokio", - "webpki 0.22.4", -] - [[package]] name = "tokio-rustls" version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.21.9", + "rustls", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ "futures-core", "pin-project-lite", @@ -4089,34 +3614,6 @@ dependencies = [ "serde", ] -[[package]] -name = "tonic" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3082666a3a6433f7f511c7192923fa1fe07c69332d3c6a2e6bb040b569199d5a" -dependencies = [ - "async-trait", - "axum", - "base64 0.21.5", - "bytes", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-timeout", - "percent-encoding", - "pin-project", - "prost 0.11.9", - "tokio", - "tokio-stream", - "tower", - "tower-layer", - "tower-service", - "tracing", -] - [[package]] name = "tonic" version = "0.10.2" @@ -4126,7 +3623,7 @@ dependencies = [ "async-stream", "async-trait", "axum", - "base64 0.21.5", + "base64", "bytes", "h2", "http", @@ -4135,12 +3632,12 @@ dependencies = [ "hyper-timeout", "percent-encoding", "pin-project", - "prost 0.12.3", - "rustls 0.21.9", - "rustls-native-certs 0.6.3", + "prost", + "rustls", + "rustls-native-certs", "rustls-pemfile", "tokio", - "tokio-rustls 0.24.1", + "tokio-rustls", "tokio-stream", "tower", "tower-layer", @@ -4199,7 +3696,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.60", ] [[package]] @@ -4213,39 +3710,18 @@ dependencies = [ [[package]] name = "treediff" -version = "4.0.2" +version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52984d277bdf2a751072b5df30ec0377febdb02f7696d64c2d7d54630bac4303" +checksum = "4d127780145176e2b5d16611cc25a900150e86e9fd79d3bde6ff3a37359c9cb5" dependencies = [ "rustc-serialize", ] [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" - -[[package]] -name = "tungstenite" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788" -dependencies = [ - "base64 0.13.1", - "byteorder", - "bytes", - "http", - "httparse", - "log", - "rand", - "rustls 0.20.9", - "sha1", - "thiserror", - "url", - "utf-8", - "webpki 0.22.4", -] +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typenum" @@ -4253,23 +3729,11 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" -[[package]] -name = "uint" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" -dependencies = [ - "byteorder", - "crunchy", - "hex", - "static_assertions", -] - [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -4279,18 +3743,18 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] [[package]] -name = "untrusted" -version = "0.7.1" +name = "unicode-segmentation" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "untrusted" @@ -4309,23 +3773,11 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - -[[package]] -name = "uuid" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" - [[package]] name = "uuid" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" [[package]] name = "vcpkg" @@ -4341,9 +3793,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -4366,9 +3818,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -4376,16 +3828,16 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.60", "wasm-bindgen-shared", ] @@ -4414,9 +3866,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.39" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if", "js-sys", @@ -4426,9 +3878,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4436,22 +3888,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.60", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "wasmer" @@ -4605,7 +4057,7 @@ dependencies = [ "lazy_static", "libc", "mach", - "memoffset 0.8.0", + "memoffset", "more-asserts", "region", "scopeguard", @@ -4626,49 +4078,14 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", ] -[[package]] -name = "webpki" -version = "0.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" -dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", -] - -[[package]] -name = "webpki" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" -dependencies = [ - "ring 0.17.6", - "untrusted 0.9.0", -] - -[[package]] -name = "webpki-roots" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940" -dependencies = [ - "webpki 0.21.4", -] - -[[package]] -name = "webpki-roots" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" - [[package]] name = "winapi" version = "0.3.9" @@ -4687,11 +4104,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -4702,11 +4119,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.48.5", + "windows-targets 0.52.5", ] [[package]] @@ -4737,7 +4154,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.5", ] [[package]] @@ -4757,17 +4174,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.5", + "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 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -4778,9 +4196,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" @@ -4796,9 +4214,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" @@ -4814,9 +4232,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +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" @@ -4832,9 +4256,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" @@ -4850,9 +4274,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" @@ -4862,9 +4286,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" @@ -4880,9 +4304,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winreg" @@ -4905,9 +4329,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "63381fa6624bf92130a6b87c0d07380116f80b565c42cf0d754136f0238359ef" dependencies = [ "zeroize_derive", ] @@ -4920,5 +4344,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.60", ] diff --git a/Cargo.toml b/Cargo.toml index 434e4116..5e0b2a68 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cw-multi-test" -version = "0.19.4" +version = "0.20.0-rc" authors = ["Ethan Frey "] edition = "2021" description = "Testing tools for multi-contract interactions" @@ -36,10 +36,8 @@ thiserror = "1.0.50" # Clone testing deps ## Network -cw-orch-daemon = { version = "0.19.0" } -cw-orch-networks = { version = "0.19.0" } +cw-orch = { version = "0.22.0-rc", features = ["daemon"] } tokio = "1.28.2" -ibc-chain-registry = "0.25.0" tonic = "0.10.2" ## Emulation diff --git a/examples/cavern_test_app.rs b/examples/cavern_test_app.rs index ef083f2e..9c35b7e7 100644 --- a/examples/cavern_test_app.rs +++ b/examples/cavern_test_app.rs @@ -14,14 +14,13 @@ use cw_multi_test::wasm_emulation::contract::WasmContract; use cw_multi_test::wasm_emulation::storage::analyzer::StorageAnalyzer; use cw_multi_test::BankKeeper; use cw_multi_test::Executor; -use cw_orch_daemon::queriers::DaemonQuerier; -use cw_orch_daemon::queriers::Node; +use cw_orch::daemon::networks::PHOENIX_1; +use cw_orch::daemon::queriers::Node; use std::path::Path; use tokio::runtime::Runtime; use cw20::Cw20QueryMsg; use cw_multi_test::AppBuilder; -use cw_orch_networks::networks::PHOENIX_1; use cosmwasm_std::Empty; use cw_multi_test::WasmKeeper; @@ -76,7 +75,13 @@ pub fn test() -> anyhow::Result<()> { let bank = BankKeeper::new().with_remote(remote_channel.clone()); - let block = runtime.block_on(Node::new(remote_channel.channel.clone()).block_info())?; + let block = runtime.block_on( + Node { + channel: remote_channel.channel.clone(), + rt_handle: Some(runtime.handle().clone()), + } + ._block_info(), + )?; // First we instantiate a new app let app = AppBuilder::default() .with_wasm(wasm) diff --git a/examples/counter/error.rs b/examples/counter/error.rs index 7b724723..16b589d3 100644 --- a/examples/counter/error.rs +++ b/examples/counter/error.rs @@ -8,9 +8,6 @@ pub enum ContractError { #[error("Unauthorized")] Unauthorized {}, - - #[error("Custom Error val: {val:?}")] - CustomError { val: String }, // Add any other custom errors you like here. // Look at https://docs.rs/thiserror/1.0.21/thiserror/ for details. } diff --git a/examples/counter/mod.rs b/examples/counter/mod.rs index 2dcd29ac..2ab5d224 100644 --- a/examples/counter/mod.rs +++ b/examples/counter/mod.rs @@ -4,5 +4,3 @@ pub(crate) mod execute; pub mod msg; pub(crate) mod query; pub mod state; - -pub use crate::counter::error::ContractError; diff --git a/examples/cousin_test.rs b/examples/cousin_test.rs index 3dc12490..ca04c24e 100644 --- a/examples/cousin_test.rs +++ b/examples/cousin_test.rs @@ -11,7 +11,7 @@ use cw_multi_test::{ wasm_emulation::{channel::RemoteChannel, contract::WasmContract}, App, AppBuilder, BankKeeper, ContractWrapper, Executor, WasmKeeper, }; -use cw_orch_networks::networks::PHOENIX_1; +use cw_orch::daemon::networks::PHOENIX_1; use tokio::runtime::Runtime; mod counter; diff --git a/examples/test_app.rs b/examples/test_app.rs index 27c323b1..2dc138c4 100644 --- a/examples/test_app.rs +++ b/examples/test_app.rs @@ -7,7 +7,7 @@ use cw20::Cw20QueryMsg; use cw_multi_test::wasm_emulation::channel::RemoteChannel; use cw_multi_test::AppBuilder; use cw_multi_test::BankKeeper; -use cw_orch_daemon::networks::PHOENIX_1; +use cw_orch::daemon::networks::PHOENIX_1; use cw_multi_test::WasmKeeper; diff --git a/src/app.rs b/src/app.rs index 7ffababa..c30f6d22 100644 --- a/src/app.rs +++ b/src/app.rs @@ -327,8 +327,8 @@ where let mut addresses = ADDRESSES.may_load(storage).unwrap().unwrap_or_default(); - let new_address = - RealApi::new(&remote.chain.bech32_prefix.clone()).next_address(addresses.len()); + let new_address = RealApi::new(&&remote.chain.network_info.pub_address_prefix.clone()) + .next_address(addresses.len()); addresses.push(new_address.clone()); ADDRESSES.save(storage, &addresses).unwrap(); diff --git a/src/contracts.rs b/src/contracts.rs index 16857f4b..5d90c9c6 100644 --- a/src/contracts.rs +++ b/src/contracts.rs @@ -401,15 +401,20 @@ pub mod test { use super::ContractWrapper; - fn execute(deps: DepsMut, env: Env, info: MessageInfo, _msg: Empty) -> StdResult { + fn execute(_deps: DepsMut, _env: Env, _info: MessageInfo, _msg: Empty) -> StdResult { Ok(Response::new()) } - fn query(deps: Deps, env: Env, _msg: Empty) -> StdResult { + fn query(_deps: Deps, _env: Env, _msg: Empty) -> StdResult { to_json_binary("resp") } - fn instantiate(deps: DepsMut, env: Env, info: MessageInfo, _msg: Empty) -> StdResult { + fn instantiate( + _deps: DepsMut, + _env: Env, + _info: MessageInfo, + _msg: Empty, + ) -> StdResult { Ok(Response::new()) } diff --git a/src/queries/bank.rs b/src/queries/bank.rs index 84eead60..8339c44f 100644 --- a/src/queries/bank.rs +++ b/src/queries/bank.rs @@ -2,7 +2,6 @@ use std::str::FromStr; use anyhow::Result as AnyResult; use cosmwasm_std::{Addr, Coin, Uint128}; -use cw_orch_daemon::queriers::DaemonQuerier; use crate::wasm_emulation::channel::RemoteChannel; @@ -10,11 +9,13 @@ pub struct BankRemoteQuerier; impl BankRemoteQuerier { pub fn get_balance(remote: RemoteChannel, account: &Addr) -> AnyResult> { - let channel = remote.channel; - let querier = cw_orch_daemon::queriers::Bank::new(channel); + let querier = cw_orch::daemon::queriers::Bank { + channel: remote.channel, + rt_handle: Some(remote.rt.clone()), + }; let distant_amounts: Vec = remote .rt - .block_on(querier.balance(account, None)) + .block_on(querier._balance(account, None)) .map(|result| { result .into_iter() diff --git a/src/queries/wasm.rs b/src/queries/wasm.rs index 02b272f6..e5cf57f0 100644 --- a/src/queries/wasm.rs +++ b/src/queries/wasm.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use anyhow::Result as AnyResult; use cosmwasm_std::{Addr, Binary, CodeInfoResponse, CustomQuery, Order, Storage}; -use cw_orch_daemon::queriers::{CosmWasm, DaemonQuerier}; +use cw_orch::daemon::queriers::CosmWasm; use crate::{ prefixed_storage::prefixed_read, @@ -15,9 +15,12 @@ pub struct WasmRemoteQuerier; impl WasmRemoteQuerier { pub fn code_info(remote: RemoteChannel, code_id: u64) -> AnyResult { - let wasm_querier = CosmWasm::new(remote.channel); + let wasm_querier = CosmWasm { + channel: remote.channel, + rt_handle: Some(remote.rt.clone()), + }; - let code_info = remote.rt.block_on(wasm_querier.code(code_id))?; + let code_info = remote.rt.block_on(wasm_querier._code(code_id))?; let mut res = cosmwasm_std::CodeInfoResponse::default(); res.code_id = code_id; res.creator = code_info.creator.to_string(); @@ -26,11 +29,14 @@ impl WasmRemoteQuerier { } pub fn load_distant_contract(remote: RemoteChannel, address: &Addr) -> AnyResult { - let wasm_querier = CosmWasm::new(remote.channel); + let wasm_querier = CosmWasm { + channel: remote.channel, + rt_handle: Some(remote.rt.clone()), + }; let code_info = remote .rt - .block_on(wasm_querier.contract_info(address.clone()))?; + .block_on(wasm_querier._contract_info(address.clone()))?; Ok(ContractData { admin: { @@ -51,10 +57,13 @@ impl WasmRemoteQuerier { contract_addr: String, key: Binary, ) -> AnyResult> { - let wasm_querier = CosmWasm::new(remote.channel); + let wasm_querier = CosmWasm { + channel: remote.channel, + rt_handle: Some(remote.rt.clone()), + }; let query_result = remote .rt - .block_on(wasm_querier.contract_raw_state(contract_addr, key.to_vec())) + .block_on(wasm_querier._contract_raw_state(contract_addr, key.to_vec())) .map(|query_result| query_result.data); Ok(query_result?) } diff --git a/src/wasm_emulation/channel.rs b/src/wasm_emulation/channel.rs index c23504cc..f952a941 100644 --- a/src/wasm_emulation/channel.rs +++ b/src/wasm_emulation/channel.rs @@ -1,12 +1,12 @@ use anyhow::Result as AnyResult; -use cw_orch_daemon::GrpcChannel; -use ibc_chain_registry::chain::ChainData; +use cw_orch::daemon::GrpcChannel; +use cw_orch::prelude::ChainInfoOwned; use tokio::runtime::{Handle, Runtime}; use tonic::transport::Channel; -fn get_channel(chain: impl Into, rt: Handle) -> AnyResult { +fn get_channel(chain: impl Into, rt: Handle) -> AnyResult { let chain = chain.into(); - let channel = rt.block_on(GrpcChannel::connect(&chain.apis.grpc, &chain.chain_id))?; + let channel = rt.block_on(GrpcChannel::connect(&chain.grpc_urls, &chain.chain_id))?; Ok(channel) } @@ -14,11 +14,11 @@ fn get_channel(chain: impl Into, rt: Handle) -> AnyResult { pub struct RemoteChannel { pub rt: Handle, pub channel: Channel, - pub chain: ChainData, + pub chain: ChainInfoOwned, } impl RemoteChannel { - pub fn new(rt: &Runtime, chain: impl Into) -> AnyResult { + pub fn new(rt: &Runtime, chain: impl Into) -> AnyResult { let chain = chain.into(); let channel = get_channel(chain.clone(), rt.handle().clone())?; Ok(Self { diff --git a/src/wasm_emulation/contract.rs b/src/wasm_emulation/contract.rs index f2abf1c5..d0ca35a2 100644 --- a/src/wasm_emulation/contract.rs +++ b/src/wasm_emulation/contract.rs @@ -9,8 +9,7 @@ use cosmwasm_vm::{ call_execute, call_instantiate, call_migrate, call_query, call_reply, call_sudo, Backend, BackendApi, Checksum, Instance, InstanceOptions, Querier, Size, }; -use cw_orch_daemon::queriers::CosmWasm; -use cw_orch_daemon::queriers::DaemonQuerier; +use cw_orch::daemon::queriers::CosmWasm; use cosmwasm_std::Order; use cosmwasm_std::Storage; @@ -121,25 +120,31 @@ impl WasmContract { match self { WasmContract::Local(LocalWasmContract { code, .. }) => Ok(code.clone()), WasmContract::DistantContract(DistantContract { contract_addr }) => { - let wasm_querier = CosmWasm::new(fork_state.remote.channel); + let wasm_querier = CosmWasm { + channel: fork_state.remote.channel.clone(), + rt_handle: Some(fork_state.remote.rt.clone()), + }; let code_info = fork_state .remote .rt - .block_on(wasm_querier.contract_info(contract_addr))?; + .block_on(wasm_querier._contract_info(contract_addr))?; let code = fork_state .remote .rt - .block_on(wasm_querier.code_data(code_info.code_id))?; + .block_on(wasm_querier._code_data(code_info.code_id))?; Ok(code) } WasmContract::DistantCodeId(DistantCodeId { code_id }) => { - let wasm_querier = CosmWasm::new(fork_state.remote.channel); + let wasm_querier = CosmWasm { + channel: fork_state.remote.channel.clone(), + rt_handle: Some(fork_state.remote.rt.clone()), + }; let code = fork_state .remote .rt - .block_on(wasm_querier.code_data(*code_id))?; + .block_on(wasm_querier._code_data(*code_id))?; Ok(code) } } @@ -160,7 +165,7 @@ impl WasmContract { let address = function.get_address(); let code = self.get_code(fork_state.clone())?; - let api = RealApi::new(&fork_state.remote.chain.bech32_prefix); + let api = RealApi::new(&fork_state.remote.chain.network_info.pub_address_prefix); // We create the backend here from outside information; let backend = Backend { diff --git a/src/wasm_emulation/query/bank.rs b/src/wasm_emulation/query/bank.rs index 0771d183..946472a9 100644 --- a/src/wasm_emulation/query/bank.rs +++ b/src/wasm_emulation/query/bank.rs @@ -5,10 +5,9 @@ use cosmwasm_std::Addr; use cosmwasm_vm::GasInfo; use std::str::FromStr; -use cw_orch_daemon::queriers::DaemonQuerier; use cw_utils::NativeBalance; -use cw_orch_daemon::queriers::Bank; +use cw_orch::daemon::queriers::Bank; use cosmwasm_std::Binary; use cosmwasm_std::Coin; @@ -80,12 +79,15 @@ impl BankQuerier { // If the amount is not available, we query it from the distant chain if amount.is_none() { - let querier = Bank::new(self.remote.channel.clone()); + let querier = Bank { + channel: self.remote.channel.clone(), + rt_handle: Some(self.remote.rt.clone()), + }; let query_result = self .remote .rt - .block_on(querier.balance(address, Some(denom.clone()))) + .block_on(querier._balance(address, Some(denom.clone()))) .map(|result| Uint128::from_str(&result[0].amount).unwrap()); if let Ok(distant_amount) = query_result { @@ -107,11 +109,14 @@ impl BankQuerier { // We query only if the bank balance doesn't exist if amount.is_none() { - let querier = Bank::new(self.remote.channel.clone()); + let querier = Bank { + channel: self.remote.channel.clone(), + rt_handle: Some(self.remote.rt.clone()), + }; let query_result: Result, _> = self .remote .rt - .block_on(querier.balance(address, None)) + .block_on(querier._balance(address, None)) .map(|result| { result .into_iter() diff --git a/src/wasm_emulation/query/wasm.rs b/src/wasm_emulation/query/wasm.rs index dc0bc06b..0ea67807 100644 --- a/src/wasm_emulation/query/wasm.rs +++ b/src/wasm_emulation/query/wasm.rs @@ -130,7 +130,9 @@ impl< let deps = OwnedDeps { storage, - api: MockApiBech32::new(&self.fork_state.remote.chain.bech32_prefix), + api: MockApiBech32::new( + &self.fork_state.remote.chain.network_info.pub_address_prefix, + ), querier: MockQuerier::new(self.fork_state.clone()), custom_query_type: PhantomData::, }; diff --git a/src/wasm_emulation/storage/analyzer.rs b/src/wasm_emulation/storage/analyzer.rs index 1a8fb4a9..17648f36 100644 --- a/src/wasm_emulation/storage/analyzer.rs +++ b/src/wasm_emulation/storage/analyzer.rs @@ -1,27 +1,14 @@ -use crate::prefixed_storage::decode_length; -use crate::prefixed_storage::to_length_prefixed; -use crate::prefixed_storage::CONTRACT_STORAGE_PREFIX; -use crate::wasm_emulation::channel::RemoteChannel; -use crate::BankKeeper; -use crate::Distribution; -use crate::Gov; -use crate::Ibc; -use crate::Module; -use crate::Staking; -use crate::WasmKeeper; -use cosmwasm_std::Addr; -use cosmwasm_std::Api; -use cosmwasm_std::Coin; -use cosmwasm_std::CustomMsg; -use cosmwasm_std::CustomQuery; -use cosmwasm_std::Storage; -use cw_orch_daemon::queriers::CosmWasm; -use cw_orch_daemon::queriers::DaemonQuerier; +use crate::{ + prefixed_storage::{decode_length, to_length_prefixed, CONTRACT_STORAGE_PREFIX}, + wasm_emulation::channel::RemoteChannel, + BankKeeper, Distribution, Gov, Ibc, Module, Staking, WasmKeeper, +}; +use cosmwasm_std::{Addr, Api, Coin, CustomMsg, CustomQuery, Storage}; +use cw_orch::prelude::BankQuerier; use cw_utils::NativeBalance; use rustc_serialize::json::Json; -use serde::Serialize; -use serde::__private::from_utf8_lossy; use serde::de::DeserializeOwned; +use serde::Serialize; use treediff::diff; use treediff::tools::Recorder; @@ -90,8 +77,8 @@ impl StorageAnalyzer { .into_iter() .map(|(key, value)| { ( - from_utf8_lossy(&key).to_string(), - from_utf8_lossy(&value).to_string(), + String::from_utf8_lossy(&key).to_string(), + String::from_utf8_lossy(&value).to_string(), ) }) .collect() @@ -118,7 +105,7 @@ impl StorageAnalyzer { .try_into() .unwrap(); let contract_addr_addr = - from_utf8_lossy(&resulting_key[2..(addr_len + 2)]).to_string(); + String::from_utf8_lossy(&resulting_key[2..(addr_len + 2)]).to_string(); let split: Vec<_> = contract_addr_addr.split('/').collect(); if split.len() != 2 || format!("{}/", split[0]) != CONTRACT_STORAGE_PREFIX { @@ -140,15 +127,18 @@ impl StorageAnalyzer { .map(|(contract, key, value)| { ( contract, - from_utf8_lossy(&key).to_string(), - from_utf8_lossy(&value).to_string(), + String::from_utf8_lossy(&key).to_string(), + String::from_utf8_lossy(&value).to_string(), ) }) .collect() } pub fn compare_all_readable_contract_storage(&self) { - let wasm_querier = CosmWasm::new(self.remote.channel.clone()); + let wasm_querier = cw_orch::daemon::queriers::CosmWasm { + channel: self.remote.channel.clone(), + rt_handle: Some(self.remote.rt.clone()), + }; self.all_contract_storage() .into_iter() .for_each(|(contract_addr, key, value)| { @@ -156,30 +146,30 @@ impl StorageAnalyzer { let distant_data = self .remote .rt - .block_on(wasm_querier.contract_raw_state(contract_addr.clone(), key.clone())); + .block_on(wasm_querier._contract_raw_state(contract_addr.clone(), key.clone())); if let Ok(data) = distant_data { let local_json: Json = - if let Ok(v) = from_utf8_lossy(&value).to_string().parse() { + if let Ok(v) = String::from_utf8_lossy(&value).to_string().parse() { v } else { log::info!( "Storage at {}, and key {}, was : {:x?}, now {:x?}", contract_addr, - from_utf8_lossy(&key).to_string(), + String::from_utf8_lossy(&key).to_string(), data.data, value ); return; }; let distant_json: Json = - if let Ok(v) = from_utf8_lossy(&data.data).to_string().parse() { + if let Ok(v) = String::from_utf8_lossy(&data.data).to_string().parse() { v } else { log::info!( "Storage at {}, and key {}, was : {:x?}, now {:x?}", contract_addr, - from_utf8_lossy(&key).to_string(), + String::from_utf8_lossy(&key).to_string(), data.data, value ); @@ -200,21 +190,21 @@ impl StorageAnalyzer { log::info!( "Storage at {}, and key {}, changed like so : {:?}", contract_addr, - from_utf8_lossy(&key).to_string(), + String::from_utf8_lossy(&key).to_string(), changes ); - } else if let Ok(v) = from_utf8_lossy(&value).to_string().parse::() { + } else if let Ok(v) = String::from_utf8_lossy(&value).to_string().parse::() { log::info!( "Storage at {}, and key {}, is new : {}", contract_addr, - from_utf8_lossy(&key).to_string(), + String::from_utf8_lossy(&key).to_string(), v ); } else { log::info!( "Storage at {}, and key {}, is new : {:?}", contract_addr, - from_utf8_lossy(&key).to_string(), + String::from_utf8_lossy(&key).to_string(), value ); } @@ -233,25 +223,17 @@ impl StorageAnalyzer { } pub fn compare_all_balances(&self) { - let bank_querier = cw_orch_daemon::queriers::Bank::new(self.remote.channel.clone()); + let bank_querier = cw_orch::daemon::queriers::Bank { + channel: self.remote.channel.clone(), + rt_handle: Some(self.remote.rt.clone()), + }; self.get_all_local_balances() .into_iter() .for_each(|(addr, balances)| { // We look for the data at that key on the contract - let distant_data = self - .remote - .rt - .block_on(bank_querier.balance(addr.clone(), None)); - - if let Ok(data) = distant_data { - let distant_coins: Vec = data - .iter() - .map(|c| Coin { - amount: c.amount.parse().unwrap(), - denom: c.denom.clone(), - }) - .collect(); + let distant_data = bank_querier.balance(addr.clone(), None); + if let Ok(distant_coins) = distant_data { let distant_coins = serde_json::to_string(&distant_coins).unwrap(); let distant_coins: Json = distant_coins.parse().unwrap(); diff --git a/src/wasm_emulation/storage/dual_std_storage.rs b/src/wasm_emulation/storage/dual_std_storage.rs index bb26a6c0..526ffec6 100644 --- a/src/wasm_emulation/storage/dual_std_storage.rs +++ b/src/wasm_emulation/storage/dual_std_storage.rs @@ -4,12 +4,10 @@ use cosmrs::proto::cosmos::base::query::v1beta1::PageRequest; use cosmrs::proto::cosmwasm::wasm::v1::Model; use cosmwasm_std::Record; use cosmwasm_std::{Order, Storage}; -use cw_orch_daemon::queriers::DaemonQuerier; +use cw_orch::daemon::queriers::CosmWasm; use num_bigint::{BigInt, Sign}; use std::iter::{self, Peekable}; -use cw_orch_daemon::queriers::CosmWasm; - fn get_key_bigint(mut key1: Vec, mut key2: Vec) -> (BigInt, BigInt) { if key1.len() >= key2.len() { key2.extend(iter::repeat(0).take(key1.len() - key2.len())) @@ -66,12 +64,15 @@ impl<'i> Iterator for Iter<'i> { && (self.distant_iter.position == 0 || !self.distant_iter.key.clone().unwrap().is_empty()) { - let wasm_querier = CosmWasm::new(self.distant_iter.remote.channel.clone()); + let wasm_querier = CosmWasm { + channel: self.distant_iter.remote.channel.clone(), + rt_handle: Some(self.distant_iter.remote.rt.clone()), + }; let new_keys = self .distant_iter .remote .rt - .block_on(wasm_querier.all_contract_state( + .block_on(wasm_querier._all_contract_state( self.distant_iter.contract_addr.clone(), Some(PageRequest { key: self.distant_iter.key.clone().unwrap(), @@ -159,10 +160,13 @@ impl<'a> Storage for DualStorage<'a> { let mut value = self.local_storage.get(key); // If it's not available, we query it online if it was not removed locally if !self.removed_keys.contains(key) && value.as_ref().is_none() { - let wasm_querier = CosmWasm::new(self.remote.channel.clone()); + let wasm_querier = CosmWasm { + channel: self.remote.channel.clone(), + rt_handle: Some(self.remote.rt.clone()), + }; let distant_result = self.remote.rt.block_on( - wasm_querier.contract_raw_state(self.contract_addr.clone(), key.to_vec()), + wasm_querier._contract_raw_state(self.contract_addr.clone(), key.to_vec()), ); if let Ok(result) = distant_result { diff --git a/src/wasm_emulation/storage/dual_storage.rs b/src/wasm_emulation/storage/dual_storage.rs index 6b630e43..70f8ab6a 100644 --- a/src/wasm_emulation/storage/dual_storage.rs +++ b/src/wasm_emulation/storage/dual_storage.rs @@ -10,12 +10,11 @@ use cosmwasm_vm::BackendError; use cosmwasm_vm::BackendResult; use cosmwasm_vm::GasInfo; use cosmwasm_vm::Storage; -use cw_orch_daemon::queriers::DaemonQuerier; use num_bigint::{BigInt, Sign}; use std::collections::HashMap; use std::iter; -use cw_orch_daemon::queriers::CosmWasm; +use cw_orch::daemon::queriers::CosmWasm; fn get_key_bigint(mut key1: Vec, mut key2: Vec) -> (BigInt, BigInt) { if key1.len() >= key2.len() { @@ -107,10 +106,13 @@ impl Storage for DualStorage { let (mut value, gas_info) = self.local_storage.get(key); // If it's not available, we query it online if it was not removed locally if !self.removed_keys.contains(key) && value.as_ref().unwrap().is_none() { - let wasm_querier = CosmWasm::new(self.remote.channel.clone()); + let wasm_querier = CosmWasm { + channel: self.remote.channel.clone(), + rt_handle: Some(self.remote.rt.clone()), + }; let distant_result = self.remote.rt.block_on( - wasm_querier.contract_raw_state(self.contract_addr.clone(), key.to_vec()), + wasm_querier._contract_raw_state(self.contract_addr.clone(), key.to_vec()), ); if let Ok(result) = distant_result { @@ -177,11 +179,14 @@ impl Storage for DualStorage { if iterator.distant_iter.position == iterator.distant_iter.data.len() && iterator.distant_iter.key.is_some() { - let wasm_querier = CosmWasm::new(self.remote.channel.clone()); + let wasm_querier = CosmWasm { + channel: self.remote.channel.clone(), + rt_handle: Some(self.remote.rt.clone()), + }; let new_keys = self .remote .rt - .block_on(wasm_querier.all_contract_state( + .block_on(wasm_querier._all_contract_state( self.contract_addr.clone(), Some(PageRequest { key: iterator.distant_iter.key.clone().unwrap(), From 0e1472df711da5de0d1fe82d2d51ae552a03b19d Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 30 Apr 2024 12:00:48 +0000 Subject: [PATCH 34/81] Added log debug for clone testing storage --- src/wasm_emulation/storage/dual_storage.rs | 4 ++++ src/wasm_emulation/storage/mod.rs | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/wasm_emulation/storage/dual_storage.rs b/src/wasm_emulation/storage/dual_storage.rs index 70f8ab6a..0c434155 100644 --- a/src/wasm_emulation/storage/dual_storage.rs +++ b/src/wasm_emulation/storage/dual_storage.rs @@ -1,5 +1,6 @@ use crate::wasm_emulation::channel::RemoteChannel; use crate::wasm_emulation::storage::mock_storage::{GAS_COST_LAST_ITERATION, GAS_COST_RANGE}; +use crate::wasm_emulation::storage::CLONE_TESTING_STORAGE_LOG; use super::mock_storage::MockStorage; use cosmrs::proto::cosmos::base::query::v1beta1::PageRequest; @@ -102,10 +103,12 @@ impl DualStorage { impl Storage for DualStorage { fn get(&self, key: &[u8]) -> BackendResult>> { + log::debug!(target: CLONE_TESTING_STORAGE_LOG, "Getting key : {:x?}", String::from_utf8_lossy(key)); // First we try to get the value locally let (mut value, gas_info) = self.local_storage.get(key); // If it's not available, we query it online if it was not removed locally if !self.removed_keys.contains(key) && value.as_ref().unwrap().is_none() { + log::debug!(target: CLONE_TESTING_STORAGE_LOG, "Value not set locally, fetching remote key"); let wasm_querier = CosmWasm { channel: self.remote.channel.clone(), rt_handle: Some(self.remote.rt.clone()), @@ -121,6 +124,7 @@ impl Storage for DualStorage { } } } + log::debug!(target: CLONE_TESTING_STORAGE_LOG, "Value found: {:x?}", value.as_ref().map(|v| v.clone().map(|v| String::from_utf8_lossy(&v).to_string()))); (value, gas_info) } diff --git a/src/wasm_emulation/storage/mod.rs b/src/wasm_emulation/storage/mod.rs index 8728e66a..252704a0 100644 --- a/src/wasm_emulation/storage/mod.rs +++ b/src/wasm_emulation/storage/mod.rs @@ -7,3 +7,5 @@ pub use dual_storage::DualStorage; pub use mock_storage::MockStorage; pub mod analyzer; + +pub const CLONE_TESTING_STORAGE_LOG: &str = "clone_testing_storage"; From 8a4fe81aaead0aa01afe237b06d93cde1a4767f9 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 30 Apr 2024 12:15:32 +0000 Subject: [PATCH 35/81] More logs --- src/wasm_emulation/storage/dual_storage.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/wasm_emulation/storage/dual_storage.rs b/src/wasm_emulation/storage/dual_storage.rs index 0c434155..9b939ab0 100644 --- a/src/wasm_emulation/storage/dual_storage.rs +++ b/src/wasm_emulation/storage/dual_storage.rs @@ -268,11 +268,13 @@ impl Storage for DualStorage { } fn set(&mut self, key: &[u8], value: &[u8]) -> BackendResult<()> { + log::debug!(target: CLONE_TESTING_STORAGE_LOG, "Setting key: {:x?} ;value: {:x?}", String::from_utf8_lossy(key), String::from_utf8_lossy(value)); self.removed_keys.remove(key); // It's not locally removed anymore, because we set it locally self.local_storage.set(key, value) } fn remove(&mut self, key: &[u8]) -> BackendResult<()> { + log::debug!(target: CLONE_TESTING_STORAGE_LOG, "Removing key: {:x?}", String::from_utf8_lossy(key)); self.removed_keys.insert(key.to_vec()); // We indicate locally if it's removed. So that we can remove keys and not query them on the distant chain self.local_storage.remove(key) } From 9ce0daafa6e86aa8a243ebb0f1894a42d758b6dc Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 30 Apr 2024 13:55:58 +0000 Subject: [PATCH 36/81] Better logs --- src/wasm_emulation/storage/dual_storage.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/wasm_emulation/storage/dual_storage.rs b/src/wasm_emulation/storage/dual_storage.rs index 9b939ab0..5adc6904 100644 --- a/src/wasm_emulation/storage/dual_storage.rs +++ b/src/wasm_emulation/storage/dual_storage.rs @@ -103,7 +103,7 @@ impl DualStorage { impl Storage for DualStorage { fn get(&self, key: &[u8]) -> BackendResult>> { - log::debug!(target: CLONE_TESTING_STORAGE_LOG, "Getting key : {:x?}", String::from_utf8_lossy(key)); + log::debug!(target: CLONE_TESTING_STORAGE_LOG, "Getting key on contract: {}; key: {}", self.contract_addr, String::from_utf8_lossy(key)); // First we try to get the value locally let (mut value, gas_info) = self.local_storage.get(key); // If it's not available, we query it online if it was not removed locally @@ -124,7 +124,12 @@ impl Storage for DualStorage { } } } - log::debug!(target: CLONE_TESTING_STORAGE_LOG, "Value found: {:x?}", value.as_ref().map(|v| v.clone().map(|v| String::from_utf8_lossy(&v).to_string()))); + if let Ok(Some(value)) = value.as_ref() { + log::debug!(target: CLONE_TESTING_STORAGE_LOG, "Value found: {}", String::from_utf8_lossy(value)); + } else { + log::debug!(target: CLONE_TESTING_STORAGE_LOG, "Found no value"); + } + (value, gas_info) } @@ -268,13 +273,13 @@ impl Storage for DualStorage { } fn set(&mut self, key: &[u8], value: &[u8]) -> BackendResult<()> { - log::debug!(target: CLONE_TESTING_STORAGE_LOG, "Setting key: {:x?} ;value: {:x?}", String::from_utf8_lossy(key), String::from_utf8_lossy(value)); + log::debug!(target: CLONE_TESTING_STORAGE_LOG, "Setting key on contract: {}; key: {}; value: {}", self.contract_addr, String::from_utf8_lossy(key), String::from_utf8_lossy(value)); self.removed_keys.remove(key); // It's not locally removed anymore, because we set it locally self.local_storage.set(key, value) } fn remove(&mut self, key: &[u8]) -> BackendResult<()> { - log::debug!(target: CLONE_TESTING_STORAGE_LOG, "Removing key: {:x?}", String::from_utf8_lossy(key)); + log::debug!(target: CLONE_TESTING_STORAGE_LOG, "Removing key on contract: {}; {}", self.contract_addr, String::from_utf8_lossy(key)); self.removed_keys.insert(key.to_vec()); // We indicate locally if it's removed. So that we can remove keys and not query them on the distant chain self.local_storage.remove(key) } From 16c1579d9a2616986dd42fe9c549fb3a076a63b1 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 30 Apr 2024 22:00:58 +0000 Subject: [PATCH 37/81] Fixed dual iterator on same keys --- src/wasm_emulation/storage/dual_storage.rs | 57 +++++++++++++++++++++- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/src/wasm_emulation/storage/dual_storage.rs b/src/wasm_emulation/storage/dual_storage.rs index 5adc6904..7816f39e 100644 --- a/src/wasm_emulation/storage/dual_storage.rs +++ b/src/wasm_emulation/storage/dual_storage.rs @@ -168,6 +168,18 @@ impl Storage for DualStorage { let new_id = last_id + 1; self.iterators.insert(new_id, iter.clone()); + log::debug!( + target: CLONE_TESTING_STORAGE_LOG, + "Create iterator {} on contract {} between {:?} and {:?}, order: {:?}", + new_id, + self.contract_addr, + start.map(|v|String::from_utf8_lossy(v)), + end.map(|v|String::from_utf8_lossy(v)), + match order{ + Order::Ascending => "ascending", + Order::Descending => "descending" + } + ); (Ok(new_id), gas_info) } @@ -231,7 +243,24 @@ impl Storage for DualStorage { } // 2. We find the first key in order between distant and local storage - let next_local = self.local_storage.peak(iterator.local_iter).unwrap(); + // We need to disregard local keys that have been removed + let next_local; + loop { + let next = self.local_storage.peak(iterator.local_iter).unwrap(); + if let Some((next_key, _next_value)) = next.as_ref() { + if self.removed_keys.contains(next_key) { + // We disregard the current key + self.local_storage.next(iterator.local_iter).0.unwrap(); + continue; + } else { + next_local = next; + break; + } + } else { + next_local = next; + break; + } + } let next_distant = iterator .distant_iter .data @@ -242,10 +271,20 @@ impl Storage for DualStorage { // We compare the two keys with the order and return the higher key let key_local = BigInt::from_bytes_be(Sign::Plus, &local.0); let key_distant = BigInt::from_bytes_be(Sign::Plus, &distant.key); - if (key_local < key_distant) == iterator.distant_iter.reverse { + + if key_local == key_distant { + // Equal keys, means we need to take the local key, which is newer + // And we need to skip the distant key + iterator.distant_iter.position += 1; + self.local_storage.next(iterator.local_iter).0.unwrap() + } else if (key_local < key_distant) == iterator.distant_iter.reverse { + // Keys are ordered such that the distant key is chosen + // We upgrade the distant iterator and return the distant key iterator.distant_iter.position += 1; Some((distant.key.clone(), distant.value.clone())) } else { + // Keys are ordered such that the local key is chosen + // We get the next local key self.local_storage.next(iterator.local_iter).0.unwrap() } } else { @@ -260,11 +299,25 @@ impl Storage for DualStorage { // We add the gas cost if let Some((key, value)) = key_value { + log::debug!( + target: CLONE_TESTING_STORAGE_LOG, + "Got next iterator value contract {}, iterator {}, key {}, value {}", + self.contract_addr, + iterator_id, + String::from_utf8_lossy(&key), + String::from_utf8_lossy(&value) + ); ( Ok(Some((key.clone(), value.clone()))), GasInfo::with_externally_used((key.len() + value.len()) as u64), ) } else { + log::debug!( + target: CLONE_TESTING_STORAGE_LOG, + "No more values for iterator {} contract {}", + self.contract_addr, + iterator_id, + ); ( Ok(None), GasInfo::with_externally_used(GAS_COST_LAST_ITERATION), From f245437842b2e4bd6e0c4dba9fa428ebcb451c64 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Wed, 1 May 2024 13:58:12 +0000 Subject: [PATCH 38/81] Updated cw-orch to 0.22 --- Cargo.lock | 26 +++++++++++++------------- Cargo.toml | 4 ++-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 144ef942..dc1dd2ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -835,7 +835,7 @@ dependencies = [ [[package]] name = "cw-multi-test" -version = "0.20.0-rc" +version = "0.20.0" dependencies = [ "anyhow", "bech32 0.9.1", @@ -872,9 +872,9 @@ dependencies = [ [[package]] name = "cw-orch" -version = "0.22.0-rc1" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dadb0d3efe8116adde3a00e005d6bb8e6d5e61269ee298f16575137920789b" +checksum = "0ab0efd28ea15c6d2a12736379c67b97118268b8b1c227483b315286a182da12" dependencies = [ "anyhow", "cosmrs", @@ -908,9 +908,9 @@ dependencies = [ [[package]] name = "cw-orch-core" -version = "1.0.0-rc" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec6d4ff5ea61a14a73b9c480d2600a0e8fbb847ea3e6696741d0a4289e2b81a0" +checksum = "1c8e62b4d04699596bc2f45c57a8e5459495584d8127588ae4bbe7f95d616b61" dependencies = [ "abstract-cw-multi-test", "anyhow", @@ -927,9 +927,9 @@ dependencies = [ [[package]] name = "cw-orch-daemon" -version = "0.22.0-rc" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc35a85bf5e7808bd076dae3704ce70670fb1194576a7a71f1ac5c2018e51a6" +checksum = "a457b6c10226854c69211e847b5402b557ad9ff4e2a4e35ec325bfdc6493c37b" dependencies = [ "anyhow", "async-recursion", @@ -979,9 +979,9 @@ dependencies = [ [[package]] name = "cw-orch-mock" -version = "0.22.0-rc" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdbe04cc54fa4559a6efb4e2dd20a921e064da36e274b440150d4b7e6a56ed45" +checksum = "ad451fddf9a61db34c7c2fd0852a83238ffcada483dcacfac4622e9085df234f" dependencies = [ "abstract-cw-multi-test", "cosmwasm-std", @@ -994,9 +994,9 @@ dependencies = [ [[package]] name = "cw-orch-networks" -version = "0.22.0-rc" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12107c5bbe6f80f5b30d617b6e5c2ab9a0131bce4940d44b7ca93626b4e64bdc" +checksum = "7557d86fb243aabf48d4358dec24b27b3fb4a4e7283ad384ae267dc9dbc2a5d4" dependencies = [ "cw-orch-core", "serde", @@ -1004,9 +1004,9 @@ dependencies = [ [[package]] name = "cw-orch-traits" -version = "0.22.0-rc" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4509406490b3682b7af9d7f0afac0021ffb54fbb8a4c7294218740498681e962" +checksum = "5959ce29e9d8a52594b47933a0a2736ea94dd9bf5e29b220cbdbe2b097f07c3a" dependencies = [ "cw-orch-core", "prost", diff --git a/Cargo.toml b/Cargo.toml index 5e0b2a68..5f1000a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cw-multi-test" -version = "0.20.0-rc" +version = "0.20.0" authors = ["Ethan Frey "] edition = "2021" description = "Testing tools for multi-contract interactions" @@ -36,7 +36,7 @@ thiserror = "1.0.50" # Clone testing deps ## Network -cw-orch = { version = "0.22.0-rc", features = ["daemon"] } +cw-orch = { version = "0.22.0", features = ["daemon"] } tokio = "1.28.2" tonic = "0.10.2" From b078bef0ca5f7d88504dff46f764de7382d43339 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Sun, 26 May 2024 12:27:31 +0000 Subject: [PATCH 39/81] Removed the chain dependency --- examples/cavern_test_app.rs | 44 ++++++++++++++++++++------------ examples/cousin_test.rs | 17 +++++++++--- examples/test_app.rs | 17 ++++++++++-- src/app.rs | 4 +-- src/wasm_emulation/channel.rs | 18 +++++-------- src/wasm_emulation/contract.rs | 2 +- src/wasm_emulation/query/wasm.rs | 4 +-- 7 files changed, 67 insertions(+), 39 deletions(-) diff --git a/examples/cavern_test_app.rs b/examples/cavern_test_app.rs index 9c35b7e7..1b6a4b2c 100644 --- a/examples/cavern_test_app.rs +++ b/examples/cavern_test_app.rs @@ -1,23 +1,23 @@ -use cosmwasm_schema::cw_serde; -use cosmwasm_schema::QueryResponses; -use cosmwasm_std::coins; -use cosmwasm_std::Addr; -use cosmwasm_std::BlockInfo; -use cosmwasm_std::ContractInfoResponse; -use cosmwasm_std::QueryRequest; -use cosmwasm_std::WasmQuery; +use anyhow::Result as AnyResult; +use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::{coins, Addr, BlockInfo, ContractInfoResponse, QueryRequest, WasmQuery}; use cw20::BalanceResponse; use cw_multi_test::addons::MockAddressGenerator; -use cw_multi_test::addons::MockApiBech32; -use cw_multi_test::wasm_emulation::channel::RemoteChannel; -use cw_multi_test::wasm_emulation::contract::WasmContract; -use cw_multi_test::wasm_emulation::storage::analyzer::StorageAnalyzer; -use cw_multi_test::BankKeeper; -use cw_multi_test::Executor; -use cw_orch::daemon::networks::PHOENIX_1; -use cw_orch::daemon::queriers::Node; +use cw_multi_test::{ + addons::MockApiBech32, + wasm_emulation::{ + channel::RemoteChannel, contract::WasmContract, storage::analyzer::StorageAnalyzer, + }, + BankKeeper, Executor, +}; +use cw_orch::{ + daemon::{networks::PHOENIX_1, queriers::Node, GrpcChannel}, + environment::ChainInfoOwned, +}; use std::path::Path; +use tokio::runtime::Handle; use tokio::runtime::Runtime; +use tonic::transport::Channel; use cw20::Cw20QueryMsg; use cw_multi_test::AppBuilder; @@ -57,6 +57,12 @@ pub struct InstantiateMsg { /// END CONTRACT MSGs +fn get_channel(chain: impl Into, rt: Handle) -> AnyResult { + let chain = chain.into(); + let channel = rt.block_on(GrpcChannel::connect(&chain.grpc_urls, &chain.chain_id))?; + Ok(channel) +} + pub fn test() -> anyhow::Result<()> { env_logger::init(); @@ -67,7 +73,11 @@ pub fn test() -> anyhow::Result<()> { let runtime = Runtime::new()?; let chain = PHOENIX_1; - let remote_channel = RemoteChannel::new(&runtime, chain.clone())?; + let remote_channel = RemoteChannel::new( + &runtime, + get_channel(chain.clone(), runtime.handle().clone())?, + chain.network_info.pub_address_prefix, + )?; let wasm = WasmKeeper::::new() .with_remote(remote_channel.clone()) diff --git a/examples/cousin_test.rs b/examples/cousin_test.rs index ca04c24e..79d2fe50 100644 --- a/examples/cousin_test.rs +++ b/examples/cousin_test.rs @@ -11,11 +11,18 @@ use cw_multi_test::{ wasm_emulation::{channel::RemoteChannel, contract::WasmContract}, App, AppBuilder, BankKeeper, ContractWrapper, Executor, WasmKeeper, }; -use cw_orch::daemon::networks::PHOENIX_1; -use tokio::runtime::Runtime; +use cw_orch::{daemon::{networks::PHOENIX_1, GrpcChannel}, environment::ChainInfoOwned}; +use tokio::runtime::{Handle, Runtime}; +use tonic::transport::Channel; mod counter; +fn get_channel(chain: impl Into, rt: Handle) -> AnyResult { + let chain = chain.into(); + let channel = rt.block_on(GrpcChannel::connect(&chain.grpc_urls, &chain.chain_id))?; + Ok(channel) +} + pub const SENDER: &str = "terra17c6ts8grcfrgquhj3haclg44le8s7qkx6l2yx33acguxhpf000xqhnl3je"; fn increment(app: &mut App, contract: Addr) -> AnyResult<()> { let sender = Addr::unchecked(SENDER); @@ -70,7 +77,11 @@ fn test() -> AnyResult<()> { let runtime = Runtime::new()?; let chain = PHOENIX_1; - let remote_channel = RemoteChannel::new(&runtime, chain.clone())?; + let remote_channel = RemoteChannel::new( + &runtime, + get_channel(chain.clone(), runtime.handle().clone())?, + chain.network_info.pub_address_prefix, + )?; let wasm = WasmKeeper::::new() .with_remote(remote_channel.clone()) diff --git a/examples/test_app.rs b/examples/test_app.rs index 2dc138c4..49381b2e 100644 --- a/examples/test_app.rs +++ b/examples/test_app.rs @@ -1,3 +1,4 @@ +use anyhow::Result as AnyResult; use cosmwasm_std::Addr; use cw20::AllAccountsResponse; use cw20::Cw20ExecuteMsg; @@ -12,19 +13,31 @@ use cw_orch::daemon::networks::PHOENIX_1; use cw_multi_test::WasmKeeper; use cosmwasm_std::Empty; +use cw_orch::daemon::GrpcChannel; +use cw_orch::environment::ChainInfoOwned; +use tokio::runtime::Handle; use tokio::runtime::Runtime; +use tonic::transport::Channel; pub fn main() { test().unwrap() } +fn get_channel(chain: impl Into, rt: Handle) -> AnyResult { + let chain = chain.into(); + let channel = rt.block_on(GrpcChannel::connect(&chain.grpc_urls, &chain.chain_id))?; + Ok(channel) +} pub fn test() -> anyhow::Result<()> { env_logger::init(); let runtime = Runtime::new()?; let chain = PHOENIX_1; - let remote_channel = RemoteChannel::new(&runtime, chain)?; - + let remote_channel = RemoteChannel::new( + &runtime, + get_channel(chain.clone(), runtime.handle().clone())?, + chain.network_info.pub_address_prefix, + )?; let wasm = WasmKeeper::::new().with_remote(remote_channel.clone()); let bank = BankKeeper::new().with_remote(remote_channel.clone()); diff --git a/src/app.rs b/src/app.rs index c30f6d22..69258653 100644 --- a/src/app.rs +++ b/src/app.rs @@ -327,8 +327,8 @@ where let mut addresses = ADDRESSES.may_load(storage).unwrap().unwrap_or_default(); - let new_address = RealApi::new(&&remote.chain.network_info.pub_address_prefix.clone()) - .next_address(addresses.len()); + let new_address = + RealApi::new(&remote.pub_address_prefix.clone()).next_address(addresses.len()); addresses.push(new_address.clone()); ADDRESSES.save(storage, &addresses).unwrap(); diff --git a/src/wasm_emulation/channel.rs b/src/wasm_emulation/channel.rs index f952a941..0b6f6812 100644 --- a/src/wasm_emulation/channel.rs +++ b/src/wasm_emulation/channel.rs @@ -4,27 +4,23 @@ use cw_orch::prelude::ChainInfoOwned; use tokio::runtime::{Handle, Runtime}; use tonic::transport::Channel; -fn get_channel(chain: impl Into, rt: Handle) -> AnyResult { - let chain = chain.into(); - let channel = rt.block_on(GrpcChannel::connect(&chain.grpc_urls, &chain.chain_id))?; - Ok(channel) -} - #[derive(Clone)] pub struct RemoteChannel { pub rt: Handle, pub channel: Channel, - pub chain: ChainInfoOwned, + pub pub_address_prefix: String, } impl RemoteChannel { - pub fn new(rt: &Runtime, chain: impl Into) -> AnyResult { - let chain = chain.into(); - let channel = get_channel(chain.clone(), rt.handle().clone())?; + pub fn new( + rt: &Runtime, + channel: Channel, + pub_address_prefix: impl Into, + ) -> AnyResult { Ok(Self { rt: rt.handle().clone(), channel, - chain, + pub_address_prefix: pub_address_prefix.into(), }) } } diff --git a/src/wasm_emulation/contract.rs b/src/wasm_emulation/contract.rs index d0ca35a2..95514a67 100644 --- a/src/wasm_emulation/contract.rs +++ b/src/wasm_emulation/contract.rs @@ -165,7 +165,7 @@ impl WasmContract { let address = function.get_address(); let code = self.get_code(fork_state.clone())?; - let api = RealApi::new(&fork_state.remote.chain.network_info.pub_address_prefix); + let api = RealApi::new(&fork_state.remote.pub_address_prefix); // We create the backend here from outside information; let backend = Backend { diff --git a/src/wasm_emulation/query/wasm.rs b/src/wasm_emulation/query/wasm.rs index 0ea67807..bb6b960f 100644 --- a/src/wasm_emulation/query/wasm.rs +++ b/src/wasm_emulation/query/wasm.rs @@ -130,9 +130,7 @@ impl< let deps = OwnedDeps { storage, - api: MockApiBech32::new( - &self.fork_state.remote.chain.network_info.pub_address_prefix, - ), + api: MockApiBech32::new(&self.fork_state.remote.pub_address_prefix), querier: MockQuerier::new(self.fork_state.clone()), custom_query_type: PhantomData::, }; From 9c28ab6fd7213c6636ad6fd62529d3fcdefdd136 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Sun, 26 May 2024 12:36:07 +0000 Subject: [PATCH 40/81] Nitg --- src/wasm_emulation/channel.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/wasm_emulation/channel.rs b/src/wasm_emulation/channel.rs index 0b6f6812..7bf1cd69 100644 --- a/src/wasm_emulation/channel.rs +++ b/src/wasm_emulation/channel.rs @@ -1,6 +1,4 @@ use anyhow::Result as AnyResult; -use cw_orch::daemon::GrpcChannel; -use cw_orch::prelude::ChainInfoOwned; use tokio::runtime::{Handle, Runtime}; use tonic::transport::Channel; From fdaa40c19674de071d526973e7dcb1b574520171 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Sun, 26 May 2024 13:12:11 +0000 Subject: [PATCH 41/81] Prepare for publishing --- Cargo.lock | 74 +++++++++++++++++++++++++++--------------------------- Cargo.toml | 6 ++--- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dc1dd2ba..f910c8cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -408,6 +408,43 @@ dependencies = [ "windows-targets 0.52.5", ] +[[package]] +name = "clone-cw-multi-test" +version = "0.1.0" +dependencies = [ + "anyhow", + "bech32 0.9.1", + "cosmrs", + "cosmwasm-schema", + "cosmwasm-std", + "cosmwasm-vm", + "cw-orch", + "cw-storage-plus 1.2.0", + "cw-utils 1.0.3", + "cw2 1.1.2", + "cw20 1.1.2", + "derivative", + "env_logger", + "hex", + "hex-literal", + "itertools", + "log", + "moneymarket", + "num-bigint", + "once_cell", + "prost", + "rustc-serialize", + "schemars", + "serde", + "serde_json", + "sha2 0.10.8", + "thiserror", + "tokio", + "tonic", + "treediff", + "wasmer", +] + [[package]] name = "clru" version = "0.6.1" @@ -833,43 +870,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "cw-multi-test" -version = "0.20.0" -dependencies = [ - "anyhow", - "bech32 0.9.1", - "cosmrs", - "cosmwasm-schema", - "cosmwasm-std", - "cosmwasm-vm", - "cw-orch", - "cw-storage-plus 1.2.0", - "cw-utils 1.0.3", - "cw2 1.1.2", - "cw20 1.1.2", - "derivative", - "env_logger", - "hex", - "hex-literal", - "itertools", - "log", - "moneymarket", - "num-bigint", - "once_cell", - "prost", - "rustc-serialize", - "schemars", - "serde", - "serde_json", - "sha2 0.10.8", - "thiserror", - "tokio", - "tonic", - "treediff", - "wasmer", -] - [[package]] name = "cw-orch" version = "0.22.0" diff --git a/Cargo.toml b/Cargo.toml index 5f1000a7..9308c791 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,9 @@ [package] -name = "cw-multi-test" -version = "0.20.0" +name = "clone-cw-multi-test" +version = "0.1.0" authors = ["Ethan Frey "] edition = "2021" -description = "Testing tools for multi-contract interactions" +description = "Testing tools for multi-contract interactions. Helps simulating chain behavior with on-chain storage locally" license = "Apache-2.0" repository = "https://github.com/CosmWasm/cw-multi-test" homepage = "https://cosmwasm.com" From 64b2ca99d835bdadac7cb202960a2467725be8a1 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Sun, 26 May 2024 13:17:52 +0000 Subject: [PATCH 42/81] Nits --- examples/cavern_test_app.rs | 13 +++---------- examples/counter/contract.rs | 10 +++------- examples/counter/msg.rs | 6 +++--- examples/counter/query.rs | 2 +- examples/cousin_test.rs | 17 ++++++++++------- examples/test_app.rs | 7 +------ src/app_builder.rs | 1 + src/wasm_emulation/storage/analyzer.rs | 5 ++++- 8 files changed, 26 insertions(+), 35 deletions(-) diff --git a/examples/cavern_test_app.rs b/examples/cavern_test_app.rs index 1b6a4b2c..b128f117 100644 --- a/examples/cavern_test_app.rs +++ b/examples/cavern_test_app.rs @@ -1,15 +1,10 @@ use anyhow::Result as AnyResult; +use clone_cw_multi_test::{addons::{MockAddressGenerator, MockApiBech32}, wasm_emulation::{ + channel::RemoteChannel, contract::WasmContract, storage::analyzer::StorageAnalyzer, + }, AppBuilder, BankKeeper, Executor, WasmKeeper}; use cosmwasm_schema::{cw_serde, QueryResponses}; use cosmwasm_std::{coins, Addr, BlockInfo, ContractInfoResponse, QueryRequest, WasmQuery}; use cw20::BalanceResponse; -use cw_multi_test::addons::MockAddressGenerator; -use cw_multi_test::{ - addons::MockApiBech32, - wasm_emulation::{ - channel::RemoteChannel, contract::WasmContract, storage::analyzer::StorageAnalyzer, - }, - BankKeeper, Executor, -}; use cw_orch::{ daemon::{networks::PHOENIX_1, queriers::Node, GrpcChannel}, environment::ChainInfoOwned, @@ -20,10 +15,8 @@ use tokio::runtime::Runtime; use tonic::transport::Channel; use cw20::Cw20QueryMsg; -use cw_multi_test::AppBuilder; use cosmwasm_std::Empty; -use cw_multi_test::WasmKeeper; use moneymarket::market::ExecuteMsg; /// COUNTER CONTRACT MSGs diff --git a/examples/counter/contract.rs b/examples/counter/contract.rs index 59bbaeba..d60a1065 100644 --- a/examples/counter/contract.rs +++ b/examples/counter/contract.rs @@ -48,16 +48,12 @@ pub fn execute( #[cfg_attr(feature = "export", entry_point)] pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { match msg { - QueryMsg::GetCount {} => to_json_binary(&query::count(deps)?), - QueryMsg::GetCousinCount {} => to_json_binary(&query::cousin_count(deps)?), - QueryMsg::GetRawCousinCount {} => to_json_binary(&query::raw_cousin_count(deps)?), + QueryMsg::Count {} => to_json_binary(&query::count(deps)?), + QueryMsg::CousinCount {} => to_json_binary(&query::cousin_count(deps)?), + QueryMsg::RawCousinCount {} => to_json_binary(&query::raw_cousin_count(deps)?), } } -#[cfg_attr(feature = "export", entry_point)] -pub fn migrate(_deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result { - Ok(Response::default().add_attribute("action", "migrate")) -} // ANCHOR_END: interface_entry #[cfg(test)] diff --git a/examples/counter/msg.rs b/examples/counter/msg.rs index bfd81a99..5b8d7dd3 100644 --- a/examples/counter/msg.rs +++ b/examples/counter/msg.rs @@ -36,13 +36,13 @@ pub enum ExecuteMsg { pub enum QueryMsg { /// GetCount returns the current count as a json-encoded number #[returns(GetCountResponse)] - GetCount {}, + Count {}, /// GetCount returns the current count as a json-encoded number #[returns(GetCountResponse)] - GetCousinCount {}, + CousinCount {}, /// GetCount returns the current count as a json-encoded number #[returns(GetCountResponse)] - GetRawCousinCount {}, + RawCousinCount {}, } // Custom response for the query diff --git a/examples/counter/query.rs b/examples/counter/query.rs index d06ab68a..c160f09a 100644 --- a/examples/counter/query.rs +++ b/examples/counter/query.rs @@ -16,7 +16,7 @@ pub fn cousin_count(deps: Deps) -> StdResult { let cousin_count: GetCountResponse = deps.querier.query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: state.cousin.unwrap().to_string(), - msg: to_json_binary(&QueryMsg::GetCount {})?, + msg: to_json_binary(&QueryMsg::Count {})?, }))?; Ok(cousin_count) } diff --git a/examples/cousin_test.rs b/examples/cousin_test.rs index 79d2fe50..b767dc5a 100644 --- a/examples/cousin_test.rs +++ b/examples/cousin_test.rs @@ -4,14 +4,17 @@ fn main() { use std::path::Path; use anyhow::Result as AnyResult; -use cosmwasm_std::{Addr, Empty}; -use counter::msg::{ExecuteMsg, GetCountResponse, QueryMsg}; -use cw_multi_test::{ +use clone_cw_multi_test::{ addons::{MockAddressGenerator, MockApiBech32}, wasm_emulation::{channel::RemoteChannel, contract::WasmContract}, App, AppBuilder, BankKeeper, ContractWrapper, Executor, WasmKeeper, }; -use cw_orch::{daemon::{networks::PHOENIX_1, GrpcChannel}, environment::ChainInfoOwned}; +use cosmwasm_std::{Addr, Empty}; +use counter::msg::{ExecuteMsg, GetCountResponse, QueryMsg}; +use cw_orch::{ + daemon::{networks::PHOENIX_1, GrpcChannel}, + environment::ChainInfoOwned, +}; use tokio::runtime::{Handle, Runtime}; use tonic::transport::Channel; @@ -38,7 +41,7 @@ fn increment(app: &mut App, contract: Addr) -> AnyRes fn count(app: &App, contract: Addr) -> AnyResult { Ok(app .wrap() - .query_wasm_smart(contract.clone(), &QueryMsg::GetCount {})?) + .query_wasm_smart(contract.clone(), &QueryMsg::Count {})?) } fn raw_cousin_count( @@ -47,7 +50,7 @@ fn raw_cousin_count( ) -> AnyResult { Ok(app .wrap() - .query_wasm_smart(contract.clone(), &QueryMsg::GetRawCousinCount {})?) + .query_wasm_smart(contract.clone(), &QueryMsg::RawCousinCount {})?) } fn cousin_count( @@ -56,7 +59,7 @@ fn cousin_count( ) -> AnyResult { Ok(app .wrap() - .query_wasm_smart(contract.clone(), &QueryMsg::GetCousinCount {})?) + .query_wasm_smart(contract.clone(), &QueryMsg::CousinCount {})?) } fn test() -> AnyResult<()> { diff --git a/examples/test_app.rs b/examples/test_app.rs index 49381b2e..81a792a4 100644 --- a/examples/test_app.rs +++ b/examples/test_app.rs @@ -1,17 +1,12 @@ use anyhow::Result as AnyResult; +use clone_cw_multi_test::{wasm_emulation::channel::RemoteChannel, AppBuilder, BankKeeper, Executor, WasmKeeper}; use cosmwasm_std::Addr; use cw20::AllAccountsResponse; use cw20::Cw20ExecuteMsg; -use cw_multi_test::Executor; use cw20::Cw20QueryMsg; -use cw_multi_test::wasm_emulation::channel::RemoteChannel; -use cw_multi_test::AppBuilder; -use cw_multi_test::BankKeeper; use cw_orch::daemon::networks::PHOENIX_1; -use cw_multi_test::WasmKeeper; - use cosmwasm_std::Empty; use cw_orch::daemon::GrpcChannel; use cw_orch::environment::ChainInfoOwned; diff --git a/src/app_builder.rs b/src/app_builder.rs index 759efde8..ad747509 100644 --- a/src/app_builder.rs +++ b/src/app_builder.rs @@ -506,6 +506,7 @@ where self } + #[allow(clippy::type_complexity)] /// Builds final `App`. At this point all components type have to be properly related to each /// other. If there are some generics related compilation errors, make sure that all components /// are properly relating to each other. diff --git a/src/wasm_emulation/storage/analyzer.rs b/src/wasm_emulation/storage/analyzer.rs index 17648f36..47036993 100644 --- a/src/wasm_emulation/storage/analyzer.rs +++ b/src/wasm_emulation/storage/analyzer.rs @@ -29,6 +29,9 @@ pub struct StorageAnalyzer { pub remote: RemoteChannel, } +pub type CustomWasmKeeper = + WasmKeeper<::ExecT, ::QueryT>; + impl StorageAnalyzer { pub fn new( app: &App< @@ -36,7 +39,7 @@ impl StorageAnalyzer { ApiT, StorageT, CustomT, - WasmKeeper, + CustomWasmKeeper, StakingT, DistrT, IbcT, From fe5f539f2eacf7bffe9f60e2ab3b764e5a52f31a Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 28 May 2024 13:05:53 +0000 Subject: [PATCH 43/81] Fix multi-test --- Cargo.lock | 327 +++++++++++++++---------------- Cargo.toml | 4 +- src/queries/bank.rs | 19 +- src/queries/wasm.rs | 15 +- src/wasm.rs | 10 +- src/wasm_emulation/query/bank.rs | 22 +-- 6 files changed, 175 insertions(+), 222 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f910c8cd..a46f70bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "abstract-cw-multi-test" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d8a77cbdea0217c303f4909298260363bd80001120689449e58a409fac9072" +checksum = "0c77f8d4bac08f74fbc4fce8943cb2d35e742682b6cae8cb65555d6cd3830feb" dependencies = [ "anyhow", "bech32 0.11.0", @@ -79,9 +79,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.82" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" dependencies = [ "backtrace", ] @@ -94,13 +94,13 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "async-recursion" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30c5ef0ede93efbf733c1a727f3b6b5a1060bbedd5600183e66f6e4be4af0ec5" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -122,7 +122,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -133,14 +133,14 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] name = "autocfg" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "axum" @@ -384,9 +384,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.95" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" +checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" [[package]] name = "cfg-if" @@ -410,7 +410,7 @@ dependencies = [ [[package]] name = "clone-cw-multi-test" -version = "0.1.0" +version = "0.2.0" dependencies = [ "anyhow", "bech32 0.9.1", @@ -447,9 +447,9 @@ dependencies = [ [[package]] name = "clru" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8191fa7302e03607ff0e237d4246cc043ff5b3cb9409d995172ba3bea16b807" +checksum = "cbd0f76e066e64fdc5631e3bb46381254deab9ef1158292f27c8c57e3bf3fe59" [[package]] name = "const-oid" @@ -542,9 +542,9 @@ dependencies = [ [[package]] name = "cosmwasm-crypto" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b4c3f9c4616d6413d4b5fc4c270a4cc32a374b9be08671e80e1a019f805d8f" +checksum = "dd50718a2b6830ce9eb5d465de5a018a12e71729d66b70807ce97e6dd14f931d" dependencies = [ "digest 0.10.7", "ecdsa", @@ -556,18 +556,18 @@ dependencies = [ [[package]] name = "cosmwasm-derive" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c586ced10c3b00e809ee664a895025a024f60d65d34fe4c09daed4a4db68a3f3" +checksum = "242e98e7a231c122e08f300d9db3262d1007b51758a8732cd6210b3e9faa4f3a" dependencies = [ "syn 1.0.109", ] [[package]] name = "cosmwasm-schema" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8467874827d384c131955ff6f4d47d02e72a956a08eb3c0ff24f8c903a5517b4" +checksum = "7879036156092ad1c22fe0d7316efc5a5eceec2bc3906462a2560215f2a2f929" dependencies = [ "cosmwasm-schema-derive", "schemars", @@ -578,9 +578,9 @@ dependencies = [ [[package]] name = "cosmwasm-schema-derive" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6db85d98ac80922aef465e564d5b21fa9cfac5058cb62df7f116c3682337393" +checksum = "0bb57855fbfc83327f8445ae0d413b1a05ac0d68c396ab4d122b2abd7bb82cb6" dependencies = [ "proc-macro2", "quote", @@ -589,9 +589,9 @@ dependencies = [ [[package]] name = "cosmwasm-std" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712fe58f39d55c812f7b2c84e097cdede3a39d520f89b6dc3153837e31741927" +checksum = "78c1556156fdf892a55cced6115968b961eaaadd6f724a2c2cb7d1e168e32dd3" dependencies = [ "base64", "bech32 0.9.1", @@ -621,9 +621,9 @@ dependencies = [ [[package]] name = "cosmwasm-vm" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faf59efc75d03bb757612998e6b839675bff844871a7c9ec9f52ad4093f665cd" +checksum = "9897b46059d68ade608fbdcec33e02b0de0ca4b32ee787a83b8a3eb31b754c85" dependencies = [ "bitflags 1.3.2", "bytecheck", @@ -738,9 +738,9 @@ checksum = "393bc73c451830ff8dbb3a07f61843d6cb41a084f9996319917c0b291ed785bb" [[package]] name = "crc32fast" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] @@ -775,9 +775,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crypto-bigint" @@ -839,7 +839,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -872,9 +872,9 @@ dependencies = [ [[package]] name = "cw-orch" -version = "0.22.0" +version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab0efd28ea15c6d2a12736379c67b97118268b8b1c227483b315286a182da12" +checksum = "fc1ddc937c28c59ccf2765fa05ddc0437644d3b283408a7cc64f7b371b0b9309" dependencies = [ "anyhow", "cosmrs", @@ -897,13 +897,13 @@ dependencies = [ [[package]] name = "cw-orch-contract-derive" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94e9c3e46e2511c26d07da1fb5fcb47f83fa6d169dbb6eeff42c1b899b849726" +checksum = "5bc8ba75692fc7bd30e91c78fad2dc208a738e4e6ea26b232f9352c320e35543" dependencies = [ "convert_case", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -927,9 +927,9 @@ dependencies = [ [[package]] name = "cw-orch-daemon" -version = "0.22.0" +version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a457b6c10226854c69211e847b5402b557ad9ff4e2a4e35ec325bfdc6493c37b" +checksum = "ecd0348bed3813368a90c988dbfdb378d72f255ad886dd916aba63291c827603" dependencies = [ "anyhow", "async-recursion", @@ -967,9 +967,9 @@ dependencies = [ [[package]] name = "cw-orch-fns-derive" -version = "0.18.1" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6423cd853c9a4aa07cc0a92a179b99bd8f8f6c696a468e3ca2ecd2575905db21" +checksum = "e9acb7a15bfacc52abdf312a9fffb139883c1effb6ea7e645cd39580a8527463" dependencies = [ "convert_case", "proc-macro2", @@ -979,9 +979,9 @@ dependencies = [ [[package]] name = "cw-orch-mock" -version = "0.22.0" +version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad451fddf9a61db34c7c2fd0852a83238ffcada483dcacfac4622e9085df234f" +checksum = "6426c05377f8549d446ab5ca4a554cfb9f501eb5002edb9a73ceae7fd65822e1" dependencies = [ "abstract-cw-multi-test", "cosmwasm-std", @@ -1140,9 +1140,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" dependencies = [ "darling_core", "darling_macro", @@ -1150,26 +1150,26 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] name = "darling_macro" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -1179,7 +1179,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "lock_api", "once_cell", "parking_lot_core", @@ -1358,9 +1358,9 @@ dependencies = [ [[package]] name = "either" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "elliptic-curve" @@ -1428,7 +1428,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -1452,9 +1452,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -1478,9 +1478,9 @@ checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" [[package]] name = "fastrand" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "ff" @@ -1494,15 +1494,15 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38793c55593b33412e3ae40c2c9781ffaa6f438f6f8c10f24e71846fbd7ae01e" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" dependencies = [ "crc32fast", "miniz_oxide", @@ -1643,9 +1643,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "js-sys", @@ -1712,9 +1712,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "heck" @@ -1935,7 +1935,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -2007,9 +2007,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libredox" @@ -2023,15 +2023,15 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -2108,9 +2108,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" dependencies = [ "adler", ] @@ -2149,11 +2149,10 @@ checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389" [[package]] name = "native-tls" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" dependencies = [ - "lazy_static", "libc", "log", "openssl", @@ -2167,11 +2166,10 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" dependencies = [ - "autocfg", "num-integer", "num-traits", ] @@ -2201,7 +2199,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -2215,9 +2213,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -2276,7 +2274,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -2305,9 +2303,9 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -2315,22 +2313,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.5", ] [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pbkdf2" @@ -2343,9 +2341,9 @@ dependencies = [ [[package]] name = "peg" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "400bcab7d219c38abf8bd7cc2054eb9bbbd4312d66f6a5557d572a203f646f61" +checksum = "8a625d12ad770914cbf7eff6f9314c3ef803bfe364a1b20bc36ddf56673e71e5" dependencies = [ "peg-macros", "peg-runtime", @@ -2353,9 +2351,9 @@ dependencies = [ [[package]] name = "peg-macros" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46e61cce859b76d19090f62da50a9fe92bab7c2a5f09e183763559a2ac392c90" +checksum = "f241d42067ed3ab6a4fece1db720838e1418f36d868585a27931f95d6bc03582" dependencies = [ "peg-runtime", "proc-macro2", @@ -2364,9 +2362,9 @@ dependencies = [ [[package]] name = "peg-runtime" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36bae92c60fa2398ce4678b98b2c4b5a7c61099961ca1fa305aec04a9ad28922" +checksum = "e3aeb8f54c078314c2065ee649a7241f46b9d8e418e1a9581ba0546657d7aa3a" [[package]] name = "percent-encoding" @@ -2391,7 +2389,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -2466,18 +2464,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6" dependencies = [ "unicode-ident", ] [[package]] name = "prost" -version = "0.12.4" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0f5d036824e4761737860779c906171497f6d55681139d8312388f8fe398922" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ "bytes", "prost-derive", @@ -2485,22 +2483,22 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.12.4" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19de2de2a00075bf566bee3bd4db014b11587e84184d3f7a791bc17f1a8e9e48" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", "itertools", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] name = "prost-types" -version = "0.12.4" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3235c33eb02c1f1e212abdbe34c78b264b038fb58ca612664343271e36e55ffe" +checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" dependencies = [ "prost", ] @@ -2598,11 +2596,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", ] [[package]] @@ -2788,9 +2786,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-serialize" @@ -2822,9 +2820,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.11" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fecbfb7b1444f477b345853b1fce097a2c6fb637b2bfb87e6bc5db0f043fae4" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", "ring", @@ -2865,15 +2863,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -2895,9 +2893,9 @@ dependencies = [ [[package]] name = "schemars" -version = "0.8.16" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" +checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" dependencies = [ "dyn-clone", "schemars_derive", @@ -2907,14 +2905,14 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.16" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" +checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 1.0.109", + "syn 2.0.66", ] [[package]] @@ -2974,11 +2972,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", "core-foundation", "core-foundation-sys", "libc", @@ -2987,9 +2985,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" dependencies = [ "core-foundation-sys", "libc", @@ -2997,21 +2995,21 @@ dependencies = [ [[package]] name = "self_cell" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58bf37232d3bb9a2c4e641ca2a11d83b5062066f88df7fed36c28772046d65ba" +checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.198" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] @@ -3047,31 +3045,31 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.198" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] name = "serde_derive_internals" -version = "0.26.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.66", ] [[package]] name = "serde_json" -version = "1.0.116" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "itoa", "ryu", @@ -3086,7 +3084,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -3183,9 +3181,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", "windows-sys 0.52.0", @@ -3272,9 +3270,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.60" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -3457,22 +3455,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.59" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.59" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -3557,7 +3555,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -3593,16 +3591,15 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] @@ -3696,7 +3693,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -3837,7 +3834,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", "wasm-bindgen-shared", ] @@ -3894,7 +3891,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4329,9 +4326,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63381fa6624bf92130a6b87c0d07380116f80b565c42cf0d754136f0238359ef" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] @@ -4344,5 +4341,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] diff --git a/Cargo.toml b/Cargo.toml index 9308c791..80ce3561 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clone-cw-multi-test" -version = "0.1.0" +version = "0.2.0" authors = ["Ethan Frey "] edition = "2021" description = "Testing tools for multi-contract interactions. Helps simulating chain behavior with on-chain storage locally" @@ -36,7 +36,7 @@ thiserror = "1.0.50" # Clone testing deps ## Network -cw-orch = { version = "0.22.0", features = ["daemon"] } +cw-orch = { version = "0.22.2", features = ["daemon"] } tokio = "1.28.2" tonic = "0.10.2" diff --git a/src/queries/bank.rs b/src/queries/bank.rs index 8339c44f..65951bc1 100644 --- a/src/queries/bank.rs +++ b/src/queries/bank.rs @@ -1,7 +1,5 @@ -use std::str::FromStr; - use anyhow::Result as AnyResult; -use cosmwasm_std::{Addr, Coin, Uint128}; +use cosmwasm_std::{Addr, Coin}; use crate::wasm_emulation::channel::RemoteChannel; @@ -13,19 +11,8 @@ impl BankRemoteQuerier { channel: remote.channel, rt_handle: Some(remote.rt.clone()), }; - let distant_amounts: Vec = remote - .rt - .block_on(querier._balance(account, None)) - .map(|result| { - result - .into_iter() - .map(|c| Coin { - amount: Uint128::from_str(&c.amount).unwrap(), - denom: c.denom, - }) - .collect() - }) - .unwrap(); + let distant_amounts: Vec = + remote.rt.block_on(querier._balance(account, None)).unwrap(); Ok(distant_amounts) } } diff --git a/src/queries/wasm.rs b/src/queries/wasm.rs index e5cf57f0..62617b67 100644 --- a/src/queries/wasm.rs +++ b/src/queries/wasm.rs @@ -21,11 +21,7 @@ impl WasmRemoteQuerier { }; let code_info = remote.rt.block_on(wasm_querier._code(code_id))?; - let mut res = cosmwasm_std::CodeInfoResponse::default(); - res.code_id = code_id; - res.creator = code_info.creator.to_string(); - res.checksum = code_info.data_hash.into(); - Ok(res) + Ok(code_info) } pub fn load_distant_contract(remote: RemoteChannel, address: &Addr) -> AnyResult { @@ -39,16 +35,9 @@ impl WasmRemoteQuerier { .block_on(wasm_querier._contract_info(address.clone()))?; Ok(ContractData { - admin: { - match code_info.admin.as_str() { - "" => None, - a => Some(Addr::unchecked(a)), - } - }, + admin: code_info.admin.map(Addr::unchecked), code_id: code_info.code_id, - created: code_info.created.unwrap().block_height, creator: Addr::unchecked(code_info.creator), - label: code_info.label, }) } diff --git a/src/wasm.rs b/src/wasm.rs index 8d84dc61..0913547b 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -65,10 +65,6 @@ pub struct ContractData { pub creator: Addr, /// Optional address of account who can execute migrations pub admin: Option, - /// Metadata passed while contract instantiation - pub label: String, - /// Blockchain height in the moment of instantiating the contract - pub created: u64, } #[derive(Serialize, Deserialize, Debug, Clone)] @@ -973,8 +969,8 @@ where code_id: u64, creator: Addr, admin: impl Into>, - label: String, - created: u64, + _label: String, + _created: u64, salt: impl Into>, ) -> AnyResult { // We don't error if the code id doesn't exist, it allows us to instantiate remote contracts @@ -1009,8 +1005,6 @@ where code_id, creator, admin: admin.into(), - label, - created, }; self.save_contract(storage, &addr, &info)?; Ok(addr) diff --git a/src/wasm_emulation/query/bank.rs b/src/wasm_emulation/query/bank.rs index 946472a9..87ea1b27 100644 --- a/src/wasm_emulation/query/bank.rs +++ b/src/wasm_emulation/query/bank.rs @@ -3,7 +3,6 @@ use crate::wasm_emulation::query::gas::{GAS_COST_ALL_BALANCE_QUERY, GAS_COST_BAL use crate::wasm_emulation::query::mock_querier::QueryResultWithGas; use cosmwasm_std::Addr; use cosmwasm_vm::GasInfo; -use std::str::FromStr; use cw_utils::NativeBalance; @@ -87,11 +86,9 @@ impl BankQuerier { let query_result = self .remote .rt - .block_on(querier._balance(address, Some(denom.clone()))) - .map(|result| Uint128::from_str(&result[0].amount).unwrap()); - + .block_on(querier._balance(address, Some(denom.clone()))); if let Ok(distant_amount) = query_result { - amount = Some(distant_amount) + amount = Some(distant_amount[0].amount) } } @@ -113,19 +110,8 @@ impl BankQuerier { channel: self.remote.channel.clone(), rt_handle: Some(self.remote.rt.clone()), }; - let query_result: Result, _> = self - .remote - .rt - .block_on(querier._balance(address, None)) - .map(|result| { - result - .into_iter() - .map(|c| Coin { - amount: Uint128::from_str(&c.amount).unwrap(), - denom: c.denom, - }) - .collect() - }); + let query_result: Result, _> = + self.remote.rt.block_on(querier._balance(address, None)); if let Ok(distant_amount) = query_result { amount = Some(distant_amount) } From 1b80625fe41ed08f3ee716852ce98e01bb6daefa Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 25 Jun 2024 14:10:28 +0000 Subject: [PATCH 44/81] added stabilized chain info --- Cargo.lock | 2 +- Cargo.toml | 2 +- examples/cavern_test_app.rs | 24 ++++++++---------------- examples/cousin_test.rs | 16 +++------------- examples/test_app.rs | 16 ++++------------ src/wasm_emulation/channel.rs | 15 +++++++++++++-- 6 files changed, 30 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a46f70bf..a9ba612d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -410,7 +410,7 @@ dependencies = [ [[package]] name = "clone-cw-multi-test" -version = "0.2.0" +version = "0.3.0" dependencies = [ "anyhow", "bech32 0.9.1", diff --git a/Cargo.toml b/Cargo.toml index 80ce3561..b9c4c6b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clone-cw-multi-test" -version = "0.2.0" +version = "0.3.0" authors = ["Ethan Frey "] edition = "2021" description = "Testing tools for multi-contract interactions. Helps simulating chain behavior with on-chain storage locally" diff --git a/examples/cavern_test_app.rs b/examples/cavern_test_app.rs index b128f117..2c255033 100644 --- a/examples/cavern_test_app.rs +++ b/examples/cavern_test_app.rs @@ -1,18 +1,16 @@ -use anyhow::Result as AnyResult; -use clone_cw_multi_test::{addons::{MockAddressGenerator, MockApiBech32}, wasm_emulation::{ +use clone_cw_multi_test::{ + addons::{MockAddressGenerator, MockApiBech32}, + wasm_emulation::{ channel::RemoteChannel, contract::WasmContract, storage::analyzer::StorageAnalyzer, - }, AppBuilder, BankKeeper, Executor, WasmKeeper}; + }, + AppBuilder, BankKeeper, Executor, WasmKeeper, +}; use cosmwasm_schema::{cw_serde, QueryResponses}; use cosmwasm_std::{coins, Addr, BlockInfo, ContractInfoResponse, QueryRequest, WasmQuery}; use cw20::BalanceResponse; -use cw_orch::{ - daemon::{networks::PHOENIX_1, queriers::Node, GrpcChannel}, - environment::ChainInfoOwned, -}; +use cw_orch::daemon::{networks::PHOENIX_1, queriers::Node}; use std::path::Path; -use tokio::runtime::Handle; use tokio::runtime::Runtime; -use tonic::transport::Channel; use cw20::Cw20QueryMsg; @@ -50,12 +48,6 @@ pub struct InstantiateMsg { /// END CONTRACT MSGs -fn get_channel(chain: impl Into, rt: Handle) -> AnyResult { - let chain = chain.into(); - let channel = rt.block_on(GrpcChannel::connect(&chain.grpc_urls, &chain.chain_id))?; - Ok(channel) -} - pub fn test() -> anyhow::Result<()> { env_logger::init(); @@ -68,7 +60,7 @@ pub fn test() -> anyhow::Result<()> { let chain = PHOENIX_1; let remote_channel = RemoteChannel::new( &runtime, - get_channel(chain.clone(), runtime.handle().clone())?, + chain.clone(), chain.network_info.pub_address_prefix, )?; diff --git a/examples/cousin_test.rs b/examples/cousin_test.rs index b767dc5a..563c27e9 100644 --- a/examples/cousin_test.rs +++ b/examples/cousin_test.rs @@ -11,21 +11,11 @@ use clone_cw_multi_test::{ }; use cosmwasm_std::{Addr, Empty}; use counter::msg::{ExecuteMsg, GetCountResponse, QueryMsg}; -use cw_orch::{ - daemon::{networks::PHOENIX_1, GrpcChannel}, - environment::ChainInfoOwned, -}; -use tokio::runtime::{Handle, Runtime}; -use tonic::transport::Channel; +use cw_orch::daemon::networks::PHOENIX_1; +use tokio::runtime::Runtime; mod counter; -fn get_channel(chain: impl Into, rt: Handle) -> AnyResult { - let chain = chain.into(); - let channel = rt.block_on(GrpcChannel::connect(&chain.grpc_urls, &chain.chain_id))?; - Ok(channel) -} - pub const SENDER: &str = "terra17c6ts8grcfrgquhj3haclg44le8s7qkx6l2yx33acguxhpf000xqhnl3je"; fn increment(app: &mut App, contract: Addr) -> AnyResult<()> { let sender = Addr::unchecked(SENDER); @@ -82,7 +72,7 @@ fn test() -> AnyResult<()> { let chain = PHOENIX_1; let remote_channel = RemoteChannel::new( &runtime, - get_channel(chain.clone(), runtime.handle().clone())?, + chain.clone(), chain.network_info.pub_address_prefix, )?; diff --git a/examples/test_app.rs b/examples/test_app.rs index 81a792a4..160e7cc1 100644 --- a/examples/test_app.rs +++ b/examples/test_app.rs @@ -1,5 +1,6 @@ -use anyhow::Result as AnyResult; -use clone_cw_multi_test::{wasm_emulation::channel::RemoteChannel, AppBuilder, BankKeeper, Executor, WasmKeeper}; +use clone_cw_multi_test::{ + wasm_emulation::channel::RemoteChannel, AppBuilder, BankKeeper, Executor, WasmKeeper, +}; use cosmwasm_std::Addr; use cw20::AllAccountsResponse; use cw20::Cw20ExecuteMsg; @@ -8,20 +9,11 @@ use cw20::Cw20QueryMsg; use cw_orch::daemon::networks::PHOENIX_1; use cosmwasm_std::Empty; -use cw_orch::daemon::GrpcChannel; -use cw_orch::environment::ChainInfoOwned; -use tokio::runtime::Handle; use tokio::runtime::Runtime; -use tonic::transport::Channel; pub fn main() { test().unwrap() } -fn get_channel(chain: impl Into, rt: Handle) -> AnyResult { - let chain = chain.into(); - let channel = rt.block_on(GrpcChannel::connect(&chain.grpc_urls, &chain.chain_id))?; - Ok(channel) -} pub fn test() -> anyhow::Result<()> { env_logger::init(); @@ -30,7 +22,7 @@ pub fn test() -> anyhow::Result<()> { let chain = PHOENIX_1; let remote_channel = RemoteChannel::new( &runtime, - get_channel(chain.clone(), runtime.handle().clone())?, + chain.clone(), chain.network_info.pub_address_prefix, )?; let wasm = WasmKeeper::::new().with_remote(remote_channel.clone()); diff --git a/src/wasm_emulation/channel.rs b/src/wasm_emulation/channel.rs index 7bf1cd69..3e132f13 100644 --- a/src/wasm_emulation/channel.rs +++ b/src/wasm_emulation/channel.rs @@ -1,7 +1,18 @@ use anyhow::Result as AnyResult; +use cw_orch::{daemon::GrpcChannel, environment::ChainInfoOwned}; use tokio::runtime::{Handle, Runtime}; use tonic::transport::Channel; +/// Simple helper to get the GRPC transport channel +fn get_channel( + chain: impl Into, + rt: &Runtime, +) -> anyhow::Result { + let chain = chain.into(); + let channel = rt.block_on(GrpcChannel::connect(&chain.grpc_urls, &chain.chain_id))?; + Ok(channel) +} + #[derive(Clone)] pub struct RemoteChannel { pub rt: Handle, @@ -12,12 +23,12 @@ pub struct RemoteChannel { impl RemoteChannel { pub fn new( rt: &Runtime, - channel: Channel, + chain: impl Into, pub_address_prefix: impl Into, ) -> AnyResult { Ok(Self { rt: rt.handle().clone(), - channel, + channel: get_channel(chain, rt)?, pub_address_prefix: pub_address_prefix.into(), }) } From a325e85fc83fa6e59ea869615dbb38a21429285e Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 25 Jun 2024 14:18:21 +0000 Subject: [PATCH 45/81] Version --- Cargo.lock | 209 +++++++++++++++++++++++++++-------------------------- Cargo.toml | 4 +- 2 files changed, 110 insertions(+), 103 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a9ba612d..856fea54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,11 +29,11 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ - "gimli 0.28.1", + "gimli 0.29.0", ] [[package]] @@ -100,7 +100,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -122,7 +122,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -133,7 +133,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -189,9 +189,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.71" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ "addr2line", "cc", @@ -290,9 +290,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bitvec" @@ -384,9 +384,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.98" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" +checksum = "c891175c3fb232128f48de6590095e59198bbeb8620c310be349bfc3afd12c7b" [[package]] name = "cfg-if" @@ -410,7 +410,7 @@ dependencies = [ [[package]] name = "clone-cw-multi-test" -version = "0.3.0" +version = "0.4.0" dependencies = [ "anyhow", "bech32 0.9.1", @@ -816,16 +816,15 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.2" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", - "platforms", "rustc_version", "subtle", "zeroize", @@ -839,7 +838,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -872,9 +871,9 @@ dependencies = [ [[package]] name = "cw-orch" -version = "0.22.2" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1ddc937c28c59ccf2765fa05ddc0437644d3b283408a7cc64f7b371b0b9309" +checksum = "97c76d9dd1c2632359f964e3531e5d0833d9022ae9fb216ce9aaaf36070d8bdf" dependencies = [ "anyhow", "cosmrs", @@ -903,19 +902,20 @@ checksum = "5bc8ba75692fc7bd30e91c78fad2dc208a738e4e6ea26b232f9352c320e35543" dependencies = [ "convert_case", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] name = "cw-orch-core" -version = "1.0.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c8e62b4d04699596bc2f45c57a8e5459495584d8127588ae4bbe7f95d616b61" +checksum = "b60b3a78e06f38cc7d23127489f356b357d795df8c62090bc66c759f875cbc5f" dependencies = [ "abstract-cw-multi-test", "anyhow", "cosmos-sdk-proto 0.21.1", "cosmwasm-std", + "cw-storage-plus 1.2.0", "cw-utils 1.0.3", "dirs", "log", @@ -927,9 +927,9 @@ dependencies = [ [[package]] name = "cw-orch-daemon" -version = "0.22.2" +version = "0.23.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd0348bed3813368a90c988dbfdb378d72f255ad886dd916aba63291c827603" +checksum = "3da5ddf3e3d51a72acdca54aaa89a3828bb26b720648b3c10bd9ec5cefc7c49c" dependencies = [ "anyhow", "async-recursion", @@ -945,14 +945,17 @@ dependencies = [ "dirs", "ed25519-dalek", "eyre", + "file-lock", "flate2", "hex", "hkd32", "lazy_static", "log", + "once_cell", "prost", "prost-types", "rand_core 0.6.4", + "regex", "reqwest", "ring", "ripemd", @@ -967,9 +970,9 @@ dependencies = [ [[package]] name = "cw-orch-fns-derive" -version = "0.19.1" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9acb7a15bfacc52abdf312a9fffb139883c1effb6ea7e645cd39580a8527463" +checksum = "e85c3dea0893dd742c33ede8b4becdfb19b458e86e006ecf9a09ed66331d0c85" dependencies = [ "convert_case", "proc-macro2", @@ -979,9 +982,9 @@ dependencies = [ [[package]] name = "cw-orch-mock" -version = "0.22.2" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6426c05377f8549d446ab5ca4a554cfb9f501eb5002edb9a73ceae7fd65822e1" +checksum = "2ae9536620b86ee78c2729fd8449538feb4f6257a9809c72c5f9e461e720cf3b" dependencies = [ "abstract-cw-multi-test", "cosmwasm-std", @@ -994,9 +997,9 @@ dependencies = [ [[package]] name = "cw-orch-networks" -version = "0.22.0" +version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7557d86fb243aabf48d4358dec24b27b3fb4a4e7283ad384ae267dc9dbc2a5d4" +checksum = "8867122381950dc06eab95544e94b62660a74743dc1586d9eeb653a40c4c2beb" dependencies = [ "cw-orch-core", "serde", @@ -1158,7 +1161,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1169,7 +1172,7 @@ checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1333,7 +1336,7 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "ed25519", "serde", "sha2 0.10.8", @@ -1428,7 +1431,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1498,6 +1501,16 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" +[[package]] +name = "file-lock" +version = "2.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "040b48f80a749da50292d0f47a1e2d5bf1d772f52836c07f64bfccc62ba6e664" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "flate2" version = "1.0.30" @@ -1667,9 +1680,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "group" @@ -1794,9 +1807,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" @@ -1812,9 +1825,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.28" +version = "0.14.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "f361cde2f109281a220d4307746cdfd5ee3f410da58a70377762396775634b33" dependencies = [ "bytes", "futures-channel", @@ -1995,9 +2008,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "leb128" @@ -2017,7 +2030,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", ] @@ -2069,9 +2082,9 @@ checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" @@ -2108,9 +2121,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", ] @@ -2199,7 +2212,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -2232,9 +2245,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" dependencies = [ "memchr", ] @@ -2257,7 +2270,7 @@ version = "0.10.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg-if", "foreign-types", "libc", @@ -2274,7 +2287,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -2389,7 +2402,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -2420,12 +2433,6 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" -[[package]] -name = "platforms" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7" - [[package]] name = "powerfmt" version = "0.2.0" @@ -2464,9 +2471,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.84" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -2491,7 +2498,7 @@ dependencies = [ "itertools", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -2596,11 +2603,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] @@ -2628,9 +2635,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.4" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", @@ -2640,9 +2647,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -2651,9 +2658,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "region" @@ -2811,7 +2818,7 @@ version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -2912,7 +2919,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -2976,7 +2983,7 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -3036,9 +3043,9 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.14" +version = "0.11.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" dependencies = [ "serde", ] @@ -3051,7 +3058,7 @@ checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3062,14 +3069,14 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4" dependencies = [ "itoa", "ryu", @@ -3084,7 +3091,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3238,9 +3245,9 @@ dependencies = [ [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "subtle-encoding" @@ -3270,9 +3277,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.66" +version = "2.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" dependencies = [ "proc-macro2", "quote", @@ -3470,7 +3477,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3505,9 +3512,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "c55115c6fbe2d2bef26eb09ad74bde02d8255476fc0c7b515ef09fbb35742d82" dependencies = [ "tinyvec_macros", ] @@ -3520,9 +3527,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.37.0" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ "backtrace", "bytes", @@ -3549,13 +3556,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3693,7 +3700,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3761,9 +3768,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", @@ -3772,9 +3779,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.8.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439" [[package]] name = "vcpkg" @@ -3834,7 +3841,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "wasm-bindgen-shared", ] @@ -3891,7 +3898,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4341,5 +4348,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] diff --git a/Cargo.toml b/Cargo.toml index b9c4c6b9..30122991 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clone-cw-multi-test" -version = "0.3.0" +version = "0.4.0" authors = ["Ethan Frey "] edition = "2021" description = "Testing tools for multi-contract interactions. Helps simulating chain behavior with on-chain storage locally" @@ -36,7 +36,7 @@ thiserror = "1.0.50" # Clone testing deps ## Network -cw-orch = { version = "0.22.2", features = ["daemon"] } +cw-orch = { version = "0.23.0", features = ["daemon"] } tokio = "1.28.2" tonic = "0.10.2" From 4f491d295d6c5c135d89b4cdd42befa459a549fb Mon Sep 17 00:00:00 2001 From: s0c5 Date: Tue, 2 Jul 2024 08:49:24 -0500 Subject: [PATCH 46/81] feat: Add caching mechanism for wasm code responses --- src/wasm_emulation/contract.rs | 66 +++++++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 8 deletions(-) diff --git a/src/wasm_emulation/contract.rs b/src/wasm_emulation/contract.rs index 95514a67..a14360f5 100644 --- a/src/wasm_emulation/contract.rs +++ b/src/wasm_emulation/contract.rs @@ -38,6 +38,8 @@ use super::input::SudoArgs; use super::input::WasmFunction; use super::output::WasmOutput; use super::query::mock_querier::ForkState; +use std::env::var; +use std::fs; fn apply_storage_changes(storage: &mut dyn Storage, output: &WasmRunnerOutput) { // We change all the values with the output @@ -91,6 +93,38 @@ impl std::fmt::Debug for LocalWasmContract { } } +fn cache_reponse AnyResult>>(key: String, cb: F) -> AnyResult> { + let wasm_cache_enabled = var("WASM_CACHE").map(|e| e == "true").unwrap_or(true); + let cargo_target_dir = var("CARGO_TARGET_DIR").expect("CARGO_TARGET_DIR must be defined"); + let wasm_cache_dir = format!("{}/wasm_cache", cargo_target_dir); + + if !wasm_cache_enabled { + let code = cb()?; + return Ok(code); + } + + match fs::metadata(&wasm_cache_dir) { + Ok(d) => assert!(d.is_dir(), "it must be a directory"), + Err(_) => fs::create_dir(&wasm_cache_dir) + .expect("wasm_cache cant be created, please check permissions."), + } + + let cached_response_file = format!("{}/{}", wasm_cache_dir, key); + + match fs::metadata(&cached_response_file) { + Ok(cache) => { + assert!(cache.is_file(), "it must be a file"); + Ok(fs::read(&cached_response_file).expect("the file cant be read")) + } + Err(_) => { + let wasm = cb()?; + + fs::write(&cached_response_file, &wasm).expect("it must write the cache"); + Ok(wasm) + } + } +} + impl WasmContract { pub fn new_local(code: Vec) -> Self { check_wasm( @@ -129,10 +163,20 @@ impl WasmContract { .remote .rt .block_on(wasm_querier._contract_info(contract_addr))?; - let code = fork_state - .remote - .rt - .block_on(wasm_querier._code_data(code_info.code_id))?; + + let cache_key = format!( + "{}:{}", + fork_state.remote.pub_address_prefix, code_info.code_id + ); + + let code = cache_reponse(cache_key, || { + fork_state + .remote + .rt + .block_on(wasm_querier._code_data(code_info.code_id)) + .map_err(|e| e.into()) + })?; + Ok(code) } WasmContract::DistantCodeId(DistantCodeId { code_id }) => { @@ -141,10 +185,16 @@ impl WasmContract { rt_handle: Some(fork_state.remote.rt.clone()), }; - let code = fork_state - .remote - .rt - .block_on(wasm_querier._code_data(*code_id))?; + let cache_key = format!("{}:{}", fork_state.remote.pub_address_prefix, &code_id); + + let code = cache_reponse(cache_key, || { + fork_state + .remote + .rt + .block_on(wasm_querier._code_data(*code_id)) + .map_err(|e| e.into()) + })?; + Ok(code) } } From 7f1f02c45c729078579251551fdbcc205de9b289 Mon Sep 17 00:00:00 2001 From: Buckram Date: Thu, 4 Jul 2024 17:10:18 +0300 Subject: [PATCH 47/81] little bit refactor --- Cargo.lock | 36 +++++++++ Cargo.toml | 3 + examples/cavern_test_app.rs | 6 +- examples/cousin_test.rs | 6 +- examples/test_app.rs | 6 +- src/wasm_emulation/contract.rs | 135 +++++++++++++++++++++++---------- 6 files changed, 135 insertions(+), 57 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 856fea54..8cac7a1f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -382,6 +382,38 @@ dependencies = [ "serde", ] +[[package]] +name = "camino" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "cc" version = "1.0.100" @@ -414,6 +446,7 @@ version = "0.4.0" dependencies = [ "anyhow", "bech32 0.9.1", + "cargo_metadata", "cosmrs", "cosmwasm-schema", "cosmwasm-std", @@ -3011,6 +3044,9 @@ name = "semver" version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +dependencies = [ + "serde", +] [[package]] name = "serde" diff --git a/Cargo.toml b/Cargo.toml index 30122991..df60f0d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,6 +61,9 @@ wasmer = { version = "=4.2.2", default-features = false, features = [ "singlepass", ] } +# For finding Cargo target dir +cargo_metadata = "0.18" + [dev-dependencies] hex = "0.4.3" hex-literal = "0.4.1" diff --git a/examples/cavern_test_app.rs b/examples/cavern_test_app.rs index 2c255033..895e3b61 100644 --- a/examples/cavern_test_app.rs +++ b/examples/cavern_test_app.rs @@ -58,11 +58,7 @@ pub fn test() -> anyhow::Result<()> { let runtime = Runtime::new()?; let chain = PHOENIX_1; - let remote_channel = RemoteChannel::new( - &runtime, - chain.clone(), - chain.network_info.pub_address_prefix, - )?; + let remote_channel = RemoteChannel::new(&runtime, chain.clone())?; let wasm = WasmKeeper::::new() .with_remote(remote_channel.clone()) diff --git a/examples/cousin_test.rs b/examples/cousin_test.rs index 563c27e9..06b08cda 100644 --- a/examples/cousin_test.rs +++ b/examples/cousin_test.rs @@ -70,11 +70,7 @@ fn test() -> AnyResult<()> { let runtime = Runtime::new()?; let chain = PHOENIX_1; - let remote_channel = RemoteChannel::new( - &runtime, - chain.clone(), - chain.network_info.pub_address_prefix, - )?; + let remote_channel = RemoteChannel::new(&runtime, chain.clone())?; let wasm = WasmKeeper::::new() .with_remote(remote_channel.clone()) diff --git a/examples/test_app.rs b/examples/test_app.rs index 160e7cc1..d0260465 100644 --- a/examples/test_app.rs +++ b/examples/test_app.rs @@ -20,11 +20,7 @@ pub fn test() -> anyhow::Result<()> { let runtime = Runtime::new()?; let chain = PHOENIX_1; - let remote_channel = RemoteChannel::new( - &runtime, - chain.clone(), - chain.network_info.pub_address_prefix, - )?; + let remote_channel = RemoteChannel::new(&runtime, chain.clone())?; let wasm = WasmKeeper::::new().with_remote(remote_channel.clone()); let bank = BankKeeper::new().with_remote(remote_channel.clone()); diff --git a/src/wasm_emulation/contract.rs b/src/wasm_emulation/contract.rs index a14360f5..bce73afc 100644 --- a/src/wasm_emulation/contract.rs +++ b/src/wasm_emulation/contract.rs @@ -38,8 +38,6 @@ use super::input::SudoArgs; use super::input::WasmFunction; use super::output::WasmOutput; use super::query::mock_querier::ForkState; -use std::env::var; -use std::fs; fn apply_storage_changes(storage: &mut dyn Storage, output: &WasmRunnerOutput) { // We change all the values with the output @@ -93,38 +91,6 @@ impl std::fmt::Debug for LocalWasmContract { } } -fn cache_reponse AnyResult>>(key: String, cb: F) -> AnyResult> { - let wasm_cache_enabled = var("WASM_CACHE").map(|e| e == "true").unwrap_or(true); - let cargo_target_dir = var("CARGO_TARGET_DIR").expect("CARGO_TARGET_DIR must be defined"); - let wasm_cache_dir = format!("{}/wasm_cache", cargo_target_dir); - - if !wasm_cache_enabled { - let code = cb()?; - return Ok(code); - } - - match fs::metadata(&wasm_cache_dir) { - Ok(d) => assert!(d.is_dir(), "it must be a directory"), - Err(_) => fs::create_dir(&wasm_cache_dir) - .expect("wasm_cache cant be created, please check permissions."), - } - - let cached_response_file = format!("{}/{}", wasm_cache_dir, key); - - match fs::metadata(&cached_response_file) { - Ok(cache) => { - assert!(cache.is_file(), "it must be a file"); - Ok(fs::read(&cached_response_file).expect("the file cant be read")) - } - Err(_) => { - let wasm = cb()?; - - fs::write(&cached_response_file, &wasm).expect("it must write the cache"); - Ok(wasm) - } - } -} - impl WasmContract { pub fn new_local(code: Vec) -> Self { check_wasm( @@ -164,17 +130,14 @@ impl WasmContract { .rt .block_on(wasm_querier._contract_info(contract_addr))?; - let cache_key = format!( - "{}:{}", - fork_state.remote.pub_address_prefix, code_info.code_id - ); + let cache_key = format!("{}:{}", fork_state.remote.chain_id, code_info.code_id); - let code = cache_reponse(cache_key, || { + let code = wasm_caching::maybe_cached_wasm(cache_key, || { fork_state .remote .rt .block_on(wasm_querier._code_data(code_info.code_id)) - .map_err(|e| e.into()) + .map_err(Into::into) })?; Ok(code) @@ -185,9 +148,9 @@ impl WasmContract { rt_handle: Some(fork_state.remote.rt.clone()), }; - let cache_key = format!("{}:{}", fork_state.remote.pub_address_prefix, &code_id); + let cache_key = format!("{}:{}", fork_state.remote.chain_id, &code_id); - let code = cache_reponse(cache_key, || { + let code = wasm_caching::maybe_cached_wasm(cache_key, || { fork_state .remote .rt @@ -477,3 +440,91 @@ pub fn execute_function< } } } + +mod wasm_caching { + use super::*; + + use std::{env, fs, path::PathBuf}; + + use anyhow::{bail, Context}; + + const WASM_CACHE_DIR: &str = "wasm_cache"; + const WASM_CACHE_ENV: &str = "WASM_CACHE"; + + static CARGO_TARGET_DIR: std::sync::OnceLock = std::sync::OnceLock::new(); + + pub(crate) fn cargo_target_dir() -> &'static PathBuf { + CARGO_TARGET_DIR.get_or_init(|| { + cargo_metadata::MetadataCommand::new() + .no_deps() + .exec() + .unwrap() + .target_directory + .into() + }) + } + + /// Returns wasm bytes for the contract + /// + /// Will get cached wasm stored in `CARGO_TARGET_DIR` (./target/ from project root by default) + /// This feature can be disabled by setting wasm cache environment variable to `false`: `WASM_CACHE=false` + /// + /// # Arguments + /// + /// * `key` - A string key that represents unique id of the contract (usually chain-id:code_id) + /// * `wasm_code_bytes` - Function that returns non-cached version of the contract + /// + /// # Scenarios + /// + /// - Wasm caching disabled: return result of the `wasm_code_bytes` function + /// - Wasm file not found in cache location: return result of the `wasm_code_bytes` function, saving cache on on success + /// - Wasm stored in cache: return bytes + pub(crate) fn maybe_cached_wasm AnyResult>>( + key: String, + wasm_code_bytes: F, + ) -> AnyResult> { + let wasm_cache_enabled = env::var(WASM_CACHE_ENV) + .ok() + .and_then(|wasm_cache| wasm_cache.parse().ok()) + .unwrap_or(true); + + // Wasm caching disabled, return function result + if !wasm_cache_enabled { + return wasm_code_bytes(); + } + + let wasm_cache_dir = cargo_target_dir().join(WASM_CACHE_DIR); + // Prepare cache directory in `./target/` + // TODO: does those checks and error messages help in any way? Won't default fs errors return same information? + match fs::metadata(&wasm_cache_dir) { + // Verify it's dir + Ok(wasm_cache_metadata) => { + if !wasm_cache_metadata.is_dir() { + bail!("{WASM_CACHE_DIR} supposed to be directory") + } + } + // Error on checking cache dir, try to create it + Err(_) => fs::create_dir(&wasm_cache_dir) + .context("Wasm cache directory cannot be created, please check permissions")?, + } + + let cached_wasm_file = wasm_cache_dir.join(format!("{key}.wasm")); + let wasm_bytes = match fs::metadata(&cached_wasm_file) { + // Cache file exists, just read it + Ok(_) => { + // TODO: do we need this check? + // assert!(wasm_file_metadata.is_file(), "it must be a file"); + fs::read(&cached_wasm_file).context("unable to read wasm cache file")? + } + // Error on checking cache dir, download it and try to store it + Err(_) => { + let wasm = wasm_code_bytes()?; + + // TODO: Not critical, should we just log the write failure? + fs::write(&cached_wasm_file, &wasm).context("unable to write wasm cache file")?; + wasm + } + }; + Ok(wasm_bytes) + } +} From 333228c957b65f7ddbf4b2e5f921f6ce8a14b14b Mon Sep 17 00:00:00 2001 From: Buckram Date: Thu, 4 Jul 2024 17:10:31 +0300 Subject: [PATCH 48/81] remote channel only needs ChainInfo --- src/wasm_emulation/channel.rs | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/wasm_emulation/channel.rs b/src/wasm_emulation/channel.rs index 3e132f13..65b66bf5 100644 --- a/src/wasm_emulation/channel.rs +++ b/src/wasm_emulation/channel.rs @@ -4,11 +4,7 @@ use tokio::runtime::{Handle, Runtime}; use tonic::transport::Channel; /// Simple helper to get the GRPC transport channel -fn get_channel( - chain: impl Into, - rt: &Runtime, -) -> anyhow::Result { - let chain = chain.into(); +fn get_channel(chain: &ChainInfoOwned, rt: &Runtime) -> anyhow::Result { let channel = rt.block_on(GrpcChannel::connect(&chain.grpc_urls, &chain.chain_id))?; Ok(channel) } @@ -18,18 +14,18 @@ pub struct RemoteChannel { pub rt: Handle, pub channel: Channel, pub pub_address_prefix: String, + // For caching + pub chain_id: String, } impl RemoteChannel { - pub fn new( - rt: &Runtime, - chain: impl Into, - pub_address_prefix: impl Into, - ) -> AnyResult { + pub fn new(rt: &Runtime, chain: impl Into) -> AnyResult { + let chain: ChainInfoOwned = chain.into(); Ok(Self { rt: rt.handle().clone(), - channel: get_channel(chain, rt)?, - pub_address_prefix: pub_address_prefix.into(), + channel: get_channel(&chain, rt)?, + pub_address_prefix: chain.network_info.pub_address_prefix, + chain_id: chain.chain_id, }) } } From 1370ed6ecdd037af0a12a44ad447fdd24aac2656 Mon Sep 17 00:00:00 2001 From: Buckram Date: Thu, 4 Jul 2024 18:00:05 +0300 Subject: [PATCH 49/81] lock file while we writing to it --- Cargo.lock | 1 + Cargo.toml | 5 +++-- src/wasm_emulation/contract.rs | 23 +++++++++++++---------- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8cac7a1f..db415519 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -458,6 +458,7 @@ dependencies = [ "cw20 1.1.2", "derivative", "env_logger", + "file-lock", "hex", "hex-literal", "itertools", diff --git a/Cargo.toml b/Cargo.toml index df60f0d4..578f5859 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,8 +61,9 @@ wasmer = { version = "=4.2.2", default-features = false, features = [ "singlepass", ] } -# For finding Cargo target dir -cargo_metadata = "0.18" +# Caching +cargo_metadata = "0.18" # For finding Cargo target dir +file-lock = "2.1" [dev-dependencies] hex = "0.4.3" diff --git a/src/wasm_emulation/contract.rs b/src/wasm_emulation/contract.rs index bce73afc..39cfa583 100644 --- a/src/wasm_emulation/contract.rs +++ b/src/wasm_emulation/contract.rs @@ -444,7 +444,7 @@ pub fn execute_function< mod wasm_caching { use super::*; - use std::{env, fs, path::PathBuf}; + use std::{env, fs, io::Write, path::PathBuf}; use anyhow::{bail, Context}; @@ -495,7 +495,6 @@ mod wasm_caching { let wasm_cache_dir = cargo_target_dir().join(WASM_CACHE_DIR); // Prepare cache directory in `./target/` - // TODO: does those checks and error messages help in any way? Won't default fs errors return same information? match fs::metadata(&wasm_cache_dir) { // Verify it's dir Ok(wasm_cache_metadata) => { @@ -511,17 +510,21 @@ mod wasm_caching { let cached_wasm_file = wasm_cache_dir.join(format!("{key}.wasm")); let wasm_bytes = match fs::metadata(&cached_wasm_file) { // Cache file exists, just read it - Ok(_) => { - // TODO: do we need this check? - // assert!(wasm_file_metadata.is_file(), "it must be a file"); - fs::read(&cached_wasm_file).context("unable to read wasm cache file")? - } - // Error on checking cache dir, download it and try to store it + Ok(_) => fs::read(&cached_wasm_file).context("unable to read wasm cache file")?, + // Error on checking cache dir, get wasm bytes and try to cache it Err(_) => { let wasm = wasm_code_bytes()?; - // TODO: Not critical, should we just log the write failure? - fs::write(&cached_wasm_file, &wasm).context("unable to write wasm cache file")?; + // Save cache + // File is locked until content written to it + let options = file_lock::FileOptions::new().create(true).write(true); + if let Err(cache_save_err) = + file_lock::FileLock::lock(&cached_wasm_file, false, options) + .and_then(|mut file_lock| file_lock.file.write_all(&wasm)) + { + // It's not critical if it fails, as we already have wasm bytes, so we just log it + log::error!(target: "wasm_caching", "Failed to save wasm cache: {cache_save_err}") + } wasm } }; From 99fe520d2d7a9d3358aff29e0a70ab456ec8f327 Mon Sep 17 00:00:00 2001 From: Buckram Date: Thu, 4 Jul 2024 19:23:48 +0300 Subject: [PATCH 50/81] save caching status --- src/wasm_emulation/contract.rs | 129 ++++++++++++++++++++++++++++----- 1 file changed, 111 insertions(+), 18 deletions(-) diff --git a/src/wasm_emulation/contract.rs b/src/wasm_emulation/contract.rs index 39cfa583..6042d15e 100644 --- a/src/wasm_emulation/contract.rs +++ b/src/wasm_emulation/contract.rs @@ -444,7 +444,7 @@ pub fn execute_function< mod wasm_caching { use super::*; - use std::{env, fs, io::Write, path::PathBuf}; + use std::{env, fs, io::Read, os::unix::fs::FileExt, path::PathBuf}; use anyhow::{bail, Context}; @@ -464,6 +464,51 @@ mod wasm_caching { }) } + enum WasmCachingStatus { + /// Currently writing + Writing, + /// This wasm ready for use + Ready, + /// Writing to it have failed, it's not usable until valid cache written to it + Corrupted, + } + + impl From for u8 { + fn from(value: WasmCachingStatus) -> Self { + match value { + WasmCachingStatus::Writing => 0, + WasmCachingStatus::Ready => 1, + WasmCachingStatus::Corrupted => 2, + } + } + } + + impl From for WasmCachingStatus { + fn from(value: u8) -> Self { + match value { + 0 => WasmCachingStatus::Writing, + 1 => WasmCachingStatus::Ready, + 2 => WasmCachingStatus::Corrupted, + _ => unimplemented!(), + } + } + } + + impl WasmCachingStatus { + pub fn set_status(self, file: &fs::File) { + file.write_at(&[self.into()], 0) + .expect("Failed to update wasm caching status"); + } + + pub fn status(file: &fs::File) -> Self { + let buf = &mut [0]; + match file.read_at(buf, 0) { + Ok(_) => buf[0].into(), + Err(_) => WasmCachingStatus::Corrupted, + } + } + } + /// Returns wasm bytes for the contract /// /// Will get cached wasm stored in `CARGO_TARGET_DIR` (./target/ from project root by default) @@ -507,27 +552,75 @@ mod wasm_caching { .context("Wasm cache directory cannot be created, please check permissions")?, } - let cached_wasm_file = wasm_cache_dir.join(format!("{key}.wasm")); + let cached_wasm_file = wasm_cache_dir.join(key); let wasm_bytes = match fs::metadata(&cached_wasm_file) { - // Cache file exists, just read it - Ok(_) => fs::read(&cached_wasm_file).context("unable to read wasm cache file")?, - // Error on checking cache dir, get wasm bytes and try to cache it - Err(_) => { - let wasm = wasm_code_bytes()?; - - // Save cache - // File is locked until content written to it - let options = file_lock::FileOptions::new().create(true).write(true); - if let Err(cache_save_err) = - file_lock::FileLock::lock(&cached_wasm_file, false, options) - .and_then(|mut file_lock| file_lock.file.write_all(&wasm)) - { - // It's not critical if it fails, as we already have wasm bytes, so we just log it - log::error!(target: "wasm_caching", "Failed to save wasm cache: {cache_save_err}") + // Cache file exists, try to read it + Ok(_) => { + let mut file = + fs::File::open(&cached_wasm_file).context("unable to open wasm cache file")?; + // If someone is writing to it we need to wait, and then check again + // TODO: decide what is the best way to wait for it + let mut status = WasmCachingStatus::status(&file); + if let WasmCachingStatus::Writing = status { + let options = file_lock::FileOptions::new().read(true); + // Blocking lock until writer unlocks it + let file_lock = file_lock::FileLock::lock(&cached_wasm_file, true, options)?; + status = WasmCachingStatus::status(&file_lock.file); + file_lock.unlock()? + } + match status { + WasmCachingStatus::Ready => { + let mut buf = vec![]; + file.read_to_end(&mut buf) + .context("unable to open wasm cache file")?; + dbg!(&buf[0]); + buf + } + // Ready for read + // Corrupted, need to write new wasm + WasmCachingStatus::Corrupted => { + store_new_wasm(wasm_code_bytes, &cached_wasm_file)? + } + // Someone dropped file lock with caching status Writing it means it's corrupted + WasmCachingStatus::Writing => { + store_new_wasm(wasm_code_bytes, &cached_wasm_file)? + } } - wasm } + // Error on checking cache dir, get wasm bytes and try to cache it + Err(_) => store_new_wasm(wasm_code_bytes, &cached_wasm_file)?, }; Ok(wasm_bytes) } + + fn store_new_wasm AnyResult>>( + wasm_code_bytes: F, + cached_wasm_file: &PathBuf, + ) -> Result, anyhow::Error> { + let wasm = wasm_code_bytes()?; + let options = file_lock::FileOptions::new().create(true).write(true); + if let Err(cache_save_err) = file_lock::FileLock::lock(cached_wasm_file, false, options) + .and_then(|file_lock| { + // Set writing status + WasmCachingStatus::Writing.set_status(&file_lock.file); + + match file_lock.file.write_all_at(&wasm, 1) { + // Done writing, set ready status + Ok(()) => { + WasmCachingStatus::Ready.set_status(&file_lock.file); + Ok(()) + } + // Failed to write, set corrupted status + Err(e) => { + WasmCachingStatus::Corrupted.set_status(&file_lock.file); + Err(e) + } + } + }) + { + // It's not critical if it fails, as we already have wasm bytes, so we just log it + log::error!(target: "wasm_caching", "Failed to save wasm cache: {cache_save_err}") + } + Ok(wasm) + } } From b0e91f0cb3bcbdc48b213f5590314a148817d8c1 Mon Sep 17 00:00:00 2001 From: Buckram Date: Thu, 4 Jul 2024 19:27:51 +0300 Subject: [PATCH 51/81] move away from magic byte --- src/wasm_emulation/contract.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/wasm_emulation/contract.rs b/src/wasm_emulation/contract.rs index 6042d15e..a5965699 100644 --- a/src/wasm_emulation/contract.rs +++ b/src/wasm_emulation/contract.rs @@ -444,7 +444,12 @@ pub fn execute_function< mod wasm_caching { use super::*; - use std::{env, fs, io::Read, os::unix::fs::FileExt, path::PathBuf}; + use std::{ + env, fs, + io::{Read, Seek}, + os::unix::fs::FileExt, + path::PathBuf, + }; use anyhow::{bail, Context}; @@ -571,6 +576,7 @@ mod wasm_caching { match status { WasmCachingStatus::Ready => { let mut buf = vec![]; + file.seek(std::io::SeekFrom::Start(1))?; file.read_to_end(&mut buf) .context("unable to open wasm cache file")?; dbg!(&buf[0]); From eaad8c1e665f16a2dfca17c7992a86753d9a7282 Mon Sep 17 00:00:00 2001 From: Buckram Date: Thu, 4 Jul 2024 19:29:06 +0300 Subject: [PATCH 52/81] remove debug --- src/wasm_emulation/contract.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/wasm_emulation/contract.rs b/src/wasm_emulation/contract.rs index a5965699..ceeda364 100644 --- a/src/wasm_emulation/contract.rs +++ b/src/wasm_emulation/contract.rs @@ -579,7 +579,6 @@ mod wasm_caching { file.seek(std::io::SeekFrom::Start(1))?; file.read_to_end(&mut buf) .context("unable to open wasm cache file")?; - dbg!(&buf[0]); buf } // Ready for read From 9eeea80bfd29299bf92bc574e84e7d8fcaef14fe Mon Sep 17 00:00:00 2001 From: Buckram Date: Wed, 24 Jul 2024 16:40:01 +0300 Subject: [PATCH 53/81] bump to 0.24.0 cw-orch --- Cargo.lock | 54 +++++++++++-------- Cargo.toml | 4 +- src/queries/wasm.rs | 15 ++---- src/wasm_emulation/contract.rs | 12 ++--- src/wasm_emulation/query/mock_querier.rs | 4 +- src/wasm_emulation/storage/analyzer.rs | 8 +-- .../storage/dual_std_storage.rs | 13 ++--- src/wasm_emulation/storage/dual_storage.rs | 10 +--- 8 files changed, 55 insertions(+), 65 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 856fea54..55196394 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -220,6 +220,12 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "base64ct" version = "1.6.0" @@ -410,7 +416,7 @@ dependencies = [ [[package]] name = "clone-cw-multi-test" -version = "0.4.0" +version = "0.5.0" dependencies = [ "anyhow", "bech32 0.9.1", @@ -593,7 +599,7 @@ version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78c1556156fdf892a55cced6115968b961eaaadd6f724a2c2cb7d1e168e32dd3" dependencies = [ - "base64", + "base64 0.21.7", "bech32 0.9.1", "bnum", "cosmwasm-crypto", @@ -871,9 +877,9 @@ dependencies = [ [[package]] name = "cw-orch" -version = "0.23.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97c76d9dd1c2632359f964e3531e5d0833d9022ae9fb216ce9aaaf36070d8bdf" +checksum = "0c81cb500eb2f9be31a0f90c7ce66572ee4a790ffbae1c6b42ff2e3f9faf3479" dependencies = [ "anyhow", "cosmrs", @@ -907,9 +913,9 @@ dependencies = [ [[package]] name = "cw-orch-core" -version = "1.1.2" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b60b3a78e06f38cc7d23127489f356b357d795df8c62090bc66c759f875cbc5f" +checksum = "5abd640f67f655411542a3c148769270c7a9e63d4097c2dc4a1f6edf23b7a9b4" dependencies = [ "abstract-cw-multi-test", "anyhow", @@ -927,14 +933,14 @@ dependencies = [ [[package]] name = "cw-orch-daemon" -version = "0.23.5" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da5ddf3e3d51a72acdca54aaa89a3828bb26b720648b3c10bd9ec5cefc7c49c" +checksum = "86e6d5033f1bf9d32a6d1b11dd8e9b9ad5cb673c3621def8fe63fa1310eda520" dependencies = [ "anyhow", "async-recursion", "base16", - "base64", + "base64 0.22.1", "bitcoin", "chrono", "cosmrs", @@ -955,7 +961,6 @@ dependencies = [ "prost", "prost-types", "rand_core 0.6.4", - "regex", "reqwest", "ring", "ripemd", @@ -966,13 +971,14 @@ dependencies = [ "thiserror", "tokio", "tonic", + "uid", ] [[package]] name = "cw-orch-fns-derive" -version = "0.21.1" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e85c3dea0893dd742c33ede8b4becdfb19b458e86e006ecf9a09ed66331d0c85" +checksum = "b9e21b23116a0702f540d7fa3f16e8276682d860b589fed56259220ad59d768e" dependencies = [ "convert_case", "proc-macro2", @@ -982,9 +988,9 @@ dependencies = [ [[package]] name = "cw-orch-mock" -version = "0.22.4" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ae9536620b86ee78c2729fd8449538feb4f6257a9809c72c5f9e461e720cf3b" +checksum = "57beb30d841bde79df51c9402741ef926ca8ef7ecd3570aa180074f767ac04d3" dependencies = [ "abstract-cw-multi-test", "cosmwasm-std", @@ -997,9 +1003,9 @@ dependencies = [ [[package]] name = "cw-orch-networks" -version = "0.22.2" +version = "0.23.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8867122381950dc06eab95544e94b62660a74743dc1586d9eeb653a40c4c2beb" +checksum = "f6b0e1af56869ced61c25f509a0a40cddd028779d838441b70f4578a8d7c0253" dependencies = [ "cw-orch-core", "serde", @@ -1007,9 +1013,9 @@ dependencies = [ [[package]] name = "cw-orch-traits" -version = "0.22.0" +version = "0.23.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5959ce29e9d8a52594b47933a0a2736ea94dd9bf5e29b220cbdbe2b097f07c3a" +checksum = "70e6b81dc282724c9c6334a499f4867e575458e69fe5b99034d4f962860f3357" dependencies = [ "cw-orch-core", "prost", @@ -2689,7 +2695,7 @@ version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ - "base64", + "base64 0.21.7", "bytes", "encoding_rs", "futures-core", @@ -2855,7 +2861,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64", + "base64 0.21.7", ] [[package]] @@ -3627,7 +3633,7 @@ dependencies = [ "async-stream", "async-trait", "axum", - "base64", + "base64 0.21.7", "bytes", "h2", "http", @@ -3733,6 +3739,12 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "uid" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "281a11e4180ee68f8c06a7bf82d1be3c496e0debcadcc4576cc0b56132201edf" + [[package]] name = "unicode-bidi" version = "0.3.15" diff --git a/Cargo.toml b/Cargo.toml index 30122991..243477e2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clone-cw-multi-test" -version = "0.4.0" +version = "0.5.0" authors = ["Ethan Frey "] edition = "2021" description = "Testing tools for multi-contract interactions. Helps simulating chain behavior with on-chain storage locally" @@ -36,7 +36,7 @@ thiserror = "1.0.50" # Clone testing deps ## Network -cw-orch = { version = "0.23.0", features = ["daemon"] } +cw-orch = { version = "0.24.1", features = ["daemon"] } tokio = "1.28.2" tonic = "0.10.2" diff --git a/src/queries/wasm.rs b/src/queries/wasm.rs index 62617b67..15cfbd3c 100644 --- a/src/queries/wasm.rs +++ b/src/queries/wasm.rs @@ -15,20 +15,14 @@ pub struct WasmRemoteQuerier; impl WasmRemoteQuerier { pub fn code_info(remote: RemoteChannel, code_id: u64) -> AnyResult { - let wasm_querier = CosmWasm { - channel: remote.channel, - rt_handle: Some(remote.rt.clone()), - }; + let wasm_querier = CosmWasm::new_sync(remote.channel, &remote.rt); let code_info = remote.rt.block_on(wasm_querier._code(code_id))?; Ok(code_info) } pub fn load_distant_contract(remote: RemoteChannel, address: &Addr) -> AnyResult { - let wasm_querier = CosmWasm { - channel: remote.channel, - rt_handle: Some(remote.rt.clone()), - }; + let wasm_querier = CosmWasm::new_sync(remote.channel, &remote.rt); let code_info = remote .rt @@ -46,10 +40,7 @@ impl WasmRemoteQuerier { contract_addr: String, key: Binary, ) -> AnyResult> { - let wasm_querier = CosmWasm { - channel: remote.channel, - rt_handle: Some(remote.rt.clone()), - }; + let wasm_querier = CosmWasm::new_sync(remote.channel, &remote.rt); let query_result = remote .rt .block_on(wasm_querier._contract_raw_state(contract_addr, key.to_vec())) diff --git a/src/wasm_emulation/contract.rs b/src/wasm_emulation/contract.rs index 95514a67..fe711b26 100644 --- a/src/wasm_emulation/contract.rs +++ b/src/wasm_emulation/contract.rs @@ -120,10 +120,8 @@ impl WasmContract { match self { WasmContract::Local(LocalWasmContract { code, .. }) => Ok(code.clone()), WasmContract::DistantContract(DistantContract { contract_addr }) => { - let wasm_querier = CosmWasm { - channel: fork_state.remote.channel.clone(), - rt_handle: Some(fork_state.remote.rt.clone()), - }; + let wasm_querier = + CosmWasm::new_sync(fork_state.remote.channel.clone(), &fork_state.remote.rt); let code_info = fork_state .remote @@ -136,10 +134,8 @@ impl WasmContract { Ok(code) } WasmContract::DistantCodeId(DistantCodeId { code_id }) => { - let wasm_querier = CosmWasm { - channel: fork_state.remote.channel.clone(), - rt_handle: Some(fork_state.remote.rt.clone()), - }; + let wasm_querier = + CosmWasm::new_sync(fork_state.remote.channel.clone(), &fork_state.remote.rt); let code = fork_state .remote diff --git a/src/wasm_emulation/query/mock_querier.rs b/src/wasm_emulation/query/mock_querier.rs index 386bda23..3894f4f6 100644 --- a/src/wasm_emulation/query/mock_querier.rs +++ b/src/wasm_emulation/query/mock_querier.rs @@ -121,9 +121,9 @@ impl< self.staking = StakingQuerier::new(denom, validators, delegations); } - pub fn with_custom_handler(mut self, handler: CH) -> Self + pub fn with_custom_handler(mut self, handler: CH) -> Self where - CH: Fn(&QueryC) -> QueryResultWithGas, + CH: Fn(&QueryC) -> QueryResultWithGas + 'static, { self.custom_handler = Box::from(handler); self diff --git a/src/wasm_emulation/storage/analyzer.rs b/src/wasm_emulation/storage/analyzer.rs index 47036993..9f7d7310 100644 --- a/src/wasm_emulation/storage/analyzer.rs +++ b/src/wasm_emulation/storage/analyzer.rs @@ -138,10 +138,10 @@ impl StorageAnalyzer { } pub fn compare_all_readable_contract_storage(&self) { - let wasm_querier = cw_orch::daemon::queriers::CosmWasm { - channel: self.remote.channel.clone(), - rt_handle: Some(self.remote.rt.clone()), - }; + let wasm_querier = cw_orch::daemon::queriers::CosmWasm::new_sync( + self.remote.channel.clone(), + &self.remote.rt, + ); self.all_contract_storage() .into_iter() .for_each(|(contract_addr, key, value)| { diff --git a/src/wasm_emulation/storage/dual_std_storage.rs b/src/wasm_emulation/storage/dual_std_storage.rs index 526ffec6..9c21f545 100644 --- a/src/wasm_emulation/storage/dual_std_storage.rs +++ b/src/wasm_emulation/storage/dual_std_storage.rs @@ -64,10 +64,10 @@ impl<'i> Iterator for Iter<'i> { && (self.distant_iter.position == 0 || !self.distant_iter.key.clone().unwrap().is_empty()) { - let wasm_querier = CosmWasm { - channel: self.distant_iter.remote.channel.clone(), - rt_handle: Some(self.distant_iter.remote.rt.clone()), - }; + let wasm_querier = CosmWasm::new_sync( + self.distant_iter.remote.channel.clone(), + &self.distant_iter.remote.rt, + ); let new_keys = self .distant_iter .remote @@ -160,10 +160,7 @@ impl<'a> Storage for DualStorage<'a> { let mut value = self.local_storage.get(key); // If it's not available, we query it online if it was not removed locally if !self.removed_keys.contains(key) && value.as_ref().is_none() { - let wasm_querier = CosmWasm { - channel: self.remote.channel.clone(), - rt_handle: Some(self.remote.rt.clone()), - }; + let wasm_querier = CosmWasm::new_sync(self.remote.channel.clone(), &self.remote.rt); let distant_result = self.remote.rt.block_on( wasm_querier._contract_raw_state(self.contract_addr.clone(), key.to_vec()), diff --git a/src/wasm_emulation/storage/dual_storage.rs b/src/wasm_emulation/storage/dual_storage.rs index 7816f39e..e004fbf1 100644 --- a/src/wasm_emulation/storage/dual_storage.rs +++ b/src/wasm_emulation/storage/dual_storage.rs @@ -109,10 +109,7 @@ impl Storage for DualStorage { // If it's not available, we query it online if it was not removed locally if !self.removed_keys.contains(key) && value.as_ref().unwrap().is_none() { log::debug!(target: CLONE_TESTING_STORAGE_LOG, "Value not set locally, fetching remote key"); - let wasm_querier = CosmWasm { - channel: self.remote.channel.clone(), - rt_handle: Some(self.remote.rt.clone()), - }; + let wasm_querier = CosmWasm::new_sync(self.remote.channel.clone(), &self.remote.rt); let distant_result = self.remote.rt.block_on( wasm_querier._contract_raw_state(self.contract_addr.clone(), key.to_vec()), @@ -200,10 +197,7 @@ impl Storage for DualStorage { if iterator.distant_iter.position == iterator.distant_iter.data.len() && iterator.distant_iter.key.is_some() { - let wasm_querier = CosmWasm { - channel: self.remote.channel.clone(), - rt_handle: Some(self.remote.rt.clone()), - }; + let wasm_querier = CosmWasm::new_sync(self.remote.channel.clone(), &self.remote.rt); let new_keys = self .remote .rt From 482d306f3f3b7525fabc04013291602742f41c21 Mon Sep 17 00:00:00 2001 From: Buckram Date: Thu, 25 Jul 2024 09:01:50 +0300 Subject: [PATCH 54/81] make it compatible with crates clonetest --- examples/cavern_test_app.rs | 2 +- examples/cousin_test.rs | 2 +- examples/test_app.rs | 2 +- src/wasm_emulation/channel.rs | 6 +++++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/examples/cavern_test_app.rs b/examples/cavern_test_app.rs index 895e3b61..757a1aa3 100644 --- a/examples/cavern_test_app.rs +++ b/examples/cavern_test_app.rs @@ -58,7 +58,7 @@ pub fn test() -> anyhow::Result<()> { let runtime = Runtime::new()?; let chain = PHOENIX_1; - let remote_channel = RemoteChannel::new(&runtime, chain.clone())?; + let remote_channel = RemoteChannel::new(&runtime, chain.clone(), "")?; let wasm = WasmKeeper::::new() .with_remote(remote_channel.clone()) diff --git a/examples/cousin_test.rs b/examples/cousin_test.rs index 06b08cda..195b9768 100644 --- a/examples/cousin_test.rs +++ b/examples/cousin_test.rs @@ -70,7 +70,7 @@ fn test() -> AnyResult<()> { let runtime = Runtime::new()?; let chain = PHOENIX_1; - let remote_channel = RemoteChannel::new(&runtime, chain.clone())?; + let remote_channel = RemoteChannel::new(&runtime, chain.clone(), "")?; let wasm = WasmKeeper::::new() .with_remote(remote_channel.clone()) diff --git a/examples/test_app.rs b/examples/test_app.rs index d0260465..d9cacca6 100644 --- a/examples/test_app.rs +++ b/examples/test_app.rs @@ -20,7 +20,7 @@ pub fn test() -> anyhow::Result<()> { let runtime = Runtime::new()?; let chain = PHOENIX_1; - let remote_channel = RemoteChannel::new(&runtime, chain.clone())?; + let remote_channel = RemoteChannel::new(&runtime, chain.clone(), "")?; let wasm = WasmKeeper::::new().with_remote(remote_channel.clone()); let bank = BankKeeper::new().with_remote(remote_channel.clone()); diff --git a/src/wasm_emulation/channel.rs b/src/wasm_emulation/channel.rs index 65b66bf5..fb818e80 100644 --- a/src/wasm_emulation/channel.rs +++ b/src/wasm_emulation/channel.rs @@ -19,7 +19,11 @@ pub struct RemoteChannel { } impl RemoteChannel { - pub fn new(rt: &Runtime, chain: impl Into) -> AnyResult { + pub fn new( + rt: &Runtime, + chain: impl Into, + _: impl Into, + ) -> AnyResult { let chain: ChainInfoOwned = chain.into(); Ok(Self { rt: rt.handle().clone(), From eb94df4af97d66aefbac9fd225d80ed6075b47d6 Mon Sep 17 00:00:00 2001 From: Buckram Date: Thu, 25 Jul 2024 16:40:33 +0300 Subject: [PATCH 55/81] Try to get file-lock asap instead of waiting for wasm download --- src/wasm_emulation/contract.rs | 37 +++++++++++++++++----------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/src/wasm_emulation/contract.rs b/src/wasm_emulation/contract.rs index 7d57c1a8..b83571f5 100644 --- a/src/wasm_emulation/contract.rs +++ b/src/wasm_emulation/contract.rs @@ -598,27 +598,26 @@ mod wasm_caching { wasm_code_bytes: F, cached_wasm_file: &PathBuf, ) -> Result, anyhow::Error> { - let wasm = wasm_code_bytes()?; let options = file_lock::FileOptions::new().create(true).write(true); - if let Err(cache_save_err) = file_lock::FileLock::lock(cached_wasm_file, false, options) - .and_then(|file_lock| { - // Set writing status - WasmCachingStatus::Writing.set_status(&file_lock.file); - - match file_lock.file.write_all_at(&wasm, 1) { - // Done writing, set ready status - Ok(()) => { - WasmCachingStatus::Ready.set_status(&file_lock.file); - Ok(()) - } - // Failed to write, set corrupted status - Err(e) => { - WasmCachingStatus::Corrupted.set_status(&file_lock.file); - Err(e) - } + let file_lock_status = file_lock::FileLock::lock(cached_wasm_file, false, options); + let wasm = wasm_code_bytes()?; + if let Err(cache_save_err) = file_lock_status.and_then(|file_lock| { + // Set writing status + WasmCachingStatus::Writing.set_status(&file_lock.file); + + match file_lock.file.write_all_at(&wasm, 1) { + // Done writing, set ready status + Ok(()) => { + WasmCachingStatus::Ready.set_status(&file_lock.file); + Ok(()) + } + // Failed to write, set corrupted status + Err(e) => { + WasmCachingStatus::Corrupted.set_status(&file_lock.file); + Err(e) } - }) - { + } + }) { // It's not critical if it fails, as we already have wasm bytes, so we just log it log::error!(target: "wasm_caching", "Failed to save wasm cache: {cache_save_err}") } From c5da2d68fd25bc4f5838e4bf2d0570f6a12dbabf Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 3 Sep 2024 08:03:40 +0000 Subject: [PATCH 56/81] cosmwasm-2_0 compiles --- Cargo.lock | 1736 +++++++++++++---- Cargo.toml | 29 +- src/bank.rs | 4 +- src/checksums.rs | 17 +- src/contracts.rs | 8 +- src/executor.rs | 1 + src/queries/wasm.rs | 6 +- src/staking.rs | 99 +- src/wasm.rs | 47 +- src/wasm_emulation/api/mod.rs | 49 +- src/wasm_emulation/contract.rs | 12 +- src/wasm_emulation/query/bank.rs | 22 +- src/wasm_emulation/query/mock_querier.rs | 7 + src/wasm_emulation/query/staking.rs | 16 +- src/wasm_emulation/query/wasm.rs | 8 +- src/wasm_emulation/storage/analyzer.rs | 10 +- .../storage/dual_std_storage.rs | 17 +- src/wasm_emulation/storage/dual_storage.rs | 15 +- 18 files changed, 1542 insertions(+), 561 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 55196394..dbb9b53c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,22 +4,22 @@ version = 3 [[package]] name = "abstract-cw-multi-test" -version = "1.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c77f8d4bac08f74fbc4fce8943cb2d35e742682b6cae8cb65555d6cd3830feb" +checksum = "f07e6d76b28a73f2c74c610d4451cd9bcdf02ffa1a2839161f9209a89af25135" dependencies = [ "anyhow", "bech32 0.11.0", - "cosmwasm-schema", - "cosmwasm-std", - "cw-storage-plus 1.2.0", - "cw-utils 1.0.3", + "cosmwasm-schema 2.1.3", + "cosmwasm-std 2.1.3", + "cw-storage-plus 2.0.0", + "cw-utils 2.0.0", "cw20-ics20", "derivative", "hex", - "itertools", + "itertools 0.13.0", "log", - "prost", + "prost 0.12.6", "schemars", "serde", "serde_json", @@ -42,6 +42,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "ahash" version = "0.7.8" @@ -53,6 +59,18 @@ dependencies = [ "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 = "aho-corasick" version = "1.1.3" @@ -62,6 +80,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + [[package]] name = "android-tzdata" version = "0.1.1" @@ -86,6 +110,127 @@ dependencies = [ "backtrace", ] +[[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 0.10.5", + "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 0.10.7", + "itertools 0.10.5", + "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 0.10.7", + "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" @@ -136,6 +281,12 @@ dependencies = [ "syn 2.0.68", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" version = "1.3.0" @@ -144,18 +295,17 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "axum" -version = "0.6.20" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" +checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" dependencies = [ "async-trait", "axum-core", - "bitflags 1.3.2", "bytes", "futures-util", - "http", - "http-body", - "hyper", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", "itoa", "matchit", "memchr", @@ -164,7 +314,7 @@ dependencies = [ "pin-project-lite", "rustversion", "serde", - "sync_wrapper", + "sync_wrapper 1.0.1", "tower", "tower-layer", "tower-service", @@ -172,17 +322,20 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.3.4" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" dependencies = [ "async-trait", "bytes", "futures-util", - "http", - "http-body", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", "mime", + "pin-project-lite", "rustversion", + "sync_wrapper 0.1.2", "tower-layer", "tower-service", ] @@ -197,7 +350,7 @@ dependencies = [ "cc", "cfg-if", "libc", - "miniz_oxide", + "miniz_oxide 0.7.4", "object", "rustc-demangle", ] @@ -214,6 +367,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +[[package]] +name = "base58ck" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c8d66485a3a2ea485c1913c4572ce0256067a5377ac8c75c4960e1cda98605f" +dependencies = [ + "bitcoin-internals", + "bitcoin_hashes 0.14.0", +] + [[package]] name = "base64" version = "0.21.7" @@ -262,23 +425,48 @@ dependencies = [ [[package]] name = "bitcoin" -version = "0.30.2" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1945a5048598e4189e239d3f809b19bdad4845c4b2ba400d304d2dcf26d2c462" +checksum = "ea507acc1cd80fc084ace38544bbcf7ced7c2aa65b653b102de0ce718df668f6" dependencies = [ - "bech32 0.9.1", - "bitcoin-private", - "bitcoin_hashes", + "base58ck", + "bech32 0.11.0", + "bitcoin-internals", + "bitcoin-io", + "bitcoin-units", + "bitcoin_hashes 0.14.0", + "hex-conservative", "hex_lit", "secp256k1", ] +[[package]] +name = "bitcoin-internals" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30bdbe14aa07b06e6cfeffc529a1f099e5fbe249524f8125358604df99a4bed2" + +[[package]] +name = "bitcoin-io" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "340e09e8399c7bd8912f495af6aa58bea0c9214773417ffaa8f6460f93aaee56" + [[package]] name = "bitcoin-private" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73290177011694f38ec25e165d0387ab7ea749a4b81cd4c80dae5988229f7a57" +[[package]] +name = "bitcoin-units" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5285c8bcaa25876d07f37e3d30c303f2609179716e11d688f51e8f1fe70063e2" +dependencies = [ + "bitcoin-internals", +] + [[package]] name = "bitcoin_hashes" version = "0.12.0" @@ -288,6 +476,16 @@ dependencies = [ "bitcoin-private", ] +[[package]] +name = "bitcoin_hashes" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" +dependencies = [ + "bitcoin-io", + "hex-conservative", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -336,6 +534,12 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56953345e39537a3e18bdaeba4cb0c58a78c1f61f361dc0fa7c5c7340ae87c5f" +[[package]] +name = "bnum" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e31ea183f6ee62ac8b8a8cf7feddd766317adfb13ff469de57ce033efd6a790" + [[package]] name = "bs58" version = "0.5.1" @@ -388,6 +592,15 @@ dependencies = [ "serde", ] +[[package]] +name = "bytesize" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e368af43e418a04d52505cf3dbc23dda4e3407ae2fa99fd0e4f308ce546acc" +dependencies = [ + "serde", +] + [[package]] name = "cc" version = "1.0.100" @@ -411,7 +624,7 @@ dependencies = [ "js-sys", "num-traits", "wasm-bindgen", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -421,24 +634,24 @@ dependencies = [ "anyhow", "bech32 0.9.1", "cosmrs", - "cosmwasm-schema", - "cosmwasm-std", + "cosmwasm-schema 2.1.3", + "cosmwasm-std 2.1.3", "cosmwasm-vm", "cw-orch", - "cw-storage-plus 1.2.0", - "cw-utils 1.0.3", - "cw2 1.1.2", - "cw20 1.1.2", + "cw-storage-plus 2.0.0", + "cw-utils 2.0.0", + "cw2 2.0.0", + "cw20 2.0.0", "derivative", "env_logger", "hex", "hex-literal", - "itertools", + "itertools 0.12.1", "log", "moneymarket", "num-bigint", "once_cell", - "prost", + "prost 0.13.2", "rustc-serialize", "schemars", "serde", @@ -503,35 +716,23 @@ dependencies = [ [[package]] name = "cosmos-sdk-proto" -version = "0.20.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32560304ab4c365791fd307282f76637213d8083c1a98490c35159cd67852237" +checksum = "1d0afc4daf81936e6ef5a2cf76f00c913ba5bc385d58ae1e09644e25d16b0381" dependencies = [ - "prost", - "prost-types", - "tendermint-proto 0.34.1", + "prost 0.13.2", + "tendermint-proto", "tonic", ] -[[package]] -name = "cosmos-sdk-proto" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e23f6ab56d5f031cde05b8b82a5fefd3a1a223595c79e32317a97189e612bc" -dependencies = [ - "prost", - "prost-types", - "tendermint-proto 0.35.0", -] - [[package]] name = "cosmrs" -version = "0.15.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47126f5364df9387b9d8559dcef62e99010e1d4098f39eb3f7ee4b5c254e40ea" +checksum = "af28a0ee4149da7cea0486fd7e3fbddea7dd81625279fdc521141ffb07fbd482" dependencies = [ "bip32", - "cosmos-sdk-proto 0.20.0", + "cosmos-sdk-proto", "ecdsa", "eyre", "k256", @@ -546,17 +747,45 @@ dependencies = [ "tokio", ] +[[package]] +name = "cosmwasm-core" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d905990ef3afb5753bb709dc7de88e9e370aa32bcc2f31731d4b533b63e82490" + [[package]] name = "cosmwasm-crypto" -version = "1.5.5" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd50718a2b6830ce9eb5d465de5a018a12e71729d66b70807ce97e6dd14f931d" +checksum = "0f862b355f7e47711e0acfe6af92cb3fd8fd5936b66a9eaa338b51edabd1e77d" dependencies = [ + "digest 0.10.7", + "ed25519-zebra 3.1.0", + "k256", + "rand_core 0.6.4", + "thiserror", +] + +[[package]] +name = "cosmwasm-crypto" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b2a7bd9c1dd9a377a4dc0f4ad97d24b03c33798cd5a6d7ceb8869b41c5d2f2d" +dependencies = [ + "ark-bls12-381", + "ark-ec", + "ark-ff", + "ark-serialize", + "cosmwasm-core", "digest 0.10.7", "ecdsa", - "ed25519-zebra", + "ed25519-zebra 4.0.3", "k256", + "num-traits", + "p256", "rand_core 0.6.4", + "rayon", + "sha2 0.10.8", "thiserror", ] @@ -569,13 +798,37 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "cosmwasm-derive" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "029910b409398fdf81955d7301b906caf81f2c42b013ea074fbd89720229c424" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + [[package]] name = "cosmwasm-schema" version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7879036156092ad1c22fe0d7316efc5a5eceec2bc3906462a2560215f2a2f929" dependencies = [ - "cosmwasm-schema-derive", + "cosmwasm-schema-derive 1.5.5", + "schemars", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cosmwasm-schema" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bc0d4d85e83438ab9a0fea9348446f7268bc016aacfebce37e998559f151294" +dependencies = [ + "cosmwasm-schema-derive 2.1.3", "schemars", "serde", "serde_json", @@ -593,6 +846,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "cosmwasm-schema-derive" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edf5c8adac41bb7751c050d7c4c18675be19ee128714454454575e894424eeef" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + [[package]] name = "cosmwasm-std" version = "1.5.5" @@ -601,15 +865,38 @@ checksum = "78c1556156fdf892a55cced6115968b961eaaadd6f724a2c2cb7d1e168e32dd3" dependencies = [ "base64 0.21.7", "bech32 0.9.1", - "bnum", - "cosmwasm-crypto", - "cosmwasm-derive", + "bnum 0.10.0", + "cosmwasm-crypto 1.5.7", + "cosmwasm-derive 1.5.5", "derivative", "forward_ref", "hex", "schemars", "serde", - "serde-json-wasm", + "serde-json-wasm 0.5.2", + "sha2 0.10.8", + "static_assertions", + "thiserror", +] + +[[package]] +name = "cosmwasm-std" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51dec99a2e478715c0a4277f0dbeadbb8466500eb7dec873d0924edd086e77f1" +dependencies = [ + "base64 0.22.1", + "bech32 0.11.0", + "bnum 0.11.0", + "cosmwasm-core", + "cosmwasm-crypto 2.1.3", + "cosmwasm-derive 2.1.3", + "derive_more", + "hex", + "rand_core 0.6.4", + "schemars", + "serde", + "serde-json-wasm 1.0.1", "sha2 0.10.8", "static_assertions", "thiserror", @@ -621,31 +908,33 @@ version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66de2ab9db04757bcedef2b5984fbe536903ada4a8a9766717a4a71197ef34f6" dependencies = [ - "cosmwasm-std", + "cosmwasm-std 1.5.5", "serde", ] [[package]] name = "cosmwasm-vm" -version = "1.5.5" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9897b46059d68ade608fbdcec33e02b0de0ca4b32ee787a83b8a3eb31b754c85" +checksum = "5481dd2f10a04aa7aef8025b342285aebf20b167d6197e653c5e9aadc588f787" dependencies = [ - "bitflags 1.3.2", - "bytecheck", + "bech32 0.11.0", "bytes", "clru", - "cosmwasm-crypto", - "cosmwasm-std", + "cosmwasm-core", + "cosmwasm-crypto 2.1.3", + "cosmwasm-std 2.1.3", "crc32fast", "derivative", - "enumset", "hex", + "rand_core 0.6.4", "schemars", "serde", "serde_json", "sha2 0.10.8", + "strum 0.26.3", "thiserror", + "tracing", "wasmer", "wasmer-middlewares", ] @@ -862,14 +1151,14 @@ dependencies = [ [[package]] name = "cw-controllers" -version = "1.1.2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57de8d3761e46be863e3ac1eba8c8a976362a48c6abf240df1e26c3e421ee9e8" +checksum = "50c1804013d21060b994dea28a080f9eab78a3bcb6b617f05e7634b0600bf7b1" dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-storage-plus 1.2.0", - "cw-utils 1.0.3", + "cosmwasm-schema 2.1.3", + "cosmwasm-std 2.1.3", + "cw-storage-plus 2.0.0", + "cw-utils 2.0.0", "schemars", "serde", "thiserror", @@ -877,13 +1166,13 @@ dependencies = [ [[package]] name = "cw-orch" -version = "0.24.1" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c81cb500eb2f9be31a0f90c7ce66572ee4a790ffbae1c6b42ff2e3f9faf3479" +checksum = "2dd6f114ab0301b99ca0d8ba48036b87372ccc3ba0271dcd6f9533e4be578f65" dependencies = [ "anyhow", "cosmrs", - "cosmwasm-std", + "cosmwasm-std 2.1.3", "cw-orch-contract-derive", "cw-orch-core", "cw-orch-daemon", @@ -891,7 +1180,7 @@ dependencies = [ "cw-orch-mock", "cw-orch-networks", "cw-orch-traits", - "cw-utils 1.0.3", + "cw-utils 2.0.0", "hex", "log", "schemars", @@ -913,16 +1202,16 @@ dependencies = [ [[package]] name = "cw-orch-core" -version = "1.2.2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5abd640f67f655411542a3c148769270c7a9e63d4097c2dc4a1f6edf23b7a9b4" +checksum = "8a9f5f99f52d7ed7c0f8c84580f2f78a15db9c7f2144d24dd485d9347917b6fa" dependencies = [ "abstract-cw-multi-test", "anyhow", - "cosmos-sdk-proto 0.21.1", - "cosmwasm-std", - "cw-storage-plus 1.2.0", - "cw-utils 1.0.3", + "cosmos-sdk-proto", + "cosmwasm-std 2.1.3", + "cw-storage-plus 2.0.0", + "cw-utils 2.0.0", "dirs", "log", "serde", @@ -933,18 +1222,19 @@ dependencies = [ [[package]] name = "cw-orch-daemon" -version = "0.24.3" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86e6d5033f1bf9d32a6d1b11dd8e9b9ad5cb673c3621def8fe63fa1310eda520" +checksum = "cfe17cbe065101ead45abda1bd6b1a3416803ae9615e6294f5fcb3ca4e67320b" dependencies = [ "anyhow", "async-recursion", "base16", "base64 0.22.1", + "bech32 0.11.0", "bitcoin", "chrono", "cosmrs", - "cosmwasm-std", + "cosmwasm-std 2.1.3", "cw-orch-core", "cw-orch-networks", "cw-orch-traits", @@ -958,10 +1248,10 @@ dependencies = [ "lazy_static", "log", "once_cell", - "prost", + "prost 0.13.2", "prost-types", "rand_core 0.6.4", - "reqwest", + "reqwest 0.12.7", "ring", "ripemd", "schemars", @@ -970,15 +1260,16 @@ dependencies = [ "sha2 0.10.8", "thiserror", "tokio", + "toml", "tonic", "uid", ] [[package]] name = "cw-orch-fns-derive" -version = "0.22.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e21b23116a0702f540d7fa3f16e8276682d860b589fed56259220ad59d768e" +checksum = "4438fbb77e1fd05b19d47287bdc5b7be73e3875b9acbbceffc9418acd000a8ad" dependencies = [ "convert_case", "proc-macro2", @@ -988,14 +1279,14 @@ dependencies = [ [[package]] name = "cw-orch-mock" -version = "0.23.2" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57beb30d841bde79df51c9402741ef926ca8ef7ecd3570aa180074f767ac04d3" +checksum = "f3a7b0d0678a9043e4b4ac489e2bb6350d33acb3c8a6c2a2042145cd72a5a069" dependencies = [ "abstract-cw-multi-test", - "cosmwasm-std", + "cosmwasm-std 2.1.3", "cw-orch-core", - "cw-utils 1.0.3", + "cw-utils 2.0.0", "log", "serde", "sha2 0.10.8", @@ -1003,9 +1294,9 @@ dependencies = [ [[package]] name = "cw-orch-networks" -version = "0.23.3" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6b0e1af56869ced61c25f509a0a40cddd028779d838441b70f4578a8d7c0253" +checksum = "8872f1f293615b38e21b28379fc0675259086725fac17d513c35792eca037a4e" dependencies = [ "cw-orch-core", "serde", @@ -1013,12 +1304,12 @@ dependencies = [ [[package]] name = "cw-orch-traits" -version = "0.23.3" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e6b81dc282724c9c6334a499f4867e575458e69fe5b99034d4f962860f3357" +checksum = "be7b10c170797abe29170d58756fd988b260430a4466a56647c8ab8dafa8fa13" dependencies = [ "cw-orch-core", - "prost", + "prost 0.13.2", "prost-types", ] @@ -1028,18 +1319,18 @@ version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc6cf70ef7686e2da9ad7b067c5942cd3e88dd9453f7af42f54557f8af300fb0" dependencies = [ - "cosmwasm-std", + "cosmwasm-std 1.5.5", "schemars", "serde", ] [[package]] name = "cw-storage-plus" -version = "1.2.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5ff29294ee99373e2cd5fd21786a3c0ced99a52fec2ca347d565489c61b723c" +checksum = "f13360e9007f51998d42b1bc6b7fa0141f74feae61ed5fd1e5b0a89eec7b5de1" dependencies = [ - "cosmwasm-std", + "cosmwasm-std 2.1.3", "schemars", "serde", ] @@ -1050,8 +1341,8 @@ version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ae0b69fa7679de78825b4edeeec045066aa2b2c4b6e063d80042e565bb4da5c" dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", + "cosmwasm-schema 1.5.5", + "cosmwasm-std 1.5.5", "cw2 0.15.1", "schemars", "semver", @@ -1061,15 +1352,13 @@ dependencies = [ [[package]] name = "cw-utils" -version = "1.0.3" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c4a657e5caacc3a0d00ee96ca8618745d050b8f757c709babafb81208d4239c" +checksum = "07dfee7f12f802431a856984a32bce1cb7da1e6c006b5409e3981035ce562dec" dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw2 1.1.2", + "cosmwasm-schema 2.1.3", + "cosmwasm-std 2.1.3", "schemars", - "semver", "serde", "thiserror", ] @@ -1080,8 +1369,8 @@ version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5abb8ecea72e09afff830252963cb60faf945ce6cef2c20a43814516082653da" dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", + "cosmwasm-schema 1.5.5", + "cosmwasm-std 1.5.5", "cw-storage-plus 0.15.1", "schemars", "serde", @@ -1089,13 +1378,13 @@ dependencies = [ [[package]] name = "cw2" -version = "1.1.2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6c120b24fbbf5c3bedebb97f2cc85fbfa1c3287e09223428e7e597b5293c1fa" +checksum = "b04852cd38f044c0751259d5f78255d07590d136b8a86d4e09efdd7666bd6d27" dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-storage-plus 1.2.0", + "cosmwasm-schema 2.1.3", + "cosmwasm-std 2.1.3", + "cw-storage-plus 2.0.0", "schemars", "semver", "serde", @@ -1108,8 +1397,8 @@ version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6025276fb6e603e974c21f3e4606982cdc646080e8fba3198816605505e1d9a" dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", + "cosmwasm-schema 1.5.5", + "cosmwasm-std 1.5.5", "cw-utils 0.15.1", "schemars", "serde", @@ -1117,44 +1406,68 @@ dependencies = [ [[package]] name = "cw20" -version = "1.1.2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "526e39bb20534e25a1cd0386727f0038f4da294e5e535729ba3ef54055246abd" +checksum = "a42212b6bf29bbdda693743697c621894723f35d3db0d5df930be22903d0e27c" dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", - "cw-utils 1.0.3", + "cosmwasm-schema 2.1.3", + "cosmwasm-std 2.1.3", + "cw-utils 2.0.0", "schemars", "serde", ] [[package]] name = "cw20-ics20" -version = "1.1.2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76221201da08fed611c857ea3aa21c031a4a7dc771a8b1750559ca987335dc02" +checksum = "80a9e377dbbd1ffb3b6a8a2dbf9128609a6458a3292f88f99e0b6840a7e9762e" dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", + "cosmwasm-schema 2.1.3", + "cosmwasm-std 2.1.3", "cw-controllers", - "cw-storage-plus 1.2.0", - "cw-utils 1.0.3", - "cw2 1.1.2", - "cw20 1.1.2", + "cw-storage-plus 2.0.0", + "cw-utils 2.0.0", + "cw2 2.0.0", + "cw20 2.0.0", "schemars", "semver", "serde", "thiserror", ] +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core 0.14.4", + "darling_macro 0.14.4", +] + [[package]] name = "darling" version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.20.9", + "darling_macro 0.20.9", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", ] [[package]] @@ -1170,13 +1483,24 @@ dependencies = [ "syn 2.0.68", ] +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core 0.14.4", + "quote", + "syn 1.0.109", +] + [[package]] name = "darling_macro" version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ - "darling_core", + "darling_core 0.20.9", "quote", "syn 2.0.68", ] @@ -1224,6 +1548,58 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_builder" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" +dependencies = [ + "darling 0.14.4", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_builder_macro" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" +dependencies = [ + "derive_builder_core", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", + "unicode-xid", +] + [[package]] name = "digest" version = "0.9.0" @@ -1266,6 +1642,15 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "document-features" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0" +dependencies = [ + "litrs", +] + [[package]] name = "dyn-clone" version = "1.0.17" @@ -1365,6 +1750,21 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ed25519-zebra" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d9ce6874da5d4415896cd45ffbc4d1cfc0c4f9c079427bd870742c30f2f65a9" +dependencies = [ + "curve25519-dalek 4.1.3", + "ed25519", + "hashbrown 0.14.5", + "hex", + "rand_core 0.6.4", + "sha2 0.10.8", + "zeroize", +] + [[package]] name = "either" version = "1.12.0" @@ -1434,7 +1834,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af" dependencies = [ - "darling", + "darling 0.20.9", "proc-macro2", "quote", "syn 2.0.68", @@ -1517,14 +1917,26 @@ dependencies = [ "libc", ] +[[package]] +name = "filetime" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +dependencies = [ + "cfg-if", + "libc", + "libredox", + "windows-sys 0.59.0", +] + [[package]] name = "flate2" -version = "1.0.30" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.8.0", ] [[package]] @@ -1712,7 +2124,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.12", "indexmap 2.2.6", "slab", "tokio", @@ -1720,13 +2132,47 @@ dependencies = [ "tracing", ] +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.1.0", + "indexmap 2.2.6", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "half" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" + [[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "ahash", + "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]] @@ -1734,6 +2180,10 @@ 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" @@ -1741,6 +2191,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.3.9" @@ -1753,6 +2209,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hex-conservative" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" +dependencies = [ + "arrayvec", +] + [[package]] name = "hex-literal" version = "0.4.1" @@ -1786,14 +2251,25 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.7", + "digest 0.10.7", +] + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", ] [[package]] name = "http" -version = "0.2.12" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ "bytes", "fnv", @@ -1807,7 +2283,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", "pin-project-lite", ] @@ -1839,9 +2338,9 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", - "http", - "http-body", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", "httparse", "httpdate", "itoa", @@ -1853,6 +2352,27 @@ dependencies = [ "want", ] +[[package]] +name = "hyper" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2 0.4.6", + "http 1.1.0", + "http-body 1.0.1", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + [[package]] name = "hyper-rustls" version = "0.24.2" @@ -1860,36 +2380,77 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", - "http", - "hyper", - "rustls", + "http 0.2.12", + "hyper 0.14.29", + "rustls 0.21.12", + "tokio", + "tokio-rustls 0.24.1", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +dependencies = [ + "futures-util", + "http 1.1.0", + "hyper 1.4.1", + "hyper-util", + "rustls 0.23.12", + "rustls-pki-types", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.0", + "tower-service", ] [[package]] name = "hyper-timeout" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" dependencies = [ - "hyper", + "hyper 1.4.1", + "hyper-util", "pin-project-lite", "tokio", - "tokio-io-timeout", + "tower-service", ] [[package]] name = "hyper-tls" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", - "hyper", + "http-body-util", + "hyper 1.4.1", + "hyper-util", "native-tls", "tokio", "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "hyper 1.4.1", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", ] [[package]] @@ -1945,6 +2506,7 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", + "serde", ] [[package]] @@ -1955,6 +2517,7 @@ checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown 0.14.5", + "serde", ] [[package]] @@ -1974,6 +2537,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.12.1" @@ -1983,6 +2555,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -2000,9 +2581,9 @@ dependencies = [ [[package]] name = "k256" -version = "0.13.1" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" dependencies = [ "cfg-if", "ecdsa", @@ -2038,6 +2619,7 @@ checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ "bitflags 2.6.0", "libc", + "redox_syscall", ] [[package]] @@ -2046,6 +2628,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litrs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" + [[package]] name = "lock_api" version = "0.4.12" @@ -2058,18 +2646,9 @@ dependencies = [ [[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" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" -dependencies = [ - "libc", -] +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "mach2" @@ -2112,9 +2691,9 @@ dependencies = [ [[package]] name = "memoffset" -version = "0.8.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" dependencies = [ "autocfg", ] @@ -2134,15 +2713,25 @@ dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "mio" -version = "0.8.11" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ + "hermit-abi", "libc", "wasi", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2150,14 +2739,14 @@ name = "moneymarket" version = "0.3.1" source = "git+https://github.com/CavernPerson/money-market-contracts#6a3b3f586cd085d434485bb13e2d12f95e8beef2" dependencies = [ - "cosmwasm-schema", - "cosmwasm-std", + "cosmwasm-schema 1.5.5", + "cosmwasm-std 1.5.5", "cosmwasm-storage", "cw20 0.15.1", "schemars", "serde", - "strum", - "strum_macros", + "strum 0.24.1", + "strum_macros 0.24.3", ] [[package]] @@ -2199,28 +2788,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" -[[package]] -name = "num-derive" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "num-derive" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.68", -] - [[package]] name = "num-integer" version = "0.1.46" @@ -2239,16 +2806,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - [[package]] name = "object" version = "0.36.0" @@ -2320,6 +2877,18 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[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 0.10.8", +] + [[package]] name = "parking_lot" version = "0.12.3" @@ -2340,7 +2909,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -2451,6 +3020,15 @@ 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" @@ -2491,7 +3069,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ "bytes", - "prost-derive", + "prost-derive 0.12.6", +] + +[[package]] +name = "prost" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2ecbe40f08db5c006b5764a2645f7f3f141ce756412ac9e1dd6087e6d32995" +dependencies = [ + "bytes", + "prost-derive 0.13.2", ] [[package]] @@ -2501,7 +3089,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools", + "itertools 0.12.1", + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "prost-derive" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acf0c195eebb4af52c752bec4f52f645da98b6e92077a04110c7f349477ae5ac" +dependencies = [ + "anyhow", + "itertools 0.12.1", "proc-macro2", "quote", "syn 2.0.68", @@ -2509,11 +3110,11 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.12.6" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" +checksum = "60caa6738c7369b940c3d49246a8d1749323674c65cb13010134f5c9bad5b519" dependencies = [ - "prost", + "prost 0.13.2", ] [[package]] @@ -2700,12 +3301,55 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-rustls", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.29", + "hyper-rustls 0.24.2", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls 0.21.12", + "rustls-native-certs 0.6.3", + "rustls-pemfile 1.0.4", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper 0.1.2", + "system-configuration 0.5.1", + "tokio", + "tokio-rustls 0.24.1", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + +[[package]] +name = "reqwest" +version = "0.12.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" +dependencies = [ + "base64 0.22.1", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2 0.4.6", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.4.1", + "hyper-rustls 0.27.2", "hyper-tls", + "hyper-util", "ipnet", "js-sys", "log", @@ -2714,23 +3358,20 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls", - "rustls-native-certs", - "rustls-pemfile", + "rustls-pemfile 2.1.3", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper", - "system-configuration", + "sync_wrapper 1.0.1", + "system-configuration 0.6.1", "tokio", "tokio-native-tls", - "tokio-rustls", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "winreg", + "windows-registry", ] [[package]] @@ -2839,10 +3480,25 @@ checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", "ring", - "rustls-webpki", + "rustls-webpki 0.101.7", "sct", ] +[[package]] +name = "rustls" +version = "0.23.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki 0.102.7", + "subtle", + "zeroize", +] + [[package]] name = "rustls-native-certs" version = "0.6.3" @@ -2850,7 +3506,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" dependencies = [ "openssl-probe", - "rustls-pemfile", + "rustls-pemfile 1.0.4", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-native-certs" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" +dependencies = [ + "openssl-probe", + "rustls-pemfile 2.1.3", + "rustls-pki-types", "schannel", "security-framework", ] @@ -2864,6 +3533,22 @@ dependencies = [ "base64 0.21.7", ] +[[package]] +name = "rustls-pemfile" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +dependencies = [ + "base64 0.22.1", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" + [[package]] name = "rustls-webpki" version = "0.101.7" @@ -2874,6 +3559,17 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustls-webpki" +version = "0.102.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84678086bd54edf2b415183ed7a94d0efb049f1b646a33e22a36f3794be6ae56" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.17" @@ -2914,6 +3610,7 @@ dependencies = [ "schemars_derive", "serde", "serde_json", + "url", ] [[package]] @@ -2966,19 +3663,19 @@ dependencies = [ [[package]] name = "secp256k1" -version = "0.27.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" +checksum = "0e0cc0f1cf93f4969faf3ea1c7d8a9faed25918d96affa959720823dfe86d4f3" dependencies = [ - "bitcoin_hashes", + "bitcoin_hashes 0.12.0", "secp256k1-sys", ] [[package]] name = "secp256k1-sys" -version = "0.8.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" +checksum = "1433bd67156263443f14d603720b082dd3121779323fce20cba2aa07b874bc1b" dependencies = [ "cc", ] @@ -3017,21 +3714,33 @@ name = "semver" version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +dependencies = [ + "serde", +] [[package]] name = "serde" -version = "1.0.203" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" dependencies = [ "serde_derive", ] [[package]] name = "serde-json-wasm" -version = "0.5.2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e9213a07d53faa0b8dd81e767a54a8188a242fdb9be99ab75ec576a774bfdd7" +dependencies = [ + "serde", +] + +[[package]] +name = "serde-json-wasm" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e9213a07d53faa0b8dd81e767a54a8188a242fdb9be99ab75ec576a774bfdd7" +checksum = "f05da0d153dd4595bdffd5099dc0e9ce425b205ee648eb93437ff7302af8c9a5" dependencies = [ "serde", ] @@ -3056,11 +3765,21 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half", + "serde", +] + [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", @@ -3080,11 +3799,12 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.118" +version = "1.0.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4" +checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -3100,6 +3820,15 @@ dependencies = [ "syn 2.0.68", ] +[[package]] +name = "serde_spanned" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -3112,6 +3841,19 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap 2.2.6", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "sha2" version = "0.9.9" @@ -3230,25 +3972,53 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strum" version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros 0.26.4", +] + [[package]] name = "strum_macros" version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "rustversion", "syn 1.0.109", ] +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.68", +] + [[package]] name = "subtle" version = "2.6.1" @@ -3298,6 +4068,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -3306,7 +4085,18 @@ checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", "core-foundation", - "system-configuration-sys", + "system-configuration-sys 0.5.0", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.6.0", + "core-foundation", + "system-configuration-sys 0.6.0", ] [[package]] @@ -3319,12 +4109,33 @@ dependencies = [ "libc", ] +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "tap" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "tar" +version = "0.4.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb797dad5fb5b76fcf519e702f4a589483b5ef06567f160c392832c1f5e44909" +dependencies = [ + "filetime", + "libc", + "xattr", +] + [[package]] name = "target-lexicon" version = "0.12.14" @@ -3345,9 +4156,9 @@ dependencies = [ [[package]] name = "tendermint" -version = "0.34.1" +version = "0.39.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15ab8f0a25d0d2ad49ac615da054d6a76aa6603ff95f7d18bafdd34450a1a04b" +checksum = "2f3afea7809ffaaf1e5d9c3c9997cb3a834df7e94fbfab2fad2bc4577f1cde41" dependencies = [ "bytes", "digest 0.10.7", @@ -3358,8 +4169,7 @@ dependencies = [ "k256", "num-traits", "once_cell", - "prost", - "prost-types", + "prost 0.13.2", "ripemd", "serde", "serde_bytes", @@ -3369,16 +4179,16 @@ dependencies = [ "signature", "subtle", "subtle-encoding", - "tendermint-proto 0.34.1", + "tendermint-proto", "time", "zeroize", ] [[package]] name = "tendermint-config" -version = "0.34.1" +version = "0.39.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1a02da769166e2052cd537b1a97c78017632c2d9e19266367b27e73910434fc" +checksum = "d8add7b85b0282e5901521f78fe441956ac1e2752452f4e1f2c0ce7e1f10d485" dependencies = [ "flex-error", "serde", @@ -3390,34 +4200,13 @@ dependencies = [ [[package]] name = "tendermint-proto" -version = "0.34.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b797dd3d2beaaee91d2f065e7bdf239dc8d80bba4a183a288bc1279dd5a69a1e" -dependencies = [ - "bytes", - "flex-error", - "num-derive 0.3.3", - "num-traits", - "prost", - "prost-types", - "serde", - "serde_bytes", - "subtle-encoding", - "time", -] - -[[package]] -name = "tendermint-proto" -version = "0.35.0" +version = "0.39.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff525d5540a9fc535c38dc0d92a98da3ee36fcdfbda99cecb9f3cce5cd4d41d7" +checksum = "bf3abf34ecf33125621519e9952688e7a59a98232d51538037ba21fbe526a802" dependencies = [ "bytes", "flex-error", - "num-derive 0.4.2", - "num-traits", - "prost", - "prost-types", + "prost 0.13.2", "serde", "serde_bytes", "subtle-encoding", @@ -3426,9 +4215,9 @@ dependencies = [ [[package]] name = "tendermint-rpc" -version = "0.34.1" +version = "0.39.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71afae8bb5f6b14ed48d4e1316a643b6c2c3cbad114f510be77b4ed20b7b3e42" +checksum = "9693f42544bf3b41be3cbbfa418650c86e137fb8f5a57981659a84b677721ecf" dependencies = [ "async-trait", "bytes", @@ -3438,7 +4227,7 @@ dependencies = [ "peg", "pin-project", "rand", - "reqwest", + "reqwest 0.11.27", "semver", "serde", "serde_bytes", @@ -3447,7 +4236,7 @@ dependencies = [ "subtle-encoding", "tendermint", "tendermint-config", - "tendermint-proto 0.34.1", + "tendermint-proto", "thiserror", "time", "tokio", @@ -3468,18 +4257,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", @@ -3533,38 +4322,27 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.38.0" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.48.0", -] - -[[package]] -name = "tokio-io-timeout" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" -dependencies = [ - "pin-project-lite", - "tokio", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", @@ -3587,7 +4365,18 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls", + "rustls 0.21.12", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls 0.23.12", + "rustls-pki-types", "tokio", ] @@ -3617,37 +4406,64 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.11" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ + "indexmap 2.2.6", "serde", + "serde_spanned", + "toml_datetime", + "winnow", ] [[package]] name = "tonic" -version = "0.10.2" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d560933a0de61cf715926b9cac824d4c883c2c43142f787595e48280c40a1d0e" +checksum = "c6f6ba989e4b2c58ae83d862d3a3e27690b6e3ae630d0deb59f3697f32aa88ad" dependencies = [ "async-stream", "async-trait", "axum", - "base64 0.21.7", + "base64 0.22.1", "bytes", - "h2", - "http", - "http-body", - "hyper", + "h2 0.4.6", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.4.1", "hyper-timeout", + "hyper-util", "percent-encoding", "pin-project", - "prost", - "rustls", - "rustls-native-certs", - "rustls-pemfile", + "prost 0.13.2", + "rustls-native-certs 0.7.3", + "rustls-pemfile 2.1.3", + "socket2", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.0", "tokio-stream", "tower", "tower-layer", @@ -3772,6 +4588,18 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +[[package]] +name = "unicode-xid" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a" + +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + [[package]] name = "untrusted" version = "0.9.0" @@ -3787,6 +4615,7 @@ dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -3857,29 +4686,6 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-downcast" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dac026d43bcca6e7ce1c0956ba68f59edf6403e8e930a5d891be72c31a44340" -dependencies = [ - "js-sys", - "once_cell", - "wasm-bindgen", - "wasm-bindgen-downcast-macros", -] - -[[package]] -name = "wasm-bindgen-downcast-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5020cfa87c7cecefef118055d44e3c1fc122c7ec25701d528ee458a0b45f38f" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "wasm-bindgen-futures" version = "0.4.42" @@ -3923,9 +4729,9 @@ checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "wasmer" -version = "4.2.2" +version = "4.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e626f958755a90a6552b9528f59b58a62ae288e6c17fcf40e99495bc33c60f0" +checksum = "3de82c1520fb75ade394d6c89cac2b05d1b7b4205a45099efcd078b0bc828375" dependencies = [ "bytes", "cfg-if", @@ -3939,8 +4745,8 @@ dependencies = [ "shared-buffer", "target-lexicon", "thiserror", + "tracing", "wasm-bindgen", - "wasm-bindgen-downcast", "wasmer-compiler", "wasmer-compiler-cranelift", "wasmer-compiler-singlepass", @@ -3952,9 +4758,9 @@ dependencies = [ [[package]] name = "wasmer-compiler" -version = "4.2.2" +version = "4.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "848e1922694cf97f4df680a0534c9d72c836378b5eb2313c1708fe1a75b40044" +checksum = "d6c18588e4b92adb2ea88a2897c93615538c7e40cfec8dc6efc3fcee63299a81" dependencies = [ "backtrace", "bytes", @@ -3963,6 +4769,7 @@ dependencies = [ "enumset", "lazy_static", "leb128", + "libc", "memmap2 0.5.10", "more-asserts", "region", @@ -3975,13 +4782,14 @@ dependencies = [ "wasmer-vm", "wasmparser", "winapi", + "xxhash-rust", ] [[package]] name = "wasmer-compiler-cranelift" -version = "4.2.2" +version = "4.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d96bce6fad15a954edcfc2749b59e47ea7de524b6ef3df392035636491a40b4" +checksum = "cf497986b83f1ae8589a22f046b803d6d1d77bbeda93e75baa89ab6501838f7c" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -3998,9 +4806,9 @@ dependencies = [ [[package]] name = "wasmer-compiler-singlepass" -version = "4.2.2" +version = "4.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebaa865b40ffb3351b03dab9fe9930a5248c25daebd55b464b79b862d9b55ccd" +checksum = "a1093545b718fdba6dc0b9d5cfac843fa859fbc10d1dfaa72a21fac19c6a5d67" dependencies = [ "byteorder", "dynasm", @@ -4015,11 +4823,33 @@ dependencies = [ "wasmer-types", ] +[[package]] +name = "wasmer-config" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b4a632496950fde9ad821e195ef1a301440076f7c7d80de55239a140359bcbd" +dependencies = [ + "anyhow", + "bytesize", + "derive_builder", + "hex", + "indexmap 2.2.6", + "schemars", + "semver", + "serde", + "serde_cbor", + "serde_json", + "serde_yaml", + "thiserror", + "toml", + "url", +] + [[package]] name = "wasmer-derive" -version = "4.2.2" +version = "4.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f08f80d166a9279671b7af7a09409c28ede2e0b4e3acabbf0e3cb22c8038ba7" +checksum = "45ab99baa393da623dbca6390c17bd9cd7666e8c48f6b42b4f8c635106a09ca8" dependencies = [ "proc-macro-error", "proc-macro2", @@ -4029,9 +4859,9 @@ dependencies = [ [[package]] name = "wasmer-middlewares" -version = "4.2.2" +version = "4.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeb4b87c0ea9f8636c81a8ab8f52bad01c8623c9fcbb3db5f367d5f157fada30" +checksum = "ef5f8fee717085401399c343b5c0daa37179c9f31c64889e9ae183a4bad15e37" dependencies = [ "wasmer", "wasmer-types", @@ -4040,25 +4870,30 @@ dependencies = [ [[package]] name = "wasmer-types" -version = "4.2.2" +version = "4.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae2c892882f0b416783fb4310e5697f5c30587f6f9555f9d4f2be85ab39d5d3d" +checksum = "0aebf59870ee6e2ef0264d87e6a83f767f5cfe83e21470c0cc32e06231335e23" dependencies = [ "bytecheck", "enum-iterator", "enumset", + "getrandom", + "hex", "indexmap 1.9.3", "more-asserts", "rkyv", + "sha2 0.10.8", "target-lexicon", "thiserror", + "webc", + "xxhash-rust", ] [[package]] name = "wasmer-vm" -version = "4.2.2" +version = "4.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c0a9a57b627fb39e5a491058d4365f099bc9b140031c000fded24a3306d9480" +checksum = "0df3b84ac2c450ad04931b558392cadd03d606d94ab15496e13ce56ee8320634" dependencies = [ "backtrace", "cc", @@ -4072,7 +4907,7 @@ dependencies = [ "indexmap 1.9.3", "lazy_static", "libc", - "mach", + "mach2", "memoffset", "more-asserts", "region", @@ -4084,12 +4919,13 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.95.0" +version = "0.121.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ea896273ea99b15132414be1da01ab0d8836415083298ecaffbe308eaac87a" +checksum = "9dbe55c8f9d0dbd25d9447a5a889ff90c0cc3feaa7395310d3d826b2c703eaab" dependencies = [ - "indexmap 1.9.3", - "url", + "bitflags 2.6.0", + "indexmap 2.2.6", + "semver", ] [[package]] @@ -4102,6 +4938,35 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webc" +version = "6.0.0-rc2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb3e2ccb43d303c5bd48f31db7a129481a9aaa5343d623f92951751df190df81" +dependencies = [ + "anyhow", + "base64 0.22.1", + "bytes", + "cfg-if", + "document-features", + "flate2", + "indexmap 1.9.3", + "libc", + "once_cell", + "semver", + "serde", + "serde_cbor", + "serde_json", + "sha2 0.10.8", + "shared-buffer", + "tar", + "tempfile", + "thiserror", + "toml", + "url", + "wasmer-config", +] + [[package]] name = "winapi" version = "0.3.9" @@ -4139,7 +5004,37 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", ] [[package]] @@ -4170,7 +5065,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -4190,18 +5094,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -4212,9 +5116,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -4230,9 +5134,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -4248,15 +5152,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -4272,9 +5176,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -4290,9 +5194,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -4302,9 +5206,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -4320,9 +5224,18 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +dependencies = [ + "memchr", +] [[package]] name = "winreg" @@ -4343,6 +5256,43 @@ dependencies = [ "tap", ] +[[package]] +name = "xattr" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" +dependencies = [ + "libc", + "linux-raw-sys", + "rustix", +] + +[[package]] +name = "xxhash-rust" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + [[package]] name = "zeroize" version = "1.8.1" diff --git a/Cargo.toml b/Cargo.toml index 243477e2..dc594475 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,24 +11,21 @@ homepage = "https://cosmwasm.com" [features] default = [] backtrace = ["anyhow/backtrace"] -cosmwasm_1_1 = ["cosmwasm-std/cosmwasm_1_1"] -cosmwasm_1_2 = ["cosmwasm_1_1", "cosmwasm-std/cosmwasm_1_2"] -cosmwasm_1_3 = ["cosmwasm_1_2", "cosmwasm-std/cosmwasm_1_3"] -cosmwasm_1_4 = ["cosmwasm_1_3", "cosmwasm-std/cosmwasm_1_4"] [dependencies] anyhow = "1.0.75" bech32 = "0.9.1" -cosmwasm-std = { version = "1.5.0", features = [ +cosmwasm-std = { version = "2.1", features = [ "iterator", "staking", "stargate", + "cosmwasm_2_0", ] } -cw-storage-plus = "1.1.0" -cw-utils = "1.0.3" +cw-storage-plus = "2.0.0" +cw-utils = "2.0.0" derivative = "2.2.0" itertools = "0.12.0" -prost = "0.12.3" +prost = "0.13.0" schemars = "0.8.16" serde = "1.0.193" sha2 = "0.10.8" @@ -36,19 +33,19 @@ thiserror = "1.0.50" # Clone testing deps ## Network -cw-orch = { version = "0.24.1", features = ["daemon"] } +cw-orch = { version = "0.25.0", features = ["daemon"] } tokio = "1.28.2" -tonic = "0.10.2" +tonic = "0.12.2" ## Emulation -cosmwasm-vm = { version = "1.2", features = [ +cosmwasm-vm = { version = "2.1.3", features = [ "staking", "stargate", "iterator", ] } ## Dual Storage -cosmrs = "0.15.0" +cosmrs = "0.19.0" num-bigint = "0.4.3" # Analyzer @@ -56,7 +53,7 @@ treediff = { version = "4.0.2", features = ["with-rustc-serialize"] } rustc-serialize = "0.3.24" serde_json = "1.0.105" log = "0.4.19" -wasmer = { version = "=4.2.2", default-features = false, features = [ +wasmer = { version = "4.3.0", default-features = false, features = [ "cranelift", "singlepass", ] } @@ -68,9 +65,9 @@ once_cell = "1.18.0" # General env_logger = "0.10.0" -cosmwasm-schema = "1.2.7" +cosmwasm-schema = "2.1.3" # Cavern Test App -cw20 = "1.0.1" +cw20 = "2.0.0" moneymarket = { git = "https://github.com/CavernPerson/money-market-contracts" } -cw2 = "1.1.2" +cw2 = "2.0.0" diff --git a/src/bank.rs b/src/bank.rs index acf5d7ec..d2a88947 100644 --- a/src/bank.rs +++ b/src/bank.rs @@ -228,7 +228,7 @@ impl Module for BankKeeper { BankQuery::AllBalances { address } => { let address = api.addr_validate(&address)?; let amount = self.get_balance(&bank_storage, &address)?; - let res = AllBalanceResponse { amount }; + let res = AllBalanceResponse::new(amount); Ok(to_json_binary(&res)?) } BankQuery::Balance { address, denom } => { @@ -238,7 +238,7 @@ impl Module for BankKeeper { .into_iter() .find(|c| c.denom == denom) .unwrap_or_else(|| coin(0, denom)); - let res = BalanceResponse { amount }; + let res = BalanceResponse::new(amount); Ok(to_json_binary(&res)?) } #[cfg(feature = "cosmwasm_1_1")] diff --git a/src/checksums.rs b/src/checksums.rs index 0499f8f0..f5c641f6 100644 --- a/src/checksums.rs +++ b/src/checksums.rs @@ -1,10 +1,11 @@ -//! # Implementation of the interface to custom checksum generator +//! # Implementation of checksum generator -use cosmwasm_std::{Addr, HexBinary}; -use sha2::{Digest, Sha256}; +use cosmwasm_std::{Addr, Checksum}; -/// An interface to call custom checksum generator for contract's code. -/// +/// Provides a custom interface for generating checksums for contract code. +/// This is crucial for ensuring code integrity and is particularly useful +/// in environments where code verification is a key part of the contract +/// deployment process. /// This trait defines a method to calculate checksum based on /// the creator's address and a unique code identifier. pub trait ChecksumGenerator { @@ -12,7 +13,7 @@ pub trait ChecksumGenerator { /// and code identifier. Returns a hexadecimal binary representation /// of the calculated checksum. There are no assumptions about /// the length of the calculated checksum. - fn checksum(&self, creator: &Addr, code_id: u64) -> HexBinary; + fn checksum(&self, creator: &Addr, code_id: u64) -> Checksum; } /// Default checksum generator implementation. @@ -21,7 +22,7 @@ pub struct SimpleChecksumGenerator; impl ChecksumGenerator for SimpleChecksumGenerator { /// Calculates the checksum based on code identifier. The resulting /// checksum is 32-byte length SHA2 digest. - fn checksum(&self, _creator: &Addr, code_id: u64) -> HexBinary { - HexBinary::from(Sha256::digest(format!("contract code {}", code_id)).to_vec()) + fn checksum(&self, _creator: &Addr, code_id: u64) -> Checksum { + Checksum::generate(format!("contract code {}", code_id).as_bytes()) } } diff --git a/src/contracts.rs b/src/contracts.rs index 5d90c9c6..93bf3fcd 100644 --- a/src/contracts.rs +++ b/src/contracts.rs @@ -395,8 +395,8 @@ where pub mod test { use cosmwasm_std::{ - testing::{mock_dependencies, mock_env, mock_info}, - to_json_binary, Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response, StdResult, + testing::{message_info, mock_dependencies, mock_env}, + to_json_binary, Addr, Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response, StdResult, }; use super::ContractWrapper; @@ -428,14 +428,14 @@ pub mod test { clone( mock_dependencies().as_mut(), mock_env(), - mock_info("sender", &[]), + message_info(&Addr::unchecked("sender"), &[]), Empty {}, )?; second_clone( mock_dependencies().as_mut(), mock_env(), - mock_info("sender", &[]), + message_info(&Addr::unchecked("sender"), &[]), Empty {}, )?; diff --git a/src/executor.rs b/src/executor.rs index 694894af..b924724b 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -53,6 +53,7 @@ impl AppResponse { impl From for AppResponse { fn from(reply: SubMsgResponse) -> Self { AppResponse { + #[allow(deprecated)] data: reply.data, events: reply.events, } diff --git a/src/queries/wasm.rs b/src/queries/wasm.rs index 15cfbd3c..a78e40e7 100644 --- a/src/queries/wasm.rs +++ b/src/queries/wasm.rs @@ -24,9 +24,7 @@ impl WasmRemoteQuerier { pub fn load_distant_contract(remote: RemoteChannel, address: &Addr) -> AnyResult { let wasm_querier = CosmWasm::new_sync(remote.channel, &remote.rt); - let code_info = remote - .rt - .block_on(wasm_querier._contract_info(address.clone()))?; + let code_info = remote.rt.block_on(wasm_querier._contract_info(address))?; Ok(ContractData { admin: code_info.admin.map(Addr::unchecked), @@ -37,7 +35,7 @@ impl WasmRemoteQuerier { pub fn raw_query( remote: RemoteChannel, - contract_addr: String, + contract_addr: &Addr, key: Binary, ) -> AnyResult> { let wasm_querier = CosmWasm::new_sync(remote.channel, &remote.rt); diff --git a/src/staking.rs b/src/staking.rs index 4872a6bf..fc0048dc 100644 --- a/src/staking.rs +++ b/src/staking.rs @@ -244,7 +244,7 @@ impl StakeKeeper { Ok(Coin { denom: staking_info.bonded_denom, - amount: Uint128::new(1) * delegator_rewards, // multiplying by 1 to convert Decimal to Uint128 + amount: Uint128::new(1).mul_floor(delegator_rewards), // multiplying by 1 to convert Decimal to Uint128 }) } @@ -350,7 +350,7 @@ impl StakeKeeper { Ok(shares.map(|shares| { Coin { denom: staking_info.bonded_denom, - amount: Uint128::new(1) * shares.stake, // multiplying by 1 to convert Decimal to Uint128 + amount: Uint128::new(1).mul_floor(shares.stake), // multiplying by 1 to convert Decimal to Uint128 } })) } @@ -470,7 +470,7 @@ impl StakeKeeper { .unwrap(); let remaining_percentage = Decimal::one() - percentage; - validator_info.stake = validator_info.stake * remaining_percentage; + validator_info.stake = validator_info.stake.mul_floor(remaining_percentage); // if the stake is completely gone, we clear all stakers and reinitialize the validator if validator_info.stake.is_zero() { @@ -503,7 +503,7 @@ impl StakeKeeper { .iter_mut() .filter(|ub| &ub.validator == validator) .for_each(|ub| { - ub.amount = ub.amount * remaining_percentage; + ub.amount = ub.amount.mul_floor(remaining_percentage); }); UNBONDING_QUEUE.save(staking_storage, &unbonding_queue)?; @@ -771,36 +771,33 @@ impl Module for StakeKeeper { ) -> AnyResult { let staking_storage = prefixed_read(storage, NAMESPACE_STAKING); match request { - StakingQuery::BondedDenom {} => Ok(to_json_binary(&BondedDenomResponse { - denom: Self::get_staking_info(&staking_storage)?.bonded_denom, - })?), + StakingQuery::BondedDenom {} => Ok(to_json_binary(&BondedDenomResponse::new( + Self::get_staking_info(&staking_storage)?.bonded_denom, + ))?), StakingQuery::AllDelegations { delegator } => { let delegator = api.addr_validate(&delegator)?; let validators = self.get_validators(&staking_storage)?; - let res: AnyResult> = validators - .into_iter() - .filter_map(|validator| { - let delegator = delegator.clone(); - let amount = self - .get_stake( - &staking_storage, - &delegator, - &Addr::unchecked(&validator.address), - ) - .transpose()?; - - Some(amount.map(|amount| Delegation { - delegator, - validator: validator.address, - amount, - })) - }) - .collect(); - - Ok(to_json_binary(&AllDelegationsResponse { - delegations: res?, - })?) + let res: AnyResult> = + validators + .into_iter() + .filter_map(|validator| { + let delegator = delegator.clone(); + let amount = self + .get_stake( + &staking_storage, + &delegator, + &Addr::unchecked(&validator.address), + ) + .transpose()?; + + Some(amount.map(|amount| { + Delegation::new(delegator, validator.address, amount) + })) + }) + .collect(); + + Ok(to_json_binary(&AllDelegationsResponse::new(res?))?) } StakingQuery::Delegation { delegator, @@ -828,38 +825,36 @@ impl Module for StakeKeeper { let staking_info = Self::get_staking_info(&staking_storage)?; let amount = coin( - (shares.stake * Uint128::new(1)).u128(), + (Uint128::new(1).mul_floor(shares.stake)).u128(), staking_info.bonded_denom, ); let full_delegation_response = if amount.amount.is_zero() { // no delegation - DelegationResponse { delegation: None } + DelegationResponse::new(None) } else { - DelegationResponse { - delegation: Some(FullDelegation { - delegator, - validator, - amount: amount.clone(), - can_redelegate: amount, // TODO: not implemented right now - accumulated_rewards: if reward.amount.is_zero() { - vec![] - } else { - vec![reward] - }, - }), - } + DelegationResponse::new(Some(FullDelegation::new( + delegator, + validator, + amount.clone(), + amount, // TODO: not implemented right now + if reward.amount.is_zero() { + vec![] + } else { + vec![reward] + }, + ))) }; let res = to_json_binary(&full_delegation_response)?; Ok(res) } - StakingQuery::AllValidators {} => Ok(to_json_binary(&AllValidatorsResponse { - validators: self.get_validators(&staking_storage)?, - })?), - StakingQuery::Validator { address } => Ok(to_json_binary(&ValidatorResponse { - validator: self.get_validator(&staking_storage, &Addr::unchecked(address))?, - })?), + StakingQuery::AllValidators {} => Ok(to_json_binary(&AllValidatorsResponse::new( + self.get_validators(&staking_storage)?, + ))?), + StakingQuery::Validator { address } => Ok(to_json_binary(&ValidatorResponse::new( + self.get_validator(&staking_storage, &Addr::unchecked(address))?, + ))?), q => bail!("Unsupported staking sudo message: {:?}", q), } } @@ -888,7 +883,7 @@ impl DistributionKeeper { // load updated rewards for delegator let mut shares = STAKES.load(&staking_storage, (delegator, validator))?; - let rewards = Uint128::new(1) * shares.rewards; // convert to Uint128 + let rewards = Uint128::new(1).mul_floor(shares.rewards); // convert to Uint128 // remove rewards from delegator shares.rewards = Decimal::zero(); diff --git a/src/wasm.rs b/src/wasm.rs index 0913547b..e1a15d23 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -14,13 +14,13 @@ use crate::wasm_emulation::input::QuerierStorage; use crate::wasm_emulation::query::mock_querier::{ForkState, LocalForkedState}; use crate::wasm_emulation::query::AllWasmQuerier; use cosmwasm_std::testing::mock_wasmd_attr; -use cosmwasm_std::CustomMsg; use cosmwasm_std::{ to_json_binary, Addr, Api, Attribute, BankMsg, Binary, BlockInfo, Coin, ContractInfo, - ContractInfoResponse, CustomQuery, Deps, DepsMut, Env, Event, HexBinary, MessageInfo, Order, - Querier, QuerierWrapper, Record, Reply, ReplyOn, Response, StdResult, Storage, SubMsg, - SubMsgResponse, SubMsgResult, TransactionInfo, WasmMsg, WasmQuery, + ContractInfoResponse, CustomQuery, Deps, DepsMut, Env, Event, MessageInfo, Order, Querier, + QuerierWrapper, Record, Reply, ReplyOn, Response, StdResult, Storage, SubMsg, SubMsgResponse, + SubMsgResult, TransactionInfo, WasmMsg, WasmQuery, }; +use cosmwasm_std::{Checksum, CustomMsg}; use cw_storage_plus::Map; use prost::Message; use schemars::JsonSchema; @@ -73,7 +73,7 @@ pub struct CodeData { /// Address of an account that initially stored the contract code. pub creator: Addr, /// Checksum of the contract's code base. - pub checksum: HexBinary, + pub checksum: Checksum, /// Identifier of the code base where the contract code is stored in memory. pub code_base_id: usize, } @@ -192,10 +192,13 @@ where WasmQuery::ContractInfo { contract_addr } => { let addr = api.addr_validate(&contract_addr)?; let contract = self.contract_data(storage, &addr)?; - let mut res = ContractInfoResponse::default(); - res.code_id = contract.code_id; - res.creator = contract.creator.to_string(); - res.admin = contract.admin.map(|x| x.into()); + let res = ContractInfoResponse::new( + contract.code_id, + contract.creator, + contract.admin, + false, + None, + ); to_json_binary(&res).map_err(Into::into) } #[cfg(feature = "cosmwasm_1_2")] @@ -531,13 +534,9 @@ where if let Some(local_key) = local_key { local_key.into() } else { - WasmRemoteQuerier::raw_query( - self.remote.clone().unwrap(), - address.to_string(), - key.into(), - ) - .unwrap_or_default() - .into() + WasmRemoteQuerier::raw_query(self.remote.clone().unwrap(), &address, key.into()) + .unwrap_or_default() + .into() } } @@ -832,10 +831,16 @@ where if matches!(reply_on, ReplyOn::Always | ReplyOn::Success) { let reply = Reply { id, - result: SubMsgResult::Ok(SubMsgResponse { - events: r.events.clone(), - data: r.data, - }), + result: SubMsgResult::Ok( + #[allow(deprecated)] + SubMsgResponse { + events: r.events.clone(), + data: r.data, + msg_responses: vec![], + }, + ), + payload: Default::default(), + gas_used: 0, }; // do reply and combine it with the original response let reply_res = self.reply(api, router, storage, block, contract, reply)?; @@ -854,6 +859,8 @@ where let reply = Reply { id, result: SubMsgResult::Err(format!("{:?}", e)), + payload: Default::default(), + gas_used: 0, }; self.reply(api, router, storage, block, contract, reply) } else { diff --git a/src/wasm_emulation/api/mod.rs b/src/wasm_emulation/api/mod.rs index 0b98c665..6e786427 100644 --- a/src/wasm_emulation/api/mod.rs +++ b/src/wasm_emulation/api/mod.rs @@ -2,6 +2,7 @@ use crate::wasm_emulation::query::gas::{GAS_COST_CANONICALIZE, GAS_COST_HUMANIZE use bech32::{FromBase32, ToBase32, Variant}; use cosmwasm_std::Addr; use cosmwasm_vm::{BackendApi, BackendError, GasInfo}; +use std::ops::AddAssign; const SHORT_CANON_LEN: usize = 20; const LONG_CANON_LEN: usize = 32; @@ -60,20 +61,49 @@ impl RealApi { pub fn next_address(&self, count: usize) -> Addr { let mut canon = format!("ADDRESS_{}", count).as_bytes().to_vec(); canon.resize(SHORT_CANON_LEN, 0); - Addr::unchecked(self.human_address(&canon).0.unwrap()) + Addr::unchecked(self.addr_humanize(&canon).0.unwrap()) } pub fn next_contract_address(&self, count: usize) -> Addr { let mut canon = format!("CONTRACT_{}", count).as_bytes().to_vec(); canon.resize(LONG_CANON_LEN, 0); - Addr::unchecked(self.human_address(&canon).0.unwrap()) + Addr::unchecked(self.addr_humanize(&canon).0.unwrap()) } } impl BackendApi for RealApi { - fn canonical_address(&self, address: &str) -> (Result, BackendError>, GasInfo) { + fn addr_validate(&self, input: &str) -> cosmwasm_vm::BackendResult<()> { + let (canon, mut gas_cost) = self.addr_canonicalize(input); + + if let Err(e) = canon { + return (Err(e), gas_cost); + } + let canon = canon.unwrap(); + + let (new_human, human_gas_cost) = self.addr_humanize(&canon); + + if let Err(e) = new_human { + gas_cost.add_assign(human_gas_cost); + return (Err(e), gas_cost); + } + let new_human = new_human.unwrap(); + + if input == new_human { + (Ok(()), gas_cost) + } else { + ( + Err(BackendError::user_err(format!( + "Address invalid : {}", + input + ))), + gas_cost, + ) + } + } + + fn addr_canonicalize(&self, human: &str) -> cosmwasm_vm::BackendResult> { let gas_cost = GasInfo::with_externally_used(GAS_COST_CANONICALIZE); - if address.trim().is_empty() { + if human.trim().is_empty() { return ( Err(BackendError::Unknown { msg: "empty address string is not allowed".to_string(), @@ -82,12 +112,13 @@ impl BackendApi for RealApi { ); } - (bytes_from_bech32(address, &self.get_prefix()), gas_cost) + (bytes_from_bech32(human, &self.get_prefix()), gas_cost) } - fn human_address(&self, canon: &[u8]) -> (Result, GasInfo) { + + fn addr_humanize(&self, canonical: &[u8]) -> cosmwasm_vm::BackendResult { let gas_cost = GasInfo::with_externally_used(GAS_COST_HUMANIZE); - if canon.len() != SHORT_CANON_LEN && canon.len() != LONG_CANON_LEN { + if canonical.len() != SHORT_CANON_LEN && canonical.len() != LONG_CANON_LEN { return ( Err(BackendError::Unknown { msg: "Canon address doesn't have the right length".to_string(), @@ -96,11 +127,11 @@ impl BackendApi for RealApi { ); } - if canon.is_empty() { + if canonical.is_empty() { return (Ok("".to_string()), gas_cost); } - let human = bech32::encode(&self.get_prefix(), canon.to_base32(), Variant::Bech32) + let human = bech32::encode(&self.get_prefix(), canonical.to_base32(), Variant::Bech32) .map_err(|e| BackendError::Unknown { msg: e.to_string() }); (human, gas_cost) diff --git a/src/wasm_emulation/contract.rs b/src/wasm_emulation/contract.rs index fe711b26..8bf29f83 100644 --- a/src/wasm_emulation/contract.rs +++ b/src/wasm_emulation/contract.rs @@ -3,11 +3,13 @@ use crate::wasm_emulation::input::ReplyArgs; use crate::wasm_emulation::output::StorageChanges; use crate::wasm_emulation::query::MockQuerier; use crate::wasm_emulation::storage::DualStorage; +use cosmwasm_std::Addr; +use cosmwasm_std::Checksum; use cosmwasm_std::CustomMsg; use cosmwasm_std::StdError; use cosmwasm_vm::{ call_execute, call_instantiate, call_migrate, call_query, call_reply, call_sudo, Backend, - BackendApi, Checksum, Instance, InstanceOptions, Querier, Size, + BackendApi, Instance, InstanceOptions, Querier, Size, }; use cw_orch::daemon::queriers::CosmWasm; @@ -57,11 +59,10 @@ fn apply_storage_changes(storage: &mut dyn Storage, output: &WasmRunnerOu /// higher than the limit for a single execution that we have in the production setup. const DEFAULT_GAS_LIMIT: u64 = 500_000_000_000_000; // ~0.5s const DEFAULT_MEMORY_LIMIT: Option = Some(Size::mebi(16)); -const DEFAULT_PRINT_DEBUG: bool = true; #[derive(Serialize, Deserialize, Debug, Clone)] pub struct DistantContract { - pub contract_addr: String, + pub contract_addr: Addr, } #[derive(Serialize, Deserialize, Debug, Clone)] @@ -106,7 +107,9 @@ impl WasmContract { } pub fn new_distant_contract(contract_addr: String) -> Self { - Self::DistantContract(DistantContract { contract_addr }) + Self::DistantContract(DistantContract { + contract_addr: Addr::unchecked(contract_addr), + }) } pub fn new_distant_code_id(code_id: u64) -> Self { @@ -175,7 +178,6 @@ impl WasmContract { }; let options = InstanceOptions { gas_limit: DEFAULT_GAS_LIMIT, - print_debug: DEFAULT_PRINT_DEBUG, }; let memory_limit = DEFAULT_MEMORY_LIMIT; diff --git a/src/wasm_emulation/query/bank.rs b/src/wasm_emulation/query/bank.rs index 87ea1b27..5987fed1 100644 --- a/src/wasm_emulation/query/bank.rs +++ b/src/wasm_emulation/query/bank.rs @@ -86,18 +86,16 @@ impl BankQuerier { let query_result = self .remote .rt - .block_on(querier._balance(address, Some(denom.clone()))); + .block_on(querier._balance(&Addr::unchecked(address), Some(denom.clone()))); if let Ok(distant_amount) = query_result { amount = Some(distant_amount[0].amount) } } - let bank_res = BalanceResponse { - amount: Coin { - amount: amount.unwrap(), - denom: denom.to_string(), - }, - }; + let bank_res = BalanceResponse::new(Coin { + amount: amount.unwrap(), + denom: denom.to_string(), + }); to_json_binary(&bank_res).into() } BankQuery::AllBalances { address } => { @@ -110,16 +108,16 @@ impl BankQuerier { channel: self.remote.channel.clone(), rt_handle: Some(self.remote.rt.clone()), }; - let query_result: Result, _> = - self.remote.rt.block_on(querier._balance(address, None)); + let query_result: Result, _> = self + .remote + .rt + .block_on(querier._balance(&Addr::unchecked(address), None)); if let Ok(distant_amount) = query_result { amount = Some(distant_amount) } } - let bank_res = AllBalanceResponse { - amount: amount.unwrap(), - }; + let bank_res = AllBalanceResponse::new(amount.unwrap()); to_json_binary(&bank_res).into() } &_ => panic!("Not implemented {:?}", request), diff --git a/src/wasm_emulation/query/mock_querier.rs b/src/wasm_emulation/query/mock_querier.rs index 3894f4f6..972a237d 100644 --- a/src/wasm_emulation/query/mock_querier.rs +++ b/src/wasm_emulation/query/mock_querier.rs @@ -191,12 +191,19 @@ impl< QueryRequest::Staking(staking_query) => self.staking.query(staking_query), QueryRequest::Wasm(msg) => self.wasm.query(self.remote.clone(), msg), + #[allow(deprecated)] QueryRequest::Stargate { .. } => ( SystemResult::Err(SystemError::UnsupportedRequest { kind: "Stargate".to_string(), }), GasInfo::with_externally_used(GAS_COST_QUERY_ERROR), ), + QueryRequest::Grpc(_req) => ( + SystemResult::Err(SystemError::UnsupportedRequest { + kind: "Stargate".to_string(), + }), + GasInfo::with_externally_used(GAS_COST_QUERY_ERROR), + ), &_ => panic!("Query Type Not implemented"), } } diff --git a/src/wasm_emulation/query/staking.rs b/src/wasm_emulation/query/staking.rs index fce84a62..277e3158 100644 --- a/src/wasm_emulation/query/staking.rs +++ b/src/wasm_emulation/query/staking.rs @@ -34,15 +34,11 @@ impl StakingQuerier { pub fn query(&self, request: &StakingQuery) -> QueryResultWithGas { let contract_result: ContractResult = match request { StakingQuery::BondedDenom {} => { - let res = BondedDenomResponse { - denom: self.denom.clone(), - }; + let res = BondedDenomResponse::new(self.denom.clone()); to_json_binary(&res).into() } StakingQuery::AllValidators {} => { - let res = AllValidatorsResponse { - validators: self.validators.clone(), - }; + let res = AllValidatorsResponse::new(self.validators.clone()); to_json_binary(&res).into() } StakingQuery::Validator { address } => { @@ -51,7 +47,7 @@ impl StakingQuerier { .iter() .find(|validator| validator.address == *address) .cloned(); - let res = ValidatorResponse { validator }; + let res = ValidatorResponse::new(validator); to_json_binary(&res).into() } StakingQuery::AllDelegations { delegator } => { @@ -62,7 +58,7 @@ impl StakingQuerier { .cloned() .map(|d| d.into()) .collect(); - let res = AllDelegationsResponse { delegations }; + let res = AllDelegationsResponse::new(delegations); to_json_binary(&res).into() } StakingQuery::Delegation { @@ -73,9 +69,7 @@ impl StakingQuerier { .delegations .iter() .find(|d| d.delegator.as_str() == delegator && d.validator == *validator); - let res = DelegationResponse { - delegation: delegation.cloned(), - }; + let res = DelegationResponse::new(delegation.cloned()); to_json_binary(&res).into() } &_ => panic!("Not implemented {:?}", request), diff --git a/src/wasm_emulation/query/wasm.rs b/src/wasm_emulation/query/wasm.rs index bb6b960f..a4eb2914 100644 --- a/src/wasm_emulation/query/wasm.rs +++ b/src/wasm_emulation/query/wasm.rs @@ -72,10 +72,8 @@ impl< ); } }; - let mut response = ContractInfoResponse::default(); - response.code_id = data.code_id; - response.creator = data.creator.to_string(); - response.admin = data.admin.map(|a| a.to_string()); + let response = + ContractInfoResponse::new(data.code_id, data.creator, data.admin, false, None); ( SystemResult::Ok(to_json_binary(&response).into()), GasInfo::with_externally_used(GAS_COST_CONTRACT_INFO), @@ -104,7 +102,7 @@ impl< SystemResult::Ok( WasmRemoteQuerier::raw_query( remote, - contract_addr.clone(), + &Addr::unchecked(contract_addr), key.clone(), ) .map(Into::into) diff --git a/src/wasm_emulation/storage/analyzer.rs b/src/wasm_emulation/storage/analyzer.rs index 9f7d7310..660aa935 100644 --- a/src/wasm_emulation/storage/analyzer.rs +++ b/src/wasm_emulation/storage/analyzer.rs @@ -146,10 +146,10 @@ impl StorageAnalyzer { .into_iter() .for_each(|(contract_addr, key, value)| { // We look for the data at that key on the contract - let distant_data = self - .remote - .rt - .block_on(wasm_querier._contract_raw_state(contract_addr.clone(), key.clone())); + let distant_data = self.remote.rt.block_on( + wasm_querier + ._contract_raw_state(&Addr::unchecked(contract_addr.clone()), key.clone()), + ); if let Ok(data) = distant_data { let local_json: Json = @@ -234,7 +234,7 @@ impl StorageAnalyzer { .into_iter() .for_each(|(addr, balances)| { // We look for the data at that key on the contract - let distant_data = bank_querier.balance(addr.clone(), None); + let distant_data = bank_querier.balance(&addr, None); if let Ok(distant_coins) = distant_data { let distant_coins = serde_json::to_string(&distant_coins).unwrap(); diff --git a/src/wasm_emulation/storage/dual_std_storage.rs b/src/wasm_emulation/storage/dual_std_storage.rs index 9c21f545..4f5c317a 100644 --- a/src/wasm_emulation/storage/dual_std_storage.rs +++ b/src/wasm_emulation/storage/dual_std_storage.rs @@ -2,7 +2,7 @@ use crate::wasm_emulation::channel::RemoteChannel; use cosmrs::proto::cosmos::base::query::v1beta1::PageRequest; use cosmrs::proto::cosmwasm::wasm::v1::Model; -use cosmwasm_std::Record; +use cosmwasm_std::{Addr, Record}; use cosmwasm_std::{Order, Storage}; use cw_orch::daemon::queriers::CosmWasm; use num_bigint::{BigInt, Sign}; @@ -39,7 +39,7 @@ const DISTANT_LIMIT: u64 = 5u64; struct DistantIter { remote: RemoteChannel, - contract_addr: String, + contract_addr: Addr, data: Vec, position: usize, key: Option>, // if set to None, there is no more keys to investigate in the distant container @@ -73,7 +73,7 @@ impl<'i> Iterator for Iter<'i> { .remote .rt .block_on(wasm_querier._all_contract_state( - self.distant_iter.contract_addr.clone(), + &self.distant_iter.contract_addr, Some(PageRequest { key: self.distant_iter.key.clone().unwrap(), offset: 0, @@ -136,7 +136,7 @@ pub struct DualStorage<'a> { pub local_storage: Box, pub removed_keys: HashSet>, pub remote: RemoteChannel, - pub contract_addr: String, + pub contract_addr: Addr, } impl<'a> DualStorage<'a> { @@ -149,7 +149,7 @@ impl<'a> DualStorage<'a> { local_storage, remote, removed_keys: HashSet::default(), - contract_addr, + contract_addr: Addr::unchecked(contract_addr), }) } } @@ -162,9 +162,10 @@ impl<'a> Storage for DualStorage<'a> { if !self.removed_keys.contains(key) && value.as_ref().is_none() { let wasm_querier = CosmWasm::new_sync(self.remote.channel.clone(), &self.remote.rt); - let distant_result = self.remote.rt.block_on( - wasm_querier._contract_raw_state(self.contract_addr.clone(), key.to_vec()), - ); + let distant_result = self + .remote + .rt + .block_on(wasm_querier._contract_raw_state(&self.contract_addr, key.to_vec())); if let Ok(result) = distant_result { if !result.data.is_empty() { diff --git a/src/wasm_emulation/storage/dual_storage.rs b/src/wasm_emulation/storage/dual_storage.rs index e004fbf1..bc6623d8 100644 --- a/src/wasm_emulation/storage/dual_storage.rs +++ b/src/wasm_emulation/storage/dual_storage.rs @@ -5,8 +5,8 @@ use crate::wasm_emulation::storage::CLONE_TESTING_STORAGE_LOG; use super::mock_storage::MockStorage; use cosmrs::proto::cosmos::base::query::v1beta1::PageRequest; use cosmrs::proto::cosmwasm::wasm::v1::Model; -use cosmwasm_std::Order; use cosmwasm_std::Record; +use cosmwasm_std::{Addr, Order}; use cosmwasm_vm::BackendError; use cosmwasm_vm::BackendResult; use cosmwasm_vm::GasInfo; @@ -67,7 +67,7 @@ pub struct DualStorage { pub local_storage: MockStorage, pub removed_keys: HashSet>, pub remote: RemoteChannel, - pub contract_addr: String, + pub contract_addr: Addr, iterators: HashMap, } @@ -88,7 +88,7 @@ impl DualStorage { local_storage, remote, removed_keys: HashSet::default(), - contract_addr, + contract_addr: Addr::unchecked(contract_addr), iterators: HashMap::new(), }) } @@ -111,9 +111,10 @@ impl Storage for DualStorage { log::debug!(target: CLONE_TESTING_STORAGE_LOG, "Value not set locally, fetching remote key"); let wasm_querier = CosmWasm::new_sync(self.remote.channel.clone(), &self.remote.rt); - let distant_result = self.remote.rt.block_on( - wasm_querier._contract_raw_state(self.contract_addr.clone(), key.to_vec()), - ); + let distant_result = self + .remote + .rt + .block_on(wasm_querier._contract_raw_state(&self.contract_addr, key.to_vec())); if let Ok(result) = distant_result { if !result.data.is_empty() { @@ -202,7 +203,7 @@ impl Storage for DualStorage { .remote .rt .block_on(wasm_querier._all_contract_state( - self.contract_addr.clone(), + &self.contract_addr, Some(PageRequest { key: iterator.distant_iter.key.clone().unwrap(), offset: 0, From d4480a51d35f80bd07376a8caf766f9eab96ca12 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 3 Sep 2024 10:55:17 +0000 Subject: [PATCH 57/81] Removed features --- Cargo.lock | 23 ++++------------------- src/bank.rs | 6 +----- src/executor.rs | 1 - src/tests/test_app.rs | 4 ---- src/wasm.rs | 11 +++++------ src/wasm_emulation/query/wasm.rs | 11 +++++------ 6 files changed, 15 insertions(+), 41 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dbb9b53c..c9197fa0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -374,7 +374,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c8d66485a3a2ea485c1913c4572ce0256067a5377ac8c75c4960e1cda98605f" dependencies = [ "bitcoin-internals", - "bitcoin_hashes 0.14.0", + "bitcoin_hashes", ] [[package]] @@ -434,7 +434,7 @@ dependencies = [ "bitcoin-internals", "bitcoin-io", "bitcoin-units", - "bitcoin_hashes 0.14.0", + "bitcoin_hashes", "hex-conservative", "hex_lit", "secp256k1", @@ -452,12 +452,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "340e09e8399c7bd8912f495af6aa58bea0c9214773417ffaa8f6460f93aaee56" -[[package]] -name = "bitcoin-private" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73290177011694f38ec25e165d0387ab7ea749a4b81cd4c80dae5988229f7a57" - [[package]] name = "bitcoin-units" version = "0.1.2" @@ -467,15 +461,6 @@ dependencies = [ "bitcoin-internals", ] -[[package]] -name = "bitcoin_hashes" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d7066118b13d4b20b23645932dfb3a81ce7e29f95726c2036fa33cd7b092501" -dependencies = [ - "bitcoin-private", -] - [[package]] name = "bitcoin_hashes" version = "0.14.0" @@ -3102,7 +3087,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acf0c195eebb4af52c752bec4f52f645da98b6e92077a04110c7f349477ae5ac" dependencies = [ "anyhow", - "itertools 0.12.1", + "itertools 0.13.0", "proc-macro2", "quote", "syn 2.0.68", @@ -3667,7 +3652,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e0cc0f1cf93f4969faf3ea1c7d8a9faed25918d96affa959720823dfe86d4f3" dependencies = [ - "bitcoin_hashes 0.12.0", + "bitcoin_hashes", "secp256k1-sys", ] diff --git a/src/bank.rs b/src/bank.rs index d2a88947..ca08475f 100644 --- a/src/bank.rs +++ b/src/bank.rs @@ -11,7 +11,6 @@ use cosmwasm_std::{ coin, to_json_binary, Addr, AllBalanceResponse, Api, BalanceResponse, BankMsg, BankQuery, Binary, BlockInfo, Coin, Event, Order, Querier, Storage, }; -#[cfg(feature = "cosmwasm_1_1")] use cosmwasm_std::{StdResult, SupplyResponse, Uint128}; use cw_storage_plus::Map; use cw_utils::NativeBalance; @@ -84,7 +83,6 @@ impl BankKeeper { } } - #[cfg(feature = "cosmwasm_1_1")] fn get_supply(&self, bank_storage: &dyn Storage, denom: String) -> AnyResult { let supply: Uint128 = BALANCES .range(bank_storage, None, None, Order::Ascending) @@ -241,11 +239,9 @@ impl Module for BankKeeper { let res = BalanceResponse::new(amount); Ok(to_json_binary(&res)?) } - #[cfg(feature = "cosmwasm_1_1")] BankQuery::Supply { denom } => { let amount = self.get_supply(&bank_storage, denom)?; - let mut res = SupplyResponse::default(); - res.amount = amount; + let res = SupplyResponse::new(amount); Ok(to_json_binary(&res)?) } q => bail!("Unsupported bank query: {:?}", q), diff --git a/src/executor.rs b/src/executor.rs index b924724b..492be9bb 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -97,7 +97,6 @@ where /// Instantiates a new contract and returns its predictable address. /// This is a helper function around [execute][Self::execute] function /// with `WasmMsg::Instantiate2` message. - #[cfg(feature = "cosmwasm_1_2")] fn instantiate2_contract( &mut self, code_id: u64, diff --git a/src/tests/test_app.rs b/src/tests/test_app.rs index 6d9817a1..dad2e1b6 100644 --- a/src/tests/test_app.rs +++ b/src/tests/test_app.rs @@ -165,7 +165,6 @@ fn multi_level_bank_cache() { } #[test] -#[cfg(feature = "cosmwasm_1_2")] fn duplicate_contract_code() { // set up the multi-test application let mut app = App::default(); @@ -1554,7 +1553,6 @@ mod response_validation { mod contract_instantiation { #[test] - #[cfg(feature = "cosmwasm_1_2")] fn instantiate2_works() { use super::*; @@ -1590,7 +1588,6 @@ mod contract_instantiation { mod wasm_queries { #[test] - #[cfg(feature = "cosmwasm_1_2")] fn query_existing_code_info() { use super::*; let mut app = App::default(); @@ -1602,7 +1599,6 @@ mod wasm_queries { } #[test] - #[cfg(feature = "cosmwasm_1_2")] fn query_non_existing_code_info() { use super::*; let app = App::default(); diff --git a/src/wasm.rs b/src/wasm.rs index e1a15d23..48af5b55 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -201,13 +201,13 @@ where ); to_json_binary(&res).map_err(Into::into) } - #[cfg(feature = "cosmwasm_1_2")] WasmQuery::CodeInfo { code_id } => { let code_data = self.code_data(code_id)?; - let mut res = cosmwasm_std::CodeInfoResponse::default(); - res.code_id = code_id; - res.creator = code_data.creator.to_string(); - res.checksum = code_data.checksum.clone(); + let res = cosmwasm_std::CodeInfoResponse::new( + code_id, + code_data.creator, + code_data.checksum, + ); to_json_binary(&res).map_err(Into::into) } other => bail!(Error::UnsupportedWasmQuery(other)), @@ -656,7 +656,6 @@ where } => self.process_wasm_msg_instantiate( api, storage, router, block, sender, admin, code_id, msg, funds, label, None, ), - #[cfg(feature = "cosmwasm_1_2")] WasmMsg::Instantiate2 { admin, code_id, diff --git a/src/wasm_emulation/query/wasm.rs b/src/wasm_emulation/query/wasm.rs index a4eb2914..bf9915e1 100644 --- a/src/wasm_emulation/query/wasm.rs +++ b/src/wasm_emulation/query/wasm.rs @@ -214,7 +214,6 @@ impl< GasInfo::with_externally_used(GAS_COST_ALL_QUERIES), ) } - #[cfg(feature = "cosmwasm_1_2")] WasmQuery::CodeInfo { code_id } => { let code_data = self .fork_state @@ -223,11 +222,11 @@ impl< .code_data .get(&(*code_id as usize)); let res = if let Some(code_data) = code_data { - let mut res = cosmwasm_std::CodeInfoResponse::default(); - res.code_id = *code_id; - res.creator = code_data.creator.to_string(); - res.checksum = code_data.checksum.clone(); - res + cosmwasm_std::CodeInfoResponse::new( + *code_id, + code_data.creator.clone(), + code_data.checksum, + ) } else { let maybe_code_info = WasmRemoteQuerier::code_info(self.fork_state.remote.clone(), *code_id); From 0d288076bfbd885e65081383b9f78b98e63c1c0c Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 3 Sep 2024 13:12:53 +0000 Subject: [PATCH 58/81] Small post-PR-fixes --- examples/cavern_test_app.rs | 2 +- examples/cousin_test.rs | 2 +- examples/test_app.rs | 2 +- src/wasm_emulation/channel.rs | 6 +----- src/wasm_emulation/contract.rs | 13 ++----------- 5 files changed, 6 insertions(+), 19 deletions(-) diff --git a/examples/cavern_test_app.rs b/examples/cavern_test_app.rs index 757a1aa3..895e3b61 100644 --- a/examples/cavern_test_app.rs +++ b/examples/cavern_test_app.rs @@ -58,7 +58,7 @@ pub fn test() -> anyhow::Result<()> { let runtime = Runtime::new()?; let chain = PHOENIX_1; - let remote_channel = RemoteChannel::new(&runtime, chain.clone(), "")?; + let remote_channel = RemoteChannel::new(&runtime, chain.clone())?; let wasm = WasmKeeper::::new() .with_remote(remote_channel.clone()) diff --git a/examples/cousin_test.rs b/examples/cousin_test.rs index 195b9768..06b08cda 100644 --- a/examples/cousin_test.rs +++ b/examples/cousin_test.rs @@ -70,7 +70,7 @@ fn test() -> AnyResult<()> { let runtime = Runtime::new()?; let chain = PHOENIX_1; - let remote_channel = RemoteChannel::new(&runtime, chain.clone(), "")?; + let remote_channel = RemoteChannel::new(&runtime, chain.clone())?; let wasm = WasmKeeper::::new() .with_remote(remote_channel.clone()) diff --git a/examples/test_app.rs b/examples/test_app.rs index d9cacca6..d0260465 100644 --- a/examples/test_app.rs +++ b/examples/test_app.rs @@ -20,7 +20,7 @@ pub fn test() -> anyhow::Result<()> { let runtime = Runtime::new()?; let chain = PHOENIX_1; - let remote_channel = RemoteChannel::new(&runtime, chain.clone(), "")?; + let remote_channel = RemoteChannel::new(&runtime, chain.clone())?; let wasm = WasmKeeper::::new().with_remote(remote_channel.clone()); let bank = BankKeeper::new().with_remote(remote_channel.clone()); diff --git a/src/wasm_emulation/channel.rs b/src/wasm_emulation/channel.rs index fb818e80..65b66bf5 100644 --- a/src/wasm_emulation/channel.rs +++ b/src/wasm_emulation/channel.rs @@ -19,11 +19,7 @@ pub struct RemoteChannel { } impl RemoteChannel { - pub fn new( - rt: &Runtime, - chain: impl Into, - _: impl Into, - ) -> AnyResult { + pub fn new(rt: &Runtime, chain: impl Into) -> AnyResult { let chain: ChainInfoOwned = chain.into(); Ok(Self { rt: rt.handle().clone(), diff --git a/src/wasm_emulation/contract.rs b/src/wasm_emulation/contract.rs index b83571f5..c7ade9c2 100644 --- a/src/wasm_emulation/contract.rs +++ b/src/wasm_emulation/contract.rs @@ -465,6 +465,7 @@ mod wasm_caching { }) } + #[repr(u8)] enum WasmCachingStatus { /// Currently writing Writing, @@ -474,16 +475,6 @@ mod wasm_caching { Corrupted, } - impl From for u8 { - fn from(value: WasmCachingStatus) -> Self { - match value { - WasmCachingStatus::Writing => 0, - WasmCachingStatus::Ready => 1, - WasmCachingStatus::Corrupted => 2, - } - } - } - impl From for WasmCachingStatus { fn from(value: u8) -> Self { match value { @@ -497,7 +488,7 @@ mod wasm_caching { impl WasmCachingStatus { pub fn set_status(self, file: &fs::File) { - file.write_at(&[self.into()], 0) + file.write_at(&[self as u8], 0) .expect("Failed to update wasm caching status"); } From b699f808082014d166a7244cee159536ab9c796e Mon Sep 17 00:00:00 2001 From: Kayanski Date: Wed, 4 Sep 2024 08:23:16 +0000 Subject: [PATCH 59/81] First try at keeping modules in memory --- Cargo.lock | 2 +- Cargo.toml | 4 +- src/app.rs | 4 +- src/queries/wasm.rs | 2 +- src/wasm.rs | 42 ++++++++++++---- src/wasm_emulation/contract.rs | 86 ++++++++++++++++++++++++++++---- src/wasm_emulation/instance.rs | 30 +++++++++++ src/wasm_emulation/mod.rs | 2 + src/wasm_emulation/query/wasm.rs | 10 +++- 9 files changed, 154 insertions(+), 28 deletions(-) create mode 100644 src/wasm_emulation/instance.rs diff --git a/Cargo.lock b/Cargo.lock index 48dbba19..8ea4e751 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -649,7 +649,7 @@ dependencies = [ [[package]] name = "clone-cw-multi-test" -version = "0.5.0" +version = "0.6.0-alpha.1" dependencies = [ "anyhow", "bech32 0.9.1", diff --git a/Cargo.toml b/Cargo.toml index a419b6d3..9946497d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clone-cw-multi-test" -version = "0.5.0" +version = "0.6.0-alpha.1" authors = ["Ethan Frey "] edition = "2021" description = "Testing tools for multi-contract interactions. Helps simulating chain behavior with on-chain storage locally" @@ -38,7 +38,7 @@ tokio = "1.28.2" tonic = "0.12.2" ## Emulation -cosmwasm-vm = { version = "2.1.3", features = [ +cosmwasm-vm = { version = "2.1.0", features = [ "staking", "stargate", "iterator", diff --git a/src/app.rs b/src/app.rs index 69258653..508b9842 100644 --- a/src/app.rs +++ b/src/app.rs @@ -237,7 +237,7 @@ where /// Registers contract code (like uploading wasm bytecode on a chain), /// so it can later be used to instantiate a contract. /// Only for wasm codes - pub fn store_wasm_code(&mut self, code: WasmContract) -> u64 { + pub fn store_wasm_code(&mut self, code: Vec) -> u64 { self.init_modules(|router, _, _| { router .wasm @@ -257,7 +257,7 @@ where /// Registers contract code (like [store_code](Self::store_code)), /// but takes the address of the code creator as an additional argument. - pub fn store_wasm_code_with_creator(&mut self, creator: Addr, code: WasmContract) -> u64 { + pub fn store_wasm_code_with_creator(&mut self, creator: Addr, code: Vec) -> u64 { self.init_modules(|router, _, _| router.wasm.store_wasm_code(creator, code)) } diff --git a/src/queries/wasm.rs b/src/queries/wasm.rs index a78e40e7..9a3c2a10 100644 --- a/src/queries/wasm.rs +++ b/src/queries/wasm.rs @@ -67,7 +67,7 @@ impl AllWasmQuerier for WasmKeeper { Ok(WasmStorage { contracts, storage: all_local_state, - codes: self.code_base.clone(), + codes: self.code_base.borrow().clone(), code_data: self.code_data.clone(), }) } diff --git a/src/wasm.rs b/src/wasm.rs index 48af5b55..832f2d7d 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -9,8 +9,9 @@ use crate::prefixed_storage::{prefixed, prefixed_read, PrefixedStorage, Readonly use crate::queries::wasm::WasmRemoteQuerier; use crate::transactions::transactional; use crate::wasm_emulation::channel::RemoteChannel; -use crate::wasm_emulation::contract::WasmContract; +use crate::wasm_emulation::contract::{LocalWasmContract, WasmContract}; use crate::wasm_emulation::input::QuerierStorage; +use crate::wasm_emulation::instance::create_module; use crate::wasm_emulation::query::mock_querier::{ForkState, LocalForkedState}; use crate::wasm_emulation::query::AllWasmQuerier; use cosmwasm_std::testing::mock_wasmd_attr; @@ -26,6 +27,7 @@ use prost::Message; use schemars::JsonSchema; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; +use std::cell::RefCell; use std::collections::HashMap; use std::fmt::Debug; @@ -116,7 +118,7 @@ pub trait Wasm: AllWasmQuerier { fn store_code(&mut self, creator: Addr, code: Box>) -> u64; /// Stores the contract's code and returns an identifier of the stored contract's code. - fn store_wasm_code(&mut self, creator: Addr, code: WasmContract) -> u64; + fn store_wasm_code(&mut self, creator: Addr, code: Vec) -> u64; /// Returns `ContractData` for the contract with specified address. fn contract_data(&self, storage: &dyn Storage, address: &Addr) -> AnyResult; @@ -128,7 +130,7 @@ pub trait Wasm: AllWasmQuerier { pub type LocalRustContract = *mut dyn Contract; pub struct WasmKeeper { /// Contract codes that stand for wasm code in real-life blockchain. - pub code_base: HashMap, + pub code_base: RefCell>, /// Contract codes that stand for rust code living in the current instance /// We also associate the queries to them to make sure we are able to use them with the vm instance pub rust_codes: HashMap>, @@ -147,7 +149,7 @@ pub struct WasmKeeper { impl Default for WasmKeeper { fn default() -> WasmKeeper { Self { - code_base: HashMap::new(), + code_base: HashMap::new().into(), code_data: HashMap::new(), address_generator: Box::new(SimpleAddressGenerator), checksum_generator: Box::new(SimpleChecksumGenerator), @@ -258,9 +260,16 @@ where /// Stores the contract's code in the in-memory lookup table. /// Returns an identifier of the stored contract code. - fn store_wasm_code(&mut self, creator: Addr, code: WasmContract) -> u64 { - let code_id = self.code_base.len() + 1 + LOCAL_WASM_CODE_OFFSET; - self.code_base.insert(code_id, code); + fn store_wasm_code(&mut self, creator: Addr, code: Vec) -> u64 { + let code_id = self.code_base.borrow().len() + 1 + LOCAL_WASM_CODE_OFFSET; + let code = WasmContract::Local(LocalWasmContract { + module: create_module(&code).unwrap(), + code, + }); + println!("Storing wasm code"); + + self.code_base.borrow_mut().insert(code_id, code); + println!("Stored wasm code"); let checksum = self.checksum_generator.checksum(&creator, code_id as u64); self.code_data.insert( code_id, @@ -349,15 +358,28 @@ where 'a: 'b, { let code_data = self.code_data(code_id)?; - let code = self.code_base.get(&code_data.code_base_id); + let code = self + .code_base + .borrow() + .get(&code_data.code_base_id) + .cloned(); if let Some(code) = code { - Ok(ContractBox::Borrowed(code)) + Ok(ContractBox::Owned(Box::new(code))) } else if let Some(&rust_code) = self.rust_codes.get(&code_data.code_base_id) { Ok(ContractBox::Borrowed(unsafe { rust_code.as_ref().unwrap() })) } else { - let wasm_contract = WasmContract::new_distant_code_id(code_id); + // We fetch the code and save the corresponding module in memory + let wasm_contract = + WasmContract::new_distant_code_id(code_id, self.remote.clone().unwrap()); + + // We save it in memory + self.code_base + .borrow_mut() + .insert(code_id as usize, wasm_contract.clone()); + + // And return a Owned reference Ok(ContractBox::Owned(Box::new(wasm_contract))) } } diff --git a/src/wasm_emulation/contract.rs b/src/wasm_emulation/contract.rs index bb481234..a19f87e5 100644 --- a/src/wasm_emulation/contract.rs +++ b/src/wasm_emulation/contract.rs @@ -1,5 +1,6 @@ use crate::wasm_emulation::api::RealApi; use crate::wasm_emulation::input::ReplyArgs; +use crate::wasm_emulation::instance::instance_from_reused_module; use crate::wasm_emulation::output::StorageChanges; use crate::wasm_emulation::query::MockQuerier; use crate::wasm_emulation::storage::DualStorage; @@ -19,6 +20,7 @@ use cosmwasm_std::Storage; use serde::de::DeserializeOwned; use serde::Deserialize; use serde::Serialize; +use wasmer::Module; use crate::wasm_emulation::input::InstanceArguments; use crate::wasm_emulation::output::WasmRunnerOutput; @@ -32,12 +34,14 @@ use cosmwasm_std::{Binary, CustomQuery, Deps, DepsMut, Env, MessageInfo, Reply, use anyhow::Result as AnyResult; +use super::channel::RemoteChannel; use super::input::ExecuteArgs; use super::input::InstantiateArgs; use super::input::MigrateArgs; use super::input::QueryArgs; use super::input::SudoArgs; use super::input::WasmFunction; +use super::instance::create_module; use super::output::WasmOutput; use super::query::mock_querier::ForkState; @@ -60,19 +64,22 @@ fn apply_storage_changes(storage: &mut dyn Storage, output: &WasmRunnerOu const DEFAULT_GAS_LIMIT: u64 = 500_000_000_000_000; // ~0.5s const DEFAULT_MEMORY_LIMIT: Option = Some(Size::mebi(16)); -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Debug, Clone)] pub struct DistantContract { pub contract_addr: Addr, + pub module: Module, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Debug, Clone)] pub struct DistantCodeId { pub code_id: u64, + pub module: Module, } -#[derive(Serialize, Deserialize, Clone)] +#[derive(Clone)] pub struct LocalWasmContract { pub code: Vec, + pub module: Module, } #[derive(Debug, Clone)] @@ -103,17 +110,61 @@ impl WasmContract { ]), ) .unwrap(); - Self::Local(LocalWasmContract { code }) + Self::Local(LocalWasmContract { + code: code.clone(), + module: create_module(&code).unwrap(), + }) } - pub fn new_distant_contract(contract_addr: String) -> Self { + pub fn new_distant_contract(contract_addr: String, remote: RemoteChannel) -> Self { + let contract_addr = Addr::unchecked(contract_addr); + let code = { + let wasm_querier = CosmWasm::new_sync(remote.channel.clone(), &remote.rt); + + let code_info = remote + .rt + .block_on(wasm_querier._contract_info(&contract_addr)) + .unwrap(); + + let cache_key = format!("{}:{}", remote.chain_id, code_info.code_id); + + let code = wasm_caching::maybe_cached_wasm(cache_key, || { + remote + .rt + .block_on(wasm_querier._code_data(code_info.code_id)) + .map_err(Into::into) + }) + .unwrap(); + + code + }; + Self::DistantContract(DistantContract { contract_addr: Addr::unchecked(contract_addr), + module: create_module(&code).unwrap(), }) } - pub fn new_distant_code_id(code_id: u64) -> Self { - Self::DistantCodeId(DistantCodeId { code_id }) + pub fn new_distant_code_id(code_id: u64, remote: RemoteChannel) -> Self { + let code = { + let wasm_querier = CosmWasm::new_sync(remote.channel.clone(), &remote.rt); + + let cache_key = format!("{}:{}", remote.chain_id, &code_id); + + let code = wasm_caching::maybe_cached_wasm(cache_key, || { + remote + .rt + .block_on(wasm_querier._code_data(code_id)) + .map_err(|e| e.into()) + }) + .unwrap(); + + code + }; + Self::DistantCodeId(DistantCodeId { + code_id, + module: create_module(&code).unwrap(), + }) } pub fn get_code( @@ -122,7 +173,7 @@ impl WasmContract { ) -> AnyResult> { match self { WasmContract::Local(LocalWasmContract { code, .. }) => Ok(code.clone()), - WasmContract::DistantContract(DistantContract { contract_addr }) => { + WasmContract::DistantContract(DistantContract { contract_addr, .. }) => { let wasm_querier = CosmWasm::new_sync(fork_state.remote.channel.clone(), &fork_state.remote.rt); @@ -143,7 +194,7 @@ impl WasmContract { Ok(code) } - WasmContract::DistantCodeId(DistantCodeId { code_id }) => { + WasmContract::DistantCodeId(DistantCodeId { code_id, .. }) => { let wasm_querier = CosmWasm::new_sync(fork_state.remote.channel.clone(), &fork_state.remote.rt); @@ -162,6 +213,17 @@ impl WasmContract { } } + pub fn get_module(&self) -> Module { + match self { + WasmContract::Local(LocalWasmContract { code, module }) => module.clone(), + WasmContract::DistantContract(DistantContract { + contract_addr, + module, + }) => module.clone(), + WasmContract::DistantCodeId(DistantCodeId { code_id, module }) => module.clone(), + } + } + pub fn run_contract< QueryC: CustomQuery + DeserializeOwned + 'static, ExecC: CustomMsg + DeserializeOwned, @@ -176,6 +238,7 @@ impl WasmContract { } = args; let address = function.get_address(); let code = self.get_code(fork_state.clone())?; + let module = self.get_module(); let api = RealApi::new(&fork_state.remote.pub_address_prefix); @@ -195,15 +258,18 @@ impl WasmContract { let memory_limit = DEFAULT_MEMORY_LIMIT; // Then we create the instance - let mut instance = Instance::from_code(&code, backend, options, memory_limit)?; + let mut instance = instance_from_reused_module(module, backend, options, memory_limit)?; let gas_before = instance.get_gas_left(); + println!("Executing function"); // Then we call the function that we wanted to call let result = execute_function(&mut instance, function)?; + println!("function executed"); let gas_after = instance.get_gas_left(); + println!("Recycling instance"); // We return the code response + any storage change (or the whole local storage object), with serializing let mut recycled_instance = instance.recycle().unwrap(); diff --git a/src/wasm_emulation/instance.rs b/src/wasm_emulation/instance.rs new file mode 100644 index 00000000..1b479e78 --- /dev/null +++ b/src/wasm_emulation/instance.rs @@ -0,0 +1,30 @@ +use cosmwasm_vm::internals::compile; +use cosmwasm_vm::internals::{instance_from_module, make_compiling_engine}; +use cosmwasm_vm::{ + Backend, BackendApi, Instance, InstanceOptions, Querier, Size, Storage, VmResult, +}; +use wasmer::{Module, Store}; + +pub fn create_module(code: &[u8]) -> VmResult { + let engine = make_compiling_engine(None); + let module = compile(&engine, code)?; + Ok(module) +} + +/// This is the only Instance constructor that can be called from outside of cosmwasm-vm, +/// e.g. in test code that needs a customized variant of cosmwasm_vm::testing::mock_instance*. +pub fn instance_from_reused_module( + module: Module, + backend: Backend, + options: InstanceOptions, + memory_limit: Option, +) -> VmResult> +where + A: BackendApi + 'static, + S: Storage + 'static, + Q: Querier + 'static, +{ + let engine = make_compiling_engine(memory_limit); + let store = Store::new(engine); + instance_from_module(store, &module, backend, options.gas_limit, None) +} diff --git a/src/wasm_emulation/mod.rs b/src/wasm_emulation/mod.rs index 33379254..5a3b7ced 100644 --- a/src/wasm_emulation/mod.rs +++ b/src/wasm_emulation/mod.rs @@ -7,3 +7,5 @@ pub mod channel; pub mod contract; pub mod api; + +pub mod instance; diff --git a/src/wasm_emulation/query/wasm.rs b/src/wasm_emulation/query/wasm.rs index bf9915e1..a68c10f0 100644 --- a/src/wasm_emulation/query/wasm.rs +++ b/src/wasm_emulation/query/wasm.rs @@ -178,7 +178,10 @@ impl< } else { // Distant Registered Contract case >::query( - &WasmContract::new_distant_code_id(local_contract.code_id), + &WasmContract::new_distant_code_id( + local_contract.code_id, + remote.clone(), + ), deps.as_ref(), env, msg.to_vec(), @@ -188,7 +191,10 @@ impl< } else { // Distant UnRegistered Contract case >::query( - &WasmContract::new_distant_contract(contract_addr.to_string()), + &WasmContract::new_distant_contract( + contract_addr.to_string(), + remote.clone(), + ), deps.as_ref(), env, msg.to_vec(), From 08e44f905a924ca93a8855b2b801fa3cbba72ea6 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Wed, 4 Sep 2024 11:22:49 +0000 Subject: [PATCH 60/81] Fixed module and engine --- examples/counter/query.rs | 1 - examples/cousin_test.rs | 6 +- src/app.rs | 1 - src/wasm.rs | 2 - src/wasm_emulation/contract.rs | 117 ++++------------------- src/wasm_emulation/instance.rs | 14 +-- src/wasm_emulation/output.rs | 7 +- src/wasm_emulation/query/mock_querier.rs | 2 +- src/wasm_emulation/query/wasm.rs | 92 +++++++++--------- 9 files changed, 73 insertions(+), 169 deletions(-) diff --git a/examples/counter/query.rs b/examples/counter/query.rs index c160f09a..ee237c59 100644 --- a/examples/counter/query.rs +++ b/examples/counter/query.rs @@ -7,7 +7,6 @@ use crate::counter::{ pub fn count(deps: Deps) -> StdResult { let state = STATE.load(deps.storage)?; - println!("Getting the rust code count please"); Ok(GetCountResponse { count: state.count }) } diff --git a/examples/cousin_test.rs b/examples/cousin_test.rs index 06b08cda..90cdc42b 100644 --- a/examples/cousin_test.rs +++ b/examples/cousin_test.rs @@ -66,7 +66,6 @@ fn test() -> AnyResult<()> { .join("counter_contract_with_cousin.wasm"), ) .unwrap(); - let wasm_contract = WasmContract::new_local(code); let runtime = Runtime::new()?; let chain = PHOENIX_1; @@ -88,7 +87,7 @@ fn test() -> AnyResult<()> { let sender = Addr::unchecked(SENDER); let rust_code_id = app.store_code(Box::new(rust_contract)); - let wasm_code_id = app.store_wasm_code(wasm_contract); + let wasm_code_id = app.store_wasm_code(code); let counter_rust = app .instantiate_contract( @@ -112,9 +111,6 @@ fn test() -> AnyResult<()> { ) .unwrap(); - println!("Rust contract {}", counter_rust); - println!("Wasm contract {}", counter_wasm); - app.execute_contract( sender.clone(), counter_rust.clone(), diff --git a/src/app.rs b/src/app.rs index 508b9842..4d10958e 100644 --- a/src/app.rs +++ b/src/app.rs @@ -13,7 +13,6 @@ use crate::module::{FailingModule, Module}; use crate::staking::{Distribution, DistributionKeeper, StakeKeeper, Staking, StakingSudo}; use crate::transactions::transactional; use crate::wasm::{ContractData, Wasm, WasmKeeper, WasmSudo}; -use crate::wasm_emulation::contract::WasmContract; use crate::{AppBuilder, Contract, GovFailingModule, IbcFailingModule}; use cosmwasm_std::testing::{MockApi, MockStorage}; use cosmwasm_std::{ diff --git a/src/wasm.rs b/src/wasm.rs index 832f2d7d..ff281601 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -266,10 +266,8 @@ where module: create_module(&code).unwrap(), code, }); - println!("Storing wasm code"); self.code_base.borrow_mut().insert(code_id, code); - println!("Stored wasm code"); let checksum = self.checksum_generator.checksum(&creator, code_id as u64); self.code_data.insert( code_id, diff --git a/src/wasm_emulation/contract.rs b/src/wasm_emulation/contract.rs index a19f87e5..1aab8e1e 100644 --- a/src/wasm_emulation/contract.rs +++ b/src/wasm_emulation/contract.rs @@ -10,7 +10,7 @@ use cosmwasm_std::CustomMsg; use cosmwasm_std::StdError; use cosmwasm_vm::{ call_execute, call_instantiate, call_migrate, call_query, call_reply, call_sudo, Backend, - BackendApi, Instance, InstanceOptions, Querier, Size, + BackendApi, Instance, InstanceOptions, Querier, }; use cw_orch::daemon::queriers::CosmWasm; @@ -18,8 +18,7 @@ use cosmwasm_std::Order; use cosmwasm_std::Storage; use serde::de::DeserializeOwned; -use serde::Deserialize; -use serde::Serialize; +use wasmer::Engine; use wasmer::Module; use crate::wasm_emulation::input::InstanceArguments; @@ -62,30 +61,22 @@ fn apply_storage_changes(storage: &mut dyn Storage, output: &WasmRunnerOu /// number of contract executions and queries on one instance. For this reason it is significatly /// higher than the limit for a single execution that we have in the production setup. const DEFAULT_GAS_LIMIT: u64 = 500_000_000_000_000; // ~0.5s -const DEFAULT_MEMORY_LIMIT: Option = Some(Size::mebi(16)); - -#[derive(Debug, Clone)] -pub struct DistantContract { - pub contract_addr: Addr, - pub module: Module, -} #[derive(Debug, Clone)] pub struct DistantCodeId { pub code_id: u64, - pub module: Module, + pub module: (Engine, Module), } #[derive(Clone)] pub struct LocalWasmContract { pub code: Vec, - pub module: Module, + pub module: (Engine, Module), } #[derive(Debug, Clone)] pub enum WasmContract { Local(LocalWasmContract), - DistantContract(DistantContract), DistantCodeId(DistantCodeId), } @@ -116,35 +107,6 @@ impl WasmContract { }) } - pub fn new_distant_contract(contract_addr: String, remote: RemoteChannel) -> Self { - let contract_addr = Addr::unchecked(contract_addr); - let code = { - let wasm_querier = CosmWasm::new_sync(remote.channel.clone(), &remote.rt); - - let code_info = remote - .rt - .block_on(wasm_querier._contract_info(&contract_addr)) - .unwrap(); - - let cache_key = format!("{}:{}", remote.chain_id, code_info.code_id); - - let code = wasm_caching::maybe_cached_wasm(cache_key, || { - remote - .rt - .block_on(wasm_querier._code_data(code_info.code_id)) - .map_err(Into::into) - }) - .unwrap(); - - code - }; - - Self::DistantContract(DistantContract { - contract_addr: Addr::unchecked(contract_addr), - module: create_module(&code).unwrap(), - }) - } - pub fn new_distant_code_id(code_id: u64, remote: RemoteChannel) -> Self { let code = { let wasm_querier = CosmWasm::new_sync(remote.channel.clone(), &remote.rt); @@ -167,60 +129,10 @@ impl WasmContract { }) } - pub fn get_code( - &self, - fork_state: ForkState, - ) -> AnyResult> { + pub fn get_module(&self) -> (Engine, Module) { match self { - WasmContract::Local(LocalWasmContract { code, .. }) => Ok(code.clone()), - WasmContract::DistantContract(DistantContract { contract_addr, .. }) => { - let wasm_querier = - CosmWasm::new_sync(fork_state.remote.channel.clone(), &fork_state.remote.rt); - - let code_info = fork_state - .remote - .rt - .block_on(wasm_querier._contract_info(contract_addr))?; - - let cache_key = format!("{}:{}", fork_state.remote.chain_id, code_info.code_id); - - let code = wasm_caching::maybe_cached_wasm(cache_key, || { - fork_state - .remote - .rt - .block_on(wasm_querier._code_data(code_info.code_id)) - .map_err(Into::into) - })?; - - Ok(code) - } - WasmContract::DistantCodeId(DistantCodeId { code_id, .. }) => { - let wasm_querier = - CosmWasm::new_sync(fork_state.remote.channel.clone(), &fork_state.remote.rt); - - let cache_key = format!("{}:{}", fork_state.remote.chain_id, &code_id); - - let code = wasm_caching::maybe_cached_wasm(cache_key, || { - fork_state - .remote - .rt - .block_on(wasm_querier._code_data(*code_id)) - .map_err(|e| e.into()) - })?; - - Ok(code) - } - } - } - - pub fn get_module(&self) -> Module { - match self { - WasmContract::Local(LocalWasmContract { code, module }) => module.clone(), - WasmContract::DistantContract(DistantContract { - contract_addr, - module, - }) => module.clone(), - WasmContract::DistantCodeId(DistantCodeId { code_id, module }) => module.clone(), + WasmContract::Local(LocalWasmContract { module, .. }) => module.clone(), + WasmContract::DistantCodeId(DistantCodeId { module, .. }) => module.clone(), } } @@ -237,7 +149,6 @@ impl WasmContract { init_storage, } = args; let address = function.get_address(); - let code = self.get_code(fork_state.clone())?; let module = self.get_module(); let api = RealApi::new(&fork_state.remote.pub_address_prefix); @@ -255,21 +166,18 @@ impl WasmContract { let options = InstanceOptions { gas_limit: DEFAULT_GAS_LIMIT, }; - let memory_limit = DEFAULT_MEMORY_LIMIT; // Then we create the instance - let mut instance = instance_from_reused_module(module, backend, options, memory_limit)?; + + let mut instance = instance_from_reused_module(module, backend, options)?; let gas_before = instance.get_gas_left(); - println!("Executing function"); // Then we call the function that we wanted to call let result = execute_function(&mut instance, function)?; - println!("function executed"); let gas_after = instance.get_gas_left(); - println!("Recycling instance"); // We return the code response + any storage change (or the whole local storage object), with serializing let mut recycled_instance = instance.recycle().unwrap(); @@ -302,6 +210,13 @@ impl WasmContract { self ); } + + pub fn code_id(&self) -> u64 { + match self { + WasmContract::Local(_) => unimplemented!(), + WasmContract::DistantCodeId(d) => d.code_id, + } + } } impl Contract for WasmContract diff --git a/src/wasm_emulation/instance.rs b/src/wasm_emulation/instance.rs index 1b479e78..41237207 100644 --- a/src/wasm_emulation/instance.rs +++ b/src/wasm_emulation/instance.rs @@ -1,30 +1,26 @@ use cosmwasm_vm::internals::compile; use cosmwasm_vm::internals::{instance_from_module, make_compiling_engine}; -use cosmwasm_vm::{ - Backend, BackendApi, Instance, InstanceOptions, Querier, Size, Storage, VmResult, -}; -use wasmer::{Module, Store}; +use cosmwasm_vm::{Backend, BackendApi, Instance, InstanceOptions, Querier, Storage, VmResult}; +use wasmer::{Engine, Module, Store}; -pub fn create_module(code: &[u8]) -> VmResult { +pub fn create_module(code: &[u8]) -> VmResult<(Engine, Module)> { let engine = make_compiling_engine(None); let module = compile(&engine, code)?; - Ok(module) + Ok((engine, module)) } /// This is the only Instance constructor that can be called from outside of cosmwasm-vm, /// e.g. in test code that needs a customized variant of cosmwasm_vm::testing::mock_instance*. pub fn instance_from_reused_module( - module: Module, + (engine, module): (Engine, Module), backend: Backend, options: InstanceOptions, - memory_limit: Option, ) -> VmResult> where A: BackendApi + 'static, S: Storage + 'static, Q: Querier + 'static, { - let engine = make_compiling_engine(memory_limit); let store = Store::new(engine); instance_from_module(store, &module, backend, options.gas_limit, None) } diff --git a/src/wasm_emulation/output.rs b/src/wasm_emulation/output.rs index 7dd9596e..d46c2bfb 100644 --- a/src/wasm_emulation/output.rs +++ b/src/wasm_emulation/output.rs @@ -1,7 +1,6 @@ use cosmwasm_std::{Binary, Response}; -use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize, Debug)] +#[derive(Debug)] pub enum WasmOutput { Execute(Response), Instantiate(Response), @@ -11,13 +10,13 @@ pub enum WasmOutput { Migrate(Response), } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Debug)] pub struct StorageChanges { pub current_keys: Vec<(Vec, Vec)>, pub removed_keys: Vec>, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Debug)] pub struct WasmRunnerOutput { pub wasm: WasmOutput, pub storage: StorageChanges, diff --git a/src/wasm_emulation/query/mock_querier.rs b/src/wasm_emulation/query/mock_querier.rs index 972a237d..ee70155c 100644 --- a/src/wasm_emulation/query/mock_querier.rs +++ b/src/wasm_emulation/query/mock_querier.rs @@ -63,7 +63,7 @@ pub struct MockQuerier< bank: BankQuerier, staking: StakingQuerier, - wasm: WasmQuerier, + pub wasm: WasmQuerier, //Box, Env, Vec) -> Result>, //fn(deps: Deps, env: Env, msg: Vec) -> Result, /// A handler to handle custom queries. This is set to a dummy handler that diff --git a/src/wasm_emulation/query/wasm.rs b/src/wasm_emulation/query/wasm.rs index a68c10f0..1ad075fa 100644 --- a/src/wasm_emulation/query/wasm.rs +++ b/src/wasm_emulation/query/wasm.rs @@ -21,6 +21,7 @@ use cosmwasm_std::{ use cosmwasm_std::{ContractInfo, ContractResult}; use cosmwasm_std::WasmQuery; +use cw_orch::daemon::queriers::CosmWasm; use serde::de::DeserializeOwned; use crate::wasm_emulation::channel::RemoteChannel; @@ -134,54 +135,56 @@ impl< }; let mut env = self.fork_state.local_state.env.clone(); env.contract = ContractInfo { - address: Addr::unchecked(contract_addr), + address: addr.clone(), }; - let result = if let Some(local_contract) = self + // First we get the code id corresponding to the contract + let code_id = if let Some(local_contract) = self .fork_state .querier_storage .wasm .contracts .get(contract_addr) { - // If the contract data is already defined in our storage, we load it from there - if let Some(code) = self - .fork_state - .querier_storage - .wasm - .codes - .get(&(local_contract.code_id as usize)) - { - // Local Wasm Contract case - >::query( - code, - deps.as_ref(), - env, - msg.to_vec(), - self.fork_state.clone(), - ) - } else if let Some(local_contract) = self - .fork_state - .local_state - .contracts - .get(&(local_contract.code_id as usize)) - { - // Local Rust Contract case - unsafe { - local_contract.as_ref().unwrap().query( - deps.as_ref(), - env, - msg.to_vec(), - self.fork_state.clone(), - ) - } - } else { - // Distant Registered Contract case - >::query( - &WasmContract::new_distant_code_id( - local_contract.code_id, - remote.clone(), - ), + local_contract.code_id + } else { + let wasm_querier = CosmWasm::new_sync(remote.channel.clone(), &remote.rt); + + let code_info = remote + .rt + .block_on(wasm_querier._contract_info(&addr)) + .unwrap(); + + code_info.code_id + }; + + // Then, we get the corresponding wasm contract + + // If the contract data is already defined in our storage, we load it from there + let result = if let Some(code) = self + .fork_state + .querier_storage + .wasm + .codes + .get(&(code_id as usize)) + { + // Local Wasm Contract case + >::query( + code, + deps.as_ref(), + env, + msg.to_vec(), + self.fork_state.clone(), + ) + } else if let Some(local_contract) = self + .fork_state + .local_state + .contracts + .get(&(code_id as usize)) + { + // Local Rust Contract case + unsafe { + local_contract.as_ref().unwrap().query( deps.as_ref(), env, msg.to_vec(), @@ -189,12 +192,11 @@ impl< ) } } else { - // Distant UnRegistered Contract case + // Distant Registered Contract case + // TODO, this should be part of the cache as well + // However, it's not really possible to register that data inside the App, because this is deep in the execution layer >::query( - &WasmContract::new_distant_contract( - contract_addr.to_string(), - remote.clone(), - ), + &WasmContract::new_distant_code_id(code_id, remote.clone()), deps.as_ref(), env, msg.to_vec(), From 65bd8f983275092ee7b32abfa517798087c65184 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Wed, 4 Sep 2024 11:28:08 +0000 Subject: [PATCH 61/81] Less diff --- Cargo.toml | 2 +- src/wasm_emulation/query/mock_querier.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9946497d..bd03ac3e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,7 @@ tokio = "1.28.2" tonic = "0.12.2" ## Emulation -cosmwasm-vm = { version = "2.1.0", features = [ +cosmwasm-vm = { version = "2.1.3", features = [ "staking", "stargate", "iterator", diff --git a/src/wasm_emulation/query/mock_querier.rs b/src/wasm_emulation/query/mock_querier.rs index ee70155c..972a237d 100644 --- a/src/wasm_emulation/query/mock_querier.rs +++ b/src/wasm_emulation/query/mock_querier.rs @@ -63,7 +63,7 @@ pub struct MockQuerier< bank: BankQuerier, staking: StakingQuerier, - pub wasm: WasmQuerier, + wasm: WasmQuerier, //Box, Env, Vec) -> Result>, //fn(deps: Deps, env: Env, msg: Vec) -> Result, /// A handler to handle custom queries. This is set to a dummy handler that From 86370ae6a304b0880a2ce554ad9f47b819fd4307 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Mon, 9 Sep 2024 11:46:22 +0000 Subject: [PATCH 62/81] Removed cw-orch external dependncy --- examples/cavern_test_app.rs | 10 +++++++--- examples/cousin_test.rs | 9 +++++++-- examples/test_app.rs | 7 ++++++- src/wasm_emulation/channel.rs | 33 +++++++++++++++++++++++++-------- 4 files changed, 45 insertions(+), 14 deletions(-) diff --git a/examples/cavern_test_app.rs b/examples/cavern_test_app.rs index 895e3b61..02769a07 100644 --- a/examples/cavern_test_app.rs +++ b/examples/cavern_test_app.rs @@ -58,7 +58,12 @@ pub fn test() -> anyhow::Result<()> { let runtime = Runtime::new()?; let chain = PHOENIX_1; - let remote_channel = RemoteChannel::new(&runtime, chain.clone())?; + let remote_channel = RemoteChannel::new( + &runtime, + chain.grpc_urls, + chain.chain_id, + chain.network_info.pub_address_prefix, + )?; let wasm = WasmKeeper::::new() .with_remote(remote_channel.clone()) @@ -127,9 +132,8 @@ pub fn test() -> anyhow::Result<()> { .join("counter_contract.wasm"), ) .unwrap(); - let counter_contract = WasmContract::new_local(code); - let code_id = app.store_wasm_code(counter_contract); + let code_id = app.store_wasm_code(code); // We try to instantiate a new contract. Should work ok ! let contract_addr = app.instantiate_contract( diff --git a/examples/cousin_test.rs b/examples/cousin_test.rs index 90cdc42b..e7825329 100644 --- a/examples/cousin_test.rs +++ b/examples/cousin_test.rs @@ -6,7 +6,7 @@ use std::path::Path; use anyhow::Result as AnyResult; use clone_cw_multi_test::{ addons::{MockAddressGenerator, MockApiBech32}, - wasm_emulation::{channel::RemoteChannel, contract::WasmContract}, + wasm_emulation::channel::RemoteChannel, App, AppBuilder, BankKeeper, ContractWrapper, Executor, WasmKeeper, }; use cosmwasm_std::{Addr, Empty}; @@ -69,7 +69,12 @@ fn test() -> AnyResult<()> { let runtime = Runtime::new()?; let chain = PHOENIX_1; - let remote_channel = RemoteChannel::new(&runtime, chain.clone())?; + let remote_channel = RemoteChannel::new( + &runtime, + chain.grpc_urls, + chain.chain_id, + chain.network_info.pub_address_prefix, + )?; let wasm = WasmKeeper::::new() .with_remote(remote_channel.clone()) diff --git a/examples/test_app.rs b/examples/test_app.rs index d0260465..b464175c 100644 --- a/examples/test_app.rs +++ b/examples/test_app.rs @@ -20,7 +20,12 @@ pub fn test() -> anyhow::Result<()> { let runtime = Runtime::new()?; let chain = PHOENIX_1; - let remote_channel = RemoteChannel::new(&runtime, chain.clone())?; + let remote_channel = RemoteChannel::new( + &runtime, + chain.grpc_urls, + chain.chain_id, + chain.network_info.pub_address_prefix, + )?; let wasm = WasmKeeper::::new().with_remote(remote_channel.clone()); let bank = BankKeeper::new().with_remote(remote_channel.clone()); diff --git a/src/wasm_emulation/channel.rs b/src/wasm_emulation/channel.rs index 65b66bf5..445c532e 100644 --- a/src/wasm_emulation/channel.rs +++ b/src/wasm_emulation/channel.rs @@ -1,11 +1,15 @@ use anyhow::Result as AnyResult; -use cw_orch::{daemon::GrpcChannel, environment::ChainInfoOwned}; +use cw_orch::daemon::GrpcChannel; use tokio::runtime::{Handle, Runtime}; use tonic::transport::Channel; /// Simple helper to get the GRPC transport channel -fn get_channel(chain: &ChainInfoOwned, rt: &Runtime) -> anyhow::Result { - let channel = rt.block_on(GrpcChannel::connect(&chain.grpc_urls, &chain.chain_id))?; +fn get_channel( + grpc_urls: &[String], + chain_id: impl Into, + rt: &Runtime, +) -> anyhow::Result { + let channel = rt.block_on(GrpcChannel::connect(grpc_urls, &chain_id.into()))?; Ok(channel) } @@ -19,13 +23,26 @@ pub struct RemoteChannel { } impl RemoteChannel { - pub fn new(rt: &Runtime, chain: impl Into) -> AnyResult { - let chain: ChainInfoOwned = chain.into(); + pub fn new( + rt: &Runtime, + grpc_urls: &[&str], + chain_id: impl Into, + pub_address_prefix: impl Into, + ) -> AnyResult { + let chain_id = chain_id.into(); Ok(Self { rt: rt.handle().clone(), - channel: get_channel(&chain, rt)?, - pub_address_prefix: chain.network_info.pub_address_prefix, - chain_id: chain.chain_id, + channel: get_channel( + &grpc_urls + .iter() + .cloned() + .map(Into::into) + .collect::>(), + chain_id.clone(), + rt, + )?, + pub_address_prefix: pub_address_prefix.into(), + chain_id, }) } } From f6f2d66be0d5ec88bf6d10f9868a2397da61752d Mon Sep 17 00:00:00 2001 From: Dariusz Depta <141360751+DariuszDepta@users.noreply.github.com> Date: Tue, 17 Sep 2024 12:39:05 +0200 Subject: [PATCH 63/81] Added checksum modifier --- Cargo.lock | 436 +++++++++++++++++++++++------------------------ Cargo.toml | 2 +- src/contracts.rs | 23 ++- src/wasm.rs | 76 ++++----- 4 files changed, 272 insertions(+), 265 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8ea4e751..84cd94f3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,14 +4,14 @@ version = 3 [[package]] name = "abstract-cw-multi-test" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f07e6d76b28a73f2c74c610d4451cd9bcdf02ffa1a2839161f9209a89af25135" +checksum = "edc2979e936aa9ef1e29f80a95fe18bfc7db4d0b4700fdffa21b07d977ba5269" dependencies = [ "anyhow", "bech32 0.11.0", "cosmwasm-schema 2.1.3", - "cosmwasm-std 2.1.3", + "cosmwasm-std 2.1.4", "cw-storage-plus 2.0.0", "cw-utils 2.0.0", "cw20-ics20", @@ -19,7 +19,7 @@ dependencies = [ "hex", "itertools 0.13.0", "log", - "prost 0.12.6", + "prost", "schemars", "serde", "serde_json", @@ -29,19 +29,13 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" dependencies = [ - "gimli 0.29.0", + "gimli 0.31.0", ] -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - [[package]] name = "adler2" version = "2.0.0" @@ -103,9 +97,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" dependencies = [ "backtrace", ] @@ -272,9 +266,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.82" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", @@ -295,9 +289,9 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "axum" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" +checksum = "8f43644eed690f5374f1af436ecd6aea01cd201f6fbdf0178adaf6907afb2cec" dependencies = [ "async-trait", "axum-core", @@ -315,16 +309,16 @@ dependencies = [ "rustversion", "serde", "sync_wrapper 1.0.1", - "tower", + "tower 0.5.1", "tower-layer", "tower-service", ] [[package]] name = "axum-core" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" +checksum = "5e6b8ba012a258d63c9adfa28b9ddcf66149da6f986c5b5452e629d5ee64bf00" dependencies = [ "async-trait", "bytes", @@ -335,24 +329,24 @@ dependencies = [ "mime", "pin-project-lite", "rustversion", - "sync_wrapper 0.1.2", + "sync_wrapper 1.0.1", "tower-layer", "tower-service", ] [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", - "miniz_oxide 0.7.4", + "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -620,9 +614,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.15" +version = "1.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" dependencies = [ "shlex", ] @@ -647,6 +641,33 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + [[package]] name = "clone-cw-multi-test" version = "0.6.0-alpha.1" @@ -656,7 +677,7 @@ dependencies = [ "cargo_metadata", "cosmrs", "cosmwasm-schema 2.1.3", - "cosmwasm-std 2.1.3", + "cosmwasm-std 2.1.4", "cosmwasm-vm", "cw-orch", "cw-storage-plus 2.0.0", @@ -673,7 +694,7 @@ dependencies = [ "moneymarket", "num-bigint", "once_cell", - "prost 0.13.2", + "prost", "rustc-serialize", "schemars", "serde", @@ -742,7 +763,7 @@ version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d0afc4daf81936e6ef5a2cf76f00c913ba5bc385d58ae1e09644e25d16b0381" dependencies = [ - "prost 0.13.2", + "prost", "tendermint-proto", "tonic", ] @@ -771,15 +792,15 @@ dependencies = [ [[package]] name = "cosmwasm-core" -version = "2.1.3" +version = "2.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d905990ef3afb5753bb709dc7de88e9e370aa32bcc2f31731d4b533b63e82490" +checksum = "5f6ceb8624260d0d3a67c4e1a1d43fc7e9406720afbcb124521501dd138f90aa" [[package]] name = "cosmwasm-crypto" -version = "1.5.7" +version = "1.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f862b355f7e47711e0acfe6af92cb3fd8fd5936b66a9eaa338b51edabd1e77d" +checksum = "58535cbcd599b3c193e3967c8292fe1dbbb5de7c2a2d87380661091dd4744044" dependencies = [ "digest 0.10.7", "ed25519-zebra 3.1.0", @@ -790,9 +811,9 @@ dependencies = [ [[package]] name = "cosmwasm-crypto" -version = "2.1.3" +version = "2.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b2a7bd9c1dd9a377a4dc0f4ad97d24b03c33798cd5a6d7ceb8869b41c5d2f2d" +checksum = "4125381e5fd7fefe9f614640049648088015eca2b60d861465329a5d87dfa538" dependencies = [ "ark-bls12-381", "ark-ec", @@ -813,18 +834,18 @@ dependencies = [ [[package]] name = "cosmwasm-derive" -version = "1.5.7" +version = "1.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd85de6467cd1073688c86b39833679ae6db18cf4771471edd9809f15f1679f1" +checksum = "a8e07de16c800ac82fd188d055ecdb923ead0cf33960d3350089260bb982c09f" dependencies = [ "syn 1.0.109", ] [[package]] name = "cosmwasm-derive" -version = "2.1.3" +version = "2.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "029910b409398fdf81955d7301b906caf81f2c42b013ea074fbd89720229c424" +checksum = "1b5658b1dc64e10b56ae7a449f678f96932a96f6cfad1769d608d1d1d656480a" dependencies = [ "proc-macro2", "quote", @@ -833,11 +854,11 @@ dependencies = [ [[package]] name = "cosmwasm-schema" -version = "1.5.7" +version = "1.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b4cd28147a66eba73720b47636a58097a979ad8c8bfdb4ed437ebcbfe362576" +checksum = "93d388adfa9cb449557a92e9318121ac1a481fc4f599213b03a5b62699b403b4" dependencies = [ - "cosmwasm-schema-derive 1.5.7", + "cosmwasm-schema-derive 1.5.8", "schemars", "serde", "serde_json", @@ -859,9 +880,9 @@ dependencies = [ [[package]] name = "cosmwasm-schema-derive" -version = "1.5.7" +version = "1.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9acd45c63d41bc9b16bc6dc7f6bd604a8c2ad29ce96c8f3c96d7fc8ef384392e" +checksum = "2411b389e56e6484f81ba955b758d02522d620c98fc960c4bd2251d48b7aa19f" dependencies = [ "proc-macro2", "quote", @@ -881,15 +902,15 @@ dependencies = [ [[package]] name = "cosmwasm-std" -version = "1.5.7" +version = "1.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2685c2182624b2e9e17f7596192de49a3f86b7a0c9a5f6b25c1df5e24592e836" +checksum = "c21fde95ccd20044a23c0ac6fd8c941f3e8c158169dc94b5aa6491a2d9551a8d" dependencies = [ "base64 0.21.7", "bech32 0.9.1", "bnum 0.10.0", - "cosmwasm-crypto 1.5.7", - "cosmwasm-derive 1.5.7", + "cosmwasm-crypto 1.5.8", + "cosmwasm-derive 1.5.8", "derivative", "forward_ref", "hex", @@ -903,16 +924,16 @@ dependencies = [ [[package]] name = "cosmwasm-std" -version = "2.1.3" +version = "2.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51dec99a2e478715c0a4277f0dbeadbb8466500eb7dec873d0924edd086e77f1" +checksum = "70eb7ab0c1e99dd6207496963ba2a457c4128ac9ad9c72a83f8d9808542b849b" dependencies = [ "base64 0.22.1", "bech32 0.11.0", "bnum 0.11.0", "cosmwasm-core", - "cosmwasm-crypto 2.1.3", - "cosmwasm-derive 2.1.3", + "cosmwasm-crypto 2.1.4", + "cosmwasm-derive 2.1.4", "derive_more", "hex", "rand_core 0.6.4", @@ -930,22 +951,22 @@ version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66de2ab9db04757bcedef2b5984fbe536903ada4a8a9766717a4a71197ef34f6" dependencies = [ - "cosmwasm-std 1.5.7", + "cosmwasm-std 1.5.8", "serde", ] [[package]] name = "cosmwasm-vm" -version = "2.1.3" +version = "2.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5481dd2f10a04aa7aef8025b342285aebf20b167d6197e653c5e9aadc588f787" +checksum = "edc6ab1b15e1253efaf228d6892ee89c1a816fbc3a755f681d2725fc4aed9679" dependencies = [ "bech32 0.11.0", "bytes", "clru", "cosmwasm-core", - "cosmwasm-crypto 2.1.3", - "cosmwasm-std 2.1.3", + "cosmwasm-crypto 2.1.4", + "cosmwasm-std 2.1.4", "crc32fast", "derivative", "hex", @@ -959,13 +980,14 @@ dependencies = [ "tracing", "wasmer", "wasmer-middlewares", + "wasmer-types", ] [[package]] name = "cpufeatures" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] @@ -1096,6 +1118,12 @@ version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-bigint" version = "0.5.5" @@ -1178,7 +1206,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50c1804013d21060b994dea28a080f9eab78a3bcb6b617f05e7634b0600bf7b1" dependencies = [ "cosmwasm-schema 2.1.3", - "cosmwasm-std 2.1.3", + "cosmwasm-std 2.1.4", "cw-storage-plus 2.0.0", "cw-utils 2.0.0", "schemars", @@ -1194,7 +1222,7 @@ checksum = "2dd6f114ab0301b99ca0d8ba48036b87372ccc3ba0271dcd6f9533e4be578f65" dependencies = [ "anyhow", "cosmrs", - "cosmwasm-std 2.1.3", + "cosmwasm-std 2.1.4", "cw-orch-contract-derive", "cw-orch-core", "cw-orch-daemon", @@ -1231,7 +1259,7 @@ dependencies = [ "abstract-cw-multi-test", "anyhow", "cosmos-sdk-proto", - "cosmwasm-std 2.1.3", + "cosmwasm-std 2.1.4", "cw-storage-plus 2.0.0", "cw-utils 2.0.0", "dirs", @@ -1244,9 +1272,9 @@ dependencies = [ [[package]] name = "cw-orch-daemon" -version = "0.25.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe17cbe065101ead45abda1bd6b1a3416803ae9615e6294f5fcb3ca4e67320b" +checksum = "3008da99bd004c9cf58571862a879298f69591e81183f6a97a9bbb9c8efb51cb" dependencies = [ "anyhow", "async-recursion", @@ -1256,7 +1284,7 @@ dependencies = [ "bitcoin", "chrono", "cosmrs", - "cosmwasm-std 2.1.3", + "cosmwasm-std 2.1.4", "cw-orch-core", "cw-orch-networks", "cw-orch-traits", @@ -1267,10 +1295,11 @@ dependencies = [ "flate2", "hex", "hkd32", + "http 1.1.0", "lazy_static", "log", "once_cell", - "prost 0.13.2", + "prost", "prost-types", "rand_core 0.6.4", "reqwest 0.12.7", @@ -1306,7 +1335,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3a7b0d0678a9043e4b4ac489e2bb6350d33acb3c8a6c2a2042145cd72a5a069" dependencies = [ "abstract-cw-multi-test", - "cosmwasm-std 2.1.3", + "cosmwasm-std 2.1.4", "cw-orch-core", "cw-utils 2.0.0", "log", @@ -1331,7 +1360,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be7b10c170797abe29170d58756fd988b260430a4466a56647c8ab8dafa8fa13" dependencies = [ "cw-orch-core", - "prost 0.13.2", + "prost", "prost-types", ] @@ -1341,7 +1370,7 @@ version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc6cf70ef7686e2da9ad7b067c5942cd3e88dd9453f7af42f54557f8af300fb0" dependencies = [ - "cosmwasm-std 1.5.7", + "cosmwasm-std 1.5.8", "schemars", "serde", ] @@ -1352,7 +1381,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f13360e9007f51998d42b1bc6b7fa0141f74feae61ed5fd1e5b0a89eec7b5de1" dependencies = [ - "cosmwasm-std 2.1.3", + "cosmwasm-std 2.1.4", "schemars", "serde", ] @@ -1363,8 +1392,8 @@ version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ae0b69fa7679de78825b4edeeec045066aa2b2c4b6e063d80042e565bb4da5c" dependencies = [ - "cosmwasm-schema 1.5.7", - "cosmwasm-std 1.5.7", + "cosmwasm-schema 1.5.8", + "cosmwasm-std 1.5.8", "cw2 0.15.1", "schemars", "semver", @@ -1379,7 +1408,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07dfee7f12f802431a856984a32bce1cb7da1e6c006b5409e3981035ce562dec" dependencies = [ "cosmwasm-schema 2.1.3", - "cosmwasm-std 2.1.3", + "cosmwasm-std 2.1.4", "schemars", "serde", "thiserror", @@ -1391,8 +1420,8 @@ version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5abb8ecea72e09afff830252963cb60faf945ce6cef2c20a43814516082653da" dependencies = [ - "cosmwasm-schema 1.5.7", - "cosmwasm-std 1.5.7", + "cosmwasm-schema 1.5.8", + "cosmwasm-std 1.5.8", "cw-storage-plus 0.15.1", "schemars", "serde", @@ -1405,7 +1434,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b04852cd38f044c0751259d5f78255d07590d136b8a86d4e09efdd7666bd6d27" dependencies = [ "cosmwasm-schema 2.1.3", - "cosmwasm-std 2.1.3", + "cosmwasm-std 2.1.4", "cw-storage-plus 2.0.0", "schemars", "semver", @@ -1419,8 +1448,8 @@ version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6025276fb6e603e974c21f3e4606982cdc646080e8fba3198816605505e1d9a" dependencies = [ - "cosmwasm-schema 1.5.7", - "cosmwasm-std 1.5.7", + "cosmwasm-schema 1.5.8", + "cosmwasm-std 1.5.8", "cw-utils 0.15.1", "schemars", "serde", @@ -1433,7 +1462,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a42212b6bf29bbdda693743697c621894723f35d3db0d5df930be22903d0e27c" dependencies = [ "cosmwasm-schema 2.1.3", - "cosmwasm-std 2.1.3", + "cosmwasm-std 2.1.4", "cw-utils 2.0.0", "schemars", "serde", @@ -1446,7 +1475,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80a9e377dbbd1ffb3b6a8a2dbf9128609a6458a3292f88f99e0b6840a7e9762e" dependencies = [ "cosmwasm-schema 2.1.3", - "cosmwasm-std 2.1.3", + "cosmwasm-std 2.1.4", "cw-controllers", "cw-storage-plus 2.0.0", "cw-utils 2.0.0", @@ -1953,12 +1982,12 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.33" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", - "miniz_oxide 0.8.0", + "miniz_oxide", ] [[package]] @@ -2120,9 +2149,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" [[package]] name = "group" @@ -2175,9 +2204,13 @@ dependencies = [ [[package]] name = "half" -version = "1.8.3" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] [[package]] name = "hashbrown" @@ -2417,15 +2450,15 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.2" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", "http 1.1.0", "hyper 1.4.1", "hyper-util", - "rustls 0.23.12", + "rustls 0.23.13", "rustls-pki-types", "tokio", "tokio-rustls 0.26.0", @@ -2463,9 +2496,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.7" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ "bytes", "futures-channel", @@ -2476,16 +2509,15 @@ dependencies = [ "pin-project-lite", "socket2", "tokio", - "tower", "tower-service", "tracing", ] [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -2550,9 +2582,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" [[package]] name = "is-terminal" @@ -2732,15 +2764,6 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[package]] -name = "miniz_oxide" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" -dependencies = [ - "adler", -] - [[package]] name = "miniz_oxide" version = "0.8.0" @@ -2767,8 +2790,8 @@ name = "moneymarket" version = "0.3.1" source = "git+https://github.com/CavernPerson/money-market-contracts#6a3b3f586cd085d434485bb13e2d12f95e8beef2" dependencies = [ - "cosmwasm-schema 1.5.7", - "cosmwasm-std 1.5.7", + "cosmwasm-schema 1.5.8", + "cosmwasm-std 1.5.8", "cosmwasm-storage", "cw20 0.15.1", "schemars", @@ -3032,9 +3055,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "powerfmt" @@ -3093,16 +3116,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "prost" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" -dependencies = [ - "bytes", - "prost-derive 0.12.6", -] - [[package]] name = "prost" version = "0.13.2" @@ -3110,20 +3123,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b2ecbe40f08db5c006b5764a2645f7f3f141ce756412ac9e1dd6087e6d32995" dependencies = [ "bytes", - "prost-derive 0.13.2", -] - -[[package]] -name = "prost-derive" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" -dependencies = [ - "anyhow", - "itertools 0.12.1", - "proc-macro2", - "quote", - "syn 2.0.77", + "prost-derive", ] [[package]] @@ -3145,7 +3145,7 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60caa6738c7369b940c3d49246a8d1749323674c65cb13010134f5c9bad5b519" dependencies = [ - "prost 0.13.2", + "prost", ] [[package]] @@ -3241,9 +3241,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.3" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "355ae415ccd3a04315d3f8246e86d67689ea74d88d915576e1589a351062a13b" dependencies = [ "bitflags 2.6.0", ] @@ -3345,7 +3345,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "rustls 0.21.12", - "rustls-native-certs 0.6.3", + "rustls-native-certs", "rustls-pemfile 1.0.4", "serde", "serde_json", @@ -3378,7 +3378,7 @@ dependencies = [ "http-body 1.0.1", "http-body-util", "hyper 1.4.1", - "hyper-rustls 0.27.2", + "hyper-rustls 0.27.3", "hyper-tls", "hyper-util", "ipnet", @@ -3492,9 +3492,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.35" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ "bitflags 2.6.0", "errno", @@ -3517,15 +3517,15 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.12" +version = "0.23.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" dependencies = [ "log", "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.102.7", + "rustls-webpki 0.102.8", "subtle", "zeroize", ] @@ -3542,19 +3542,6 @@ dependencies = [ "security-framework", ] -[[package]] -name = "rustls-native-certs" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" -dependencies = [ - "openssl-probe", - "rustls-pemfile 2.1.3", - "rustls-pki-types", - "schannel", - "security-framework", -] - [[package]] name = "rustls-pemfile" version = "1.0.4" @@ -3592,9 +3579,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.7" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84678086bd54edf2b415183ed7a94d0efb049f1b646a33e22a36f3794be6ae56" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring", "rustls-pki-types", @@ -3624,11 +3611,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3694,9 +3681,9 @@ dependencies = [ [[package]] name = "secp256k1" -version = "0.29.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e0cc0f1cf93f4969faf3ea1c7d8a9faed25918d96affa959720823dfe86d4f3" +checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" dependencies = [ "bitcoin_hashes", "secp256k1-sys", @@ -3704,9 +3691,9 @@ dependencies = [ [[package]] name = "secp256k1-sys" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1433bd67156263443f14d603720b082dd3121779323fce20cba2aa07b874bc1b" +checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" dependencies = [ "cc", ] @@ -3726,9 +3713,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" dependencies = [ "core-foundation-sys", "libc", @@ -3751,9 +3738,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] @@ -3796,21 +3783,11 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_cbor" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" -dependencies = [ - "half", - "serde", -] - [[package]] name = "serde_derive" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", @@ -3830,9 +3807,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.127" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", "memchr", @@ -3853,9 +3830,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -3946,9 +3923,9 @@ dependencies = [ [[package]] name = "simdutf8" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "slab" @@ -4164,9 +4141,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tar" -version = "0.4.41" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb797dad5fb5b76fcf519e702f4a589483b5ef06567f160c392832c1f5e44909" +checksum = "4ff6c40d3aedb5e06b57c6f669ad17ab063dd1e63d977c6a88e7f4dfa4f04020" dependencies = [ "filetime", "libc", @@ -4207,7 +4184,7 @@ dependencies = [ "k256", "num-traits", "once_cell", - "prost 0.13.2", + "prost", "ripemd", "serde", "serde_bytes", @@ -4244,7 +4221,7 @@ checksum = "bf3abf34ecf33125621519e9952688e7a59a98232d51538037ba21fbe526a802" dependencies = [ "bytes", "flex-error", - "prost 0.13.2", + "prost", "serde", "serde_bytes", "subtle-encoding", @@ -4413,16 +4390,16 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.12", + "rustls 0.23.13", "rustls-pki-types", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", @@ -4431,9 +4408,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", @@ -4465,9 +4442,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.20" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ "indexmap 2.5.0", "serde", @@ -4478,9 +4455,9 @@ dependencies = [ [[package]] name = "tonic" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6f6ba989e4b2c58ae83d862d3a3e27690b6e3ae630d0deb59f3697f32aa88ad" +checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" dependencies = [ "async-stream", "async-trait", @@ -4496,14 +4473,13 @@ dependencies = [ "hyper-util", "percent-encoding", "pin-project", - "prost 0.13.2", - "rustls-native-certs 0.7.3", + "prost", "rustls-pemfile 2.1.3", "socket2", "tokio", "tokio-rustls 0.26.0", "tokio-stream", - "tower", + "tower 0.4.13", "tower-layer", "tower-service", "tracing", @@ -4529,6 +4505,20 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper 0.1.2", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-layer" version = "0.3.3" @@ -4595,9 +4585,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "uid" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "281a11e4180ee68f8c06a7bf82d1be3c496e0debcadcc4576cc0b56132201edf" +checksum = "7041bb797d82c5728d3a4a40432809095d8acc59bdd9e67426a2529b3b80c9be" [[package]] name = "unicode-bidi" @@ -4607,24 +4597,24 @@ checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-xid" @@ -4864,19 +4854,19 @@ dependencies = [ [[package]] name = "wasmer-config" -version = "0.4.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b4a632496950fde9ad821e195ef1a301440076f7c7d80de55239a140359bcbd" +checksum = "644b7e3547bd7e796d92220f60bf57734914254c6cee56607e80177a3e8a28da" dependencies = [ "anyhow", "bytesize", + "ciborium", "derive_builder", "hex", "indexmap 2.5.0", "schemars", "semver", "serde", - "serde_cbor", "serde_json", "serde_yaml", "thiserror", @@ -4979,14 +4969,15 @@ dependencies = [ [[package]] name = "webc" -version = "6.0.0-rc2" +version = "6.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb3e2ccb43d303c5bd48f31db7a129481a9aaa5343d623f92951751df190df81" +checksum = "c48441419be082f8d2537c84d8b1f502624d77bc08fbbd09ab17cadfe7f0ac53" dependencies = [ "anyhow", "base64 0.22.1", "bytes", "cfg-if", + "ciborium", "document-features", "flate2", "indexmap 1.9.3", @@ -4994,7 +4985,6 @@ dependencies = [ "once_cell", "semver", "serde", - "serde_cbor", "serde_json", "sha2 0.10.8", "shared-buffer", @@ -5269,9 +5259,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.18" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index bd03ac3e..a653a1b3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,7 +65,7 @@ file-lock = "2.1" [dev-dependencies] hex = "0.4.3" hex-literal = "0.4.1" -once_cell = "1.18.0" +once_cell = "1.19.0" # General env_logger = "0.10.0" diff --git a/src/contracts.rs b/src/contracts.rs index 93bf3fcd..e6d218ff 100644 --- a/src/contracts.rs +++ b/src/contracts.rs @@ -6,8 +6,7 @@ use std::{ use schemars::JsonSchema; use cosmwasm_std::{ - from_json, Binary, CustomMsg, CustomQuery, Deps, DepsMut, Empty, Env, MessageInfo, - QuerierWrapper, Reply, Response, StdError, + from_json, Binary, Checksum, CustomMsg, CustomQuery, Deps, DepsMut, Empty, Env, MessageInfo, QuerierWrapper, Reply, Response, StdError }; use anyhow::Result as AnyResult; @@ -76,6 +75,11 @@ where msg: Vec, fork_state: ForkState, ) -> AnyResult>; + + /// Returns the provided checksum of the contract's Wasm blob. + fn checksum(&self) -> Option { + None + } } type ContractFn = @@ -127,6 +131,7 @@ pub struct ContractWrapper< sudo_fn: Option>, reply_fn: Option>, migrate_fn: Option>, + checksum: Option, } impl ContractWrapper @@ -152,6 +157,7 @@ where sudo_fn: None, reply_fn: None, migrate_fn: None, + checksum: None, } } } @@ -188,6 +194,7 @@ where sudo_fn: Some(sudo_fn), reply_fn: self.reply_fn, migrate_fn: self.migrate_fn, + checksum: None, } } @@ -205,6 +212,7 @@ where sudo_fn: self.sudo_fn, reply_fn: Some(reply_fn), migrate_fn: self.migrate_fn, + checksum: None, } } @@ -223,8 +231,14 @@ where sudo_fn: self.sudo_fn, reply_fn: self.reply_fn, migrate_fn: Some(migrate_fn), + checksum: None, } } + /// Populates [ContractWrapper] with the provided checksum of the contract's Wasm blob. + pub fn with_checksum(mut self, checksum: Checksum) -> Self { + self.checksum = Some(checksum); + self + } } impl Contract @@ -389,6 +403,11 @@ where None => bail!("migrate not implemented for contract"), } } + + /// Returns the provided checksum of the contract's Wasm blob. + fn checksum(&self) -> Option { + self.checksum + } } #[cfg(test)] diff --git a/src/wasm.rs b/src/wasm.rs index ff281601..77f95771 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -434,46 +434,7 @@ where let storage = ReadonlyPrefixedStorage::multilevel(storage, &[NAMESPACE_WASM, &namespace]); Box::new(storage) } - - fn verify_attributes(attributes: &[Attribute]) -> AnyResult<()> { - for attr in attributes { - let key = attr.key.trim(); - let val = attr.value.trim(); - - if key.is_empty() { - bail!(Error::empty_attribute_key(val)); - } - - if val.is_empty() { - bail!(Error::empty_attribute_value(key)); - } - - if key.starts_with('_') { - bail!(Error::reserved_attribute_key(key)); - } - } - - Ok(()) - } - - fn verify_response(response: Response) -> AnyResult> - where - T: Clone + Debug + PartialEq + JsonSchema, - { - Self::verify_attributes(&response.attributes)?; - - for event in &response.events { - Self::verify_attributes(&event.attributes)?; - let ty = event.ty.trim(); - if ty.len() < 2 { - bail!(Error::event_type_too_short(ty)); - } - } - - Ok(response) - } } - impl WasmKeeper where ExecC: CustomMsg + DeserializeOwned + 'static, @@ -516,6 +477,43 @@ where self } + /// Validates all attributes. + /// + /// In `wasmd`, before version v0.45.0 empty attribute values were not allowed. + /// Since `wasmd` v0.45.0 empty attribute values are allowed, + /// so the value is not validated anymore. + fn verify_attributes(attributes: &[Attribute]) -> AnyResult<()> { + for attr in attributes { + let key = attr.key.trim(); + let val = attr.value.trim(); + if key.is_empty() { + bail!(Error::empty_attribute_key(val)); + } + if key.starts_with('_') { + bail!(Error::reserved_attribute_key(key)); + } + } + Ok(()) + } + + fn verify_response(response: Response) -> AnyResult> + where + T: CustomMsg, + { + Self::verify_attributes(&response.attributes)?; + + for event in &response.events { + Self::verify_attributes(&event.attributes)?; + let ty = event.ty.trim(); + if ty.len() < 2 { + bail!(Error::event_type_too_short(ty)); + } + } + + Ok(response) + } + + /// Executes the contract's `query` entry-point. pub fn query_smart( &self, address: Addr, From 9f77fd92e7da481f87f93b7b00d10b1b3263acf1 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Fri, 27 Sep 2024 07:58:54 +0000 Subject: [PATCH 64/81] version publish --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 84cd94f3..37b009c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -670,7 +670,7 @@ dependencies = [ [[package]] name = "clone-cw-multi-test" -version = "0.6.0-alpha.1" +version = "0.6.1" dependencies = [ "anyhow", "bech32 0.9.1", diff --git a/Cargo.toml b/Cargo.toml index a653a1b3..5d2717e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clone-cw-multi-test" -version = "0.6.0-alpha.1" +version = "0.6.1" authors = ["Ethan Frey "] edition = "2021" description = "Testing tools for multi-contract interactions. Helps simulating chain behavior with on-chain storage locally" From 926ed48ce853c16820c69e1130b64822f37109f8 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Fri, 27 Sep 2024 08:58:05 +0000 Subject: [PATCH 65/81] Fix faulty merge --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/wasm.rs | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 37b009c9..6ce5bb86 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -670,7 +670,7 @@ dependencies = [ [[package]] name = "clone-cw-multi-test" -version = "0.6.1" +version = "0.6.2" dependencies = [ "anyhow", "bech32 0.9.1", diff --git a/Cargo.toml b/Cargo.toml index 5d2717e4..640b110a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clone-cw-multi-test" -version = "0.6.1" +version = "0.6.2" authors = ["Ethan Frey "] edition = "2021" description = "Testing tools for multi-contract interactions. Helps simulating chain behavior with on-chain storage locally" diff --git a/src/wasm.rs b/src/wasm.rs index 77f95771..d7891f8a 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -283,12 +283,14 @@ where /// Stores the contract's code in the in-memory lookup table. /// Returns an identifier of the stored contract code. fn store_code(&mut self, creator: Addr, code: Box>) -> u64 { + let code_id = self.rust_codes.len() + 1 + LOCAL_RUST_CODE_OFFSET; + let checksum = code + .checksum() + .unwrap_or(self.checksum_generator.checksum(&creator, code_id as u64)); let static_ref = Box::leak(code); - let code_id = self.rust_codes.len() + 1 + LOCAL_RUST_CODE_OFFSET; let raw_pointer = static_ref as *mut dyn Contract; self.rust_codes.insert(code_id, raw_pointer); - let checksum = self.checksum_generator.checksum(&creator, code_id as u64); self.code_data.insert( code_id, CodeData { From 692e90d05e6d876d89b8ef2353f011390b4f2fbe Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 1 Oct 2024 11:08:49 +0000 Subject: [PATCH 66/81] Merge changes --- .circleci/config.yml | 38 +- CHANGELOG.md | 122 +- CLA.md | 23 - Cargo.lock | 2 +- Cargo.toml | 4 +- SECURITY.md | 19 +- src/addons/addresses/mock.rs | 148 -- src/addons/addresses/mod.rs | 1 - src/addons/api/bech32.rs | 187 --- src/addons/api/bech32m.rs | 154 --- src/addons/api/mod.rs | 2 - src/addons/mod.rs | 11 - src/addresses.rs | 180 ++- src/api.rs | 119 ++ src/app.rs | 297 +++- src/app_builder.rs | 152 ++- src/bank.rs | 473 ++++++- src/contracts.rs | 349 +++-- src/custom_handler.rs | 43 +- src/error.rs | 72 +- src/executor.rs | 52 +- src/gov.rs | 11 +- src/ibc.rs | 12 +- src/lib.rs | 148 +- src/module.rs | 68 +- src/prefixed_storage/length_prefixed.rs | 4 +- src/prefixed_storage/mod.rs | 119 +- src/staking.rs | 1652 ++++++++++++++++++++++- src/stargate.rs | 145 ++ src/test_helpers/caller.rs | 6 +- src/test_helpers/echo.rs | 11 +- src/test_helpers/error.rs | 6 +- src/test_helpers/gov.rs | 27 + src/test_helpers/hackatom.rs | 8 +- src/test_helpers/ibc.rs | 26 + src/test_helpers/mod.rs | 7 +- src/test_helpers/payout.rs | 7 +- src/test_helpers/reflect.rs | 12 +- src/test_helpers/stargate.rs | 30 +- src/tests/mod.rs | 2 + src/tests/test_app.rs | 467 ++++--- src/tests/test_custom_handler.rs | 26 +- src/tests/test_error.rs | 43 + src/tests/test_gov.rs | 102 +- src/tests/test_ibc.rs | 44 +- src/tests/test_stargate.rs | 54 + src/transactions.rs | 47 +- src/wasm.rs | 1320 +++++++++++++++--- src/wasm_emulation/api/mod.rs | 29 +- src/wasm_emulation/input.rs | 6 +- src/wasm_emulation/query/wasm.rs | 3 +- 51 files changed, 5210 insertions(+), 1680 deletions(-) delete mode 100644 CLA.md delete mode 100644 src/addons/addresses/mock.rs delete mode 100644 src/addons/addresses/mod.rs delete mode 100644 src/addons/api/bech32.rs delete mode 100644 src/addons/api/bech32m.rs delete mode 100644 src/addons/api/mod.rs delete mode 100644 src/addons/mod.rs create mode 100644 src/api.rs create mode 100644 src/stargate.rs create mode 100644 src/test_helpers/gov.rs create mode 100644 src/test_helpers/ibc.rs create mode 100644 src/tests/test_error.rs create mode 100644 src/tests/test_stargate.rs diff --git a/.circleci/config.yml b/.circleci/config.yml index e9a3a574..50ebb17b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -30,7 +30,7 @@ workflows: jobs: build_and_test: docker: - - image: rust:1.65.0 + - image: rust:1.70 working_directory: ~/project steps: - checkout @@ -42,8 +42,8 @@ jobs: command: cargo update - restore_cache: keys: - - cargocache-v2-multi-test:1.65.0-{{ checksum "Cargo.lock" }} - - cargocache-v2-multi-test:1.65.0- + - cargocache-v2-multi-test:1.70-{{ checksum "Cargo.lock" }} + - cargocache-v2-multi-test:1.70- - run: name: Build library for native target command: cargo build --locked @@ -54,7 +54,7 @@ jobs: paths: - /usr/local/cargo/registry - target - key: cargocache-v2-multi-test:1.65.0-{{ checksum "Cargo.lock" }} + key: cargocache-v2-multi-test:1.70-{{ checksum "Cargo.lock" }} build_minimal: docker: @@ -70,22 +70,22 @@ jobs: command: rm Cargo.lock - restore_cache: keys: - - cargocache-v2-multi-test:1.65.0-minimal-{{ checksum "Cargo.toml" }} + - cargocache-v2-multi-test:1.70-minimal-{{ checksum "Cargo.toml" }} - run: name: Build library for native target - command: cargo build -Zminimal-versions --features backtrace,cosmwasm_1_1,cosmwasm_1_2,cosmwasm_1_3,cosmwasm_1_4 + command: cargo build -Zminimal-versions --all-features - run: name: Run unit tests - command: cargo test --workspace -Zminimal-versions --features backtrace,cosmwasm_1_1,cosmwasm_1_2,cosmwasm_1_3,cosmwasm_1_4 + command: cargo test --workspace -Zminimal-versions --all-features - save_cache: paths: - /usr/local/cargo/registry - target - key: cargocache-v2-multi-test:1.65.0-minimal-{{ checksum "Cargo.toml" }} + key: cargocache-v2-multi-test:1.70-minimal-{{ checksum "Cargo.toml" }} build_maximal: docker: - - image: rust:1.65.0 + - image: rust:1.70 working_directory: ~/project/ steps: - checkout @@ -97,22 +97,22 @@ jobs: command: cargo update - restore_cache: keys: - - cargocache-v2-multi-test:1.65.0-{{ checksum "Cargo.lock" }} + - cargocache-v2-multi-test:1.70-{{ checksum "Cargo.lock" }} - run: name: Build library for native target command: cargo build --locked --all-features - run: name: Run unit tests - command: cargo test --workspace --locked --features backtrace,cosmwasm_1_1,cosmwasm_1_2,cosmwasm_1_3,cosmwasm_1_4 + command: cargo test --workspace --locked --all-features - save_cache: paths: - /usr/local/cargo/registry - target - key: cargocache-v2-multi-test:1.65.0-{{ checksum "Cargo.lock" }} + key: cargocache-v2-multi-test:1.70-{{ checksum "Cargo.lock" }} lint: docker: - - image: rust:1.65.0 + - image: rust:1.70 steps: - checkout - run: @@ -123,8 +123,8 @@ jobs: command: cargo update - restore_cache: keys: - - cargocache-v2-lint-rust:1.65.0-{{ checksum "Cargo.lock" }} - - cargocache-v2-lint-rust:1.65.0- + - cargocache-v2-lint-rust:1.70-{{ checksum "Cargo.lock" }} + - cargocache-v2-lint-rust:1.70- - run: name: Add rustfmt component command: rustup component add rustfmt @@ -143,19 +143,19 @@ jobs: - target/debug/.fingerprint - target/debug/build - target/debug/deps - key: cargocache-v2-lint-rust:1.65.0-{{ checksum "Cargo.lock" }} + key: cargocache-v2-lint-rust:1.70-{{ checksum "Cargo.lock" }} coverage: # https://circleci.com/developer/images?imageType=machine machine: - image: ubuntu-2004:202201-02 + image: ubuntu-2204:2024.01.1 steps: - checkout - run: name: Run tests with coverage command: | mkdir -p cov - docker run --security-opt seccomp=unconfined -v "${PWD}:/volume" xd009642/tarpaulin \ - sh -c "cargo tarpaulin --workspace --features backtrace,cosmwasm_1_1,cosmwasm_1_2,cosmwasm_1_3,cosmwasm_1_4 --force-clean --engine llvm --out xml --output-dir cov" + docker run --security-opt seccomp=unconfined -v "${PWD}:/volume" xd009642/tarpaulin:0.27.1 \ + sh -c "cargo tarpaulin --workspace --all-features --force-clean --engine llvm --out xml --output-dir cov" - codecov/upload: file: cov/cobertura.xml diff --git a/CHANGELOG.md b/CHANGELOG.md index d84531fb..c2758683 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,83 @@ # Changelog +## [v2.0.1](https://github.com/CosmWasm/cw-multi-test/tree/v2.0.1) (2024-04-22) + +[Full Changelog](https://github.com/CosmWasm/cw-multi-test/compare/v2.0.0...v2.0.1) + +**Closed issues:** + +- Restore support for `Stargate` messages [\#159](https://github.com/CosmWasm/cw-multi-test/issues/159) + +**Merged pull requests:** + +- Distinctive Stargate [\#163](https://github.com/CosmWasm/cw-multi-test/pull/163) ([DariuszDepta](https://github.com/DariuszDepta)) +- Expose contract storage [\#153](https://github.com/CosmWasm/cw-multi-test/pull/153) ([DariuszDepta](https://github.com/DariuszDepta)) +- Expose prefixed storage [\#154](https://github.com/CosmWasm/cw-multi-test/pull/154) ([DariuszDepta](https://github.com/DariuszDepta)) +- Upgraded dependencies [\#164](https://github.com/CosmWasm/cw-multi-test/pull/164) ([DariuszDepta](https://github.com/DariuszDepta)) +- Fixes typos [\#167](https://github.com/CosmWasm/cw-multi-test/pull/157) ([DariuszDepta](https://github.com/DariuszDepta)) + +## [v2.0.0](https://github.com/CosmWasm/cw-multi-test/tree/v2.0.0) (2024-03-22) + +[Full Changelog](https://github.com/CosmWasm/cw-multi-test/compare/v1.0.0...v2.0.0) + +**Closed issues:** + +- Forward port: Fixing contract wrapper [\#146](https://github.com/CosmWasm/cw-multi-test/issues/146) +- Forward port: `store_code_with_id` helper [#131](https://github.com/CosmWasm/cw-multi-test/issues/131) + +**Merged pull requests:** + +- V2: upgrading dependencies and refactoring [\#128](https://github.com/CosmWasm/cw-multi-test/pull/128) ([DariuszDepta](https://github.com/DariuszDepta)) + +## [v1.0.0](https://github.com/CosmWasm/cw-multi-test/tree/v1.0.0) (2024-03-22) + +[Full Changelog](https://github.com/CosmWasm/cw-multi-test/compare/v0.20.1...v1.0.0) + +**Closed issues:** + +- Forward port: Fixing contract wrapper [\#145](https://github.com/CosmWasm/cw-multi-test/issues/145) +- Implement `store_code_with_id` helper [\#22](https://github.com/CosmWasm/cw-multi-test/issues/22) +- New `App::store_code` function definition [\#69](https://github.com/CosmWasm/cw-multi-test/issues/69) (wontfix) +- Make `App::store_code_with_creator` deprecated [\#70](https://github.com/CosmWasm/cw-multi-test/issues/70) (wontfix) +- Remove function `next_address` from `AddressGenerator` trait [\#90](https://github.com/CosmWasm/cw-multi-test/issues/90) +- Remove `new_with_custom_address_generator` function from `WasmKeeper` [\#91](https://github.com/CosmWasm/cw-multi-test/issues/91) + +**Merged pull requests:** + +- Refactored contract wrapper [\#149](https://github.com/CosmWasm/cw-multi-test/pull/149) ([DariuszDepta](https://github.com/DariuszDepta)) +- Fixed contract wrapper [\#148](https://github.com/CosmWasm/cw-multi-test/pull/148) ([DariuszDepta](https://github.com/DariuszDepta)) +- Remove `Addr::unchecked` where possible [\#141](https://github.com/CosmWasm/cw-multi-test/pull/141) ([DariuszDepta](https://github.com/DariuszDepta)) +- Refactored wasm trait [\#139](https://github.com/CosmWasm/cw-multi-test/pull/139) ([DariuszDepta](https://github.com/DariuszDepta)) +- Added `IntoAddr` trait [\#138](https://github.com/CosmWasm/cw-multi-test/pull/138) ([DariuszDepta](https://github.com/DariuszDepta)) +- Removed `new_with_custom_address_generator` function [\#135](https://github.com/CosmWasm/cw-multi-test/pull/135) ([DariuszDepta](https://github.com/DariuszDepta)) +- Removed `next_address` function [\#134](https://github.com/CosmWasm/cw-multi-test/pull/134) ([DariuszDepta](https://github.com/DariuszDepta)) +- Added `store_code_with_id` function to `App` [\#117](https://github.com/CosmWasm/cw-multi-test/pull/117) ([DariuszDepta](https://github.com/DariuszDepta)) + +## [v0.20.1](https://github.com/CosmWasm/cw-multi-test/tree/v0.20.1) (2024-03-15) + +[Full Changelog](https://github.com/CosmWasm/cw-multi-test/compare/v0.20.0...v0.20.1) + +**Merged pull requests:** + +- Fixed contract wrapper [\#147](https://github.com/CosmWasm/cw-multi-test/pull/147) ([DariuszDepta](https://github.com/DariuszDepta)) + +## [v0.20.0](https://github.com/CosmWasm/cw-multi-test/tree/v0.20.0) (2023-12-06) + +[Full Changelog](https://github.com/CosmWasm/cw-multi-test/compare/v0.19.0...v0.20.0) + +**Closed issues:** + +- Unit testing IBC with mock module fails: Cannot execute Stargate [\#37](https://github.com/CosmWasm/cw-multi-test/issues/37) +- Allow mocking Stargate messages [\#40](https://github.com/CosmWasm/cw-multi-test/issues/40) +- MultiTest does not support CosmosMsg::Stargate [\#88](https://github.com/CosmWasm/cw-multi-test/issues/88) + +**Merged pull requests:** + +- Stargate mock support [\#106](https://github.com/CosmWasm/cw-multi-test/pull/106) ([DariuszDepta](https://github.com/DariuszDepta)) +- Made `no_init` function public [\#107](https://github.com/CosmWasm/cw-multi-test/pull/107) ([DariuszDepta](https://github.com/DariuszDepta)) +- Separated test helper contracts for Gov and IBC [\#108](https://github.com/CosmWasm/cw-multi-test/pull/108) ([DariuszDepta](https://github.com/DariuszDepta)) +- Add test to check custom `AddressGenerator` implementation [\#110](https://github.com/CosmWasm/cw-multi-test/pull/110) ([epanchee](https://github.com/epanchee)) + ## [v0.19.0](https://github.com/CosmWasm/cw-multi-test/tree/v0.19.0) (2023-11-28) [Full Changelog](https://github.com/CosmWasm/cw-multi-test/compare/v0.18.1...v0.19.0) @@ -68,6 +146,15 @@ - Adds BankQuery::Supply support [\#51](https://github.com/CosmWasm/cw-multi-test/pull/51) ([JakeHartnell](https://github.com/JakeHartnell)) - Remove direct k256 dependencies [\#47](https://github.com/CosmWasm/cw-multi-test/pull/47) ([webmaster128](https://github.com/webmaster128)) +## [v0.16.6](https://github.com/CosmWasm/cw-multi-test/tree/v0.16.6) (2024-03-15) + +[Full Changelog](https://github.com/CosmWasm/cw-multi-test/compare/v0.16.5...v0.16.6) + +**Merged pull requests:** + +- Fixed contract + wrapper [\#143](https://github.com/CosmWasm/cw-multi-test/pull/143) ([DariuszDepta](https://github.com/DariuszDepta)) + ## [v0.16.5](https://github.com/CosmWasm/cw-multi-test/tree/v0.16.5) (2023-06-07) [Full Changelog](https://github.com/CosmWasm/cw-multi-test/compare/v0.16.4...v0.16.5) @@ -131,6 +218,7 @@ changelog will be noisy - not everything is relevant to `cw-multi-test` there. ## [v0.16.1](https://github.com/CosmWasm/cw-plus/tree/v0.16.1) (2022-11-23) [Full Changelog](https://github.com/CosmWasm/cw-plus/compare/v0.16.0...v0.16.1) + - Modules for Stargate (IBC and Gov) messages - failing by default, but possible to exchange ## [v0.16.0](https://github.com/CosmWasm/cw-plus/tree/v0.16.0) (2022-10-14) @@ -329,7 +417,7 @@ changelog will be noisy - not everything is relevant to `cw-multi-test` there. - Update changelog add upcoming [\#675](https://github.com/CosmWasm/cw-plus/pull/675) ([maurolacy](https://github.com/maurolacy)) - Reject proposals early [\#668](https://github.com/CosmWasm/cw-plus/pull/668) ([Callum-A](https://github.com/Callum-A)) - cw20-base: validate addresses are unique in initial balances [\#659](https://github.com/CosmWasm/cw-plus/pull/659) ([harryscholes](https://github.com/harryscholes)) -- New SECURITY.md refering to wasmd [\#624](https://github.com/CosmWasm/cw-plus/pull/624) ([ethanfrey](https://github.com/ethanfrey)) +- New SECURITY.md referring to wasmd [\#624](https://github.com/CosmWasm/cw-plus/pull/624) ([ethanfrey](https://github.com/ethanfrey)) ## [v0.13.0](https://github.com/CosmWasm/cw-plus/tree/v0.13.0) (2022-03-09) @@ -389,7 +477,7 @@ changelog will be noisy - not everything is relevant to `cw-multi-test` there. **Merged pull requests:** - Prepare release v0.12.0 [\#654](https://github.com/CosmWasm/cw-plus/pull/654) ([uint](https://github.com/uint)) -- Ics20 same ack handling as ibctransfer [\#653](https://github.com/CosmWasm/cw-plus/pull/653) ([ethanfrey](https://github.com/ethanfrey)) +- Ics20 same ack handling as IBC transfer [\#653](https://github.com/CosmWasm/cw-plus/pull/653) ([ethanfrey](https://github.com/ethanfrey)) - packages: support custom queries [\#652](https://github.com/CosmWasm/cw-plus/pull/652) ([uint](https://github.com/uint)) - CW20 - Fix Docs URL [\#649](https://github.com/CosmWasm/cw-plus/pull/649) ([entrancedjames](https://github.com/entrancedjames)) - CW3: Add proposal\_id field to VoteInfo structure [\#648](https://github.com/CosmWasm/cw-plus/pull/648) ([ueco-jb](https://github.com/ueco-jb)) @@ -539,7 +627,7 @@ changelog will be noisy - not everything is relevant to `cw-multi-test` there. - ics20: Handle send errors with reply [\#520](https://github.com/CosmWasm/cw-plus/pull/520) ([ethanfrey](https://github.com/ethanfrey)) - Proper execute responses [\#519](https://github.com/CosmWasm/cw-plus/pull/519) ([ethanfrey](https://github.com/ethanfrey)) - Publish MsgInstantiate / Execute responses [\#518](https://github.com/CosmWasm/cw-plus/pull/518) ([maurolacy](https://github.com/maurolacy)) -- Fix instaniate reply data [\#517](https://github.com/CosmWasm/cw-plus/pull/517) ([ethanfrey](https://github.com/ethanfrey)) +- Fix instantiate reply data [\#517](https://github.com/CosmWasm/cw-plus/pull/517) ([ethanfrey](https://github.com/ethanfrey)) - Use protobuf de helpers [\#515](https://github.com/CosmWasm/cw-plus/pull/515) ([maurolacy](https://github.com/maurolacy)) - Add tests for the claims controller [\#514](https://github.com/CosmWasm/cw-plus/pull/514) ([sgoya](https://github.com/sgoya)) - Implement cw3-flex-multisig helper [\#479](https://github.com/CosmWasm/cw-plus/pull/479) ([orkunkl](https://github.com/orkunkl)) @@ -558,9 +646,9 @@ changelog will be noisy - not everything is relevant to `cw-multi-test` there. - Prepare 0.10.1 release [\#513](https://github.com/CosmWasm/cw-plus/pull/513) ([ethanfrey](https://github.com/ethanfrey)) - Added cw1-whitelist-ng to CI [\#512](https://github.com/CosmWasm/cw-plus/pull/512) ([hashedone](https://github.com/hashedone)) -- cw1-subkeys-ng: Additional follow up improvements [\#506](https://github.com/CosmWasm/cw-plus/pull/506) ([hashedone](https://github.com/hashedone)) +- cw1-subkeys-ng: Additional follow-up improvements [\#506](https://github.com/CosmWasm/cw-plus/pull/506) ([hashedone](https://github.com/hashedone)) - Parse reply helpers [\#502](https://github.com/CosmWasm/cw-plus/pull/502) ([maurolacy](https://github.com/maurolacy)) -- cw1-whitelist-ng: Contract implementation in terms of semantical structures [\#499](https://github.com/CosmWasm/cw-plus/pull/499) ([hashedone](https://github.com/hashedone)) +- cw1-whitelist-ng: Contract implementation in terms of semantic structures [\#499](https://github.com/CosmWasm/cw-plus/pull/499) ([hashedone](https://github.com/hashedone)) - range\_de for IndexMap [\#498](https://github.com/CosmWasm/cw-plus/pull/498) ([uint](https://github.com/uint)) - Implement range\_de for SnapshotMap [\#497](https://github.com/CosmWasm/cw-plus/pull/497) ([uint](https://github.com/uint)) - Fix publish script [\#486](https://github.com/CosmWasm/cw-plus/pull/486) ([ethanfrey](https://github.com/ethanfrey)) @@ -608,7 +696,7 @@ changelog will be noisy - not everything is relevant to `cw-multi-test` there. - Release v0.10.0-soon4 [\#477](https://github.com/CosmWasm/cw-plus/pull/477) ([ethanfrey](https://github.com/ethanfrey)) - Update to CosmWasm 1.0.0-soon2 [\#475](https://github.com/CosmWasm/cw-plus/pull/475) ([ethanfrey](https://github.com/ethanfrey)) - Allow error type conversions in ensure! and ensure\_eq! [\#474](https://github.com/CosmWasm/cw-plus/pull/474) ([webmaster128](https://github.com/webmaster128)) -- Improve error handling / remove FIXMEs [\#470](https://github.com/CosmWasm/cw-plus/pull/470) ([maurolacy](https://github.com/maurolacy)) +- Improve error handling / remove FIXME markers [\#470](https://github.com/CosmWasm/cw-plus/pull/470) ([maurolacy](https://github.com/maurolacy)) - Add ensure [\#469](https://github.com/CosmWasm/cw-plus/pull/469) ([ethanfrey](https://github.com/ethanfrey)) - Key deserializer improvements [\#467](https://github.com/CosmWasm/cw-plus/pull/467) ([maurolacy](https://github.com/maurolacy)) - Upgrade to cosmwasm/workspace-optimizer:0.12.3 [\#465](https://github.com/CosmWasm/cw-plus/pull/465) ([webmaster128](https://github.com/webmaster128)) @@ -659,7 +747,7 @@ changelog will be noisy - not everything is relevant to `cw-multi-test` there. - storage-plus: Improve in-code documentation of map primitives, in particular `MultiIndex` [\#407](https://github.com/CosmWasm/cw-plus/issues/407) - Remove use of dyn in multitest Router [\#404](https://github.com/CosmWasm/cw-plus/issues/404) - Define generic multitest module [\#387](https://github.com/CosmWasm/cw-plus/issues/387) -- Cw20 state key compatibity with previous versions [\#346](https://github.com/CosmWasm/cw-plus/issues/346) +- Cw20 state key compatibility with previous versions [\#346](https://github.com/CosmWasm/cw-plus/issues/346) - Refactor cw20-base to use controller pattern [\#205](https://github.com/CosmWasm/cw-plus/issues/205) **Merged pull requests:** @@ -715,7 +803,7 @@ changelog will be noisy - not everything is relevant to `cw-multi-test` there. - Snapshot item [\#409](https://github.com/CosmWasm/cw-plus/pull/409) ([maurolacy](https://github.com/maurolacy)) - cw20-base: upgrade helper.ts to cosmjs 0.26.0 [\#406](https://github.com/CosmWasm/cw-plus/pull/406) ([spacepotahto](https://github.com/spacepotahto)) - CW1-whitelist execute multitest [\#402](https://github.com/CosmWasm/cw-plus/pull/402) ([ueco-jb](https://github.com/ueco-jb)) -- Implementing all messages handling in mutlitest App [\#398](https://github.com/CosmWasm/cw-plus/pull/398) ([hashedone](https://github.com/hashedone)) +- Implementing all messages handling in MultiTest App [\#398](https://github.com/CosmWasm/cw-plus/pull/398) ([hashedone](https://github.com/hashedone)) - Make it easier to assert events on reply statements [\#395](https://github.com/CosmWasm/cw-plus/pull/395) ([ethanfrey](https://github.com/ethanfrey)) - Add helpers to check events [\#392](https://github.com/CosmWasm/cw-plus/pull/392) ([ethanfrey](https://github.com/ethanfrey)) - Switching from String to anyhow::Error for error type in multi-test [\#389](https://github.com/CosmWasm/cw-plus/pull/389) ([hashedone](https://github.com/hashedone)) @@ -788,7 +876,7 @@ changelog will be noisy - not everything is relevant to `cw-multi-test` there. - Responses validation in multi-test [\#373](https://github.com/CosmWasm/cw-plus/pull/373) ([hashedone](https://github.com/hashedone)) - Cw20 logo spec [\#370](https://github.com/CosmWasm/cw-plus/pull/370) ([ethanfrey](https://github.com/ethanfrey)) - Properly handling data in submessages in multi-test [\#369](https://github.com/CosmWasm/cw-plus/pull/369) ([hashedone](https://github.com/hashedone)) -- Abstracting API out of tests internals so it is clearly owned by `App` [\#368](https://github.com/CosmWasm/cw-plus/pull/368) ([hashedone](https://github.com/hashedone)) +- Abstracting API out of tests internals, so it is clearly owned by `App` [\#368](https://github.com/CosmWasm/cw-plus/pull/368) ([hashedone](https://github.com/hashedone)) - Storage plus doc correction [\#367](https://github.com/CosmWasm/cw-plus/pull/367) ([hashedone](https://github.com/hashedone)) - Multitest migrate support [\#366](https://github.com/CosmWasm/cw-plus/pull/366) ([ethanfrey](https://github.com/ethanfrey)) - Reorganizations of contracts in `multi-test::test_utils` [\#365](https://github.com/CosmWasm/cw-plus/pull/365) ([hashedone](https://github.com/hashedone)) @@ -841,7 +929,7 @@ changelog will be noisy - not everything is relevant to `cw-multi-test` there. - Proper event/data handling on reply in multitest [\#326](https://github.com/CosmWasm/cw-plus/issues/326) - Messages differ for cw20 & cw20\_base [\#320](https://github.com/CosmWasm/cw-plus/issues/320) - Upgrade cw20-staking to cw 15 [\#312](https://github.com/CosmWasm/cw-plus/issues/312) -- Uprade cw20-ics20 to cw 0.15 [\#311](https://github.com/CosmWasm/cw-plus/issues/311) +- Upgrade cw20-ics20 to cw 0.15 [\#311](https://github.com/CosmWasm/cw-plus/issues/311) - Upgrade cw20-escrow to 0.15 [\#309](https://github.com/CosmWasm/cw-plus/issues/309) - Upgrade cw20-bonding to 0.15 [\#307](https://github.com/CosmWasm/cw-plus/issues/307) - cw1-subkeys [\#305](https://github.com/CosmWasm/cw-plus/issues/305) @@ -911,7 +999,7 @@ changelog will be noisy - not everything is relevant to `cw-multi-test` there. **Merged pull requests:** - Clarify index\_key\(\) range\(\) vs prefix\(\) behaviour [\#291](https://github.com/CosmWasm/cw-plus/pull/291) ([maurolacy](https://github.com/maurolacy)) -- Pkowned to vec u8 [\#290](https://github.com/CosmWasm/cw-plus/pull/290) ([maurolacy](https://github.com/maurolacy)) +- PkOwned to vec u8 [\#290](https://github.com/CosmWasm/cw-plus/pull/290) ([maurolacy](https://github.com/maurolacy)) - Update to CosmWasm v0.14.0 [\#289](https://github.com/CosmWasm/cw-plus/pull/289) ([ethanfrey](https://github.com/ethanfrey)) - Primary key / index key helpers [\#288](https://github.com/CosmWasm/cw-plus/pull/288) ([maurolacy](https://github.com/maurolacy)) @@ -961,7 +1049,7 @@ changelog will be noisy - not everything is relevant to `cw-multi-test` there. **Merged pull requests:** -- Bump dependency to cosmasm v0.14.0-beta3 [\#269](https://github.com/CosmWasm/cw-plus/pull/269) ([ethanfrey](https://github.com/ethanfrey)) +- Bump dependency to cosmwasm v0.14.0-beta3 [\#269](https://github.com/CosmWasm/cw-plus/pull/269) ([ethanfrey](https://github.com/ethanfrey)) - Remove unused PrimaryKey::parse\_key [\#267](https://github.com/CosmWasm/cw-plus/pull/267) ([webmaster128](https://github.com/webmaster128)) - Use workspace-optimizer:0.11.0 [\#262](https://github.com/CosmWasm/cw-plus/pull/262) ([webmaster128](https://github.com/webmaster128)) - Update cosmwasm-std [\#260](https://github.com/CosmWasm/cw-plus/pull/260) ([yihuang](https://github.com/yihuang)) @@ -1072,7 +1160,7 @@ changelog will be noisy - not everything is relevant to `cw-multi-test` there. - Don't use hooks for snapshotting on cw3-cw4 interface [\#162](https://github.com/CosmWasm/cw-plus/issues/162) - Refactor snapshotting into reusable module [\#161](https://github.com/CosmWasm/cw-plus/issues/161) - Distinguish between weight 0 and not member in cw3 queries [\#154](https://github.com/CosmWasm/cw-plus/issues/154) -- Migrate strorage-plus to v0.12.0 [\#149](https://github.com/CosmWasm/cw-plus/issues/149) +- Migrate storage-plus to v0.12.0 [\#149](https://github.com/CosmWasm/cw-plus/issues/149) - Asymmetries between query and execute in CW1 \(subkeys\) [\#145](https://github.com/CosmWasm/cw-plus/issues/145) - Add token-weighted group [\#142](https://github.com/CosmWasm/cw-plus/issues/142) - Multisig handles changes to group membership [\#141](https://github.com/CosmWasm/cw-plus/issues/141) @@ -1180,7 +1268,7 @@ changelog will be noisy - not everything is relevant to `cw-multi-test` there. **Closed issues:** -- Migration to 0.11: errors of shared functions accross contracts [\#103](https://github.com/CosmWasm/cw-plus/issues/103) +- Migration to 0.11: errors of shared functions across contracts [\#103](https://github.com/CosmWasm/cw-plus/issues/103) - Look at serde\(flatten\) to simplify return value composition [\#57](https://github.com/CosmWasm/cw-plus/issues/57) **Merged pull requests:** @@ -1222,7 +1310,7 @@ changelog will be noisy - not everything is relevant to `cw-multi-test` there. **Closed issues:** - Implement Copy for Coin / Vec\ [\#77](https://github.com/CosmWasm/cw-plus/issues/77) -- Why does not cw20 pass the received native token? [\#74](https://github.com/CosmWasm/cw-plus/issues/74) +- Why cw20 does not pass the received native token? [\#74](https://github.com/CosmWasm/cw-plus/issues/74) - Cw20Coin duplication [\#73](https://github.com/CosmWasm/cw-plus/issues/73) - Fix docker run script in all contract README [\#69](https://github.com/CosmWasm/cw-plus/issues/69) - Add cw20 support to atomic swap contract [\#27](https://github.com/CosmWasm/cw-plus/issues/27) @@ -1275,7 +1363,7 @@ changelog will be noisy - not everything is relevant to `cw-multi-test` there. - Bump all CosmWasm dependencies to 0.10.1 [\#56](https://github.com/CosmWasm/cw-plus/pull/56) ([ethanfrey](https://github.com/ethanfrey)) - Add new query to return all allowances on subkeys [\#54](https://github.com/CosmWasm/cw-plus/pull/54) ([ethanfrey](https://github.com/ethanfrey)) - Add CanSend query to the cw1 spec [\#53](https://github.com/CosmWasm/cw-plus/pull/53) ([ethanfrey](https://github.com/ethanfrey)) -- Add Expration to cw0 [\#51](https://github.com/CosmWasm/cw-plus/pull/51) ([ethanfrey](https://github.com/ethanfrey)) +- Add expiration to cw0 [\#51](https://github.com/CosmWasm/cw-plus/pull/51) ([ethanfrey](https://github.com/ethanfrey)) - Nft 721 spec [\#50](https://github.com/CosmWasm/cw-plus/pull/50) ([ethanfrey](https://github.com/ethanfrey)) - Add Subkeys helper [\#49](https://github.com/CosmWasm/cw-plus/pull/49) ([ethanfrey](https://github.com/ethanfrey)) - Add helpers to cw20-base [\#46](https://github.com/CosmWasm/cw-plus/pull/46) ([ethanfrey](https://github.com/ethanfrey)) @@ -1331,6 +1419,4 @@ changelog will be noisy - not everything is relevant to `cw-multi-test` there. - Define all Message and Query types [\#11](https://github.com/CosmWasm/cw-plus/pull/11) ([ethanfrey](https://github.com/ethanfrey)) - Set up basic CI script [\#10](https://github.com/CosmWasm/cw-plus/pull/10) ([ethanfrey](https://github.com/ethanfrey)) - - \* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* diff --git a/CLA.md b/CLA.md deleted file mode 100644 index 17a701ee..00000000 --- a/CLA.md +++ /dev/null @@ -1,23 +0,0 @@ -## Contributor License Agreement -The following terms are used throughout this agreement: - -* You - the person or legal entity including its affiliates asked to accept this agreement. An affiliate is any entity that controls or is controlled by the legal entity, or is under common control with it. -* Project - is an umbrella term that refers to any and all Confio OÜ open source projects. -* Contribution - any type of work that is submitted to a Project, including any modifications or additions to existing work. -* Submitted - conveyed to a Project via a pull request, commit, issue, or any form of electronic, written, or verbal communication with Confio OÜ, contributors or maintainers. - -## 1. Grant of Copyright License. - -Subject to the terms and conditions of this agreement, You grant to the Projects’ maintainers, contributors, users and to Confio OÜ a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your contributions and such derivative works. Except for this license, You reserve all rights, title, and interest in your contributions. - -## 2. Grant of Patent License. - -Subject to the terms and conditions of this agreement, You grant to the Projects’ maintainers, contributors, users and to Confio OÜ a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer your contributions, where such license applies only to those patent claims licensable by you that are necessarily infringed by your contribution or by combination of your contribution with the project to which this contribution was submitted. - -If any entity institutes patent litigation - including cross-claim or counterclaim in a lawsuit - against You alleging that your contribution or any project it was submitted to constitutes or is responsible for direct or contributory patent infringement, then any patent licenses granted to that entity under this agreement shall terminate as of the date such litigation is filed. - -## 3. Source of Contribution. - -Your contribution is either your original creation, based upon previous work that, to the best of your knowledge, is covered under an appropriate open source license and you have the right under that license to submit that work with modifications, whether created in whole or in part by you, or you have clearly identified the source of the contribution and any license or other restriction (like related patents, trademarks, and license agreements) of which you are personally aware. - -_Based in [GitHub's CLA](https://cla.github.com/agreement)__ \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 6ce5bb86..e3f565c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -673,7 +673,7 @@ name = "clone-cw-multi-test" version = "0.6.2" dependencies = [ "anyhow", - "bech32 0.9.1", + "bech32 0.11.0", "cargo_metadata", "cosmrs", "cosmwasm-schema 2.1.3", diff --git a/Cargo.toml b/Cargo.toml index 640b110a..b2c1a004 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ backtrace = ["anyhow/backtrace"] [dependencies] anyhow = "1.0.75" -bech32 = "0.9.1" +bech32 = "0.11.0" cosmwasm-std = { version = "2.1", features = [ "iterator", "staking", @@ -29,7 +29,7 @@ prost = "0.13.0" schemars = "0.8.16" serde = "1.0.193" sha2 = "0.10.8" -thiserror = "1.0.50" +thiserror = "1.0.61" # Clone testing deps ## Network diff --git a/SECURITY.md b/SECURITY.md index 830ec171..e5fc15ed 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,16 +1,11 @@ # Security Policy This repository is maintained by Confio as part of the CosmWasm stack. -Please see https://github.com/CosmWasm/advisories/blob/main/SECURITY.md -for our security policy. -## Supported Versions - -cw-plus is still pre v1.0. A best effort has been made that the contracts here are secure, and we have moved the more -experimental contracts into community repositories like [cw-nfts](https://github.com/CosmWasm/cw-nfts) and -[cw-tokens](https://github.com/CosmWasm/cw-tokens). That said, we have not done an audit on them (formal or informal) -and you can use them at your own risk. We highly suggest doing your own audit on any contract you plan to deploy -with significant token value, and please inform us if it detects any issues so we can upstream them. - -Until v1.0 APIs are subject to change. The contracts APIs are pretty much stable, most work is currently -in `storage-plus` and `multi-test`. +The code here is not intended to be used in production +(i.e. cw-multi-test should only be used as a [Development dependency](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#development-dependencies)). +Thus it is not covered by the Cosmos bug bounty program and is not treated as strict +as other components when it comes to bugs. +However, if you still think you found a security critical +issue please find the contact information at +https://github.com/CosmWasm/advisories/blob/main/SECURITY.md. diff --git a/src/addons/addresses/mock.rs b/src/addons/addresses/mock.rs deleted file mode 100644 index 081199cc..00000000 --- a/src/addons/addresses/mock.rs +++ /dev/null @@ -1,148 +0,0 @@ -use crate::error::AnyResult; -use crate::AddressGenerator; -use cosmwasm_std::{instantiate2_address, Addr, Api, CanonicalAddr, Storage}; -use sha2::digest::Update; -use sha2::{Digest, Sha256}; - -/// Address generator that mimics the original `wasmd` behavior. -/// -/// [MockAddressGenerator] implements [AddressGenerator] trait in terms of -/// [`contract_address`](AddressGenerator::contract_address) and -/// [`predictable_contract_address`](AddressGenerator::predictable_contract_address) functions: -/// - `contract_address` generates non-predictable addresses for contracts, -/// using the same algorithm as `wasmd`, see: [`BuildContractAddressClassic`] for details. -/// - `predictable_contract_address` generates predictable addresses for contracts using -/// [`instantiate2_address`] function defined in `cosmwasm-std`. -/// -/// [`BuildContractAddressClassic`]:https://github.com/CosmWasm/wasmd/blob/3b6512c9f154995188ead84ab3bd9e034b49a0f3/x/wasm/keeper/addresses.go#L35-L41 -/// [`instantiate2_address`]:https://github.com/CosmWasm/cosmwasm/blob/8a652d7cd8071f71139deca6be8194ed4a278b2c/packages/std/src/addresses.rs#L309-L318 -#[derive(Default)] -pub struct MockAddressGenerator; - -impl AddressGenerator for MockAddressGenerator { - /// Generates a _non-predictable_ contract address, like `wasmd` does it in real-life chain. - /// - /// Note that addresses generated by `wasmd` may change and users **should not** - /// rely on this value in any extend. - /// - /// Returns the contract address after its instantiation. - /// Address generated by this function is returned as a result - /// of processing `WasmMsg::Instantiate` message. - /// - /// **NOTES** - /// > 👉 The canonical address generated by this function is humanized using the - /// > `Api::addr_humanize` function, so the resulting value depends on used `Api` implementation. - /// > The following example uses Bech32 format for humanizing canonical addresses. - /// - /// > 👉 Do NOT use this function **directly** to generate a contract address, - /// > pass this address generator to `WasmKeeper`: - /// > `WasmKeeper::new().with_address_generator(MockAddressGenerator::default());` - /// - /// # Example - /// - /// ``` - /// # use cosmwasm_std::testing::MockStorage; - /// # use cw_multi_test::AddressGenerator; - /// # use cw_multi_test::addons::{MockAddressGenerator, MockApiBech32}; - /// // use `Api` that implements Bech32 format - /// let api = MockApiBech32::new("juno"); - /// // prepare mock storage - /// let mut storage = MockStorage::default(); - /// // initialize the address generator - /// let address_generator = MockAddressGenerator::default(); - /// // generate the address - /// let addr = address_generator.contract_address(&api, &mut storage, 1, 1).unwrap(); - /// - /// assert_eq!(addr.to_string(), - /// "juno14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9skjuwg8"); - /// ``` - fn contract_address( - &self, - api: &dyn Api, - _storage: &mut dyn Storage, - code_id: u64, - instance_id: u64, - ) -> AnyResult { - let canonical_addr = instantiate_address(code_id, instance_id); - Ok(Addr::unchecked(api.addr_humanize(&canonical_addr)?)) - } - - /// Generates a _predictable_ contract address, like `wasmd` does it in real-life chain. - /// - /// Returns a contract address after its instantiation. - /// Address generated by this function is returned as a result - /// of processing `WasmMsg::Instantiate2` message. - /// - /// **NOTES** - /// > 👉 The canonical address generated by this function is humanized using the - /// > `Api::addr_humanize` function, so the resulting value depends on used `Api` implementation. - /// > The following example uses Bech32 format for humanizing canonical addresses. - /// - /// > 👉 Do NOT use this function **directly** to generate a contract address, - /// > pass this address generator to WasmKeeper: - /// > `WasmKeeper::new().with_address_generator(MockAddressGenerator::default());` - /// - /// # Example - /// - /// ``` - /// # use cosmwasm_std::Api; - /// # use cosmwasm_std::testing::MockStorage; - /// # use cw_multi_test::AddressGenerator; - /// # use cw_multi_test::addons::{MockAddressGenerator, MockApiBech32}; - /// // use `Api` that implements Bech32 format - /// let api = MockApiBech32::new("juno"); - /// // prepare mock storage - /// let mut storage = MockStorage::default(); - /// // initialize the address generator - /// let address_generator = MockAddressGenerator::default(); - /// // checksum of the contract code base - /// let checksum = [0, 1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10, - /// 11,12,13,14,15,16,17,18,19,20,21, - /// 22,23,24,25,26,27,28,29,30,31]; - /// // creator address - /// let creator = api.addr_canonicalize(api.addr_make("creator").as_str()).unwrap(); - /// // salt - /// let salt = [10,11,12]; - /// // generate the address - /// let addr = address_generator - /// .predictable_contract_address(&api, &mut storage, 1, 1, &checksum, &creator, &salt) - /// .unwrap(); - /// - /// assert_eq!(addr.to_string(), - /// "juno1sv3gjp85m3xxluxreruards8ruxk5ykys8qfljwrdj5tv8kqxuhsmlfyud"); - /// ``` - fn predictable_contract_address( - &self, - api: &dyn Api, - _storage: &mut dyn Storage, - _code_id: u64, - _instance_id: u64, - checksum: &[u8], - - creator: &CanonicalAddr, - salt: &[u8], - ) -> AnyResult { - let canonical_addr = instantiate2_address(checksum, creator, salt)?; - Ok(Addr::unchecked(api.addr_humanize(&canonical_addr)?)) - } -} - -/// Returns non-predictable contract address. -/// -/// Address is generated using the same algorithm as [`BuildContractAddressClassic`] -/// implementation in `wasmd`. -/// -/// [`BuildContractAddressClassic`]:https://github.com/CosmWasm/wasmd/blob/3b6512c9f154995188ead84ab3bd9e034b49a0f3/x/wasm/keeper/addresses.go#L35-L41 -fn instantiate_address(code_id: u64, instance_id: u64) -> CanonicalAddr { - let mut key = Vec::::new(); - key.extend_from_slice(b"wasm\0"); - key.extend_from_slice(&code_id.to_be_bytes()); - key.extend_from_slice(&instance_id.to_be_bytes()); - let module = Sha256::digest("module".as_bytes()); - Sha256::new() - .chain(module) - .chain(key) - .finalize() - .to_vec() - .into() -} diff --git a/src/addons/addresses/mod.rs b/src/addons/addresses/mod.rs deleted file mode 100644 index 9afc1d5e..00000000 --- a/src/addons/addresses/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod mock; diff --git a/src/addons/api/bech32.rs b/src/addons/api/bech32.rs deleted file mode 100644 index 55b21cc3..00000000 --- a/src/addons/api/bech32.rs +++ /dev/null @@ -1,187 +0,0 @@ -use bech32::{decode, encode, FromBase32, ToBase32, Variant}; -use cosmwasm_std::testing::MockApi; -use cosmwasm_std::{ - Addr, Api, CanonicalAddr, RecoverPubkeyError, StdError, StdResult, VerificationError, -}; -use sha2::{Digest, Sha256}; - -/// Implementation of the `Api` trait that uses [`Bech32`] format -/// for humanizing canonical addresses. -/// -/// [`Bech32`]:https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki -pub struct MockApiBech32 { - api: MockApi, - prefix: String, - variant: Variant, -} - -impl MockApiBech32 { - /// Returns `Api` implementation that uses specified prefix - /// to generate addresses in **Bech32** format. - /// - /// # Example - /// - /// ``` - /// use cw_multi_test::addons::MockApiBech32; - /// - /// let api = MockApiBech32::new("juno"); - /// let addr = api.addr_make("creator"); - /// assert_eq!(addr.as_str(), - /// "juno1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqsksmtyp"); - /// ``` - pub fn new(prefix: &str) -> Self { - Self::new_with_variant(prefix, Variant::Bech32) - } - - /// Creates `Api` implementation that uses specified prefix - /// to generate addresses in format defined by provided Bech32 variant. - pub(crate) fn new_with_variant(prefix: &str, variant: Variant) -> Self { - Self { - api: MockApi::default(), - prefix: prefix.to_string(), - variant, - } - } -} - -impl Api for MockApiBech32 { - /// Takes a human readable address in **Bech32** format and checks if it is valid. - /// - /// If the validation succeeds, an `Addr` containing the same string as the input is returned. - /// - /// # Example - /// - /// ``` - /// use cosmwasm_std::Api; - /// use cw_multi_test::addons::MockApiBech32; - /// - /// let api = MockApiBech32::new("juno"); - /// let addr = api.addr_make("creator"); - /// assert_eq!(api.addr_validate(addr.as_str()).unwrap().as_str(), - /// addr.as_str()); - /// ``` - fn addr_validate(&self, input: &str) -> StdResult { - self.addr_humanize(&self.addr_canonicalize(input)?) - } - - /// Takes a human readable address in **Bech32** format and returns - /// a canonical binary representation of it. - /// - /// # Example - /// - /// ``` - /// use cosmwasm_std::Api; - /// use cw_multi_test::addons::MockApiBech32; - /// - /// let api = MockApiBech32::new("juno"); - /// let addr = api.addr_make("creator"); - /// assert_eq!(api.addr_canonicalize(addr.as_str()).unwrap().to_string(), - /// "BC6BFD848EBD7819C9A82BF124D65E7F739D08E002601E23BB906AACD40A3D81"); - /// ``` - fn addr_canonicalize(&self, input: &str) -> StdResult { - if let Ok((prefix, decoded, variant)) = decode(input) { - if prefix == self.prefix && variant == self.variant { - if let Ok(bytes) = Vec::::from_base32(&decoded) { - return Ok(bytes.into()); - } - } - } - Err(StdError::generic_err("Invalid input")) - } - - /// Takes a canonical address and returns a human readable address in **Bech32** format. - /// - /// This is the inverse operation of [`addr_canonicalize`]. - /// - /// [`addr_canonicalize`]: MockApiBech32::addr_canonicalize - /// - /// # Example - /// - /// ``` - /// use cosmwasm_std::Api; - /// use cw_multi_test::addons::MockApiBech32; - /// - /// let api = MockApiBech32::new("juno"); - /// let addr = api.addr_make("creator"); - /// let canonical_addr = api.addr_canonicalize(addr.as_str()).unwrap(); - /// assert_eq!(api.addr_humanize(&canonical_addr).unwrap().as_str(), - /// addr.as_str()); - /// ``` - fn addr_humanize(&self, canonical: &CanonicalAddr) -> StdResult { - if let Ok(encoded) = encode(&self.prefix, canonical.as_slice().to_base32(), self.variant) { - Ok(Addr::unchecked(encoded)) - } else { - Err(StdError::generic_err("Invalid canonical address")) - } - } - - fn secp256k1_verify( - &self, - message_hash: &[u8], - signature: &[u8], - public_key: &[u8], - ) -> Result { - self.api - .secp256k1_verify(message_hash, signature, public_key) - } - - fn secp256k1_recover_pubkey( - &self, - message_hash: &[u8], - signature: &[u8], - recovery_param: u8, - ) -> Result, RecoverPubkeyError> { - self.api - .secp256k1_recover_pubkey(message_hash, signature, recovery_param) - } - - fn ed25519_verify( - &self, - message: &[u8], - signature: &[u8], - public_key: &[u8], - ) -> Result { - self.api.ed25519_verify(message, signature, public_key) - } - - fn ed25519_batch_verify( - &self, - messages: &[&[u8]], - signatures: &[&[u8]], - public_keys: &[&[u8]], - ) -> Result { - self.api - .ed25519_batch_verify(messages, signatures, public_keys) - } - - fn debug(&self, message: &str) { - self.api.debug(message) - } -} - -impl MockApiBech32 { - /// Returns an address in **Bech32** format, built from provided input string. - /// - /// # Example - /// - /// ``` - /// use cw_multi_test::addons::MockApiBech32; - /// - /// let api = MockApiBech32::new("juno"); - /// let addr = api.addr_make("creator"); - /// assert_eq!(addr.as_str(), - /// "juno1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqsksmtyp"); - /// ``` - /// - /// # Panics - /// - /// This function panics when generating a valid address in **Bech32** - /// format is not possible, especially when prefix is too long or empty. - pub fn addr_make(&self, input: &str) -> Addr { - let digest = Sha256::digest(input).to_vec(); - match encode(&self.prefix, digest.to_base32(), self.variant) { - Ok(address) => Addr::unchecked(address), - Err(reason) => panic!("Generating address failed with reason: {}", reason), - } - } -} diff --git a/src/addons/api/bech32m.rs b/src/addons/api/bech32m.rs deleted file mode 100644 index d630f2b0..00000000 --- a/src/addons/api/bech32m.rs +++ /dev/null @@ -1,154 +0,0 @@ -use crate::addons::MockApiBech32; -use bech32::Variant; -use cosmwasm_std::{Addr, Api, CanonicalAddr, RecoverPubkeyError, StdResult, VerificationError}; - -/// Implementation of the `Api` trait that uses [`Bech32m`] format -/// for humanizing canonical addresses. -/// -/// [`Bech32m`]:https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki -pub struct MockApiBech32m(MockApiBech32); - -impl MockApiBech32m { - /// Returns `Api` implementation that uses specified prefix - /// to generate addresses in **Bech32m** format. - /// - /// # Example - /// - /// ``` - /// use cw_multi_test::addons::MockApiBech32m; - /// - /// let api = MockApiBech32m::new("osmosis"); - /// let addr = api.addr_make("sender"); - /// assert_eq!(addr.as_str(), - /// "osmosis1pgm8hyk0pvphmlvfjc8wsvk4daluz5tgrw6pu5mfpemk74uxnx9qgv9940"); - /// ``` - pub fn new(prefix: &'static str) -> Self { - Self(MockApiBech32::new_with_variant(prefix, Variant::Bech32m)) - } -} - -impl Api for MockApiBech32m { - /// Takes a human readable address in **Bech32m** format and checks if it is valid. - /// - /// If the validation succeeds, an `Addr` containing the same string as the input is returned. - /// - /// # Example - /// - /// ``` - /// use cosmwasm_std::Api; - /// use cw_multi_test::addons::MockApiBech32m; - /// - /// let api = MockApiBech32m::new("osmosis"); - /// let addr = api.addr_make("sender"); - /// assert_eq!(api.addr_validate(addr.as_str()).unwrap().as_str(), - /// addr.as_str()); - /// ``` - fn addr_validate(&self, input: &str) -> StdResult { - self.0.addr_validate(input) - } - - /// Takes a human readable address in **Bech32m** format and returns - /// a canonical binary representation of it. - /// - /// # Example - /// - /// ``` - /// use cosmwasm_std::Api; - /// use cw_multi_test::addons::MockApiBech32; - /// - /// let api = MockApiBech32::new("osmosis"); - /// let addr = api.addr_make("sender"); - /// assert_eq!(api.addr_canonicalize(addr.as_str()).unwrap().to_string(), - /// "0A367B92CF0B037DFD89960EE832D56F7FC151681BB41E53690E776F5786998A"); - /// ``` - fn addr_canonicalize(&self, input: &str) -> StdResult { - self.0.addr_canonicalize(input) - } - - /// Takes a canonical address and returns a human readable address in **Bech32m** format. - /// - /// This is the inverse operation of [`addr_canonicalize`]. - /// - /// [`addr_canonicalize`]: MockApiBech32m::addr_canonicalize - /// - /// # Example - /// - /// ``` - /// use cosmwasm_std::Api; - /// use cw_multi_test::addons::MockApiBech32m; - /// - /// let api = MockApiBech32m::new("osmosis"); - /// let addr = api.addr_make("sender"); - /// let canonical_addr = api.addr_canonicalize(addr.as_str()).unwrap(); - /// assert_eq!(api.addr_humanize(&canonical_addr).unwrap().as_str(), - /// addr.as_str()); - /// ``` - fn addr_humanize(&self, canonical: &CanonicalAddr) -> StdResult { - self.0.addr_humanize(canonical) - } - - fn secp256k1_verify( - &self, - message_hash: &[u8], - signature: &[u8], - public_key: &[u8], - ) -> Result { - self.0.secp256k1_verify(message_hash, signature, public_key) - } - - fn secp256k1_recover_pubkey( - &self, - message_hash: &[u8], - signature: &[u8], - recovery_param: u8, - ) -> Result, RecoverPubkeyError> { - self.0 - .secp256k1_recover_pubkey(message_hash, signature, recovery_param) - } - - fn ed25519_verify( - &self, - message: &[u8], - signature: &[u8], - public_key: &[u8], - ) -> Result { - self.0.ed25519_verify(message, signature, public_key) - } - - fn ed25519_batch_verify( - &self, - messages: &[&[u8]], - signatures: &[&[u8]], - public_keys: &[&[u8]], - ) -> Result { - self.0 - .ed25519_batch_verify(messages, signatures, public_keys) - } - - fn debug(&self, message: &str) { - self.0.debug(message) - } -} - -impl MockApiBech32m { - /// Returns an address in **Bech32m** format, built from provided input string. - /// - /// # Example - /// - /// ``` - /// use cw_multi_test::addons::MockApiBech32m; - /// - /// let api = MockApiBech32m::new("osmosis"); - /// let addr = api.addr_make("sender"); - /// assert_eq!(addr.as_str(), - /// "osmosis1pgm8hyk0pvphmlvfjc8wsvk4daluz5tgrw6pu5mfpemk74uxnx9qgv9940"); - /// ``` - /// - /// # Panics - /// - /// This function panics when generating a valid address in **Bech32** - /// format is not possible, especially when prefix is too long or empty. - pub fn addr_make(&self, input: &str) -> Addr { - self.0.addr_make(input) - } -} diff --git a/src/addons/api/mod.rs b/src/addons/api/mod.rs deleted file mode 100644 index d59bbae5..00000000 --- a/src/addons/api/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod bech32; -pub mod bech32m; diff --git a/src/addons/mod.rs b/src/addons/mod.rs deleted file mode 100644 index c31658c3..00000000 --- a/src/addons/mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -//! # MultiTest add-ons -//! -//! Additional components and functionalities used to enhance -//! or customize tests of CosmWasm smart contracts. - -mod addresses; -mod api; - -pub use addresses::mock::MockAddressGenerator; -pub use api::bech32::MockApiBech32; -pub use api::bech32m::MockApiBech32m; diff --git a/src/addresses.rs b/src/addresses.rs index 3a0b1669..43d49341 100644 --- a/src/addresses.rs +++ b/src/addresses.rs @@ -1,9 +1,78 @@ -//! # Implementation of address generators +//! # Implementation of address conversions and generators use crate::error::AnyResult; -use crate::prefixed_storage::prefixed_read; -use crate::wasm::{CONTRACTS, NAMESPACE_WASM}; -use cosmwasm_std::{Addr, Api, CanonicalAddr, HexBinary, Order, Storage}; +use crate::{MockApiBech32, MockApiBech32m}; +use cosmwasm_std::testing::MockApi; +use cosmwasm_std::{instantiate2_address, Addr, Api, CanonicalAddr, Storage}; +use sha2::digest::Update; +use sha2::{Digest, Sha256}; + +const DEFAULT_PREFIX: &str = "cosmwasm"; + +/// Defines conversions to [Addr], this conversion is format agnostic +/// and should be aligned with the format generated by [MockApi]. +/// +/// [MockApi]: https://github.com/CosmWasm/cosmwasm/blob/9a239838baba50f4f47230da306f39a8bb4ea697/packages/std/src/testing/mock.rs#L251-L257 +pub trait IntoAddr { + /// Converts into [Addr]. + fn into_addr(self) -> Addr; + + /// Converts into [Addr] with custom prefix. + fn into_addr_with_prefix(self, prefix: &'static str) -> Addr; +} + +impl IntoAddr for &str { + /// Converts [&str] into [Addr]. + fn into_addr(self) -> Addr { + MockApi::default().addr_make(self) + } + + /// Converts [&str] into [Addr] with custom prefix. + fn into_addr_with_prefix(self, prefix: &'static str) -> Addr { + MockApi::default().with_prefix(prefix).addr_make(self) + } +} + +/// Defines conversions to `Bech32` compatible addresses. +pub trait IntoBech32 { + /// Converts into [Addr] containing a string compatible with `Bech32` format with default prefix. + fn into_bech32(self) -> Addr; + + /// Converts into [Addr] containing a string compatible with `Bech32` format with custom prefix. + fn into_bech32_with_prefix(self, prefix: &'static str) -> Addr; +} + +impl IntoBech32 for &str { + /// Converts [&str] into [Addr] containing a string compatible with `Bech32` format with default prefix. + fn into_bech32(self) -> Addr { + MockApiBech32::new(DEFAULT_PREFIX).addr_make(self) + } + + /// Converts [&str] into [Addr] containing a string compatible with `Bech32` format with custom prefix. + fn into_bech32_with_prefix(self, prefix: &'static str) -> Addr { + MockApiBech32::new(prefix).addr_make(self) + } +} + +/// Defines conversions to `Bech32m` compatible addresses. +pub trait IntoBech32m { + /// Converts into [Addr] containing a string compatible with `Bech32m` format with default prefix. + fn into_bech32m(self) -> Addr; + /// Converts into [Addr] containing a string compatible with `Bech32m` format with custom prefix. + fn into_bech32m_with_prefix(self, prefix: &'static str) -> Addr; +} + +impl IntoBech32m for &str { + /// Converts [&str] into [Addr] containing a string compatible with `Bech32m` format with default prefix. + fn into_bech32m(self) -> Addr { + MockApiBech32m::new(DEFAULT_PREFIX).addr_make(self) + } + + /// Converts [&str] into [Addr] containing a string compatible with `Bech32m` format with custom prefix. + fn into_bech32m_with_prefix(self, prefix: &'static str) -> Addr { + MockApiBech32m::new(prefix).addr_make(self) + } +} /// Common address generator interface. /// @@ -12,30 +81,13 @@ use cosmwasm_std::{Addr, Api, CanonicalAddr, HexBinary, Order, Storage}; /// or [predictable_contract_address](AddressGenerator::predictable_contract_address) is used, /// but users should not make any assumptions about the value of the generated address. pub trait AddressGenerator { - #[deprecated( - since = "0.18.0", - note = "use `contract_address` or `predictable_contract_address` instead; will be removed in version 1.0.0" - )] - fn next_address(&self, storage: &mut dyn Storage) -> Addr { - //TODO After removing this function in version 1.0, make `CONTRACTS` and `NAMESPACE_WASM` private in `wasm.rs`. - let count = CONTRACTS - .range_raw( - &prefixed_read(storage, NAMESPACE_WASM), - None, - None, - Order::Ascending, - ) - .count(); - Addr::unchecked(format!("contract{}", count)) - } - /// Generates a _non-predictable_ contract address, just like the real-life chain /// returns contract address after its instantiation. /// Address generated by this function is returned as a result of processing /// `WasmMsg::Instantiate` message. /// /// The default implementation generates a contract address based - /// on contract's instance identifier only. + /// on contract's code and instance identifier. /// /// # Example /// @@ -50,26 +102,18 @@ pub trait AddressGenerator { /// /// let my_address_generator = MyAddressGenerator{}; /// - /// let addr = my_address_generator.contract_address(&api, &mut storage, 100, 0).unwrap(); - /// assert_eq!(addr.to_string(),"contract0"); - /// /// let addr = my_address_generator.contract_address(&api, &mut storage, 100, 1).unwrap(); - /// assert_eq!(addr.to_string(),"contract1"); - /// - /// let addr = my_address_generator.contract_address(&api, &mut storage, 200, 5).unwrap(); - /// assert_eq!(addr.to_string(),"contract5"); - /// - /// let addr = my_address_generator.contract_address(&api, &mut storage, 200, 6).unwrap(); - /// assert_eq!(addr.to_string(),"contract6"); + /// assert!(addr.as_str().starts_with("cosmwasm1")); /// ``` fn contract_address( &self, - _api: &dyn Api, + api: &dyn Api, _storage: &mut dyn Storage, - _code_id: u64, + code_id: u64, instance_id: u64, ) -> AnyResult { - Ok(Addr::unchecked(format!("contract{instance_id}"))) + let canonical_addr = instantiate_address(code_id, instance_id); + Ok(api.addr_humanize(&canonical_addr)?) } /// Generates a _predictable_ contract address, just like the real-life chain @@ -77,52 +121,76 @@ pub trait AddressGenerator { /// Address generated by this function is returned as a result of processing /// `WasmMsg::Instantiate2` message. /// - /// The default implementation generates a contract address based on provided salt only. + /// The default implementation generates a contract address based on provided + /// creator address and salt. /// /// # Example /// /// ``` - /// # use cosmwasm_std::Api; + /// # use cosmwasm_std::{Api, Checksum}; /// # use cosmwasm_std::testing::{MockApi, MockStorage}; /// # use cw_multi_test::{AddressGenerator, SimpleAddressGenerator}; /// # let api = MockApi::default(); /// # let mut storage = MockStorage::default(); - /// # let creator = api.addr_canonicalize("creator").unwrap(); /// struct MyAddressGenerator; /// /// impl AddressGenerator for MyAddressGenerator {} /// /// let my_address_generator = MyAddressGenerator{}; /// - /// let addr = my_address_generator.predictable_contract_address(&api, &mut storage, 100, 0, &[0], &creator, &[0]).unwrap(); - /// assert_eq!(addr.to_string(),"contract00"); - /// - /// let addr = my_address_generator.predictable_contract_address(&api, &mut storage, 100, 1, &[1], &creator, &[0]).unwrap(); - /// assert_eq!(addr.to_string(),"contract00"); - /// - /// let addr = my_address_generator.predictable_contract_address(&api, &mut storage, 200, 0, &[2], &creator, &[1]).unwrap(); - /// assert_eq!(addr.to_string(),"contract01"); - /// - /// let addr = my_address_generator.predictable_contract_address(&api, &mut storage, 200, 1, &[3], &creator, &[1]).unwrap(); - /// assert_eq!(addr.to_string(),"contract01"); + /// let creator1 = api.addr_canonicalize(&api.addr_make("creator1").to_string()).unwrap(); + /// let creator2 = api.addr_canonicalize(&api.addr_make("creator2").to_string()).unwrap(); + /// let salt1 = [0xc0,0xff,0xee]; + /// let salt2 = [0xbe,0xef]; + /// let chs = Checksum::generate(&[1]); + /// + /// let addr11 = my_address_generator.predictable_contract_address(&api, &mut storage, 1, 0, chs.as_slice(), &creator1, &salt1).unwrap(); + /// let addr12 = my_address_generator.predictable_contract_address(&api, &mut storage, 1, 0, chs.as_slice(), &creator1, &salt2).unwrap(); + /// let addr21 = my_address_generator.predictable_contract_address(&api, &mut storage, 1, 0, chs.as_slice(), &creator2, &salt1).unwrap(); + /// let addr22 = my_address_generator.predictable_contract_address(&api, &mut storage, 1, 0, chs.as_slice(), &creator2, &salt2).unwrap(); + /// + /// assert_ne!(addr11, addr12); + /// assert_ne!(addr11, addr21); + /// assert_ne!(addr11, addr22); + /// assert_ne!(addr12, addr21); + /// assert_ne!(addr12, addr22); + /// assert_ne!(addr21, addr22); /// ``` fn predictable_contract_address( &self, - _api: &dyn Api, + api: &dyn Api, _storage: &mut dyn Storage, _code_id: u64, _instance_id: u64, - _checksum: &[u8], - _creator: &CanonicalAddr, + checksum: &[u8], + creator: &CanonicalAddr, salt: &[u8], ) -> AnyResult { - Ok(Addr::unchecked(format!( - "contract{}", - HexBinary::from(salt).to_hex() - ))) + let canonical_addr = instantiate2_address(checksum, creator, salt)?; + Ok(api.addr_humanize(&canonical_addr)?) } } +/// Returns non-predictable contract address. +/// +/// Address is generated using the same algorithm as [`BuildContractAddressClassic`] +/// implementation in `wasmd`. +/// +/// [`BuildContractAddressClassic`]:https://github.com/CosmWasm/wasmd/blob/3b6512c9f154995188ead84ab3bd9e034b49a0f3/x/wasm/keeper/addresses.go#L35-L41 +fn instantiate_address(code_id: u64, instance_id: u64) -> CanonicalAddr { + let mut key = Vec::::new(); + key.extend_from_slice(b"wasm\0"); + key.extend_from_slice(&code_id.to_be_bytes()); + key.extend_from_slice(&instance_id.to_be_bytes()); + let module = Sha256::digest("module".as_bytes()); + Sha256::new() + .chain(module) + .chain(key) + .finalize() + .to_vec() + .into() +} + /// Default contract address generator used in [WasmKeeper](crate::WasmKeeper). pub struct SimpleAddressGenerator; diff --git a/src/api.rs b/src/api.rs new file mode 100644 index 00000000..bd3fa9ed --- /dev/null +++ b/src/api.rs @@ -0,0 +1,119 @@ +use bech32::primitives::decode::CheckedHrpstring; +use bech32::{encode, Bech32, Bech32m, Hrp}; +use cosmwasm_std::testing::MockApi; +use cosmwasm_std::{ + Addr, Api, CanonicalAddr, RecoverPubkeyError, StdError, StdResult, VerificationError, +}; +use sha2::{Digest, Sha256}; + +pub struct MockApiBech { + api: MockApi, + prefix: String, + _phantom_data: std::marker::PhantomData, +} + +impl MockApiBech { + /// Returns `Api` implementation that uses specified prefix + /// to generate addresses in `Bech32` or `Bech32m` format. + pub fn new(prefix: &str) -> Self { + Self { + api: MockApi::default(), + prefix: prefix.to_string(), + _phantom_data: std::marker::PhantomData, + } + } +} + +impl Api for MockApiBech { + fn addr_validate(&self, input: &str) -> StdResult { + self.addr_humanize(&self.addr_canonicalize(input)?) + } + + fn addr_canonicalize(&self, input: &str) -> StdResult { + if let Ok(s) = CheckedHrpstring::new::(input) { + if s.hrp().to_string() == self.prefix { + return Ok(s.byte_iter().collect::>().into()); + } + } + Err(StdError::generic_err("Invalid input")) + } + + fn addr_humanize(&self, canonical: &CanonicalAddr) -> StdResult { + let hrp = Hrp::parse(&self.prefix).map_err(|e| StdError::generic_err(e.to_string()))?; + if let Ok(encoded) = encode::(hrp, canonical.as_slice()) { + Ok(Addr::unchecked(encoded)) + } else { + Err(StdError::generic_err("Invalid canonical address")) + } + } + + fn secp256k1_verify( + &self, + message_hash: &[u8], + signature: &[u8], + public_key: &[u8], + ) -> Result { + self.api + .secp256k1_verify(message_hash, signature, public_key) + } + + fn secp256k1_recover_pubkey( + &self, + message_hash: &[u8], + signature: &[u8], + recovery_param: u8, + ) -> Result, RecoverPubkeyError> { + self.api + .secp256k1_recover_pubkey(message_hash, signature, recovery_param) + } + + fn ed25519_verify( + &self, + message: &[u8], + signature: &[u8], + public_key: &[u8], + ) -> Result { + self.api.ed25519_verify(message, signature, public_key) + } + + fn ed25519_batch_verify( + &self, + messages: &[&[u8]], + signatures: &[&[u8]], + public_keys: &[&[u8]], + ) -> Result { + self.api + .ed25519_batch_verify(messages, signatures, public_keys) + } + + fn debug(&self, message: &str) { + self.api.debug(message) + } +} + +impl MockApiBech { + /// Returns an address in `Bech32` or `Bech32m` format, built from provided input string. + /// + /// # Panics + /// + /// This function panics when generating a valid address in `Bech32` or `Bech32m` + /// format is not possible, especially when the prefix is too long or empty. + pub fn addr_make(&self, input: &str) -> Addr { + match Hrp::parse(&self.prefix) { + Ok(hrp) => Addr::unchecked(encode::(hrp, Sha256::digest(input).as_slice()).unwrap()), + Err(reason) => panic!("Generating address failed with reason: {}", reason), + } + } +} + +/// Implementation of the `cosmwasm_std::Api` trait that uses [Bech32] format +/// for humanizing canonical addresses. +/// +/// [Bech32]: https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki +pub type MockApiBech32 = MockApiBech; + +/// Implementation of the `cosmwasm_std::Api` trait that uses [Bech32m] format +/// for humanizing canonical addresses. +/// +/// [Bech32m]: https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki +pub type MockApiBech32m = MockApiBech; diff --git a/src/app.rs b/src/app.rs index 4d10958e..9e32bba4 100644 --- a/src/app.rs +++ b/src/app.rs @@ -10,29 +10,34 @@ use crate::executor::{AppResponse, Executor}; use crate::gov::Gov; use crate::ibc::Ibc; use crate::module::{FailingModule, Module}; +use crate::prefixed_storage::{ + prefixed, prefixed_multilevel, prefixed_multilevel_read, prefixed_read, +}; use crate::staking::{Distribution, DistributionKeeper, StakeKeeper, Staking, StakingSudo}; use crate::transactions::transactional; use crate::wasm::{ContractData, Wasm, WasmKeeper, WasmSudo}; -use crate::{AppBuilder, Contract, GovFailingModule, IbcFailingModule}; +use crate::{AppBuilder, Contract, GovFailingModule, IbcFailingModule, Stargate, StargateFailing}; use cosmwasm_std::testing::{MockApi, MockStorage}; use cosmwasm_std::{ from_json, to_json_binary, Addr, Api, Binary, BlockInfo, ContractResult, CosmosMsg, CustomQuery, Empty, Querier, QuerierResult, QuerierWrapper, QueryRequest, Record, Storage, SystemError, SystemResult, }; -use schemars::JsonSchema; use serde::{de::DeserializeOwned, Serialize}; use std::fmt::Debug; use std::marker::PhantomData; const ADDRESSES: Item> = Item::new("addresses"); +/// Advances the blockchain environment to the next block in tests, enabling developers to simulate +/// time-dependent contract behaviors and block-related triggers efficiently. pub fn next_block(block: &mut BlockInfo) { block.time = block.time.plus_seconds(5); block.height += 1; } -/// Type alias for default build `App` to make its storing simpler in typical scenario +/// A type alias for the default-built App. It simplifies storage and handling in typical scenarios, +/// streamlining the use of the App structure in standard test setups. pub type BasicApp = App< BankKeeper, MockApi, @@ -43,11 +48,12 @@ pub type BasicApp = App< DistributionKeeper, IbcFailingModule, GovFailingModule, + StargateFailing, >; -/// Router is a persisted state. You can query this. -/// Execution generally happens on the RouterCache, which then can be atomically committed or rolled back. -/// We offer .execute() as a wrapper around cache, execute, commit/rollback process. +/// # Blockchain application simulator +/// +/// This structure is the main component of the real-life blockchain simulator. #[derive(Clone)] pub struct App< Bank = BankKeeper, @@ -59,17 +65,27 @@ pub struct App< Distr = DistributionKeeper, Ibc = IbcFailingModule, Gov = GovFailingModule, + Stargate = StargateFailing, > { - pub(crate) router: Router, + pub(crate) router: Router, pub(crate) api: Api, pub(crate) storage: Storage, pub(crate) block: BlockInfo, pub(crate) remote: RemoteChannel, } +/// No-op application initialization function. +pub fn no_init( + router: &mut Router, + api: &dyn Api, + storage: &mut dyn Storage, +) { + let _ = (router, api, storage); +} + impl BasicApp { /// Creates new default `App` implementation working with Empty custom messages. - pub fn new(remote: RemoteChannel, init_fn: F) -> AnyResult + pub fn new(remote: RemoteChannel, init_fn: F) -> Self where F: FnOnce( &mut Router< @@ -80,6 +96,7 @@ impl BasicApp { DistributionKeeper, IbcFailingModule, GovFailingModule, + StargateFailing, >, &dyn Api, &mut dyn Storage, @@ -90,11 +107,8 @@ impl BasicApp { } /// Creates new default `App` implementation working with customized exec and query messages. -/// Outside of `App` implementation to make type elision better. -pub fn custom_app( - remote: RemoteChannel, - init_fn: F, -) -> AnyResult> +/// Outside the `App` implementation to make type elision better. +pub fn custom_app(remote: RemoteChannel, init_fn: F) -> BasicApp where ExecC: CustomMsg + DeserializeOwned + 'static, QueryC: Debug + CustomQuery + DeserializeOwned + 'static, @@ -107,6 +121,7 @@ where DistributionKeeper, IbcFailingModule, GovFailingModule, + StargateFailing, >, &dyn Api, &mut dyn Storage, @@ -115,10 +130,10 @@ where AppBuilder::new_custom().with_remote(remote).build(init_fn) } -impl Querier - for App +impl Querier + for App where - CustomT::ExecT: Clone + Debug + PartialEq + JsonSchema + DeserializeOwned + 'static, + CustomT::ExecT: CustomMsg + DeserializeOwned + 'static, CustomT::QueryT: CustomQuery + DeserializeOwned + 'static, WasmT: Wasm, BankT: Bank, @@ -129,6 +144,7 @@ where DistrT: Distribution, IbcT: Ibc, GovT: Gov, + StargateT: Stargate, { fn raw_query(&self, bin_request: &[u8]) -> QuerierResult { self.router @@ -137,10 +153,11 @@ where } } -impl Executor - for App +impl + Executor + for App where - CustomT::ExecT: Clone + Debug + PartialEq + JsonSchema + DeserializeOwned + 'static, + CustomT::ExecT: CustomMsg + DeserializeOwned + 'static, CustomT::QueryT: CustomQuery + DeserializeOwned + 'static, WasmT: Wasm, BankT: Bank, @@ -151,6 +168,7 @@ where DistrT: Distribution, IbcT: Ibc, GovT: Gov, + StargateT: Stargate, { fn execute(&mut self, sender: Addr, msg: CosmosMsg) -> AnyResult { let mut all = self.execute_multi(sender, vec![msg])?; @@ -159,8 +177,8 @@ where } } -impl - App +impl + App where WasmT: Wasm, BankT: Bank, @@ -171,14 +189,16 @@ where DistrT: Distribution, IbcT: Ibc, GovT: Gov, - CustomT::QueryT: CustomQuery, + StargateT: Stargate, { /// Returns a shared reference to application's router. - pub fn router(&self) -> &Router { + pub fn router( + &self, + ) -> &Router { &self.router } - /// Returns a shared reference to application's api. + /// Returns a shared reference to application's API. pub fn api(&self) -> &ApiT { &self.api } @@ -193,10 +213,11 @@ where &mut self.storage } + /// Initializes modules. pub fn init_modules(&mut self, init_fn: F) -> T where F: FnOnce( - &mut Router, + &mut Router, &dyn Api, &mut dyn Storage, ) -> T, @@ -204,10 +225,11 @@ where init_fn(&mut self.router, &self.api, &mut self.storage) } + /// Queries a module. pub fn read_module(&self, query_fn: F) -> T where F: FnOnce( - &Router, + &Router, &dyn Api, &dyn Storage, ) -> T, @@ -218,8 +240,8 @@ where // Helper functions to call some custom WasmKeeper logic. // They show how we can easily add such calls to other custom keepers (CustomT, StakingT, etc) -impl - App +impl + App where BankT: Bank, ApiT: Api, @@ -230,6 +252,7 @@ where DistrT: Distribution, IbcT: Ibc, GovT: Gov, + StargateT: Stargate, CustomT::ExecT: CustomMsg + DeserializeOwned + 'static, CustomT::QueryT: CustomQuery + DeserializeOwned + 'static, { @@ -247,11 +270,9 @@ where /// Registers contract code (like uploading wasm bytecode on a chain), /// so it can later be used to instantiate a contract. pub fn store_code(&mut self, code: Box>) -> u64 { - self.init_modules(|router, _, _| { - router - .wasm - .store_code(Addr::unchecked("code-creator"), code) - }) + self.router + .wasm + .store_code(MockApi::default().addr_make("creator"), code) } /// Registers contract code (like [store_code](Self::store_code)), @@ -267,24 +288,128 @@ where creator: Addr, code: Box>, ) -> u64 { - self.init_modules(|router, _, _| router.wasm.store_code(creator, code)) + self.router.wasm.store_code(creator, code) + } + + /// Registers contract code (like [store_code_with_creator](Self::store_code_with_creator)), + /// but takes the code identifier as an additional argument. + pub fn store_code_with_id( + &mut self, + creator: Addr, + code_id: u64, + code: Box>, + ) -> AnyResult { + self.router.wasm.store_code_with_id(creator, code_id, code) + } + + /// Duplicates the contract code identified by `code_id` and returns + /// the identifier of the newly created copy of the contract code. + /// + /// # Examples + /// + /// ``` + /// use cosmwasm_std::Addr; + /// use cw_multi_test::App; + /// + /// // contract implementation + /// mod echo { + /// // contract entry points not shown here + /// # use std::todo; + /// # use cosmwasm_std::{Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response, StdError, SubMsg, WasmMsg}; + /// # use serde::{Deserialize, Serialize}; + /// # use cw_multi_test::{Contract, ContractWrapper}; + /// # + /// # fn instantiate(_: DepsMut, _: Env, _: MessageInfo, _: Empty) -> Result { + /// # todo!() + /// # } + /// # + /// # fn execute(_: DepsMut, _: Env, _info: MessageInfo, msg: WasmMsg) -> Result { + /// # todo!() + /// # } + /// # + /// # fn query(_deps: Deps, _env: Env, _msg: Empty) -> Result { + /// # todo!() + /// # } + /// # + /// pub fn contract() -> Box> { + /// // should return the contract + /// # Box::new(ContractWrapper::new(execute, instantiate, query)) + /// } + /// } + /// + /// let mut app = App::default(); + /// + /// // store a new contract, save the code id + /// let code_id = app.store_code(echo::contract()); + /// + /// // duplicate the existing contract, duplicated contract has different code id + /// assert_ne!(code_id, app.duplicate_code(code_id).unwrap()); + /// + /// // zero is an invalid identifier for contract code, returns an error + /// assert_eq!("code id: invalid", app.duplicate_code(0).unwrap_err().to_string()); + /// + /// // there is no contract code with identifier 100 stored yet, returns an error + /// assert_eq!("code id 100: no such code", app.duplicate_code(100).unwrap_err().to_string()); + /// ``` + pub fn duplicate_code(&mut self, code_id: u64) -> AnyResult { + self.router.wasm.duplicate_code(code_id) } /// Returns `ContractData` for the contract with specified address. pub fn contract_data(&self, address: &Addr) -> AnyResult { - self.read_module(|router, _, storage| router.wasm.contract_data(storage, address)) + self.router.wasm.contract_data(&self.storage, address) } /// Returns a raw state dump of all key-values held by a contract with specified address. pub fn dump_wasm_raw(&self, address: &Addr) -> Vec { - self.read_module(|router, _, storage| router.wasm.dump_wasm_raw(storage, address)) + self.router.wasm.dump_wasm_raw(&self.storage, address) + } + + /// Returns **read-only** storage for a contract with specified address. + pub fn contract_storage<'a>(&'a self, contract_addr: &Addr) -> Box { + self.router + .wasm + .contract_storage(&self.storage, contract_addr) + } + + /// Returns **read-write** storage for a contract with specified address. + pub fn contract_storage_mut<'a>(&'a mut self, contract_addr: &Addr) -> Box { + self.router + .wasm + .contract_storage_mut(&mut self.storage, contract_addr) + } + + /// Returns **read-only** prefixed storage with specified namespace. + pub fn prefixed_storage<'a>(&'a self, namespace: &[u8]) -> Box { + Box::new(prefixed_read(&self.storage, namespace)) + } + + /// Returns **mutable** prefixed storage with specified namespace. + pub fn prefixed_storage_mut<'a>(&'a mut self, namespace: &[u8]) -> Box { + Box::new(prefixed(&mut self.storage, namespace)) + } + + /// Returns **read-only** prefixed, multilevel storage with specified namespaces. + pub fn prefixed_multilevel_storage<'a>( + &'a self, + namespaces: &[&[u8]], + ) -> Box { + Box::new(prefixed_multilevel_read(&self.storage, namespaces)) + } + + /// Returns **mutable** prefixed, multilevel storage with specified namespaces. + pub fn prefixed_multilevel_storage_mut<'a>( + &'a mut self, + namespaces: &[&[u8]], + ) -> Box { + Box::new(prefixed_multilevel(&mut self.storage, namespaces)) } } -impl - App +impl + App where - CustomT::ExecT: Debug + PartialEq + Clone + JsonSchema + DeserializeOwned + 'static, + CustomT::ExecT: CustomMsg + DeserializeOwned + 'static, CustomT::QueryT: CustomQuery + DeserializeOwned + 'static, WasmT: Wasm, BankT: Bank, @@ -295,25 +420,27 @@ where DistrT: Distribution, IbcT: Ibc, GovT: Gov, + StargateT: Stargate, { + /// Sets the initial block properties. pub fn set_block(&mut self, block: BlockInfo) { + self.block = block; self.router .staking .process_queue(&self.api, &mut self.storage, &self.router, &self.block) .unwrap(); - self.block = block; } - // this let's use use "next block" steps that add eg. one height and 5 seconds + /// Updates the current block applying the specified closure, usually [next_block]. pub fn update_block(&mut self, action: F) { + action(&mut self.block); self.router .staking .process_queue(&self.api, &mut self.storage, &self.router, &self.block) .unwrap(); - action(&mut self.block); } - /// Returns a copy of the current block_info + /// Returns a copy of the current block info. pub fn block_info(&self) -> BlockInfo { self.block.clone() } @@ -335,7 +462,7 @@ where } /// Simple helper so we get access to all the QuerierWrapper helpers, - /// eg. wrap().query_wasm_smart, query_all_balances, ... + /// e.g. wrap().query_wasm_smart, query_all_balances, ... pub fn wrap(&self) -> QuerierWrapper { QuerierWrapper::new(self) } @@ -382,7 +509,10 @@ where contract_addr: U, msg: &T, ) -> AnyResult { - let msg = to_json_binary(msg)?; + let msg = WasmSudo { + contract_addr: contract_addr.into(), + message: to_json_binary(msg)?, + }; let Self { block, @@ -393,9 +523,7 @@ where } = self; transactional(&mut *storage, |write_cache, _| { - router - .wasm - .sudo(&*api, contract_addr.into(), write_cache, router, block, msg) + router.wasm.sudo(&*api, write_cache, router, block, msg) }) } @@ -419,25 +547,32 @@ where }) } } - +/// The Router plays a critical role in managing and directing +/// transactions within the Cosmos blockchain. #[derive(Clone)] -pub struct Router { - // this can remain crate-only as all special functions are wired up to app currently - // we need to figure out another format for wasm, as some like sudo need to be called after init +pub struct Router { + /// Wasm module instance to be used in this [Router]. pub(crate) wasm: Wasm, - // these must be pub so we can initialize them (super user) on build + /// Bank module instance to be used in this [Router]. pub bank: Bank, + /// Custom module instance to be used in this [Router]. pub custom: Custom, + /// Staking module instance to be used in this [Router]. pub staking: Staking, + /// Distribution module instance to be used in this [Router]. pub distribution: Distr, + /// IBC module instance to be used in this [Router]. pub ibc: Ibc, + /// Governance module instance to be used in this [Router]. pub gov: Gov, + /// Stargate handler instance to be used in this [Router]. + pub stargate: Stargate, } -impl - Router +impl + Router where - CustomT::ExecT: Clone + Debug + PartialEq + JsonSchema + DeserializeOwned + 'static, + CustomT::ExecT: CustomMsg + DeserializeOwned + 'static, CustomT::QueryT: CustomQuery + DeserializeOwned + 'static, CustomT: Module, WasmT: Wasm, @@ -446,7 +581,9 @@ where DistrT: Distribution, IbcT: Ibc, GovT: Gov, + StargateT: Stargate, { + /// Returns a querier populated with the instance of this [Router]. pub fn querier<'a>( &'a self, api: &'a dyn Api, @@ -465,9 +602,13 @@ where /// We use it to allow calling into modules from another module in sudo mode. /// Things like gov proposals belong here. pub enum SudoMsg { + /// Bank privileged actions. Bank(BankSudo), + /// Custom privileged actions. Custom(Empty), + /// Staking privileged actions. Staking(StakingSudo), + /// Wasm privileged actions. Wasm(WasmSudo), } @@ -488,11 +629,18 @@ impl From for SudoMsg { SudoMsg::Staking(staking) } } - +/// A trait representing the Cosmos based chain's router. +/// +/// This trait is designed for routing messages within the Cosmos ecosystem. +/// It is key to ensure that transactions and contract calls are directed to the +/// correct destinations during testing, simulating real-world blockchain operations. pub trait CosmosRouter { - type ExecC; + /// Type of the executed custom message. + type ExecC: CustomMsg; + /// Type of the query custom message. type QueryC: CustomQuery; + /// Executes messages. fn execute( &self, api: &dyn Api, @@ -502,6 +650,7 @@ pub trait CosmosRouter { msg: CosmosMsg, ) -> AnyResult; + /// Evaluates queries. fn query( &self, api: &dyn Api, @@ -510,6 +659,7 @@ pub trait CosmosRouter { request: QueryRequest, ) -> AnyResult; + /// Evaluates privileged actions. fn sudo( &self, api: &dyn Api, @@ -521,10 +671,10 @@ pub trait CosmosRouter { fn get_querier_storage(&self, storage: &dyn Storage) -> AnyResult; } -impl CosmosRouter - for Router +impl CosmosRouter + for Router where - CustomT::ExecT: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static, + CustomT::ExecT: CustomMsg + DeserializeOwned + 'static, CustomT::QueryT: CustomQuery + DeserializeOwned + 'static, CustomT: Module, WasmT: Wasm, @@ -533,6 +683,7 @@ where DistrT: Distribution, IbcT: Ibc, GovT: Gov, + StargateT: Stargate, { type ExecC = CustomT::ExecT; type QueryC = CustomT::QueryT; @@ -555,11 +706,19 @@ where .execute(api, storage, self, block, sender, msg), CosmosMsg::Ibc(msg) => self.ibc.execute(api, storage, self, block, sender, msg), CosmosMsg::Gov(msg) => self.gov.execute(api, storage, self, block, sender, msg), + #[allow(deprecated)] + CosmosMsg::Stargate { type_url, value } => self + .stargate + .execute_stargate(api, storage, self, block, sender, type_url, value), + #[cfg(feature = "cosmwasm_2_0")] + CosmosMsg::Any(msg) => self + .stargate + .execute_any(api, storage, self, block, sender, msg), _ => bail!("Cannot execute {:?}", msg), } } - /// this is used by `RouterQuerier` to actual implement the `Querier` interface. + /// This is used by `RouterQuerier` to actual implement the `Querier` interface. /// you most likely want to use `router.querier(storage, block).wrap()` to get a /// QuerierWrapper to interact with fn query( @@ -576,6 +735,12 @@ where QueryRequest::Custom(req) => self.custom.query(api, storage, &querier, block, req), QueryRequest::Staking(req) => self.staking.query(api, storage, &querier, block, req), QueryRequest::Ibc(req) => self.ibc.query(api, storage, &querier, block, req), + #[allow(deprecated)] + QueryRequest::Stargate { path, data } => self + .stargate + .query_stargate(api, storage, &querier, block, path, data), + #[cfg(feature = "cosmwasm_2_0")] + QueryRequest::Grpc(req) => self.stargate.query_grpc(api, storage, &querier, block, req), _ => unimplemented!(), } } @@ -588,10 +753,7 @@ where msg: SudoMsg, ) -> AnyResult { match msg { - SudoMsg::Wasm(msg) => { - self.wasm - .sudo(api, msg.contract_addr, storage, self, block, msg.msg) - } + SudoMsg::Wasm(msg) => self.wasm.sudo(api, storage, self, block, msg), SudoMsg::Bank(msg) => self.bank.sudo(api, storage, self, block, msg), SudoMsg::Staking(msg) => self.staking.sudo(api, storage, self, block, msg), SudoMsg::Custom(_) => unimplemented!(), @@ -625,6 +787,7 @@ impl MockRouter { impl CosmosRouter for MockRouter where + ExecC: CustomMsg, QueryC: CustomQuery, { type ExecC = ExecC; @@ -691,7 +854,7 @@ impl<'a, ExecC, QueryC> RouterQuerier<'a, ExecC, QueryC> { impl<'a, ExecC, QueryC> Querier for RouterQuerier<'a, ExecC, QueryC> where - ExecC: Clone + Debug + PartialEq + JsonSchema + DeserializeOwned + 'static, + ExecC: CustomMsg + DeserializeOwned + 'static, QueryC: CustomQuery + DeserializeOwned + 'static, { fn raw_query(&self, bin_request: &[u8]) -> QuerierResult { diff --git a/src/app_builder.rs b/src/app_builder.rs index ad747509..73339430 100644 --- a/src/app_builder.rs +++ b/src/app_builder.rs @@ -1,11 +1,11 @@ -//! Implementation of the builder for [App]. +//! AppBuilder helps you set up your test blockchain environment step by step [App]. use crate::wasm_emulation::channel::RemoteChannel; use crate::{ App, Bank, BankKeeper, Distribution, DistributionKeeper, FailingModule, Gov, GovFailingModule, - Ibc, IbcFailingModule, Module, Router, StakeKeeper, Staking, Wasm, WasmKeeper, + Ibc, IbcFailingModule, Module, Router, StakeKeeper, Staking, Stargate, StargateFailing, Wasm, + WasmKeeper, }; -use anyhow::Result as AnyResult; use cosmwasm_std::testing::{mock_env, MockApi, MockStorage}; use cosmwasm_std::{Api, BlockInfo, CustomMsg, CustomQuery, Empty, Storage}; use serde::de::DeserializeOwned; @@ -17,15 +17,18 @@ use std::fmt::Debug; /// /// ``` /// # use cosmwasm_std::Empty; -/// # use cw_multi_test::{BasicAppBuilder, FailingModule, Module}; +/// # use cw_multi_test::{BasicAppBuilder, FailingModule, Module, no_init}; /// # type MyHandler = FailingModule; /// # type MyExecC = Empty; /// # type MyQueryC = Empty; /// /// let mut app = BasicAppBuilder::::new_custom() /// .with_custom(MyHandler::default()) -/// .build(|_, _, _| {}); +/// .build(no_init); /// ``` +/// This type alias is crucial for constructing a custom app with specific modules. +/// It provides a streamlined approach to building and configuring an App tailored to +/// particular testing needs or scenarios. pub type BasicAppBuilder = AppBuilder< BankKeeper, MockApi, @@ -36,11 +39,12 @@ pub type BasicAppBuilder = AppBuilder< DistributionKeeper, IbcFailingModule, GovFailingModule, + StargateFailing, >; /// Utility to build [App] in stages. /// When particular properties are not explicitly set, then default values are used. -pub struct AppBuilder { +pub struct AppBuilder { api: Api, block: BlockInfo, storage: Storage, @@ -52,6 +56,7 @@ pub struct AppBuilder, + stargate: Stargate, } impl Default @@ -65,6 +70,7 @@ impl Default DistributionKeeper, IbcFailingModule, GovFailingModule, + StargateFailing, > { fn default() -> Self { @@ -83,6 +89,7 @@ impl DistributionKeeper, IbcFailingModule, GovFailingModule, + StargateFailing, > { /// Creates builder with default components working with empty exec and query messages. @@ -93,11 +100,12 @@ impl storage: MockStorage::new(), bank: BankKeeper::new(), wasm: WasmKeeper::new(), - custom: FailingModule::new("custom"), + custom: FailingModule::new(), staking: StakeKeeper::new(), distribution: DistributionKeeper::new(), - ibc: IbcFailingModule::new("ibc"), - gov: GovFailingModule::new("gov"), + ibc: IbcFailingModule::new(), + gov: GovFailingModule::new(), + stargate: StargateFailing, remote: None, } } @@ -114,6 +122,7 @@ impl DistributionKeeper, IbcFailingModule, GovFailingModule, + StargateFailing, > where ExecC: CustomMsg + DeserializeOwned + 'static, @@ -128,18 +137,19 @@ where storage: MockStorage::new(), bank: BankKeeper::new(), wasm: WasmKeeper::new(), - custom: FailingModule::new("custom"), + custom: FailingModule::new(), staking: StakeKeeper::new(), distribution: DistributionKeeper::new(), - ibc: IbcFailingModule::new("ibc"), - gov: GovFailingModule::new("gov"), + ibc: IbcFailingModule::new(), + gov: GovFailingModule::new(), + stargate: StargateFailing, remote: None, } } } -impl - AppBuilder +impl + AppBuilder where CustomT: Module, WasmT: Wasm, @@ -153,7 +163,8 @@ where pub fn with_wasm>( self, wasm: NewWasm, - ) -> AppBuilder { + ) -> AppBuilder + { let AppBuilder { bank, api, @@ -165,6 +176,7 @@ where ibc, gov, remote, + stargate, .. } = self; @@ -180,6 +192,7 @@ where ibc, gov, remote, + stargate, } } @@ -187,7 +200,8 @@ where pub fn with_bank( self, bank: NewBank, - ) -> AppBuilder { + ) -> AppBuilder + { let AppBuilder { wasm, api, @@ -199,6 +213,7 @@ where ibc, gov, remote, + stargate, .. } = self; @@ -213,6 +228,7 @@ where distribution, ibc, gov, + stargate, remote, } } @@ -221,7 +237,8 @@ where pub fn with_api( self, api: NewApi, - ) -> AppBuilder { + ) -> AppBuilder + { let AppBuilder { wasm, bank, @@ -232,6 +249,7 @@ where distribution, ibc, gov, + stargate, remote, .. } = self; @@ -247,6 +265,7 @@ where distribution, ibc, gov, + stargate, remote, } } @@ -255,7 +274,8 @@ where pub fn with_storage( self, storage: NewStorage, - ) -> AppBuilder { + ) -> AppBuilder + { let AppBuilder { wasm, api, @@ -266,6 +286,7 @@ where distribution, ibc, gov, + stargate, remote, .. } = self; @@ -281,11 +302,12 @@ where distribution, ibc, gov, + stargate, remote, } } - /// Overwrites the default custom messages handler. + /// Overwrites the default handler for custom messages. /// /// At this point it is needed that new custom implements some `Module` trait, but it doesn't need /// to be bound to ExecC or QueryC yet - as those may change. The cross-components validation is @@ -293,7 +315,8 @@ where pub fn with_custom( self, custom: NewCustom, - ) -> AppBuilder { + ) -> AppBuilder + { let AppBuilder { wasm, bank, @@ -304,6 +327,7 @@ where distribution, ibc, gov, + stargate, remote, .. } = self; @@ -319,6 +343,7 @@ where distribution, ibc, gov, + stargate, remote, } } @@ -327,7 +352,8 @@ where pub fn with_staking( self, staking: NewStaking, - ) -> AppBuilder { + ) -> AppBuilder + { let AppBuilder { wasm, api, @@ -338,6 +364,7 @@ where distribution, ibc, gov, + stargate, remote, .. } = self; @@ -353,6 +380,7 @@ where distribution, ibc, gov, + stargate, remote, } } @@ -361,8 +389,18 @@ where pub fn with_distribution( self, distribution: NewDistribution, - ) -> AppBuilder - { + ) -> AppBuilder< + BankT, + ApiT, + StorageT, + CustomT, + WasmT, + StakingT, + NewDistribution, + IbcT, + GovT, + StargateT, + > { let AppBuilder { wasm, api, @@ -373,6 +411,7 @@ where bank, ibc, gov, + stargate, remote, .. } = self; @@ -388,6 +427,7 @@ where distribution, ibc, gov, + stargate, remote, } } @@ -402,7 +442,8 @@ where pub fn with_ibc( self, ibc: NewIbc, - ) -> AppBuilder { + ) -> AppBuilder + { let AppBuilder { wasm, api, @@ -414,6 +455,7 @@ where distribution, gov, remote, + stargate, .. } = self; @@ -425,6 +467,7 @@ where wasm, custom, staking, + stargate, distribution, ibc, gov, @@ -436,7 +479,8 @@ where pub fn with_gov( self, gov: NewGov, - ) -> AppBuilder { + ) -> AppBuilder + { let AppBuilder { wasm, api, @@ -448,6 +492,7 @@ where distribution, ibc, remote, + stargate, .. } = self; @@ -462,6 +507,7 @@ where distribution, ibc, gov, + stargate, remote, } } @@ -470,7 +516,8 @@ where pub fn with_remote( self, remote: RemoteChannel, - ) -> AppBuilder { + ) -> AppBuilder + { let AppBuilder { wasm, api, @@ -482,6 +529,7 @@ where distribution, ibc, gov, + stargate, .. } = self; @@ -495,8 +543,46 @@ where staking, distribution, ibc, + gov, + stargate, remote: Some(remote), + } + } + + /// Overwrites the default stargate interface. + pub fn with_stargate( + self, + stargate: NewStargate, + ) -> AppBuilder + { + let AppBuilder { + wasm, + api, + storage, + custom, + block, + staking, + bank, + distribution, + ibc, gov, + remote, + .. + } = self; + + AppBuilder { + api, + block, + storage, + bank, + wasm, + custom, + staking, + distribution, + ibc, + gov, + stargate, + remote, } } @@ -513,7 +599,7 @@ where pub fn build( self, init_fn: F, - ) -> AnyResult> + ) -> App where BankT: Bank, ApiT: Api, @@ -524,8 +610,9 @@ where DistrT: Distribution, IbcT: Ibc, GovT: Gov, + StargateT: Stargate, F: FnOnce( - &mut Router, + &mut Router, &dyn Api, &mut dyn Storage, ), @@ -538,6 +625,7 @@ where distribution: self.distribution, ibc: self.ibc, gov: self.gov, + stargate: self.stargate, }; let mut app = App { @@ -545,11 +633,11 @@ where api: self.api, block: self.block, storage: self.storage, - remote: self.remote.ok_or(anyhow::anyhow!( - "Remote has to be defined to use clone-testing" - ))?, + remote: self + .remote + .expect("Remote has to be defined to use clone-testing"), }; app.init_modules(init_fn); - Ok(app) + app } } diff --git a/src/bank.rs b/src/bank.rs index ca08475f..213c7912 100644 --- a/src/bank.rs +++ b/src/bank.rs @@ -9,39 +9,59 @@ use crate::wasm_emulation::input::BankStorage; use crate::wasm_emulation::query::AllBankQuerier; use cosmwasm_std::{ coin, to_json_binary, Addr, AllBalanceResponse, Api, BalanceResponse, BankMsg, BankQuery, - Binary, BlockInfo, Coin, Event, Order, Querier, Storage, + Binary, BlockInfo, Coin, DenomMetadata, Event, Order, Querier, Storage, }; -use cosmwasm_std::{StdResult, SupplyResponse, Uint128}; +use cosmwasm_std::{StdResult, Uint128}; use cw_storage_plus::Map; use cw_utils::NativeBalance; use itertools::Itertools; use schemars::JsonSchema; -pub(crate) const BALANCES: Map<&Addr, NativeBalance> = Map::new("balances"); +/// Collection of bank balances. +const BALANCES: Map<&Addr, NativeBalance> = Map::new("balances"); -pub const NAMESPACE_BANK: &[u8] = b"bank"; +/// Collection of metadata for denomination. +const DENOM_METADATA: Map = Map::new("metadata"); -#[derive(Clone, std::fmt::Debug, PartialEq, Eq, JsonSchema)] +/// Default storage namespace for bank module. +const NAMESPACE_BANK: &[u8] = b"bank"; + +/// A message representing privileged actions in bank module. +#[derive(Clone, Debug, PartialEq, Eq, JsonSchema)] pub enum BankSudo { + /// Minting privileged action. Mint { + /// Destination address the tokens will be minted for. to_address: String, + /// Amount of the minted tokens. amount: Vec, }, } +/// This trait defines the interface for simulating banking operations. +/// +/// In the test environment, it is essential for testing financial transactions, +/// like transfers and balance checks, within your smart contracts. +/// This trait implements all of these functionalities. pub trait Bank: Module + AllBankQuerier { } +/// A structure representing a default bank keeper. +/// +/// Manages financial interactions in CosmWasm tests, such as simulating token transactions +/// and account balances. This is particularly important for contracts that deal with financial +/// operations in the Cosmos ecosystem. #[derive(Default)] pub struct BankKeeper { remote: Option, } impl BankKeeper { + /// Creates a new instance of a bank keeper with default settings. pub fn new() -> Self { - BankKeeper::default() + Self::default() } pub fn with_remote(mut self, remote: RemoteChannel) -> Self { @@ -49,7 +69,7 @@ impl BankKeeper { self } - // this is an "admin" function to let us adjust bank accounts in genesis + /// Administration function for adjusting bank accounts in genesis. pub fn init_balance( &self, storage: &mut dyn Storage, @@ -60,7 +80,7 @@ impl BankKeeper { self.set_balance(&mut bank_storage, account, amount) } - // this is an "admin" function to let us adjust bank accounts + /// Administration function for adjusting bank accounts. fn set_balance( &self, bank_storage: &mut dyn Storage, @@ -74,6 +94,18 @@ impl BankKeeper { .map_err(Into::into) } + /// Administration function for adjusting denomination metadata. + pub fn set_denom_metadata( + &self, + bank_storage: &mut dyn Storage, + denom: String, + metadata: DenomMetadata, + ) -> AnyResult<()> { + DENOM_METADATA + .save(bank_storage, denom, &metadata) + .map_err(Into::into) + } + fn get_balance(&self, bank_storage: &dyn Storage, account: &Addr) -> AnyResult> { // If there is no balance present, we query it on the distant chain if let Some(val) = BALANCES.may_load(bank_storage, account)? { @@ -136,7 +168,7 @@ impl BankKeeper { self.set_balance(bank_storage, &from_address, a.into_vec()) } - /// Filters out all 0 value coins and returns an error if the resulting Vec is empty + /// Filters out all `0` value coins and returns an error if the resulting vector is empty. fn normalize_amount(&self, amount: Vec) -> AnyResult> { let res: Vec<_> = amount.into_iter().filter(|x| !x.amount.is_zero()).collect(); if res.is_empty() { @@ -191,25 +223,7 @@ impl Module for BankKeeper { self.burn(&mut bank_storage, sender, amount)?; Ok(AppResponse::default()) } - m => bail!("Unsupported bank message: {:?}", m), - } - } - - fn sudo( - &self, - api: &dyn Api, - storage: &mut dyn Storage, - _router: &dyn CosmosRouter, - _block: &BlockInfo, - msg: BankSudo, - ) -> AnyResult { - let mut bank_storage = prefixed(storage, NAMESPACE_BANK); - match msg { - BankSudo::Mint { to_address, amount } => { - let to_address = api.addr_validate(&to_address)?; - self.mint(&mut bank_storage, to_address, amount)?; - Ok(AppResponse::default()) - } + other => unimplemented!("bank message: {other:?}"), } } @@ -227,7 +241,7 @@ impl Module for BankKeeper { let address = api.addr_validate(&address)?; let amount = self.get_balance(&bank_storage, &address)?; let res = AllBalanceResponse::new(amount); - Ok(to_json_binary(&res)?) + to_json_binary(&res).map_err(Into::into) } BankQuery::Balance { address, denom } => { let address = api.addr_validate(&address)?; @@ -237,14 +251,48 @@ impl Module for BankKeeper { .find(|c| c.denom == denom) .unwrap_or_else(|| coin(0, denom)); let res = BalanceResponse::new(amount); - Ok(to_json_binary(&res)?) + to_json_binary(&res).map_err(Into::into) } + #[cfg(feature = "cosmwasm_1_1")] BankQuery::Supply { denom } => { let amount = self.get_supply(&bank_storage, denom)?; let res = SupplyResponse::new(amount); - Ok(to_json_binary(&res)?) + to_json_binary(&res).map_err(Into::into) + } + #[cfg(feature = "cosmwasm_1_3")] + BankQuery::DenomMetadata { denom } => { + let meta = DENOM_METADATA.may_load(storage, denom)?.unwrap_or_default(); + let res = DenomMetadataResponse::new(meta); + to_json_binary(&res).map_err(Into::into) + } + #[cfg(feature = "cosmwasm_1_3")] + BankQuery::AllDenomMetadata { pagination: _ } => { + let mut metadata = vec![]; + for key in DENOM_METADATA.keys(storage, None, None, Order::Ascending) { + metadata.push(DENOM_METADATA.may_load(storage, key?)?.unwrap_or_default()); + } + let res = AllDenomMetadataResponse::new(metadata, None); + to_json_binary(&res).map_err(Into::into) + } + other => unimplemented!("bank query: {other:?}"), + } + } + + fn sudo( + &self, + api: &dyn Api, + storage: &mut dyn Storage, + _router: &dyn CosmosRouter, + _block: &BlockInfo, + msg: BankSudo, + ) -> AnyResult { + let mut bank_storage = prefixed(storage, NAMESPACE_BANK); + match msg { + BankSudo::Mint { to_address, amount } => { + let to_address = api.addr_validate(&to_address)?; + self.mint(&mut bank_storage, to_address, amount)?; + Ok(AppResponse::default()) } - q => bail!("Unsupported bank query: {:?}", q), } } } @@ -258,3 +306,364 @@ impl AllBankQuerier for BankKeeper { Ok(BankStorage { storage: balances? }) } } + +#[cfg(test)] +mod test { + use super::*; + + use crate::app::MockRouter; + use cosmwasm_std::testing::{mock_env, MockApi, MockQuerier, MockStorage}; + use cosmwasm_std::{coins, from_json, Empty, StdError}; + + fn query_balance( + bank: &BankKeeper, + api: &dyn Api, + store: &dyn Storage, + rcpt: &Addr, + ) -> Vec { + let req = BankQuery::AllBalances { + address: rcpt.clone().into(), + }; + let block = mock_env().block; + let querier: MockQuerier = MockQuerier::new(&[]); + + let raw = bank.query(api, store, &querier, &block, req).unwrap(); + let res: AllBalanceResponse = from_json(raw).unwrap(); + res.amount + } + + #[test] + #[cfg(feature = "cosmwasm_1_1")] + fn get_set_balance() { + let api = MockApi::default(); + let mut store = MockStorage::new(); + let block = mock_env().block; + let querier: MockQuerier = MockQuerier::new(&[]); + let router = MockRouter::default(); + + let owner = api.addr_make("owner"); + let rcpt = api.addr_make("receiver"); + let init_funds = vec![coin(100, "eth"), coin(20, "btc")]; + let norm = vec![coin(20, "btc"), coin(100, "eth")]; + + // set money + let bank = BankKeeper::new(); + bank.init_balance(&mut store, &owner, init_funds).unwrap(); + let bank_storage = prefixed_read(&store, NAMESPACE_BANK); + + // get balance work + let rich = bank.get_balance(&bank_storage, &owner).unwrap(); + assert_eq!(rich, norm); + let poor = bank.get_balance(&bank_storage, &rcpt).unwrap(); + assert_eq!(poor, vec![]); + + // proper queries work + let req = BankQuery::AllBalances { + address: owner.clone().into(), + }; + let raw = bank.query(&api, &store, &querier, &block, req).unwrap(); + let res: AllBalanceResponse = from_json(raw).unwrap(); + assert_eq!(res.amount, norm); + + let req = BankQuery::AllBalances { + address: rcpt.clone().into(), + }; + let raw = bank.query(&api, &store, &querier, &block, req).unwrap(); + let res: AllBalanceResponse = from_json(raw).unwrap(); + assert_eq!(res.amount, vec![]); + + let req = BankQuery::Balance { + address: owner.clone().into(), + denom: "eth".into(), + }; + let raw = bank.query(&api, &store, &querier, &block, req).unwrap(); + let res: BalanceResponse = from_json(raw).unwrap(); + assert_eq!(res.amount, coin(100, "eth")); + + let req = BankQuery::Balance { + address: owner.into(), + denom: "foobar".into(), + }; + let raw = bank.query(&api, &store, &querier, &block, req).unwrap(); + let res: BalanceResponse = from_json(raw).unwrap(); + assert_eq!(res.amount, coin(0, "foobar")); + + let req = BankQuery::Balance { + address: rcpt.clone().into(), + denom: "eth".into(), + }; + let raw = bank.query(&api, &store, &querier, &block, req).unwrap(); + let res: BalanceResponse = from_json(raw).unwrap(); + assert_eq!(res.amount, coin(0, "eth")); + + // Query total supply of a denom + let req = BankQuery::Supply { + denom: "eth".into(), + }; + let raw = bank.query(&api, &store, &querier, &block, req).unwrap(); + let res: SupplyResponse = from_json(raw).unwrap(); + assert_eq!(res.amount, coin(100, "eth")); + + // Mint tokens for recipient account + let msg = BankSudo::Mint { + to_address: rcpt.to_string(), + amount: norm.clone(), + }; + bank.sudo(&api, &mut store, &router, &block, msg).unwrap(); + + // Check that the recipient account has the expected balance + let req = BankQuery::AllBalances { + address: rcpt.into(), + }; + let raw = bank.query(&api, &store, &querier, &block, req).unwrap(); + let res: AllBalanceResponse = from_json(raw).unwrap(); + assert_eq!(res.amount, norm); + + // Check that the total supply of a denom is updated + let req = BankQuery::Supply { + denom: "eth".into(), + }; + let raw = bank.query(&api, &store, &querier, &block, req).unwrap(); + let res: SupplyResponse = from_json(raw).unwrap(); + assert_eq!(res.amount, coin(200, "eth")); + } + + #[test] + fn send_coins() { + let api = MockApi::default(); + let mut store = MockStorage::new(); + let block = mock_env().block; + let router = MockRouter::default(); + + let owner = api.addr_make("owner"); + let rcpt = api.addr_make("receiver"); + let init_funds = vec![coin(20, "btc"), coin(100, "eth")]; + let rcpt_funds = vec![coin(5, "btc")]; + + // set money + let bank = BankKeeper::new(); + bank.init_balance(&mut store, &owner, init_funds).unwrap(); + bank.init_balance(&mut store, &rcpt, rcpt_funds).unwrap(); + + // send both tokens + let to_send = vec![coin(30, "eth"), coin(5, "btc")]; + let msg = BankMsg::Send { + to_address: rcpt.clone().into(), + amount: to_send, + }; + bank.execute( + &api, + &mut store, + &router, + &block, + owner.clone(), + msg.clone(), + ) + .unwrap(); + let rich = query_balance(&bank, &api, &store, &owner); + assert_eq!(vec![coin(15, "btc"), coin(70, "eth")], rich); + let poor = query_balance(&bank, &api, &store, &rcpt); + assert_eq!(vec![coin(10, "btc"), coin(30, "eth")], poor); + + // can send from any account with funds + bank.execute(&api, &mut store, &router, &block, rcpt.clone(), msg) + .unwrap(); + + // cannot send too much + let msg = BankMsg::Send { + to_address: rcpt.into(), + amount: coins(20, "btc"), + }; + bank.execute(&api, &mut store, &router, &block, owner.clone(), msg) + .unwrap_err(); + + let rich = query_balance(&bank, &api, &store, &owner); + assert_eq!(vec![coin(15, "btc"), coin(70, "eth")], rich); + } + + #[test] + fn burn_coins() { + let api = MockApi::default(); + let mut store = MockStorage::new(); + let block = mock_env().block; + let router = MockRouter::default(); + + let owner = api.addr_make("owner"); + let rcpt = api.addr_make("recipient"); + let init_funds = vec![coin(20, "btc"), coin(100, "eth")]; + + // set money + let bank = BankKeeper::new(); + bank.init_balance(&mut store, &owner, init_funds).unwrap(); + + // burn both tokens + let to_burn = vec![coin(30, "eth"), coin(5, "btc")]; + let msg = BankMsg::Burn { amount: to_burn }; + bank.execute(&api, &mut store, &router, &block, owner.clone(), msg) + .unwrap(); + let rich = query_balance(&bank, &api, &store, &owner); + assert_eq!(vec![coin(15, "btc"), coin(70, "eth")], rich); + + // cannot burn too much + let msg = BankMsg::Burn { + amount: coins(20, "btc"), + }; + let err = bank + .execute(&api, &mut store, &router, &block, owner.clone(), msg) + .unwrap_err(); + assert!(matches!(err.downcast().unwrap(), StdError::Overflow { .. })); + + let rich = query_balance(&bank, &api, &store, &owner); + assert_eq!(vec![coin(15, "btc"), coin(70, "eth")], rich); + + // cannot burn from empty account + let msg = BankMsg::Burn { + amount: coins(1, "btc"), + }; + let err = bank + .execute(&api, &mut store, &router, &block, rcpt, msg) + .unwrap_err(); + assert!(matches!(err.downcast().unwrap(), StdError::Overflow { .. })); + } + + #[test] + #[cfg(feature = "cosmwasm_1_3")] + fn set_get_denom_metadata_should_work() { + let api = MockApi::default(); + let mut store = MockStorage::new(); + let block = mock_env().block; + let querier: MockQuerier = MockQuerier::new(&[]); + let bank = BankKeeper::new(); + // set metadata for Ether + let denom_eth_name = "eth".to_string(); + bank.set_denom_metadata( + &mut store, + denom_eth_name.clone(), + DenomMetadata { + name: denom_eth_name.clone(), + ..Default::default() + }, + ) + .unwrap(); + // query metadata + let req = BankQuery::DenomMetadata { + denom: denom_eth_name.clone(), + }; + let raw = bank.query(&api, &store, &querier, &block, req).unwrap(); + let res: DenomMetadataResponse = from_json(raw).unwrap(); + assert_eq!(res.metadata.name, denom_eth_name); + } + + #[test] + #[cfg(feature = "cosmwasm_1_3")] + fn set_get_all_denom_metadata_should_work() { + let api = MockApi::default(); + let mut store = MockStorage::new(); + let block = mock_env().block; + let querier: MockQuerier = MockQuerier::new(&[]); + let bank = BankKeeper::new(); + // set metadata for Bitcoin + let denom_btc_name = "btc".to_string(); + bank.set_denom_metadata( + &mut store, + denom_btc_name.clone(), + DenomMetadata { + name: denom_btc_name.clone(), + ..Default::default() + }, + ) + .unwrap(); + // set metadata for Ether + let denom_eth_name = "eth".to_string(); + bank.set_denom_metadata( + &mut store, + denom_eth_name.clone(), + DenomMetadata { + name: denom_eth_name.clone(), + ..Default::default() + }, + ) + .unwrap(); + // query metadata + let req = BankQuery::AllDenomMetadata { pagination: None }; + let raw = bank.query(&api, &store, &querier, &block, req).unwrap(); + let res: AllDenomMetadataResponse = from_json(raw).unwrap(); + assert_eq!(res.metadata[0].name, denom_btc_name); + assert_eq!(res.metadata[1].name, denom_eth_name); + } + + #[test] + fn fail_on_zero_values() { + let api = MockApi::default(); + let mut store = MockStorage::new(); + let block = mock_env().block; + let router = MockRouter::default(); + + let owner = api.addr_make("owner"); + let rcpt = api.addr_make("recipient"); + let init_funds = vec![coin(5000, "atom"), coin(100, "eth")]; + + // set money + let bank = BankKeeper::new(); + bank.init_balance(&mut store, &owner, init_funds).unwrap(); + + // can send normal amounts + let msg = BankMsg::Send { + to_address: rcpt.to_string(), + amount: coins(100, "atom"), + }; + bank.execute(&api, &mut store, &router, &block, owner.clone(), msg) + .unwrap(); + + // fails send on no coins + let msg = BankMsg::Send { + to_address: rcpt.to_string(), + amount: vec![], + }; + bank.execute(&api, &mut store, &router, &block, owner.clone(), msg) + .unwrap_err(); + + // fails send on 0 coins + let msg = BankMsg::Send { + to_address: rcpt.to_string(), + amount: coins(0, "atom"), + }; + bank.execute(&api, &mut store, &router, &block, owner.clone(), msg) + .unwrap_err(); + + // fails burn on no coins + let msg = BankMsg::Burn { amount: vec![] }; + bank.execute(&api, &mut store, &router, &block, owner.clone(), msg) + .unwrap_err(); + + // fails burn on 0 coins + let msg = BankMsg::Burn { + amount: coins(0, "atom"), + }; + bank.execute(&api, &mut store, &router, &block, owner, msg) + .unwrap_err(); + + // can mint via sudo + let msg = BankSudo::Mint { + to_address: rcpt.to_string(), + amount: coins(4321, "atom"), + }; + bank.sudo(&api, &mut store, &router, &block, msg).unwrap(); + + // mint fails with 0 tokens + let msg = BankSudo::Mint { + to_address: rcpt.to_string(), + amount: coins(0, "atom"), + }; + bank.sudo(&api, &mut store, &router, &block, msg) + .unwrap_err(); + + // mint fails with no tokens + let msg = BankSudo::Mint { + to_address: rcpt.to_string(), + amount: vec![], + }; + bank.sudo(&api, &mut store, &router, &block, msg) + .unwrap_err(); + } +} diff --git a/src/contracts.rs b/src/contracts.rs index e6d218ff..ef364be7 100644 --- a/src/contracts.rs +++ b/src/contracts.rs @@ -1,80 +1,49 @@ -use std::{ - error::Error, - fmt::{self, Debug, Display}, -}; - -use schemars::JsonSchema; +//! # Implementation of the contract trait and contract wrapper +use crate::error::{anyhow, bail, AnyError, AnyResult}; +use crate::wasm_emulation::query::mock_querier::ForkState; +use crate::wasm_emulation::query::MockQuerier; +use crate::wasm_emulation::storage::dual_std_storage::DualStorage; +use crate::wasm_emulation::storage::storage_wrappers::{ReadonlyStorageWrapper, StorageWrapper}; use cosmwasm_std::{ - from_json, Binary, Checksum, CustomMsg, CustomQuery, Deps, DepsMut, Empty, Env, MessageInfo, QuerierWrapper, Reply, Response, StdError + from_json, Binary, Checksum, CosmosMsg, CustomMsg, CustomQuery, Deps, DepsMut, Empty, Env, + MessageInfo, QuerierWrapper, Reply, Response, StdError, SubMsg, }; - -use anyhow::Result as AnyResult; use serde::de::DeserializeOwned; +use std::fmt::{Debug, Display}; +use std::ops::Deref; -use crate::wasm_emulation::{ - query::{mock_querier::ForkState, MockQuerier}, - storage::{ - dual_std_storage::DualStorage, - storage_wrappers::{ReadonlyStorageWrapper, StorageWrapper}, - }, -}; -use anyhow::{anyhow, bail}; -/// Interface to call into a [Contract]. -pub trait Contract +/// This trait serves as a primary interface for interacting with contracts. +#[rustfmt::skip] +pub trait Contract where - T: CustomMsg + DeserializeOwned + Clone + std::fmt::Debug + PartialEq + JsonSchema, + C: CustomMsg, Q: CustomQuery + DeserializeOwned, { - fn execute( - &self, - deps: DepsMut, - env: Env, - info: MessageInfo, - msg: Vec, - fork_state: ForkState, - ) -> AnyResult>; + /// Evaluates contract's `execute` entry-point. + fn execute(&self, deps: DepsMut, env: Env, info: MessageInfo, msg: Vec, + fork_state: ForkState,) -> AnyResult>; - fn instantiate( - &self, - deps: DepsMut, - env: Env, - info: MessageInfo, - msg: Vec, - fork_state: ForkState, - ) -> AnyResult>; + /// Evaluates contract's `instantiate` entry-point. + fn instantiate(&self, deps: DepsMut, env: Env, info: MessageInfo, msg: Vec, + fork_state: ForkState,) -> AnyResult>; - fn query( - &self, - deps: Deps, - env: Env, - msg: Vec, - fork_state: ForkState, - ) -> AnyResult; + /// Evaluates contract's `query` entry-point. + fn query(&self, deps: Deps, env: Env, msg: Vec, + fork_state: ForkState,) -> AnyResult; - fn sudo( - &self, - deps: DepsMut, - env: Env, - msg: Vec, - fork_state: ForkState, - ) -> AnyResult>; + /// Evaluates contract's `sudo` entry-point. + fn sudo(&self, deps: DepsMut, env: Env, msg: Vec, + fork_state: ForkState,) -> AnyResult>; - fn reply( - &self, - deps: DepsMut, - env: Env, - msg: Reply, - fork_state: ForkState, - ) -> AnyResult>; + /// Evaluates contract's `reply` entry-point. + fn reply(&self, deps: DepsMut, env: Env, msg: Reply, + fork_state: ForkState,) -> AnyResult>; + + /// Evaluates contract's `migrate` entry-point. + fn migrate(&self, deps: DepsMut, env: Env, msg: Vec, + fork_state: ForkState,) -> AnyResult>; - fn migrate( - &self, - deps: DepsMut, - env: Env, - msg: Vec, - fork_state: ForkState, - ) -> AnyResult>; /// Returns the provided checksum of the contract's Wasm blob. fn checksum(&self) -> Option { @@ -82,20 +51,92 @@ where } } -type ContractFn = - fn(deps: DepsMut, env: Env, info: MessageInfo, msg: T) -> Result, E>; -type PermissionedFn = fn(deps: DepsMut, env: Env, msg: T) -> Result, E>; -type ReplyFn = fn(deps: DepsMut, env: Env, msg: Reply) -> Result, E>; -type QueryFn = fn(deps: Deps, env: Env, msg: T) -> Result; - -type ContractClosure = fn(DepsMut, Env, MessageInfo, T) -> Result, E>; -type PermissionedClosure = fn(DepsMut, Env, T) -> Result, E>; -type ReplyClosure = fn(DepsMut, Env, Reply) -> Result, E>; -type QueryClosure = fn(Deps, Env, T) -> Result; +#[rustfmt::skip] +mod closures { + use super::*; + + // function types + pub type ContractFn = fn(deps: DepsMut, env: Env, info: MessageInfo, msg: T) -> Result, E>; + pub type PermissionedFn = fn(deps: DepsMut, env: Env, msg: T) -> Result, E>; + pub type ReplyFn = fn(deps: DepsMut, env: Env, msg: Reply) -> Result, E>; + pub type QueryFn = fn(deps: Deps, env: Env, msg: T) -> Result; + + // closure types + pub type ContractClosure = Box, Env, MessageInfo, T) -> Result, E>>; + pub type PermissionedClosure = Box, Env, T) -> Result, E>>; + pub type ReplyClosure = Box, Env, Reply) -> Result, E>>; + pub type QueryClosure = Box, Env, T) -> Result>; +} -#[derive(Clone, Copy)] -/// Wraps the exported functions from a contract and provides the normalized format -/// Place T4 and E4 at the end, as we just want default placeholders for most contracts that don't have sudo +use closures::*; + +/// This structure wraps the [Contract] trait implementor +/// and provides generic access to the contract's entry-points. +/// +/// List of generic types used in [ContractWrapper]: +/// - **T1** type of message passed to [execute] entry-point. +/// - **T2** type of message passed to [instantiate] entry-point. +/// - **T3** type of message passed to [query] entry-point. +/// - **T4** type of message passed to [sudo] entry-point. +/// - instead of **~~T5~~**, always the `Reply` type is used in [reply] entry-point. +/// - **T6** type of message passed to [migrate] entry-point. +/// - **E1** type of error returned from [execute] entry-point. +/// - **E2** type of error returned from [instantiate] entry-point. +/// - **E3** type of error returned from [query] entry-point. +/// - **E4** type of error returned from [sudo] entry-point. +/// - **E5** type of error returned from [reply] entry-point. +/// - **E6** type of error returned from [migrate] entry-point. +/// - **C** type of custom message returned from all entry-points except [query]. +/// - **Q** type of custom query in `Querier` passed as 'Deps' or 'DepsMut' to all entry-points. +/// +/// The following table summarizes the purpose of all generic types used in [ContractWrapper]. +/// ```text +/// ┌─────────────┬────────────────┬─────────────────────┬─────────┬─────────┬───────┬───────┐ +/// │ Contract │ Contract │ │ │ │ │ │ +/// │ entry-point │ wrapper │ Closure type │ Message │ Message │ Error │ Query │ +/// │ │ member │ │ IN │ OUT │ OUT │ │ +/// ╞═════════════╪════════════════╪═════════════════════╪═════════╪═════════╪═══════╪═══════╡ +/// │ (1) │ │ │ │ │ │ │ +/// ╞═════════════╪════════════════╪═════════════════════╪═════════╪═════════╪═══════╪═══════╡ +/// │ execute │ execute_fn │ ContractClosure │ T1 │ C │ E1 │ Q │ +/// ├─────────────┼────────────────┼─────────────────────┼─────────┼─────────┼───────┼───────┤ +/// │ instantiate │ instantiate_fn │ ContractClosure │ T2 │ C │ E2 │ Q │ +/// ├─────────────┼────────────────┼─────────────────────┼─────────┼─────────┼───────┼───────┤ +/// │ query │ query_fn │ QueryClosure │ T3 │ Binary │ E3 │ Q │ +/// ├─────────────┼────────────────┼─────────────────────┼─────────┼─────────┼───────┼───────┤ +/// │ sudo │ sudo_fn │ PermissionedClosure │ T4 │ C │ E4 │ Q │ +/// ├─────────────┼────────────────┼─────────────────────┼─────────┼─────────┼───────┼───────┤ +/// │ reply │ reply_fn │ ReplyClosure │ Reply │ C │ E5 │ Q │ +/// ├─────────────┼────────────────┼─────────────────────┼─────────┼─────────┼───────┼───────┤ +/// │ migrate │ migrate_fn │ PermissionedClosure │ T6 │ C │ E6 │ Q │ +/// └─────────────┴────────────────┴─────────────────────┴─────────┴─────────┴───────┴───────┘ +/// ``` +/// The general schema depicting which generic type is used in entry points is shown below. +/// Entry point, when called, is provided minimum two arguments: custom query of type **Q** +/// (inside `Deps` or `DepsMut`) and input message of type **T1**, **T2**, **T3**, **T4**, +/// **Reply** or **T6**. As a result, entry point returns custom output message of type +/// Response<**C**> or **Binary** and an error of type **E1**, **E2**, **E3**, **E4**, **E5** +/// or **E6**. +/// +/// ```text +/// entry_point(query, .., message_in) -> Result +/// ┬ ┬ ┬ ┬ +/// Q >──┘ │ │ └──> E1,E2,E3,E4,E5,E6 +/// T1,T2,T3,T4,Reply,T6 >────┘ └─────────────> C,Binary +/// ``` +/// Generic type **C** defines a custom message that is specific for the **whole blockchain**. +/// Similarly, the generic type **Q** defines a custom query that is also specific +/// to the **whole blockchain**. Other generic types are specific to the implemented contract. +/// So all smart contracts used in the same blockchain will have the same types for **C** and **Q**, +/// but each contract may use different type for other generic types. +/// It means that e.g. **T1** in smart contract `A` may differ from **T1** in smart contract `B`. +/// +/// [execute]: Contract::execute +/// [instantiate]: Contract::instantiate +/// [query]: Contract::query +/// [sudo]: Contract::sudo +/// [reply]: Contract::reply +/// [migrate]: Contract::migrate pub struct ContractWrapper< T1, T2, @@ -111,19 +152,19 @@ pub struct ContractWrapper< T6 = Empty, E6 = StdError, > where - T1: DeserializeOwned + Debug, - T2: DeserializeOwned, - T3: DeserializeOwned, - T4: DeserializeOwned, - T6: DeserializeOwned, - E1: Display + Debug + Send + Sync + 'static, - E2: Display + Debug + Send + Sync + 'static, - E3: Display + Debug + Send + Sync + 'static, - E4: Display + Debug + Send + Sync + 'static, - E5: Display + Debug + Send + Sync + 'static, - E6: Display + Debug + Send + Sync + 'static, - C: Clone + fmt::Debug + PartialEq + JsonSchema, - Q: CustomQuery + DeserializeOwned + 'static, + T1: DeserializeOwned, // Type of message passed to `execute` entry-point. + T2: DeserializeOwned, // Type of message passed to `instantiate` entry-point. + T3: DeserializeOwned, // Type of message passed to `query` entry-point. + T4: DeserializeOwned, // Type of message passed to `sudo` entry-point. + T6: DeserializeOwned, // Type of message passed to `migrate` entry-point. + E1: Display + Debug + Send + Sync, // Type of error returned from `execute` entry-point. + E2: Display + Debug + Send + Sync, // Type of error returned from `instantiate` entry-point. + E3: Display + Debug + Send + Sync, // Type of error returned from `query` entry-point. + E4: Display + Debug + Send + Sync, // Type of error returned from `sudo` entry-point. + E5: Display + Debug + Send + Sync, // Type of error returned from `reply` entry-point. + E6: Display + Debug + Send + Sync, // Type of error returned from `migrate` entry-point. + C: CustomMsg, // Type of custom message returned from all entry-points except `query`. + Q: CustomQuery + DeserializeOwned, // Type of custom query in querier passed as deps/deps_mut to all entry-points. { execute_fn: ContractClosure, instantiate_fn: ContractClosure, @@ -136,24 +177,25 @@ pub struct ContractWrapper< impl ContractWrapper where - T1: DeserializeOwned + Debug + 'static, - T2: DeserializeOwned + 'static, - T3: DeserializeOwned + 'static, - E1: Display + Debug + Send + Sync + 'static, - E2: Display + Debug + Send + Sync + 'static, - E3: Display + Debug + Send + Sync + 'static, - C: Clone + fmt::Debug + PartialEq + JsonSchema + 'static, - Q: CustomQuery + DeserializeOwned + 'static, + T1: DeserializeOwned + 'static, // Type of message passed to `execute` entry-point. + T2: DeserializeOwned + 'static, // Type of message passed to `instantiate` entry-point. + T3: DeserializeOwned + 'static, // Type of message passed to `query` entry-point. + E1: Display + Debug + Send + Sync + 'static, // Type of error returned from `execute` entry-point. + E2: Display + Debug + Send + Sync + 'static, // Type of error returned from `instantiate` entry-point. + E3: Display + Debug + Send + Sync + 'static, // Type of error returned from `query` entry-point. + C: CustomMsg + 'static, // Type of custom message returned from all entry-points except `query`. + Q: CustomQuery + DeserializeOwned + 'static, // Type of custom query in querier passed as deps/deps_mut to all entry-points. { + /// Creates a new contract wrapper with default settings. pub fn new( execute_fn: ContractFn, instantiate_fn: ContractFn, query_fn: QueryFn, ) -> Self { Self { - execute_fn, - instantiate_fn, - query_fn, + execute_fn: Box::new(execute_fn), + instantiate_fn: Box::new(instantiate_fn), + query_fn: Box::new(query_fn), sudo_fn: None, reply_fn: None, migrate_fn: None, @@ -162,23 +204,25 @@ where } } +#[allow(clippy::type_complexity)] impl ContractWrapper where - T1: DeserializeOwned + Debug + 'static, - T2: DeserializeOwned + 'static, - T3: DeserializeOwned + 'static, - T4: DeserializeOwned + 'static, - T6: DeserializeOwned + 'static, - E1: Display + Debug + Send + Sync + 'static, - E2: Display + Debug + Send + Sync + 'static, - E3: Display + Debug + Send + Sync + 'static, - E4: Display + Debug + Send + Sync + 'static, - E5: Display + Debug + Send + Sync + 'static, - E6: Display + Debug + Send + Sync + 'static, - C: Clone + fmt::Debug + PartialEq + JsonSchema + 'static, - Q: CustomQuery + DeserializeOwned + 'static, + T1: DeserializeOwned, // Type of message passed to `execute` entry-point. + T2: DeserializeOwned, // Type of message passed to `instantiate` entry-point. + T3: DeserializeOwned, // Type of message passed to `query` entry-point. + T4: DeserializeOwned, // Type of message passed to `sudo` entry-point. + T6: DeserializeOwned, // Type of message passed to `migrate` entry-point. + E1: Display + Debug + Send + Sync, // Type of error returned from `execute` entry-point. + E2: Display + Debug + Send + Sync, // Type of error returned from `instantiate` entry-point. + E3: Display + Debug + Send + Sync, // Type of error returned from `query` entry-point. + E4: Display + Debug + Send + Sync, // Type of error returned from `sudo` entry-point. + E5: Display + Debug + Send + Sync, // Type of error returned from `reply` entry-point. + E6: Display + Debug + Send + Sync, // Type of error returned from `migrate` entry-point. + C: CustomMsg + 'static, // Type of custom message returned from all entry-points except `query`. + Q: CustomQuery + DeserializeOwned + 'static, // Type of custom query in querier passed as deps/deps_mut to all entry-points. { + /// Populates [ContractWrapper] with contract's `sudo` entry-point and custom message type. pub fn with_sudo( self, sudo_fn: PermissionedFn, @@ -191,13 +235,14 @@ where execute_fn: self.execute_fn, instantiate_fn: self.instantiate_fn, query_fn: self.query_fn, - sudo_fn: Some(sudo_fn), + sudo_fn: Some(Box::new(sudo_fn)), reply_fn: self.reply_fn, migrate_fn: self.migrate_fn, checksum: None, } } + /// Populates [ContractWrapper] with contract's `reply` entry-point and custom message type. pub fn with_reply( self, reply_fn: ReplyFn, @@ -210,12 +255,13 @@ where instantiate_fn: self.instantiate_fn, query_fn: self.query_fn, sudo_fn: self.sudo_fn, - reply_fn: Some(reply_fn), + reply_fn: Some(Box::new(reply_fn)), migrate_fn: self.migrate_fn, checksum: None, } } + /// Populates [ContractWrapper] with contract's `migrate` entry-point and custom message type. pub fn with_migrate( self, migrate_fn: PermissionedFn, @@ -230,7 +276,7 @@ where query_fn: self.query_fn, sudo_fn: self.sudo_fn, reply_fn: self.reply_fn, - migrate_fn: Some(migrate_fn), + migrate_fn: Some(Box::new(migrate_fn)), checksum: None, } } @@ -244,20 +290,23 @@ where impl Contract for ContractWrapper where - T1: DeserializeOwned + Debug + Clone, - T2: DeserializeOwned + Debug + Clone, - T3: DeserializeOwned + Debug + Clone, - T4: DeserializeOwned, - T6: DeserializeOwned, - E1: Display + Debug + Send + Sync + Error + 'static, - E2: Display + Debug + Send + Sync + Error + 'static, - E3: Display + Debug + Send + Sync + Error + 'static, - E4: Display + Debug + Send + Sync + 'static, - E5: Display + Debug + Send + Sync + 'static, - E6: Display + Debug + Send + Sync + 'static, - C: CustomMsg + DeserializeOwned + Clone + fmt::Debug + PartialEq + JsonSchema, - Q: CustomQuery + DeserializeOwned, + T1: DeserializeOwned, // Type of message passed to `execute` entry-point. + T2: DeserializeOwned, // Type of message passed to `instantiate` entry-point. + T3: DeserializeOwned, // Type of message passed to `query` entry-point. + T4: DeserializeOwned, // Type of message passed to `sudo` entry-point. + T6: DeserializeOwned, // Type of message passed to `migrate` entry-point. + E1: Display + Debug + Send + Sync + 'static, // Type of error returned from `execute` entry-point. + E2: Display + Debug + Send + Sync + 'static, // Type of error returned from `instantiate` entry-point. + E3: Display + Debug + Send + Sync + 'static, // Type of error returned from `query` entry-point. + E4: Display + Debug + Send + Sync + 'static, // Type of error returned from `sudo` entry-point. + E5: Display + Debug + Send + Sync + 'static, // Type of error returned from `reply` entry-point. + E6: Display + Debug + Send + Sync + 'static, // Type of error returned from `migrate` entry-point. + C: CustomMsg + DeserializeOwned, // Type of custom message returned from all entry-points except `query`. + Q: CustomQuery + DeserializeOwned, // Type of custom query in querier passed as deps/deps_mut to all entry-points. { + /// Calls [execute] on wrapped [Contract] trait implementor. + /// + /// [execute]: Contract::execute fn execute( &self, deps: DepsMut, @@ -279,9 +328,12 @@ where }; let msg: T1 = from_json(msg)?; - (self.execute_fn)(deps, env, info, msg).map_err(|err| anyhow!(err)) + (self.execute_fn)(deps, env, info, msg).map_err(|err: E1| anyhow!(err)) } + /// Calls [instantiate] on wrapped [Contract] trait implementor. + /// + /// [instantiate]: Contract::instantiate fn instantiate( &self, deps: DepsMut, @@ -302,9 +354,12 @@ where querier: QuerierWrapper::new(&querier), }; let msg: T2 = from_json(msg)?; - (self.instantiate_fn)(deps, env, info, msg).map_err(|err| anyhow!(err)) + (self.instantiate_fn)(deps, env, info, msg).map_err(|err: E2| anyhow!(err)) } + /// Calls [query] on wrapped [Contract] trait implementor. + /// + /// [query]: Contract::query fn query( &self, deps: Deps, @@ -324,10 +379,13 @@ where querier: QuerierWrapper::new(&querier), }; let msg: T3 = from_json(msg)?; - (self.query_fn)(deps, env, msg).map_err(|err| anyhow!(err)) + (self.query_fn)(deps, env, msg).map_err(|err: E3| anyhow!(err)) } - // this returns an error if the contract doesn't implement sudo + /// Calls [sudo] on wrapped [Contract] trait implementor. + /// Returns an error when the contract does not implement [sudo]. + /// + /// [sudo]: Contract::sudo fn sudo( &self, deps: DepsMut, @@ -348,12 +406,15 @@ where }; let msg = from_json(msg)?; match &self.sudo_fn { - Some(sudo) => sudo(deps, env, msg).map_err(|err| anyhow!(err)), - None => bail!("sudo not implemented for contract"), + Some(sudo) => sudo(deps, env, msg).map_err(|err: E4| anyhow!(err)), + None => bail!("sudo is not implemented for contract"), } } - // this returns an error if the contract doesn't implement reply + /// Calls [reply] on wrapped [Contract] trait implementor. + /// Returns an error when the contract does not implement [reply]. + /// + /// [reply]: Contract::reply fn reply( &self, deps: DepsMut, @@ -361,6 +422,7 @@ where reply_data: Reply, fork_state: ForkState, ) -> AnyResult> { + let msg: Reply = reply_data; let querier = MockQuerier::new(fork_state.clone()); let mut storage = DualStorage::new( fork_state.remote, @@ -373,12 +435,15 @@ where querier: QuerierWrapper::new(&querier), }; match &self.reply_fn { - Some(reply) => reply(deps, env, reply_data).map_err(|err| anyhow!(err)), - None => bail!("reply not implemented for contract"), + Some(reply) => reply(deps, env, msg).map_err(|err: E5| anyhow!(err)), + None => bail!("reply is not implemented for contract"), } } - // this returns an error if the contract doesn't implement migrate + /// Calls [migrate] on wrapped [Contract] trait implementor. + /// Returns an error when the contract does not implement [migrate]. + /// + /// [migrate]: Contract::migrate fn migrate( &self, deps: DepsMut, @@ -399,8 +464,8 @@ where }; let msg = from_json(msg)?; match &self.migrate_fn { - Some(migrate) => migrate(deps, env, msg).map_err(|err| anyhow!(err)), - None => bail!("migrate not implemented for contract"), + Some(migrate) => migrate(deps, env, msg).map_err(|err: E6| anyhow!(err)), + None => bail!("migrate is not implemented for contract"), } } diff --git a/src/custom_handler.rs b/src/custom_handler.rs index cb634b59..1ab9dbeb 100644 --- a/src/custom_handler.rs +++ b/src/custom_handler.rs @@ -1,3 +1,5 @@ +//! # Custom message and query handler + use crate::app::CosmosRouter; use crate::error::{bail, AnyResult}; use crate::{AppResponse, Module}; @@ -7,40 +9,46 @@ use std::cell::{Ref, RefCell}; use std::ops::Deref; use std::rc::Rc; -/// Internal state of `CachingCustomHandler` wrapping internal mutability so it is not exposed to -/// user. Those have to be shared internal state, as after mock is passed to app it is not -/// possible to access mock internals which are not exposed by API. +/// A cache for messages and queries processes by the custom module. #[derive(Derivative)] #[derivative(Default(bound = "", new = "true"), Clone(bound = ""))] pub struct CachingCustomHandlerState { + /// Cache for processes custom messages. execs: Rc>>, + /// Cache for processed custom queries. queries: Rc>>, } impl CachingCustomHandlerState { + /// Returns a slice of processed custom messages. pub fn execs(&self) -> impl Deref + '_ { Ref::map(self.execs.borrow(), Vec::as_slice) } + /// Returns a slice of processed custom queries. pub fn queries(&self) -> impl Deref + '_ { Ref::map(self.queries.borrow(), Vec::as_slice) } + /// Clears the cache. pub fn reset(&self) { self.execs.borrow_mut().clear(); self.queries.borrow_mut().clear(); } } -/// Custom handler storing all the messages it received, so they can be later verified. -/// State is thin shared state, so it can be hold after mock is passed to App to read state. +/// Custom handler that stores all received messages and queries. +/// +/// State is thin shared state, so it can be held after mock is passed to [App](crate::App) to read state. #[derive(Clone, Derivative)] #[derivative(Default(bound = "", new = "true"))] pub struct CachingCustomHandler { + /// Cached state. state: CachingCustomHandlerState, } impl CachingCustomHandler { + /// Returns the cached state. pub fn state(&self) -> CachingCustomHandlerState { self.state.clone() } @@ -51,8 +59,7 @@ impl Module for CachingCustomHandler { type QueryT = Query; type SudoT = Empty; - // TODO: how to assert - // where ExecC: Exec, QueryC: Query + // TODO: how to assert like `where ExecC: Exec, QueryC: Query` fn execute( &self, _api: &dyn Api, @@ -66,17 +73,6 @@ impl Module for CachingCustomHandler { Ok(AppResponse::default()) } - fn sudo( - &self, - _api: &dyn Api, - _storage: &mut dyn Storage, - _router: &dyn CosmosRouter, - _block: &BlockInfo, - msg: Self::SudoT, - ) -> AnyResult { - bail!("Unexpected sudo msg {:?}", msg) - } - fn query( &self, _api: &dyn Api, @@ -88,4 +84,15 @@ impl Module for CachingCustomHandler { self.state.queries.borrow_mut().push(request); Ok(Binary::default()) } + + fn sudo( + &self, + _api: &dyn Api, + _storage: &mut dyn Storage, + _router: &dyn CosmosRouter, + _block: &BlockInfo, + msg: Self::SudoT, + ) -> AnyResult { + bail!("Unexpected custom sudo message {:?}", msg) + } } diff --git a/src/error.rs b/src/error.rs index 289a7949..b6c26c8a 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,33 +1,54 @@ +//! # Error definitions + pub use anyhow::{anyhow, bail, Context as AnyContext, Error as AnyError, Result as AnyResult}; use cosmwasm_std::{WasmMsg, WasmQuery}; use thiserror::Error; +/// An enumeration of errors reported across the **CosmWasm MultiTest** library. #[derive(Debug, Error, PartialEq, Eq)] pub enum Error { - #[error("Empty attribute key. Value: {value}")] - EmptyAttributeKey { value: String }, + /// Error variant for reporting an empty attribute key. + #[error("Empty attribute key. Value: {0}")] + EmptyAttributeKey(String), - #[error("Empty attribute value. Key: {key}")] - EmptyAttributeValue { key: String }, + /// Error variant for reporting an empty attribute value. + #[deprecated(note = "This error is not reported anymore. Will be removed in next release.")] + #[error("Empty attribute value. Key: {0}")] + EmptyAttributeValue(String), + /// Error variant for reporting a usage of reserved key prefix. #[error("Attribute key starts with reserved prefix _: {0}")] ReservedAttributeKey(String), + /// Error variant for reporting too short event types. #[error("Event type too short: {0}")] EventTypeTooShort(String), + /// Error variant for reporting that unsupported wasm query was encountered during processing. #[error("Unsupported wasm query: {0:?}")] UnsupportedWasmQuery(WasmQuery), + /// Error variant for reporting that unsupported wasm message was encountered during processing. #[error("Unsupported wasm message: {0:?}")] UnsupportedWasmMsg(WasmMsg), + /// Error variant for reporting invalid contract code. #[error("code id: invalid")] InvalidCodeId, + /// Error variant for reporting unregistered contract code. #[error("code id {0}: no such code")] UnregisteredCodeId(u64), + /// Error variant for reporting duplicated contract code identifier. + #[error("duplicated code id {0}")] + DuplicatedCodeId(u64), + + /// Error variant for reporting a situation when no more contract code identifiers are available. + #[error("no more code identifiers available")] + NoMoreCodeIdAvailable, + + /// Error variant for reporting duplicated contract addresses. #[error("Contract with this address already exists: {0}")] DuplicatedContractAddress(String), @@ -36,24 +57,59 @@ pub enum Error { } impl Error { + /// Creates an instance of the [Error](Self) for empty attribute key. pub fn empty_attribute_key(value: impl Into) -> Self { - Self::EmptyAttributeKey { - value: value.into(), - } + Self::EmptyAttributeKey(value.into()) } + #[deprecated(note = "This error is not reported anymore. Will be removed in next release.")] + /// Creates an instance of the [Error](Self) for empty attribute value. pub fn empty_attribute_value(key: impl Into) -> Self { - Self::EmptyAttributeValue { key: key.into() } + #[allow(deprecated)] + Self::EmptyAttributeValue(key.into()) } + /// Creates an instance of the [Error](Self) when reserved attribute key was used. pub fn reserved_attribute_key(key: impl Into) -> Self { Self::ReservedAttributeKey(key.into()) } + /// Creates an instance of the [Error](Self) for too short event types. pub fn event_type_too_short(ty: impl Into) -> Self { Self::EventTypeTooShort(ty.into()) } + /// Creates an instance of the [Error](Self) for unsupported wasm queries. + pub fn unsupported_wasm_query(query: WasmQuery) -> Self { + Self::UnsupportedWasmQuery(query) + } + + /// Creates an instance of the [Error](Self) for unsupported wasm messages. + pub fn unsupported_wasm_message(msg: WasmMsg) -> Self { + Self::UnsupportedWasmMsg(msg) + } + + /// Creates an instance of the [Error](Self) for invalid contract code identifier. + pub fn invalid_code_id() -> Self { + Self::InvalidCodeId + } + + /// Creates an instance of the [Error](Self) for unregistered contract code identifier. + pub fn unregistered_code_id(code_id: u64) -> Self { + Self::UnregisteredCodeId(code_id) + } + + /// Creates an instance of the [Error](Self) for duplicated contract code identifier. + pub fn duplicated_code_id(code_id: u64) -> Self { + Self::DuplicatedCodeId(code_id) + } + + /// Creates an instance of the [Error](Self) for exhausted contract code identifiers. + pub fn no_more_code_id_available() -> Self { + Self::NoMoreCodeIdAvailable + } + + /// Creates an instance of the [Error](Self) for duplicated contract addresses. pub fn duplicated_contract_address(address: impl Into) -> Self { Self::DuplicatedContractAddress(address.into()) } diff --git a/src/executor.rs b/src/executor.rs index 492be9bb..ed2a5fad 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -1,30 +1,35 @@ use crate::error::AnyResult; use cosmwasm_std::{ - to_json_binary, Addr, Attribute, BankMsg, Binary, Coin, CosmosMsg, Event, SubMsgResponse, - WasmMsg, + to_json_binary, Addr, Attribute, BankMsg, Binary, Coin, CosmosMsg, CustomMsg, Event, + SubMsgResponse, WasmMsg, }; use cw_utils::{parse_execute_response_data, parse_instantiate_response_data}; -use schemars::JsonSchema; use serde::Serialize; use std::fmt::Debug; +/// A subset of data returned as a response of a contract entry point, +/// such as `instantiate`, `execute` or `migrate`. #[derive(Default, Clone, Debug)] pub struct AppResponse { + /// Response events. pub events: Vec, + /// Response data. pub data: Option, } impl AppResponse { - // Return all custom attributes returned by the contract in the `idx` event. - // We assert the type is wasm, and skip the contract_address attribute. + /// Returns all custom attributes returned by the contract in the `idx` event. + /// + /// We assert the type is wasm, and skip the contract_address attribute. #[track_caller] pub fn custom_attrs(&self, idx: usize) -> &[Attribute] { assert_eq!(self.events[idx].ty.as_str(), "wasm"); &self.events[idx].attributes[1..] } - /// Check if there is an Event that is a super-set of this. - /// It has the same type, and all compare.attributes are included in it as well. + /// Checks if there is an Event that is a super-set of this. + /// + /// It has the same type, and all compared attributes are included in it as well. /// You don't need to specify them all. pub fn has_event(&self, expected: &Event) -> bool { self.events.iter().any(|ev| { @@ -36,7 +41,7 @@ impl AppResponse { }) } - /// Like has_event but panics if no match + /// Like [has_event](Self::has_event) but panics if there is no match. #[track_caller] pub fn assert_event(&self, expected: &Event) { assert!( @@ -48,7 +53,7 @@ impl AppResponse { } } -/// They have the same shape, SubMsgExecutionResponse is what is returned in reply. +/// They have the same shape, SubMsgResponse is what is returned in reply. /// This is just to make some test cases easier. impl From for AppResponse { fn from(reply: SubMsgResponse) -> Self { @@ -59,14 +64,19 @@ impl From for AppResponse { } } } - +/// A trait defining a default behavior of the message executor. +/// +/// Defines the interface for executing transactions and contract interactions. +/// It is a central component in the testing framework, managing the operational +/// flow and ensuring that contract _calls_ are processed correctly. pub trait Executor where - C: Clone + Debug + PartialEq + JsonSchema + 'static, + C: CustomMsg + 'static, { - /// Runs arbitrary CosmosMsg. - /// This will create a cache before the execution, so no state changes are persisted if this - /// returns an error, but all are persisted on success. + /// Processes (executes) an arbitrary `CosmosMsg`. + /// This will create a cache before the execution, + /// so no state changes are persisted if this returns an error, + /// but all are persisted on success. fn execute(&mut self, sender: Addr, msg: CosmosMsg) -> AnyResult; /// Create a contract and get the new address. @@ -128,8 +138,9 @@ where } /// Execute a contract and process all returned messages. - /// This is just a helper around execute(), - /// but we parse out the data field to that what is returned by the contract (not the protobuf wrapper) + /// This is just a helper function around [execute()](Self::execute) + /// with `WasmMsg::Execute` message, but in this case we parse out the data field + /// to that what is returned by the contract (not the protobuf wrapper). fn execute_contract( &mut self, sender: Addr, @@ -150,8 +161,10 @@ where Ok(res) } - /// Migrate a contract. Sender must be registered admin. - /// This is just a helper around execute() + /// Migrates a contract. + /// Sender must be registered admin. + /// This is just a helper function around [execute()](Self::execute) + /// with `WasmMsg::Migrate` message. fn migrate_contract( &mut self, sender: Addr, @@ -168,6 +181,9 @@ where self.execute(sender, msg.into()) } + /// Sends tokens to specified recipient. + /// This is just a helper function around [execute()](Self::execute) + /// with `BankMsg::Send` message. fn send_tokens( &mut self, sender: Addr, diff --git a/src/gov.rs b/src/gov.rs index 286333a7..f2c01940 100644 --- a/src/gov.rs +++ b/src/gov.rs @@ -1,12 +1,17 @@ use crate::{AcceptingModule, FailingModule, Module}; use cosmwasm_std::{Empty, GovMsg}; - +/// Handles governance-related operations within the test environment. +/// This trait is essential for testing contracts that interact with governance mechanisms, +/// simulating proposals, voting, and other governance activities. pub trait Gov: Module {} - +/// A type alias for a module that accepts governance-related interactions. +/// It's used in scenarios where you need to test how your contract interacts +/// with governance processes and messages. pub type GovAcceptingModule = AcceptingModule; impl Gov for GovAcceptingModule {} - +/// This type alias represents a module designed to fail in response to governance operations. +/// It's useful for testing how contracts behave when governance actions do not proceed as expected. pub type GovFailingModule = FailingModule; impl Gov for GovFailingModule {} diff --git a/src/ibc.rs b/src/ibc.rs index 97e5b026..e8442c2b 100644 --- a/src/ibc.rs +++ b/src/ibc.rs @@ -1,12 +1,18 @@ use crate::{AcceptingModule, FailingModule, Module}; use cosmwasm_std::{Empty, IbcMsg, IbcQuery}; - +///Manages Inter-Blockchain Communication (IBC) functionalities. +///This trait is critical for testing contracts that involve cross-chain interactions, +///reflecting the interconnected nature of the Cosmos ecosystem. pub trait Ibc: Module {} - +/// Ideal for testing contracts that involve IBC, this module is designed to successfully +/// handle cross-chain messages. It's key for ensuring that your contract can smoothly interact +/// with other blockchains in the Cosmos network. pub type IbcAcceptingModule = AcceptingModule; impl Ibc for IbcAcceptingModule {} - +/// Use this to test how your contract deals with problematic IBC scenarios. +/// It's a module that deliberately fails in handling IBC messages, allowing you +/// to check how your contract behaves in less-than-ideal cross-chain communication situations. pub type IbcFailingModule = FailingModule; impl Ibc for IbcFailingModule {} diff --git a/src/lib.rs b/src/lib.rs index 99a926b7..d933e0a7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,18 +1,135 @@ -//! Multitest is a design to simulate a blockchain environment in pure Rust. -//! This allows us to run unit tests that involve contract -> contract, -//! and contract -> bank interactions. This is not intended to be a full blockchain app -//! but to simulate the Cosmos SDK x/wasm module close enough to gain confidence in -//! multi-contract deployments before testing them on a live blockchain. +//! # CosmWasm MultiTest //! -//! To understand the design of this module, please refer to `../DESIGN.md` +//! **CosmWasm MultiTest** is designed to simulate a blockchain environment in pure Rust. +//! This allows to run unit tests that involve **contract 🡘 contract**, +//! and **contract 🡘 module** interactions. **CosmWasm MultiTest** is not intended +//! to be a full blockchain application, but to simulate the Cosmos SDK x/wasm module close enough +//! to gain confidence in multi-contract deployments, before testing them on a live blockchain. +//! +//! The following sections explains some of the design for those who want to use the API, +//! as well as those who want to take a look under the hood of **CosmWasm MultiTest**. +//! +//! ## Key APIs +//! +//! ### App +//! +//! The main entry point to the system is called [App], which represents a blockchain application. +//! It maintains an idea of block height and time, which can be updated to simulate multiple +//! blocks. You can use application's [update_block](App::update_block) method to increment +//! the timestamp by 5 seconds and the height by 1 (simulating a new block) or you can write +//! any other mutator of [BlockInfo](cosmwasm_std::BlockInfo) to advance more. +//! +//! [App] exposes an entry point [execute](App::execute) that allows to execute +//! any [CosmosMsg](cosmwasm_std::CosmosMsg) and wraps it in an atomic transaction. +//! That is, only if [execute](App::execute) returns a success, then the state will be committed. +//! It returns the data and a list of [Event](cosmwasm_std::Event)s on successful execution +//! or an **`Err(String)`** on error. There are some helper methods tied to the [Executor] trait +//! that create the [CosmosMsg](cosmwasm_std::CosmosMsg) for you to provide a less verbose API. +//! [App]'s methods like [instantiate_contract](App::instantiate_contract), +//! [execute_contract](App::execute_contract), and [send_tokens](App::send_tokens) are exposed +//! for your convenience in writing tests. +//! Each method executes one [CosmosMsg](cosmwasm_std::CosmosMsg) atomically, as if it was submitted by a user. +//! You can also use [execute_multi](App::execute_multi) if you wish to execute multiple messages together +//! that revert the state as a whole in case of any failure. +//! +//! The other key entry point to [App] is the [Querier](cosmwasm_std::Querier) interface that it implements. +//! In particular, you can use [wrap](App::wrap) to get a [QuerierWrapper](cosmwasm_std::QuerierWrapper), +//! which provides all kinds of interesting APIs to query the blockchain, like +//! [query_all_balances](cosmwasm_std::QuerierWrapper::query_all_balances) and +//! [query_wasm_smart](cosmwasm_std::QuerierWrapper::query_wasm_smart). +//! Putting this all together, you have one [Storage](cosmwasm_std::Storage) wrapped into an application, +//! where you can execute contracts and bank, query them easily, and update the current +//! [BlockInfo](cosmwasm_std::BlockInfo), in an API that is not very verbose or cumbersome. +//! Under the hood it will process all messages returned from contracts, move _bank_ tokens +//! and call into other contracts. +//! +//! You can easily create an [App] for use in your testcode like shown below. +//! Having a single utility function for creating and configuring the [App] is the common +//! pattern while testing contracts with **CosmWasm MultiTest**. +//! +//! ``` +//! use cw_multi_test::App; +//! +//! fn mock_app() -> App { +//! App::default() +//! } +//! ``` +//! +//! The [App] maintains the root [Storage](cosmwasm_std::Storage), and the [BlockInfo](cosmwasm_std::BlockInfo) +//! for the current block. It also contains a [Router] (discussed below), which can process +//! any [CosmosMsg](cosmwasm_std::CosmosMsg) variant by passing it to the proper keeper. +//! +//! > **Note**: [App] properly handles submessages and reply blocks. +//! +//! > **Note**: While the API currently supports custom messages, we don't currently have an implementation +//! > of the default keeper, except of experimental [CachingCustomHandler](custom_handler::CachingCustomHandler). +//! +//! ### Contracts +//! +//! Before you can call contracts, you must **instantiate** them. And to instantiate them, you need a `code_id`. +//! In `wasmd`, this `code_id` points to some stored Wasm code that is then run. In multitest, we use it to +//! point to a `Box` that should be run. That is, you need to implement the [Contract] trait +//! and then add the contract to the [App] via [store_code](App::store_code) function. +//! +//! The [Contract] trait defines the major entry points to any CosmWasm contract: +//! [instantiate](Contract::instantiate), [execute](Contract::execute), [query](Contract::query), +//! [sudo](Contract::sudo), [reply](Contract::reply) (for submessages) and [migrate](Contract::migrate). +//! +//! In order to easily implement [Contract] from some existing contract code, we use the [ContractWrapper] struct, +//! which takes some function pointers and combines them. You can take a look at **test_helpers** module +//! for some examples or how to do so (and useful mocks for some test cases). +//! Here is an example of wrapping a CosmWasm contract into a [Contract] trait to be added to an [App]: +//! +//! ```ignore +//! use cosmwasm_std::Empty; +//! use cw1_whitelist::contract::{execute, instantiate, query}; +//! use cw_multi_test::{App, Contract, ContractWrapper}; +//! +//! pub fn contract_whitelist() -> Box> { +//! Box::new(ContractWrapper::new(execute, instantiate, query)) +//! } +//! +//! let mut app = App::default(); +//! let code_id = app.store_code(contract_whitelist()); +//! // use this code_id to instantiate a contract +//! ``` +//! +//! ### Modules +//! +//! There is only one root [Storage](cosmwasm_std::Storage), stored inside [App]. +//! This is wrapped into a transaction, and then passed down to other functions to work with. +//! The code that modifies the Storage is divided into _modules_ much like the CosmosSDK. +//! Currently, the message processing logic is divided into one _module_ for every [CosmosMsg](cosmwasm_std) variant. +//! [Bank] handles [BankMsg](cosmwasm_std::BankMsg) and [BankQuery](cosmwasm_std::BankQuery), +//! [Wasm] handles [WasmMsg](cosmwasm_std::WasmMsg) and [WasmQuery](cosmwasm_std::WasmQuery), etc. +//! +//! ### Router +//! +//! The [Router] groups all modules in the system into one "macro-module" that can handle +//! any [CosmosMsg](cosmwasm_std::CosmosMsg). While [Bank] handles [BankMsg](cosmwasm_std::BankMsg), +//! and [Wasm] handles [WasmMsg](cosmwasm_std::WasmMsg), we need to combine them into a larger composite +//! to let them process messages from [App]. This is the whole concept of the [Router]. +//! If you take a look at the [execute](Router::execute) method, you will see it is quite straightforward. +//! +//! Note that the only way one module can call or query another module is by dispatching messages via the [Router]. +//! This allows us to implement an independent [Wasm] in a way that it can process [SubMsg](cosmwasm_std::SubMsg) +//! that call into [Bank]. You can see an example of that in _send_ method of the [WasmKeeper], +//! where it moves bank tokens from one account to another. +//! +//! ### Addons +//! +//! (tbd) + +// #![deny(missing_docs)] +#![deny(rustdoc::broken_intra_doc_links)] +#![deny(rustdoc::missing_crate_level_docs)] -pub mod addons; mod addresses; +mod api; mod app; mod app_builder; mod bank; mod checksums; -#[allow(clippy::type_complexity)] mod contracts; pub mod custom_handler; pub mod error; @@ -23,12 +140,20 @@ mod module; pub(crate) mod prefixed_storage; pub mod queries; mod staking; +mod stargate; +mod test_helpers; +mod tests; mod transactions; mod wasm; pub mod wasm_emulation; -pub use crate::addresses::{AddressGenerator, SimpleAddressGenerator}; -pub use crate::app::{custom_app, next_block, App, BasicApp, CosmosRouter, Router, SudoMsg}; +pub use crate::addresses::{ + AddressGenerator, IntoAddr, IntoBech32, IntoBech32m, SimpleAddressGenerator, +}; +pub use crate::api::{MockApiBech32, MockApiBech32m}; +pub use crate::app::{ + custom_app, next_block, no_init, App, BasicApp, CosmosRouter, Router, SudoMsg, +}; pub use crate::app_builder::{AppBuilder, BasicAppBuilder}; pub use crate::bank::{Bank, BankKeeper, BankSudo}; pub use crate::checksums::ChecksumGenerator; @@ -40,8 +165,7 @@ pub use crate::module::{AcceptingModule, FailingModule, Module}; pub use crate::staking::{ Distribution, DistributionKeeper, StakeKeeper, Staking, StakingInfo, StakingSudo, }; +pub use crate::stargate::{Stargate, StargateAccepting, StargateFailing}; pub use crate::wasm::{ ContractData, Wasm, WasmKeeper, WasmSudo, LOCAL_RUST_CODE_OFFSET, LOCAL_WASM_CODE_OFFSET, }; - -pub use prefixed_storage::{PrefixedStorage, ReadonlyPrefixedStorage}; diff --git a/src/module.rs b/src/module.rs index 470e8d97..7b0dc9d1 100644 --- a/src/module.rs +++ b/src/module.rs @@ -1,16 +1,23 @@ use crate::app::CosmosRouter; use crate::error::{bail, AnyResult}; use crate::AppResponse; -use cosmwasm_std::{Addr, Api, Binary, BlockInfo, CustomQuery, Querier, Storage}; -use schemars::JsonSchema; +use cosmwasm_std::{Addr, Api, Binary, BlockInfo, CustomMsg, CustomQuery, Querier, Storage}; use serde::de::DeserializeOwned; use std::fmt::Debug; use std::marker::PhantomData; -/// Module interface. +/// # General module +/// +/// Provides a generic interface for modules within the test environment. +/// It is essential for creating modular and extensible testing setups, +/// allowing developers to integrate custom functionalities +/// or test specific scenarios. pub trait Module { + /// Type of messages processed by the module instance. type ExecT; + /// Type of queries processed by the module instance. type QueryT; + /// Type of privileged messages used by the module instance. type SudoT; /// Runs any [ExecT](Self::ExecT) message, @@ -25,7 +32,7 @@ pub trait Module { msg: Self::ExecT, ) -> AnyResult where - ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static, + ExecC: CustomMsg + DeserializeOwned + 'static, QueryC: CustomQuery + DeserializeOwned + 'static; /// Runs any [QueryT](Self::QueryT) message, @@ -53,21 +60,26 @@ pub trait Module { msg: Self::SudoT, ) -> AnyResult where - ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static, + ExecC: CustomMsg + DeserializeOwned + 'static, QueryC: CustomQuery + DeserializeOwned + 'static; } +/// # Always failing module +/// +/// This could be a diagnostic or testing tool within the Cosmos ecosystem, +/// designed to intentionally fail during processing any message, query or privileged action. +pub struct FailingModule(PhantomData<(ExecT, QueryT, SudoT)>); -pub struct FailingModule { - module_type: String, - _t: PhantomData<(ExecT, QueryT, SudoT)>, +impl FailingModule { + /// Creates an instance of a failing module. + pub fn new() -> Self { + Self(PhantomData) + } } -impl FailingModule { - pub fn new(module_type: &str) -> Self { - Self { - module_type: module_type.to_string(), - _t: PhantomData, - } +impl Default for FailingModule { + /// Creates a default instance of a failing module. + fn default() -> Self { + Self::new() } } @@ -91,12 +103,7 @@ where sender: Addr, msg: Self::ExecT, ) -> AnyResult { - bail!( - "Unexpected exec msg {:?} from {:?} on {} module", - msg, - sender, - self.module_type - ) + bail!("Unexpected exec msg {:?} from {:?}", msg, sender,) } /// Runs any [QueryT](Self::QueryT) message, always returns an error. @@ -108,11 +115,7 @@ where _block: &BlockInfo, request: Self::QueryT, ) -> AnyResult { - bail!( - "Unexpected custom query {:?} on {} module", - request, - self.module_type - ) + bail!("Unexpected custom query {:?}", request,) } /// Runs any [SudoT](Self::SudoT) privileged action, always returns an error. @@ -124,23 +127,24 @@ where _block: &BlockInfo, msg: Self::SudoT, ) -> AnyResult { - bail!( - "Unexpected sudo msg {:?} on {} module", - msg, - self.module_type - ) + bail!("Unexpected sudo msg {:?}", msg,) } } - +/// # Always accepting module +/// +/// This struct represents a module in the Cosmos ecosystem designed to +/// always accept all processed messages, queries and privileged actions. pub struct AcceptingModule(PhantomData<(ExecT, QueryT, SudoT)>); impl AcceptingModule { + /// Creates an instance of an accepting module. pub fn new() -> Self { Self(PhantomData) } } impl Default for AcceptingModule { + /// Creates an instance of an accepting module with default settings. fn default() -> Self { Self::new() } @@ -169,7 +173,7 @@ where Ok(AppResponse::default()) } - /// Runs any [QueryT](Self::QueryT) message, always returns an empty binary. + /// Runs any [QueryT](Self::QueryT) message, always returns a default (empty) binary. fn query( &self, _api: &dyn Api, diff --git a/src/prefixed_storage/length_prefixed.rs b/src/prefixed_storage/length_prefixed.rs index 82eaf23b..931b8acd 100644 --- a/src/prefixed_storage/length_prefixed.rs +++ b/src/prefixed_storage/length_prefixed.rs @@ -102,7 +102,7 @@ mod tests { #[test] fn to_length_prefixed_calculates_capacity_correctly() { // Those tests cannot guarantee the required capacity was calculated correctly before - // the vector allocation but increase the likelyhood of a proper implementation. + // the vector allocation but increase the likelihood of a proper implementation. let key = to_length_prefixed(b""); assert_eq!(key.capacity(), key.len()); @@ -161,7 +161,7 @@ mod tests { #[test] fn to_length_prefixed_nested_calculates_capacity_correctly() { // Those tests cannot guarantee the required capacity was calculated correctly before - // the vector allocation but increase the likelyhood of a proper implementation. + // the vector allocation but increase the likelihood of a proper implementation. let key = to_length_prefixed_nested(&[]); assert_eq!(key.capacity(), key.len()); diff --git a/src/prefixed_storage/mod.rs b/src/prefixed_storage/mod.rs index 4506230a..78f05e29 100644 --- a/src/prefixed_storage/mod.rs +++ b/src/prefixed_storage/mod.rs @@ -11,12 +11,12 @@ pub use length_prefixed::{ CONTRACT_STORAGE_PREFIX, }; -/// An alias of PrefixedStorage::new for less verbose usage +/// An alias of [PrefixedStorage::new] for less verbose usage. pub fn prefixed<'a>(storage: &'a mut dyn Storage, namespace: &[u8]) -> PrefixedStorage<'a> { PrefixedStorage::new(storage, namespace) } -/// An alias of ReadonlyPrefixedStorage::new for less verbose usage +/// An alias of [ReadonlyPrefixedStorage::new] for less verbose usage. pub fn prefixed_read<'a>( storage: &'a dyn Storage, namespace: &[u8], @@ -24,12 +24,30 @@ pub fn prefixed_read<'a>( ReadonlyPrefixedStorage::new(storage, namespace) } +/// An alias of [PrefixedStorage::multilevel] for less verbose usage. +pub fn prefixed_multilevel<'a>( + storage: &'a mut dyn Storage, + namespaces: &[&[u8]], +) -> PrefixedStorage<'a> { + PrefixedStorage::multilevel(storage, namespaces) +} + +/// An alias of [ReadonlyPrefixedStorage::multilevel] for less verbose usage. +pub fn prefixed_multilevel_read<'a>( + storage: &'a dyn Storage, + namespaces: &[&[u8]], +) -> ReadonlyPrefixedStorage<'a> { + ReadonlyPrefixedStorage::multilevel(storage, namespaces) +} + +/// Prefixed, mutable storage. pub struct PrefixedStorage<'a> { storage: &'a mut dyn Storage, prefix: Vec, } impl<'a> PrefixedStorage<'a> { + /// Returns a mutable prefixed storage with specified namespace. pub fn new(storage: &'a mut dyn Storage, namespace: &[u8]) -> Self { PrefixedStorage { storage, @@ -37,8 +55,9 @@ impl<'a> PrefixedStorage<'a> { } } - // Nested namespaces as documented in - // https://github.com/webmaster128/key-namespacing#nesting + /// Returns a mutable prefixed storage with [nested namespaces]. + /// + /// [nested namespaces]: https://github.com/webmaster128/key-namespacing#nesting pub fn multilevel(storage: &'a mut dyn Storage, namespaces: &[&[u8]]) -> Self { PrefixedStorage { storage, @@ -52,16 +71,8 @@ impl<'a> Storage for PrefixedStorage<'a> { get_with_prefix(self.storage, &self.prefix, key) } - fn set(&mut self, key: &[u8], value: &[u8]) { - set_with_prefix(self.storage, &self.prefix, key, value); - } - - fn remove(&mut self, key: &[u8]) { - remove_with_prefix(self.storage, &self.prefix, key); - } - - /// range allows iteration over a set of keys, either forwards or backwards - /// uses standard rust range notation, and eg db.range(b"foo"..b"bar") also works reverse + /// Range allows iteration over a set of keys, either forwards or backwards. + /// Uses standard rust range notation, and e.g. `db.range(b"foo"‥b"bar")` and also works reverse. fn range<'b>( &'b self, start: Option<&[u8]>, @@ -70,14 +81,24 @@ impl<'a> Storage for PrefixedStorage<'a> { ) -> Box + 'b> { range_with_prefix(self.storage, &self.prefix, start, end, order) } + + fn set(&mut self, key: &[u8], value: &[u8]) { + set_with_prefix(self.storage, &self.prefix, key, value); + } + + fn remove(&mut self, key: &[u8]) { + remove_with_prefix(self.storage, &self.prefix, key); + } } +/// Prefixed, read-only storage. pub struct ReadonlyPrefixedStorage<'a> { storage: &'a dyn Storage, prefix: Vec, } impl<'a> ReadonlyPrefixedStorage<'a> { + /// Returns a read-only prefixed storage with specified namespace. pub fn new(storage: &'a dyn Storage, namespace: &[u8]) -> Self { ReadonlyPrefixedStorage { storage, @@ -85,8 +106,9 @@ impl<'a> ReadonlyPrefixedStorage<'a> { } } - // Nested namespaces as documented in - // https://github.com/webmaster128/key-namespacing#nesting + /// Returns a read-only prefixed storage with [nested namespaces]. + /// + /// [nested namespaces]: https://github.com/webmaster128/key-namespacing#nesting pub fn multilevel(storage: &'a dyn Storage, namespaces: &[&[u8]]) -> Self { ReadonlyPrefixedStorage { storage, @@ -100,15 +122,7 @@ impl<'a> Storage for ReadonlyPrefixedStorage<'a> { get_with_prefix(self.storage, &self.prefix, key) } - fn set(&mut self, _key: &[u8], _value: &[u8]) { - unimplemented!(); - } - - fn remove(&mut self, _key: &[u8]) { - unimplemented!(); - } - - /// range allows iteration over a set of keys, either forwards or backwards + /// Range allows iteration over a set of keys, either forwards or backwards. fn range<'b>( &'b self, start: Option<&[u8]>, @@ -117,6 +131,14 @@ impl<'a> Storage for ReadonlyPrefixedStorage<'a> { ) -> Box + 'b> { range_with_prefix(self.storage, &self.prefix, start, end, order) } + + fn set(&mut self, _key: &[u8], _value: &[u8]) { + unimplemented!(); + } + + fn remove(&mut self, _key: &[u8]) { + unimplemented!(); + } } #[cfg(test)] @@ -139,6 +161,35 @@ mod tests { assert_eq!(s2.get(b"elsewhere"), None); } + #[test] + fn prefixed_storage_range() { + // prepare prefixed storage + let mut storage = MockStorage::new(); + let mut ps1 = PrefixedStorage::new(&mut storage, b"foo"); + ps1.set(b"a", b"A"); + ps1.set(b"l", b"L"); + ps1.set(b"p", b"P"); + ps1.set(b"z", b"Z"); + assert_eq!(storage.get(b"\x00\x03fooa").unwrap(), b"A".to_vec()); + assert_eq!(storage.get(b"\x00\x03fool").unwrap(), b"L".to_vec()); + assert_eq!(storage.get(b"\x00\x03foop").unwrap(), b"P".to_vec()); + assert_eq!(storage.get(b"\x00\x03fooz").unwrap(), b"Z".to_vec()); + // query prefixed storage using range function + let ps2 = PrefixedStorage::new(&mut storage, b"foo"); + assert_eq!( + vec![b"A".to_vec(), b"L".to_vec(), b"P".to_vec()], + ps2.range(Some(b"a"), Some(b"z"), Order::Ascending) + .map(|(_, value)| value) + .collect::>>() + ); + assert_eq!( + vec![b"Z".to_vec(), b"P".to_vec(), b"L".to_vec(), b"A".to_vec()], + ps2.range(Some(b"a"), None, Order::Descending) + .map(|(_, value)| value) + .collect::>>() + ); + } + #[test] fn prefixed_storage_multilevel_set_and_get() { let mut storage = MockStorage::new(); @@ -172,6 +223,24 @@ mod tests { assert_eq!(s2.get(b"obar"), None); } + #[test] + #[should_panic(expected = "not implemented")] + #[allow(clippy::unnecessary_mut_passed)] + fn readonly_prefixed_storage_set() { + let mut storage = MockStorage::new(); + let mut rps = ReadonlyPrefixedStorage::new(&mut storage, b"foo"); + rps.set(b"bar", b"gotcha"); + } + + #[test] + #[should_panic(expected = "not implemented")] + #[allow(clippy::unnecessary_mut_passed)] + fn readonly_prefixed_storage_remove() { + let mut storage = MockStorage::new(); + let mut rps = ReadonlyPrefixedStorage::new(&mut storage, b"foo"); + rps.remove(b"gotcha"); + } + #[test] fn readonly_prefixed_storage_multilevel_get() { let mut storage = MockStorage::new(); diff --git a/src/staking.rs b/src/staking.rs index fc0048dc..cb311cdc 100644 --- a/src/staking.rs +++ b/src/staking.rs @@ -5,16 +5,16 @@ use crate::prefixed_storage::{prefixed, prefixed_read}; use crate::{BankSudo, Module}; use cosmwasm_std::{ coin, ensure, ensure_eq, to_json_binary, Addr, AllDelegationsResponse, AllValidatorsResponse, - Api, BankMsg, Binary, BlockInfo, BondedDenomResponse, Coin, CustomQuery, Decimal, Delegation, - DelegationResponse, DistributionMsg, Empty, Event, FullDelegation, Querier, StakingMsg, - StakingQuery, Storage, Timestamp, Uint128, Validator, ValidatorResponse, + Api, BankMsg, Binary, BlockInfo, BondedDenomResponse, Coin, CustomMsg, CustomQuery, Decimal, + Delegation, DelegationResponse, DistributionMsg, Empty, Event, FullDelegation, Querier, + StakingMsg, StakingQuery, Storage, Timestamp, Uint128, Validator, ValidatorResponse, }; use cw_storage_plus::{Deque, Item, Map}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::collections::{BTreeSet, VecDeque}; -// Contains some general staking parameters +/// A structure containing some general staking parameters. #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] pub struct StakingInfo { /// The denominator of the staking token @@ -26,6 +26,7 @@ pub struct StakingInfo { } impl Default for StakingInfo { + /// Creates staking info with default settings. fn default() -> Self { StakingInfo { bonded_denom: "TOKEN".to_string(), @@ -101,49 +102,58 @@ pub const NAMESPACE_STAKING: &[u8] = b"staking"; // https://github.com/cosmos/cosmos-sdk/blob/4f6f6c00021f4b5ee486bbb71ae2071a8ceb47c9/x/distribution/types/keys.go#L16 pub const NAMESPACE_DISTRIBUTION: &[u8] = b"distribution"; -// We need to expand on this, but we will need this to properly test out staking -#[derive(Clone, std::fmt::Debug, PartialEq, Eq, JsonSchema)] +/// Staking privileged action definition. +/// +/// We need to expand on this, but we will need this to properly test out staking +#[derive(Clone, Debug, PartialEq, Eq, JsonSchema)] pub enum StakingSudo { /// Slashes the given percentage of the validator's stake. /// For now, you cannot slash retrospectively in tests. Slash { + /// Validator's address. validator: String, + /// Percentage of the validator's stake. percentage: Decimal, }, - /// Causes the unbonding queue to be processed. - /// This needs to be triggered manually, since there is no good place to do this right now. - /// In cosmos-sdk, this is done in `EndBlock`, but we don't have that here. - #[deprecated(note = "This is not needed anymore. Just call `update_block`")] - ProcessQueue {}, } +/// A trait defining a behavior of the stake keeper. +/// +/// Manages staking operations, vital for testing contracts in proof-of-stake (PoS) blockchain environments. +/// This trait simulates staking behaviors, including delegation, validator operations, and reward mechanisms. pub trait Staking: Module { /// This is called from the end blocker (`update_block` / `set_block`) to process the - /// staking queue. - /// Needed because unbonding has a waiting time. + /// staking queue. Needed because unbonding has a waiting time. /// If you're implementing a dummy staking module, this can be a no-op. - fn process_queue( + fn process_queue( &self, - api: &dyn Api, - storage: &mut dyn Storage, - router: &dyn CosmosRouter, - block: &BlockInfo, - ) -> AnyResult; + _api: &dyn Api, + _storage: &mut dyn Storage, + _router: &dyn CosmosRouter, + _block: &BlockInfo, + ) -> AnyResult { + Ok(AppResponse::default()) + } } +/// A trait defining a behavior of the distribution keeper. pub trait Distribution: Module {} +/// A structure representing a default stake keeper. pub struct StakeKeeper { + /// Module address of a default stake keeper. module_addr: Addr, } impl Default for StakeKeeper { + /// Creates a new stake keeper with default settings. fn default() -> Self { Self::new() } } impl StakeKeeper { + /// Creates a new stake keeper with default module address. pub fn new() -> Self { StakeKeeper { // The address of the staking module. This holds all staked tokens. @@ -154,7 +164,6 @@ impl StakeKeeper { /// Provides some general parameters to the stake keeper pub fn setup(&self, storage: &mut dyn Storage, staking_info: StakingInfo) -> AnyResult<()> { let mut storage = prefixed(storage, NAMESPACE_STAKING); - STAKING_INFO.save(&mut storage, &staking_info)?; Ok(()) } @@ -270,7 +279,7 @@ impl StakeKeeper { } /// Updates the staking reward for the given validator and their stakers - /// It saves the validator info and it's stakers, so make sure not to overwrite that. + /// It saves the validator info and stakers, so make sure not to overwrite that. /// Always call this to update rewards before changing anything that influences future rewards. fn update_rewards( api: &dyn Api, @@ -532,7 +541,7 @@ impl StakeKeeper { Ok(()) } - fn process_queue( + fn process_queue( &self, api: &dyn Api, storage: &mut dyn Storage, @@ -601,7 +610,7 @@ impl StakeKeeper { } impl Staking for StakeKeeper { - fn process_queue( + fn process_queue( &self, api: &dyn Api, storage: &mut dyn Storage, @@ -617,7 +626,7 @@ impl Module for StakeKeeper { type QueryT = StakingQuery; type SudoT = StakingSudo; - fn execute( + fn execute( &self, api: &dyn Api, storage: &mut dyn Storage, @@ -735,32 +744,6 @@ impl Module for StakeKeeper { } } - fn sudo( - &self, - api: &dyn Api, - storage: &mut dyn Storage, - router: &dyn CosmosRouter, - block: &BlockInfo, - msg: StakingSudo, - ) -> AnyResult { - match msg { - StakingSudo::Slash { - validator, - percentage, - } => { - let mut staking_storage = prefixed(storage, NAMESPACE_STAKING); - let validator = api.addr_validate(&validator)?; - self.validate_percentage(percentage)?; - - self.slash(api, &mut staking_storage, block, &validator, percentage)?; - - Ok(AppResponse::default()) - } - #[allow(deprecated)] - StakingSudo::ProcessQueue {} => self.process_queue(api, storage, router, block), - } - } - fn query( &self, api: &dyn Api, @@ -825,7 +808,7 @@ impl Module for StakeKeeper { let staking_info = Self::get_staking_info(&staking_storage)?; let amount = coin( - (Uint128::new(1).mul_floor(shares.stake)).u128(), + Uint128::new(1).mul_floor(shares.stake).u128(), staking_info.bonded_denom, ); @@ -858,14 +841,42 @@ impl Module for StakeKeeper { q => bail!("Unsupported staking sudo message: {:?}", q), } } + + fn sudo( + &self, + api: &dyn Api, + storage: &mut dyn Storage, + _router: &dyn CosmosRouter, + block: &BlockInfo, + msg: StakingSudo, + ) -> AnyResult { + match msg { + StakingSudo::Slash { + validator, + percentage, + } => { + let mut staking_storage = prefixed(storage, NAMESPACE_STAKING); + let validator = api.addr_validate(&validator)?; + self.validate_percentage(percentage)?; + self.slash(api, &mut staking_storage, block, &validator, percentage)?; + Ok(AppResponse::default()) + } + } + } } +/// A structure representing a default distribution keeper. +/// +/// This module likely manages the distribution of rewards and fees within the blockchain network. +/// It could handle tasks like distributing block rewards to validators and delegators, +/// and managing community funding mechanisms. #[derive(Default)] pub struct DistributionKeeper {} impl DistributionKeeper { + /// Creates a new distribution keeper with default settings. pub fn new() -> Self { - DistributionKeeper {} + Self::default() } /// Removes all rewards from the given (delegator, validator) pair and returns the amount @@ -892,6 +903,7 @@ impl DistributionKeeper { Ok(rewards) } + /// Returns the withdrawal address for specified delegator. pub fn get_withdraw_address(storage: &dyn Storage, delegator: &Addr) -> AnyResult { Ok(match WITHDRAW_ADDRESS.may_load(storage, delegator)? { Some(a) => a, @@ -899,20 +911,22 @@ impl DistributionKeeper { }) } - // https://docs.cosmos.network/main/modules/distribution#msgsetwithdrawaddress + /// Sets (changes) the [withdraw address] of the delegator. + /// + /// [withdraw address]: https://docs.cosmos.network/main/modules/distribution#msgsetwithdrawaddress pub fn set_withdraw_address( storage: &mut dyn Storage, delegator: &Addr, - withdraw_address: &Addr, + withdraw_addr: &Addr, ) -> AnyResult<()> { - if delegator == withdraw_address { + if delegator == withdraw_addr { WITHDRAW_ADDRESS.remove(storage, delegator); Ok(()) } else { // technically we should require that this address is not // the address of a module. TODO: how? WITHDRAW_ADDRESS - .save(storage, delegator, withdraw_address) + .save(storage, delegator, withdraw_addr) .map_err(|e| e.into()) } } @@ -925,7 +939,7 @@ impl Module for DistributionKeeper { type QueryT = Empty; type SudoT = Empty; - fn execute( + fn execute( &self, api: &dyn Api, storage: &mut dyn Storage, @@ -984,6 +998,17 @@ impl Module for DistributionKeeper { } } + fn query( + &self, + _api: &dyn Api, + _storage: &dyn Storage, + _querier: &dyn Querier, + _block: &BlockInfo, + _request: Empty, + ) -> AnyResult { + bail!("Something went wrong - Distribution doesn't have query messages") + } + fn sudo( &self, _api: &dyn Api, @@ -994,15 +1019,1510 @@ impl Module for DistributionKeeper { ) -> AnyResult { bail!("Something went wrong - Distribution doesn't have sudo messages") } +} - fn query( - &self, - _api: &dyn Api, - _storage: &dyn Storage, - _querier: &dyn Querier, - _block: &BlockInfo, - _request: Empty, - ) -> AnyResult { - bail!("Something went wrong - Distribution doesn't have query messages") +#[cfg(test)] +mod test { + use super::*; + use crate::{ + app::MockRouter, BankKeeper, FailingModule, GovFailingModule, IbcFailingModule, Router, + StargateFailing, WasmKeeper, + }; + use cosmwasm_std::{ + from_json, + testing::{mock_env, MockApi, MockStorage}, + BalanceResponse, BankQuery, + }; + + /// Type alias for default build `Router` to make its reference in typical scenario + type BasicRouter = Router< + BankKeeper, + FailingModule, + WasmKeeper, + StakeKeeper, + DistributionKeeper, + IbcFailingModule, + GovFailingModule, + StargateFailing, + >; + + fn mock_router() -> BasicRouter { + Router { + wasm: WasmKeeper::new(), + bank: BankKeeper::new(), + custom: FailingModule::new(), + staking: StakeKeeper::new(), + distribution: DistributionKeeper::new(), + ibc: IbcFailingModule::new(), + gov: GovFailingModule::new(), + stargate: StargateFailing, + } + } + + fn setup_test_env( + apr: Decimal, + validator_commission: Decimal, + ) -> (MockApi, MockStorage, BasicRouter, BlockInfo, Addr) { + let api = MockApi::default(); + let router = mock_router(); + let mut store = MockStorage::new(); + let block = mock_env().block; + + let validator_addr = api.addr_make("testvaloper1"); + + router + .staking + .setup( + &mut store, + StakingInfo { + bonded_denom: "TOKEN".to_string(), + unbonding_time: 60, + apr, + }, + ) + .unwrap(); + + // add validator + let valoper1 = Validator::new( + validator_addr.to_string(), + validator_commission, + Decimal::percent(100), + Decimal::percent(1), + ); + router + .staking + .add_validator(&api, &mut store, &block, valoper1) + .unwrap(); + + (api, store, router, block, validator_addr) + } + + #[test] + fn add_get_validators() { + let api = MockApi::default(); + let mut store = MockStorage::new(); + let stake = StakeKeeper::default(); + let block = mock_env().block; + + let validator_addr = api.addr_make("test-validator"); + + // add validator + let validator = Validator::new( + validator_addr.to_string(), + Decimal::percent(10), + Decimal::percent(20), + Decimal::percent(1), + ); + stake + .add_validator(&api, &mut store, &block, validator.clone()) + .unwrap(); + + // get it + let staking_storage = prefixed_read(&store, NAMESPACE_STAKING); + let val = stake + .get_validator(&staking_storage, &validator_addr) + .unwrap() + .unwrap(); + assert_eq!(val, validator); + + // try to add with same address + let validator_fake = Validator::new( + validator_addr.to_string(), + Decimal::percent(1), + Decimal::percent(10), + Decimal::percent(100), + ); + stake + .add_validator(&api, &mut store, &block, validator_fake) + .unwrap_err(); + + // should still be original value + let staking_storage = prefixed_read(&store, NAMESPACE_STAKING); + let val = stake + .get_validator(&staking_storage, &validator_addr) + .unwrap() + .unwrap(); + assert_eq!(val, validator); + } + + #[test] + fn validator_slashing() { + let api = MockApi::default(); + let router = MockRouter::default(); + let mut store = MockStorage::new(); + let stake = StakeKeeper::new(); + let block = mock_env().block; + + let delegator_addr = api.addr_make("delegator"); + let validator_addr = api.addr_make("testvaloper1"); + + // add validator + let valoper1 = Validator::new( + validator_addr.to_string(), + Decimal::percent(10), + Decimal::percent(20), + Decimal::percent(1), + ); + stake + .add_validator(&api, &mut store, &block, valoper1) + .unwrap(); + + // stake 100 tokens + let mut staking_storage = prefixed(&mut store, NAMESPACE_STAKING); + stake + .add_stake( + &api, + &mut staking_storage, + &block, + &delegator_addr, + &validator_addr, + coin(100, "TOKEN"), + ) + .unwrap(); + + // slash 50% + stake + .sudo( + &api, + &mut store, + &router, + &block, + StakingSudo::Slash { + validator: validator_addr.to_string(), + percentage: Decimal::percent(50), + }, + ) + .unwrap(); + + // check stake + let staking_storage = prefixed(&mut store, NAMESPACE_STAKING); + let stake_left = stake + .get_stake(&staking_storage, &delegator_addr, &validator_addr) + .unwrap(); + assert_eq!( + stake_left.unwrap().amount.u128(), + 50, + "should have slashed 50%" + ); + + // slash all + stake + .sudo( + &api, + &mut store, + &router, + &block, + StakingSudo::Slash { + validator: validator_addr.to_string(), + percentage: Decimal::percent(100), + }, + ) + .unwrap(); + + // check stake + let staking_storage = prefixed(&mut store, NAMESPACE_STAKING); + let stake_left = stake + .get_stake(&staking_storage, &delegator_addr, &validator_addr) + .unwrap(); + assert_eq!(stake_left, None, "should have slashed whole stake"); + } + + #[test] + fn rewards_work_for_single_delegator() { + let (api, mut store, router, mut block, validator_addr) = + setup_test_env(Decimal::percent(10), Decimal::percent(10)); + let stake = &router.staking; + let distr = &router.distribution; + let delegator_addr = api.addr_make("delegator"); + + let mut staking_storage = prefixed(&mut store, NAMESPACE_STAKING); + // stake 200 tokens + stake + .add_stake( + &api, + &mut staking_storage, + &block, + &delegator_addr, + &validator_addr, + coin(200, "TOKEN"), + ) + .unwrap(); + + // wait 1/2 year + block.time = block.time.plus_seconds(60 * 60 * 24 * 365 / 2); + + // should now have 200 * 10% / 2 - 10% commission = 9 tokens reward + let rewards = stake + .get_rewards(&store, &block, &delegator_addr, &validator_addr) + .unwrap() + .unwrap(); + assert_eq!(rewards.amount.u128(), 9, "should have 9 tokens reward"); + + // withdraw rewards + distr + .execute( + &api, + &mut store, + &router, + &block, + delegator_addr.clone(), + DistributionMsg::WithdrawDelegatorReward { + validator: validator_addr.to_string(), + }, + ) + .unwrap(); + + // should have no rewards left + let rewards = stake + .get_rewards(&store, &block, &delegator_addr, &validator_addr) + .unwrap() + .unwrap(); + assert_eq!(rewards.amount.u128(), 0); + + // wait another 1/2 year + block.time = block.time.plus_seconds(60 * 60 * 24 * 365 / 2); + // should now have 9 tokens again + let rewards = stake + .get_rewards(&store, &block, &delegator_addr, &validator_addr) + .unwrap() + .unwrap(); + assert_eq!(rewards.amount.u128(), 9); + } + + #[test] + fn rewards_work_for_multiple_delegators() { + let (api, mut store, router, mut block, validator) = + setup_test_env(Decimal::percent(10), Decimal::percent(10)); + let stake = &router.staking; + let distr = &router.distribution; + let bank = &router.bank; + let delegator1 = api.addr_make("delegator1"); + let delegator2 = api.addr_make("delegator2"); + + let mut staking_storage = prefixed(&mut store, NAMESPACE_STAKING); + + // add 100 stake to delegator1 and 200 to delegator2 + stake + .add_stake( + &api, + &mut staking_storage, + &block, + &delegator1, + &validator, + coin(100, "TOKEN"), + ) + .unwrap(); + stake + .add_stake( + &api, + &mut staking_storage, + &block, + &delegator2, + &validator, + coin(200, "TOKEN"), + ) + .unwrap(); + + // wait 1 year + block.time = block.time.plus_seconds(60 * 60 * 24 * 365); + + // delegator1 should now have 100 * 10% - 10% commission = 9 tokens + let rewards = stake + .get_rewards(&store, &block, &delegator1, &validator) + .unwrap() + .unwrap(); + assert_eq!(rewards.amount.u128(), 9); + + // delegator2 should now have 200 * 10% - 10% commission = 18 tokens + let rewards = stake + .get_rewards(&store, &block, &delegator2, &validator) + .unwrap() + .unwrap(); + assert_eq!(rewards.amount.u128(), 18); + + // delegator1 stakes 100 more + let mut staking_storage = prefixed(&mut store, NAMESPACE_STAKING); + stake + .add_stake( + &api, + &mut staking_storage, + &block, + &delegator1, + &validator, + coin(100, "TOKEN"), + ) + .unwrap(); + + // wait another year + block.time = block.time.plus_seconds(60 * 60 * 24 * 365); + + // delegator1 should now have 9 + 200 * 10% - 10% commission = 27 tokens + let rewards = stake + .get_rewards(&store, &block, &delegator1, &validator) + .unwrap() + .unwrap(); + assert_eq!(rewards.amount.u128(), 27); + + // delegator2 should now have 18 + 200 * 10% - 10% commission = 36 tokens + let rewards = stake + .get_rewards(&store, &block, &delegator2, &validator) + .unwrap() + .unwrap(); + assert_eq!(rewards.amount.u128(), 36); + + // delegator2 unstakes 100 (has 100 left after that) + let mut staking_storage = prefixed(&mut store, NAMESPACE_STAKING); + stake + .remove_stake( + &api, + &mut staking_storage, + &block, + &delegator2, + &validator, + coin(100, "TOKEN"), + ) + .unwrap(); + + // and delegator1 withdraws rewards + distr + .execute( + &api, + &mut store, + &router, + &block, + delegator1.clone(), + DistributionMsg::WithdrawDelegatorReward { + validator: validator.to_string(), + }, + ) + .unwrap(); + + let balance: BalanceResponse = from_json( + bank.query( + &api, + &store, + &router.querier(&api, &store, &block), + &block, + BankQuery::Balance { + address: delegator1.to_string(), + denom: "TOKEN".to_string(), + }, + ) + .unwrap(), + ) + .unwrap(); + assert_eq!( + balance.amount.amount.u128(), + 27, + "withdraw should change bank balance" + ); + let rewards = stake + .get_rewards(&store, &block, &delegator1, &validator) + .unwrap() + .unwrap(); + assert_eq!( + rewards.amount.u128(), + 0, + "withdraw should reduce rewards to 0" + ); + + // wait another year + block.time = block.time.plus_seconds(60 * 60 * 24 * 365); + + // delegator1 should now have 0 + 200 * 10% - 10% commission = 18 tokens + let rewards = stake + .get_rewards(&store, &block, &delegator1, &validator) + .unwrap() + .unwrap(); + assert_eq!(rewards.amount.u128(), 18); + + // delegator2 should now have 36 + 100 * 10% - 10% commission = 45 tokens + let rewards = stake + .get_rewards(&store, &block, &delegator2, &validator) + .unwrap() + .unwrap(); + assert_eq!(rewards.amount.u128(), 45); + } + + mod msg { + use cosmwasm_std::{coins, QuerierWrapper}; + use serde::de::DeserializeOwned; + + use super::*; + + // shortens tests a bit + struct TestEnv { + api: MockApi, + store: MockStorage, + router: BasicRouter, + block: BlockInfo, + } + + impl TestEnv { + fn wrap(tuple: (MockApi, MockStorage, BasicRouter, BlockInfo, Addr)) -> (Self, Addr) { + ( + Self { + api: tuple.0, + store: tuple.1, + router: tuple.2, + block: tuple.3, + }, + tuple.4, + ) + } + } + + fn execute_stake( + env: &mut TestEnv, + sender: Addr, + msg: StakingMsg, + ) -> AnyResult { + env.router.staking.execute( + &env.api, + &mut env.store, + &env.router, + &env.block, + sender, + msg, + ) + } + + fn query_stake(env: &TestEnv, msg: StakingQuery) -> AnyResult { + Ok(from_json(env.router.staking.query( + &env.api, + &env.store, + &env.router.querier(&env.api, &env.store, &env.block), + &env.block, + msg, + )?)?) + } + + fn execute_distr( + env: &mut TestEnv, + sender: Addr, + msg: DistributionMsg, + ) -> AnyResult { + env.router.distribution.execute( + &env.api, + &mut env.store, + &env.router, + &env.block, + sender, + msg, + ) + } + + fn query_bank(env: &TestEnv, msg: BankQuery) -> AnyResult { + Ok(from_json(env.router.bank.query( + &env.api, + &env.store, + &env.router.querier(&env.api, &env.store, &env.block), + &env.block, + msg, + )?)?) + } + + fn assert_balances(env: &TestEnv, balances: impl IntoIterator) { + for (addr, amount) in balances { + let balance: BalanceResponse = query_bank( + env, + BankQuery::Balance { + address: addr.to_string(), + denom: "TOKEN".to_string(), + }, + ) + .unwrap(); + assert_eq!(balance.amount.amount.u128(), amount); + } + } + + #[test] + fn execute() { + // test all execute msgs + let (mut test_env, validator1) = + TestEnv::wrap(setup_test_env(Decimal::percent(10), Decimal::percent(10))); + + let delegator1 = test_env.api.addr_make("delegator1"); + let reward_receiver = test_env.api.addr_make("rewardreceiver"); + + // fund delegator1 account + test_env + .router + .bank + .init_balance(&mut test_env.store, &delegator1, vec![coin(1000, "TOKEN")]) + .unwrap(); + + // add second validator + let validator2 = test_env.api.addr_make("validator2"); + test_env + .router + .staking + .add_validator( + &test_env.api, + &mut test_env.store, + &test_env.block, + Validator::new( + validator2.to_string(), + Decimal::zero(), + Decimal::percent(20), + Decimal::percent(1), + ), + ) + .unwrap(); + + // delegate 100 tokens to validator1 + execute_stake( + &mut test_env, + delegator1.clone(), + StakingMsg::Delegate { + validator: validator1.to_string(), + amount: coin(100, "TOKEN"), + }, + ) + .unwrap(); + + // should now have 100 tokens less + assert_balances(&test_env, vec![(delegator1.clone(), 900)]); + + // wait a year + test_env.block.time = test_env.block.time.plus_seconds(60 * 60 * 24 * 365); + + // change the withdrawal address + execute_distr( + &mut test_env, + delegator1.clone(), + DistributionMsg::SetWithdrawAddress { + address: reward_receiver.to_string(), + }, + ) + .unwrap(); + + // withdraw rewards + execute_distr( + &mut test_env, + delegator1.clone(), + DistributionMsg::WithdrawDelegatorReward { + validator: validator1.to_string(), + }, + ) + .unwrap(); + + // withdrawal address received rewards. + assert_balances( + &test_env, + // one year, 10%apr, 10% commission, 100 tokens staked + vec![(reward_receiver, 100 / 10 * 9 / 10)], + ); + + // redelegate to validator2 + execute_stake( + &mut test_env, + delegator1.clone(), + StakingMsg::Redelegate { + src_validator: validator1.to_string(), + dst_validator: validator2.to_string(), + amount: coin(100, "TOKEN"), + }, + ) + .unwrap(); + + // should have same amount as before (rewards receiver received rewards). + assert_balances(&test_env, vec![(delegator1.clone(), 900)]); + + let delegations: AllDelegationsResponse = query_stake( + &test_env, + StakingQuery::AllDelegations { + delegator: delegator1.to_string(), + }, + ) + .unwrap(); + assert_eq!( + delegations.delegations, + [Delegation::new( + delegator1.clone(), + validator2.to_string(), + coin(100, "TOKEN"), + )] + ); + + // undelegate all tokens + execute_stake( + &mut test_env, + delegator1.clone(), + StakingMsg::Undelegate { + validator: validator2.to_string(), + amount: coin(100, "TOKEN"), + }, + ) + .unwrap(); + + // wait for unbonding period (60 seconds in default config) + test_env.block.time = test_env.block.time.plus_seconds(60); + + // need to manually cause queue to get processed + test_env + .router + .staking + .process_queue( + &test_env.api, + &mut test_env.store, + &test_env.router, + &test_env.block, + ) + .unwrap(); + + // check bank balance + assert_balances(&test_env, vec![(delegator1.clone(), 1000)]); + } + + #[test] + fn can_set_withdraw_address() { + let (mut test_env, validator) = + TestEnv::wrap(setup_test_env(Decimal::percent(10), Decimal::percent(10))); + + let delegator = test_env.api.addr_make("delegator"); + let reward_receiver = test_env.api.addr_make("rewardreceiver"); + + test_env + .router + .bank + .init_balance(&mut test_env.store, &delegator, coins(100, "TOKEN")) + .unwrap(); + + // Stake 100 tokens to the validator. + execute_stake( + &mut test_env, + delegator.clone(), + StakingMsg::Delegate { + validator: validator.to_string(), + amount: coin(100, "TOKEN"), + }, + ) + .unwrap(); + + // Change rewards receiver. + execute_distr( + &mut test_env, + delegator.clone(), + DistributionMsg::SetWithdrawAddress { + address: reward_receiver.to_string(), + }, + ) + .unwrap(); + + // A year passes. + test_env.block.time = test_env.block.time.plus_seconds(60 * 60 * 24 * 365); + + // Withdraw rewards to reward receiver. + execute_distr( + &mut test_env, + delegator.clone(), + DistributionMsg::WithdrawDelegatorReward { + validator: validator.to_string(), + }, + ) + .unwrap(); + + // Change reward receiver back to delegator. + execute_distr( + &mut test_env, + delegator.clone(), + DistributionMsg::SetWithdrawAddress { + address: delegator.to_string(), + }, + ) + .unwrap(); + + // Another year passes. + test_env.block.time = test_env.block.time.plus_seconds(60 * 60 * 24 * 365); + + // Withdraw rewards to delegator. + execute_distr( + &mut test_env, + delegator.clone(), + DistributionMsg::WithdrawDelegatorReward { + validator: validator.to_string(), + }, + ) + .unwrap(); + + // one year, 10%apr, 10% commission, 100 tokens staked + let rewards_yr = 100 / 10 * 9 / 10; + + assert_balances( + &test_env, + vec![(reward_receiver, rewards_yr), (delegator, rewards_yr)], + ); + } + + #[test] + fn cannot_steal() { + let (mut test_env, validator1) = + TestEnv::wrap(setup_test_env(Decimal::percent(10), Decimal::percent(10))); + + let delegator1 = test_env.api.addr_make("delegator1"); + + // fund delegator1 account + test_env + .router + .bank + .init_balance(&mut test_env.store, &delegator1, vec![coin(100, "TOKEN")]) + .unwrap(); + + // delegate 100 tokens to validator1 + execute_stake( + &mut test_env, + delegator1.clone(), + StakingMsg::Delegate { + validator: validator1.to_string(), + amount: coin(100, "TOKEN"), + }, + ) + .unwrap(); + + // undelegate more tokens than we have + let e = execute_stake( + &mut test_env, + delegator1.clone(), + StakingMsg::Undelegate { + validator: validator1.to_string(), + amount: coin(200, "TOKEN"), + }, + ) + .unwrap_err(); + + assert_eq!(e.to_string(), "invalid shares amount"); + + // add second validator + let validator2 = test_env.api.addr_make("validator2"); + test_env + .router + .staking + .add_validator( + &test_env.api, + &mut test_env.store, + &test_env.block, + Validator::new( + validator2.to_string(), + Decimal::zero(), + Decimal::percent(20), + Decimal::percent(1), + ), + ) + .unwrap(); + + // redelegate more tokens than we have + let e = execute_stake( + &mut test_env, + delegator1.clone(), + StakingMsg::Redelegate { + src_validator: validator1.to_string(), + dst_validator: validator2.to_string(), + amount: coin(200, "TOKEN"), + }, + ) + .unwrap_err(); + assert_eq!(e.to_string(), "invalid shares amount"); + + // undelegate from non-existing delegation + let e = execute_stake( + &mut test_env, + delegator1.clone(), + StakingMsg::Undelegate { + validator: validator2.to_string(), + amount: coin(100, "TOKEN"), + }, + ) + .unwrap_err(); + assert_eq!( + e.to_string(), + "no delegation for (address, validator) tuple" + ); + } + + #[test] + fn denom_validation() { + let (mut test_env, validator_addr) = + TestEnv::wrap(setup_test_env(Decimal::percent(10), Decimal::percent(10))); + + let delegator_addr = test_env.api.addr_make("delegator"); + + // fund delegator1 account + test_env + .router + .bank + .init_balance( + &mut test_env.store, + &delegator_addr, + vec![coin(100, "FAKE")], + ) + .unwrap(); + + // try to delegate 100 to validator + let e = execute_stake( + &mut test_env, + delegator_addr.clone(), + StakingMsg::Delegate { + validator: validator_addr.to_string(), + amount: coin(100, "FAKE"), + }, + ) + .unwrap_err(); + + assert_eq!( + e.to_string(), + "cannot delegate coins of denominator FAKE, only of TOKEN", + ); + } + + #[test] + fn cannot_slash_nonexistent() { + let (mut test_env, _) = + TestEnv::wrap(setup_test_env(Decimal::percent(10), Decimal::percent(10))); + + let delegator = test_env.api.addr_make("delegator"); + let non_existing_validator = test_env.api.addr_make("nonexistingvaloper"); + + // fund delegator1 account + test_env + .router + .bank + .init_balance(&mut test_env.store, &delegator, vec![coin(100, "FAKE")]) + .unwrap(); + + // try to delegate 100 to validator1 + let e = test_env + .router + .staking + .sudo( + &test_env.api, + &mut test_env.store, + &test_env.router, + &test_env.block, + StakingSudo::Slash { + validator: non_existing_validator.to_string(), + percentage: Decimal::percent(50), + }, + ) + .unwrap_err(); + assert_eq!(e.to_string(), "validator does not exist"); + } + + #[test] + fn non_existent_validator() { + let (mut test_env, _) = + TestEnv::wrap(setup_test_env(Decimal::percent(10), Decimal::percent(10))); + + let delegator = test_env.api.addr_make("delegator1"); + let validator = test_env.api.addr_make("testvaloper2"); + + // init balances + test_env + .router + .bank + .init_balance(&mut test_env.store, &delegator, vec![coin(100, "TOKEN")]) + .unwrap(); + + // try to delegate + let err = execute_stake( + &mut test_env, + delegator.clone(), + StakingMsg::Delegate { + validator: validator.to_string(), + amount: coin(100, "TOKEN"), + }, + ) + .unwrap_err(); + assert_eq!(err.to_string(), "validator does not exist"); + + // try to undelegate + let err = execute_stake( + &mut test_env, + delegator.clone(), + StakingMsg::Undelegate { + validator: validator.to_string(), + amount: coin(100, "TOKEN"), + }, + ) + .unwrap_err(); + assert_eq!(err.to_string(), "validator does not exist"); + } + + #[test] + fn zero_staking_forbidden() { + let (mut test_env, validator) = + TestEnv::wrap(setup_test_env(Decimal::percent(10), Decimal::percent(10))); + + let delegator_addr = test_env.api.addr_make("delegator"); + + // delegate 0 + let err = execute_stake( + &mut test_env, + delegator_addr.clone(), + StakingMsg::Delegate { + validator: validator.to_string(), + amount: coin(0, "TOKEN"), + }, + ) + .unwrap_err(); + assert_eq!(err.to_string(), "invalid delegation amount"); + + // undelegate 0 + let err = execute_stake( + &mut test_env, + delegator_addr, + StakingMsg::Undelegate { + validator: validator.to_string(), + amount: coin(0, "TOKEN"), + }, + ) + .unwrap_err(); + assert_eq!(err.to_string(), "invalid shares amount"); + } + + #[test] + fn query_staking() { + // run all staking queries + let (mut test_env, validator1) = + TestEnv::wrap(setup_test_env(Decimal::percent(10), Decimal::percent(10))); + let delegator1 = test_env.api.addr_make("delegator1"); + let delegator2 = test_env.api.addr_make("delegator2"); + let validator2 = test_env.api.addr_make("testvaloper2"); + let not_validator = test_env.api.addr_make("notvaloper"); + + // init balances + test_env + .router + .bank + .init_balance(&mut test_env.store, &delegator1, vec![coin(260, "TOKEN")]) + .unwrap(); + test_env + .router + .bank + .init_balance(&mut test_env.store, &delegator2, vec![coin(150, "TOKEN")]) + .unwrap(); + + // add another validator + let valoper2 = Validator::new( + validator2.to_string(), + Decimal::percent(0), + Decimal::percent(1), + Decimal::percent(1), + ); + test_env + .router + .staking + .add_validator( + &test_env.api, + &mut test_env.store, + &test_env.block, + valoper2.clone(), + ) + .unwrap(); + + // query validators + let valoper1: ValidatorResponse = query_stake( + &test_env, + StakingQuery::Validator { + address: validator1.to_string(), + }, + ) + .unwrap(); + let validators: AllValidatorsResponse = + query_stake(&test_env, StakingQuery::AllValidators {}).unwrap(); + assert_eq!( + validators.validators, + [valoper1.validator.unwrap(), valoper2] + ); + // query non-existent validator + let response = query_stake::( + &test_env, + StakingQuery::Validator { + address: not_validator.to_string(), + }, + ) + .unwrap(); + assert_eq!(response.validator, None); + + // query bonded denom + let response: BondedDenomResponse = + query_stake(&test_env, StakingQuery::BondedDenom {}).unwrap(); + assert_eq!(response.denom, "TOKEN"); + + // delegate some tokens with delegator1 and delegator2 + execute_stake( + &mut test_env, + delegator1.clone(), + StakingMsg::Delegate { + validator: validator1.to_string(), + amount: coin(100, "TOKEN"), + }, + ) + .unwrap(); + execute_stake( + &mut test_env, + delegator1.clone(), + StakingMsg::Delegate { + validator: validator2.to_string(), + amount: coin(160, "TOKEN"), + }, + ) + .unwrap(); + execute_stake( + &mut test_env, + delegator2.clone(), + StakingMsg::Delegate { + validator: validator1.to_string(), + amount: coin(150, "TOKEN"), + }, + ) + .unwrap(); + // unstake some again + execute_stake( + &mut test_env, + delegator1.clone(), + StakingMsg::Undelegate { + validator: validator1.to_string(), + amount: coin(50, "TOKEN"), + }, + ) + .unwrap(); + execute_stake( + &mut test_env, + delegator2.clone(), + StakingMsg::Undelegate { + validator: validator1.to_string(), + amount: coin(50, "TOKEN"), + }, + ) + .unwrap(); + + // query all delegations + let response1: AllDelegationsResponse = query_stake( + &test_env, + StakingQuery::AllDelegations { + delegator: delegator1.to_string(), + }, + ) + .unwrap(); + assert_eq!( + response1.delegations, + vec![ + Delegation::new( + delegator1.clone(), + validator1.to_string(), + coin(50, "TOKEN"), + ), + Delegation::new( + delegator1.clone(), + validator2.to_string(), + coin(160, "TOKEN"), + ), + ] + ); + let response2: DelegationResponse = query_stake( + &test_env, + StakingQuery::Delegation { + delegator: delegator2.to_string(), + validator: validator1.to_string(), + }, + ) + .unwrap(); + assert_eq!( + response2.delegation.unwrap(), + FullDelegation::new( + delegator2.clone(), + validator1.to_string(), + coin(100, "TOKEN"), + coin(100, "TOKEN"), + vec![], + ), + ); + } + + #[test] + fn delegation_queries_unbonding() { + // run all staking queries + let (mut test_env, validator) = + TestEnv::wrap(setup_test_env(Decimal::percent(10), Decimal::percent(10))); + let delegator1 = test_env.api.addr_make("delegator1"); + let delegator2 = test_env.api.addr_make("delegator2"); + + // init balances + test_env + .router + .bank + .init_balance(&mut test_env.store, &delegator1, vec![coin(100, "TOKEN")]) + .unwrap(); + test_env + .router + .bank + .init_balance(&mut test_env.store, &delegator2, vec![coin(150, "TOKEN")]) + .unwrap(); + + // delegate some tokens with delegator1 and delegator2 + execute_stake( + &mut test_env, + delegator1.clone(), + StakingMsg::Delegate { + validator: validator.to_string(), + amount: coin(100, "TOKEN"), + }, + ) + .unwrap(); + execute_stake( + &mut test_env, + delegator2.clone(), + StakingMsg::Delegate { + validator: validator.to_string(), + amount: coin(150, "TOKEN"), + }, + ) + .unwrap(); + // unstake some of delegator1's stake + execute_stake( + &mut test_env, + delegator1.clone(), + StakingMsg::Undelegate { + validator: validator.to_string(), + amount: coin(50, "TOKEN"), + }, + ) + .unwrap(); + // unstake all of delegator2's stake + execute_stake( + &mut test_env, + delegator2.clone(), + StakingMsg::Undelegate { + validator: validator.to_string(), + amount: coin(150, "TOKEN"), + }, + ) + .unwrap(); + + // query all delegations + let response1: AllDelegationsResponse = query_stake( + &test_env, + StakingQuery::AllDelegations { + delegator: delegator1.to_string(), + }, + ) + .unwrap(); + assert_eq!( + response1.delegations, + vec![Delegation::new( + delegator1.clone(), + validator.to_string(), + coin(50, "TOKEN"), + )] + ); + let response2: DelegationResponse = query_stake( + &test_env, + StakingQuery::Delegation { + delegator: delegator2.to_string(), + validator: validator.to_string(), + }, + ) + .unwrap(); + assert_eq!(response2.delegation, None); + + // unstake rest of delegator1's stake in two steps + execute_stake( + &mut test_env, + delegator1.clone(), + StakingMsg::Undelegate { + validator: validator.to_string(), + amount: coin(25, "TOKEN"), + }, + ) + .unwrap(); + test_env.block.time = test_env.block.time.plus_seconds(10); + execute_stake( + &mut test_env, + delegator1.clone(), + StakingMsg::Undelegate { + validator: validator.to_string(), + amount: coin(25, "TOKEN"), + }, + ) + .unwrap(); + + // query all delegations again + let response1: DelegationResponse = query_stake( + &test_env, + StakingQuery::Delegation { + delegator: delegator1.to_string(), + validator: validator.to_string(), + }, + ) + .unwrap(); + let response2: AllDelegationsResponse = query_stake( + &test_env, + StakingQuery::AllDelegations { + delegator: delegator1.to_string(), + }, + ) + .unwrap(); + assert_eq!( + response1.delegation, None, + "delegator1 should have no delegations left" + ); + assert_eq!(response2.delegations, vec![]); + } + + #[test] + fn partial_unbonding_reduces_stake() { + let (mut test_env, validator) = + TestEnv::wrap(setup_test_env(Decimal::percent(10), Decimal::percent(10))); + let delegator = test_env.api.addr_make("delegator1"); + + // init balance + test_env + .router + .bank + .init_balance(&mut test_env.store, &delegator, vec![coin(100, "TOKEN")]) + .unwrap(); + + // delegate all tokens + execute_stake( + &mut test_env, + delegator.clone(), + StakingMsg::Delegate { + validator: validator.to_string(), + amount: coin(100, "TOKEN"), + }, + ) + .unwrap(); + // unstake in multiple steps + execute_stake( + &mut test_env, + delegator.clone(), + StakingMsg::Undelegate { + validator: validator.to_string(), + amount: coin(50, "TOKEN"), + }, + ) + .unwrap(); + test_env.block.time = test_env.block.time.plus_seconds(10); + execute_stake( + &mut test_env, + delegator.clone(), + StakingMsg::Undelegate { + validator: validator.to_string(), + amount: coin(30, "TOKEN"), + }, + ) + .unwrap(); + test_env.block.time = test_env.block.time.plus_seconds(10); + execute_stake( + &mut test_env, + delegator.clone(), + StakingMsg::Undelegate { + validator: validator.to_string(), + amount: coin(20, "TOKEN"), + }, + ) + .unwrap(); + + // wait for first unbonding to complete (but not the others) and process queue + test_env.block.time = test_env.block.time.plus_seconds(40); + test_env + .router + .staking + .process_queue( + &test_env.api, + &mut test_env.store, + &test_env.router, + &test_env.block, + ) + .unwrap(); + + // query delegations + // we now have 0 stake, 50 unbonding and 50 completed unbonding + let response1: DelegationResponse = query_stake( + &test_env, + StakingQuery::Delegation { + delegator: delegator.to_string(), + validator: validator.to_string(), + }, + ) + .unwrap(); + let response2: AllDelegationsResponse = query_stake( + &test_env, + StakingQuery::AllDelegations { + delegator: delegator.to_string(), + }, + ) + .unwrap(); + assert_eq!(response1.delegation, None); + assert_eq!(response2.delegations, vec![]); + + // wait for the rest to complete + test_env.block.time = test_env.block.time.plus_seconds(20); + test_env + .router + .staking + .process_queue( + &test_env.api, + &mut test_env.store, + &test_env.router, + &test_env.block, + ) + .unwrap(); + + // query delegations again + let response1: DelegationResponse = query_stake( + &test_env, + StakingQuery::Delegation { + delegator: delegator.to_string(), + validator: validator.to_string(), + }, + ) + .unwrap(); + let response2: AllDelegationsResponse = query_stake( + &test_env, + StakingQuery::AllDelegations { + delegator: delegator.to_string(), + }, + ) + .unwrap(); + assert_eq!( + response1.delegation, None, + "delegator should have nothing left" + ); + assert!(response2.delegations.is_empty()); + } + + #[test] + fn delegations_slashed() { + // run all staking queries + let (mut test_env, validator) = + TestEnv::wrap(setup_test_env(Decimal::percent(10), Decimal::percent(10))); + let delegator = test_env.api.addr_make("delegator"); + + // init balance + test_env + .router + .bank + .init_balance(&mut test_env.store, &delegator, vec![coin(333, "TOKEN")]) + .unwrap(); + + // delegate some tokens + execute_stake( + &mut test_env, + delegator.clone(), + StakingMsg::Delegate { + validator: validator.to_string(), + amount: coin(333, "TOKEN"), + }, + ) + .unwrap(); + // unstake some + execute_stake( + &mut test_env, + delegator.clone(), + StakingMsg::Undelegate { + validator: validator.to_string(), + amount: coin(111, "TOKEN"), + }, + ) + .unwrap(); + + // slash validator + test_env + .router + .staking + .sudo( + &test_env.api, + &mut test_env.store, + &test_env.router, + &test_env.block, + StakingSudo::Slash { + validator: validator.to_string(), + percentage: Decimal::percent(50), + }, + ) + .unwrap(); + + // query all delegations + let response1: AllDelegationsResponse = query_stake( + &test_env, + StakingQuery::AllDelegations { + delegator: delegator.to_string(), + }, + ) + .unwrap(); + assert_eq!( + response1.delegations[0], + Delegation::new(delegator.clone(), validator.to_string(), coin(111, "TOKEN"),) + ); + + // wait until unbonding is complete and check if amount was slashed + test_env.block.time = test_env.block.time.plus_seconds(60); + test_env + .router + .staking + .process_queue( + &test_env.api, + &mut test_env.store, + &test_env.router, + &test_env.block, + ) + .unwrap(); + let balance = QuerierWrapper::::new(&test_env.router.querier( + &test_env.api, + &test_env.store, + &test_env.block, + )) + .query_balance(delegator, "TOKEN") + .unwrap(); + assert_eq!(balance.amount.u128(), 55); + } + + #[test] + fn rewards_initial_wait() { + let (mut test_env, validator) = + TestEnv::wrap(setup_test_env(Decimal::percent(10), Decimal::zero())); + let delegator = test_env.api.addr_make("delegator"); + + // init balance + test_env + .router + .bank + .init_balance(&mut test_env.store, &delegator, vec![coin(100, "TOKEN")]) + .unwrap(); + + // wait a year before staking + const YEAR: u64 = 60 * 60 * 24 * 365; + test_env.block.time = test_env.block.time.plus_seconds(YEAR); + + // delegate some tokens + execute_stake( + &mut test_env, + delegator.clone(), + StakingMsg::Delegate { + validator: validator.to_string(), + amount: coin(100, "TOKEN"), + }, + ) + .unwrap(); + + // wait another year + test_env.block.time = test_env.block.time.plus_seconds(YEAR); + + // query rewards + let response: DelegationResponse = query_stake( + &test_env, + StakingQuery::Delegation { + delegator: delegator.to_string(), + validator: validator.to_string(), + }, + ) + .unwrap(); + assert_eq!( + response.delegation.unwrap().accumulated_rewards, + vec![coin(10, "TOKEN")] // 10% of 100 + ); + } } } diff --git a/src/stargate.rs b/src/stargate.rs new file mode 100644 index 00000000..7228d8a4 --- /dev/null +++ b/src/stargate.rs @@ -0,0 +1,145 @@ +//! # Handler for `CosmosMsg::Stargate`, `CosmosMsg::Any`, `QueryRequest::Stargate` and `QueryRequest::Grpc` messages + +use crate::error::AnyResult; +use crate::{AppResponse, CosmosRouter}; +use anyhow::bail; +use cosmwasm_std::{ + to_json_binary, Addr, AnyMsg, Api, Binary, BlockInfo, CustomMsg, CustomQuery, Empty, GrpcQuery, + Querier, Storage, +}; +use serde::de::DeserializeOwned; + +/// Interface of handlers for processing `Stargate`/`Any` message variants +/// and `Stargate`/`Grpc` queries. +pub trait Stargate { + /// Processes `CosmosMsg::Stargate` message variant. + fn execute_stargate( + &self, + _api: &dyn Api, + _storage: &mut dyn Storage, + _router: &dyn CosmosRouter, + _block: &BlockInfo, + sender: Addr, + type_url: String, + value: Binary, + ) -> AnyResult + where + ExecC: CustomMsg + DeserializeOwned + 'static, + QueryC: CustomQuery + DeserializeOwned + 'static, + { + bail!( + "Unexpected stargate execute: type_url={}, value={} from {}", + type_url, + value, + sender, + ) + } + + /// Processes `QueryRequest::Stargate` query. + fn query_stargate( + &self, + _api: &dyn Api, + _storage: &dyn Storage, + _querier: &dyn Querier, + _block: &BlockInfo, + path: String, + data: Binary, + ) -> AnyResult { + bail!("Unexpected stargate query: path={}, data={}", path, data) + } + + /// Processes `CosmosMsg::Any` message variant. + fn execute_any( + &self, + _api: &dyn Api, + _storage: &mut dyn Storage, + _router: &dyn CosmosRouter, + _block: &BlockInfo, + sender: Addr, + msg: AnyMsg, + ) -> AnyResult + where + ExecC: CustomMsg + DeserializeOwned + 'static, + QueryC: CustomQuery + DeserializeOwned + 'static, + { + bail!("Unexpected any execute: msg={:?} from {}", msg, sender) + } + + /// Processes `QueryRequest::Grpc` query. + fn query_grpc( + &self, + _api: &dyn Api, + _storage: &dyn Storage, + _querier: &dyn Querier, + _block: &BlockInfo, + request: GrpcQuery, + ) -> AnyResult { + bail!("Unexpected grpc query: request={:?}", request) + } +} + +/// Always failing handler for `Stargate`/`Any` message variants and `Stargate`/`Grpc` queries. +pub struct StargateFailing; + +impl Stargate for StargateFailing {} + +/// Always accepting handler for `Stargate`/`Any` message variants and `Stargate`/`Grpc` queries. +pub struct StargateAccepting; + +impl Stargate for StargateAccepting { + fn execute_stargate( + &self, + _api: &dyn Api, + _storage: &mut dyn Storage, + _router: &dyn CosmosRouter, + _block: &BlockInfo, + _sender: Addr, + _type_url: String, + _value: Binary, + ) -> AnyResult + where + ExecC: CustomMsg + DeserializeOwned + 'static, + QueryC: CustomQuery + DeserializeOwned + 'static, + { + Ok(AppResponse::default()) + } + + fn query_stargate( + &self, + _api: &dyn Api, + _storage: &dyn Storage, + _querier: &dyn Querier, + _block: &BlockInfo, + _path: String, + _data: Binary, + ) -> AnyResult { + to_json_binary(&Empty {}).map_err(Into::into) + } + + fn execute_any( + &self, + _api: &dyn Api, + _storage: &mut dyn Storage, + _router: &dyn CosmosRouter, + _block: &BlockInfo, + _sender: Addr, + _msg: AnyMsg, + ) -> AnyResult + where + ExecC: CustomMsg + DeserializeOwned + 'static, + QueryC: CustomQuery + DeserializeOwned + 'static, + { + Ok(AppResponse::default()) + } + + fn query_grpc( + &self, + _api: &dyn Api, + _storage: &dyn Storage, + _querier: &dyn Querier, + _block: &BlockInfo, + _request: GrpcQuery, + ) -> AnyResult { + Ok(Binary::default()) + } +} diff --git a/src/test_helpers/caller.rs b/src/test_helpers/caller.rs index c283cda5..1d50a62a 100644 --- a/src/test_helpers/caller.rs +++ b/src/test_helpers/caller.rs @@ -1,9 +1,7 @@ use crate::{Contract, ContractWrapper}; use cosmwasm_std::{ - Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response, StdError, SubMsg, WasmMsg, + Binary, CustomMsg, Deps, DepsMut, Empty, Env, MessageInfo, Response, StdError, SubMsg, WasmMsg, }; -use schemars::JsonSchema; -use std::fmt::Debug; fn instantiate( _deps: DepsMut, @@ -33,7 +31,7 @@ fn query(_deps: Deps, _env: Env, _msg: Empty) -> Result { pub fn contract() -> Box> where - C: Clone + Debug + PartialEq + JsonSchema + 'static, + C: CustomMsg + 'static, { let contract = ContractWrapper::new_with_empty(execute, instantiate, query); Box::new(contract) diff --git a/src/test_helpers/echo.rs b/src/test_helpers/echo.rs index 02ab2696..884df65c 100644 --- a/src/test_helpers/echo.rs +++ b/src/test_helpers/echo.rs @@ -1,12 +1,12 @@ //! Very simple echoing contract which just returns incoming string if any, //! but performing sub call of given message to test response. //! -//! Additionally it bypasses all events and attributes send to it. +//! Additionally, it bypasses all events and attributes send to it. use crate::{Contract, ContractWrapper}; use cosmwasm_std::{ - to_json_binary, Attribute, Binary, Deps, DepsMut, Empty, Env, Event, MessageInfo, Reply, - Response, StdError, SubMsg, SubMsgResponse, SubMsgResult, + to_json_binary, Attribute, Binary, CustomMsg, Deps, DepsMut, Empty, Env, Event, MessageInfo, + Reply, Response, StdError, SubMsg, SubMsgResponse, SubMsgResult, }; use cw_utils::{parse_execute_response_data, parse_instantiate_response_data}; use derivative::Derivative; @@ -87,7 +87,7 @@ fn query(_deps: Deps, _env: Env, msg: Empty) -> Result { to_json_binary(&msg) } -#[allow(clippy::unnecessary_wraps)] +#[allow(clippy::unnecessary_wraps, deprecated)] fn reply(_deps: DepsMut, _env: Env, msg: Reply) -> Result, StdError> where ExecC: Debug + PartialEq + Clone + JsonSchema + 'static, @@ -98,6 +98,7 @@ where result: SubMsgResult::Ok(SubMsgResponse { data: Some(data), .. }), + .. } = msg { // We parse out the WasmMsg::Execute wrapper... @@ -130,7 +131,7 @@ pub fn contract() -> Box> { pub fn custom_contract() -> Box> where - C: Clone + Debug + PartialEq + JsonSchema + DeserializeOwned + 'static, + C: CustomMsg + DeserializeOwned + 'static, { let contract = ContractWrapper::new(execute::, instantiate::, query).with_reply(reply::); diff --git a/src/test_helpers/error.rs b/src/test_helpers/error.rs index 033853de..1654440a 100644 --- a/src/test_helpers/error.rs +++ b/src/test_helpers/error.rs @@ -1,7 +1,5 @@ use crate::{Contract, ContractWrapper}; -use cosmwasm_std::{Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response, StdError}; -use schemars::JsonSchema; -use std::fmt::Debug; +use cosmwasm_std::{Binary, CustomMsg, Deps, DepsMut, Empty, Env, MessageInfo, Response, StdError}; fn instantiate_err( _deps: DepsMut, @@ -36,7 +34,7 @@ fn query(_deps: Deps, _env: Env, _msg: Empty) -> Result { pub fn contract(instantiable: bool) -> Box> where - C: Clone + Debug + PartialEq + JsonSchema + 'static, + C: CustomMsg + 'static, { let contract = if instantiable { ContractWrapper::new_with_empty(execute, instantiate_ok, query) diff --git a/src/test_helpers/gov.rs b/src/test_helpers/gov.rs new file mode 100644 index 00000000..0c885c3a --- /dev/null +++ b/src/test_helpers/gov.rs @@ -0,0 +1,27 @@ +use crate::{Contract, ContractWrapper}; +use cosmwasm_std::{ + Binary, CosmosMsg, Deps, DepsMut, Empty, Env, GovMsg, MessageInfo, Response, StdResult, +}; + +fn instantiate(_deps: DepsMut, _env: Env, _info: MessageInfo, _msg: Empty) -> StdResult { + Ok(Response::new()) +} + +fn execute(_deps: DepsMut, _env: Env, _info: MessageInfo, _msg: Empty) -> StdResult { + let msg: CosmosMsg = GovMsg::Vote { + proposal_id: 1, + option: cosmwasm_std::VoteOption::No, + } + .into(); + let resp = Response::new().add_message(msg); + Ok(resp) +} + +fn query(_deps: Deps, _env: Env, _msg: Empty) -> StdResult { + Ok(Binary::default()) +} + +pub fn contract() -> Box> { + let contract = ContractWrapper::new(execute, instantiate, query); + Box::new(contract) +} diff --git a/src/test_helpers/hackatom.rs b/src/test_helpers/hackatom.rs index 394c7351..95df71ba 100644 --- a/src/test_helpers/hackatom.rs +++ b/src/test_helpers/hackatom.rs @@ -2,10 +2,10 @@ use crate::{Contract, ContractWrapper}; use cosmwasm_std::{ - to_json_binary, BankMsg, Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response, StdError, + to_json_binary, BankMsg, Binary, CustomMsg, Deps, DepsMut, Empty, Env, MessageInfo, Response, + StdError, }; use cw_storage_plus::Item; -use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::fmt::Debug; @@ -16,7 +16,7 @@ pub struct InstantiateMsg { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct MigrateMsg { - // just use some other string so we see there are other types + // just use some other string, so we see there are other types pub new_guy: String, } @@ -77,7 +77,7 @@ pub fn contract() -> Box> { #[allow(dead_code)] pub fn custom_contract() -> Box> where - C: Clone + Debug + PartialEq + JsonSchema + 'static, + C: CustomMsg + 'static, { let contract = ContractWrapper::new_with_empty(execute, instantiate, query).with_migrate_empty(migrate); diff --git a/src/test_helpers/ibc.rs b/src/test_helpers/ibc.rs new file mode 100644 index 00000000..402edda6 --- /dev/null +++ b/src/test_helpers/ibc.rs @@ -0,0 +1,26 @@ +use crate::{Contract, ContractWrapper}; +use cosmwasm_std::{ + Binary, CosmosMsg, Deps, DepsMut, Empty, Env, IbcMsg, MessageInfo, Response, StdResult, +}; + +fn instantiate(_deps: DepsMut, _env: Env, _info: MessageInfo, _msg: Empty) -> StdResult { + Ok(Response::new()) +} + +fn execute(_deps: DepsMut, _env: Env, _info: MessageInfo, _msg: Empty) -> StdResult { + let msg: CosmosMsg = IbcMsg::CloseChannel { + channel_id: "channel".to_string(), + } + .into(); + let resp = Response::new().add_message(msg); + Ok(resp) +} + +fn query(_deps: Deps, _env: Env, _msg: Empty) -> StdResult { + Ok(Binary::default()) +} + +pub fn contract() -> Box> { + let contract = ContractWrapper::new(execute, instantiate, query); + Box::new(contract) +} diff --git a/src/test_helpers/mod.rs b/src/test_helpers/mod.rs index f67efbc5..d6ee1adc 100644 --- a/src/test_helpers/mod.rs +++ b/src/test_helpers/mod.rs @@ -1,5 +1,6 @@ #![cfg(test)] +use cosmwasm_std::CustomMsg; use cw_storage_plus::Item; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -7,7 +8,9 @@ use serde::{Deserialize, Serialize}; pub mod caller; pub mod echo; pub mod error; +pub mod gov; pub mod hackatom; +pub mod ibc; pub mod payout; pub mod reflect; pub mod stargate; @@ -15,10 +18,12 @@ pub mod stargate; /// Custom message for testing purposes. #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] #[serde(rename = "snake_case")] -pub enum CustomMsg { +pub enum CustomHelperMsg { SetName { name: String }, SetAge { age: u32 }, } +impl CustomMsg for CustomHelperMsg {} + /// Persisted counter for testing purposes. pub const COUNT: Item = Item::new("count"); diff --git a/src/test_helpers/payout.rs b/src/test_helpers/payout.rs index a1d13ea2..159f6cea 100644 --- a/src/test_helpers/payout.rs +++ b/src/test_helpers/payout.rs @@ -1,11 +1,10 @@ use crate::test_helpers::COUNT; use crate::{Contract, ContractWrapper}; use cosmwasm_std::{ - to_json_binary, BankMsg, Binary, Coin, Deps, DepsMut, Empty, Env, MessageInfo, Response, - StdError, + to_json_binary, BankMsg, Binary, Coin, CustomMsg, Deps, DepsMut, Empty, Env, MessageInfo, + Response, StdError, }; use cw_storage_plus::Item; -use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::fmt::Debug; @@ -76,7 +75,7 @@ fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result { pub fn contract() -> Box> where - C: Clone + Debug + PartialEq + JsonSchema + 'static, + C: CustomMsg + 'static, { let contract = ContractWrapper::new_with_empty(execute, instantiate, query).with_sudo_empty(sudo); diff --git a/src/test_helpers/reflect.rs b/src/test_helpers/reflect.rs index c7b37407..41b4396e 100644 --- a/src/test_helpers/reflect.rs +++ b/src/test_helpers/reflect.rs @@ -1,4 +1,4 @@ -use crate::test_helpers::{payout, CustomMsg, COUNT}; +use crate::test_helpers::{payout, CustomHelperMsg, COUNT}; use crate::{Contract, ContractWrapper}; use cosmwasm_std::{ to_json_binary, Binary, Deps, DepsMut, Empty, Env, Event, MessageInfo, Reply, Response, @@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct Message { - pub messages: Vec>, + pub messages: Vec>, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -25,7 +25,7 @@ fn instantiate( _env: Env, _info: MessageInfo, _msg: Empty, -) -> Result, StdError> { +) -> Result, StdError> { COUNT.save(deps.storage, &0)?; Ok(Response::default()) } @@ -35,7 +35,7 @@ fn execute( _env: Env, _info: MessageInfo, msg: Message, -) -> Result, StdError> { +) -> Result, StdError> { COUNT.update::<_, StdError>(deps.storage, |old| Ok(old + 1))?; Ok(Response::new().add_submessages(msg.messages)) @@ -55,7 +55,7 @@ fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result { } } -fn reply(deps: DepsMut, _env: Env, msg: Reply) -> Result, StdError> { +fn reply(deps: DepsMut, _env: Env, msg: Reply) -> Result, StdError> { REFLECT.save(deps.storage, msg.id, &msg)?; // add custom event here to test let event = Event::new("custom") @@ -64,7 +64,7 @@ fn reply(deps: DepsMut, _env: Env, msg: Reply) -> Result, St Ok(Response::new().add_event(event)) } -pub fn contract() -> Box> { +pub fn contract() -> Box> { let contract = ContractWrapper::new(execute, instantiate, query).with_reply(reply); Box::new(contract) } diff --git a/src/test_helpers/stargate.rs b/src/test_helpers/stargate.rs index 0a31efcb..a4165354 100644 --- a/src/test_helpers/stargate.rs +++ b/src/test_helpers/stargate.rs @@ -1,35 +1,19 @@ use crate::{Contract, ContractWrapper}; use cosmwasm_std::{ - Binary, CosmosMsg, Deps, DepsMut, Empty, Env, GovMsg, IbcMsg, MessageInfo, Response, StdResult, + Binary, CosmosMsg, Deps, DepsMut, Empty, Env, MessageInfo, Response, StdResult, }; -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum ExecMsg { - Ibc {}, - Gov {}, -} fn instantiate(_deps: DepsMut, _env: Env, _info: MessageInfo, _msg: Empty) -> StdResult { Ok(Response::new()) } -fn execute(_deps: DepsMut, _env: Env, _info: MessageInfo, msg: ExecMsg) -> StdResult { - let msg: CosmosMsg = if let ExecMsg::Ibc {} = msg { - IbcMsg::CloseChannel { - channel_id: "channel".to_string(), - } - .into() - } else { - GovMsg::Vote { - proposal_id: 1, - vote: cosmwasm_std::VoteOption::No, - } - .into() +fn execute(_deps: DepsMut, _env: Env, _info: MessageInfo, _msg: Empty) -> StdResult { + #[allow(deprecated)] + let msg = CosmosMsg::Stargate { + type_url: "/this.is.a.stargate.test.helper".to_string(), + value: Default::default(), }; - - let resp = Response::new().add_message(msg); - Ok(resp) + Ok(Response::new().add_message(msg)) } fn query(_deps: Deps, _env: Env, _msg: Empty) -> StdResult { diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 2a190c34..2f5d2092 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -2,5 +2,7 @@ mod test_app; mod test_custom_handler; +mod test_error; mod test_gov; mod test_ibc; +mod test_stargate; diff --git a/src/tests/test_app.rs b/src/tests/test_app.rs index dad2e1b6..7dc5b413 100644 --- a/src/tests/test_app.rs +++ b/src/tests/test_app.rs @@ -1,20 +1,20 @@ -use crate::app::no_init; use crate::custom_handler::CachingCustomHandler; use crate::error::{bail, AnyResult}; use crate::test_helpers::echo::EXECUTE_REPLY_BASE_ID; -use crate::test_helpers::{caller, echo, error, hackatom, payout, reflect, CustomMsg}; +use crate::test_helpers::{caller, echo, error, hackatom, payout, reflect, CustomHelperMsg}; use crate::transactions::{transactional, StorageTransaction}; use crate::wasm::ContractData; -use crate::AppBuilder; use crate::{ - custom_app, next_block, App, AppResponse, Bank, CosmosRouter, Distribution, Executor, Module, - Router, Staking, Wasm, WasmSudo, + custom_app, next_block, no_init, App, AppResponse, Bank, CosmosRouter, Distribution, Executor, + Module, Router, Staking, Wasm, WasmSudo, }; +use crate::{AppBuilder, IntoAddr}; use cosmwasm_std::testing::{mock_env, MockQuerier}; use cosmwasm_std::{ coin, coins, from_json, to_json_binary, Addr, AllBalanceResponse, Api, Attribute, BankMsg, - BankQuery, Binary, BlockInfo, Coin, CosmosMsg, CustomQuery, Empty, Event, OverflowError, - OverflowOperation, Querier, Reply, StdError, StdResult, Storage, SubMsg, WasmMsg, + BankQuery, Binary, BlockInfo, Coin, CosmosMsg, CustomMsg, CustomQuery, Empty, Event, + OverflowError, OverflowOperation, Querier, Reply, StdError, StdResult, Storage, SubMsg, + WasmMsg, }; use cw_storage_plus::Item; use cw_utils::parse_instantiate_response_data; @@ -29,7 +29,7 @@ fn get_balance( addr: &Addr, ) -> Vec where - CustomT::ExecT: Clone + Debug + PartialEq + JsonSchema + DeserializeOwned + 'static, + CustomT::ExecT: CustomMsg + DeserializeOwned + 'static, CustomT::QueryT: CustomQuery + DeserializeOwned + 'static, WasmT: Wasm, BankT: Bank, @@ -40,14 +40,14 @@ where app.wrap().query_all_balances(addr).unwrap() } -fn query_router( - router: &Router, +fn query_router( + router: &Router, api: &dyn Api, storage: &dyn Storage, rcpt: &Addr, ) -> Vec where - CustomT::ExecT: Clone + Debug + PartialEq + JsonSchema, + CustomT::ExecT: CustomMsg, CustomT::QueryT: CustomQuery + DeserializeOwned, WasmT: Wasm, BankT: Bank, @@ -73,7 +73,7 @@ fn query_app( rcpt: &Addr, ) -> Vec where - CustomT::ExecT: Debug + PartialEq + Clone + JsonSchema + DeserializeOwned + 'static, + CustomT::ExecT: CustomMsg + DeserializeOwned + 'static, CustomT::QueryT: CustomQuery + DeserializeOwned + 'static, WasmT: Wasm, BankT: Bank, @@ -91,35 +91,39 @@ where val.amount } +/// Utility function for generating user addresses. +fn addr_make(addr: &str) -> Addr { + addr.into_addr() +} + #[test] fn update_block() { let mut app = App::default(); - let BlockInfo { time, height, .. } = app.block_info(); app.update_block(next_block); - assert_eq!(time.plus_seconds(5), app.block_info().time); assert_eq!(height + 1, app.block_info().height); } #[test] fn multi_level_bank_cache() { + // prepare user addresses + let owner_addr = addr_make("owner"); + let recipient_addr = addr_make("recipient"); + // set personal balance - let owner = Addr::unchecked("owner"); - let rcpt = Addr::unchecked("recipient"); let init_funds = vec![coin(20, "btc"), coin(100, "eth")]; - let mut app = App::new(|router, _, storage| { router .bank - .init_balance(storage, &owner, init_funds) + .init_balance(storage, &owner_addr, init_funds) .unwrap(); }); // cache 1 - send some tokens let mut cache = StorageTransaction::new(app.storage()); let msg = BankMsg::Send { - to_address: rcpt.clone().into(), + to_address: recipient_addr.clone().into(), amount: coins(25, "eth"), }; app.router() @@ -127,31 +131,31 @@ fn multi_level_bank_cache() { app.api(), &mut cache, &app.block_info(), - owner.clone(), + owner_addr.clone(), msg.into(), ) .unwrap(); // shows up in cache - let cached_rcpt = query_router(app.router(), app.api(), &cache, &rcpt); + let cached_rcpt = query_router(app.router(), app.api(), &cache, &recipient_addr); assert_eq!(coins(25, "eth"), cached_rcpt); - let router_rcpt = query_app(&app, &rcpt); + let router_rcpt = query_app(&app, &recipient_addr); assert_eq!(router_rcpt, vec![]); // now, second level cache transactional(&mut cache, |cache2, read| { let msg = BankMsg::Send { - to_address: rcpt.clone().into(), + to_address: recipient_addr.clone().into(), amount: coins(12, "eth"), }; app.router() - .execute(app.api(), cache2, &app.block_info(), owner, msg.into()) + .execute(app.api(), cache2, &app.block_info(), owner_addr, msg.into()) .unwrap(); // shows up in 2nd cache - let cached_rcpt = query_router(app.router(), app.api(), read, &rcpt); + let cached_rcpt = query_router(app.router(), app.api(), read, &recipient_addr); assert_eq!(coins(25, "eth"), cached_rcpt); - let cached2_rcpt = query_router(app.router(), app.api(), cache2, &rcpt); + let cached2_rcpt = query_router(app.router(), app.api(), cache2, &recipient_addr); assert_eq!(coins(37, "eth"), cached2_rcpt); Ok(()) }) @@ -160,7 +164,7 @@ fn multi_level_bank_cache() { // apply first to router cache.prepare().commit(app.storage_mut()); - let committed = query_app(&app, &rcpt); + let committed = query_app(&app, &recipient_addr); assert_eq!(coins(37, "eth"), committed); } @@ -186,61 +190,64 @@ fn duplicate_contract_code() { #[test] fn send_tokens() { - let owner = Addr::unchecked("owner"); - let rcpt = Addr::unchecked("receiver"); + // prepare user addresses + let owner_addr = addr_make("owner"); + let recipient_addr = addr_make("recipient"); + + // set personal balance let init_funds = vec![coin(20, "btc"), coin(100, "eth")]; let rcpt_funds = vec![coin(5, "btc")]; - let mut app = App::new(|router, _, storage| { // initialization moved to App construction router .bank - .init_balance(storage, &owner, init_funds) + .init_balance(storage, &owner_addr, init_funds) .unwrap(); router .bank - .init_balance(storage, &rcpt, rcpt_funds) + .init_balance(storage, &recipient_addr, rcpt_funds) .unwrap(); }); // send both tokens let to_send = vec![coin(30, "eth"), coin(5, "btc")]; let msg: CosmosMsg = BankMsg::Send { - to_address: rcpt.clone().into(), + to_address: recipient_addr.clone().into(), amount: to_send, } .into(); - app.execute(owner.clone(), msg.clone()).unwrap(); - let rich = get_balance(&app, &owner); + app.execute(owner_addr.clone(), msg.clone()).unwrap(); + let rich = get_balance(&app, &owner_addr); assert_eq!(vec![coin(15, "btc"), coin(70, "eth")], rich); - let poor = get_balance(&app, &rcpt); + let poor = get_balance(&app, &recipient_addr); assert_eq!(vec![coin(10, "btc"), coin(30, "eth")], poor); // can send from other account (but funds will be deducted from sender) - app.execute(rcpt.clone(), msg).unwrap(); + app.execute(recipient_addr.clone(), msg).unwrap(); // cannot send too much let msg = BankMsg::Send { - to_address: rcpt.into(), + to_address: recipient_addr.into(), amount: coins(20, "btc"), } .into(); - app.execute(owner.clone(), msg).unwrap_err(); + app.execute(owner_addr.clone(), msg).unwrap_err(); - let rich = get_balance(&app, &owner); + let rich = get_balance(&app, &owner_addr); assert_eq!(vec![coin(15, "btc"), coin(70, "eth")], rich); } #[test] fn simple_contract() { + // prepare user addresses + let owner_addr = addr_make("owner"); + // set personal balance - let owner = Addr::unchecked("owner"); let init_funds = vec![coin(20, "btc"), coin(100, "eth")]; - let mut app = App::new(|router, _, storage| { router .bank - .init_balance(storage, &owner, init_funds) + .init_balance(storage, &owner_addr, init_funds) .unwrap(); }); @@ -253,7 +260,7 @@ fn simple_contract() { let contract_addr = app .instantiate_contract( code_id, - owner.clone(), + owner_addr.clone(), &msg, &coins(23, "eth"), "Payout", @@ -266,7 +273,7 @@ fn simple_contract() { contract_data, ContractData { code_id, - creator: owner.clone(), + creator: owner_addr.clone(), admin: None, label: "Payout".to_owned(), created: app.block_info().height @@ -274,20 +281,20 @@ fn simple_contract() { ); // sender funds deducted - let sender = get_balance(&app, &owner); + let sender = get_balance(&app, &owner_addr); assert_eq!(sender, vec![coin(20, "btc"), coin(77, "eth")]); // get contract address, has funds let funds = get_balance(&app, &contract_addr); assert_eq!(funds, coins(23, "eth")); // create empty account - let random = Addr::unchecked("random"); - let funds = get_balance(&app, &random); + let random_addr = app.api().addr_make("random"); + let funds = get_balance(&app, &random_addr); assert_eq!(funds, vec![]); // do one payout and see money coming in let res = app - .execute_contract(random.clone(), contract_addr.clone(), &Empty {}, &[]) + .execute_contract(random_addr.clone(), contract_addr.clone(), &Empty {}, &[]) .unwrap(); assert_eq!(3, res.events.len()); @@ -305,13 +312,13 @@ fn simple_contract() { // then the transfer event let expected_transfer = Event::new("transfer") - .add_attribute("recipient", "random") + .add_attribute("recipient", &random_addr) .add_attribute("sender", &contract_addr) .add_attribute("amount", "5eth"); assert_eq!(&expected_transfer, &res.events[2]); // random got cash - let funds = get_balance(&app, &random); + let funds = get_balance(&app, &random_addr); assert_eq!(funds, coins(5, "eth")); // contract lost it let funds = get_balance(&app, &contract_addr); @@ -320,14 +327,16 @@ fn simple_contract() { #[test] fn reflect_success() { + // prepare user addresses + let owner_addr = addr_make("owner"); + let random_addr = addr_make("random"); + // set personal balance - let owner = Addr::unchecked("owner"); let init_funds = vec![coin(20, "btc"), coin(100, "eth")]; - - let mut app = custom_app::(|router, _, storage| { + let mut app = custom_app::(|router, _, storage| { router .bank - .init_balance(storage, &owner, init_funds) + .init_balance(storage, &owner_addr, init_funds) .unwrap(); }); @@ -340,7 +349,7 @@ fn reflect_success() { let payout_addr = app .instantiate_contract( payout_id, - owner.clone(), + owner_addr.clone(), &msg, &coins(23, "eth"), "Payout", @@ -352,7 +361,7 @@ fn reflect_success() { let reflect_id = app.store_code(reflect::contract()); let reflect_addr = app - .instantiate_contract(reflect_id, owner, &Empty {}, &[], "Reflect", None) + .instantiate_contract(reflect_id, owner_addr, &Empty {}, &[], "Reflect", None) .unwrap(); // reflect account is empty @@ -375,7 +384,7 @@ fn reflect_success() { messages: vec![msg], }; let res = app - .execute_contract(Addr::unchecked("random"), reflect_addr.clone(), &msgs, &[]) + .execute_contract(random_addr, reflect_addr.clone(), &msgs, &[]) .unwrap(); // ensure the attributes were relayed from the sub-message @@ -426,11 +435,12 @@ fn reflect_success() { #[test] fn reflect_error() { + // prepare user addresses + let owner = addr_make("owner"); + // set personal balance - let owner = Addr::unchecked("owner"); let init_funds = vec![coin(20, "btc"), coin(100, "eth")]; - - let mut app = custom_app::(|router, _, storage| { + let mut app = custom_app::(|router, _, storage| { router .bank .init_balance(storage, &owner, init_funds) @@ -454,18 +464,18 @@ fn reflect_error() { // reflect has 40 eth let funds = get_balance(&app, &reflect_addr); assert_eq!(funds, coins(40, "eth")); - let random = Addr::unchecked("random"); + let random_addr = app.api().addr_make("random"); // sending 7 eth works let msg = SubMsg::new(BankMsg::Send { - to_address: random.clone().into(), + to_address: random_addr.clone().into(), amount: coins(7, "eth"), }); let msgs = reflect::Message { messages: vec![msg], }; let res = app - .execute_contract(random.clone(), reflect_addr.clone(), &msgs, &[]) + .execute_contract(random_addr.clone(), reflect_addr.clone(), &msgs, &[]) .unwrap(); // no wasm events as no attributes assert_eq!(2, res.events.len()); @@ -478,7 +488,7 @@ fn reflect_error() { assert_eq!(transfer.ty.as_str(), "transfer"); // ensure random got paid - let funds = get_balance(&app, &random); + let funds = get_balance(&app, &random_addr); assert_eq!(funds, coins(7, "eth")); // reflect count should be updated to 1 @@ -490,26 +500,26 @@ fn reflect_error() { // sending 8 eth, then 3 btc should fail both let msg = SubMsg::new(BankMsg::Send { - to_address: random.clone().into(), + to_address: random_addr.clone().into(), amount: coins(8, "eth"), }); let msg2 = SubMsg::new(BankMsg::Send { - to_address: random.clone().into(), + to_address: random_addr.clone().into(), amount: coins(3, "btc"), }); let msgs = reflect::Message { messages: vec![msg, msg2], }; let err = app - .execute_contract(random.clone(), reflect_addr.clone(), &msgs, &[]) + .execute_contract(random_addr.clone(), reflect_addr.clone(), &msgs, &[]) .unwrap_err(); assert_eq!( - StdError::overflow(OverflowError::new(OverflowOperation::Sub, 0, 3)), + StdError::overflow(OverflowError::new(OverflowOperation::Sub)), err.downcast().unwrap() ); // first one should have been rolled-back on error (no second payment) - let funds = get_balance(&app, &random); + let funds = get_balance(&app, &random_addr); assert_eq!(funds, coins(7, "eth")); // failure should not update reflect count @@ -522,13 +532,15 @@ fn reflect_error() { #[test] fn sudo_works() { - let owner = Addr::unchecked("owner"); - let init_funds = vec![coin(100, "eth")]; + // prepare user addresses + let owner_addr = addr_make("owner"); + // set personal balance + let init_funds = vec![coin(100, "eth")]; let mut app = App::new(|router, _, storage| { router .bank - .init_balance(storage, &owner, init_funds) + .init_balance(storage, &owner_addr, init_funds) .unwrap(); }); @@ -538,7 +550,14 @@ fn sudo_works() { payout: coin(5, "eth"), }; let payout_addr = app - .instantiate_contract(payout_id, owner, &msg, &coins(23, "eth"), "Payout", None) + .instantiate_contract( + payout_id, + owner_addr, + &msg, + &coins(23, "eth"), + "Payout", + None, + ) .unwrap(); // count is 1 @@ -563,7 +582,7 @@ fn sudo_works() { let msg = payout::SudoMsg { set_count: 49 }; let sudo_msg = WasmSudo { contract_addr: payout_addr.clone(), - msg: to_json_binary(&msg).unwrap(), + message: to_json_binary(&msg).unwrap(), }; app.sudo(sudo_msg.into()).unwrap(); @@ -576,12 +595,13 @@ fn sudo_works() { #[test] fn reflect_sub_message_reply_works() { + // prepare user addresses + let owner = addr_make("owner"); + let random = addr_make("random"); + // set personal balance - let owner = Addr::unchecked("owner"); - let random = Addr::unchecked("random"); let init_funds = vec![coin(20, "btc"), coin(100, "eth")]; - - let mut app = custom_app::(|router, _, storage| { + let mut app = custom_app::(|router, _, storage| { router .bank .init_balance(storage, &owner, init_funds) @@ -602,7 +622,7 @@ fn reflect_sub_message_reply_works() { ) .unwrap(); - // no reply writen beforehand + // no reply written beforehand let query = reflect::QueryMsg::Reply { id: 123 }; let res: StdResult = app.wrap().query_wasm_smart(&reflect_addr, &query); res.unwrap_err(); @@ -672,12 +692,12 @@ fn send_update_admin_works() { // update admin succeeds if admin // update admin fails if not (new) admin // check admin set properly - let owner = Addr::unchecked("owner"); - let owner2 = Addr::unchecked("owner2"); - let beneficiary = Addr::unchecked("beneficiary"); - let mut app = App::default(); + let owner = addr_make("owner"); + let owner2 = addr_make("owner2"); + let beneficiary = addr_make("beneficiary"); + // create a hackatom contract with some funds let code_id = app.store_code(hackatom::contract()); @@ -736,14 +756,18 @@ fn sent_wasm_migration_works() { // migrate fails if not admin // migrate succeeds if admin // check beneficiary updated - let owner = Addr::unchecked("owner"); - let beneficiary = Addr::unchecked("beneficiary"); - let init_funds = coins(30, "btc"); + // prepare user addresses + let owner_addr = addr_make("owner"); + let beneficiary_addr = addr_make("beneficiary"); + let random_addr = addr_make("random"); + + // set personal balance + let init_funds = coins(30, "btc"); let mut app = App::new(|router, _, storage| { router .bank - .init_balance(storage, &owner, init_funds) + .init_balance(storage, &owner_addr, init_funds) .unwrap(); }); @@ -753,40 +777,44 @@ fn sent_wasm_migration_works() { let contract = app .instantiate_contract( code_id, - owner.clone(), + owner_addr.clone(), &hackatom::InstantiateMsg { - beneficiary: beneficiary.as_str().to_owned(), + beneficiary: beneficiary_addr.as_str().to_owned(), }, &coins(20, "btc"), "Hackatom", - Some(owner.to_string()), + Some(owner_addr.to_string()), ) .unwrap(); // check admin set properly let info = app.contract_data(&contract).unwrap(); - assert_eq!(info.admin, Some(owner.clone())); + assert_eq!(info.admin, Some(owner_addr.clone())); // check beneficiary set properly let state: hackatom::InstantiateMsg = app .wrap() .query_wasm_smart(&contract, &hackatom::QueryMsg::Beneficiary {}) .unwrap(); - assert_eq!(state.beneficiary, beneficiary); + assert_eq!(state.beneficiary, beneficiary_addr.to_string()); // migrate fails if not admin - let random = Addr::unchecked("random"); let migrate_msg = hackatom::MigrateMsg { - new_guy: random.to_string(), + new_guy: random_addr.to_string(), }; - app.migrate_contract(beneficiary, contract.clone(), &migrate_msg, code_id) + app.migrate_contract(beneficiary_addr, contract.clone(), &migrate_msg, code_id) .unwrap_err(); // migrate fails if unregistered code id - app.migrate_contract(owner.clone(), contract.clone(), &migrate_msg, code_id + 7) - .unwrap_err(); + app.migrate_contract( + owner_addr.clone(), + contract.clone(), + &migrate_msg, + code_id + 7, + ) + .unwrap_err(); // migrate succeeds when the stars align - app.migrate_contract(owner, contract.clone(), &migrate_msg, code_id) + app.migrate_contract(owner_addr, contract.clone(), &migrate_msg, code_id) .unwrap(); // check beneficiary updated @@ -794,7 +822,7 @@ fn sent_wasm_migration_works() { .wrap() .query_wasm_smart(&contract, &hackatom::QueryMsg::Beneficiary {}) .unwrap(); - assert_eq!(state.beneficiary, random); + assert_eq!(state.beneficiary, random_addr.to_string()); } #[test] @@ -804,14 +832,17 @@ fn sent_funds_properly_visible_on_execution() { // additional 20btc. Then beneficiary balance is checked - expected value is 30btc. 10btc // would mean that sending tokens with message is not visible for this very message, and // 20btc means, that only such just send funds are visible. - let owner = Addr::unchecked("owner"); - let beneficiary = Addr::unchecked("beneficiary"); - let init_funds = coins(30, "btc"); + // prepare user addresses + let owner_addr = addr_make("owner"); + let beneficiary_addr = addr_make("beneficiary"); + + // set personal balance + let init_funds = coins(30, "btc"); let mut app = App::new(|router, _, storage| { router .bank - .init_balance(storage, &owner, init_funds) + .init_balance(storage, &owner_addr, init_funds) .unwrap(); }); @@ -820,9 +851,9 @@ fn sent_funds_properly_visible_on_execution() { let contract = app .instantiate_contract( code_id, - owner.clone(), + owner_addr.clone(), &hackatom::InstantiateMsg { - beneficiary: beneficiary.as_str().to_owned(), + beneficiary: beneficiary_addr.as_str().to_owned(), }, &coins(10, "btc"), "Hackatom", @@ -831,7 +862,7 @@ fn sent_funds_properly_visible_on_execution() { .unwrap(); app.execute_contract( - owner.clone(), + owner_addr.clone(), contract.clone(), &Empty {}, &coins(20, "btc"), @@ -840,32 +871,34 @@ fn sent_funds_properly_visible_on_execution() { // Check balance of all accounts to ensure no tokens where burned or created, and they are // in correct places - assert_eq!(get_balance(&app, &owner), &[]); + assert_eq!(get_balance(&app, &owner_addr), &[]); assert_eq!(get_balance(&app, &contract), &[]); - assert_eq!(get_balance(&app, &beneficiary), coins(30, "btc")); + assert_eq!(get_balance(&app, &beneficiary_addr), coins(30, "btc")); } /// Demonstrates that we can mint tokens and send from other accounts /// via a custom module, as an example of ability to do privileged actions. mod custom_handler { use super::*; - use crate::{BankSudo, BasicAppBuilder, CosmosRouter}; + use crate::{BankSudo, BasicAppBuilder}; const LOTTERY: Item = Item::new("lottery"); const PITY: Item = Item::new("pity"); #[derive(Clone, Debug, PartialEq, JsonSchema, Serialize, Deserialize)] - struct CustomMsg { + struct CustomLotteryMsg { // we mint LOTTERY tokens to this one lucky_winner: String, // we transfer PITY from lucky_winner to runner_up runner_up: String, } + impl CustomMsg for CustomLotteryMsg {} + struct CustomHandler {} impl Module for CustomHandler { - type ExecT = CustomMsg; + type ExecT = CustomLotteryMsg; type QueryT = Empty; type SudoT = Empty; @@ -879,7 +912,7 @@ mod custom_handler { msg: Self::ExecT, ) -> AnyResult where - ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static, + ExecC: CustomMsg + DeserializeOwned + 'static, QueryC: CustomQuery + DeserializeOwned + 'static, { let lottery = LOTTERY.load(storage)?; @@ -912,7 +945,7 @@ mod custom_handler { _msg: Self::SudoT, ) -> AnyResult where - ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static, + ExecC: CustomMsg + DeserializeOwned + 'static, QueryC: CustomQuery + DeserializeOwned + 'static, { bail!("sudo not implemented for CustomHandler") @@ -947,15 +980,12 @@ mod custom_handler { // let's call this custom handler #[test] fn dispatches_messages() { - let winner = "winner".to_string(); - let second = "second".to_string(); - // payments. note 54321 - 12321 = 42000 let denom = "tix"; let lottery = coin(54321, denom); let bonus = coin(12321, denom); - let mut app = BasicAppBuilder::::new_custom() + let mut app = BasicAppBuilder::::new_custom() .with_custom(CustomHandler {}) .build(|router, _, storage| { router @@ -964,16 +994,20 @@ mod custom_handler { .unwrap(); }); + let winner = app.api().addr_make("winner"); + let second = app.api().addr_make("second"); + // query that balances are empty let start = app.wrap().query_balance(&winner, denom).unwrap(); assert_eq!(start, coin(0, denom)); // trigger the custom module - let msg = CosmosMsg::Custom(CustomMsg { - lucky_winner: winner.clone(), - runner_up: second.clone(), + let msg = CosmosMsg::Custom(CustomLotteryMsg { + lucky_winner: winner.to_string(), + runner_up: second.to_string(), }); - app.execute(Addr::unchecked("anyone"), msg).unwrap(); + let anyone = app.api().addr_make("anyone"); + app.execute(anyone, msg).unwrap(); // see if coins were properly added let big_win = app.wrap().query_balance(&winner, denom).unwrap(); @@ -985,9 +1019,6 @@ mod custom_handler { mod reply_data_overwrite { use super::*; - use cosmwasm_std::to_json_binary; - - use echo::EXECUTE_REPLY_BASE_ID; fn make_echo_submsg( contract: Addr, @@ -1033,7 +1064,7 @@ mod reply_data_overwrite { fn no_submsg() { let mut app = App::default(); - let owner = Addr::unchecked("owner"); + let owner = app.api().addr_make("owner"); let code_id = app.store_code(echo::contract()); @@ -1060,7 +1091,7 @@ mod reply_data_overwrite { fn single_submsg() { let mut app = App::default(); - let owner = Addr::unchecked("owner"); + let owner = app.api().addr_make("owner"); let code_id = app.store_code(echo::contract()); @@ -1093,7 +1124,7 @@ mod reply_data_overwrite { fn single_submsg_no_reply() { let mut app = App::default(); - let owner = Addr::unchecked("owner"); + let owner = app.api().addr_make("owner"); let code_id = app.store_code(echo::contract()); @@ -1121,7 +1152,7 @@ mod reply_data_overwrite { fn single_no_submsg_data() { let mut app = App::default(); - let owner = Addr::unchecked("owner"); + let owner = app.api().addr_make("owner"); let code_id = app.store_code(echo::contract()); @@ -1149,7 +1180,7 @@ mod reply_data_overwrite { fn single_no_top_level_data() { let mut app = App::default(); - let owner = Addr::unchecked("owner"); + let owner = app.api().addr_make("owner"); let code_id = app.store_code(echo::contract()); @@ -1179,11 +1210,12 @@ mod reply_data_overwrite { #[test] fn single_submsg_reply_returns_none() { + // prepare user addresses + let owner = addr_make("owner"); + // set personal balance - let owner = Addr::unchecked("owner"); let init_funds = coins(100, "tgd"); - - let mut app = custom_app::(|router, _, storage| { + let mut app = custom_app::(|router, _, storage| { router .bank .init_balance(storage, &owner, init_funds) @@ -1237,7 +1269,7 @@ mod reply_data_overwrite { fn multiple_submsg() { let mut app = App::default(); - let owner = Addr::unchecked("owner"); + let owner = app.api().addr_make("owner"); let code_id = app.store_code(echo::contract()); @@ -1280,7 +1312,7 @@ mod reply_data_overwrite { fn multiple_submsg_no_reply() { let mut app = App::default(); - let owner = Addr::unchecked("owner"); + let owner = app.api().addr_make("owner"); let code_id = app.store_code(echo::contract()); @@ -1313,7 +1345,7 @@ mod reply_data_overwrite { fn multiple_submsg_mixed() { let mut app = App::default(); - let owner = Addr::unchecked("owner"); + let owner = app.api().addr_make("owner"); let code_id = app.store_code(echo::contract()); @@ -1351,7 +1383,7 @@ mod reply_data_overwrite { fn nested_submsg() { let mut app = App::default(); - let owner = Addr::unchecked("owner"); + let owner = app.api().addr_make("owner"); let code_id = app.store_code(echo::contract()); @@ -1404,7 +1436,7 @@ mod response_validation { fn empty_attribute_key() { let mut app = App::default(); - let owner = Addr::unchecked("owner"); + let owner = app.api().addr_make("owner"); let code_id = app.store_code(echo::contract()); @@ -1432,18 +1464,17 @@ mod response_validation { } #[test] - fn empty_attribute_value() { + fn empty_attribute_value_should_work() { let mut app = App::default(); - let owner = Addr::unchecked("owner"); - + let owner = app.api().addr_make("owner"); let code_id = app.store_code(echo::contract()); let contract = app .instantiate_contract(code_id, owner.clone(), &Empty {}, &[], "Echo", None) .unwrap(); - let err = app + assert!(app .execute_contract( owner, contract, @@ -1457,16 +1488,14 @@ mod response_validation { }, &[], ) - .unwrap_err(); - - assert_eq!(Error::empty_attribute_value("key"), err.downcast().unwrap()); + .is_ok()); } #[test] fn empty_event_attribute_key() { let mut app = App::default(); - let owner = Addr::unchecked("owner"); + let owner = app.api().addr_make("owner"); let code_id = app.store_code(echo::contract()); @@ -1493,18 +1522,17 @@ mod response_validation { } #[test] - fn empty_event_attribute_value() { + fn empty_event_attribute_value_should_work() { let mut app = App::default(); - let owner = Addr::unchecked("owner"); - + let owner = app.api().addr_make("owner"); let code_id = app.store_code(echo::contract()); let contract = app .instantiate_contract(code_id, owner.clone(), &Empty {}, &[], "Echo", None) .unwrap(); - let err = app + assert!(app .execute_contract( owner, contract, @@ -1517,16 +1545,14 @@ mod response_validation { }, &[], ) - .unwrap_err(); - - assert_eq!(Error::empty_attribute_value("key"), err.downcast().unwrap()); + .is_ok()); } #[test] fn too_short_event_type() { let mut app = App::default(); - let owner = Addr::unchecked("owner"); + let owner = app.api().addr_make("owner"); let code_id = app.store_code(echo::contract()); @@ -1552,26 +1578,29 @@ mod response_validation { } mod contract_instantiation { + #[test] fn instantiate2_works() { use super::*; // prepare application and actors let mut app = App::default(); - let sender = Addr::unchecked("sender"); + let sender = app.api().addr_make("sender"); + let creator = app.api().addr_make("creator"); // store contract's code - let code_id = app.store_code_with_creator(Addr::unchecked("creator"), echo::contract()); + let code_id = app.store_code_with_creator(creator, echo::contract()); // initialize the contract let init_msg = to_json_binary(&Empty {}).unwrap(); + let salt = cosmwasm_std::HexBinary::from_hex("010203040506").unwrap(); let msg = WasmMsg::Instantiate2 { admin: None, code_id, msg: init_msg, funds: vec![], label: "label".into(), - salt: [1, 2, 3, 4, 5, 6].as_slice().into(), + salt: salt.into(), }; let res = app.execute(sender, msg.into()).unwrap(); @@ -1581,7 +1610,10 @@ mod contract_instantiation { // assert contract's address is exactly the predicted one, // in default address generator, this is like `contract` + salt in hex - assert_eq!(parsed.contract_address, "contract010203040506"); + assert_eq!( + parsed.contract_address, + "cosmwasm167g7x7auj3l00lhdcevusncx565ytz6a6xvmx2f5xuy84re9ddrqczpzkm", + ); } } @@ -1591,11 +1623,12 @@ mod wasm_queries { fn query_existing_code_info() { use super::*; let mut app = App::default(); - let code_id = app.store_code_with_creator(Addr::unchecked("creator"), echo::contract()); + let creator = app.api().addr_make("creator"); + let code_id = app.store_code_with_creator(creator.clone(), echo::contract()); let code_info_response = app.wrap().query_wasm_code_info(code_id).unwrap(); assert_eq!(code_id, code_info_response.code_id); - assert_eq!("creator", code_info_response.creator); - assert!(!code_info_response.checksum.is_empty()); + assert_eq!(creator.to_string(), code_info_response.creator.to_string()); + assert_eq!(32, code_info_response.checksum.as_slice().len()); } #[test] @@ -1618,15 +1651,15 @@ mod custom_messages { #[test] fn triggering_custom_msg() { - let custom_handler = CachingCustomHandler::::new(); + let custom_handler = CachingCustomHandler::::new(); let custom_handler_state = custom_handler.state(); let mut app = AppBuilder::new_custom() .with_custom(custom_handler) .build(no_init); - let sender = app.api().addr_validate("sender").unwrap(); - let owner = app.api().addr_validate("owner").unwrap(); + let sender = app.api().addr_make("sender"); + let owner = app.api().addr_make("owner"); let contract_id = app.store_code(echo::custom_contract()); @@ -1638,7 +1671,7 @@ mod custom_messages { sender, contract, &echo::Message { - sub_msg: vec![SubMsg::new(CosmosMsg::Custom(CustomMsg::SetAge { + sub_msg: vec![SubMsg::new(CosmosMsg::Custom(CustomHelperMsg::SetAge { age: 20, }))], ..Default::default() @@ -1649,7 +1682,7 @@ mod custom_messages { assert_eq!( custom_handler_state.execs().to_owned(), - vec![CustomMsg::SetAge { age: 20 }] + vec![CustomHelperMsg::SetAge { age: 20 }] ); assert!(custom_handler_state.queries().is_empty()); @@ -1662,11 +1695,12 @@ mod protobuf_wrapped_data { #[test] fn instantiate_wrapped_properly() { + // prepare user addresses + let owner = addr_make("owner"); + // set personal balance - let owner = Addr::unchecked("owner"); let init_funds = vec![coin(20, "btc")]; - - let mut app = custom_app::(|router, _, storage| { + let mut app = custom_app::(|router, _, storage| { router .bank .init_balance(storage, &owner, init_funds) @@ -1700,8 +1734,9 @@ mod protobuf_wrapped_data { #[test] fn instantiate_with_data_works() { - let owner = Addr::unchecked("owner"); - let mut app = BasicApp::new(|_, _, _| {}); + let mut app = BasicApp::new(no_init); + + let owner = app.api().addr_make("owner"); // set up echo contract let code_id = app.store_code(echo::contract()); @@ -1729,8 +1764,9 @@ mod protobuf_wrapped_data { #[test] fn instantiate_with_reply_works() { - let owner = Addr::unchecked("owner"); - let mut app = BasicApp::new(|_, _, _| {}); + let mut app = BasicApp::new(no_init); + + let owner = app.api().addr_make("owner"); // set up echo contract let code_id = app.store_code(echo::contract()); @@ -1781,8 +1817,9 @@ mod protobuf_wrapped_data { #[test] fn execute_wrapped_properly() { - let owner = Addr::unchecked("owner"); - let mut app = BasicApp::new(|_, _, _| {}); + let mut app = BasicApp::new(no_init); + + let owner = app.api().addr_make("owner"); // set up reflect contract let code_id = app.store_code(echo::contract()); @@ -1804,13 +1841,13 @@ mod protobuf_wrapped_data { mod errors { use super::*; - use cosmwasm_std::to_json_binary; #[test] fn simple_instantiation() { - let owner = Addr::unchecked("owner"); let mut app = App::default(); + let owner = app.api().addr_make("owner"); + // set up contract let code_id = app.store_code(error::contract(false)); @@ -1821,7 +1858,7 @@ mod errors { // we should be able to retrieve the original error by downcasting let source: &StdError = err.downcast_ref().unwrap(); - if let StdError::GenericErr { msg } = source { + if let StdError::GenericErr { msg, .. } = source { assert_eq!(msg, "Init failed"); } else { panic!("wrong StdError variant"); @@ -1834,9 +1871,11 @@ mod errors { #[test] fn simple_call() { - let owner = Addr::unchecked("owner"); let mut app = App::default(); + let owner = app.api().addr_make("owner"); + let random_addr = app.api().addr_make("random"); + // set up contract let code_id = app.store_code(error::contract(true)); @@ -1847,12 +1886,12 @@ mod errors { // execute should error let err = app - .execute_contract(Addr::unchecked("random"), contract_addr, &msg, &[]) + .execute_contract(random_addr, contract_addr, &msg, &[]) .unwrap_err(); // we should be able to retrieve the original error by downcasting let source: &StdError = err.downcast_ref().unwrap(); - if let StdError::GenericErr { msg } = source { + if let StdError::GenericErr { msg, .. } = source { assert_eq!(msg, "Handle failed"); } else { panic!("wrong StdError variant"); @@ -1865,9 +1904,11 @@ mod errors { #[test] fn nested_call() { - let owner = Addr::unchecked("owner"); let mut app = App::default(); + let owner = app.api().addr_make("owner"); + let random_addr = app.api().addr_make("random"); + let error_code_id = app.store_code(error::contract(true)); let caller_code_id = app.store_code(caller::contract()); @@ -1887,12 +1928,12 @@ mod errors { funds: vec![], }; let err = app - .execute_contract(Addr::unchecked("random"), caller_addr, &msg, &[]) + .execute_contract(random_addr, caller_addr, &msg, &[]) .unwrap_err(); - // we can downcast to get the original error + // we can get the original error by downcasting let source: &StdError = err.downcast_ref().unwrap(); - if let StdError::GenericErr { msg } = source { + if let StdError::GenericErr { msg, .. } = source { assert_eq!(msg, "Handle failed"); } else { panic!("wrong StdError variant"); @@ -1905,22 +1946,38 @@ mod errors { #[test] fn double_nested_call() { - let owner = Addr::unchecked("owner"); let mut app = App::default(); + let owner_addr = app.api().addr_make("owner"); + let random_addr = app.api().addr_make("random"); + let error_code_id = app.store_code(error::contract(true)); let caller_code_id = app.store_code(caller::contract()); // set up contract_helpers let msg = Empty {}; let caller_addr1 = app - .instantiate_contract(caller_code_id, owner.clone(), &msg, &[], "caller", None) + .instantiate_contract( + caller_code_id, + owner_addr.clone(), + &msg, + &[], + "caller", + None, + ) .unwrap(); let caller_addr2 = app - .instantiate_contract(caller_code_id, owner.clone(), &msg, &[], "caller", None) + .instantiate_contract( + caller_code_id, + owner_addr.clone(), + &msg, + &[], + "caller", + None, + ) .unwrap(); let error_addr = app - .instantiate_contract(error_code_id, owner, &msg, &[], "error", None) + .instantiate_contract(error_code_id, owner_addr, &msg, &[], "error", None) .unwrap(); // caller1 calls caller2, caller2 calls error @@ -1935,15 +1992,15 @@ mod errors { funds: vec![], }; let err = app - .execute_contract(Addr::unchecked("random"), caller_addr1, &msg, &[]) + .execute_contract(random_addr, caller_addr1, &msg, &[]) .unwrap_err(); // uncomment to have the test fail and see how the error stringifies // panic!("{:?}", err); - // we can downcast to get the original error + // we can get the original error by downcasting let source: &StdError = err.downcast_ref().unwrap(); - if let StdError::GenericErr { msg } = source { + if let StdError::GenericErr { msg, .. } = source { assert_eq!(msg, "Handle failed"); } else { panic!("wrong StdError variant"); @@ -1954,29 +2011,3 @@ mod errors { assert_eq!(err.chain().count(), 4); } } - -mod api { - use super::*; - - #[test] - fn api_addr_validate_should_work() { - let app = App::default(); - let addr = app.api().addr_validate("creator").unwrap(); - assert_eq!(addr.to_string(), "creator"); - } - - #[test] - #[cfg(not(feature = "cosmwasm_1_5"))] - fn api_addr_canonicalize_should_work() { - let app = App::default(); - let canonical = app.api().addr_canonicalize("creator").unwrap(); - assert_eq!(canonical.to_string(), "0000000000000000000000000000726F0000000000000000000000000000000000000000006572000000000000000000000000000000000000000000610000000000000000000000000000000000000000006374000000000000"); - } - - #[test] - fn api_addr_humanize_should_work() { - let app = App::default(); - let canonical = app.api().addr_canonicalize("creator").unwrap(); - assert_eq!(app.api().addr_humanize(&canonical).unwrap(), "creator"); - } -} diff --git a/src/tests/test_custom_handler.rs b/src/tests/test_custom_handler.rs index 834f1e73..5ba0d70e 100644 --- a/src/tests/test_custom_handler.rs +++ b/src/tests/test_custom_handler.rs @@ -1,9 +1,12 @@ use crate::custom_handler::CachingCustomHandler; -use crate::test_helpers::CustomMsg; +use crate::test_helpers::CustomHelperMsg; use crate::{App, Module}; use cosmwasm_std::testing::MockStorage; -use cosmwasm_std::{Addr, Empty}; +use cosmwasm_std::Empty; +///Custom handlers in CosmWasm allow developers to incorporate their own unique logic into tests. +///This feature is valuable for tailoring the testing environment to reflect specific +/// use-cases or behaviors in a CosmWasm-based smart contract. #[test] fn custom_handler_works() { // prepare needed tools @@ -11,7 +14,10 @@ fn custom_handler_works() { let mut storage = MockStorage::default(); // create custom handler - let custom_handler = CachingCustomHandler::::new(); + let custom_handler = CachingCustomHandler::::new(); + + // prepare user addresses + let sender_addr = app.api().addr_make("sender"); // run execute function let _ = custom_handler.execute( @@ -19,8 +25,8 @@ fn custom_handler_works() { &mut storage, app.router(), &app.block_info(), - Addr::unchecked("sender"), - CustomMsg::SetAge { age: 32 }, + sender_addr, + CustomHelperMsg::SetAge { age: 32 }, ); // run query function @@ -29,7 +35,7 @@ fn custom_handler_works() { &storage, &(*app.wrap()), &app.block_info(), - CustomMsg::SetName { + CustomHelperMsg::SetName { name: "John".to_string(), }, ); @@ -40,13 +46,13 @@ fn custom_handler_works() { // there should be one exec message assert_eq!( custom_handler_state.execs().to_owned(), - vec![CustomMsg::SetAge { age: 32 }] + vec![CustomHelperMsg::SetAge { age: 32 }] ); // there should be one query message assert_eq!( custom_handler_state.queries().to_owned(), - vec![CustomMsg::SetName { + vec![CustomHelperMsg::SetName { name: "John".to_string() }] ); @@ -64,11 +70,11 @@ fn custom_handler_has_no_sudo() { let mut storage = MockStorage::default(); // create custom handler - let custom_handler = CachingCustomHandler::::new(); + let custom_handler = CachingCustomHandler::::new(); // run sudo function assert_eq!( - "Unexpected sudo msg Empty", + "Unexpected custom sudo message Empty", custom_handler .sudo( app.api(), diff --git a/src/tests/test_error.rs b/src/tests/test_error.rs new file mode 100644 index 00000000..d3f16290 --- /dev/null +++ b/src/tests/test_error.rs @@ -0,0 +1,43 @@ +use crate::error::Error; +use cosmwasm_std::{WasmMsg, WasmQuery}; + +#[test] +fn instantiating_error_should_work() { + assert_eq!( + "Empty attribute key. Value: alpha", + Error::empty_attribute_key("alpha").to_string() + ); + assert_eq!( + "Attribute key starts with reserved prefix _: gamma", + Error::reserved_attribute_key("gamma").to_string() + ); + assert_eq!( + "Event type too short: event_type", + Error::event_type_too_short("event_type").to_string() + ); + assert_eq!( + r#"Unsupported wasm query: ContractInfo { contract_addr: "contract1984" }"#, + Error::unsupported_wasm_query(WasmQuery::ContractInfo { + contract_addr: "contract1984".to_string() + }) + .to_string() + ); + assert_eq!( + r#"Unsupported wasm message: Migrate { contract_addr: "contract1984", new_code_id: 1984, msg: }"#, + Error::unsupported_wasm_message(WasmMsg::Migrate { + contract_addr: "contract1984".to_string(), + new_code_id: 1984, + msg: Default::default(), + }) + .to_string() + ); + assert_eq!("code id: invalid", Error::invalid_code_id().to_string()); + assert_eq!( + "code id 53: no such code", + Error::unregistered_code_id(53).to_string() + ); + assert_eq!( + "Contract with this address already exists: contract1984", + Error::duplicated_contract_address("contract1984").to_string() + ); +} diff --git a/src/tests/test_gov.rs b/src/tests/test_gov.rs index e900c40f..68897735 100644 --- a/src/tests/test_gov.rs +++ b/src/tests/test_gov.rs @@ -1,99 +1,37 @@ -use crate::error::AnyResult; -use crate::test_helpers::{stargate, stargate::ExecMsg}; -use crate::{App, AppBuilder, AppResponse, CosmosRouter, Executor, Gov, Module}; -use cosmwasm_std::{Addr, Api, Binary, BlockInfo, CustomQuery, Empty, GovMsg, Querier, Storage}; -use schemars::JsonSchema; -use serde::de::DeserializeOwned; -use std::fmt::Debug; - -struct AcceptingModule; - -impl Module for AcceptingModule { - type ExecT = GovMsg; - type QueryT = Empty; - type SudoT = Empty; - - fn execute( - &self, - _api: &dyn Api, - _storage: &mut dyn Storage, - _router: &dyn CosmosRouter, - _block: &BlockInfo, - _sender: Addr, - _msg: Self::ExecT, - ) -> AnyResult - where - ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static, - QueryC: CustomQuery + DeserializeOwned + 'static, - { - Ok(AppResponse::default()) - } - - fn sudo( - &self, - _api: &dyn Api, - _storage: &mut dyn Storage, - _router: &dyn CosmosRouter, - _block: &BlockInfo, - _msg: Self::SudoT, - ) -> AnyResult - where - ExecC: Debug + Clone + PartialEq + schemars::JsonSchema + DeserializeOwned + 'static, - QueryC: CustomQuery + DeserializeOwned + 'static, - { - Ok(AppResponse::default()) - } - - fn query( - &self, - _api: &dyn Api, - _storage: &dyn Storage, - _querier: &dyn Querier, - _block: &BlockInfo, - _request: Self::QueryT, - ) -> AnyResult { - Ok(Binary::default()) - } -} - -impl Gov for AcceptingModule {} +use crate::test_helpers::gov; +use crate::{no_init, App, AppBuilder, Executor, GovAcceptingModule}; +use cosmwasm_std::Empty; #[test] fn default_gov() { let mut app = App::default(); - let code = app.store_code(stargate::contract()); + + let creator_addr = app.api().addr_make("creator"); + let code = app.store_code_with_creator(creator_addr, gov::contract()); + + let owner_addr = app.api().addr_make("owner"); let contract = app - .instantiate_contract( - code, - Addr::unchecked("owner"), - &Empty {}, - &[], - "contract", - None, - ) + .instantiate_contract(code, owner_addr.clone(), &Empty {}, &[], "govenius", None) .unwrap(); - app.execute_contract(Addr::unchecked("owner"), contract, &ExecMsg::Gov {}, &[]) + app.execute_contract(owner_addr, contract, &Empty {}, &[]) .unwrap_err(); } #[test] -fn substituting_gov() { +fn accepting_gov() { let mut app = AppBuilder::new() - .with_gov(AcceptingModule) - .build(|_, _, _| ()); - let code = app.store_code(stargate::contract()); + .with_gov(GovAcceptingModule::new()) + .build(no_init); + + let creator_addr = app.api().addr_make("creator"); + let code = app.store_code_with_creator(creator_addr, gov::contract()); + + let owner_addr = app.api().addr_make("owner"); let contract = app - .instantiate_contract( - code, - Addr::unchecked("owner"), - &Empty {}, - &[], - "contract", - None, - ) + .instantiate_contract(code, owner_addr.clone(), &Empty {}, &[], "govenius", None) .unwrap(); - app.execute_contract(Addr::unchecked("owner"), contract, &ExecMsg::Gov {}, &[]) + app.execute_contract(owner_addr, contract, &Empty {}, &[]) .unwrap(); } diff --git a/src/tests/test_ibc.rs b/src/tests/test_ibc.rs index 2497478c..ed32377e 100644 --- a/src/tests/test_ibc.rs +++ b/src/tests/test_ibc.rs @@ -1,43 +1,37 @@ -use crate::test_helpers::{stargate, stargate::ExecMsg}; -use crate::{App, AppBuilder, Executor, IbcAcceptingModule}; -use cosmwasm_std::{Addr, Empty}; +use crate::test_helpers::ibc; +use crate::{no_init, App, AppBuilder, Executor, IbcAcceptingModule}; +use cosmwasm_std::Empty; #[test] fn default_ibc() { let mut app = App::default(); - let code = app.store_code(stargate::contract()); + + let creator_addr = app.api().addr_make("creator"); + let code = app.store_code_with_creator(creator_addr, ibc::contract()); + + let owner_addr = app.api().addr_make("owner"); let contract = app - .instantiate_contract( - code, - Addr::unchecked("owner"), - &Empty {}, - &[], - "contract", - None, - ) + .instantiate_contract(code, owner_addr.clone(), &Empty {}, &[], "ibanera", None) .unwrap(); - app.execute_contract(Addr::unchecked("owner"), contract, &ExecMsg::Ibc {}, &[]) + app.execute_contract(owner_addr, contract, &Empty {}, &[]) .unwrap_err(); } #[test] -fn substituting_ibc() { +fn accepting_ibc() { let mut app = AppBuilder::new() .with_ibc(IbcAcceptingModule::new()) - .build(|_, _, _| ()); - let code = app.store_code(stargate::contract()); + .build(no_init); + + let creator_addr = app.api().addr_make("creator"); + let code = app.store_code_with_creator(creator_addr, ibc::contract()); + + let owner_addr = app.api().addr_make("owner"); let contract = app - .instantiate_contract( - code, - Addr::unchecked("owner"), - &Empty {}, - &[], - "contract", - None, - ) + .instantiate_contract(code, owner_addr.clone(), &Empty {}, &[], "ibanera", None) .unwrap(); - app.execute_contract(Addr::unchecked("owner"), contract, &ExecMsg::Ibc {}, &[]) + app.execute_contract(owner_addr, contract, &Empty {}, &[]) .unwrap(); } diff --git a/src/tests/test_stargate.rs b/src/tests/test_stargate.rs new file mode 100644 index 00000000..01f2f975 --- /dev/null +++ b/src/tests/test_stargate.rs @@ -0,0 +1,54 @@ +use crate::test_helpers::stargate; +use crate::{no_init, App, AppBuilder, Executor, StargateAccepting}; +use cosmwasm_std::Empty; + +#[test] +fn default_failing_stargate_handler_should_work() { + let mut app = App::default(); + + // store the contract + let creator_addr = app.api().addr_make("creator"); + let code = app.store_code_with_creator(creator_addr, stargate::contract()); + + // instantiate contract + let owner_addr = app.api().addr_make("owner"); + let contract_addr = app + .instantiate_contract(code, owner_addr.clone(), &Empty {}, &[], "tauri", None) + .unwrap(); + + // execute empty message on the contract, this contract returns stargate message + // which is rejected by default failing stargate keeper + let err = app + .execute_contract(owner_addr, contract_addr, &Empty {}, &[]) + .unwrap_err(); + + // source error message comes from failing stargate keeper + assert!(err + .source() + .unwrap() + .to_string() + .starts_with("Unexpected stargate execute")); +} + +#[test] +fn accepting_stargate_handler_should_work() { + let mut app = AppBuilder::default() + .with_stargate(StargateAccepting) + .build(no_init); + + // store the contract + let creator_addr = app.api().addr_make("creator"); + let code = app.store_code_with_creator(creator_addr, stargate::contract()); + + // instantiate contract + let owner_addr = app.api().addr_make("owner"); + let contract_addr = app + .instantiate_contract(code, owner_addr.clone(), &Empty {}, &[], "tauri", None) + .unwrap(); + + // execute empty message on the contract, this contract returns stargate message + // which is just silently processed by accepting stargate keeper + assert!(app + .execute_contract(owner_addr, contract_addr, &Empty {}, &[]) + .is_ok()); +} diff --git a/src/transactions.rs b/src/transactions.rs index 4e8b2645..59ac0b0f 100644 --- a/src/transactions.rs +++ b/src/transactions.rs @@ -56,23 +56,9 @@ impl<'a> Storage for StorageTransaction<'a> { } } - fn set(&mut self, key: &[u8], value: &[u8]) { - let op = Op::Set { - key: key.to_vec(), - value: value.to_vec(), - }; - self.local_state.insert(key.to_vec(), op.to_delta()); - self.rep_log.append(op); - } - - fn remove(&mut self, key: &[u8]) { - let op = Op::Delete { key: key.to_vec() }; - self.local_state.insert(key.to_vec(), op.to_delta()); - self.rep_log.append(op); - } - - /// range allows iteration over a set of keys, either forwards or backwards - /// uses standard rust range notation, and eg db.range(b"foo"..b"bar") also works reverse + /// Range allows iteration over a set of keys, either forwards or backwards + /// uses standard Rust range notation, e.g. `db.range(b"foo"‥b"bar")`, + /// works also in reverse order. fn range<'b>( &'b self, start: Option<&[u8]>, @@ -101,6 +87,21 @@ impl<'a> Storage for StorageTransaction<'a> { let merged = MergeOverlay::new(local, base, order); Box::new(merged) } + + fn set(&mut self, key: &[u8], value: &[u8]) { + let op = Op::Set { + key: key.to_vec(), + value: value.to_vec(), + }; + self.local_state.insert(key.to_vec(), op.to_delta()); + self.rep_log.append(op); + } + + fn remove(&mut self, key: &[u8]) { + let op = Op::Delete { key: key.to_vec() }; + self.local_state.insert(key.to_vec(), op.to_delta()); + self.rep_log.append(op); + } } pub struct RepLog { @@ -127,7 +128,7 @@ impl RepLog { } /// Op is the user operation, which can be stored in the RepLog. -/// Currently Set or Delete. +/// Currently: `Set` or `Delete`. enum Op { /// represents the `Set` operation for setting a key-value pair in storage Set { @@ -544,17 +545,17 @@ mod test { let mut base = MemoryStorage::new(); base.set(b"foo", b"bar"); - let mut stxn1 = StorageTransaction::new(&base); + let mut stx1 = StorageTransaction::new(&base); - assert_eq!(stxn1.get(b"foo"), Some(b"bar".to_vec())); + assert_eq!(stx1.get(b"foo"), Some(b"bar".to_vec())); - stxn1.set(b"subtx", b"works"); - assert_eq!(stxn1.get(b"subtx"), Some(b"works".to_vec())); + stx1.set(b"subtx", b"works"); + assert_eq!(stx1.get(b"subtx"), Some(b"works".to_vec())); // Can still read from base, txn is not yet committed assert_eq!(base.get(b"subtx"), None); - stxn1.prepare().commit(&mut base); + stx1.prepare().commit(&mut base); assert_eq!(base.get(b"subtx"), Some(b"works".to_vec())); } diff --git a/src/wasm.rs b/src/wasm.rs index d7891f8a..5de0994a 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -28,31 +28,37 @@ use schemars::JsonSchema; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use std::cell::RefCell; -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; use std::fmt::Debug; -//TODO Make `CONTRACTS` private in version 1.0 when the function AddressGenerator::next_address will be removed. /// Contract state kept in storage, separate from the contracts themselves (contract code). -pub(crate) const CONTRACTS: Map<&Addr, ContractData> = Map::new("contracts"); +pub const CONTRACTS: Map<&Addr, ContractData> = Map::new("contracts"); -//TODO Make `NAMESPACE_WASM` private in version 1.0 when the function AddressGenerator::next_address will be removed. -pub(crate) const NAMESPACE_WASM: &[u8] = b"wasm"; -/// See +/// Wasm module namespace. +pub const NAMESPACE_WASM: &[u8] = b"wasm"; + +/// Contract [address namespace]. +/// +/// [address namespace]: https://github.com/CosmWasm/wasmd/blob/96e2b91144c9a371683555f3c696f882583cc6a2/x/wasm/types/events.go#L59 const CONTRACT_ATTR: &str = "_contract_address"; pub const LOCAL_WASM_CODE_OFFSET: usize = 5_000_000; pub const LOCAL_RUST_CODE_OFFSET: usize = 10_000_000; +/// A structure representing a privileged message. #[derive(Clone, Debug, PartialEq, Eq, JsonSchema)] pub struct WasmSudo { + /// Address of a contract the privileged action will be sent to. pub contract_addr: Addr, - pub msg: Binary, + /// Message representing privileged action to be executed by contract `sudo` entry-point. + pub message: Binary, } impl WasmSudo { + /// Creates a new privileged message for specified contract address and action to be executed. pub fn new(contract_addr: &Addr, msg: &T) -> StdResult { Ok(WasmSudo { contract_addr: contract_addr.clone(), - msg: to_json_binary(msg)?, + message: to_json_binary(msg)?, }) } } @@ -80,18 +86,10 @@ pub struct CodeData { pub code_base_id: usize, } -pub trait Wasm: AllWasmQuerier { - /// Handles all WasmQuery requests - fn query( - &self, - api: &dyn Api, - storage: &dyn Storage, - router: &dyn CosmosRouter, - querier: &dyn Querier, - block: &BlockInfo, - request: WasmQuery, - ) -> AnyResult; - +/// Acts as the interface for interacting with WebAssembly (Wasm) modules. +/// This trait is crucial for testing smart contracts written in languages that compile to WebAssembly, +/// which is common in the Cosmos and CosmWasm ecosystems. +pub trait Wasm: AllWasmQuerier { /// Handles all `WasmMsg` messages. fn execute( &self, @@ -103,15 +101,25 @@ pub trait Wasm: AllWasmQuerier { msg: WasmMsg, ) -> AnyResult; + /// Handles all `WasmQuery` requests. + fn query( + &self, + api: &dyn Api, + storage: &dyn Storage, + router: &dyn CosmosRouter, + querier: &dyn Querier, + block: &BlockInfo, + request: WasmQuery, + ) -> AnyResult; + /// Handles all sudo messages, this is an admin interface and can not be called via `CosmosMsg`. fn sudo( &self, api: &dyn Api, - contract_addr: Addr, storage: &mut dyn Storage, router: &dyn CosmosRouter, block: &BlockInfo, - msg: Binary, + msg: WasmSudo, ) -> AnyResult; /// Stores the contract's code and returns an identifier of the stored contract's code. @@ -119,23 +127,68 @@ pub trait Wasm: AllWasmQuerier { /// Stores the contract's code and returns an identifier of the stored contract's code. fn store_wasm_code(&mut self, creator: Addr, code: Vec) -> u64; + /// Stores the contract's code under specified identifier, + /// returns the same code identifier when successful. + fn store_code_with_id( + &mut self, + creator: Addr, + code_id: u64, + code: Box>, + ) -> AnyResult; + + /// Duplicates the contract's code with specified identifier + /// and returns an identifier of the copy of the contract's code. + fn duplicate_code(&mut self, code_id: u64) -> AnyResult; /// Returns `ContractData` for the contract with specified address. fn contract_data(&self, storage: &dyn Storage, address: &Addr) -> AnyResult; /// Returns a raw state dump of all key-values held by a contract with specified address. fn dump_wasm_raw(&self, storage: &dyn Storage, address: &Addr) -> Vec; + + /// Returns the namespace of the contract storage. + fn contract_namespace(&self, contract: &Addr) -> Vec { + let mut name = b"contract_data/".to_vec(); + name.extend_from_slice(contract.as_bytes()); + name + } + + /// Returns **read-only** (not mutable) contract storage. + fn contract_storage<'a>( + &self, + storage: &'a dyn Storage, + address: &Addr, + ) -> Box { + // We double-namespace this, once from global storage -> wasm_storage + // then from wasm_storage -> the contracts subspace + let namespace = self.contract_namespace(address); + let storage = ReadonlyPrefixedStorage::multilevel(storage, &[NAMESPACE_WASM, &namespace]); + Box::new(storage) + } + + /// Returns **read-write** (mutable) contract storage. + fn contract_storage_mut<'a>( + &self, + storage: &'a mut dyn Storage, + address: &Addr, + ) -> Box { + // We double-namespace this, once from global storage -> wasm_storage + // then from wasm_storage -> the contracts subspace + let namespace = self.contract_namespace(address); + let storage = PrefixedStorage::multilevel(storage, &[NAMESPACE_WASM, &namespace]); + Box::new(storage) + } } pub type LocalRustContract = *mut dyn Contract; pub struct WasmKeeper { /// Contract codes that stand for wasm code in real-life blockchain. - pub code_base: RefCell>, + pub code_base: RefCell>, /// Contract codes that stand for rust code living in the current instance /// We also associate the queries to them to make sure we are able to use them with the vm instance pub rust_codes: HashMap>, /// Code data with code base identifier and additional attributes. - pub code_data: HashMap, + pub code_data: BTreeMap, /// Contract's address generator. address_generator: Box, /// Contract's code checksum generator. @@ -149,8 +202,8 @@ pub struct WasmKeeper { impl Default for WasmKeeper { fn default() -> WasmKeeper { Self { - code_base: HashMap::new().into(), - code_data: HashMap::new(), + code_base: BTreeMap::default().into(), + code_data: BTreeMap::default(), address_generator: Box::new(SimpleAddressGenerator), checksum_generator: Box::new(SimpleChecksumGenerator), _p: std::marker::PhantomData, @@ -165,6 +218,22 @@ where ExecC: CustomMsg + DeserializeOwned + 'static, QueryC: CustomQuery + DeserializeOwned + 'static, { + fn execute( + &self, + api: &dyn Api, + storage: &mut dyn Storage, + router: &dyn CosmosRouter, + block: &BlockInfo, + sender: Addr, + msg: WasmMsg, + ) -> AnyResult { + self.execute_wasm(api, storage, router, block, sender.clone(), msg.clone()) + .context(format!( + "Error executing WasmMsg:\n sender: {}\n {:?}", + sender, msg + )) + } + fn query( &self, api: &dyn Api, @@ -212,50 +281,33 @@ where ); to_json_binary(&res).map_err(Into::into) } - other => bail!(Error::UnsupportedWasmQuery(other)), + _ => unimplemented!("{}", Error::unsupported_wasm_query(request)), } } - fn execute( - &self, - api: &dyn Api, - storage: &mut dyn Storage, - router: &dyn CosmosRouter, - block: &BlockInfo, - sender: Addr, - msg: WasmMsg, - ) -> AnyResult { - self.execute_wasm(api, storage, router, block, sender.clone(), msg.clone()) - .context(format!( - "Error executing WasmMsg:\n sender: {}\n {:?}", - sender, msg - )) - } - fn sudo( &self, api: &dyn Api, - contract: Addr, storage: &mut dyn Storage, router: &dyn CosmosRouter, block: &BlockInfo, - msg: Binary, + msg: WasmSudo, ) -> AnyResult { - let custom_event = Event::new("sudo").add_attribute(CONTRACT_ATTR, &contract); + let custom_event = Event::new("sudo").add_attribute(CONTRACT_ATTR, &msg.contract_addr); let querier_storage = router.get_querier_storage(storage)?; let res = self.call_sudo( - contract.clone(), + msg.contract_addr.clone(), api, storage, router, block, - msg.to_vec(), + msg.message.to_vec(), querier_storage, )?; - let (res, msgs) = self.build_app_response(&contract, custom_event, res); - self.process_response(api, router, storage, block, contract, res, msgs) + let (res, msgs) = self.build_app_response(&msg.contract_addr, custom_event, res); + self.process_response(api, router, storage, block, msg.contract_addr, res, msgs) } /// Stores the contract's code in the in-memory lookup table. @@ -268,38 +320,54 @@ where }); self.code_base.borrow_mut().insert(code_id, code); - let checksum = self.checksum_generator.checksum(&creator, code_id as u64); - self.code_data.insert( - code_id, - CodeData { - creator, - checksum, - code_base_id: code_id, - }, - ); - code_id as u64 + self.save_code_data(code_id as u64, creator) } /// Stores the contract's code in the in-memory lookup table. /// Returns an identifier of the stored contract code. fn store_code(&mut self, creator: Addr, code: Box>) -> u64 { let code_id = self.rust_codes.len() + 1 + LOCAL_RUST_CODE_OFFSET; - let checksum = code - .checksum() - .unwrap_or(self.checksum_generator.checksum(&creator, code_id as u64)); - let static_ref = Box::leak(code); + let static_ref = Box::leak(code); let raw_pointer = static_ref as *mut dyn Contract; self.rust_codes.insert(code_id, raw_pointer); + self.save_code_data(code_id as u64, creator) + } + + /// Stores the contract's code in the in-memory lookup table. + /// Returns an identifier of the stored contract code. + fn store_code_with_id( + &mut self, + creator: Addr, + code_id: u64, + code: Box>, + ) -> AnyResult { + // validate provided contract code identifier + if self.code_data.contains_key(&(code_id as usize)) { + bail!(Error::duplicated_code_id(code_id)); + } else if code_id == 0 { + bail!(Error::invalid_code_id()); + } + let static_ref = Box::leak(code); + let raw_pointer = static_ref as *mut dyn Contract; + self.rust_codes.insert(code_id as usize, raw_pointer); + Ok(self.save_code_data(code_id, creator)) + } + + /// Duplicates the contract's code with specified identifier. + /// Returns an identifier of the copy of the contract's code. + fn duplicate_code(&mut self, code_id: u64) -> AnyResult { + let code_data = self.code_data(code_id)?; + let new_code_id = self.code_base.borrow().len() + 1 + LOCAL_WASM_CODE_OFFSET; self.code_data.insert( - code_id, + new_code_id, CodeData { - creator, - checksum, - code_base_id: code_id, + creator: code_data.creator.clone(), + checksum: code_data.checksum, + code_base_id: code_data.code_base_id, }, ); - code_id as u64 + Ok(new_code_id as u64) } /// Returns `ContractData` for the contract with specified address. @@ -314,7 +382,7 @@ where /// Returns a raw state dump of all key-values held by a contract with specified address. fn dump_wasm_raw(&self, storage: &dyn Storage, address: &Addr) -> Vec { - let storage = self.contract_storage_readonly(storage, address); + let storage = self.contract_storage(storage, address); storage.range(None, None, Order::Ascending).collect() } } @@ -387,7 +455,7 @@ where /// Returns code data of the contract with specified code id. fn code_data(&self, code_id: u64) -> AnyResult { if code_id < 1 { - bail!(Error::InvalidCodeId); + bail!(Error::invalid_code_id()); } if let Some(code_data) = self.code_data.get(&(code_id as usize)) { Ok(code_data.clone()) @@ -403,82 +471,10 @@ where } pub fn dump_wasm_raw(&self, storage: &dyn Storage, address: &Addr) -> Vec { - let storage = self.contract_storage_readonly(storage, address); + let storage = self.contract_storage(storage, address); storage.range(None, None, Order::Ascending).collect() } - fn contract_namespace(&self, contract: &Addr) -> Vec { - contract_namespace(contract) - } - - fn contract_storage<'a>( - &self, - storage: &'a mut dyn Storage, - address: &Addr, - ) -> Box { - // We double-namespace this, once from global storage -> wasm_storage - // then from wasm_storage -> the contracts subspace - let namespace = self.contract_namespace(address); - let storage = PrefixedStorage::multilevel(storage, &[NAMESPACE_WASM, &namespace]); - - Box::new(storage) - } - - // fails RUNTIME if you try to write. please don't - fn contract_storage_readonly<'a>( - &self, - storage: &'a dyn Storage, - address: &Addr, - ) -> Box { - // We double-namespace this, once from global storage -> wasm_storage - // then from wasm_storage -> the contracts subspace - let namespace = self.contract_namespace(address); - let storage = ReadonlyPrefixedStorage::multilevel(storage, &[NAMESPACE_WASM, &namespace]); - Box::new(storage) - } -} -impl WasmKeeper -where - ExecC: CustomMsg + DeserializeOwned + 'static, - QueryC: CustomQuery + DeserializeOwned + 'static, -{ - pub fn new() -> Self { - Self::default() - } - - #[deprecated( - since = "0.18.0", - note = "use `WasmKeeper::new().with_address_generator` instead; will be removed in version 1.0.0" - )] - pub fn new_with_custom_address_generator( - address_generator: impl AddressGenerator + 'static, - ) -> Self { - Self { - address_generator: Box::new(address_generator), - ..Default::default() - } - } - - pub fn with_remote(mut self, remote: RemoteChannel) -> Self { - self.remote = Some(remote); - self - } - pub fn with_address_generator( - mut self, - address_generator: impl AddressGenerator + 'static, - ) -> Self { - self.address_generator = Box::new(address_generator); - self - } - - pub fn with_checksum_generator( - mut self, - checksum_generator: impl ChecksumGenerator + 'static, - ) -> Self { - self.checksum_generator = Box::new(checksum_generator); - self - } - /// Validates all attributes. /// /// In `wasmd`, before version v0.45.0 empty attribute values were not allowed. @@ -515,7 +511,119 @@ where Ok(response) } - /// Executes the contract's `query` entry-point. + fn save_code_data(&mut self, code_id: u64, creator: Addr) -> u64 { + // calculate the checksum of the contract 'source' code based on code_id + let checksum = self.checksum_generator.checksum(&creator, code_id); + // store the additional code attributes like creator address and checksum + self.code_data.insert( + code_id as usize, + CodeData { + creator, + checksum, + code_base_id: code_id as usize, + }, + ); + code_id + } +} +impl WasmKeeper +where + ExecC: CustomMsg + DeserializeOwned + 'static, + QueryC: CustomQuery + DeserializeOwned + 'static, +{ + /// Creates a wasm keeper with default settings. + /// + /// # Example + /// + /// ``` + /// use cw_multi_test::{AppBuilder, no_init, WasmKeeper}; + /// + /// // create wasm keeper + /// let wasm_keeper = WasmKeeper::new(); + /// + /// // create and use the application with newly created wasm keeper + /// let mut app = AppBuilder::default().with_wasm(wasm_keeper).build(no_init); + /// ``` + pub fn new() -> Self { + Self::default() + } + /// Populates an existing [WasmKeeper] with custom contract address generator. + /// + /// # Example + /// + /// ``` + /// use cosmwasm_std::{Addr, Api, Storage}; + /// use cw_multi_test::{AddressGenerator, AppBuilder, no_init, WasmKeeper}; + /// use cw_multi_test::error::AnyResult; + /// # use cosmwasm_std::testing::MockApi; + /// + /// struct CustomAddressGenerator; + /// + /// impl AddressGenerator for CustomAddressGenerator { + /// fn contract_address( + /// &self, + /// api: &dyn Api, + /// storage: &mut dyn Storage, + /// code_id: u64, + /// instance_id: u64, + /// ) -> AnyResult { + /// // here implement your address generation logic + /// # Ok(MockApi::default().addr_make("test_address")) + /// } + /// } + /// + /// // populate wasm with your custom address generator + /// let wasm_keeper = WasmKeeper::new().with_address_generator(CustomAddressGenerator); + /// + /// // create and use the application with customized wasm keeper + /// let mut app = AppBuilder::default().with_wasm(wasm_keeper).build(no_init); + /// ``` + pub fn with_address_generator( + mut self, + address_generator: impl AddressGenerator + 'static, + ) -> Self { + self.address_generator = Box::new(address_generator); + self + } + + /// Populates an existing [WasmKeeper] with custom checksum generator for the contract code. + /// + /// # Example + /// + /// ``` + /// use cosmwasm_std::{Addr, Checksum}; + /// use cw_multi_test::{AppBuilder, ChecksumGenerator, no_init, WasmKeeper}; + /// + /// struct MyChecksumGenerator; + /// + /// impl ChecksumGenerator for MyChecksumGenerator { + /// fn checksum(&self, creator: &Addr, code_id: u64) -> Checksum { + /// // here implement your custom checksum generator + /// # Checksum::from_hex("custom_checksum").unwrap() + /// } + /// } + /// + /// // populate wasm keeper with your custom checksum generator + /// let wasm_keeper = WasmKeeper::new().with_checksum_generator(MyChecksumGenerator); + /// + /// // create and use the application with customized wasm keeper + /// let mut app = AppBuilder::default().with_wasm(wasm_keeper).build(no_init); + /// ``` + pub fn with_checksum_generator( + mut self, + checksum_generator: impl ChecksumGenerator + 'static, + ) -> Self { + self.checksum_generator = Box::new(checksum_generator); + self + } + + /// Specify the remote location of this wasm + pub fn with_remote(mut self, remote: RemoteChannel) -> Self { + self.remote = Some(remote); + self + } + + /// Executes contract's `query` entry-point. pub fn query_smart( &self, address: Addr, @@ -549,8 +657,9 @@ where ) } + /// Returns the value stored under specified key in contracts storage. pub fn query_raw(&self, address: Addr, storage: &dyn Storage, key: &[u8]) -> Binary { - let local_key = self.contract_storage_readonly(storage, &address).get(key); + let local_key = self.contract_storage(storage, &address).get(key); if let Some(local_key) = local_key { local_key.into() } else { @@ -622,9 +731,9 @@ where router: &dyn CosmosRouter, block: &BlockInfo, sender: Addr, - wasm_msg: WasmMsg, + msg: WasmMsg, ) -> AnyResult { - match wasm_msg { + match msg { WasmMsg::Execute { contract_addr, msg, @@ -740,7 +849,7 @@ where WasmMsg::ClearAdmin { contract_addr } => { self.update_admin(api, storage, sender, &contract_addr, None) } - msg => bail!(Error::UnsupportedWasmMsg(msg)), + _ => unimplemented!("{}", Error::unsupported_wasm_message(msg)), } } @@ -850,6 +959,8 @@ where if matches!(reply_on, ReplyOn::Always | ReplyOn::Success) { let reply = Reply { id, + payload: Default::default(), + gas_used: 0, result: SubMsgResult::Ok( #[allow(deprecated)] SubMsgResponse { @@ -858,8 +969,6 @@ where msg_responses: vec![], }, ), - payload: Default::default(), - gas_used: 0, }; // do reply and combine it with the original response let reply_res = self.reply(api, router, storage, block, contract, reply)?; @@ -871,15 +980,14 @@ where // reply is not called, no data should be returned r.data = None; } - Ok(r) } else if let Err(e) = res { if matches!(reply_on, ReplyOn::Always | ReplyOn::Error) { let reply = Reply { id, - result: SubMsgResult::Err(format!("{:?}", e)), payload: Default::default(), gas_used: 0, + result: SubMsgResult::Err(format!("{:?}", e)), }; self.reply(api, router, storage, block, contract, reply) } else { @@ -1036,6 +1144,7 @@ where Ok(addr) } + /// Executes contract's `execute` entry-point. pub fn call_execute( &self, api: &dyn Api, @@ -1072,6 +1181,7 @@ where )?) } + /// Executes contract's `instantiate` entry-point. pub fn call_instantiate( &self, address: Addr, @@ -1108,6 +1218,7 @@ where )?) } + /// Executes contract's `reply` entry-point. pub fn call_reply( &self, address: Addr, @@ -1141,6 +1252,7 @@ where )?) } + /// Executes contract's `sudo` entry-point. pub fn call_sudo( &self, address: Addr, @@ -1174,6 +1286,7 @@ where )?) } + /// Executes contract's `migrate` entry-point. pub fn call_migrate( &self, address: Addr, @@ -1232,7 +1345,7 @@ where { let contract = self.contract_data(storage, &address)?; let handler = self.contract_code::<'a, 'b>(contract.code_id)?; - let storage = self.contract_storage_readonly(storage, &address); + let storage = self.contract_storage(storage, &address); let env = self.get_env(address, block); let deps = Deps { @@ -1265,7 +1378,7 @@ where // However, we need to get write and read access to the same storage in two different objects, // and this is the only way I know how to do so. transactional(storage, |write_cache, read_store| { - let mut contract_storage = self.contract_storage(write_cache, &address); + let mut contract_storage = self.contract_storage_mut(write_cache, &address); let querier = RouterQuerier::new(router, api, read_store, block); let env = self.get_env(address, block); @@ -1278,6 +1391,7 @@ where }) } + /// Saves contract data in a storage under specified address. pub fn save_contract( &self, storage: &mut dyn Storage, @@ -1302,17 +1416,14 @@ where } } -// TODO: replace with code in utils - #[derive(Clone, PartialEq, Message)] struct InstantiateResponse { #[prost(string, tag = "1")] - pub address: ::prost::alloc::string::String, + pub address: String, #[prost(bytes, tag = "2")] - pub data: ::prost::alloc::vec::Vec, + pub data: Vec, } -// TODO: encode helpers in utils fn instantiate_response(data: Option, contact_address: &Addr) -> Binary { let data = data.unwrap_or_default().to_vec(); let init_data = InstantiateResponse { @@ -1328,7 +1439,7 @@ fn instantiate_response(data: Option, contact_address: &Addr) -> Binary #[derive(Clone, PartialEq, Message)] struct ExecuteResponse { #[prost(bytes, tag = "1")] - pub data: ::prost::alloc::vec::Vec, + pub data: Vec, } // empty return if no data present in original @@ -1341,3 +1452,890 @@ fn execute_response(data: Option) -> Option { new_data.into() }) } + +#[cfg(test)] +mod test { + use super::*; + use crate::app::Router; + use crate::bank::BankKeeper; + use crate::module::FailingModule; + use crate::staking::{DistributionKeeper, StakeKeeper}; + use crate::test_helpers::{caller, error, payout}; + use crate::transactions::StorageTransaction; + use crate::{GovFailingModule, IbcFailingModule, StargateFailing}; + use cosmwasm_std::testing::{message_info, mock_env, MockApi, MockQuerier, MockStorage}; + #[cfg(feature = "cosmwasm_1_2")] + use cosmwasm_std::CodeInfoResponse; + use cosmwasm_std::{ + coin, from_json, to_json_vec, CanonicalAddr, CosmosMsg, Empty, HexBinary, StdError, + }; + + /// Type alias for default build `Router` to make its reference in typical scenario + type BasicRouter = Router< + BankKeeper, + FailingModule, + WasmKeeper, + StakeKeeper, + DistributionKeeper, + IbcFailingModule, + GovFailingModule, + StargateFailing, + >; + + fn wasm_keeper() -> WasmKeeper { + WasmKeeper::new() + } + + fn mock_router() -> BasicRouter { + Router { + wasm: WasmKeeper::new(), + bank: BankKeeper::new(), + custom: FailingModule::new(), + staking: StakeKeeper::new(), + distribution: DistributionKeeper::new(), + ibc: IbcFailingModule::new(), + gov: GovFailingModule::new(), + stargate: StargateFailing, + } + } + + #[test] + fn register_contract() { + let api = MockApi::default(); + + // prepare user addresses + let creator_addr = api.addr_make("creator"); + let user_addr = api.addr_make("foobar"); + let admin_addr = api.addr_make("admin"); + let unregistered_addr = api.addr_make("unregistered"); + + let mut wasm_storage = MockStorage::new(); + let mut wasm_keeper = wasm_keeper(); + let block = mock_env().block; + let code_id = wasm_keeper.store_code(creator_addr, error::contract(false)); + + transactional(&mut wasm_storage, |cache, _| { + // cannot register contract with unregistered codeId + wasm_keeper.register_contract( + &api, + cache, + code_id + 1, + user_addr.clone(), + admin_addr.clone(), + "label".to_owned(), + 1000, + None, + ) + }) + .unwrap_err(); + + let contract_addr = transactional(&mut wasm_storage, |cache, _| { + // we can register a new instance of this code + wasm_keeper.register_contract( + &api, + cache, + code_id, + user_addr.clone(), + admin_addr.clone(), + "label".to_owned(), + 1000, + None, + ) + }) + .unwrap(); + + // verify contract data are as expected + let contract_data = wasm_keeper + .contract_data(&wasm_storage, &contract_addr) + .unwrap(); + + assert_eq!( + contract_data, + ContractData { + code_id, + creator: user_addr.clone(), + admin: admin_addr.into(), + label: "label".to_owned(), + created: 1000, + } + ); + + let err = transactional(&mut wasm_storage, |cache, _| { + // now, we call this contract and see the error message from the contract + let info = message_info(&user_addr, &[]); + wasm_keeper.call_instantiate( + contract_addr.clone(), + &api, + cache, + &mock_router(), + &block, + info, + b"{}".to_vec(), + ) + }) + .unwrap_err(); + + // StdError from contract_error auto-converted to string + assert_eq!( + StdError::generic_err("Init failed"), + err.downcast().unwrap() + ); + + let err = transactional(&mut wasm_storage, |cache, _| { + // and the error for calling an unregistered contract + let info = message_info(&user_addr, &[]); + wasm_keeper.call_instantiate( + unregistered_addr, + &api, + cache, + &mock_router(), + &block, + info, + b"{}".to_vec(), + ) + }) + .unwrap_err(); + + // Default error message from router when not found + assert!(matches!(err.downcast().unwrap(), StdError::NotFound { .. })); + } + + #[test] + fn query_contract_info() { + let api = MockApi::default(); + + // prepare user addresses + let creator_addr = api.addr_make("creator"); + let admin_addr = api.addr_make("admin"); + + let mut wasm_storage = MockStorage::new(); + let mut wasm_keeper = wasm_keeper(); + let block = mock_env().block; + let code_id = wasm_keeper.store_code(creator_addr.clone(), payout::contract()); + assert_eq!(1, code_id); + + let contract_addr = wasm_keeper + .register_contract( + &api, + &mut wasm_storage, + code_id, + creator_addr.clone(), + admin_addr.clone(), + "label".to_owned(), + 1000, + None, + ) + .unwrap(); + + let querier: MockQuerier = MockQuerier::new(&[]); + let query = WasmQuery::ContractInfo { + contract_addr: contract_addr.into(), + }; + + let contract_info = wasm_keeper + .query(&api, &wasm_storage, &querier, &block, query) + .unwrap(); + + let actual: ContractInfoResponse = from_json(contract_info).unwrap(); + let expected = + ContractInfoResponse::new(code_id, creator_addr, admin_addr.into(), false, None); + assert_eq!(expected, actual); + } + + #[test] + #[cfg(feature = "cosmwasm_1_2")] + fn query_code_info() { + let api = MockApi::default(); + let wasm_storage = MockStorage::new(); + let mut wasm_keeper = wasm_keeper(); + let block = mock_env().block; + let creator_addr = api.addr_make("creator"); + let code_id = wasm_keeper.store_code(creator_addr.clone(), payout::contract()); + let querier: MockQuerier = MockQuerier::new(&[]); + let query = WasmQuery::CodeInfo { code_id }; + let code_info = wasm_keeper + .query(&api, &wasm_storage, &querier, &block, query) + .unwrap(); + let actual: CodeInfoResponse = from_json(code_info).unwrap(); + assert_eq!(code_id, actual.code_id); + assert_eq!(creator_addr.as_str(), actual.creator.as_str()); + assert_eq!(32, actual.checksum.as_slice().len()); + } + + #[test] + #[cfg(feature = "cosmwasm_1_2")] + fn different_contracts_must_have_different_checksum() { + let api = MockApi::default(); + let creator_addr = api.addr_make("creator"); + let wasm_storage = MockStorage::new(); + let mut wasm_keeper = wasm_keeper(); + let block = mock_env().block; + let code_id_payout = wasm_keeper.store_code(creator_addr.clone(), payout::contract()); + let code_id_caller = wasm_keeper.store_code(creator_addr, caller::contract()); + let querier: MockQuerier = MockQuerier::new(&[]); + let query_payout = WasmQuery::CodeInfo { + code_id: code_id_payout, + }; + let query_caller = WasmQuery::CodeInfo { + code_id: code_id_caller, + }; + let code_info_payout = wasm_keeper + .query(&api, &wasm_storage, &querier, &block, query_payout) + .unwrap(); + let code_info_caller = wasm_keeper + .query(&api, &wasm_storage, &querier, &block, query_caller) + .unwrap(); + let info_payout: CodeInfoResponse = from_json(code_info_payout).unwrap(); + let info_caller: CodeInfoResponse = from_json(code_info_caller).unwrap(); + assert_eq!(code_id_payout, info_payout.code_id); + assert_eq!(code_id_caller, info_caller.code_id); + assert_ne!(info_caller.code_id, info_payout.code_id); + assert_eq!(info_caller.creator, info_payout.creator); + assert_ne!(info_caller.checksum, info_payout.checksum); + } + + #[test] + #[cfg(feature = "cosmwasm_1_2")] + fn querying_invalid_code_info_must_fail() { + let api = MockApi::default(); + let wasm_storage = MockStorage::new(); + let wasm_keeper = wasm_keeper(); + let block = mock_env().block; + + let querier: MockQuerier = MockQuerier::new(&[]); + let query = WasmQuery::CodeInfo { code_id: 100 }; + + wasm_keeper + .query(&api, &wasm_storage, &querier, &block, query) + .unwrap_err(); + } + + #[test] + fn can_dump_raw_wasm_state() { + let api = MockApi::default(); + + // prepare user addresses + let creator_addr = api.addr_make("creator"); + let admin_addr = api.addr_make("admin"); + let user_addr = api.addr_make("foobar"); + + let mut wasm_keeper = wasm_keeper(); + let block = mock_env().block; + let code_id = wasm_keeper.store_code(creator_addr, payout::contract()); + + let mut wasm_storage = MockStorage::new(); + + let contract_addr = wasm_keeper + .register_contract( + &api, + &mut wasm_storage, + code_id, + user_addr.clone(), + admin_addr, + "label".to_owned(), + 1000, + None, + ) + .unwrap(); + + // make a contract with state + let payout = coin(1500, "mlg"); + let msg = payout::InstantiateMessage { + payout: payout.clone(), + }; + wasm_keeper + .call_instantiate( + contract_addr.clone(), + &api, + &mut wasm_storage, + &mock_router(), + &block, + message_info(&user_addr, &[]), + to_json_vec(&msg).unwrap(), + ) + .unwrap(); + + // dump state + let state = wasm_keeper.dump_wasm_raw(&wasm_storage, &contract_addr); + assert_eq!(state.len(), 2); + // check contents + let (k, v) = &state[0]; + assert_eq!(k.as_slice(), b"count"); + let count: u32 = from_json(v).unwrap(); + assert_eq!(count, 1); + let (k, v) = &state[1]; + assert_eq!(k.as_slice(), b"payout"); + let stored_pay: payout::InstantiateMessage = from_json(v).unwrap(); + assert_eq!(stored_pay.payout, payout); + } + + #[test] + fn contract_send_coins() { + let api = MockApi::default(); + + // prepare user addresses + let creator_addr = api.addr_make("creator"); + let user_addr = api.addr_make("foobar"); + + let mut wasm_keeper = wasm_keeper(); + let block = mock_env().block; + let code_id = wasm_keeper.store_code(creator_addr, payout::contract()); + + let mut wasm_storage = MockStorage::new(); + let mut cache = StorageTransaction::new(&wasm_storage); + + let contract_addr = wasm_keeper + .register_contract( + &api, + &mut cache, + code_id, + user_addr.clone(), + None, + "label".to_owned(), + 1000, + None, + ) + .unwrap(); + + let payout = coin(100, "TGD"); + + // init the contract + let info = message_info(&user_addr, &[]); + let init_msg = to_json_vec(&payout::InstantiateMessage { + payout: payout.clone(), + }) + .unwrap(); + let res = wasm_keeper + .call_instantiate( + contract_addr.clone(), + &api, + &mut cache, + &mock_router(), + &block, + info, + init_msg, + ) + .unwrap(); + assert_eq!(0, res.messages.len()); + + // execute the contract + let info = message_info(&user_addr, &[]); + let res = wasm_keeper + .call_execute( + &api, + &mut cache, + contract_addr.clone(), + &mock_router(), + &block, + info, + b"{}".to_vec(), + ) + .unwrap(); + assert_eq!(1, res.messages.len()); + match &res.messages[0].msg { + CosmosMsg::Bank(BankMsg::Send { to_address, amount }) => { + assert_eq!(to_address.as_str(), user_addr.as_str()); + assert_eq!(amount.as_slice(), &[payout.clone()]); + } + m => panic!("Unexpected message {:?}", m), + } + + // and flush before query + cache.prepare().commit(&mut wasm_storage); + + // query the contract + let query = to_json_vec(&payout::QueryMsg::Payout {}).unwrap(); + let querier: MockQuerier = MockQuerier::new(&[]); + let data = wasm_keeper + .query_smart(contract_addr, &api, &wasm_storage, &querier, &block, query) + .unwrap(); + let res: payout::InstantiateMessage = from_json(data).unwrap(); + assert_eq!(res.payout, payout); + } + + fn assert_payout( + router: &WasmKeeper, + storage: &mut dyn Storage, + contract_addr: &Addr, + payout: &Coin, + ) { + let api = MockApi::default(); + let user_addr = api.addr_make("silly"); + let info = message_info(&user_addr, &[]); + let res = router + .call_execute( + &api, + storage, + contract_addr.clone(), + &mock_router(), + &mock_env().block, + info, + b"{}".to_vec(), + ) + .unwrap(); + assert_eq!(1, res.messages.len()); + match &res.messages[0].msg { + CosmosMsg::Bank(BankMsg::Send { to_address, amount }) => { + assert_eq!(to_address.as_str(), user_addr.as_str()); + assert_eq!(amount.as_slice(), &[payout.clone()]); + } + m => panic!("Unexpected message {:?}", m), + } + } + + fn assert_no_contract(storage: &dyn Storage, contract_addr: &Addr) { + let contract = CONTRACTS.may_load(storage, contract_addr).unwrap(); + assert!(contract.is_none(), "{:?}", contract_addr); + } + + #[test] + fn multi_level_wasm_cache() { + let api = MockApi::default(); + + // prepare user addresses + let creator_addr = api.addr_make("creator"); + let user_addr = api.addr_make("foobar"); + let user_addr_1 = api.addr_make("johnny"); + + let mut wasm_keeper = wasm_keeper(); + let block = mock_env().block; + let code_id = wasm_keeper.store_code(creator_addr, payout::contract()); + + let mut wasm_storage = MockStorage::new(); + + let payout1 = coin(100, "TGD"); + + // set contract 1 and commit (on router) + let contract1 = transactional(&mut wasm_storage, |cache, _| { + let contract = wasm_keeper + .register_contract( + &api, + cache, + code_id, + user_addr.clone(), + None, + "".to_string(), + 1000, + None, + ) + .unwrap(); + let info = message_info(&user_addr, &[]); + let init_msg = to_json_vec(&payout::InstantiateMessage { + payout: payout1.clone(), + }) + .unwrap(); + wasm_keeper + .call_instantiate( + contract.clone(), + &api, + cache, + &mock_router(), + &block, + info, + init_msg, + ) + .unwrap(); + + Ok(contract) + }) + .unwrap(); + + let payout2 = coin(50, "BTC"); + let payout3 = coin(1234, "ATOM"); + + // create a new cache and check we can use contract 1 + let (contract2, contract3) = transactional(&mut wasm_storage, |cache, wasm_reader| { + assert_payout(&wasm_keeper, cache, &contract1, &payout1); + + // create contract 2 and use it + let contract2 = wasm_keeper + .register_contract( + &api, + cache, + code_id, + user_addr.clone(), + None, + "".to_owned(), + 1000, + None, + ) + .unwrap(); + let info = message_info(&user_addr, &[]); + let init_msg = to_json_vec(&payout::InstantiateMessage { + payout: payout2.clone(), + }) + .unwrap(); + let _res = wasm_keeper + .call_instantiate( + contract2.clone(), + &api, + cache, + &mock_router(), + &block, + info, + init_msg, + ) + .unwrap(); + assert_payout(&wasm_keeper, cache, &contract2, &payout2); + + // create a level2 cache and check we can use contract 1 and contract 2 + let contract3 = transactional(cache, |cache2, read| { + assert_payout(&wasm_keeper, cache2, &contract1, &payout1); + assert_payout(&wasm_keeper, cache2, &contract2, &payout2); + + // create a contract on level 2 + let contract3 = wasm_keeper + .register_contract( + &api, + cache2, + code_id, + user_addr, + None, + "".to_owned(), + 1000, + None, + ) + .unwrap(); + let info = message_info(&user_addr_1, &[]); + let init_msg = to_json_vec(&payout::InstantiateMessage { + payout: payout3.clone(), + }) + .unwrap(); + let _res = wasm_keeper + .call_instantiate( + contract3.clone(), + &api, + cache2, + &mock_router(), + &block, + info, + init_msg, + ) + .unwrap(); + assert_payout(&wasm_keeper, cache2, &contract3, &payout3); + + // ensure first cache still doesn't see this contract + assert_no_contract(read, &contract3); + Ok(contract3) + }) + .unwrap(); + + // after applying transaction, all contracts present on cache + assert_payout(&wasm_keeper, cache, &contract1, &payout1); + assert_payout(&wasm_keeper, cache, &contract2, &payout2); + assert_payout(&wasm_keeper, cache, &contract3, &payout3); + + // but not yet the root router + assert_no_contract(wasm_reader, &contract1); + assert_no_contract(wasm_reader, &contract2); + assert_no_contract(wasm_reader, &contract3); + + Ok((contract2, contract3)) + }) + .unwrap(); + + // ensure that it is now applied to the router + assert_payout(&wasm_keeper, &mut wasm_storage, &contract1, &payout1); + assert_payout(&wasm_keeper, &mut wasm_storage, &contract2, &payout2); + assert_payout(&wasm_keeper, &mut wasm_storage, &contract3, &payout3); + } + + fn assert_admin( + storage: &dyn Storage, + wasm_keeper: &WasmKeeper, + contract_addr: &impl ToString, + admin: Option, + ) { + let api = MockApi::default(); + let querier: MockQuerier = MockQuerier::new(&[]); + // query + let data = wasm_keeper + .query( + &api, + storage, + &querier, + &mock_env().block, + WasmQuery::ContractInfo { + contract_addr: contract_addr.to_string(), + }, + ) + .unwrap(); + let res: ContractInfoResponse = from_json(data).unwrap(); + assert_eq!(res.admin, admin); + } + + #[test] + fn update_clear_admin_works() { + let api = MockApi::default(); + let mut wasm_keeper = wasm_keeper(); + let block = mock_env().block; + let creator = api.addr_make("creator"); + let code_id = wasm_keeper.store_code(creator.clone(), caller::contract()); + + let mut wasm_storage = MockStorage::new(); + + let admin = api.addr_make("admin"); + let new_admin = api.addr_make("new_admin"); + let normal_user = api.addr_make("normal_user"); + + let contract_addr = wasm_keeper + .register_contract( + &api, + &mut wasm_storage, + code_id, + creator, + admin.clone(), + "label".to_owned(), + 1000, + None, + ) + .unwrap(); + + // init the contract + let info = message_info(&admin, &[]); + let init_msg = to_json_vec(&Empty {}).unwrap(); + let res = wasm_keeper + .call_instantiate( + contract_addr.clone(), + &api, + &mut wasm_storage, + &mock_router(), + &block, + info, + init_msg, + ) + .unwrap(); + assert_eq!(0, res.messages.len()); + + assert_admin( + &wasm_storage, + &wasm_keeper, + &contract_addr, + Some(admin.clone()), + ); + + // non-admin should not be allowed to become admin on their own + wasm_keeper + .execute_wasm( + &api, + &mut wasm_storage, + &mock_router(), + &block, + normal_user.clone(), + WasmMsg::UpdateAdmin { + contract_addr: contract_addr.to_string(), + admin: normal_user.to_string(), + }, + ) + .unwrap_err(); + + // should still be admin + assert_admin( + &wasm_storage, + &wasm_keeper, + &contract_addr, + Some(admin.clone()), + ); + + // admin should be allowed to transfer administration permissions + let res = wasm_keeper + .execute_wasm( + &api, + &mut wasm_storage, + &mock_router(), + &block, + admin, + WasmMsg::UpdateAdmin { + contract_addr: contract_addr.to_string(), + admin: new_admin.to_string(), + }, + ) + .unwrap(); + assert_eq!(res.events.len(), 0); + + // new_admin should now be admin + assert_admin( + &wasm_storage, + &wasm_keeper, + &contract_addr, + Some(new_admin.clone()), + ); + + // new_admin should now be able to clear to admin + let res = wasm_keeper + .execute_wasm( + &api, + &mut wasm_storage, + &mock_router(), + &block, + new_admin, + WasmMsg::ClearAdmin { + contract_addr: contract_addr.to_string(), + }, + ) + .unwrap(); + assert_eq!(res.events.len(), 0); + + // should have no admin now + assert_admin(&wasm_storage, &wasm_keeper, &contract_addr, None); + } + + #[test] + fn uses_simple_address_generator_by_default() { + let api = MockApi::default(); + let mut wasm_keeper = wasm_keeper(); + let creator_addr = api.addr_make("creator"); + let code_id = wasm_keeper.store_code(creator_addr.clone(), payout::contract()); + assert_eq!(1, code_id); + + let mut wasm_storage = MockStorage::new(); + + let admin = api.addr_make("admin"); + let contract_addr = wasm_keeper + .register_contract( + &api, + &mut wasm_storage, + code_id, + creator_addr.clone(), + admin.clone(), + "label".to_owned(), + 1000, + None, + ) + .unwrap(); + + assert_eq!( + contract_addr.as_str(), + "cosmwasm1mzdhwvvh22wrt07w59wxyd58822qavwkx5lcej7aqfkpqqlhaqfsgn6fq2", + "default address generator returned incorrect address" + ); + + let salt = HexBinary::from_hex("c0ffee").unwrap(); + + let contract_addr = wasm_keeper + .register_contract( + &api, + &mut wasm_storage, + code_id, + creator_addr.clone(), + admin.clone(), + "label".to_owned(), + 1000, + Binary::from(salt.clone()), + ) + .unwrap(); + + assert_eq!( + contract_addr.as_str(), + "cosmwasm1drhu6t78wacgm5qjzs4hvkv9fd9awa9henw7fh6vmzrhf7k2nkjsg3flns", + "default address generator returned incorrect address" + ); + + let code_id = wasm_keeper.store_code(creator_addr, payout::contract()); + assert_eq!(2, code_id); + + let user_addr = api.addr_make("boobaz"); + + let contract_addr = wasm_keeper + .register_contract( + &api, + &mut wasm_storage, + code_id, + user_addr, + admin, + "label".to_owned(), + 1000, + Binary::from(salt), + ) + .unwrap(); + + assert_eq!( + contract_addr.as_str(), + "cosmwasm13cfeertf2gny0rzp5jwqzst8crmfgvcd2lq5su0c9z66yxa45qdsdd0uxc", + "default address generator returned incorrect address" + ); + } + + struct TestAddressGenerator { + address: Addr, + predictable_address: Addr, + } + + impl AddressGenerator for TestAddressGenerator { + fn contract_address( + &self, + _api: &dyn Api, + _storage: &mut dyn Storage, + _code_id: u64, + _instance_id: u64, + ) -> AnyResult { + Ok(self.address.clone()) + } + + fn predictable_contract_address( + &self, + _api: &dyn Api, + _storage: &mut dyn Storage, + _code_id: u64, + _instance_id: u64, + _checksum: &[u8], + _creator: &CanonicalAddr, + _salt: &[u8], + ) -> AnyResult { + Ok(self.predictable_address.clone()) + } + } + + #[test] + fn can_use_custom_address_generator() { + let api = MockApi::default(); + let expected_addr = api.addr_make("address"); + let expected_predictable_addr = api.addr_make("predictable_address"); + let mut wasm_keeper: WasmKeeper = + WasmKeeper::new().with_address_generator(TestAddressGenerator { + address: expected_addr.clone(), + predictable_address: expected_predictable_addr.clone(), + }); + let creator = api.addr_make("creator"); + let code_id = wasm_keeper.store_code(creator.clone(), payout::contract()); + + let mut wasm_storage = MockStorage::new(); + + let admin = api.addr_make("admin"); + let contract_addr = wasm_keeper + .register_contract( + &api, + &mut wasm_storage, + code_id, + creator.clone(), + admin.clone(), + "label".to_owned(), + 1000, + None, + ) + .unwrap(); + + assert_eq!( + contract_addr, expected_addr, + "custom address generator returned incorrect address" + ); + + let contract_addr = wasm_keeper + .register_contract( + &api, + &mut wasm_storage, + code_id, + creator, + admin, + "label".to_owned(), + 1000, + Binary::from(HexBinary::from_hex("23A74B8C").unwrap()), + ) + .unwrap(); + + assert_eq!( + contract_addr, expected_predictable_addr, + "custom address generator returned incorrect address" + ); + } +} diff --git a/src/wasm_emulation/api/mod.rs b/src/wasm_emulation/api/mod.rs index 6e786427..707dea7f 100644 --- a/src/wasm_emulation/api/mod.rs +++ b/src/wasm_emulation/api/mod.rs @@ -1,5 +1,5 @@ use crate::wasm_emulation::query::gas::{GAS_COST_CANONICALIZE, GAS_COST_HUMANIZE}; -use bech32::{FromBase32, ToBase32, Variant}; +use bech32::{Bech32, Hrp}; use cosmwasm_std::Addr; use cosmwasm_vm::{BackendApi, BackendError, GasInfo}; use std::ops::AddAssign; @@ -7,23 +7,23 @@ use std::ops::AddAssign; const SHORT_CANON_LEN: usize = 20; const LONG_CANON_LEN: usize = 32; -pub fn bytes_from_bech32(address: &str, prefix: &str) -> Result, BackendError> { +pub fn bytes_from_bech32(address: &str, prefix: &Hrp) -> Result, BackendError> { if address.is_empty() { return Err(BackendError::Unknown { msg: "empty address string is not allowed".to_string(), }); } - let (hrp, data, _variant) = bech32::decode(address).map_err(|e| BackendError::Unknown { + let (hrp, data) = bech32::decode(address).map_err(|e| BackendError::Unknown { msg: format!("Invalid Bech32 address : Err {}", e), })?; - if hrp != prefix { + if hrp.ne(prefix) { return Err(BackendError::Unknown { msg: format!("invalid Bech32 prefix; expected {}, got {}", prefix, hrp), }); } - Ok(Vec::::from_base32(&data).unwrap()) + Ok(data) } pub const MAX_PREFIX_CHARS: usize = 10; @@ -47,7 +47,7 @@ impl RealApi { Self { prefix: api_prefix } } - pub fn get_prefix(&self) -> String { + pub fn get_prefix(&self) -> Result { let mut prefix = Vec::new(); for &c in self.prefix.iter() { @@ -55,7 +55,8 @@ impl RealApi { prefix.push(c); } } - prefix.iter().collect() + let prefix_string: String = prefix.into_iter().collect(); + Hrp::parse(&prefix_string).map_err(|e| BackendError::Unknown { msg: e.to_string() }) } pub fn next_address(&self, count: usize) -> Addr { @@ -112,7 +113,11 @@ impl BackendApi for RealApi { ); } - (bytes_from_bech32(human, &self.get_prefix()), gas_cost) + ( + self.get_prefix() + .and_then(|prefix| bytes_from_bech32(human, &prefix)), + gas_cost, + ) } fn addr_humanize(&self, canonical: &[u8]) -> cosmwasm_vm::BackendResult { @@ -131,8 +136,10 @@ impl BackendApi for RealApi { return (Ok("".to_string()), gas_cost); } - let human = bech32::encode(&self.get_prefix(), canonical.to_base32(), Variant::Bech32) - .map_err(|e| BackendError::Unknown { msg: e.to_string() }); + let human = self.get_prefix().and_then(|prefix| { + bech32::encode::(prefix, canonical) + .map_err(|e| BackendError::Unknown { msg: e.to_string() }) + }); (human, gas_cost) } @@ -149,7 +156,7 @@ mod test { let api = RealApi::new(prefix); let final_prefix = api.get_prefix(); - assert_eq!(prefix, final_prefix); + assert_eq!(prefix, final_prefix.unwrap().as_str()); } #[test] diff --git a/src/wasm_emulation/input.rs b/src/wasm_emulation/input.rs index 2580b591..3babf5ab 100644 --- a/src/wasm_emulation/input.rs +++ b/src/wasm_emulation/input.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; use cosmwasm_std::Addr; use cosmwasm_std::{Env, MessageInfo, Reply}; @@ -13,8 +13,8 @@ use super::contract::WasmContract; #[derive(Debug, Clone, Default)] pub struct WasmStorage { pub contracts: HashMap, - pub codes: HashMap, - pub code_data: HashMap, + pub codes: BTreeMap, + pub code_data: BTreeMap, pub storage: Vec<(Vec, Vec)>, } diff --git a/src/wasm_emulation/query/wasm.rs b/src/wasm_emulation/query/wasm.rs index 1ad075fa..6d0e53a6 100644 --- a/src/wasm_emulation/query/wasm.rs +++ b/src/wasm_emulation/query/wasm.rs @@ -1,6 +1,5 @@ use std::marker::PhantomData; -use crate::addons::MockApiBech32; use crate::prefixed_storage::get_full_contract_storage_namespace; use crate::queries::wasm::WasmRemoteQuerier; use crate::wasm_emulation::query::gas::{ @@ -8,7 +7,7 @@ use crate::wasm_emulation::query::gas::{ }; use crate::wasm_emulation::query::mock_querier::QueryResultWithGas; use crate::wasm_emulation::query::MockQuerier; -use crate::Contract; +use crate::{Contract, MockApiBech32}; use crate::wasm_emulation::contract::WasmContract; use cosmwasm_std::testing::MockStorage; From a68fa131ad935b0f090d4864b01464ffc9accdae Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 1 Oct 2024 15:59:55 +0000 Subject: [PATCH 67/81] Less diff and better trait structure --- Cargo.toml | 8 +-- examples/cavern_test_app.rs | 13 +---- examples/counter/contract.rs | 6 +- examples/counter/msg.rs | 6 +- examples/counter/query.rs | 2 +- examples/cousin_test.rs | 10 ++-- examples/test_app.rs | 1 + src/app.rs | 53 ++++++----------- src/app_builder.rs | 47 +++++----------- src/bank.rs | 24 ++++---- src/contracts.rs | 11 ++-- src/error.rs | 3 - src/executor.rs | 1 + src/lib.rs | 10 ++-- src/module.rs | 6 +- src/tests/mod.rs | 6 +- src/tests/test_app.rs | 1 + src/wasm.rs | 72 ++++++++++++------------ src/wasm_emulation/query/mod.rs | 11 +++- tests/test_app_builder/test_with_bank.rs | 13 ++++- tests/test_app_builder/test_with_wasm.rs | 11 ++++ 21 files changed, 154 insertions(+), 161 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d3d9c781..419e7b5e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,15 +1,15 @@ [package] -repository = "https://github.com/CosmWasm/cw-multi-test" +name = "clone-cw-multi-test" version = "0.6.2" authors = [ "Ethan Frey ", "Dariusz Depta ", ] -edition = "2021" description = "Testing tools for multi-contract interactions. Helps simulating chain behavior with on-chain storage locally" -license = "Apache-2.0" -name = "clone-cw-multi-test" +repository = "https://github.com/CosmWasm/cw-multi-test" homepage = "https://cosmwasm.com" +license = "Apache-2.0" +edition = "2021" [package.metadata.docs.rs] all-features = true diff --git a/examples/cavern_test_app.rs b/examples/cavern_test_app.rs index 8c3dfe92..4a852c81 100644 --- a/examples/cavern_test_app.rs +++ b/examples/cavern_test_app.rs @@ -1,8 +1,6 @@ use clone_cw_multi_test::{ - wasm_emulation::{ - channel::RemoteChannel, contract::WasmContract, storage::analyzer::StorageAnalyzer, - }, - AppBuilder, BankKeeper, Executor, MockApiBech32, WasmKeeper, + wasm_emulation::{channel::RemoteChannel, storage::analyzer::StorageAnalyzer}, + AppBuilder, Executor, MockApiBech32, }; use cosmwasm_schema::{cw_serde, QueryResponses}; use cosmwasm_std::{coins, Addr, BlockInfo, ContractInfoResponse, QueryRequest, WasmQuery}; @@ -64,9 +62,6 @@ pub fn test() -> anyhow::Result<()> { chain.network_info.pub_address_prefix, )?; - let wasm = WasmKeeper::::new().with_remote(remote_channel.clone()); - let bank = BankKeeper::new().with_remote(remote_channel.clone()); - let block = runtime.block_on( Node { channel: remote_channel.channel.clone(), @@ -76,8 +71,6 @@ pub fn test() -> anyhow::Result<()> { )?; // First we instantiate a new app let app = AppBuilder::default() - .with_wasm(wasm) - .with_bank(bank) .with_remote(remote_channel.clone()) .with_block(BlockInfo { height: block.height, @@ -125,7 +118,7 @@ pub fn test() -> anyhow::Result<()> { let code = std::fs::read( Path::new(env!("CARGO_MANIFEST_DIR")) .join("artifacts") - .join("counter_contract.wasm"), + .join("counter_contract_with_cousin.wasm"), ) .unwrap(); diff --git a/examples/counter/contract.rs b/examples/counter/contract.rs index d60a1065..3df53e71 100644 --- a/examples/counter/contract.rs +++ b/examples/counter/contract.rs @@ -48,9 +48,9 @@ pub fn execute( #[cfg_attr(feature = "export", entry_point)] pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { match msg { - QueryMsg::Count {} => to_json_binary(&query::count(deps)?), - QueryMsg::CousinCount {} => to_json_binary(&query::cousin_count(deps)?), - QueryMsg::RawCousinCount {} => to_json_binary(&query::raw_cousin_count(deps)?), + QueryMsg::GetCount {} => to_json_binary(&query::count(deps)?), + QueryMsg::GetCousinCount {} => to_json_binary(&query::cousin_count(deps)?), + QueryMsg::GetRawCousinCount {} => to_json_binary(&query::raw_cousin_count(deps)?), } } diff --git a/examples/counter/msg.rs b/examples/counter/msg.rs index 5b8d7dd3..bfd81a99 100644 --- a/examples/counter/msg.rs +++ b/examples/counter/msg.rs @@ -36,13 +36,13 @@ pub enum ExecuteMsg { pub enum QueryMsg { /// GetCount returns the current count as a json-encoded number #[returns(GetCountResponse)] - Count {}, + GetCount {}, /// GetCount returns the current count as a json-encoded number #[returns(GetCountResponse)] - CousinCount {}, + GetCousinCount {}, /// GetCount returns the current count as a json-encoded number #[returns(GetCountResponse)] - RawCousinCount {}, + GetRawCousinCount {}, } // Custom response for the query diff --git a/examples/counter/query.rs b/examples/counter/query.rs index ee237c59..31a1d585 100644 --- a/examples/counter/query.rs +++ b/examples/counter/query.rs @@ -15,7 +15,7 @@ pub fn cousin_count(deps: Deps) -> StdResult { let cousin_count: GetCountResponse = deps.querier.query(&QueryRequest::Wasm(WasmQuery::Smart { contract_addr: state.cousin.unwrap().to_string(), - msg: to_json_binary(&QueryMsg::Count {})?, + msg: to_json_binary(&QueryMsg::GetCount {})?, }))?; Ok(cousin_count) } diff --git a/examples/cousin_test.rs b/examples/cousin_test.rs index 71806ebb..e592dc38 100644 --- a/examples/cousin_test.rs +++ b/examples/cousin_test.rs @@ -5,8 +5,8 @@ use std::path::Path; use anyhow::Result as AnyResult; use clone_cw_multi_test::{ - wasm_emulation::channel::RemoteChannel, App, AppBuilder, BankKeeper, ContractWrapper, Executor, - MockApiBech32, WasmKeeper, + wasm_emulation::{channel::RemoteChannel, query::ContainsRemote}, + App, AppBuilder, BankKeeper, ContractWrapper, Executor, MockApiBech32, WasmKeeper, }; use cosmwasm_std::{Addr, Empty}; use counter::msg::{ExecuteMsg, GetCountResponse, QueryMsg}; @@ -30,7 +30,7 @@ fn increment(app: &mut App, contract: Addr) -> AnyRes fn count(app: &App, contract: Addr) -> AnyResult { Ok(app .wrap() - .query_wasm_smart(contract.clone(), &QueryMsg::Count {})?) + .query_wasm_smart(contract.clone(), &QueryMsg::GetCount {})?) } fn raw_cousin_count( @@ -39,7 +39,7 @@ fn raw_cousin_count( ) -> AnyResult { Ok(app .wrap() - .query_wasm_smart(contract.clone(), &QueryMsg::RawCousinCount {})?) + .query_wasm_smart(contract.clone(), &QueryMsg::GetRawCousinCount {})?) } fn cousin_count( @@ -48,7 +48,7 @@ fn cousin_count( ) -> AnyResult { Ok(app .wrap() - .query_wasm_smart(contract.clone(), &QueryMsg::CousinCount {})?) + .query_wasm_smart(contract.clone(), &QueryMsg::GetCousinCount {})?) } fn test() -> AnyResult<()> { diff --git a/examples/test_app.rs b/examples/test_app.rs index d3f92cd3..7e46b5c4 100644 --- a/examples/test_app.rs +++ b/examples/test_app.rs @@ -1,3 +1,4 @@ +use clone_cw_multi_test::wasm_emulation::query::ContainsRemote; use clone_cw_multi_test::{ wasm_emulation::channel::RemoteChannel, AppBuilder, BankKeeper, Executor, WasmKeeper, }; diff --git a/src/app.rs b/src/app.rs index e001bd1f..82c88ee1 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,8 +1,6 @@ -use crate::wasm_emulation::api::RealApi; use crate::wasm_emulation::channel::RemoteChannel; use crate::wasm_emulation::input::QuerierStorage; use cosmwasm_std::CustomMsg; -use cw_storage_plus::Item; use crate::bank::{Bank, BankKeeper, BankSudo}; use crate::error::{bail, AnyResult}; @@ -29,8 +27,6 @@ use serde::{de::DeserializeOwned, Serialize}; use std::fmt::Debug; use std::marker::PhantomData; -const ADDRESSES: Item> = Item::new("addresses"); - /// Advances the blockchain environment to the next block in tests, enabling developers to simulate /// time-dependent contract behaviors and block-related triggers efficiently. pub fn next_block(block: &mut BlockInfo) { @@ -258,17 +254,6 @@ where CustomT::ExecT: CustomMsg + DeserializeOwned + 'static, CustomT::QueryT: CustomQuery + DeserializeOwned + 'static, { - /// Registers contract code (like uploading wasm bytecode on a chain), - /// so it can later be used to instantiate a contract. - /// Only for wasm codes - pub fn store_wasm_code(&mut self, code: Vec) -> u64 { - self.init_modules(|router, _, _| { - router - .wasm - .store_wasm_code(Addr::unchecked("code-creator"), code) - }) - } - /// Registers contract code (like uploading wasm bytecode on a chain), /// so it can later be used to instantiate a contract. pub fn store_code(&mut self, code: Box>) -> u64 { @@ -277,12 +262,6 @@ where .store_code(MockApi::default().addr_make("creator"), code) } - /// Registers contract code (like [store_code](Self::store_code)), - /// but takes the address of the code creator as an additional argument. - pub fn store_wasm_code_with_creator(&mut self, creator: Addr, code: Vec) -> u64 { - self.init_modules(|router, _, _| router.wasm.store_wasm_code(creator, code)) - } - /// Registers contract code (like [store_code](Self::store_code)), /// but takes the address of the code creator as an additional argument. pub fn store_code_with_creator( @@ -293,6 +272,22 @@ where self.router.wasm.store_code(creator, code) } + /// Registers contract code (like uploading wasm bytecode on a chain), + /// so it can later be used to instantiate a contract. + /// Only for wasm codes + pub fn store_wasm_code(&mut self, code: Vec) -> u64 { + self.init_modules(|router, _, _| { + router + .wasm + .store_wasm_code(Addr::unchecked("code-creator"), code) + }) + } + /// Registers contract code (like [store_code](Self::store_code)), + /// but takes the address of the code creator as an additional argument. + pub fn store_wasm_code_with_creator(&mut self, creator: Addr, code: Vec) -> u64 { + self.init_modules(|router, _, _| router.wasm.store_wasm_code(creator, code)) + } + /// Registers contract code (like [store_code_with_creator](Self::store_code_with_creator)), /// but takes the code identifier as an additional argument. pub fn store_code_with_id( @@ -447,22 +442,6 @@ where self.block.clone() } - /// Returns a new account address - pub fn next_address(&mut self) -> Addr { - let Self { - storage, remote, .. - } = self; - - let mut addresses = ADDRESSES.may_load(storage).unwrap().unwrap_or_default(); - - let new_address = - RealApi::new(&remote.pub_address_prefix.clone()).next_address(addresses.len()); - addresses.push(new_address.clone()); - ADDRESSES.save(storage, &addresses).unwrap(); - - new_address - } - /// Simple helper so we get access to all the QuerierWrapper helpers, /// e.g. wrap().query_wasm_smart, query_all_balances, ... pub fn wrap(&self) -> QuerierWrapper { diff --git a/src/app_builder.rs b/src/app_builder.rs index 3c14131a..94929310 100644 --- a/src/app_builder.rs +++ b/src/app_builder.rs @@ -152,6 +152,7 @@ impl, + BankT: Bank, CustomT::QueryT: CustomQuery, { /// Overwrites the default wasm executor. @@ -161,7 +162,7 @@ where /// done on final building. pub fn with_wasm>( self, - wasm: NewWasm, + mut wasm: NewWasm, ) -> AppBuilder { let AppBuilder { @@ -178,7 +179,9 @@ where stargate, .. } = self; - + if let Some(remote) = remote.as_ref() { + wasm.set_remote(remote.clone()); + } AppBuilder { api, block, @@ -198,7 +201,7 @@ where /// Overwrites the default bank interface. pub fn with_bank( self, - bank: NewBank, + mut bank: NewBank, ) -> AppBuilder { let AppBuilder { @@ -216,6 +219,9 @@ where .. } = self; + if let Some(remote) = remote.as_ref() { + bank.set_remote(remote.clone()); + } AppBuilder { api, block, @@ -513,39 +519,14 @@ where /// Sets the chain of the app pub fn with_remote( - self, + mut self, remote: RemoteChannel, ) -> AppBuilder { - let AppBuilder { - wasm, - api, - storage, - custom, - block, - staking, - bank, - distribution, - ibc, - gov, - stargate, - .. - } = self; - - AppBuilder { - api, - block, - storage, - bank, - wasm, - custom, - staking, - distribution, - ibc, - gov, - stargate, - remote: Some(remote), - } + self.remote = Some(remote.clone()); + self.wasm.set_remote(remote.clone()); + self.bank.set_remote(remote.clone()); + self } /// Overwrites the default stargate interface. diff --git a/src/bank.rs b/src/bank.rs index 18a5a95a..14f8781f 100644 --- a/src/bank.rs +++ b/src/bank.rs @@ -5,7 +5,7 @@ use crate::module::Module; use crate::prefixed_storage::{prefixed, prefixed_read}; use crate::queries::bank::BankRemoteQuerier; use crate::wasm_emulation::channel::RemoteChannel; -use crate::wasm_emulation::query::AllBankQuerier; +use crate::wasm_emulation::query::{AllBankQuerier, ContainsRemote}; use cosmwasm_std::{ coin, to_json_binary, Addr, AllBalanceResponse, Api, BalanceResponse, BankMsg, BankQuery, Binary, BlockInfo, Coin, DenomMetadata, Event, Querier, Storage, @@ -46,7 +46,7 @@ pub enum BankSudo { /// like transfers and balance checks, within your smart contracts. /// This trait implements all of these functionalities. pub trait Bank: - Module + AllBankQuerier + Module + AllBankQuerier + ContainsRemote { } @@ -66,15 +66,6 @@ impl BankKeeper { Self::default() } - pub fn with_remote(mut self, remote: RemoteChannel) -> Self { - self.remote = Some(remote); - self - } - - pub fn set_remote(&mut self, remote: RemoteChannel) { - self.remote = Some(remote); - } - /// Administration function for adjusting bank accounts in genesis. pub fn init_balance( &self, @@ -186,6 +177,17 @@ impl BankKeeper { } } +impl ContainsRemote for BankKeeper { + fn with_remote(mut self, remote: RemoteChannel) -> Self { + self.set_remote(remote); + self + } + + fn set_remote(&mut self, remote: RemoteChannel) { + self.remote = Some(remote) + } +} + fn coins_to_string(coins: &[Coin]) -> String { coins .iter() diff --git a/src/contracts.rs b/src/contracts.rs index 6f5202b4..868c3146 100644 --- a/src/contracts.rs +++ b/src/contracts.rs @@ -5,9 +5,10 @@ use crate::wasm_emulation::query::mock_querier::ForkState; use crate::wasm_emulation::query::MockQuerier; use crate::wasm_emulation::storage::dual_std_storage::DualStorage; use crate::wasm_emulation::storage::storage_wrappers::{ReadonlyStorageWrapper, StorageWrapper}; +use anyhow::Error as AnyError; use cosmwasm_std::{ from_json, Binary, Checksum, CosmosMsg, CustomMsg, CustomQuery, Deps, DepsMut, Empty, Env, - MessageInfo, QuerierWrapper, Reply, Response, StdError, SubMsg, + MessageInfo, QuerierWrapper, Reply, Response, SubMsg, }; use serde::de::DeserializeOwned; use std::fmt::{Debug, Display}; @@ -177,10 +178,10 @@ pub struct ContractWrapper< C = Empty, Q = Empty, T4 = Empty, - E4 = StdError, - E5 = StdError, + E4 = AnyError, + E5 = AnyError, T6 = Empty, - E6 = StdError, + E6 = AnyError, > where T1: DeserializeOwned, // Type of message passed to `execute` entry-point. T2: DeserializeOwned, // Type of message passed to `instantiate` entry-point. @@ -198,7 +199,7 @@ pub struct ContractWrapper< { execute_fn: ContractClosure, instantiate_fn: ContractClosure, - pub query_fn: QueryClosure, + query_fn: QueryClosure, sudo_fn: Option>, reply_fn: Option>, migrate_fn: Option>, diff --git a/src/error.rs b/src/error.rs index b6c26c8a..b5c3c09a 100644 --- a/src/error.rs +++ b/src/error.rs @@ -51,9 +51,6 @@ pub enum Error { /// Error variant for reporting duplicated contract addresses. #[error("Contract with this address already exists: {0}")] DuplicatedContractAddress(String), - - #[error("Unregistered contract address, not present locally or on-chain")] - UnregisteredContractAddress(String), } impl Error { diff --git a/src/executor.rs b/src/executor.rs index ed2a5fad..5269276b 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -107,6 +107,7 @@ where /// Instantiates a new contract and returns its predictable address. /// This is a helper function around [execute][Self::execute] function /// with `WasmMsg::Instantiate2` message. + #[cfg(feature = "cosmwasm_1_2")] fn instantiate2_contract( &mut self, code_id: u64, diff --git a/src/lib.rs b/src/lib.rs index fe6b3533..4923842b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -139,7 +139,6 @@ mod gov; mod ibc; mod module; pub(crate) mod prefixed_storage; -pub mod queries; #[cfg(feature = "staking")] mod staking; mod stargate; @@ -147,7 +146,11 @@ mod test_helpers; pub(crate) mod tests; mod transactions; mod wasm; + +// --- Clone Testing Modules --- // +pub mod queries; pub mod wasm_emulation; +// --- End --- // pub use crate::addresses::{ AddressGenerator, IntoAddr, IntoBech32, IntoBech32m, SimpleAddressGenerator, @@ -169,6 +172,5 @@ pub use crate::staking::{ Distribution, DistributionKeeper, StakeKeeper, Staking, StakingInfo, StakingSudo, }; pub use crate::stargate::{Stargate, StargateAccepting, StargateFailing}; -pub use crate::wasm::{ - ContractData, Wasm, WasmKeeper, WasmSudo, LOCAL_RUST_CODE_OFFSET, LOCAL_WASM_CODE_OFFSET, -}; +pub use crate::wasm::{ContractData, Wasm, WasmKeeper, WasmSudo}; +pub use crate::wasm::{LOCAL_RUST_CODE_OFFSET, LOCAL_WASM_CODE_OFFSET}; diff --git a/src/module.rs b/src/module.rs index 7b0dc9d1..cc73a4d6 100644 --- a/src/module.rs +++ b/src/module.rs @@ -103,7 +103,7 @@ where sender: Addr, msg: Self::ExecT, ) -> AnyResult { - bail!("Unexpected exec msg {:?} from {:?}", msg, sender,) + bail!("Unexpected exec msg {:?} from {:?}", msg, sender) } /// Runs any [QueryT](Self::QueryT) message, always returns an error. @@ -115,7 +115,7 @@ where _block: &BlockInfo, request: Self::QueryT, ) -> AnyResult { - bail!("Unexpected custom query {:?}", request,) + bail!("Unexpected custom query {:?}", request) } /// Runs any [SudoT](Self::SudoT) privileged action, always returns an error. @@ -127,7 +127,7 @@ where _block: &BlockInfo, msg: Self::SudoT, ) -> AnyResult { - bail!("Unexpected sudo msg {:?}", msg,) + bail!("Unexpected sudo msg {:?}", msg) } } /// # Always accepting module diff --git a/src/tests/mod.rs b/src/tests/mod.rs index c7a06491..a313b471 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -6,7 +6,11 @@ use cw_orch::{ prelude::ChainInfo, }; -use crate::{no_init, wasm_emulation::channel::RemoteChannel, App, AppBuilder, WasmKeeper}; +use crate::{ + no_init, + wasm_emulation::{channel::RemoteChannel, query::ContainsRemote}, + App, AppBuilder, WasmKeeper, +}; pub const CHAIN: ChainInfo = XION_TESTNET_1; pub fn remote_channel() -> RemoteChannel { RemoteChannel::new( diff --git a/src/tests/test_app.rs b/src/tests/test_app.rs index f6cc7290..c501d232 100644 --- a/src/tests/test_app.rs +++ b/src/tests/test_app.rs @@ -7,6 +7,7 @@ use crate::tests::{default_app, remote_channel}; use crate::transactions::{transactional, StorageTransaction}; use crate::wasm::ContractData; use crate::wasm_emulation::channel::RemoteChannel; +use crate::wasm_emulation::query::ContainsRemote; use crate::{ custom_app, next_block, no_init, App, AppResponse, Bank, CosmosRouter, Executor, Module, Router, Wasm, WasmKeeper, WasmSudo, diff --git a/src/wasm.rs b/src/wasm.rs index fa1b56ab..371f4056 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -12,7 +12,7 @@ use crate::wasm_emulation::contract::{LocalWasmContract, WasmContract}; use crate::wasm_emulation::input::QuerierStorage; use crate::wasm_emulation::instance::create_module; use crate::wasm_emulation::query::mock_querier::{ForkState, LocalForkedState}; -use crate::wasm_emulation::query::AllWasmQuerier; +use crate::wasm_emulation::query::{AllWasmQuerier, ContainsRemote}; use cosmwasm_std::testing::mock_wasmd_attr; use cosmwasm_std::{ to_json_binary, Addr, Api, Attribute, BankMsg, Binary, BlockInfo, Checksum, Coin, ContractInfo, @@ -89,7 +89,7 @@ pub struct CodeData { pub source_id: usize, } /// This trait implements the interface of the Wasm module. -pub trait Wasm: AllWasmQuerier { +pub trait Wasm: AllWasmQuerier + ContainsRemote { /// Handles all `WasmMsg` messages. fn execute( &self, @@ -196,7 +196,7 @@ pub struct WasmKeeper { // chain on which the contract should be queried/tested against remote: Option, /// Just markers to make type elision fork when using it as `Wasm` trait - _p: std::marker::PhantomData<(ExecC, QueryC)>, + _p: std::marker::PhantomData, } impl Default for WasmKeeper { @@ -277,7 +277,7 @@ where let code_data = self.code_data(code_id)?; let res = cosmwasm_std::CodeInfoResponse::new( code_id, - code_data.creator, + code_data.creator.clone(), code_data.checksum, ); to_json_binary(&res).map_err(Into::into) @@ -342,7 +342,6 @@ where let code_id = self .next_code_id() .unwrap_or_else(|| panic!("{}", Error::NoMoreCodeIdAvailable)); - self.save_code(code_id, creator, code) } @@ -383,12 +382,12 @@ where /// Returns `ContractData` for the contract with specified address. fn contract_data(&self, storage: &dyn Storage, address: &Addr) -> AnyResult { - let contract = CONTRACTS.load(&prefixed_read(storage, NAMESPACE_WASM), address); - if let Ok(local_contract) = contract { - Ok(local_contract) - } else { - WasmRemoteQuerier::load_distant_contract(self.remote.clone().unwrap(), address) - } + CONTRACTS + .load(&prefixed_read(storage, NAMESPACE_WASM), address) + .or_else(|_| { + WasmRemoteQuerier::load_distant_contract(self.remote.clone().unwrap(), address) + }) + .map_err(Into::into) } /// Returns a raw state dump of all key-values held by a contract with specified address. @@ -514,17 +513,6 @@ where self } - /// Specify the remote location of this wasm - pub fn with_remote(mut self, remote: RemoteChannel) -> Self { - self.remote = Some(remote); - self - } - - /// Specify the remote location of this wasm - pub fn set_remote(&mut self, remote: RemoteChannel) { - self.remote = Some(remote); - } - /// Returns a handler to code of the contract with specified code id. pub fn contract_code<'a, 'b>( &'a self, @@ -684,14 +672,14 @@ where /// Returns the value stored under specified key in contracts storage. pub fn query_raw(&self, address: Addr, storage: &dyn Storage, key: &[u8]) -> Binary { let storage = self.contract_storage(storage, &address); - let local_key = storage.get(key); - if let Some(local_key) = local_key { - local_key.into() - } else { - WasmRemoteQuerier::raw_query(self.remote.clone().unwrap(), &address, key.into()) - .unwrap_or_default() - .into() - } + let data = storage + .get(key) + .or_else(|| { + WasmRemoteQuerier::raw_query(self.remote.clone().unwrap(), &address, key.into()) + .ok() + }) + .unwrap_or_default(); + data.into() } fn send( @@ -795,7 +783,6 @@ where Event::new("execute").add_attribute(CONTRACT_ATTR, &contract_addr); let (res, msgs) = self.build_app_response(&contract_addr, custom_event, res); - let mut res = self.process_response(api, router, storage, block, contract_addr, res, msgs)?; res.data = execute_response(res.data); @@ -938,7 +925,6 @@ where .add_attribute("code_id", code_id.to_string()); let (res, msgs) = self.build_app_response(&contract_addr, custom_event, res); - let mut res = self.process_response( api, router, @@ -1383,8 +1369,8 @@ where action(handler, deps, env) } - fn with_storage<'a, 'b, F, T>( - &'a self, + fn with_storage( + &self, api: &dyn Api, storage: &mut dyn Storage, router: &dyn CosmosRouter, @@ -1393,8 +1379,7 @@ where action: F, ) -> AnyResult where - F: FnOnce(ContractBox<'b, ExecC, QueryC>, DepsMut, Env) -> AnyResult, - 'a: 'b, + F: FnOnce(ContractBox, DepsMut, Env) -> AnyResult, ExecC: DeserializeOwned, { let contract = self.contract_data(storage, &address)?; @@ -1443,6 +1428,21 @@ where } } +impl ContainsRemote for WasmKeeper +where + ExecC: CustomMsg + DeserializeOwned + 'static, + QueryC: CustomQuery + DeserializeOwned + 'static, +{ + fn with_remote(mut self, remote: RemoteChannel) -> Self { + self.set_remote(remote); + self + } + + fn set_remote(&mut self, remote: RemoteChannel) { + self.remote = Some(remote) + } +} + #[derive(Clone, PartialEq, Message)] struct InstantiateResponse { #[prost(string, tag = "1")] diff --git a/src/wasm_emulation/query/mod.rs b/src/wasm_emulation/query/mod.rs index 258bc0b7..d483e656 100644 --- a/src/wasm_emulation/query/mod.rs +++ b/src/wasm_emulation/query/mod.rs @@ -9,7 +9,16 @@ pub mod gas; use anyhow::Result as AnyResult; -use super::input::{BankStorage, WasmStorage}; +use super::{ + channel::RemoteChannel, + input::{BankStorage, WasmStorage}, +}; + +pub trait ContainsRemote { + fn with_remote(self, remote: RemoteChannel) -> Self; + + fn set_remote(&mut self, remote: RemoteChannel); +} pub trait AllWasmQuerier { fn query_all(&self, storage: &dyn Storage) -> AnyResult; diff --git a/tests/test_app_builder/test_with_bank.rs b/tests/test_app_builder/test_with_bank.rs index 95944247..b17906bc 100644 --- a/tests/test_app_builder/test_with_bank.rs +++ b/tests/test_app_builder/test_with_bank.rs @@ -2,7 +2,9 @@ use crate::test_app_builder::MyKeeper; use anyhow::bail; use cosmwasm_std::{coins, BankMsg, BankQuery}; use cw_multi_test::{ - no_init, wasm_emulation::query::AllBankQuerier, AppBuilder, Bank, BankSudo, Executor, + no_init, + wasm_emulation::query::{AllBankQuerier, ContainsRemote}, + AppBuilder, Bank, BankSudo, Executor, }; type MyBankKeeper = MyKeeper; @@ -16,6 +18,15 @@ impl AllBankQuerier for MyBankKeeper { bail!(self.1) } } +impl ContainsRemote for MyBankKeeper { + fn with_remote(self, _remote: cw_multi_test::wasm_emulation::channel::RemoteChannel) -> Self { + todo!() + } + + fn set_remote(&mut self, _remote: cw_multi_test::wasm_emulation::channel::RemoteChannel) { + todo!() + } +} const EXECUTE_MSG: &str = "bank execute called"; const QUERY_MSG: &str = "bank query called"; diff --git a/tests/test_app_builder/test_with_wasm.rs b/tests/test_app_builder/test_with_wasm.rs index 24326395..aa6fdc79 100644 --- a/tests/test_app_builder/test_with_wasm.rs +++ b/tests/test_app_builder/test_with_wasm.rs @@ -1,5 +1,6 @@ use crate::cw_multi_test::wasm_emulation::input::WasmStorage; use crate::cw_multi_test::wasm_emulation::query::AllWasmQuerier; +use crate::cw_multi_test::wasm_emulation::query::ContainsRemote; use crate::test_app_builder::MyKeeper; use crate::test_contracts; use cosmwasm_std::{ @@ -26,6 +27,16 @@ static WASM_RAW: Lazy> = Lazy::new(|| vec![(vec![154u8], vec![155u8] // when custom wasm keeper implements also Module trait (although it is not needed). type MyWasmKeeper = MyKeeper; +impl ContainsRemote for MyWasmKeeper { + fn with_remote(self, _remote: cw_multi_test::wasm_emulation::channel::RemoteChannel) -> Self { + todo!() + } + + fn set_remote(&mut self, _remote: cw_multi_test::wasm_emulation::channel::RemoteChannel) { + todo!() + } +} + impl Wasm for MyWasmKeeper { fn execute( &self, From 405c9e32b72e0f21504163952dce0c6ec59c1ad9 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Wed, 2 Oct 2024 07:09:31 +0000 Subject: [PATCH 68/81] Less diff even --- src/tests/test_app.rs | 3 ++- src/tests/test_gov.rs | 2 +- src/tests/test_ibc.rs | 2 +- src/tests/test_stargate.rs | 2 +- src/wasm.rs | 23 +++++++++++++---------- 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/tests/test_app.rs b/src/tests/test_app.rs index c501d232..a05bcd76 100644 --- a/src/tests/test_app.rs +++ b/src/tests/test_app.rs @@ -3,7 +3,8 @@ use crate::error::{bail, AnyResult}; use crate::featured::staking::{Distribution, Staking}; use crate::test_helpers::echo::EXECUTE_REPLY_BASE_ID; use crate::test_helpers::{caller, echo, error, hackatom, payout, reflect, CustomHelperMsg}; -use crate::tests::{default_app, remote_channel}; +use crate::tests::default_app; +use crate::tests::remote_channel; use crate::transactions::{transactional, StorageTransaction}; use crate::wasm::ContractData; use crate::wasm_emulation::channel::RemoteChannel; diff --git a/src/tests/test_gov.rs b/src/tests/test_gov.rs index 8e621d46..60dd5b7d 100644 --- a/src/tests/test_gov.rs +++ b/src/tests/test_gov.rs @@ -1,7 +1,7 @@ #![cfg(feature = "stargate")] use crate::test_helpers::gov; -use crate::tests::test_app::default_app; +use crate::tests::default_app; use crate::{no_init, App, AppBuilder, Executor, GovAcceptingModule}; use cosmwasm_std::Empty; #[test] diff --git a/src/tests/test_ibc.rs b/src/tests/test_ibc.rs index 175c012d..295ced67 100644 --- a/src/tests/test_ibc.rs +++ b/src/tests/test_ibc.rs @@ -1,7 +1,7 @@ #![cfg(feature = "stargate")] use crate::test_helpers::ibc; -use crate::tests::test_app::default_app; +use crate::tests::default_app; use crate::{no_init, App, AppBuilder, Executor, IbcAcceptingModule}; use cosmwasm_std::Empty; #[test] diff --git a/src/tests/test_stargate.rs b/src/tests/test_stargate.rs index 4667a03f..2e667d38 100644 --- a/src/tests/test_stargate.rs +++ b/src/tests/test_stargate.rs @@ -1,7 +1,7 @@ #![cfg(feature = "stargate")] use crate::test_helpers::stargate; -use crate::tests::test_app::default_app; +use crate::tests::default_app; use crate::{no_init, App, AppBuilder, Executor, StargateAccepting}; use cosmwasm_std::Empty; #[test] diff --git a/src/wasm.rs b/src/wasm.rs index 371f4056..1071a93f 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -548,17 +548,20 @@ where if code_id < 1 { bail!(Error::invalid_code_id()); } - if let Some(code_data) = self.code_data.get(&code_id) { - Ok(code_data.clone()) - } else { - let code_info_response = - WasmRemoteQuerier::code_info(self.remote.clone().unwrap(), code_id)?; - Ok(CodeData { - creator: Addr::unchecked(code_info_response.creator), - checksum: code_info_response.checksum, - source_id: code_id as usize, + Ok(self + .code_data + .get(&code_id) + .cloned() + .ok_or_else(|| { + let code_info_response = + WasmRemoteQuerier::code_info(self.remote.clone().unwrap(), code_id)?; + Ok::<_, anyhow::Error>(CodeData { + creator: Addr::unchecked(code_info_response.creator), + checksum: code_info_response.checksum, + source_id: code_id as usize, + }) }) - } + .map_err(|_| Error::unregistered_code_id(code_id))?) } pub fn dump_wasm_raw(&self, storage: &dyn Storage, address: &Addr) -> Vec { From f209adf9b378d5e0361cb33e95e31198d2267912 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Wed, 2 Oct 2024 07:11:15 +0000 Subject: [PATCH 69/81] Removed useless lifetimes --- src/wasm.rs | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/wasm.rs b/src/wasm.rs index 1071a93f..e96137f9 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -514,13 +514,7 @@ where } /// Returns a handler to code of the contract with specified code id. - pub fn contract_code<'a, 'b>( - &'a self, - code_id: u64, - ) -> AnyResult> - where - 'a: 'b, - { + pub fn contract_code(&self, code_id: u64) -> AnyResult> { let code = self.code_base.borrow().get(&code_id).cloned(); if let Some(code) = code { Ok(ContractBox::Owned(Box::new(code))) @@ -1346,8 +1340,8 @@ where } } - fn with_storage_readonly<'a, 'b, F, T>( - &'a self, + fn with_storage_readonly( + &self, api: &dyn Api, storage: &dyn Storage, querier: &dyn Querier, @@ -1356,11 +1350,10 @@ where action: F, ) -> AnyResult where - F: FnOnce(ContractBox<'b, ExecC, QueryC>, Deps, Env) -> AnyResult, - 'a: 'b, + F: FnOnce(ContractBox, Deps, Env) -> AnyResult, { let contract = self.contract_data(storage, &address)?; - let handler = self.contract_code::<'a, 'b>(contract.code_id)?; + let handler = self.contract_code(contract.code_id)?; let storage = self.contract_storage(storage, &address); let env = self.get_env(address, block); From bd24337454c5aa44549095dc8863f27a8b057aa4 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 17 Dec 2024 13:49:33 +0100 Subject: [PATCH 70/81] cosmwasm_vm --- Cargo.lock | 1361 ++++++++++++++++---------------- Cargo.toml | 2 +- src/wasm_emulation/contract.rs | 4 +- 3 files changed, 700 insertions(+), 667 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6ce5bb86..66f24ba8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,21 +1,20 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "abstract-cw-multi-test" -version = "2.1.0" +version = "2.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edc2979e936aa9ef1e29f80a95fe18bfc7db4d0b4700fdffa21b07d977ba5269" +checksum = "e09b032e3379899df1872e6a8e38ce31d1d446bb26adfe7d3ff432b0fe0bf4c1" dependencies = [ "anyhow", "bech32 0.11.0", - "cosmwasm-schema 2.1.3", - "cosmwasm-std 2.1.4", + "cosmwasm-schema 2.2.0", + "cosmwasm-std 2.2.0", "cw-storage-plus 2.0.0", "cw-utils 2.0.0", "cw20-ics20", - "derivative", "hex", "itertools 0.13.0", "log", @@ -25,15 +24,16 @@ dependencies = [ "serde_json", "sha2 0.10.8", "thiserror", + "tiny-keccak", ] [[package]] name = "addr2line" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ - "gimli 0.31.0", + "gimli 0.31.1", ] [[package]] @@ -76,9 +76,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.18" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "android-tzdata" @@ -97,9 +97,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.89" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" dependencies = [ "backtrace", ] @@ -239,14 +239,14 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.90", ] [[package]] name = "async-stream" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ "async-stream-impl", "futures-core", @@ -255,13 +255,13 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.90", ] [[package]] @@ -272,7 +272,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.90", ] [[package]] @@ -283,21 +283,21 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "axum" -version = "0.7.6" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f43644eed690f5374f1af436ecd6aea01cd201f6fbdf0178adaf6907afb2cec" +checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" dependencies = [ "async-trait", "axum-core", "bytes", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "http-body-util", "itoa", @@ -308,28 +308,28 @@ dependencies = [ "pin-project-lite", "rustversion", "serde", - "sync_wrapper 1.0.1", - "tower 0.5.1", + "sync_wrapper 1.0.2", + "tower 0.5.2", "tower-layer", "tower-service", ] [[package]] name = "axum-core" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6b8ba012a258d63c9adfa28b9ddcf66149da6f986c5b5452e629d5ee64bf00" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" dependencies = [ "async-trait", "bytes", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "http-body-util", "mime", "pin-project-lite", "rustversion", - "sync_wrapper 1.0.1", + "sync_wrapper 1.0.2", "tower-layer", "tower-service", ] @@ -419,9 +419,9 @@ dependencies = [ [[package]] name = "bitcoin" -version = "0.32.2" +version = "0.32.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea507acc1cd80fc084ace38544bbcf7ced7c2aa65b653b102de0ce718df668f6" +checksum = "ce6bc65742dea50536e35ad42492b234c27904a27f0abdcbce605015cb4ea026" dependencies = [ "base58ck", "bech32 0.11.0", @@ -442,9 +442,9 @@ checksum = "30bdbe14aa07b06e6cfeffc529a1f099e5fbe249524f8125358604df99a4bed2" [[package]] name = "bitcoin-io" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "340e09e8399c7bd8912f495af6aa58bea0c9214773417ffaa8f6460f93aaee56" +checksum = "0b47c4ab7a93edb0c7198c5535ed9b52b63095f4e9b45279c6736cec4b856baf" [[package]] name = "bitcoin-units" @@ -489,6 +489,15 @@ dependencies = [ "wyz", ] +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "block-buffer" version = "0.9.0" @@ -564,18 +573,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" -dependencies = [ - "serde", -] - -[[package]] -name = "bytesize" -version = "1.3.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e368af43e418a04d52505cf3dbc23dda4e3407ae2fa99fd0e4f308ce546acc" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" dependencies = [ "serde", ] @@ -591,9 +591,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" dependencies = [ "serde", ] @@ -614,9 +614,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.21" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" +checksum = "9157bbaa6b165880c27a4293a474c91cdcf265cc68cc829bf10be0964a391caf" dependencies = [ "shlex", ] @@ -629,9 +629,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", @@ -641,33 +641,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "ciborium" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" -dependencies = [ - "ciborium-io", - "ciborium-ll", - "serde", -] - -[[package]] -name = "ciborium-io" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" - -[[package]] -name = "ciborium-ll" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" -dependencies = [ - "ciborium-io", - "half", -] - [[package]] name = "clone-cw-multi-test" version = "0.6.2" @@ -676,8 +649,8 @@ dependencies = [ "bech32 0.9.1", "cargo_metadata", "cosmrs", - "cosmwasm-schema 2.1.3", - "cosmwasm-std 2.1.4", + "cosmwasm-schema 2.2.0", + "cosmwasm-std 2.2.0", "cosmwasm-vm", "cw-orch", "cw-storage-plus 2.0.0", @@ -792,15 +765,15 @@ dependencies = [ [[package]] name = "cosmwasm-core" -version = "2.1.4" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6ceb8624260d0d3a67c4e1a1d43fc7e9406720afbcb124521501dd138f90aa" +checksum = "c34c440d4d8e3ecec783d0f9c89d25565168b0f4cdb80a1f6a387cf2168c0740" [[package]] name = "cosmwasm-crypto" -version = "1.5.8" +version = "1.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58535cbcd599b3c193e3967c8292fe1dbbb5de7c2a2d87380661091dd4744044" +checksum = "eba94b9f3fb79b9f1101b3e0c61995a557828e2c0d3f5579c1d0bfbea333c19e" dependencies = [ "digest 0.10.7", "ed25519-zebra 3.1.0", @@ -811,15 +784,16 @@ dependencies = [ [[package]] name = "cosmwasm-crypto" -version = "2.1.4" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4125381e5fd7fefe9f614640049648088015eca2b60d861465329a5d87dfa538" +checksum = "134e765161d60228cc27635032d2a466542ca83fd6c87f3c87f4963c0bd51008" dependencies = [ "ark-bls12-381", "ark-ec", "ark-ff", "ark-serialize", "cosmwasm-core", + "curve25519-dalek 4.1.3", "digest 0.10.7", "ecdsa", "ed25519-zebra 4.0.3", @@ -834,31 +808,31 @@ dependencies = [ [[package]] name = "cosmwasm-derive" -version = "1.5.8" +version = "1.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8e07de16c800ac82fd188d055ecdb923ead0cf33960d3350089260bb982c09f" +checksum = "d67457e4acb04e738788d3489e343957455df2c4643f2b53050eb052ca631d19" dependencies = [ "syn 1.0.109", ] [[package]] name = "cosmwasm-derive" -version = "2.1.4" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5658b1dc64e10b56ae7a449f678f96932a96f6cfad1769d608d1d1d656480a" +checksum = "3c94a4b93e722c91d2e58471cfe69480f4a656cfccacd8bfda5638f2a5d4512b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.90", ] [[package]] name = "cosmwasm-schema" -version = "1.5.8" +version = "1.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d388adfa9cb449557a92e9318121ac1a481fc4f599213b03a5b62699b403b4" +checksum = "13bf06bf1c7ea737f6b3d955d9cabeb8cbbe4dcb8dea392e30f6fab4493a4b7a" dependencies = [ - "cosmwasm-schema-derive 1.5.8", + "cosmwasm-schema-derive 1.5.9", "schemars", "serde", "serde_json", @@ -867,11 +841,11 @@ dependencies = [ [[package]] name = "cosmwasm-schema" -version = "2.1.3" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bc0d4d85e83438ab9a0fea9348446f7268bc016aacfebce37e998559f151294" +checksum = "3e9a7b56d154870ec4b57b224509854f706c9744449548d8a3bf91ac75c59192" dependencies = [ - "cosmwasm-schema-derive 2.1.3", + "cosmwasm-schema-derive 2.2.0", "schemars", "serde", "serde_json", @@ -880,9 +854,9 @@ dependencies = [ [[package]] name = "cosmwasm-schema-derive" -version = "1.5.8" +version = "1.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2411b389e56e6484f81ba955b758d02522d620c98fc960c4bd2251d48b7aa19f" +checksum = "077fe378f16b54e3d0a57adb3f39a65bcf7bdbda6a5eade2f8ba7755c2fb1250" dependencies = [ "proc-macro2", "quote", @@ -891,26 +865,26 @@ dependencies = [ [[package]] name = "cosmwasm-schema-derive" -version = "2.1.3" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edf5c8adac41bb7751c050d7c4c18675be19ee128714454454575e894424eeef" +checksum = "edd3d80310cd7b86b09dbe886f4f2ca235a5ddb8d478493c6e50e720a3b38a42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.90", ] [[package]] name = "cosmwasm-std" -version = "1.5.8" +version = "1.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c21fde95ccd20044a23c0ac6fd8c941f3e8c158169dc94b5aa6491a2d9551a8d" +checksum = "3745e9fd9aad96236c3d6f1a6d844249ed3bb6b92fcdae16d8fe067c7a5121e8" dependencies = [ "base64 0.21.7", "bech32 0.9.1", "bnum 0.10.0", - "cosmwasm-crypto 1.5.8", - "cosmwasm-derive 1.5.8", + "cosmwasm-crypto 1.5.9", + "cosmwasm-derive 1.5.9", "derivative", "forward_ref", "hex", @@ -924,19 +898,20 @@ dependencies = [ [[package]] name = "cosmwasm-std" -version = "2.1.4" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70eb7ab0c1e99dd6207496963ba2a457c4128ac9ad9c72a83f8d9808542b849b" +checksum = "4434e556b0aebff34bf082e75d175b5d7edbcf1d90d4cedb59623a1249fff567" dependencies = [ "base64 0.22.1", "bech32 0.11.0", "bnum 0.11.0", "cosmwasm-core", - "cosmwasm-crypto 2.1.4", - "cosmwasm-derive 2.1.4", + "cosmwasm-crypto 2.2.0", + "cosmwasm-derive 2.2.0", "derive_more", "hex", "rand_core 0.6.4", + "rmp-serde", "schemars", "serde", "serde-json-wasm 1.0.1", @@ -951,22 +926,24 @@ version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66de2ab9db04757bcedef2b5984fbe536903ada4a8a9766717a4a71197ef34f6" dependencies = [ - "cosmwasm-std 1.5.8", + "cosmwasm-std 1.5.9", "serde", ] [[package]] name = "cosmwasm-vm" -version = "2.1.4" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edc6ab1b15e1253efaf228d6892ee89c1a816fbc3a755f681d2725fc4aed9679" +checksum = "8609b60a64d3db43ccfe775828b701cc29d27c7ac136c0a89d5279353bdc1513" dependencies = [ "bech32 0.11.0", + "blake2", "bytes", "clru", "cosmwasm-core", - "cosmwasm-crypto 2.1.4", - "cosmwasm-std 2.1.4", + "cosmwasm-crypto 2.2.0", + "cosmwasm-std 2.2.0", + "cosmwasm-vm-derive", "crc32fast", "derivative", "hex", @@ -983,11 +960,23 @@ dependencies = [ "wasmer-types", ] +[[package]] +name = "cosmwasm-vm-derive" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58fc803c6bb936441d5224e6cc04bd32b2f17a5030a1a186ad103bc4328e5401" +dependencies = [ + "blake2", + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -1086,9 +1075,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -1105,18 +1094,18 @@ dependencies = [ [[package]] name = "crossbeam-queue" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" @@ -1183,7 +1172,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.90", ] [[package]] @@ -1205,8 +1194,8 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50c1804013d21060b994dea28a080f9eab78a3bcb6b617f05e7634b0600bf7b1" dependencies = [ - "cosmwasm-schema 2.1.3", - "cosmwasm-std 2.1.4", + "cosmwasm-schema 2.2.0", + "cosmwasm-std 2.2.0", "cw-storage-plus 2.0.0", "cw-utils 2.0.0", "schemars", @@ -1216,13 +1205,13 @@ dependencies = [ [[package]] name = "cw-orch" -version = "0.25.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dd6f114ab0301b99ca0d8ba48036b87372ccc3ba0271dcd6f9533e4be578f65" +checksum = "b7353edbba484283e3162fba408bc450de43b8cc20124f89299af6ba70ad8727" dependencies = [ "anyhow", "cosmrs", - "cosmwasm-std 2.1.4", + "cosmwasm-std 2.2.0", "cw-orch-contract-derive", "cw-orch-core", "cw-orch-daemon", @@ -1241,25 +1230,25 @@ dependencies = [ [[package]] name = "cw-orch-contract-derive" -version = "0.21.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bc8ba75692fc7bd30e91c78fad2dc208a738e4e6ea26b232f9352c320e35543" +checksum = "bad52865e313bb7ed3f3938f7ad9d566e430fb6143a63476c22bed505ea78cd7" dependencies = [ "convert_case", "quote", - "syn 2.0.77", + "syn 2.0.90", ] [[package]] name = "cw-orch-core" -version = "2.0.0" +version = "2.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9f5f99f52d7ed7c0f8c84580f2f78a15db9c7f2144d24dd485d9347917b6fa" +checksum = "cd60ffab817101418b26b6bceadfdfc430dad4219c7e4cd972f8838e21190981" dependencies = [ "abstract-cw-multi-test", "anyhow", "cosmos-sdk-proto", - "cosmwasm-std 2.1.4", + "cosmwasm-std 2.2.0", "cw-storage-plus 2.0.0", "cw-utils 2.0.0", "dirs", @@ -1272,9 +1261,9 @@ dependencies = [ [[package]] name = "cw-orch-daemon" -version = "0.25.1" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3008da99bd004c9cf58571862a879298f69591e81183f6a97a9bbb9c8efb51cb" +checksum = "10346b7f1b552d8b454e908ba8be798a2ea7c97288e54df73f448f636e0245e7" dependencies = [ "anyhow", "async-recursion", @@ -1284,7 +1273,7 @@ dependencies = [ "bitcoin", "chrono", "cosmrs", - "cosmwasm-std 2.1.4", + "cosmwasm-std 2.2.0", "cw-orch-core", "cw-orch-networks", "cw-orch-traits", @@ -1295,14 +1284,14 @@ dependencies = [ "flate2", "hex", "hkd32", - "http 1.1.0", + "http 1.2.0", "lazy_static", "log", "once_cell", "prost", "prost-types", "rand_core 0.6.4", - "reqwest 0.12.7", + "reqwest 0.12.9", "ring", "ripemd", "schemars", @@ -1313,29 +1302,29 @@ dependencies = [ "tokio", "toml", "tonic", - "uid", + "uuid", ] [[package]] name = "cw-orch-fns-derive" -version = "0.23.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4438fbb77e1fd05b19d47287bdc5b7be73e3875b9acbbceffc9418acd000a8ad" +checksum = "194e944e6bcb51a53f99e2b0a510ecc8919605b9a83d93641748cf1b163315f6" dependencies = [ "convert_case", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.90", ] [[package]] name = "cw-orch-mock" -version = "0.24.0" +version = "0.24.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a7b0d0678a9043e4b4ac489e2bb6350d33acb3c8a6c2a2042145cd72a5a069" +checksum = "ce639c909e59fc1505f56772b9a37057a54d3c5a20f7a4c197cd518a27ce9770" dependencies = [ "abstract-cw-multi-test", - "cosmwasm-std 2.1.4", + "cosmwasm-std 2.2.0", "cw-orch-core", "cw-utils 2.0.0", "log", @@ -1345,9 +1334,9 @@ dependencies = [ [[package]] name = "cw-orch-networks" -version = "0.24.0" +version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8872f1f293615b38e21b28379fc0675259086725fac17d513c35792eca037a4e" +checksum = "7fd4b6651ba68b83474ecfb09d12c7d59e2d9bab76810a41ffe6a948f635136b" dependencies = [ "cw-orch-core", "serde", @@ -1355,9 +1344,9 @@ dependencies = [ [[package]] name = "cw-orch-traits" -version = "0.24.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be7b10c170797abe29170d58756fd988b260430a4466a56647c8ab8dafa8fa13" +checksum = "563311d320c9bdbb2287892a70d54102381a2265c75b65086236c7d85cd7dd87" dependencies = [ "cw-orch-core", "prost", @@ -1370,7 +1359,7 @@ version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc6cf70ef7686e2da9ad7b067c5942cd3e88dd9453f7af42f54557f8af300fb0" dependencies = [ - "cosmwasm-std 1.5.8", + "cosmwasm-std 1.5.9", "schemars", "serde", ] @@ -1381,7 +1370,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f13360e9007f51998d42b1bc6b7fa0141f74feae61ed5fd1e5b0a89eec7b5de1" dependencies = [ - "cosmwasm-std 2.1.4", + "cosmwasm-std 2.2.0", "schemars", "serde", ] @@ -1392,8 +1381,8 @@ version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ae0b69fa7679de78825b4edeeec045066aa2b2c4b6e063d80042e565bb4da5c" dependencies = [ - "cosmwasm-schema 1.5.8", - "cosmwasm-std 1.5.8", + "cosmwasm-schema 1.5.9", + "cosmwasm-std 1.5.9", "cw2 0.15.1", "schemars", "semver", @@ -1407,8 +1396,8 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07dfee7f12f802431a856984a32bce1cb7da1e6c006b5409e3981035ce562dec" dependencies = [ - "cosmwasm-schema 2.1.3", - "cosmwasm-std 2.1.4", + "cosmwasm-schema 2.2.0", + "cosmwasm-std 2.2.0", "schemars", "serde", "thiserror", @@ -1420,8 +1409,8 @@ version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5abb8ecea72e09afff830252963cb60faf945ce6cef2c20a43814516082653da" dependencies = [ - "cosmwasm-schema 1.5.8", - "cosmwasm-std 1.5.8", + "cosmwasm-schema 1.5.9", + "cosmwasm-std 1.5.9", "cw-storage-plus 0.15.1", "schemars", "serde", @@ -1433,8 +1422,8 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b04852cd38f044c0751259d5f78255d07590d136b8a86d4e09efdd7666bd6d27" dependencies = [ - "cosmwasm-schema 2.1.3", - "cosmwasm-std 2.1.4", + "cosmwasm-schema 2.2.0", + "cosmwasm-std 2.2.0", "cw-storage-plus 2.0.0", "schemars", "semver", @@ -1448,8 +1437,8 @@ version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6025276fb6e603e974c21f3e4606982cdc646080e8fba3198816605505e1d9a" dependencies = [ - "cosmwasm-schema 1.5.8", - "cosmwasm-std 1.5.8", + "cosmwasm-schema 1.5.9", + "cosmwasm-std 1.5.9", "cw-utils 0.15.1", "schemars", "serde", @@ -1461,8 +1450,8 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a42212b6bf29bbdda693743697c621894723f35d3db0d5df930be22903d0e27c" dependencies = [ - "cosmwasm-schema 2.1.3", - "cosmwasm-std 2.1.4", + "cosmwasm-schema 2.2.0", + "cosmwasm-std 2.2.0", "cw-utils 2.0.0", "schemars", "serde", @@ -1474,8 +1463,8 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80a9e377dbbd1ffb3b6a8a2dbf9128609a6458a3292f88f99e0b6840a7e9762e" dependencies = [ - "cosmwasm-schema 2.1.3", - "cosmwasm-std 2.1.4", + "cosmwasm-schema 2.2.0", + "cosmwasm-std 2.2.0", "cw-controllers", "cw-storage-plus 2.0.0", "cw-utils 2.0.0", @@ -1487,38 +1476,14 @@ dependencies = [ "thiserror", ] -[[package]] -name = "darling" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" -dependencies = [ - "darling_core 0.14.4", - "darling_macro 0.14.4", -] - [[package]] name = "darling" version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ - "darling_core 0.20.10", - "darling_macro 0.20.10", -] - -[[package]] -name = "darling_core" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 1.0.109", + "darling_core", + "darling_macro", ] [[package]] @@ -1531,18 +1496,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "syn 2.0.77", -] - -[[package]] -name = "darling_macro" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" -dependencies = [ - "darling_core 0.14.4", - "quote", - "syn 1.0.109", + "syn 2.0.90", ] [[package]] @@ -1551,18 +1505,19 @@ version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ - "darling_core 0.20.10", + "darling_core", "quote", - "syn 2.0.77", + "syn 2.0.90", ] [[package]] name = "dashmap" -version = "5.5.3" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" dependencies = [ "cfg-if", + "crossbeam-utils", "hashbrown 0.14.5", "lock_api", "once_cell", @@ -1599,37 +1554,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "derive_builder" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" -dependencies = [ - "derive_builder_macro", -] - -[[package]] -name = "derive_builder_core" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" -dependencies = [ - "darling 0.14.4", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "derive_builder_macro" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" -dependencies = [ - "derive_builder_core", - "syn 1.0.109", -] - [[package]] name = "derive_more" version = "1.0.0" @@ -1647,7 +1571,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.90", "unicode-xid", ] @@ -1694,12 +1618,14 @@ dependencies = [ ] [[package]] -name = "document-features" -version = "0.2.10" +name = "displaydoc" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ - "litrs", + "proc-macro2", + "quote", + "syn 2.0.90", ] [[package]] @@ -1843,9 +1769,9 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.34" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] @@ -1885,10 +1811,10 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59c3b24c345d8c314966bdc1832f6c2635bfcce8e7cf363bd115987bba2ee242" dependencies = [ - "darling 0.20.10", + "darling", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.90", ] [[package]] @@ -1912,12 +1838,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1938,9 +1864,9 @@ checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" [[package]] name = "fastrand" -version = "2.1.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "ff" @@ -1968,23 +1894,11 @@ dependencies = [ "libc", ] -[[package]] -name = "filetime" -version = "0.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" -dependencies = [ - "cfg-if", - "libc", - "libredox", - "windows-sys 0.59.0", -] - [[package]] name = "flate2" -version = "1.0.34" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", "miniz_oxide", @@ -2044,9 +1958,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -2058,9 +1972,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -2068,33 +1982,33 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", "futures-sink", @@ -2149,9 +2063,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.31.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "group" @@ -2176,7 +2090,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.5.0", + "indexmap 2.7.0", "slab", "tokio", "tokio-util", @@ -2185,33 +2099,23 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e" dependencies = [ "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "http 1.1.0", - "indexmap 2.5.0", + "http 1.2.0", + "indexmap 2.7.0", "slab", "tokio", "tokio-util", "tracing", ] -[[package]] -name = "half" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" -dependencies = [ - "cfg-if", - "crunchy", -] - [[package]] name = "hashbrown" version = "0.12.3" @@ -2240,6 +2144,12 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + [[package]] name = "heck" version = "0.4.1" @@ -2252,12 +2162,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "hermit-abi" version = "0.4.0" @@ -2328,9 +2232,9 @@ dependencies = [ [[package]] name = "http" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" dependencies = [ "bytes", "fnv", @@ -2355,7 +2259,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.1.0", + "http 1.2.0", ] [[package]] @@ -2366,16 +2270,16 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "pin-project-lite", ] [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -2391,9 +2295,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.30" +version = "0.14.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" dependencies = [ "bytes", "futures-channel", @@ -2415,15 +2319,15 @@ dependencies = [ [[package]] name = "hyper" -version = "1.4.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.6", - "http 1.1.0", + "h2 0.4.7", + "http 1.2.0", "http-body 1.0.1", "httparse", "httpdate", @@ -2442,7 +2346,7 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http 0.2.12", - "hyper 0.14.30", + "hyper 0.14.32", "rustls 0.21.12", "tokio", "tokio-rustls 0.24.1", @@ -2455,23 +2359,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", - "http 1.1.0", - "hyper 1.4.1", + "http 1.2.0", + "hyper 1.5.2", "hyper-util", - "rustls 0.23.13", + "rustls 0.23.20", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls 0.26.1", "tower-service", ] [[package]] name = "hyper-timeout" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ - "hyper 1.4.1", + "hyper 1.5.2", "hyper-util", "pin-project-lite", "tokio", @@ -2486,7 +2390,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.2", "hyper-util", "native-tls", "tokio", @@ -2496,16 +2400,16 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-channel", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", - "hyper 1.4.1", + "hyper 1.5.2", "pin-project-lite", "socket2", "tokio", @@ -2536,6 +2440,124 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -2544,12 +2566,23 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", ] [[package]] @@ -2566,25 +2599,23 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", - "serde", ] [[package]] name = "indexmap" -version = "2.5.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.14.5", - "serde", + "hashbrown 0.15.2", ] [[package]] name = "ipnet" -version = "2.10.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "is-terminal" @@ -2592,7 +2623,7 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" dependencies = [ - "hermit-abi 0.4.0", + "hermit-abi", "libc", "windows-sys 0.52.0", ] @@ -2626,24 +2657,25 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" dependencies = [ + "once_cell", "wasm-bindgen", ] [[package]] name = "k256" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" dependencies = [ "cfg-if", "ecdsa", @@ -2667,9 +2699,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.168" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" [[package]] name = "libredox" @@ -2679,7 +2711,6 @@ checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ "bitflags 2.6.0", "libc", - "redox_syscall", ] [[package]] @@ -2689,10 +2720,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] -name = "litrs" -version = "0.4.1" +name = "litemap" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "lock_api" @@ -2775,11 +2806,10 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ - "hermit-abi 0.3.9", "libc", "wasi", "windows-sys 0.52.0", @@ -2790,8 +2820,8 @@ name = "moneymarket" version = "0.3.1" source = "git+https://github.com/CavernPerson/money-market-contracts#6a3b3f586cd085d434485bb13e2d12f95e8beef2" dependencies = [ - "cosmwasm-schema 1.5.8", - "cosmwasm-std 1.5.8", + "cosmwasm-schema 1.5.9", + "cosmwasm-std 1.5.9", "cosmwasm-storage", "cw20 0.15.1", "schemars", @@ -2859,18 +2889,18 @@ dependencies = [ [[package]] name = "object" -version = "0.36.4" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "opaque-debug" @@ -2880,9 +2910,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.66" +version = "0.10.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ "bitflags 2.6.0", "cfg-if", @@ -2901,7 +2931,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.90", ] [[package]] @@ -2912,9 +2942,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.103" +version = "0.9.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" dependencies = [ "cc", "libc", @@ -3013,29 +3043,29 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.90", ] [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -3109,18 +3139,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] [[package]] name = "prost" -version = "0.13.2" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2ecbe40f08db5c006b5764a2645f7f3f141ce756412ac9e1dd6087e6d32995" +checksum = "2c0fef6c4230e4ccf618a35c59d7ede15dea37de8427500f50aff708806e42ec" dependencies = [ "bytes", "prost-derive", @@ -3128,22 +3158,22 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.13.2" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acf0c195eebb4af52c752bec4f52f645da98b6e92077a04110c7f349477ae5ac" +checksum = "157c5a9d7ea5c2ed2d9fb8f495b64759f7816c7eaea54ba3978f0d63000162e3" dependencies = [ "anyhow", "itertools 0.13.0", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.90", ] [[package]] name = "prost-types" -version = "0.13.2" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60caa6738c7369b940c3d49246a8d1749323674c65cb13010134f5c9bad5b519" +checksum = "cc2f1e56baa61e93533aebc21af4d2134b70f66275e0fcdf3cbe43d77ff7e8fc" dependencies = [ "prost", ] @@ -3241,9 +3271,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.6" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "355ae415ccd3a04315d3f8246e86d67689ea74d88d915576e1589a351062a13b" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ "bitflags 2.6.0", ] @@ -3273,9 +3303,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.6" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -3285,9 +3315,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -3296,9 +3326,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "region" @@ -3335,7 +3365,7 @@ dependencies = [ "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.30", + "hyper 0.14.32", "hyper-rustls 0.24.2", "ipnet", "js-sys", @@ -3364,20 +3394,20 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.7" +version = "0.12.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" +checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" dependencies = [ "base64 0.22.1", "bytes", "encoding_rs", "futures-core", "futures-util", - "h2 0.4.6", - "http 1.1.0", + "h2 0.4.7", + "http 1.2.0", "http-body 1.0.1", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.2", "hyper-rustls 0.27.3", "hyper-tls", "hyper-util", @@ -3389,11 +3419,11 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls-pemfile 2.1.3", + "rustls-pemfile 2.2.0", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 1.0.1", + "sync_wrapper 1.0.2", "system-configuration 0.6.1", "tokio", "tokio-native-tls", @@ -3469,6 +3499,28 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "rmp" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" +dependencies = [ + "byteorder", + "num-traits", + "paste", +] + +[[package]] +name = "rmp-serde" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e599a477cf9840e92f2cde9a7189e67b42c57532749bf90aea6ec10facd4db" +dependencies = [ + "byteorder", + "rmp", + "serde", +] + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -3492,15 +3544,15 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.37" +version = "0.38.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" dependencies = [ "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3517,9 +3569,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.13" +version = "0.23.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" dependencies = [ "log", "once_cell", @@ -3553,19 +3605,18 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.3" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "base64 0.22.1", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.8.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" +checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" [[package]] name = "rustls-webpki" @@ -3590,9 +3641,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "ryu" @@ -3611,9 +3662,9 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.24" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ "windows-sys 0.59.0", ] @@ -3628,7 +3679,6 @@ dependencies = [ "schemars_derive", "serde", "serde_json", - "url", ] [[package]] @@ -3640,7 +3690,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.77", + "syn 2.0.90", ] [[package]] @@ -3713,9 +3763,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.12.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" dependencies = [ "core-foundation-sys", "libc", @@ -3723,24 +3773,24 @@ dependencies = [ [[package]] name = "self_cell" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" +checksum = "c2fdfc24bc566f839a2da4c4295b82db7d25a24253867d5c64355abb5799bdbe" [[package]] name = "semver" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.210" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" dependencies = [ "serde_derive", ] @@ -3785,13 +3835,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.90", ] [[package]] @@ -3802,14 +3852,14 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.90", ] [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", "memchr", @@ -3825,7 +3875,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.90", ] [[package]] @@ -3849,19 +3899,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_yaml" -version = "0.9.34+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" -dependencies = [ - "indexmap 2.5.0", - "itoa", - "ryu", - "serde", - "unsafe-libyaml", -] - [[package]] name = "sha2" version = "0.9.9" @@ -3950,9 +3987,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", @@ -3986,12 +4023,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "strum" version = "0.24.1" @@ -4030,7 +4061,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.77", + "syn 2.0.90", ] [[package]] @@ -4067,9 +4098,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.77" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -4084,13 +4115,24 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "sync_wrapper" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" dependencies = [ "futures-core", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -4139,17 +4181,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" -[[package]] -name = "tar" -version = "0.4.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ff6c40d3aedb5e06b57c6f669ad17ab063dd1e63d977c6a88e7f4dfa4f04020" -dependencies = [ - "filetime", - "libc", - "xattr", -] - [[package]] name = "target-lexicon" version = "0.12.16" @@ -4158,9 +4189,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tempfile" -version = "3.12.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", "fastrand", @@ -4272,29 +4303,29 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.90", ] [[package]] name = "time" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "num-conv", @@ -4312,14 +4343,33 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ "num-conv", "time-core", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinyvec" version = "1.8.0" @@ -4337,9 +4387,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.40.0" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", "bytes", @@ -4361,7 +4411,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.90", ] [[package]] @@ -4386,20 +4436,19 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" dependencies = [ - "rustls 0.23.13", - "rustls-pki-types", + "rustls 0.23.20", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", "pin-project-lite", @@ -4408,9 +4457,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.12" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ "bytes", "futures-core", @@ -4446,7 +4495,7 @@ version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.5.0", + "indexmap 2.7.0", "serde", "serde_spanned", "toml_datetime", @@ -4464,20 +4513,20 @@ dependencies = [ "axum", "base64 0.22.1", "bytes", - "h2 0.4.6", - "http 1.1.0", + "h2 0.4.7", + "http 1.2.0", "http-body 1.0.1", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.2", "hyper-timeout", "hyper-util", "percent-encoding", "pin-project", "prost", - "rustls-pemfile 2.1.3", + "rustls-pemfile 2.2.0", "socket2", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls 0.26.1", "tokio-stream", "tower 0.4.13", "tower-layer", @@ -4507,14 +4556,14 @@ dependencies = [ [[package]] name = "tower" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", "pin-project-lite", - "sync_wrapper 0.1.2", + "sync_wrapper 1.0.2", "tower-layer", "tower-service", ] @@ -4533,9 +4582,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", "tracing-attributes", @@ -4544,20 +4593,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.90", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", ] @@ -4583,32 +4632,11 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" -[[package]] -name = "uid" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7041bb797d82c5728d3a4a40432809095d8acc59bdd9e67426a2529b3b80c9be" - -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" - -[[package]] -name = "unicode-normalization" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" -dependencies = [ - "tinyvec", -] +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-segmentation" @@ -4618,15 +4646,9 @@ checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-xid" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a" - -[[package]] -name = "unsafe-libyaml" -version = "0.2.11" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "untrusted" @@ -4636,21 +4658,36 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.2" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", "percent-encoding", - "serde", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "uuid" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" +dependencies = [ + "getrandom", + "rand", +] [[package]] name = "vcpkg" @@ -4691,9 +4728,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.93" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" dependencies = [ "cfg-if", "once_cell", @@ -4702,36 +4739,36 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.90", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.43" +version = "0.4.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4739,28 +4776,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.90", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" [[package]] name = "wasmer" -version = "4.3.3" +version = "4.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3de82c1520fb75ade394d6c89cac2b05d1b7b4205a45099efcd078b0bc828375" +checksum = "4b28d4251f96ece14460328c56ee0525edcf4bbb08748cfd87fef3580ae4d403" dependencies = [ "bytes", "cfg-if", @@ -4782,14 +4819,14 @@ dependencies = [ "wasmer-derive", "wasmer-types", "wasmer-vm", - "winapi", + "windows-sys 0.59.0", ] [[package]] name = "wasmer-compiler" -version = "4.3.3" +version = "4.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c18588e4b92adb2ea88a2897c93615538c7e40cfec8dc6efc3fcee63299a81" +checksum = "009b8417d51dbca8ac9a640ea999cc924fc59040a81245ecd0e092cb7c45dc10" dependencies = [ "backtrace", "bytes", @@ -4810,15 +4847,15 @@ dependencies = [ "wasmer-types", "wasmer-vm", "wasmparser", - "winapi", + "windows-sys 0.59.0", "xxhash-rust", ] [[package]] name = "wasmer-compiler-cranelift" -version = "4.3.3" +version = "4.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf497986b83f1ae8589a22f046b803d6d1d77bbeda93e75baa89ab6501838f7c" +checksum = "2445c6fb03824979448293e91d8a6daf0cdf66e8d996f31ef270e0d2cc3ea1f3" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -4835,9 +4872,9 @@ dependencies = [ [[package]] name = "wasmer-compiler-singlepass" -version = "4.3.3" +version = "4.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1093545b718fdba6dc0b9d5cfac843fa859fbc10d1dfaa72a21fac19c6a5d67" +checksum = "c6add6b3abdbd2db38dd6a42e4727d860b893e5a6ba3ac49bdd42fe0e6dc06db" dependencies = [ "byteorder", "dynasm", @@ -4852,33 +4889,11 @@ dependencies = [ "wasmer-types", ] -[[package]] -name = "wasmer-config" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "644b7e3547bd7e796d92220f60bf57734914254c6cee56607e80177a3e8a28da" -dependencies = [ - "anyhow", - "bytesize", - "ciborium", - "derive_builder", - "hex", - "indexmap 2.5.0", - "schemars", - "semver", - "serde", - "serde_json", - "serde_yaml", - "thiserror", - "toml", - "url", -] - [[package]] name = "wasmer-derive" -version = "4.3.3" +version = "4.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45ab99baa393da623dbca6390c17bd9cd7666e8c48f6b42b4f8c635106a09ca8" +checksum = "02592d86ac19fb09c972e72edeb3e57ac5c569eac7e77b919b165da014e8c139" dependencies = [ "proc-macro-error", "proc-macro2", @@ -4888,9 +4903,9 @@ dependencies = [ [[package]] name = "wasmer-middlewares" -version = "4.3.3" +version = "4.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef5f8fee717085401399c343b5c0daa37179c9f31c64889e9ae183a4bad15e37" +checksum = "9b8606706b694465035cbdd85a5a1ea437b7cd851e6a8dfe4e387a3e8f81ef78" dependencies = [ "wasmer", "wasmer-types", @@ -4899,9 +4914,9 @@ dependencies = [ [[package]] name = "wasmer-types" -version = "4.3.3" +version = "4.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aebf59870ee6e2ef0264d87e6a83f767f5cfe83e21470c0cc32e06231335e23" +checksum = "3d22a00f1a90e9e66d5427853f41e76d8ab89e03eb3034debd11933607fef56a" dependencies = [ "bytecheck", "enum-iterator", @@ -4914,15 +4929,14 @@ dependencies = [ "sha2 0.10.8", "target-lexicon", "thiserror", - "webc", "xxhash-rust", ] [[package]] name = "wasmer-vm" -version = "4.3.3" +version = "4.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df3b84ac2c450ad04931b558392cadd03d606d94ab15496e13ce56ee8320634" +checksum = "87d88e8355157cd730fb81e33c3b4d6849fd44c26d32bf78820638e1d935967b" dependencies = [ "backtrace", "cc", @@ -4943,7 +4957,7 @@ dependencies = [ "scopeguard", "thiserror", "wasmer-types", - "winapi", + "windows-sys 0.59.0", ] [[package]] @@ -4953,65 +4967,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9dbe55c8f9d0dbd25d9447a5a889ff90c0cc3feaa7395310d3d826b2c703eaab" dependencies = [ "bitflags 2.6.0", - "indexmap 2.5.0", + "indexmap 2.7.0", "semver", ] [[package]] name = "web-sys" -version = "0.3.70" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" dependencies = [ "js-sys", "wasm-bindgen", ] -[[package]] -name = "webc" -version = "6.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c48441419be082f8d2537c84d8b1f502624d77bc08fbbd09ab17cadfe7f0ac53" -dependencies = [ - "anyhow", - "base64 0.22.1", - "bytes", - "cfg-if", - "ciborium", - "document-features", - "flate2", - "indexmap 1.9.3", - "libc", - "once_cell", - "semver", - "serde", - "serde_json", - "sha2 0.10.8", - "shared-buffer", - "tar", - "tempfile", - "thiserror", - "toml", - "url", - "wasmer-config", -] - -[[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-util" version = "0.1.9" @@ -5021,12 +4990,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[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-core" version = "0.52.0" @@ -5276,6 +5239,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "wyz" version = "0.5.1" @@ -5286,21 +5261,34 @@ dependencies = [ ] [[package]] -name = "xattr" -version = "1.3.1" +name = "xxhash-rust" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" +checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984" + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" dependencies = [ - "libc", - "linux-raw-sys", - "rustix", + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", ] [[package]] -name = "xxhash-rust" -version = "0.8.12" +name = "yoke-derive" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "synstructure", +] [[package]] name = "zerocopy" @@ -5320,7 +5308,28 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.90", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "synstructure", ] [[package]] @@ -5340,5 +5349,27 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.90", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", ] diff --git a/Cargo.toml b/Cargo.toml index 640b110a..4ec9e9df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,7 @@ tokio = "1.28.2" tonic = "0.12.2" ## Emulation -cosmwasm-vm = { version = "2.1.3", features = [ +cosmwasm-vm = { version = "2.2,0", features = [ "staking", "stargate", "iterator", diff --git a/src/wasm_emulation/contract.rs b/src/wasm_emulation/contract.rs index 1aab8e1e..b904e286 100644 --- a/src/wasm_emulation/contract.rs +++ b/src/wasm_emulation/contract.rs @@ -4,10 +4,10 @@ use crate::wasm_emulation::instance::instance_from_reused_module; use crate::wasm_emulation::output::StorageChanges; use crate::wasm_emulation::query::MockQuerier; use crate::wasm_emulation::storage::DualStorage; -use cosmwasm_std::Addr; use cosmwasm_std::Checksum; use cosmwasm_std::CustomMsg; use cosmwasm_std::StdError; +use cosmwasm_vm::WasmLimits; use cosmwasm_vm::{ call_execute, call_instantiate, call_migrate, call_query, call_reply, call_sudo, Backend, BackendApi, Instance, InstanceOptions, Querier, @@ -99,6 +99,8 @@ impl WasmContract { "staking".to_string(), "stargate".to_string(), ]), + &WasmLimits::default(), + cosmwasm_vm::internals::Logger::Off, ) .unwrap(); Self::Local(LocalWasmContract { From 3754fdcfb63e77f8f112cd764573d254bc94e232 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 17 Dec 2024 14:26:54 +0100 Subject: [PATCH 71/81] Updated cosmwasm-vm --- Cargo.lock | 2 +- Cargo.toml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 66f24ba8..e804b8f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -643,7 +643,7 @@ dependencies = [ [[package]] name = "clone-cw-multi-test" -version = "0.6.2" +version = "0.6.3" dependencies = [ "anyhow", "bech32 0.9.1", diff --git a/Cargo.toml b/Cargo.toml index 4ec9e9df..caa878fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clone-cw-multi-test" -version = "0.6.2" +version = "0.6.3" authors = ["Ethan Frey "] edition = "2021" description = "Testing tools for multi-contract interactions. Helps simulating chain behavior with on-chain storage locally" @@ -38,7 +38,7 @@ tokio = "1.28.2" tonic = "0.12.2" ## Emulation -cosmwasm-vm = { version = "2.2,0", features = [ +cosmwasm-vm = { version = "2.2.0", features = [ "staking", "stargate", "iterator", From e7ab1bd6181f052cd6ab351c6d294f6d3db8d6f3 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 17 Dec 2024 14:46:29 +0100 Subject: [PATCH 72/81] Error when creating wasm cache --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/wasm_emulation/contract.rs | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e804b8f5..8dd4fa2d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -643,7 +643,7 @@ dependencies = [ [[package]] name = "clone-cw-multi-test" -version = "0.6.3" +version = "0.6.4" dependencies = [ "anyhow", "bech32 0.9.1", diff --git a/Cargo.toml b/Cargo.toml index caa878fb..eca14087 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clone-cw-multi-test" -version = "0.6.3" +version = "0.6.4" authors = ["Ethan Frey "] edition = "2021" description = "Testing tools for multi-contract interactions. Helps simulating chain behavior with on-chain storage locally" diff --git a/src/wasm_emulation/contract.rs b/src/wasm_emulation/contract.rs index b904e286..62a35cc2 100644 --- a/src/wasm_emulation/contract.rs +++ b/src/wasm_emulation/contract.rs @@ -525,8 +525,10 @@ mod wasm_caching { } } // Error on checking cache dir, try to create it - Err(_) => fs::create_dir(&wasm_cache_dir) - .context("Wasm cache directory cannot be created, please check permissions")?, + Err(_) => { + // We try to create the dir silently, it's ok if it fails, the error will pop-up later if there's an issue + let _ = fs::create_dir(&wasm_cache_dir); + } } let cached_wasm_file = wasm_cache_dir.join(key); From e30657ad8ffdd3e0e858a81d8fe3f4f82af4ee70 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 17 Dec 2024 15:28:23 +0100 Subject: [PATCH 73/81] Pin cosmwsm-vm version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index eca14087..fbb3cfe8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,7 @@ tokio = "1.28.2" tonic = "0.12.2" ## Emulation -cosmwasm-vm = { version = "2.2.0", features = [ +cosmwasm-vm = { version = "=2.2.0", features = [ "staking", "stargate", "iterator", From 4d9beaa669132252d4f18a6520e979608f35cd06 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 17 Dec 2024 15:29:18 +0100 Subject: [PATCH 74/81] Version update --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8dd4fa2d..d7c00dce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -643,7 +643,7 @@ dependencies = [ [[package]] name = "clone-cw-multi-test" -version = "0.6.4" +version = "0.6.5" dependencies = [ "anyhow", "bech32 0.9.1", diff --git a/Cargo.toml b/Cargo.toml index fbb3cfe8..7eef4874 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clone-cw-multi-test" -version = "0.6.4" +version = "0.6.5" authors = ["Ethan Frey "] edition = "2021" description = "Testing tools for multi-contract interactions. Helps simulating chain behavior with on-chain storage locally" From d9cf2f4b72c7080c65af95d7e19af5fbaea2f796 Mon Sep 17 00:00:00 2001 From: Buckram Date: Tue, 14 Jan 2025 15:55:22 +0200 Subject: [PATCH 75/81] remove unwrap, so error can be handled --- src/queries/bank.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/queries/bank.rs b/src/queries/bank.rs index 65951bc1..4cdb5046 100644 --- a/src/queries/bank.rs +++ b/src/queries/bank.rs @@ -11,8 +11,7 @@ impl BankRemoteQuerier { channel: remote.channel, rt_handle: Some(remote.rt.clone()), }; - let distant_amounts: Vec = - remote.rt.block_on(querier._balance(account, None)).unwrap(); + let distant_amounts: Vec = remote.rt.block_on(querier._balance(account, None))?; Ok(distant_amounts) } } From b3f6111dd086273c233cc057f5743d8b517a1988 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 14 Jan 2025 17:55:26 +0100 Subject: [PATCH 76/81] Started adding tokenfactory --- Cargo.lock | 82 ++++++-- Cargo.toml | 13 ++ src/lib.rs | 6 + src/tokenfactory/mod.rs | 257 +++++++++++++++++++++++ src/tokenfactory/osmosis.rs | 392 ++++++++++++++++++++++++++++++++++++ src/tokenfactory/serde.rs | 104 ++++++++++ src/tokenfactory/shim.rs | 284 ++++++++++++++++++++++++++ 7 files changed, 1126 insertions(+), 12 deletions(-) create mode 100644 src/tokenfactory/mod.rs create mode 100644 src/tokenfactory/osmosis.rs create mode 100644 src/tokenfactory/serde.rs create mode 100644 src/tokenfactory/shim.rs diff --git a/Cargo.lock b/Cargo.lock index d7c00dce..13a2d131 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,7 +18,7 @@ dependencies = [ "hex", "itertools 0.13.0", "log", - "prost", + "prost 0.13.4", "schemars", "serde", "serde_json", @@ -648,6 +648,7 @@ dependencies = [ "anyhow", "bech32 0.9.1", "cargo_metadata", + "chrono", "cosmrs", "cosmwasm-schema 2.2.0", "cosmwasm-std 2.2.0", @@ -667,10 +668,13 @@ dependencies = [ "moneymarket", "num-bigint", "once_cell", - "prost", + "osmosis-std-derive", + "prost 0.13.4", + "prost-types 0.13.4", "rustc-serialize", "schemars", "serde", + "serde-cw-value", "serde_json", "sha2 0.10.8", "thiserror", @@ -736,7 +740,7 @@ version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d0afc4daf81936e6ef5a2cf76f00c913ba5bc385d58ae1e09644e25d16b0381" dependencies = [ - "prost", + "prost 0.13.4", "tendermint-proto", "tonic", ] @@ -1288,8 +1292,8 @@ dependencies = [ "lazy_static", "log", "once_cell", - "prost", - "prost-types", + "prost 0.13.4", + "prost-types 0.13.4", "rand_core 0.6.4", "reqwest 0.12.9", "ring", @@ -1349,8 +1353,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "563311d320c9bdbb2287892a70d54102381a2265c75b65086236c7d85cd7dd87" dependencies = [ "cw-orch-core", - "prost", - "prost-types", + "prost 0.13.4", + "prost-types 0.13.4", ] [[package]] @@ -2958,6 +2962,19 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "osmosis-std-derive" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b0240fd030a4bbc79fa6cbea0b3eb0260a4b79075ebc039b93e2652bff8655b" +dependencies = [ + "itertools 0.10.5", + "proc-macro2", + "prost-types 0.11.9", + "quote", + "syn 1.0.109", +] + [[package]] name = "p256" version = "0.13.2" @@ -3146,6 +3163,16 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "prost" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +dependencies = [ + "bytes", + "prost-derive 0.11.9", +] + [[package]] name = "prost" version = "0.13.4" @@ -3153,7 +3180,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c0fef6c4230e4ccf618a35c59d7ede15dea37de8427500f50aff708806e42ec" dependencies = [ "bytes", - "prost-derive", + "prost-derive 0.13.4", +] + +[[package]] +name = "prost-derive" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +dependencies = [ + "anyhow", + "itertools 0.10.5", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] @@ -3169,13 +3209,22 @@ dependencies = [ "syn 2.0.90", ] +[[package]] +name = "prost-types" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" +dependencies = [ + "prost 0.11.9", +] + [[package]] name = "prost-types" version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc2f1e56baa61e93533aebc21af4d2134b70f66275e0fcdf3cbe43d77ff7e8fc" dependencies = [ - "prost", + "prost 0.13.4", ] [[package]] @@ -3795,6 +3844,15 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-cw-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75d32da6b8ed758b7d850b6c3c08f1d7df51a4df3cb201296e63e34a78e99d4" +dependencies = [ + "serde", +] + [[package]] name = "serde-json-wasm" version = "0.5.2" @@ -4215,7 +4273,7 @@ dependencies = [ "k256", "num-traits", "once_cell", - "prost", + "prost 0.13.4", "ripemd", "serde", "serde_bytes", @@ -4252,7 +4310,7 @@ checksum = "bf3abf34ecf33125621519e9952688e7a59a98232d51538037ba21fbe526a802" dependencies = [ "bytes", "flex-error", - "prost", + "prost 0.13.4", "serde", "serde_bytes", "subtle-encoding", @@ -4522,7 +4580,7 @@ dependencies = [ "hyper-util", "percent-encoding", "pin-project", - "prost", + "prost 0.13.4", "rustls-pemfile 2.2.0", "socket2", "tokio", diff --git a/Cargo.toml b/Cargo.toml index 7eef4874..d0a6ea44 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,12 @@ homepage = "https://cosmwasm.com" [features] default = [] backtrace = ["anyhow/backtrace"] +tokenfactory = [ + "dep:osmosis-std-derive", + "dep:chrono", + "dep:prost-types", + "dep:serde-cw-value", +] [dependencies] anyhow = "1.0.75" @@ -21,6 +27,7 @@ cosmwasm-std = { version = "2.1", features = [ "stargate", "cosmwasm_2_0", ] } +cosmwasm-schema = { version = "2.1" } cw-storage-plus = "2.0.0" cw-utils = "2.0.0" derivative = "2.2.0" @@ -62,6 +69,12 @@ wasmer = { version = "4.3.0", default-features = false, features = [ cargo_metadata = "0.18" # For finding Cargo target dir file-lock = "2.1" +# For tokenfactory +osmosis-std-derive = { version = "0.26.0", optional = true } +prost-types = { version = "0.13.4", optional = true } +serde-cw-value = { version = "0.7.0", optional = true } +chrono = { version = "0.4.39", optional = true } + [dev-dependencies] hex = "0.4.3" hex-literal = "0.4.1" diff --git a/src/lib.rs b/src/lib.rs index 99a926b7..c58467d7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,6 +27,12 @@ mod transactions; mod wasm; pub mod wasm_emulation; +#[cfg(feature = "tokenfactory")] +/// TokenFactory integration for cw-multi-test +pub mod tokenfactory; +#[cfg(feature = "tokenfactory")] +pub(crate) use tokenfactory::shim; + pub use crate::addresses::{AddressGenerator, SimpleAddressGenerator}; pub use crate::app::{custom_app, next_block, App, BasicApp, CosmosRouter, Router, SudoMsg}; pub use crate::app_builder::{AppBuilder, BasicAppBuilder}; diff --git a/src/tokenfactory/mod.rs b/src/tokenfactory/mod.rs new file mode 100644 index 00000000..fbcbb936 --- /dev/null +++ b/src/tokenfactory/mod.rs @@ -0,0 +1,257 @@ +use anyhow::{bail, Result as AnyResult}; +use cosmwasm_schema::serde::de::DeserializeOwned; +use cosmwasm_std::{ + to_json_binary, Addr, AnyMsg, Api, Binary, BlockInfo, CosmosMsg, CustomMsg, CustomQuery, Empty, + GrpcQuery, Querier, Storage, +}; +use cw_storage_plus::Map; +use prost::Message; + +use crate::{AppResponse, CosmosRouter, Stargate}; + +pub mod osmosis; +pub(crate) mod serde; +pub use shim::Coin; + +pub(crate) mod shim; + +/// Always accepting handler for `Stargate`/`Any` message variants and `Stargate`/`Grpc` queries. +pub struct TokenFactoryStargate; + +const TOKENFACTORY_DENOMS: Map<(&String, &String), ()> = Map::new("tokenfactory_denoms"); + +/// Merge sender and subdenom to create the denom +pub fn denom(sender: &str, subdenom: &str) -> String { + format!("factory/{sender}/{subdenom}") +} + +fn split_denom(denom: &str) -> AnyResult<(String, String)> { + let split_result: Vec<&str> = denom.splitn(3, "/").collect(); + + if split_result.len() != 3 { + bail!("Error decoding denom {denom} into factory/sender/subdenom") + } + if split_result[0] != "factory" { + bail!("Error decoding denom {denom} into factory/sender/subdenom") + } + + Ok((split_result[1].to_string(), split_result[2].to_string())) +} + +impl Stargate for TokenFactoryStargate { + fn execute_stargate( + &self, + api: &dyn Api, + storage: &mut dyn Storage, + router: &dyn CosmosRouter, + block: &BlockInfo, + sender: Addr, + type_url: String, + value: Binary, + ) -> AnyResult + where + ExecC: CustomMsg + DeserializeOwned + 'static, + QueryC: CustomQuery + DeserializeOwned + 'static, + { + // We match the type url + match type_url.as_str() { + osmosis::MsgCreateDenom::TYPE_URL => { + let msg = osmosis::MsgCreateDenom::decode(value.as_slice())?; + if sender != api.addr_validate(&msg.sender)? { + bail!("Sender field should match the message sender") + } + self.create_denom(storage, msg.sender, msg.subdenom) + } + osmosis::MsgMint::TYPE_URL => { + let msg = osmosis::MsgMint::decode(value.as_slice())?; + if sender != api.addr_validate(&msg.sender)? { + bail!("Sender field should match the message sender") + } + self.mint( + api, + storage, + router, + block, + msg.sender, + msg.amount, + msg.mint_to_address, + ) + } + osmosis::MsgBurn::TYPE_URL => { + let msg = osmosis::MsgBurn::decode(value.as_slice())?; + if sender != api.addr_validate(&msg.sender)? { + bail!("Sender field should match the message sender") + } + self.burn( + api, + storage, + router, + block, + msg.sender, + msg.amount, + msg.burn_from_address, + ) + } + _ => { + bail!("type url {} is not supported", type_url) + } + } + } + + fn query_stargate( + &self, + _api: &dyn Api, + _storage: &dyn Storage, + _querier: &dyn Querier, + _block: &BlockInfo, + _path: String, + _data: Binary, + ) -> AnyResult { + bail!("Stargate / any queries, unsupported") + } + + fn execute_any( + &self, + api: &dyn Api, + storage: &mut dyn Storage, + router: &dyn CosmosRouter, + block: &BlockInfo, + sender: Addr, + msg: AnyMsg, + ) -> AnyResult + where + ExecC: CustomMsg + DeserializeOwned + 'static, + QueryC: CustomQuery + DeserializeOwned + 'static, + { + self.execute_stargate(api, storage, router, block, sender, msg.type_url, msg.value) + } + + fn query_grpc( + &self, + api: &dyn Api, + storage: &dyn Storage, + querier: &dyn Querier, + block: &BlockInfo, + request: GrpcQuery, + ) -> AnyResult { + self.query_stargate(api, storage, querier, block, request.path, request.data) + } +} + +impl TokenFactoryStargate { + fn create_denom( + &self, + storage: &mut dyn Storage, + sender: String, + subdenom: String, + ) -> AnyResult { + if TOKENFACTORY_DENOMS.has(storage, (&sender, &subdenom)) { + bail!("Subdenom {subdenom} by sender {sender} already exists") + } + + TOKENFACTORY_DENOMS.save(storage, (&sender, &subdenom), &())?; + + let data = osmosis::MsgCreateDenomResponse { + new_token_denom: denom(&sender, &subdenom), + } + .to_proto_bytes(); + + Ok(AppResponse { + data: Some(data.into()), + events: vec![], + }) + } + fn mint( + &self, + api: &dyn Api, + storage: &mut dyn Storage, + router: &dyn CosmosRouter, + block: &BlockInfo, + sender: String, + amount: Option, + mint_to_address: String, + ) -> AnyResult + where + ExecC: CustomMsg + DeserializeOwned + 'static, + QueryC: CustomQuery + DeserializeOwned + 'static, + { + let amount = if let Some(amount) = amount { + amount + } else { + bail!("Can't mint nothing, please specify an amount") + }; + + // We verify the denom exists + let (creator, subdenom) = split_denom(&amount.denom)?; + if creator != sender { + bail!("Only creator can mint token factory tokens") + } + if !TOKENFACTORY_DENOMS.has(storage, (&sender, &subdenom)) { + bail!("Subdenom {subdenom} by sender {sender} doesn't exist") + } + + // We mint. No need for transactional cache here, if this fails, the tokenfactory mint fails + router.sudo( + api, + storage, + block, + crate::SudoMsg::Bank(crate::BankSudo::Mint { + to_address: mint_to_address, + amount: vec![amount.try_into()?], + }), + )?; + + let data = osmosis::MsgMintResponse {}.to_proto_bytes(); + + Ok(AppResponse { + data: Some(data.into()), + events: vec![], + }) + } + + fn burn( + &self, + api: &dyn Api, + storage: &mut dyn Storage, + router: &dyn CosmosRouter, + block: &BlockInfo, + sender: String, + amount: Option, + burn_from_address: String, + ) -> AnyResult + where + ExecC: CustomMsg + DeserializeOwned + 'static, + QueryC: CustomQuery + DeserializeOwned + 'static, + { + let amount = if let Some(amount) = amount { + amount + } else { + bail!("Can't burn nothing, please specify an amount") + }; + let (creator, subdenom) = split_denom(&amount.denom)?; + if creator != sender { + bail!("Only creator can burn token factory tokens from any address") + } + // We verify the denom exists + if !TOKENFACTORY_DENOMS.has(storage, (&sender, &subdenom)) { + bail!("Subdenom {subdenom} by sender {sender} doesn't exist") + } + + // We burn. No need for transactional cache here, if this fails, the tokenfactory burn fails + router.execute( + api, + storage, + block, + api.addr_validate(&burn_from_address)?, + CosmosMsg::Bank(cosmwasm_std::BankMsg::Burn { + amount: vec![amount.try_into()?], + }), + )?; + let data = osmosis::MsgBurnResponse {}.to_proto_bytes(); + + Ok(AppResponse { + data: Some(data.into()), + events: vec![], + }) + } +} diff --git a/src/tokenfactory/osmosis.rs b/src/tokenfactory/osmosis.rs new file mode 100644 index 00000000..e4caa02a --- /dev/null +++ b/src/tokenfactory/osmosis.rs @@ -0,0 +1,392 @@ +#![allow(missing_docs)] + +use osmosis_std_derive::CosmwasmExt; + +use super::shim::Coin; + +/// QueryDenomsFromCreatorRequest defines the request structure for the +/// DenomsFromCreator gRPC query. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/osmosis.tokenfactory.v1beta1.QueryDenomsFromCreatorRequest")] +#[proto_query( + path = "/osmosis.tokenfactory.v1beta1.Query/DenomsFromCreator", + response_type = QueryDenomsFromCreatorResponse +)] +pub struct QueryDenomsFromCreatorRequest { + #[prost(string, tag = "1")] + pub creator: ::prost::alloc::string::String, +} +/// QueryDenomsFromCreatorRequest defines the response structure for the +/// DenomsFromCreator gRPC query. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/osmosis.tokenfactory.v1beta1.QueryDenomsFromCreatorResponse")] +pub struct QueryDenomsFromCreatorResponse { + #[prost(string, repeated, tag = "1")] + pub denoms: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/osmosis.tokenfactory.v1beta1.QueryBeforeSendHookAddressRequest")] +#[proto_query( + path = "/osmosis.tokenfactory.v1beta1.Query/BeforeSendHookAddress", + response_type = QueryBeforeSendHookAddressResponse +)] +pub struct QueryBeforeSendHookAddressRequest { + #[prost(string, tag = "1")] + pub denom: ::prost::alloc::string::String, +} +/// QueryBeforeSendHookAddressResponse defines the response structure for the +/// DenomBeforeSendHook gRPC query. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/osmosis.tokenfactory.v1beta1.QueryBeforeSendHookAddressResponse")] +pub struct QueryBeforeSendHookAddressResponse { + #[prost(string, tag = "1")] + pub cosmwasm_address: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/osmosis.tokenfactory.v1beta1.QueryAllBeforeSendHooksAddressesRequest")] +#[proto_query( + path = "/osmosis.tokenfactory.v1beta1.Query/AllBeforeSendHooksAddresses", + response_type = QueryAllBeforeSendHooksAddressesResponse +)] +pub struct QueryAllBeforeSendHooksAddressesRequest {} +/// QueryAllBeforeSendHooksAddressesResponse defines the response structure for +/// the AllBeforeSendHooksAddresses gRPC query. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message( + type_url = "/osmosis.tokenfactory.v1beta1.QueryAllBeforeSendHooksAddressesResponse" +)] +pub struct QueryAllBeforeSendHooksAddressesResponse { + #[prost(string, repeated, tag = "1")] + pub denoms: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + #[prost(string, repeated, tag = "2")] + pub before_send_hook_addresses: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, +} +/// MsgCreateDenom defines the message structure for the CreateDenom gRPC service +/// method. It allows an account to create a new denom. It requires a sender +/// address and a sub denomination. The (sender_address, sub_denomination) tuple +/// must be unique and cannot be re-used. +/// +/// The resulting denom created is defined as +/// . The resulting denom's admin is +/// originally set to be the creator, but this can be changed later. The token +/// denom does not indicate the current admin. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/osmosis.tokenfactory.v1beta1.MsgCreateDenom")] +pub struct MsgCreateDenom { + #[prost(string, tag = "1")] + pub sender: ::prost::alloc::string::String, + /// subdenom can be up to 44 "alphanumeric" characters long. + #[prost(string, tag = "2")] + pub subdenom: ::prost::alloc::string::String, +} +/// MsgCreateDenomResponse is the return value of MsgCreateDenom +/// It returns the full string of the newly created denom +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/osmosis.tokenfactory.v1beta1.MsgCreateDenomResponse")] +pub struct MsgCreateDenomResponse { + #[prost(string, tag = "1")] + pub new_token_denom: ::prost::alloc::string::String, +} +/// MsgMint is the sdk.Msg type for allowing an admin account to mint +/// more of a token. +/// Only the admin of the token factory denom has permission to mint unless +/// the denom does not have any admin. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/osmosis.tokenfactory.v1beta1.MsgMint")] +pub struct MsgMint { + #[prost(string, tag = "1")] + pub sender: ::prost::alloc::string::String, + #[prost(message, optional, tag = "2")] + pub amount: ::core::option::Option, + #[prost(string, tag = "3")] + pub mint_to_address: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/osmosis.tokenfactory.v1beta1.MsgMintResponse")] +pub struct MsgMintResponse {} +/// MsgBurn is the sdk.Msg type for allowing an admin account to burn +/// a token. +/// Only the admin of the token factory denom has permission to burn unless +/// the denom does not have any admin. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/osmosis.tokenfactory.v1beta1.MsgBurn")] +pub struct MsgBurn { + #[prost(string, tag = "1")] + pub sender: ::prost::alloc::string::String, + #[prost(message, optional, tag = "2")] + pub amount: ::core::option::Option, + #[prost(string, tag = "3")] + pub burn_from_address: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/osmosis.tokenfactory.v1beta1.MsgBurnResponse")] +pub struct MsgBurnResponse {} +/// MsgChangeAdmin is the sdk.Msg type for allowing an admin account to reassign +/// adminship of a denom to a new account +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/osmosis.tokenfactory.v1beta1.MsgChangeAdmin")] +pub struct MsgChangeAdmin { + #[prost(string, tag = "1")] + pub sender: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub denom: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub new_admin: ::prost::alloc::string::String, +} +/// MsgChangeAdminResponse defines the response structure for an executed +/// MsgChangeAdmin message. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/osmosis.tokenfactory.v1beta1.MsgChangeAdminResponse")] +pub struct MsgChangeAdminResponse {} +/// MsgSetBeforeSendHook is the sdk.Msg type for allowing an admin account to +/// assign a CosmWasm contract to call with a BeforeSend hook +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/osmosis.tokenfactory.v1beta1.MsgSetBeforeSendHook")] +pub struct MsgSetBeforeSendHook { + #[prost(string, tag = "1")] + pub sender: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub denom: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub cosmwasm_address: ::prost::alloc::string::String, +} +/// MsgSetBeforeSendHookResponse defines the response structure for an executed +/// MsgSetBeforeSendHook message. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/osmosis.tokenfactory.v1beta1.MsgSetBeforeSendHookResponse")] +pub struct MsgSetBeforeSendHookResponse {} +/// MsgSetDenomMetadataResponse defines the response structure for an executed +/// MsgSetDenomMetadata message. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/osmosis.tokenfactory.v1beta1.MsgSetDenomMetadataResponse")] +pub struct MsgSetDenomMetadataResponse {} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/osmosis.tokenfactory.v1beta1.MsgForceTransfer")] +pub struct MsgForceTransfer { + #[prost(string, tag = "1")] + pub sender: ::prost::alloc::string::String, + #[prost(message, optional, tag = "2")] + pub amount: ::core::option::Option, + #[prost(string, tag = "3")] + pub transfer_from_address: ::prost::alloc::string::String, + #[prost(string, tag = "4")] + pub transfer_to_address: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/osmosis.tokenfactory.v1beta1.MsgForceTransferResponse")] +pub struct MsgForceTransferResponse {} +pub struct TokenfactoryQuerier<'a, Q: cosmwasm_std::CustomQuery> { + querier: &'a cosmwasm_std::QuerierWrapper<'a, Q>, +} +impl<'a, Q: cosmwasm_std::CustomQuery> TokenfactoryQuerier<'a, Q> { + pub fn new(querier: &'a cosmwasm_std::QuerierWrapper<'a, Q>) -> Self { + Self { querier } + } + pub fn denoms_from_creator( + &self, + creator: ::prost::alloc::string::String, + ) -> Result { + QueryDenomsFromCreatorRequest { creator }.query(self.querier) + } + pub fn before_send_hook_address( + &self, + denom: ::prost::alloc::string::String, + ) -> Result { + QueryBeforeSendHookAddressRequest { denom }.query(self.querier) + } + pub fn all_before_send_hooks_addresses( + &self, + ) -> Result { + QueryAllBeforeSendHooksAddressesRequest {}.query(self.querier) + } +} diff --git a/src/tokenfactory/serde.rs b/src/tokenfactory/serde.rs new file mode 100644 index 00000000..5461e99a --- /dev/null +++ b/src/tokenfactory/serde.rs @@ -0,0 +1,104 @@ +pub mod as_str { + use serde::{de, Deserialize, Deserializer, Serializer}; + use std::{fmt::Display, str::FromStr}; + + pub fn deserialize<'de, T, D>(deserializer: D) -> Result + where + T: FromStr, + T::Err: Display, + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + T::from_str(&s).map_err(de::Error::custom) + } + + pub fn serialize(value: &T, serializer: S) -> Result + where + S: Serializer, + T: Display, + { + serializer.serialize_str(&value.to_string()) + } +} + +pub mod as_str_vec { + use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; + use std::{fmt::Display, str::FromStr}; + + pub fn deserialize<'de, T, D>(deserializer: D) -> Result, D::Error> + where + T: FromStr, + T::Err: Display, + D: Deserializer<'de>, + { + let vec_of_strings: Vec = Vec::deserialize(deserializer)?; + vec_of_strings + .into_iter() + .map(|s| T::from_str(&s).map_err(de::Error::custom)) + .collect() + } + + pub fn serialize(values: &[T], serializer: S) -> Result + where + S: Serializer, + T: Display, + { + let vec_of_strings: Vec = values.iter().map(|value| value.to_string()).collect(); + vec_of_strings.serialize(serializer) + } +} + +pub mod as_base64_encoded_string { + use cosmwasm_std::Binary; + use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; + + pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> + where + D: Deserializer<'de>, + { + let encoded_string = String::deserialize(deserializer)?; + Binary::from_base64(&encoded_string) + .map(|b| b.to_vec()) + .map_err(de::Error::custom) + } + + pub fn serialize(values: &[u8], serializer: S) -> Result + where + S: Serializer, + { + Binary::new(values.to_vec()) + .to_base64() + .serialize(serializer) + } +} + +pub mod as_option_base64_encoded_string { + use cosmwasm_std::Binary; + use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; + + pub fn deserialize<'de, D>(deserializer: D) -> Result>, D::Error> + where + D: Deserializer<'de>, + { + let encoded_string: Option = Option::deserialize(deserializer)?; + match encoded_string { + Some(s) => Binary::from_base64(&s) + .map(|b| Some(b.to_vec())) + .map_err(de::Error::custom), + None => Ok(None), + } + } + + pub fn serialize(value: &Option>, serializer: S) -> Result + where + S: Serializer, + { + match value { + Some(vec) => { + let encoded_string = Binary::new(vec.clone()).to_base64(); + encoded_string.serialize(serializer) + } + None => serializer.serialize_none(), + } + } +} diff --git a/src/tokenfactory/shim.rs b/src/tokenfactory/shim.rs new file mode 100644 index 00000000..623d6ac2 --- /dev/null +++ b/src/tokenfactory/shim.rs @@ -0,0 +1,284 @@ +#![allow(missing_docs)] + +use ::serde::{Deserialize, Deserializer, Serialize, Serializer}; +use chrono::{DateTime, NaiveDateTime, Utc}; +use cosmwasm_std::StdResult; +use osmosis_std_derive::CosmwasmExt; +use serde::de; +use serde::de::Visitor; + +use std::fmt; +use std::str::FromStr; + +#[derive(Clone, PartialEq, Eq, ::prost::Message, schemars::JsonSchema)] +pub struct Timestamp { + /// Represents seconds of UTC time since Unix epoch + /// 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + /// 9999-12-31T23:59:59Z inclusive. + #[prost(int64, tag = "1")] + pub seconds: i64, + /// Non-negative fractions of a second at nanosecond resolution. Negative + /// second values with fractions must still have non-negative nanos values + /// that count forward in time. Must be from 0 to 999,999,999 + /// inclusive. + #[prost(int32, tag = "2")] + pub nanos: i32, +} + +impl Serialize for Timestamp { + fn serialize(&self, serializer: S) -> Result<::Ok, ::Error> + where + S: Serializer, + { + let mut ts = prost_types::Timestamp { + seconds: self.seconds, + nanos: self.nanos, + }; + ts.normalize(); + let dt = NaiveDateTime::from_timestamp_opt(ts.seconds, ts.nanos as u32) + .expect("invalid or out-of-range datetime"); + let dt: DateTime = DateTime::from_naive_utc_and_offset(dt, Utc); + serializer.serialize_str(format!("{:?}", dt).as_str()) + } +} + +impl<'de> Deserialize<'de> for Timestamp { + fn deserialize(deserializer: D) -> Result>::Error> + where + D: Deserializer<'de>, + { + struct TimestampVisitor; + + impl<'de> Visitor<'de> for TimestampVisitor { + type Value = Timestamp; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("Timestamp in RFC3339 format") + } + + fn visit_str(self, value: &str) -> Result + where + E: de::Error, + { + let utc: DateTime = chrono::DateTime::from_str(value).map_err(|err| { + serde::de::Error::custom(format!( + "Failed to parse {} as datetime: {:?}", + value, err + )) + })?; + let ts = Timestamp::from(utc); + Ok(ts) + } + } + deserializer.deserialize_str(TimestampVisitor) + } +} + +impl From> for Timestamp { + fn from(dt: DateTime) -> Self { + Timestamp { + seconds: dt.timestamp(), + nanos: dt.timestamp_subsec_nanos() as i32, + } + } +} +#[derive(Clone, PartialEq, Eq, ::prost::Message, schemars::JsonSchema)] +pub struct Duration { + /// Signed seconds of the span of time. Must be from -315,576,000,000 + /// to +315,576,000,000 inclusive. Note: these bounds are computed from: + /// 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years + #[prost(int64, tag = "1")] + pub seconds: i64, + /// Signed fractions of a second at nanosecond resolution of the span + /// of time. Durations less than one second are represented with a 0 + /// `seconds` field and a positive or negative `nanos` field. For durations + /// of one second or more, a non-zero value for the `nanos` field must be + /// of the same sign as the `seconds` field. Must be from -999,999,999 + /// to +999,999,999 inclusive. + #[prost(int32, tag = "2")] + pub nanos: i32, +} + +impl Serialize for Duration { + fn serialize(&self, serializer: S) -> Result<::Ok, ::Error> + where + S: Serializer, + { + let mut d = prost_types::Duration::from(self.to_owned()); + d.normalize(); + + serializer.serialize_str(d.to_string().as_str()) + } +} + +impl<'de> Deserialize<'de> for Duration { + fn deserialize(deserializer: D) -> Result>::Error> + where + D: Deserializer<'de>, + { + struct DurationVisitor; + + impl<'de> Visitor<'de> for DurationVisitor { + type Value = Duration; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("Timestamp in RFC3339 format") + } + + fn visit_str(self, value: &str) -> Result + where + E: de::Error, + { + value + .parse::() + .map(Into::into) + .map_err(de::Error::custom) + } + } + deserializer.deserialize_str(DurationVisitor) + } +} + +#[derive(Clone, PartialEq, Eq, ::prost::Message, schemars::JsonSchema)] +pub struct Any { + /// A URL/resource name that uniquely identifies the type of the serialized + /// protocol buffer message. This string must contain at least + /// one "/" character. The last segment of the URL's path must represent + /// the fully qualified name of the type (as in + /// `path/google.protobuf.Duration`). The name should be in a canonical form + /// (e.g., leading "." is not accepted). + /// + /// In practice, teams usually precompile into the binary all types that they + /// expect it to use in the context of Any. However, for URLs which use the + /// scheme `http`, `https`, or no scheme, one can optionally set up a type + /// server that maps type URLs to message definitions as follows: + /// + /// * If no scheme is provided, `https` is assumed. + /// * An HTTP GET on the URL must yield a \[google.protobuf.Type][\] + /// value in binary format, or produce an error. + /// * Applications are allowed to cache lookup results based on the + /// URL, or have them precompiled into a binary to avoid any + /// lookup. Therefore, binary compatibility needs to be preserved + /// on changes to types. (Use versioned type names to manage + /// breaking changes.) + /// + /// Note: this functionality is not currently available in the official + /// protobuf release, and it is not used for type URLs beginning with + /// type.googleapis.com. + /// + /// Schemes other than `http`, `https` (or the empty scheme) might be + /// used with implementation specific semantics. + /// + #[prost(string, tag = "1")] + pub type_url: ::prost::alloc::string::String, + /// Must be a valid serialized protocol buffer of the above specified type. + #[prost(bytes = "vec", tag = "2")] + pub value: ::prost::alloc::vec::Vec, +} + +macro_rules! impl_prost_types_exact_conversion { + ($t:ident | $($arg:ident),*) => { + impl From<$t> for prost_types::$t { + fn from(src: $t) -> Self { + prost_types::$t { + $( + $arg: src.$arg, + )* + } + } + } + + impl From for $t { + fn from(src: prost_types::$t) -> Self { + $t { + $( + $arg: src.$arg, + )* + } + } + } + }; +} + +impl_prost_types_exact_conversion! { Timestamp | seconds, nanos } +impl_prost_types_exact_conversion! { Duration | seconds, nanos } +impl_prost_types_exact_conversion! { Any | type_url, value } +/// Coin defines a token with a denomination and an amount. +/// +/// NOTE: The amount field is an Int which implements the custom method +/// signatures required by gogoproto. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + ::schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/cosmos.base.v1beta1.Coin")] +pub struct Coin { + #[prost(string, tag = "1")] + pub denom: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub amount: ::prost::alloc::string::String, +} +impl From for Coin { + fn from(cosmwasm_std::Coin { denom, amount }: cosmwasm_std::Coin) -> Self { + Coin { + denom, + amount: amount.into(), + } + } +} + +impl TryFrom for cosmwasm_std::Coin { + type Error = cosmwasm_std::StdError; + + fn try_from(Coin { denom, amount }: Coin) -> cosmwasm_std::StdResult { + Ok(cosmwasm_std::Coin { + denom, + amount: amount.parse()?, + }) + } +} + +/// Convert a list of `Coin` from osmosis proto generated proto `Coin` type to cosmwasm `Coin` type +pub fn try_proto_to_cosmwasm_coins( + coins: impl IntoIterator, +) -> StdResult> { + coins.into_iter().map(|c| c.try_into()).collect() +} + +/// Convert a list of `Coin` from cosmwasm `Coin` type to osmosis proto generated proto `Coin` type +pub fn cosmwasm_to_proto_coins(coins: impl IntoIterator) -> Vec { + coins.into_iter().map(|c| c.into()).collect() +} + +#[cfg(test)] +mod tests { + use cosmwasm_std::Uint128; + + use super::*; + + #[test] + fn test_coins_conversion() { + let coins = vec![ + cosmwasm_std::Coin { + denom: "uatom".to_string(), + amount: Uint128::new(100), + }, + cosmwasm_std::Coin { + denom: "uosmo".to_string(), + amount: Uint128::new(200), + }, + ]; + + let proto_coins = cosmwasm_to_proto_coins(coins.clone()); + let cosmwasm_coins = try_proto_to_cosmwasm_coins(proto_coins).unwrap(); + + assert_eq!(coins, cosmwasm_coins); + } +} From de8605811db326ca37ca46125cbeda3e3e92cb6d Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 14 Jan 2025 18:10:29 +0100 Subject: [PATCH 77/81] Less diff --- Cargo.lock | 4 +- Cargo.toml | 2 +- src/addresses.rs | 2 +- src/app.rs | 34 ++++++++++-- src/tests/test_app.rs | 125 +++++++++++++++++++++--------------------- src/wasm.rs | 1 + 6 files changed, 99 insertions(+), 69 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 53e48811..17a01b41 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "abstract-cw-multi-test" @@ -670,7 +670,7 @@ dependencies = [ [[package]] name = "clone-cw-multi-test" -version = "0.6.2" +version = "0.7.0" dependencies = [ "anyhow", "bech32 0.11.0", diff --git a/Cargo.toml b/Cargo.toml index 419e7b5e..b33813e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clone-cw-multi-test" -version = "0.6.2" +version = "0.7.0" authors = [ "Ethan Frey ", "Dariusz Depta ", diff --git a/src/addresses.rs b/src/addresses.rs index f4edc837..43d49341 100644 --- a/src/addresses.rs +++ b/src/addresses.rs @@ -7,7 +7,7 @@ use cosmwasm_std::{instantiate2_address, Addr, Api, CanonicalAddr, Storage}; use sha2::digest::Update; use sha2::{Digest, Sha256}; -const DEFAULT_PREFIX: &str = "xion"; +const DEFAULT_PREFIX: &str = "cosmwasm"; /// Defines conversions to [Addr], this conversion is format agnostic /// and should be aligned with the format generated by [MockApi]. diff --git a/src/app.rs b/src/app.rs index 82c88ee1..8bf0c2c2 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,5 +1,6 @@ use crate::wasm_emulation::channel::RemoteChannel; use crate::wasm_emulation::input::QuerierStorage; +use crate::wasm_emulation::query::ContainsRemote; use cosmwasm_std::CustomMsg; use crate::bank::{Bank, BankKeeper, BankSudo}; @@ -72,6 +73,31 @@ pub struct App< pub(crate) remote: RemoteChannel, } +impl ContainsRemote + for App +{ + fn with_remote(self, remote: RemoteChannel) -> Self { + let Self { + router, + api, + storage, + block, + .. + } = self; + Self { + router, + api, + storage, + block, + remote, + } + } + + fn set_remote(&mut self, remote: RemoteChannel) { + self.remote = remote; + } +} + /// No-op application initialization function. pub fn no_init( router: &mut Router, @@ -83,7 +109,7 @@ pub fn no_init(remote: RemoteChannel, init_fn: F) -> Self + pub fn new(init_fn: F) -> Self where F: FnOnce( &mut Router< @@ -100,13 +126,13 @@ impl BasicApp { &mut dyn Storage, ), { - AppBuilder::new().with_remote(remote).build(init_fn) + AppBuilder::new().build(init_fn) } } /// Creates new default `App` implementation working with customized exec and query messages. /// Outside the `App` implementation to make type elision better. -pub fn custom_app(remote: RemoteChannel, init_fn: F) -> BasicApp +pub fn custom_app(init_fn: F) -> BasicApp where ExecC: CustomMsg + DeserializeOwned + 'static, QueryC: Debug + CustomQuery + DeserializeOwned + 'static, @@ -125,7 +151,7 @@ where &mut dyn Storage, ), { - AppBuilder::new_custom().with_remote(remote).build(init_fn) + AppBuilder::new_custom().build(init_fn) } impl Querier diff --git a/src/tests/test_app.rs b/src/tests/test_app.rs index a05bcd76..757e5dd2 100644 --- a/src/tests/test_app.rs +++ b/src/tests/test_app.rs @@ -7,11 +7,10 @@ use crate::tests::default_app; use crate::tests::remote_channel; use crate::transactions::{transactional, StorageTransaction}; use crate::wasm::ContractData; -use crate::wasm_emulation::channel::RemoteChannel; use crate::wasm_emulation::query::ContainsRemote; use crate::{ custom_app, next_block, no_init, App, AppResponse, Bank, CosmosRouter, Executor, Module, - Router, Wasm, WasmKeeper, WasmSudo, + Router, Wasm, WasmSudo, }; use crate::{AppBuilder, IntoAddr}; use cosmwasm_std::testing::{mock_env, MockQuerier}; @@ -21,7 +20,6 @@ use cosmwasm_std::{ OverflowError, OverflowOperation, Querier, Reply, StdError, StdResult, Storage, SubMsg, WasmMsg, }; -use cw_orch::daemon::RUNTIME; use cw_storage_plus::Item; use cw_utils::parse_instantiate_response_data; use schemars::JsonSchema; @@ -119,12 +117,13 @@ fn multi_level_bank_cache() { // set personal balance let init_funds = vec![coin(20, "btc"), coin(100, "eth")]; - let mut app = App::new(remote_channel(), |router, _, storage| { + let mut app = App::new(|router, _, storage| { router .bank .init_balance(storage, &owner_addr, init_funds) .unwrap(); - }); + }) + .with_remote(remote_channel()); // cache 1 - send some tokens let mut cache = StorageTransaction::new(app.storage()); @@ -203,7 +202,7 @@ fn send_tokens() { // set personal balance let init_funds = vec![coin(20, "btc"), coin(100, "eth")]; let rcpt_funds = vec![coin(5, "btc")]; - let mut app = App::new(remote_channel(), |router, _, storage| { + let mut app = App::new(|router, _, storage| { // initialization moved to App construction router .bank @@ -213,7 +212,8 @@ fn send_tokens() { .bank .init_balance(storage, &recipient_addr, rcpt_funds) .unwrap(); - }); + }) + .with_remote(remote_channel()); // send both tokens let to_send = vec![coin(30, "eth"), coin(5, "btc")]; @@ -250,12 +250,13 @@ fn simple_contract() { // set personal balance let init_funds = vec![coin(20, "btc"), coin(100, "eth")]; - let mut app = App::new(remote_channel(), |router, _, storage| { + let mut app = App::new(|router, _, storage| { router .bank .init_balance(storage, &owner_addr, init_funds) .unwrap(); - }); + }) + .with_remote(remote_channel()); // set up contract let code_id = app.store_code(payout::contract()); @@ -339,15 +340,15 @@ fn reflect_success() { // set personal balance let init_funds = vec![coin(20, "btc"), coin(100, "eth")]; - let mut app = - custom_app::(remote_channel(), |router, _, storage| { - router - .bank - .init_balance(storage, &owner_addr, init_funds) - .unwrap(); - router.bank.set_remote(remote_channel()); - router.wasm.set_remote(remote_channel()); - }); + let mut app = custom_app::(|router, _, storage| { + router + .bank + .init_balance(storage, &owner_addr, init_funds) + .unwrap(); + router.bank.set_remote(remote_channel()); + router.wasm.set_remote(remote_channel()); + }) + .with_remote(remote_channel()); // set up payout contract let payout_id = app.store_code(payout::contract()); @@ -449,15 +450,15 @@ fn reflect_error() { // set personal balance let init_funds = vec![coin(20, "btc"), coin(100, "eth")]; - let mut app = - custom_app::(remote_channel(), |router, _, storage| { - router - .bank - .init_balance(storage, &owner, init_funds) - .unwrap(); - router.bank.set_remote(remote_channel()); - router.wasm.set_remote(remote_channel()); - }); + let mut app = custom_app::(|router, _, storage| { + router + .bank + .init_balance(storage, &owner, init_funds) + .unwrap(); + router.bank.set_remote(remote_channel()); + router.wasm.set_remote(remote_channel()); + }) + .with_remote(remote_channel()); // set up reflect contract let reflect_id = app.store_code(reflect::contract()); @@ -549,12 +550,13 @@ fn sudo_works() { // set personal balance let init_funds = vec![coin(100, "eth")]; - let mut app = App::new(remote_channel(), |router, _, storage| { + let mut app = App::new(|router, _, storage| { router .bank .init_balance(storage, &owner_addr, init_funds) .unwrap(); - }); + }) + .with_remote(remote_channel()); let payout_id = app.store_code(payout::contract()); @@ -613,15 +615,15 @@ fn reflect_sub_message_reply_works() { // set personal balance let init_funds = vec![coin(20, "btc"), coin(100, "eth")]; - let mut app = - custom_app::(remote_channel(), |router, _, storage| { - router - .bank - .init_balance(storage, &owner, init_funds) - .unwrap(); - router.bank.set_remote(remote_channel()); - router.wasm.set_remote(remote_channel()); - }); + let mut app = custom_app::(|router, _, storage| { + router + .bank + .init_balance(storage, &owner, init_funds) + .unwrap(); + router.bank.set_remote(remote_channel()); + router.wasm.set_remote(remote_channel()); + }) + .with_remote(remote_channel()); // set up reflect contract let reflect_id = app.store_code(reflect::contract()); @@ -779,12 +781,13 @@ fn sent_wasm_migration_works() { // set personal balance let init_funds = coins(30, "btc"); - let mut app = App::new(remote_channel(), |router, _, storage| { + let mut app = App::new(|router, _, storage| { router .bank .init_balance(storage, &owner_addr, init_funds) .unwrap(); - }); + }) + .with_remote(remote_channel()); // create a hackatom contract with some funds let code_id = app.store_code(hackatom::contract()); @@ -854,12 +857,13 @@ fn sent_funds_properly_visible_on_execution() { // set personal balance let init_funds = coins(30, "btc"); - let mut app = App::new(remote_channel(), |router, _, storage| { + let mut app = App::new(|router, _, storage| { router .bank .init_balance(storage, &owner_addr, init_funds) .unwrap(); - }); + }) + .with_remote(remote_channel()); let code_id = app.store_code(hackatom::contract()); @@ -1230,15 +1234,15 @@ mod reply_data_overwrite { // set personal balance let init_funds = coins(100, "tgd"); - let mut app = - custom_app::(remote_channel(), |router, _, storage| { - router - .bank - .init_balance(storage, &owner, init_funds) - .unwrap(); - router.bank.set_remote(remote_channel()); - router.wasm.set_remote(remote_channel()); - }); + let mut app = custom_app::(|router, _, storage| { + router + .bank + .init_balance(storage, &owner, init_funds) + .unwrap(); + router.bank.set_remote(remote_channel()); + router.wasm.set_remote(remote_channel()); + }) + .with_remote(remote_channel()); // set up reflect contract let reflect_id = app.store_code(reflect::contract()); @@ -1710,7 +1714,6 @@ mod custom_messages { mod protobuf_wrapped_data { use super::*; - use crate::BasicApp; #[test] fn instantiate_wrapped_properly() { @@ -1719,15 +1722,15 @@ mod protobuf_wrapped_data { // set personal balance let init_funds = vec![coin(20, "btc")]; - let mut app = - custom_app::(remote_channel(), |router, _, storage| { - router - .bank - .init_balance(storage, &owner, init_funds) - .unwrap(); - router.bank.set_remote(remote_channel()); - router.wasm.set_remote(remote_channel()); - }); + let mut app = custom_app::(|router, _, storage| { + router + .bank + .init_balance(storage, &owner, init_funds) + .unwrap(); + router.bank.set_remote(remote_channel()); + router.wasm.set_remote(remote_channel()); + }) + .with_remote(remote_channel()); // set up reflect contract let code_id = app.store_code(reflect::contract()); diff --git a/src/wasm.rs b/src/wasm.rs index e96137f9..487f5405 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -181,6 +181,7 @@ pub trait Wasm: AllWasmQuerier + ContainsRemote { } pub type LocalRustContract = *mut dyn Contract; +/// A structure representing a default wasm keeper. pub struct WasmKeeper { /// Contract codes that stand for wasm code in real-life blockchain. pub code_base: RefCell>, From 8c83ac84404f5a92da3a80f9a91039ebab701c69 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 14 Jan 2025 19:06:18 +0100 Subject: [PATCH 78/81] Push --- Cargo.lock | 9 +++------ Cargo.toml | 3 ++- examples/abstract_test_app.rs | 6 +++--- examples/cavern_test_app.rs | 2 +- examples/cousin_test.rs | 2 +- examples/test_app.rs | 2 +- src/queries/bank.rs | 2 +- src/queries/wasm.rs | 2 +- src/tests/mod.rs | 6 ++---- src/wasm.rs | 13 +++++++++---- src/wasm_emulation/channel.rs | 2 +- src/wasm_emulation/contract.rs | 2 +- src/wasm_emulation/query/bank.rs | 2 +- src/wasm_emulation/query/wasm.rs | 2 +- src/wasm_emulation/storage/analyzer.rs | 4 ++-- src/wasm_emulation/storage/dual_std_storage.rs | 2 +- src/wasm_emulation/storage/dual_storage.rs | 2 +- tests/mod.rs | 5 +++-- 18 files changed, 35 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9f2fb640..cb37ed0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -683,6 +683,7 @@ dependencies = [ "cosmwasm-std 2.2.0", "cosmwasm-vm", "cw-orch", + "cw-orch-daemon", "cw-storage-plus 2.0.0", "cw-utils 2.0.0", "cw2 2.0.0", @@ -1252,14 +1253,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8970af7113824ab8d82f0a0d12f92b41d85410f3b7651425989ffa55d517708b" dependencies = [ "anyhow", - "cosmrs", "cosmwasm-std 2.2.0", "cw-orch-contract-derive", "cw-orch-core", - "cw-orch-daemon", "cw-orch-fns-derive", "cw-orch-mock", - "cw-orch-networks", "cw-orch-traits", "cw-utils 2.0.0", "hex", @@ -1267,7 +1265,6 @@ dependencies = [ "schemars", "serde", "thiserror", - "tokio", ] [[package]] @@ -1303,9 +1300,9 @@ dependencies = [ [[package]] name = "cw-orch-daemon" -version = "0.28.1" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb318421ff15d3760f21cb851de41b3b6a82cc42bedddebe2abb677507fbc752" +checksum = "148b57fe55a3f7bc56a42773646ee2a5722084e0c1b9a2f618226b610acfb2fb" dependencies = [ "anyhow", "async-recursion", diff --git a/Cargo.toml b/Cargo.toml index 0839cc69..b754ddf0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,7 +48,7 @@ thiserror = "1.0.64" # Clone testing deps ## Network -cw-orch = { version = "0.27.0", features = ["daemon"] } +cw-orch-daemon = { version = "0.29.1" } tokio = "1.28.2" tonic = "0.12.2" @@ -82,6 +82,7 @@ osmosis-std-derive = { version = "0.26.0", optional = true } prost-types = { version = "0.13.4", optional = true } serde-cw-value = { version = "0.7.0", optional = true } chrono = { version = "0.4.39", optional = true } +cw-orch = "0.27.0" [dev-dependencies] hex = "0.4.3" diff --git a/examples/abstract_test_app.rs b/examples/abstract_test_app.rs index d75ae846..2a400376 100644 --- a/examples/abstract_test_app.rs +++ b/examples/abstract_test_app.rs @@ -4,7 +4,7 @@ // use cosmwasm_std::coins; // use cosmwasm_std::Timestamp; // use cosmwasm_std::Uint128; -// use cw_orch::daemon::queriers::Node; +// use cw_orch_daemon::queriers::Node; // use cw_orch_daemon::DaemonQuerier; // use tokio::runtime::Runtime; @@ -42,7 +42,7 @@ // use abstract_interface::ManagerQueryFns; // use cosmwasm_std::Empty; // use cw_multi_test::WasmKeeper; -// use cw_orch::daemon::Daemon; +// use cw_orch_daemon::Daemon; // use cw_orch::deploy::Deploy; // use cw_orch_daemon::prelude::ContractInstance; @@ -61,7 +61,7 @@ // dotenv().ok(); // let runtime = tokio::runtime::Runtime::new().unwrap(); -// let mut chain = cw_orch::daemon::networks::JUNO_1; +// let mut chain = cw_orch_daemon::networks::JUNO_1; // chain.grpc_urls = &["http://juno-grpc.polkachu.com:12690"]; // let daemon = Daemon::builder() diff --git a/examples/cavern_test_app.rs b/examples/cavern_test_app.rs index 4a852c81..c9b1ae59 100644 --- a/examples/cavern_test_app.rs +++ b/examples/cavern_test_app.rs @@ -5,7 +5,7 @@ use clone_cw_multi_test::{ use cosmwasm_schema::{cw_serde, QueryResponses}; use cosmwasm_std::{coins, Addr, BlockInfo, ContractInfoResponse, QueryRequest, WasmQuery}; use cw20::BalanceResponse; -use cw_orch::daemon::{networks::PHOENIX_1, queriers::Node}; +use cw_orch_daemon::{networks::PHOENIX_1, queriers::Node}; use std::path::Path; use tokio::runtime::Runtime; diff --git a/examples/cousin_test.rs b/examples/cousin_test.rs index e592dc38..27234597 100644 --- a/examples/cousin_test.rs +++ b/examples/cousin_test.rs @@ -10,7 +10,7 @@ use clone_cw_multi_test::{ }; use cosmwasm_std::{Addr, Empty}; use counter::msg::{ExecuteMsg, GetCountResponse, QueryMsg}; -use cw_orch::daemon::networks::PHOENIX_1; +use cw_orch_daemon::networks::PHOENIX_1; use tokio::runtime::Runtime; mod counter; diff --git a/examples/test_app.rs b/examples/test_app.rs index 7e46b5c4..3d209cc0 100644 --- a/examples/test_app.rs +++ b/examples/test_app.rs @@ -7,7 +7,7 @@ use cw20::AllAccountsResponse; use cw20::Cw20ExecuteMsg; use cw20::Cw20QueryMsg; -use cw_orch::daemon::networks::PHOENIX_1; +use cw_orch_daemon::networks::PHOENIX_1; use cosmwasm_std::Empty; use tokio::runtime::Runtime; diff --git a/src/queries/bank.rs b/src/queries/bank.rs index 4cdb5046..012ebc65 100644 --- a/src/queries/bank.rs +++ b/src/queries/bank.rs @@ -7,7 +7,7 @@ pub struct BankRemoteQuerier; impl BankRemoteQuerier { pub fn get_balance(remote: RemoteChannel, account: &Addr) -> AnyResult> { - let querier = cw_orch::daemon::queriers::Bank { + let querier = cw_orch_daemon::queriers::Bank { channel: remote.channel, rt_handle: Some(remote.rt.clone()), }; diff --git a/src/queries/wasm.rs b/src/queries/wasm.rs index c09aa7e3..d2b53bed 100644 --- a/src/queries/wasm.rs +++ b/src/queries/wasm.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use anyhow::Result as AnyResult; use cosmwasm_std::{Addr, Binary, CodeInfoResponse, CustomQuery, Order, Storage}; -use cw_orch::daemon::queriers::CosmWasm; +use cw_orch_daemon::queriers::CosmWasm; use crate::{ prefixed_storage::prefixed_read, diff --git a/src/tests/mod.rs b/src/tests/mod.rs index a313b471..024a63df 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -1,10 +1,8 @@ #![cfg(test)] use cosmwasm_std::Empty; -use cw_orch::{ - daemon::{networks::XION_TESTNET_1, RUNTIME}, - prelude::ChainInfo, -}; +use cw_orch::prelude::ChainInfo; +use cw_orch_daemon::{networks::XION_TESTNET_1, RUNTIME}; use crate::{ no_init, diff --git a/src/wasm.rs b/src/wasm.rs index 487f5405..3ea428b2 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -316,7 +316,7 @@ where /// Returns an identifier of the stored contract code. fn store_wasm_code(&mut self, creator: Addr, code: Vec) -> u64 { let code_id = self - .next_code_id() + .next_wasm_code_id() .unwrap_or_else(|| panic!("{}", Error::NoMoreCodeIdAvailable)); let code = WasmContract::Local(LocalWasmContract { module: create_module(&code).unwrap(), @@ -341,7 +341,7 @@ where /// Returns an identifier of the stored contract code. fn store_code(&mut self, creator: Addr, code: Box>) -> u64 { let code_id = self - .next_code_id() + .next_rust_code_id() .unwrap_or_else(|| panic!("{}", Error::NoMoreCodeIdAvailable)); self.save_code(code_id, creator, code) } @@ -368,7 +368,7 @@ where fn duplicate_code(&mut self, code_id: u64) -> AnyResult { let code_data = self.code_data(code_id)?; let new_code_id = self - .next_code_id() + .next_rust_code_id() .ok_or_else(Error::no_more_code_id_available)?; self.code_data.insert( new_code_id, @@ -629,7 +629,12 @@ where } /// Returns the next contract's code identifier. - fn next_code_id(&self) -> Option { + fn next_rust_code_id(&self) -> Option { + Some((self.code_base.borrow().len() + 1 + LOCAL_RUST_CODE_OFFSET) as u64) + } + + /// Returns the next contract's code identifier. + fn next_wasm_code_id(&self) -> Option { Some((self.code_base.borrow().len() + 1 + LOCAL_WASM_CODE_OFFSET) as u64) } diff --git a/src/wasm_emulation/channel.rs b/src/wasm_emulation/channel.rs index 445c532e..041e5b97 100644 --- a/src/wasm_emulation/channel.rs +++ b/src/wasm_emulation/channel.rs @@ -1,5 +1,5 @@ use anyhow::Result as AnyResult; -use cw_orch::daemon::GrpcChannel; +use cw_orch_daemon::GrpcChannel; use tokio::runtime::{Handle, Runtime}; use tonic::transport::Channel; diff --git a/src/wasm_emulation/contract.rs b/src/wasm_emulation/contract.rs index 72b74b14..a3e3c5e3 100644 --- a/src/wasm_emulation/contract.rs +++ b/src/wasm_emulation/contract.rs @@ -14,7 +14,7 @@ use cosmwasm_vm::{ call_execute, call_instantiate, call_migrate, call_query, call_reply, call_sudo, internals::check_wasm, Backend, BackendApi, Instance, InstanceOptions, Querier, WasmLimits, }; -use cw_orch::daemon::queriers::CosmWasm; +use cw_orch_daemon::queriers::CosmWasm; use serde::de::DeserializeOwned; use wasmer::Engine; diff --git a/src/wasm_emulation/query/bank.rs b/src/wasm_emulation/query/bank.rs index 5987fed1..136b478a 100644 --- a/src/wasm_emulation/query/bank.rs +++ b/src/wasm_emulation/query/bank.rs @@ -6,7 +6,7 @@ use cosmwasm_vm::GasInfo; use cw_utils::NativeBalance; -use cw_orch::daemon::queriers::Bank; +use cw_orch_daemon::queriers::Bank; use cosmwasm_std::Binary; use cosmwasm_std::Coin; diff --git a/src/wasm_emulation/query/wasm.rs b/src/wasm_emulation/query/wasm.rs index eddbbd4e..18eb4dab 100644 --- a/src/wasm_emulation/query/wasm.rs +++ b/src/wasm_emulation/query/wasm.rs @@ -20,7 +20,7 @@ use cosmwasm_std::{ use cosmwasm_std::{ContractInfo, ContractResult}; use cosmwasm_std::WasmQuery; -use cw_orch::daemon::queriers::CosmWasm; +use cw_orch_daemon::queriers::CosmWasm; use serde::de::DeserializeOwned; use crate::wasm_emulation::channel::RemoteChannel; diff --git a/src/wasm_emulation/storage/analyzer.rs b/src/wasm_emulation/storage/analyzer.rs index 1ae682b1..2ec4a6bc 100644 --- a/src/wasm_emulation/storage/analyzer.rs +++ b/src/wasm_emulation/storage/analyzer.rs @@ -144,7 +144,7 @@ impl StorageAnalyzer { } pub fn compare_all_readable_contract_storage(&self) { - let wasm_querier = cw_orch::daemon::queriers::CosmWasm::new_sync( + let wasm_querier = cw_orch_daemon::queriers::CosmWasm::new_sync( self.remote.channel.clone(), &self.remote.rt, ); @@ -232,7 +232,7 @@ impl StorageAnalyzer { } pub fn compare_all_balances(&self) { - let bank_querier = cw_orch::daemon::queriers::Bank { + let bank_querier = cw_orch_daemon::queriers::Bank { channel: self.remote.channel.clone(), rt_handle: Some(self.remote.rt.clone()), }; diff --git a/src/wasm_emulation/storage/dual_std_storage.rs b/src/wasm_emulation/storage/dual_std_storage.rs index 8469dcde..6d523113 100644 --- a/src/wasm_emulation/storage/dual_std_storage.rs +++ b/src/wasm_emulation/storage/dual_std_storage.rs @@ -4,7 +4,7 @@ use cosmrs::proto::cosmos::base::query::v1beta1::PageRequest; use cosmrs::proto::cosmwasm::wasm::v1::Model; use cosmwasm_std::{Addr, Record}; use cosmwasm_std::{Order, Storage}; -use cw_orch::daemon::queriers::CosmWasm; +use cw_orch_daemon::queriers::CosmWasm; use num_bigint::{BigInt, Sign}; use std::iter::{self, Peekable}; diff --git a/src/wasm_emulation/storage/dual_storage.rs b/src/wasm_emulation/storage/dual_storage.rs index bc6623d8..b98b10ba 100644 --- a/src/wasm_emulation/storage/dual_storage.rs +++ b/src/wasm_emulation/storage/dual_storage.rs @@ -15,7 +15,7 @@ use num_bigint::{BigInt, Sign}; use std::collections::HashMap; use std::iter; -use cw_orch::daemon::queriers::CosmWasm; +use cw_orch_daemon::queriers::CosmWasm; fn get_key_bigint(mut key1: Vec, mut key2: Vec) -> (BigInt, BigInt) { if key1.len() >= key2.len() { diff --git a/tests/mod.rs b/tests/mod.rs index da2e3d1d..7c81a535 100644 --- a/tests/mod.rs +++ b/tests/mod.rs @@ -3,7 +3,8 @@ use clone_cw_multi_test::wasm_emulation::channel::RemoteChannel; use clone_cw_multi_test::{no_init, App}; use cw_multi_test::wasm_emulation::query::ContainsRemote; -use cw_orch::daemon::RUNTIME; +use cw_orch_daemon::networks::XION_TESTNET_1; +use cw_orch_daemon::RUNTIME; mod test_api; mod test_app; @@ -88,7 +89,7 @@ mod test_contracts { } } -use cw_orch::{daemon::networks::XION_TESTNET_1, prelude::ChainInfo}; +use cw_orch::prelude::ChainInfo; pub const CHAIN: ChainInfo = XION_TESTNET_1; pub fn remote_channel() -> RemoteChannel { RemoteChannel::new( From bb3a38d186e6c07c1b53b4f0ba5759cf4ace619e Mon Sep 17 00:00:00 2001 From: Kayanski Date: Wed, 15 Jan 2025 12:37:44 +0100 Subject: [PATCH 79/81] Fix next code id --- src/lib.rs | 2 +- src/wasm.rs | 18 ++++++------------ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index c945adc4..f9bfcbf3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -177,5 +177,5 @@ pub use crate::staking::{ Distribution, DistributionKeeper, StakeKeeper, Staking, StakingInfo, StakingSudo, }; pub use crate::stargate::{Stargate, StargateAccepting, StargateFailing}; +pub use crate::wasm::LOCAL_CODE_OFFSET; pub use crate::wasm::{ContractData, Wasm, WasmKeeper, WasmSudo}; -pub use crate::wasm::{LOCAL_RUST_CODE_OFFSET, LOCAL_WASM_CODE_OFFSET}; diff --git a/src/wasm.rs b/src/wasm.rs index 3ea428b2..78a15676 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -40,8 +40,7 @@ pub const NAMESPACE_WASM: &[u8] = b"wasm"; /// /// [address namespace]: https://github.com/CosmWasm/wasmd/blob/96e2b91144c9a371683555f3c696f882583cc6a2/x/wasm/types/events.go#L59 const CONTRACT_ATTR: &str = "_contract_address"; -pub const LOCAL_WASM_CODE_OFFSET: usize = 5_000_000; -pub const LOCAL_RUST_CODE_OFFSET: usize = 10_000_000; +pub const LOCAL_CODE_OFFSET: usize = 5_000_000; /// A structure representing a privileged message. #[derive(Clone, Debug, PartialEq, Eq, JsonSchema)] @@ -316,7 +315,7 @@ where /// Returns an identifier of the stored contract code. fn store_wasm_code(&mut self, creator: Addr, code: Vec) -> u64 { let code_id = self - .next_wasm_code_id() + .next_local_code_id() .unwrap_or_else(|| panic!("{}", Error::NoMoreCodeIdAvailable)); let code = WasmContract::Local(LocalWasmContract { module: create_module(&code).unwrap(), @@ -341,7 +340,7 @@ where /// Returns an identifier of the stored contract code. fn store_code(&mut self, creator: Addr, code: Box>) -> u64 { let code_id = self - .next_rust_code_id() + .next_local_code_id() .unwrap_or_else(|| panic!("{}", Error::NoMoreCodeIdAvailable)); self.save_code(code_id, creator, code) } @@ -368,7 +367,7 @@ where fn duplicate_code(&mut self, code_id: u64) -> AnyResult { let code_data = self.code_data(code_id)?; let new_code_id = self - .next_rust_code_id() + .next_local_code_id() .ok_or_else(Error::no_more_code_id_available)?; self.code_data.insert( new_code_id, @@ -629,13 +628,8 @@ where } /// Returns the next contract's code identifier. - fn next_rust_code_id(&self) -> Option { - Some((self.code_base.borrow().len() + 1 + LOCAL_RUST_CODE_OFFSET) as u64) - } - - /// Returns the next contract's code identifier. - fn next_wasm_code_id(&self) -> Option { - Some((self.code_base.borrow().len() + 1 + LOCAL_WASM_CODE_OFFSET) as u64) + fn next_local_code_id(&self) -> Option { + Some((self.code_data.len() + 1 + LOCAL_CODE_OFFSET) as u64) } /// Executes the contract's `query` entry-point. From 2c74c61dbbad98ab6a25bc8606034c9028f9cc7e Mon Sep 17 00:00:00 2001 From: Buckram Date: Wed, 15 Jan 2025 18:11:13 +0200 Subject: [PATCH 80/81] add payload support on clone-testing --- src/contracts.rs | 4 ++-- src/wasm.rs | 10 +++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/contracts.rs b/src/contracts.rs index 868c3146..80747379 100644 --- a/src/contracts.rs +++ b/src/contracts.rs @@ -488,7 +488,7 @@ where { SubMsg { id: msg.id, - payload: Binary::default(), + payload: msg.payload, msg: match msg.msg { CosmosMsg::Wasm(wasm) => CosmosMsg::Wasm(wasm), CosmosMsg::Bank(bank) => CosmosMsg::Bank(bank), @@ -501,7 +501,7 @@ where CosmosMsg::Ibc(ibc) => CosmosMsg::Ibc(ibc), #[cfg(feature = "cosmwasm_2_0")] CosmosMsg::Any(any) => CosmosMsg::Any(any), - _ => panic!("unknown message variant {:?}", msg), + other => panic!("unknown message variant {:?}", other), }, gas_limit: msg.gas_limit, reply_on: msg.reply_on, diff --git a/src/wasm.rs b/src/wasm.rs index 78a15676..5c239507 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -954,7 +954,11 @@ where msg: SubMsg, ) -> AnyResult { let SubMsg { - msg, id, reply_on, .. + msg, + id, + reply_on, + payload, + .. } = msg; // execute in cache @@ -967,7 +971,7 @@ where if matches!(reply_on, ReplyOn::Always | ReplyOn::Success) { let reply = Reply { id, - payload: Default::default(), + payload, gas_used: 0, result: SubMsgResult::Ok( #[allow(deprecated)] @@ -993,7 +997,7 @@ where if matches!(reply_on, ReplyOn::Always | ReplyOn::Error) { let reply = Reply { id, - payload: Default::default(), + payload, gas_used: 0, result: SubMsgResult::Err(format!("{:?}", e)), }; From f3c6d27940e84f8fa141d2374792e5dfb7a3c570 Mon Sep 17 00:00:00 2001 From: Buckram Date: Mon, 20 Jan 2025 22:06:38 +0200 Subject: [PATCH 81/81] add supply query --- src/wasm_emulation/query/bank.rs | 18 +++++++++++++++++- src/wasm_emulation/query/gas.rs | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/wasm_emulation/query/bank.rs b/src/wasm_emulation/query/bank.rs index 136b478a..2a577bd1 100644 --- a/src/wasm_emulation/query/bank.rs +++ b/src/wasm_emulation/query/bank.rs @@ -1,7 +1,7 @@ use crate::wasm_emulation::channel::RemoteChannel; use crate::wasm_emulation::query::gas::{GAS_COST_ALL_BALANCE_QUERY, GAS_COST_BALANCE_QUERY}; use crate::wasm_emulation::query::mock_querier::QueryResultWithGas; -use cosmwasm_std::Addr; +use cosmwasm_std::{Addr, SupplyResponse}; use cosmwasm_vm::GasInfo; use cw_utils::NativeBalance; @@ -18,6 +18,8 @@ use cosmwasm_std::{AllBalanceResponse, BalanceResponse, BankQuery}; use cosmwasm_std::to_json_binary; use cosmwasm_std::{ContractResult, SystemResult}; +use super::gas::GAS_COST_SUPPLY_QUERY; + #[derive(Clone)] pub struct BankQuerier { #[allow(dead_code)] @@ -120,6 +122,19 @@ impl BankQuerier { let bank_res = AllBalanceResponse::new(amount.unwrap()); to_json_binary(&bank_res).into() } + BankQuery::Supply { denom } => { + let supply_clone = self.supplies.get(denom).cloned().unwrap_or_default(); + let querier = Bank { + channel: self.remote.channel.clone(), + rt_handle: Some(self.remote.rt.clone()), + }; + let query_result: Result = + self.remote.rt.block_on(querier._supply_of(denom)); + let mut supply = query_result.unwrap_or(Coin::new(Uint128::zero(), denom)); + supply.amount += supply_clone; + let supply_res = SupplyResponse::new(supply); + to_json_binary(&supply_res).into() + } &_ => panic!("Not implemented {:?}", request), }; @@ -127,6 +142,7 @@ impl BankQuerier { let gas_info = match request { BankQuery::Balance { .. } => GAS_COST_BALANCE_QUERY, BankQuery::AllBalances { .. } => GAS_COST_ALL_BALANCE_QUERY, + BankQuery::Supply { .. } => GAS_COST_SUPPLY_QUERY, &_ => panic!("Not implemented {:?}", request), }; diff --git a/src/wasm_emulation/query/gas.rs b/src/wasm_emulation/query/gas.rs index 9dd7b9b3..5ee4c613 100644 --- a/src/wasm_emulation/query/gas.rs +++ b/src/wasm_emulation/query/gas.rs @@ -1,6 +1,7 @@ // Bank pub const GAS_COST_BALANCE_QUERY: u64 = 1000; pub const GAS_COST_ALL_BALANCE_QUERY: u64 = 10000; +pub const GAS_COST_SUPPLY_QUERY: u64 = 1000; // Staking pub const GAS_COST_BONDED_DENOM: u64 = 100;