From 82a8d4cc2915face53a73b8e75867366f2ff0312 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Fri, 11 Feb 2022 11:41:42 +0100 Subject: [PATCH 01/42] Add ink! linting MVP stage --- .github/workflows/macos.yml | 2 + .github/workflows/windows.yml | 2 + .gitlab-ci.yml | 26 ++ Cargo.lock | 398 +++++++++--------- README.md | 2 + build.rs | 181 +++++++- ink_linting/.cargo/config.toml | 11 + ink_linting/.rustfmt.toml | 3 + ink_linting/Cargo.toml | 91 ++++ ink_linting/LICENSE | 203 +++++++++ ink_linting/README.md | 17 + ink_linting/rust-toolchain | 6 + ink_linting/src/lib.rs | 40 ++ ink_linting/src/mapping_initialized.rs | 345 +++++++++++++++ .../ui/fail/mapping-nested-initialize-call.rs | 58 +++ .../mapping-nested-initialize-call.stderr | 27 ++ .../ui/fail/mapping-one-constructor.rs | 47 +++ .../ui/fail/mapping-one-constructor.stderr | 26 ++ .../ui/fail/mapping-two-constructors-01.rs | 62 +++ .../fail/mapping-two-constructors-01.stderr | 27 ++ .../ui/fail/mapping-two-constructors-02.rs | 62 +++ .../fail/mapping-two-constructors-02.stderr | 27 ++ .../mapping-additional-logic-constructor.rs | 61 +++ .../ui/pass/mapping-one-constructor.rs | 52 +++ .../ui/pass/mapping-two-constructors.rs | 60 +++ metadata/Cargo.toml | 2 +- src/cmd/build.rs | 143 ++++++- src/cmd/metadata.rs | 1 + src/cmd/new.rs | 61 +-- src/cmd/test.rs | 2 +- src/util.rs | 98 ++++- src/workspace/manifest.rs | 10 +- 32 files changed, 1866 insertions(+), 287 deletions(-) create mode 100644 ink_linting/.cargo/config.toml create mode 100644 ink_linting/.rustfmt.toml create mode 100644 ink_linting/Cargo.toml create mode 100644 ink_linting/LICENSE create mode 100644 ink_linting/README.md create mode 100644 ink_linting/rust-toolchain create mode 100644 ink_linting/src/lib.rs create mode 100644 ink_linting/src/mapping_initialized.rs create mode 100644 ink_linting/ui/fail/mapping-nested-initialize-call.rs create mode 100644 ink_linting/ui/fail/mapping-nested-initialize-call.stderr create mode 100644 ink_linting/ui/fail/mapping-one-constructor.rs create mode 100644 ink_linting/ui/fail/mapping-one-constructor.stderr create mode 100644 ink_linting/ui/fail/mapping-two-constructors-01.rs create mode 100644 ink_linting/ui/fail/mapping-two-constructors-01.stderr create mode 100644 ink_linting/ui/fail/mapping-two-constructors-02.rs create mode 100644 ink_linting/ui/fail/mapping-two-constructors-02.stderr create mode 100644 ink_linting/ui/pass/mapping-additional-logic-constructor.rs create mode 100644 ink_linting/ui/pass/mapping-one-constructor.rs create mode 100644 ink_linting/ui/pass/mapping-two-constructors.rs diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 7cea2c73..184ef096 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -50,6 +50,8 @@ jobs: run: | wasm-opt --version cargo -vV + cargo install cargo-dylint dylint-link + cargo dylint --version cargo run -- contract --version cargo run -- contract new foobar echo "[workspace]" >> foobar/Cargo.toml diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index e9a179bf..087efe73 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -53,6 +53,8 @@ jobs: run: | wasm-opt --version cargo -vV + cargo install cargo-dylint dylint-link + cargo dylint --version cargo run -- contract --version cargo run -- contract new foobar echo "[workspace]" >> foobar/Cargo.toml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 99f0db2b..87258d9e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -39,11 +39,17 @@ workflow: - cargo -vV - rustc -vV - rustup show + - cargo dylint --version - bash --version - ./scripts/ci/pre_cache.sh # global RUSTFLAGS overrides the linker args so this way is better to pass the flags - printf '[build]\nrustflags = ["-C", "link-dead-code"]\n' > ${CARGO_HOME}/config - sccache -s + + # needed until https://github.com/mozilla/sccache/issues/1000 is fixed. + # this is unfortunate, since it disables `sccache` for this entire file. + - unset RUSTC_WRAPPER + - git show rules: - if: $CI_PIPELINE_SOURCE == "web" @@ -81,6 +87,26 @@ clippy: #### stage: test (all features) +test-dylint: + stage: test + <<: *docker-env + script: + - cd ink_linting/ + + # Installing these components here is necessary because + # `ink_linting/` has a fixed `rust-toolchain` file. + # We can't move this line to the Docker container, since + # that would then make it impossible to upgrade the + # `ink_linting/rust-toolchain` file while still having + # this CI job succeed. + - rustup component add rustfmt clippy rust-src + + - cargo check --verbose + - cargo fmt --verbose --all -- --check + - cargo clippy --verbose -- -D warnings; + + - cargo test --verbose --workspace --all-features + test: stage: test <<: *docker-env diff --git a/Cargo.lock b/Cargo.lock index b248953e..46d2e2db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -33,7 +33,7 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "getrandom 0.2.3", + "getrandom 0.2.4", "once_cell", "version_check", ] @@ -234,9 +234,9 @@ dependencies = [ [[package]] name = "async-task" -version = "4.0.3" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0" +checksum = "677d306121baf53310a3fd342d88dc0824f6bbeace68347593658525565abee8" [[package]] name = "async-trait" @@ -268,15 +268,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.63" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321629d8ba6513061f26707241fa9bc89524ff1cd7a915a97ef0c62c666ce1b6" +checksum = "5e121dee8023ce33ab248d9ce1493df03c3b38a659b240096fcbd7048ff9c31f" dependencies = [ "addr2line", "cc", @@ -332,7 +332,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b94ba84325db59637ffc528bbe8c7f86c02c57cff5c0e2b9b00f9a851f42f309" dependencies = [ - "digest 0.10.1", + "digest 0.10.3", ] [[package]] @@ -363,16 +363,16 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "generic-array 0.14.4", + "generic-array 0.14.5", ] [[package]] name = "block-buffer" -version = "0.10.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1d36a02058e76b040de25a4464ba1c80935655595b661505c8b39b664828b95" +checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" dependencies = [ - "generic-array 0.14.4", + "generic-array 0.14.5", ] [[package]] @@ -421,9 +421,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.8.0" +version = "3.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c" +checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" [[package]] name = "byte-slice-cast" @@ -457,9 +457,9 @@ checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" [[package]] name = "camino" -version = "1.0.5" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52d74260d9bf6944e2208aa46841b4b8f0d7ffc0849a06837b2f510337f86b2b" +checksum = "6f3132262930b0522068049f5870a856ab8affc80c70d08b6ecb785771a6fc23" dependencies = [ "serde", ] @@ -531,9 +531,9 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba2ae6de944143141f6155a473a6b02f66c7c3f9f47316f802f80204ebfe6e12" +checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" dependencies = [ "camino", "cargo-platform", @@ -553,9 +553,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.72" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" [[package]] name = "cfg-if" @@ -598,9 +598,9 @@ dependencies = [ [[package]] name = "cmake" -version = "0.1.46" +version = "0.1.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7b858541263efe664aead4a5209a4ae5c5d2811167d4ed4ee0944503f8d2089" +checksum = "e8ad8cef104ac57b68b89df3208164d228503abbdce70f6880ffa3d970e7443a" dependencies = [ "cc", ] @@ -651,9 +651,9 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] name = "core-foundation" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" dependencies = [ "core-foundation-sys", "libc", @@ -676,9 +676,9 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.3.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "738c290dfaea84fc1ca15ad9c168d083b05a714e1efddd8edaab678dc28d2836" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ "cfg-if", ] @@ -721,9 +721,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" +checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa" dependencies = [ "cfg-if", "crossbeam-utils", @@ -742,9 +742,9 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.5" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" +checksum = "c00d6d2ea26e8b151d99093005cb442fb9a37aeaca582a03ec70946f49ab5ed9" dependencies = [ "cfg-if", "crossbeam-utils", @@ -755,9 +755,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.5" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6" dependencies = [ "cfg-if", "lazy_static", @@ -771,11 +771,12 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-common" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d6b536309245c849479fba3da410962a43ed8e51c26b729208ec0ac2798d0" +checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" dependencies = [ - "generic-array 0.14.4", + "generic-array 0.14.5", + "typenum", ] [[package]] @@ -784,7 +785,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" dependencies = [ - "generic-array 0.14.4", + "generic-array 0.14.5", "subtle", ] @@ -794,7 +795,7 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" dependencies = [ - "generic-array 0.14.4", + "generic-array 0.14.5", "subtle", ] @@ -942,18 +943,17 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array 0.14.4", + "generic-array 0.14.5", ] [[package]] name = "digest" -version = "0.10.1" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b697d66081d42af4fba142d56918a3cb21dc8eb63372c6b85d14f44fb9c5979b" +checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" dependencies = [ - "block-buffer 0.10.0", + "block-buffer 0.10.2", "crypto-common", - "generic-array 0.14.4", "subtle", ] @@ -1015,7 +1015,7 @@ dependencies = [ "ed25519", "rand 0.7.3", "serde", - "sha2 0.9.8", + "sha2 0.9.9", "zeroize", ] @@ -1055,9 +1055,9 @@ dependencies = [ [[package]] name = "event-listener" -version = "2.5.1" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59" +checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" [[package]] name = "fake-simd" @@ -1067,9 +1067,9 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "fastrand" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "779d043b6a0b90cc4c0ed7ee380a6504394cee7efd7db050e3774eee387324b2" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" dependencies = [ "instant", ] @@ -1081,7 +1081,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" dependencies = [ "byteorder", - "rand 0.8.4", + "rand 0.8.5", "rustc-hex", "static_assertions", ] @@ -1245,9 +1245,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.4" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" +checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" dependencies = [ "typenum", "version_check", @@ -1268,9 +1268,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" dependencies = [ "cfg-if", "libc", @@ -1291,15 +1291,14 @@ checksum = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" [[package]] name = "gloo-timers" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f16c88aa13d2656ef20d1c042086b8767bbe2bdb62526894275a1b062161b2e" +checksum = "4d12a7f4e95cfe710f1d624fb1210b7d961a5fb05c4fd942f4feab06e61f590e" dependencies = [ "futures-channel", "futures-core", "js-sys", "wasm-bindgen", - "web-sys", ] [[package]] @@ -1332,6 +1331,15 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c21d40587b92fa6a6c6e3c1bdbf87d75511db5672f9c93175574b3a00df1758" +dependencies = [ + "ahash", +] + [[package]] name = "heck" version = "0.3.3" @@ -1389,19 +1397,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" dependencies = [ "digest 0.9.0", - "generic-array 0.14.4", + "generic-array 0.14.5", "hmac 0.8.1", ] [[package]] name = "http" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b" +checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" dependencies = [ "bytes", "fnv", - "itoa 0.4.8", + "itoa 1.0.1", ] [[package]] @@ -1417,9 +1425,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" +checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" [[package]] name = "httpdate" @@ -1435,9 +1443,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.16" +version = "0.14.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55" +checksum = "043f0e083e9901b6cc658a77d1eb86f4fc650bbb977a4337dd63192826aa85dd" dependencies = [ "bytes", "futures-channel", @@ -1447,7 +1455,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 0.4.8", + "itoa 1.0.1", "pin-project-lite", "tokio", "tower-service", @@ -1492,9 +1500,9 @@ dependencies = [ [[package]] name = "impl-trait-for-tuples" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5dacb10c5b3bb92d46ba347505a9041e676bb20ad220101326bffb0c93031ee" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" dependencies = [ "proc-macro2", "quote", @@ -1514,7 +1522,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.11.2", ] [[package]] @@ -1543,7 +1551,7 @@ dependencies = [ "num-traits", "parity-scale-codec", "paste", - "rand 0.8.4", + "rand 0.8.5", "rlibc", "scale-info", "secp256k1", @@ -1739,9 +1747,9 @@ checksum = "72167d68f5fce3b8655487b8038691a3c9984ee769590f93f2a631f4ad64e4f5" [[package]] name = "js-sys" -version = "0.3.55" +version = "0.3.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" +checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" dependencies = [ "wasm-bindgen", ] @@ -1902,9 +1910,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.112" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" +checksum = "06e509672465a0504304aa87f9f176f2b2b716ed8fb105ebe5c02dc6dce96a94" [[package]] name = "libsecp256k1" @@ -1919,9 +1927,9 @@ dependencies = [ "libsecp256k1-core", "libsecp256k1-gen-ecmult", "libsecp256k1-gen-genmult", - "rand 0.8.4", + "rand 0.8.5", "serde", - "sha2 0.9.8", + "sha2 0.9.9", "typenum", ] @@ -1956,9 +1964,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" dependencies = [ "scopeguard", ] @@ -2010,7 +2018,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de006e09d04fc301a5f7e817b75aa49801c4479a8af753764416b085337ddcc5" dependencies = [ "hash-db", - "hashbrown", + "hashbrown 0.11.2", "parity-util-mem", ] @@ -2021,7 +2029,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d505169b746dacf02f7d14d8c80b34edfd8212159c63d23c977739a0d960c626" dependencies = [ "hash-db", - "hashbrown", + "hashbrown 0.11.2", "parity-util-mem", ] @@ -2061,9 +2069,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.7.14" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" +checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2" dependencies = [ "libc", "log", @@ -2119,9 +2127,9 @@ checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" [[package]] name = "ntapi" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" dependencies = [ "winapi", ] @@ -2213,15 +2221,15 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl-probe" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "output_vt100" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" +checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66" dependencies = [ "winapi", ] @@ -2262,7 +2270,7 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1557010476e0595c9b568d16dcfb81b93cdeb157612726f5170d31aa707bed27" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.2", "proc-macro2", "quote", "syn", @@ -2275,7 +2283,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f4cb4e169446179cbc6b8b6320cc9fca49bd2e94e8db25f25f200a8ea774770" dependencies = [ "cfg-if", - "hashbrown", + "hashbrown 0.11.2", "impl-trait-for-tuples", "parity-util-mem-derive", "parking_lot", @@ -2363,18 +2371,18 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] name = "pin-project" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08" +checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389" +checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" dependencies = [ "proc-macro2", "quote", @@ -2383,9 +2391,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" +checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" [[package]] name = "pin-utils" @@ -2448,9 +2456,9 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "predicates" @@ -2468,15 +2476,15 @@ dependencies = [ [[package]] name = "predicates-core" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57e35a3326b75e49aa85f5dc6ec15b41108cf5aee58eabb1f274dd18b73c2451" +checksum = "da1c2388b1513e1b605fcec39a95e0a9e8ef088f71443ef37099fa9ae6673fcb" [[package]] name = "predicates-tree" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "338c7be2905b732ae3984a2f40032b5e94fd8f52505b186c7d4d68d193445df7" +checksum = "4d86de6de25020a36c6d3643a86d9a6a9f552107c0559c60ea03551b5e16c032" dependencies = [ "predicates-core", "termtree", @@ -2518,9 +2526,9 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83" +checksum = "9dada8c9981fcf32929c3c0f0cd796a9284aca335565227ed88c83babb1d43dc" dependencies = [ "thiserror", "toml", @@ -2552,18 +2560,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.34" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f84e92c0f7c9d58328b85a78557813e4bd845130db68d7184635344399423b1" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" dependencies = [ "unicode-xid", ] [[package]] name = "quote" -version = "1.0.10" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" dependencies = [ "proc-macro2", ] @@ -2584,20 +2592,19 @@ dependencies = [ "libc", "rand_chacha 0.2.2", "rand_core 0.5.1", - "rand_hc 0.2.0", + "rand_hc", "rand_pcg", ] [[package]] name = "rand" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.3", - "rand_hc 0.3.1", ] [[package]] @@ -2635,7 +2642,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "getrandom 0.2.3", + "getrandom 0.2.4", ] [[package]] @@ -2647,15 +2654,6 @@ dependencies = [ "rand_core 0.5.1", ] -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core 0.6.3", -] - [[package]] name = "rand_pcg" version = "0.2.1" @@ -2804,9 +2802,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.20.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d37e5e2290f3e040b594b1a9e04377c2c671f1a1cfd9bfdef82106ac1c113f84" +checksum = "b323592e3164322f5b193dc4302e4e36cd8d37158a712d664efae1a5c2791700" dependencies = [ "log", "ring", @@ -2876,7 +2874,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baeb2780690380592f86205aa4ee49815feb2acad8c2f59e6dd207148c3f1fcd" dependencies = [ - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.2", "proc-macro2", "quote", "syn", @@ -2955,9 +2953,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.4.2" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525bc1abfda2e1998d152c45cf13e696f76d0a4972310b22fac1658b05df7c87" +checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" dependencies = [ "bitflags", "core-foundation", @@ -2968,9 +2966,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.4.2" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9dd14d83160b528b7bfd66439110573efcfbe281b17fc2ca9f39f550d619c7e" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" dependencies = [ "core-foundation-sys", "libc", @@ -3053,9 +3051,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ "block-buffer 0.9.0", "cfg-if", @@ -3072,7 +3070,7 @@ checksum = "99c3bd8169c58782adad9290a9af5939994036b76187f7b4f0e6de91dbbfc0ec" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.1", + "digest 0.10.3", ] [[package]] @@ -3081,7 +3079,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31f935e31cf406e8c0e96c2815a5516181b7004ae8c5f296293221e9b1e356bd" dependencies = [ - "digest 0.10.1", + "digest 0.10.3", "keccak", ] @@ -3096,9 +3094,9 @@ dependencies = [ [[package]] name = "signature" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02658e48d89f2bec991f9a78e69cfa4c316f8d6a6c4ec12fae1aeb263d486788" +checksum = "f054c6c1a6e95179d6f23ed974060dcefb2d9388bb7256900badad682c499de4" [[package]] name = "slab" @@ -3108,15 +3106,15 @@ checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" [[package]] name = "smallvec" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" [[package]] name = "socket2" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" dependencies = [ "libc", "winapi", @@ -3133,7 +3131,7 @@ dependencies = [ "futures", "httparse", "log", - "rand 0.8.4", + "rand 0.8.5", "sha-1", ] @@ -3213,7 +3211,7 @@ dependencies = [ "schnorrkel", "secrecy", "serde", - "sha2 0.9.8", + "sha2 0.9.9", "sp-core-hashing", "sp-debug-derive", "sp-externalities 0.10.0", @@ -3287,7 +3285,7 @@ checksum = "ec864a6a67249f0c8dd3d5acab43623a61677e85ff4f2f9b04b802d2fe780e83" dependencies = [ "blake2-rfc", "byteorder", - "sha2 0.9.8", + "sha2 0.9.9", "sp-std", "tiny-keccak", "twox-hash", @@ -3523,7 +3521,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b58cc6060b2d2f35061db5b4172f4a47353c3f01a89f281699a6c3f05d1267a" dependencies = [ "Inflector", - "proc-macro-crate 1.1.0", + "proc-macro-crate 1.1.2", "proc-macro2", "quote", "syn", @@ -3573,7 +3571,7 @@ dependencies = [ "sp-trie 5.0.0", "thiserror", "tracing", - "trie-db 0.23.0", + "trie-db 0.23.1", "trie-root 0.17.0", ] @@ -3652,7 +3650,7 @@ dependencies = [ "scale-info", "sp-core 5.0.0", "sp-std", - "trie-db 0.23.0", + "trie-db 0.23.1", "trie-root 0.17.0", ] @@ -3718,9 +3716,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "ss58-registry" -version = "1.12.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8319f44e20b42e5c11b88b1ad4130c35fe2974665a007b08b02322070177136a" +checksum = "d8cb4b9ce18beb6cb16ecad62d936245cef5212ddc8e094d7417a75e8d0e85f5" dependencies = [ "Inflector", "proc-macro2", @@ -3781,7 +3779,7 @@ dependencies = [ "hmac 0.11.0", "pbkdf2 0.8.0", "schnorrkel", - "sha2 0.9.8", + "sha2 0.9.9", "zeroize", ] @@ -3868,9 +3866,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.82" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" +checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" dependencies = [ "proc-macro2", "quote", @@ -3920,9 +3918,9 @@ dependencies = [ [[package]] name = "termtree" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13a4ec180a2de59b57434704ccfad967f789b12737738798fa08798cd5824c16" +checksum = "507e9898683b6c43a9aa55b64259b721b52ba226e0f3779137e50ad114a4c90b" [[package]] name = "textwrap" @@ -3955,9 +3953,9 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" dependencies = [ "once_cell", ] @@ -3974,7 +3972,7 @@ dependencies = [ "pbkdf2 0.4.0", "rand 0.7.3", "rustc-hash", - "sha2 0.9.8", + "sha2 0.9.9", "thiserror", "unicode-normalization", "wasm-bindgen", @@ -4017,14 +4015,15 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.15.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838" +checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" dependencies = [ "libc", "mio", "num_cpus", "pin-project-lite", + "socket2", "tokio-macros", "winapi", ] @@ -4083,9 +4082,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.29" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" +checksum = "2d8d93354fe2a8e50d5953f5ae2e47a3fc2ef03292e7ea46e3cc38f549525fb9" dependencies = [ "cfg-if", "pin-project-lite", @@ -4095,9 +4094,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e" +checksum = "8276d9a4a3a558d7b7ad5303ad50b53d58264641b82914b7ada36bd762e7a716" dependencies = [ "proc-macro2", "quote", @@ -4106,11 +4105,12 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" +checksum = "03cfcb51380632a72d3111cb8d3447a8d908e577d31beeac006f836383d29a23" dependencies = [ "lazy_static", + "valuable", ] [[package]] @@ -4126,9 +4126,9 @@ dependencies = [ [[package]] name = "tracing-serde" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb65ea441fbb84f9f6748fd496cf7f63ec9af5bca94dd86456978d055e8eb28b" +checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" dependencies = [ "serde", "tracing-core", @@ -4163,7 +4163,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9eac131e334e81b6b3be07399482042838adcd7957aa0010231d0813e39e02fa" dependencies = [ "hash-db", - "hashbrown", + "hashbrown 0.11.2", "log", "rustc-hex", "smallvec", @@ -4171,12 +4171,12 @@ dependencies = [ [[package]] name = "trie-db" -version = "0.23.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ddae50680c12ef75bfbf58416ca6622fa43d879553f6cb2ed1a817346e1ffe" +checksum = "d32d034c0d3db64b43c31de38e945f15b40cd4ca6d2dcfc26d4798ce8de4ab83" dependencies = [ "hash-db", - "hashbrown", + "hashbrown 0.12.0", "log", "rustc-hex", "smallvec", @@ -4213,21 +4213,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ee73e6e4924fe940354b8d4d98cad5231175d615cd855b758adc658c0aac6a0" dependencies = [ "cfg-if", - "rand 0.8.4", + "rand 0.8.5", "static_assertions", ] [[package]] name = "typenum" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "uint" -version = "0.9.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6470ab50f482bde894a037a57064480a246dbfdd5960bd65a44824693f08da5f" +checksum = "12f03af7ccf01dd611cc450a0d10dbc9b745770d096473e2faf0ca6e2d66d1e0" dependencies = [ "byteorder", "crunchy", @@ -4252,9 +4252,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" +checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" [[package]] name = "unicode-width" @@ -4287,6 +4287,12 @@ dependencies = [ "serde", ] +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "value-bag" version = "1.0.0-alpha.8" @@ -4305,9 +4311,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wabt" @@ -4382,9 +4388,9 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "wasm-bindgen" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" +checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -4392,9 +4398,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" +checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" dependencies = [ "bumpalo", "lazy_static", @@ -4407,9 +4413,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.28" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39" +checksum = "2eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395" dependencies = [ "cfg-if", "js-sys", @@ -4419,9 +4425,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" +checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4429,9 +4435,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" +checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" dependencies = [ "proc-macro2", "quote", @@ -4442,9 +4448,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" +checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" [[package]] name = "wasmi" @@ -4472,9 +4478,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.55" +version = "0.3.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" +checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb" dependencies = [ "js-sys", "wasm-bindgen", @@ -4492,9 +4498,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.22.1" +version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c475786c6f47219345717a043a37ec04cb4bc185e28853adcc4fa0a947eba630" +checksum = "552ceb903e957524388c4d3475725ff2c8b7960922063af6ce53c9a43da07449" dependencies = [ "webpki", ] @@ -4558,18 +4564,18 @@ checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" [[package]] name = "zeroize" -version = "1.4.3" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d68d9dcec5f9b43a30d38c49f91dfedfaac384cb8f085faca366c26207dd1619" +checksum = "7c88870063c39ee00ec285a2f8d6a966e5b6fb2becc4e8dac77ed0d370ed6006" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" -version = "1.2.2" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65f1a51723ec88c66d5d1fe80c841f17f63587d6691901d66be9bec6c3b51f73" +checksum = "81e8f13fef10b63c06356d65d416b070798ddabcadc10d3ece0c5be9b3c7eddb" dependencies = [ "proc-macro2", "quote", diff --git a/README.md b/README.md index 23ac2564..1894b691 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,8 @@ More relevant links: There's only an old version in your distributions package manager? Just use a [binary release](https://github.com/WebAssembly/binaryen/releases). +* Step 4: `cargo install cargo-dylint dylint-link`. + * Step 3: `cargo install --force cargo-contract`. You can always update the `cargo-contract` binary to the latest version by running the Step 3. diff --git a/build.rs b/build.rs index dc79aa3f..351a54ea 100644 --- a/build.rs +++ b/build.rs @@ -42,36 +42,147 @@ fn main() { .expect("OUT_DIR should be set by cargo") .into(); - let template_dir = manifest_dir.join("templates").join("new"); - let dst_file = out_dir.join("template.zip"); + generate_cargo_keys(); + rerun_if_git_head_changed(); + let template_dir = manifest_dir.join("templates").join("new"); + let template_dst_file = out_dir.join("template.zip"); println!( "Creating template zip: template_dir '{}', destination archive '{}'", template_dir.display(), - dst_file.display() + template_dst_file.display() ); - - generate_cargo_keys(); - rerun_if_git_head_changed(); - - std::process::exit( - match zip_dir(&template_dir, &dst_file, CompressionMethod::Stored) { + let zipped_template = + match zip_dir(&template_dir, &template_dst_file, CompressionMethod::Stored) { Ok(_) => { println!( "done: {} written to {}", template_dir.display(), - dst_file.display() + template_dst_file.display() ); - 0 + true } Err(e) => { eprintln!("Error: {:?}", e); - 1 + false } - }, + }; + + // This zip file will contain the `dylint` driver, this is one file named in the form of + // `libink_linting@nightly-2021-11-04-x86_64-unknown-linux-gnu.so`. This file is obtained + // by building the crate in `ink_linting/`. + let dylint_driver_dst_file = out_dir.join("ink-dylint-driver.zip"); + + #[cfg(feature = "cargo-clippy")] + { + // For `clippy` runs it is not necessary to build the `dylint` driver. + // Furthermore the fixed Rust nightly specified in `ink_linting/rust-toolchain` + // contains a bug that results in an `error[E0786]: found invalid metadata files` ICE. + // + // We still have to create an empty file though, due to the `include_bytes!` macro. + File::create(dylint_driver_dst_file).unwrap_or_else(|err| { + panic!( + "Failed creating an empty ink-dylint-driver.zip file: {:?}", + err + ); + }); + std::process::exit(bool_to_exit_code(zipped_template)); + } + + #[cfg(not(feature = "cargo-clippy"))] + { + let zipped_lints = build_dylint_driver(manifest_dir, out_dir, dylint_driver_dst_file) + .map(|_| true) + .unwrap_or_else(|err| { + panic!("Failed building dylint driver: {:?}", err); + }); + std::process::exit(bool_to_exit_code(zipped_template && zipped_lints)); + } +} + +/// Returns the process exit code which corresponds to a boolean. +fn bool_to_exit_code(val: bool) -> i32 { + match val { + true => 0, + false => 1, + } +} + +/// Builds the crate in `ink_linting/`. This crate contains the `dylint` driver with ink! specific +/// linting rules. +#[cfg(not(feature = "cargo-clippy"))] +fn build_dylint_driver( + manifest_dir: PathBuf, + out_dir: PathBuf, + dylint_driver_dst_file: PathBuf, +) -> Result<()> { + let ink_dylint_driver_dir = manifest_dir.join("ink_linting"); + + let mut cmd = Command::new("cargo"); + + let manifest_arg = format!( + "--manifest-path={}", + ink_dylint_driver_dir.join("Cargo.toml").display() ); + let target_dir = format!("--target-dir={}", out_dir.display()); + cmd.args(vec!["build", "--release", &target_dir, &manifest_arg]); + + // We need to remove those environment variables because `dylint` uses a + // fixed Rust toolchain via the `ink_linting/rust-toolchain` file. By removing + // these env variables we avoid issues with different Rust toolchains + // interfering with each other. + cmd.env_remove("RUSTUP_TOOLCHAIN"); + cmd.env_remove("CARGO_TARGET_DIR"); + + println!( + "Setting cargo working dir to '{}'", + ink_dylint_driver_dir.display() + ); + cmd.current_dir(ink_dylint_driver_dir.clone()); + + println!("Invoking cargo: {:?}", cmd); + + let child = cmd + // capture the stdout to return from this function as bytes + .stdout(std::process::Stdio::piped()) + .spawn() + .unwrap_or_else(|_| panic!("Error executing `{:?}`", cmd)); + let output = child.wait_with_output()?; + + if !output.status.success() { + anyhow::bail!( + "`{:?}` failed with exit code: {:?}", + cmd, + output.status.code() + ); + } + + println!( + "Creating ink-dylint-driver.zip: destination archive '{}'", + dylint_driver_dst_file.display() + ); + + match zip_dylint_driver( + &out_dir.join("release"), + &dylint_driver_dst_file, + CompressionMethod::Stored, + ) { + Ok(_) => { + println!( + "done: {} written to {}", + ink_dylint_driver_dir.display(), + dylint_driver_dst_file.display() + ); + Ok(()) + } + Err(e) => { + eprintln!("Error: {:?}", e); + Err(e) + } + } } +/// Creates a zip archive at `dst_file` with the content of the `src_dir`. fn zip_dir(src_dir: &Path, dst_file: &Path, method: CompressionMethod) -> Result<()> { if !src_dir.exists() { anyhow::bail!("src_dir '{}' does not exist", src_dir.display()); @@ -118,6 +229,50 @@ fn zip_dir(src_dir: &Path, dst_file: &Path, method: CompressionMethod) -> Result Ok(()) } +/// Creates a zip archive at `dst_file` with the `dylint` driver found in `src_dir`. +/// +/// `dylint` drivers have a file name of the form `libink_linting@toolchain.[so,dll]`. +#[cfg(not(feature = "cargo-clippy"))] +fn zip_dylint_driver(src_dir: &Path, dst_file: &Path, method: CompressionMethod) -> Result<()> { + if !src_dir.exists() { + anyhow::bail!("src_dir '{}' does not exist", src_dir.display()); + } + if !src_dir.is_dir() { + anyhow::bail!("src_dir '{}' is not a directory", src_dir.display()); + } + + let file = File::create(dst_file)?; + + let mut zip = ZipWriter::new(file); + let options = FileOptions::default() + .compression_method(method) + .unix_permissions(DEFAULT_UNIX_PERMISSIONS); + + let mut buffer = Vec::new(); + + let walkdir = WalkDir::new(src_dir); + let it = walkdir.into_iter().filter_map(|e| e.ok()); + + for entry in it { + let path = entry.path(); + let name = path.strip_prefix(&src_dir)?.to_path_buf(); + let file_path = name.as_os_str().to_string_lossy(); + + if path.is_file() && path.display().to_string().contains("libink_linting@") { + zip.start_file(file_path, options)?; + let mut f = File::open(path)?; + + f.read_to_end(&mut buffer)?; + zip.write_all(&*buffer)?; + buffer.clear(); + + zip.finish()?; + break; + } + } + Ok(()) +} + /// Generate the `cargo:` key output fn generate_cargo_keys() { let output = Command::new("git") diff --git a/ink_linting/.cargo/config.toml b/ink_linting/.cargo/config.toml new file mode 100644 index 00000000..e8488c83 --- /dev/null +++ b/ink_linting/.cargo/config.toml @@ -0,0 +1,11 @@ +# This file corresponds to the `.cargo/config.toml` file used for the `dylint` examples here: +# https://github.com/trailofbits/dylint/tree/master/examples. + +[target.x86_64-apple-darwin] +linker = "dylint-link" + +[target.x86_64-unknown-linux-gnu] +linker = "dylint-link" + +[target.x86_64-pc-windows-msvc] +linker = "dylint-link" diff --git a/ink_linting/.rustfmt.toml b/ink_linting/.rustfmt.toml new file mode 100644 index 00000000..8ebf443f --- /dev/null +++ b/ink_linting/.rustfmt.toml @@ -0,0 +1,3 @@ +license_template_path = "../FILE_HEADER" # changed +report_todo = "Always" +report_fixme = "Always" diff --git a/ink_linting/Cargo.toml b/ink_linting/Cargo.toml new file mode 100644 index 00000000..cd85dd40 --- /dev/null +++ b/ink_linting/Cargo.toml @@ -0,0 +1,91 @@ +[package] +name = "ink_linting" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2021" +publish = false + +license = "Apache-2.0" +readme = "README.md" +repository = "https://github.com/paritytech/cargo-contract" +documentation = "https://docs.rs/ink_linting" +homepage = "https://github.com/paritytech/cargo-contract" +description = "Linting tool for ink! smart contracts." +keywords = ["parity", "blockchain", "ink", "smart contracts", "substrate"] +include = ["Cargo.toml", "*.rs", "LICENSE"] + +[lib] +crate-type = ["cdylib"] + +[dependencies] +clippy_utils = { git = "https://github.com/rust-lang/rust-clippy", tag = "rust-1.58.0" } +dylint_linting = "1.0.13" +if_chain = "1.0.2" +log = "0.4.14" +regex = "1.5.4" + +[dev-dependencies] +dylint_testing = "1.0.13" + +# The following are ink! dependencies, they are only required for the `ui` tests. +ink_primitives = { git = "https://github.com/paritytech/ink", default-features = false } +ink_metadata = { git = "https://github.com/paritytech/ink", default-features = false, features = ["derive"] } +ink_env = { git = "https://github.com/paritytech/ink", default-features = false } +ink_storage = { git = "https://github.com/paritytech/ink", default-features = false } +ink_lang = { git = "https://github.com/paritytech/ink", default-features = false } +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } +scale-info = { version = "2", default-features = false, features = ["derive"] } + +# For the moment we have to include the tests as examples and +# then use `dylint_testing::ui_test_examples`. +# +# The reason is that the `dylint_testing` API currently does not +# provide any other option to run the tests on those files +# *while giving us the option to specify the dependencies*. +# +# Those files require the ink! dependencies though, by having +# them as examples here, they inherit the `dev-dependencies`. +[[example]] +name = "fail_mapping_one_constructor" +path = "ui/fail/mapping-one-constructor.rs" + +[[example]] +name = "fail_mapping_two_constructors_01" +path = "ui/fail/mapping-two-constructors-01.rs" + +[[example]] +name = "fail_mapping_two_constructors_02" +path = "ui/fail/mapping-two-constructors-02.rs" + +[[example]] +name = "fail_mapping_nested_initialize_call" +path = "ui/fail/mapping-nested-initialize-call.rs" + +[[example]] +name = "pass_mapping_one_constructor" +path = "ui/pass/mapping-one-constructor.rs" + +[[example]] +name = "pass_mapping_two_constructors" +path = "ui/pass/mapping-two-constructors.rs" + +[[example]] +name = "pass_mapping_03" +path = "ui/pass/mapping-additional-logic-constructor.rs" + +[package.metadata.rust-analyzer] +rustc_private = true + +[workspace] + +[features] +default = ["std"] +std = [ + "ink_metadata/std", + "ink_env/std", + "ink_storage/std", + "ink_primitives/std", + "scale/std", + "scale-info/std", +] +ink-as-dependency = [] diff --git a/ink_linting/LICENSE b/ink_linting/LICENSE new file mode 100644 index 00000000..6b0b1270 --- /dev/null +++ b/ink_linting/LICENSE @@ -0,0 +1,203 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You 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 the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You 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 the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/ink_linting/README.md b/ink_linting/README.md new file mode 100644 index 00000000..80279a66 --- /dev/null +++ b/ink_linting/README.md @@ -0,0 +1,17 @@ +# ink! linting rules + +This crate uses [`dylint`](https://github.com/trailofbits/dylint) to define custom +linting rules for [ink!](https://github.com/paritytech/ink); + +You can use it this way: + +```bash +# Install all prerequisites. +cargo install cargo-dylint dylint-link + +cargo build --release + +# Run the linting on a contract. +DYLINT_LIBRARY_PATH=$PWD/target/release cargo dylint contract_instantiated + --manifest-path ../ink/examples/erc20/Cargo.toml +``` \ No newline at end of file diff --git a/ink_linting/rust-toolchain b/ink_linting/rust-toolchain new file mode 100644 index 00000000..480368fe --- /dev/null +++ b/ink_linting/rust-toolchain @@ -0,0 +1,6 @@ +# This file corresponds to the `rust-toolchain` file used for the `dylint` examples here: +# https://github.com/trailofbits/dylint/tree/master/examples. + +[toolchain] +channel = "nightly-2021-11-04" +components = ["llvm-tools-preview", "rustc-dev"] diff --git a/ink_linting/src/lib.rs b/ink_linting/src/lib.rs new file mode 100644 index 00000000..7253469e --- /dev/null +++ b/ink_linting/src/lib.rs @@ -0,0 +1,40 @@ +// Copyright 2018-2022 Parity Technologies (UK) Ltd. +// This file is part of cargo-contract. +// +// cargo-contract is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// cargo-contract is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with cargo-contract. If not, see . + +#![feature(rustc_private)] + +dylint_linting::dylint_library!(); + +extern crate rustc_errors; +extern crate rustc_hir; +extern crate rustc_lint; +extern crate rustc_middle; +extern crate rustc_session; +extern crate rustc_span; + +mod mapping_initialized; + +#[doc(hidden)] +#[no_mangle] +pub fn register_lints(_sess: &rustc_session::Session, lint_store: &mut rustc_lint::LintStore) { + lint_store.register_lints(&[mapping_initialized::MAPPING_INITIALIZED]); + lint_store.register_late_pass(|| Box::new(mapping_initialized::MappingInitialized)); +} + +#[test] +fn ui() { + dylint_testing::ui_test_examples(env!("CARGO_PKG_NAME")); +} diff --git a/ink_linting/src/mapping_initialized.rs b/ink_linting/src/mapping_initialized.rs new file mode 100644 index 00000000..a684ccc5 --- /dev/null +++ b/ink_linting/src/mapping_initialized.rs @@ -0,0 +1,345 @@ +// Copyright 2018-2022 Parity Technologies (UK) Ltd. +// This file is part of cargo-contract. +// +// cargo-contract is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// cargo-contract is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with cargo-contract. If not, see . + +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::source::snippet_opt; +use if_chain::if_chain; +use regex::Regex; +use rustc_errors::Applicability; +use rustc_hir::{ + def_id::DefId, + intravisit::{walk_fn, walk_item, walk_qpath, FnKind, NestedVisitorMap, Visitor}, + BodyId, FnDecl, HirId, Item, ItemKind, +}; +use rustc_hir::{QPath, VariantData}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::{hir::map::Map, ty::Attributes}; +use rustc_session::{declare_lint, declare_lint_pass}; +use rustc_span::source_map::Span; + +declare_lint! { + /// **What it does:** Checks for ink! contracts that use + /// [`ink_storage::Mapping`](https://paritytech.github.io/ink/ink_storage/struct.Mapping.html) + /// in their storage without initializing it properly in the ink! constructor. + /// + /// **Why is this bad?** If `Mapping` is not properly initialized corruption of storage + /// might occur. + /// + /// **Known problems:** The lint currently requires for the + /// `ink_lang::utils::initialize_contract(…)` function call to be made on the top + /// level of the constructor *and* it has be made explicitly in this form. + /// + /// The lint can currently not detect if `initialize_contract` would be called in a + /// nested function within the constructor. + /// + /// **Example:** + /// + /// ```rust + /// // Good + /// use ink_storage::{traits::SpreadAllocate, Mapping}; + /// + /// #[ink(storage)] + /// #[derive(SpreadAllocate)] + /// pub struct MyContract { + /// balances: Mapping, + /// } + /// + /// #[ink(constructor)] + /// pub fn new() -> Self { + /// ink_lang::utils::initialize_contract(Self::new_init) + /// } + /// + /// /// Default initializes the contract. + /// fn new_init(&mut self) { + /// let caller = Self::env().caller(); + /// let value: Balance = Default::default(); + /// self.balances.insert(&caller, &value); + /// } + /// ``` + /// + /// ```rust + /// // Bad + /// use ink_storage::{traits::SpreadAllocate, Mapping}; + /// + /// #[ink(storage)] + /// #[derive(SpreadAllocate)] + /// pub struct MyContract { + /// balances: Mapping, + /// } + /// + /// #[ink(constructor)] + /// pub fn new() -> Self { + /// Self { + /// balances: Default::default(), + /// } + /// } + /// ``` + pub MAPPING_INITIALIZED, + Deny, + "Error on ink! contracts that use `ink_storage::Mapping` without initializing it." +} + +declare_lint_pass!(MappingInitialized => [MAPPING_INITIALIZED]); + +/// An ink! attribute. +#[derive(PartialEq)] +enum InkAttribute { + // #[ink(storage)] + Storage, + // #[ink(constructor)] + Constructor, +} + +/// Returns `Some(InkAttribute)` if an ink! attribute is among `attributes`. +fn get_ink_attribute(attributes: Attributes) -> Option { + const INK_STORAGE: &str = "__ink_dylint_Storage"; + const INK_CONSTRUCTOR: &str = "__ink_dylint_Constructor"; + + let attrs = format!("symbol: \"{:?}\"", attributes); + if attrs.contains(INK_STORAGE) { + Some(InkAttribute::Storage) + } else if attrs.contains(INK_CONSTRUCTOR) { + Some(InkAttribute::Constructor) + } else { + None + } +} + +impl<'tcx> LateLintPass<'tcx> for MappingInitialized { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { + let attrs = cx.tcx.hir().attrs(item.hir_id()); + let ink_attrs = get_ink_attribute(attrs); + if ink_attrs.is_none() { + return; + } + + if let ItemKind::Struct(variant_data, _) = &item.kind { + if let VariantData::Unit(..) = variant_data { + return; + } + check_struct(cx, item, variant_data); + } + } +} + +/// Examines a `struct`. If the struct is annotated as an ink! storage struct +/// we examine if there is a `ink_storage::Mapping` in it; in case there +/// is we continue checking all ink! constructors for correct usage of the +/// `ink_lang::utils::initialize_contract` API. +/// +/// This function is backwards compatible, in case no annotated ink! struct is +/// found nothing happens. +fn check_struct<'a>(cx: &LateContext<'a>, item: &'a Item, data: &VariantData) { + let attrs = cx.tcx.hir().attrs(item.hir_id()); + match get_ink_attribute(attrs) { + Some(InkAttribute::Storage) => {} + _ => return, + } + + let mut marker = None; + let fields = data.fields(); + let storage_contains_mapping = fields.iter().any(|field| { + let re = Regex::new(r"ink_storage\[.*\]::lazy::mapping::Mapping") + .expect("failed creating regex"); + if re.is_match(&format!("{:?}", field.ty.kind)) { + marker = Some(field); + return true; + } + false + }); + + if !storage_contains_mapping { + log::debug!("Found `#[ink(storage)]` struct without `Mapping`"); + return; + } + log::debug!("Found `#[ink(storage)]` struct with `Mapping`"); + + let inherent_impls = cx.tcx.inherent_impls(item.def_id); + let constructors_without_initialize: Vec = inherent_impls + .iter() + .map(|imp_did| item_from_def_id(cx, *imp_did)) + .filter_map(|item| constructor_but_no_initialize(cx, item)) + .collect(); + log::debug!( + "Result of searching for constructors without initialize: {:?}", + constructors_without_initialize + ); + + if_chain! { + if storage_contains_mapping; + if !constructors_without_initialize.is_empty(); + then { + let constructor_span = constructors_without_initialize.get(0) + .expect("at least one faulty constructor must exist"); + let snippet = snippet_opt(cx, *constructor_span) + .expect("snippet must exist"); + span_lint_and_then( + cx, + MAPPING_INITIALIZED, + item.span, + &format!( + "you have declared an `#[ink(storage)]` on `{}` without initializing it in the contract constructor.", + item.ident + ), + |diag| { + diag.span_suggestion( + *constructor_span, + "add an `ink_lang::utils::initialize_contract(…)` function in this constructor", + snippet, + Applicability::Unspecified, + ); + diag.span_help(marker.expect("marker must exist").span, "this field uses a `Mapping`"); + }); + } + } +} + +/// Returns `Some(span)` if a constructor without a call of +/// `ink_lang::utils::initialize_contract(…)` was found. +fn constructor_but_no_initialize<'tcx>( + cx: &LateContext<'tcx>, + item: &'tcx Item<'_>, +) -> Option { + let mut visitor = InkAttributeVisitor { + cx, + ink_attribute: None, + constructor_info: None, + }; + + walk_item(&mut visitor, item); + + match visitor.constructor_info { + Some(info) if !info.uses_initialize_contract => Some(info.span), + _ => None, + } +} + +/// Visitor for ink! attributes. +struct InkAttributeVisitor<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + ink_attribute: Option, + constructor_info: Option, +} + +// Information about an ink! constructor. +struct InkConstructor { + // The constructor has a call to `ink_lang::utils::initialize_contract(…)` + // in its function. + uses_initialize_contract: bool, + // The span for the constructor function. + span: Span, +} + +impl<'tcx> Visitor<'tcx> for InkAttributeVisitor<'_, 'tcx> { + type Map = Map<'tcx>; + + fn visit_fn( + &mut self, + kind: FnKind<'tcx>, + decl: &'tcx FnDecl<'_>, + body_id: BodyId, + span: Span, + id: HirId, + ) { + // We can return immediately if an incorrect constructor was already found + if let Some(constructor) = &self.constructor_info { + if !constructor.uses_initialize_contract { + return; + } + } + + let attrs = self.cx.tcx.get_attrs(id.owner.to_def_id()); + self.ink_attribute = get_ink_attribute(attrs); + + if self.ink_attribute == Some(InkAttribute::Storage) { + return; + } else if self.ink_attribute == Some(InkAttribute::Constructor) { + log::debug!("Found constructor, starting to search for `initialize_contract`"); + let mut visitor = InitializeContractVisitor { + cx: self.cx, + uses_initialize_contract: false, + }; + walk_fn(&mut visitor, kind, decl, body_id, span, id); + + log::debug!( + "Has `initialize_contract`? {:?}", + visitor.uses_initialize_contract + ); + self.constructor_info = Some(InkConstructor { + uses_initialize_contract: visitor.uses_initialize_contract, + span, + }); + + return; + } + + walk_fn(self, kind, decl, body_id, span, id); + } + + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::All(self.cx.tcx.hir()) + } +} + +/// Visitor to determine if a `fn` contains a call to `ink_lang::utils::initialize_contract(…)`. +/// +/// # Known Limitation +/// +/// This function currently only finds call to `initialize_contract` which happen +/// on the first level of the `fn` ‒ no nested calls are found! So if you would +/// call `initialize_contract` within a sub-function of the ink! constructor +/// this is not recognized! +/// +/// Also the function call must be explicitly called `ink_lang::utils::initialize_contract(…)`, +/// the linter currently does not detected indirections. +struct InitializeContractVisitor<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + uses_initialize_contract: bool, +} + +impl<'tcx> Visitor<'tcx> for InitializeContractVisitor<'_, 'tcx> { + type Map = Map<'tcx>; + + fn visit_qpath(&mut self, qpath: &'tcx QPath<'_>, id: HirId, span: Span) { + log::debug!("Visiting path {:?}", qpath); + if self.uses_initialize_contract { + return; + } + + if let QPath::Resolved(_, path) = qpath { + log::debug!("QPath: {:?}", path.res); + let re = + Regex::new(r"ink_lang\[.*\]::codegen::dispatch::execution::initialize_contract") + .expect("failed creating regex"); + if re.is_match(&format!("{:?}", path.res)) { + self.uses_initialize_contract = true; + return; + } + } + + walk_qpath(self, qpath, id, span); + } + + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::All(self.cx.tcx.hir()) + } +} + +/// Returns the `rustc_hir::Item` for a `rustc_hir::def_id::DefId`. +fn item_from_def_id<'tcx>(cx: &LateContext<'tcx>, def_id: DefId) -> &'tcx Item<'tcx> { + let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + cx.tcx.hir().expect_item(hir_id) +} diff --git a/ink_linting/ui/fail/mapping-nested-initialize-call.rs b/ink_linting/ui/fail/mapping-nested-initialize-call.rs new file mode 100644 index 00000000..a8064b72 --- /dev/null +++ b/ink_linting/ui/fail/mapping-nested-initialize-call.rs @@ -0,0 +1,58 @@ +// Copyright 2018-2022 Parity Technologies (UK) Ltd. +// This file is part of cargo-contract. +// +// cargo-contract is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// cargo-contract is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with cargo-contract. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +use ink_lang as ink; + +#[ink::contract] +mod my_contract { + use ink_storage::{traits::SpreadAllocate, Mapping}; + + #[ink(storage)] + #[derive(SpreadAllocate)] + pub struct MyContract { + balances: Mapping, + } + + impl MyContract { + /// The linter currently does not detect if `initialize_contract` is + /// called in a nested function. + #[ink(constructor)] + pub fn new1() -> Self { + Self::foo() + } + + fn foo() -> Self { + ink_lang::utils::initialize_contract(Self::new_init) + } + + /// Default initializes the contract. + fn new_init(&mut self) { + let caller = Self::env().caller(); + let value: Balance = Default::default(); + self.balances.insert(&caller, &value); + } + + /// Returns something. + #[ink(message)] + pub fn get(&self) { + // ... + } + } +} + +fn main() {} diff --git a/ink_linting/ui/fail/mapping-nested-initialize-call.stderr b/ink_linting/ui/fail/mapping-nested-initialize-call.stderr new file mode 100644 index 00000000..cd11d830 --- /dev/null +++ b/ink_linting/ui/fail/mapping-nested-initialize-call.stderr @@ -0,0 +1,27 @@ +error: you have declared an `#[ink(storage)]` on `MyContract` without initializing it in the contract constructor. + --> $DIR/mapping-nested-initialize-call.rs:26:5 + | +LL | / #[derive(SpreadAllocate)] +LL | | pub struct MyContract { +LL | | balances: Mapping, +LL | | } + | |_____^ + | + = note: `#[deny(mapping_initialized)]` on by default +help: this field uses a `Mapping` + --> $DIR/mapping-nested-initialize-call.rs:28:9 + | +LL | balances: Mapping, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: add an `ink_lang::utils::initialize_contract(…)` function in this constructor + | +LL ~ /// The linter currently does not detect if `initialize_contract` is +LL + /// called in a nested function. +LL + #[ink(constructor)] +LL + pub fn new1() -> Self { +LL + Self::foo() +LL + } + | + +error: aborting due to previous error + diff --git a/ink_linting/ui/fail/mapping-one-constructor.rs b/ink_linting/ui/fail/mapping-one-constructor.rs new file mode 100644 index 00000000..18fbe1b7 --- /dev/null +++ b/ink_linting/ui/fail/mapping-one-constructor.rs @@ -0,0 +1,47 @@ +// Copyright 2018-2022 Parity Technologies (UK) Ltd. +// This file is part of cargo-contract. +// +// cargo-contract is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// cargo-contract is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with cargo-contract. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +use ink_lang as ink; + +#[ink::contract] +mod my_contract { + use ink_storage::{traits::SpreadAllocate, Mapping}; + + #[ink(storage)] + #[derive(SpreadAllocate)] + pub struct MyContract { + balances: Mapping, + } + + impl MyContract { + #[ink(constructor)] + pub fn new() -> Self { + Self { + balances: Default::default(), + } + } + + /// Returns the total token supply. + #[ink(message)] + pub fn get(&self) { + // ... + } + } +} + +fn main() {} diff --git a/ink_linting/ui/fail/mapping-one-constructor.stderr b/ink_linting/ui/fail/mapping-one-constructor.stderr new file mode 100644 index 00000000..8e0a4d8a --- /dev/null +++ b/ink_linting/ui/fail/mapping-one-constructor.stderr @@ -0,0 +1,26 @@ +error: you have declared an `#[ink(storage)]` on `MyContract` without initializing it in the contract constructor. + --> $DIR/mapping-one-constructor.rs:26:5 + | +LL | / #[derive(SpreadAllocate)] +LL | | pub struct MyContract { +LL | | balances: Mapping, +LL | | } + | |_____^ + | + = note: `#[deny(mapping_initialized)]` on by default +help: this field uses a `Mapping` + --> $DIR/mapping-one-constructor.rs:28:9 + | +LL | balances: Mapping, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: add an `ink_lang::utils::initialize_contract(…)` function in this constructor + | +LL ~ pub fn new() -> Self { +LL + Self { +LL + balances: Default::default(), +LL + } +LL + } + | + +error: aborting due to previous error + diff --git a/ink_linting/ui/fail/mapping-two-constructors-01.rs b/ink_linting/ui/fail/mapping-two-constructors-01.rs new file mode 100644 index 00000000..645ce9a5 --- /dev/null +++ b/ink_linting/ui/fail/mapping-two-constructors-01.rs @@ -0,0 +1,62 @@ +// Copyright 2018-2022 Parity Technologies (UK) Ltd. +// This file is part of cargo-contract. +// +// cargo-contract is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// cargo-contract is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with cargo-contract. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +use ink_lang as ink; + +#[ink::contract] +mod my_contract { + use ink_storage::{traits::SpreadAllocate, Mapping}; + + #[ink(storage)] + #[derive(SpreadAllocate)] + pub struct MyContract { + balances: Mapping, + } + + impl MyContract { + /// This constructor is correct. + /// It comes before the incorrect constructor. + #[ink(constructor)] + pub fn new1() -> Self { + ink_lang::utils::initialize_contract(Self::new_init) + } + + /// Default initializes the contract. + fn new_init(&mut self) { + let caller = Self::env().caller(); + let value: Balance = Default::default(); + self.balances.insert(&caller, &value); + } + + /// This constructor is **not** correct. + #[ink(constructor)] + pub fn new2() -> Self { + Self { + balances: Default::default(), + } + } + + /// Returns something. + #[ink(message)] + pub fn get(&self) { + // ... + } + } +} + +fn main() {} diff --git a/ink_linting/ui/fail/mapping-two-constructors-01.stderr b/ink_linting/ui/fail/mapping-two-constructors-01.stderr new file mode 100644 index 00000000..d174f423 --- /dev/null +++ b/ink_linting/ui/fail/mapping-two-constructors-01.stderr @@ -0,0 +1,27 @@ +error: you have declared an `#[ink(storage)]` on `MyContract` without initializing it in the contract constructor. + --> $DIR/mapping-two-constructors-01.rs:26:5 + | +LL | / #[derive(SpreadAllocate)] +LL | | pub struct MyContract { +LL | | balances: Mapping, +LL | | } + | |_____^ + | + = note: `#[deny(mapping_initialized)]` on by default +help: this field uses a `Mapping` + --> $DIR/mapping-two-constructors-01.rs:28:9 + | +LL | balances: Mapping, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: add an `ink_lang::utils::initialize_contract(…)` function in this constructor + | +LL ~ /// This constructor is **not** correct. +LL + #[ink(constructor)] +LL + pub fn new2() -> Self { +LL + Self { +LL + balances: Default::default(), +LL + } + ... + +error: aborting due to previous error + diff --git a/ink_linting/ui/fail/mapping-two-constructors-02.rs b/ink_linting/ui/fail/mapping-two-constructors-02.rs new file mode 100644 index 00000000..253ac1a5 --- /dev/null +++ b/ink_linting/ui/fail/mapping-two-constructors-02.rs @@ -0,0 +1,62 @@ +// Copyright 2018-2022 Parity Technologies (UK) Ltd. +// This file is part of cargo-contract. +// +// cargo-contract is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// cargo-contract is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with cargo-contract. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +use ink_lang as ink; + +#[ink::contract] +mod my_contract { + use ink_storage::{traits::SpreadAllocate, Mapping}; + + #[ink(storage)] + #[derive(SpreadAllocate)] + pub struct MyContract { + balances: Mapping, + } + + impl MyContract { + /// This constructor is **not** correct. + /// It comes before the correct constructor. + #[ink(constructor)] + pub fn new2() -> Self { + Self { + balances: Default::default(), + } + } + + /// This constructor is correct. + #[ink(constructor)] + pub fn new1() -> Self { + ink_lang::utils::initialize_contract(Self::new_init) + } + + /// Default initializes the contract. + fn new_init(&mut self) { + let caller = Self::env().caller(); + let value: Balance = Default::default(); + self.balances.insert(&caller, &value); + } + + /// Returns something. + #[ink(message)] + pub fn get(&self) { + // ... + } + } +} + +fn main() {} diff --git a/ink_linting/ui/fail/mapping-two-constructors-02.stderr b/ink_linting/ui/fail/mapping-two-constructors-02.stderr new file mode 100644 index 00000000..ff42f1f5 --- /dev/null +++ b/ink_linting/ui/fail/mapping-two-constructors-02.stderr @@ -0,0 +1,27 @@ +error: you have declared an `#[ink(storage)]` on `MyContract` without initializing it in the contract constructor. + --> $DIR/mapping-two-constructors-02.rs:26:5 + | +LL | / #[derive(SpreadAllocate)] +LL | | pub struct MyContract { +LL | | balances: Mapping, +LL | | } + | |_____^ + | + = note: `#[deny(mapping_initialized)]` on by default +help: this field uses a `Mapping` + --> $DIR/mapping-two-constructors-02.rs:28:9 + | +LL | balances: Mapping, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: add an `ink_lang::utils::initialize_contract(…)` function in this constructor + | +LL ~ /// This constructor is **not** correct. +LL + /// It comes before the correct constructor. +LL + #[ink(constructor)] +LL + pub fn new2() -> Self { +LL + Self { +LL + balances: Default::default(), + ... + +error: aborting due to previous error + diff --git a/ink_linting/ui/pass/mapping-additional-logic-constructor.rs b/ink_linting/ui/pass/mapping-additional-logic-constructor.rs new file mode 100644 index 00000000..964d8a91 --- /dev/null +++ b/ink_linting/ui/pass/mapping-additional-logic-constructor.rs @@ -0,0 +1,61 @@ +// Copyright 2018-2022 Parity Technologies (UK) Ltd. +// This file is part of cargo-contract. +// +// cargo-contract is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// cargo-contract is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with cargo-contract. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +use ink_lang as ink; + +#[ink::contract] +mod my_contract { + /// The `Mapping` must be recognized, even if it is imported + /// under a different name. + use ink_storage::{traits::SpreadAllocate, Mapping as SomeOtherName}; + + #[ink(storage)] + #[derive(SpreadAllocate)] + pub struct MyContract { + balances: SomeOtherName, + } + + impl MyContract { + #[ink(constructor)] + pub fn new() -> Self { + let a = 1; + let b = 2; + assert_eq!(add(a, b), 3); + ink_lang::utils::initialize_contract(Self::new_init) + } + + /// Default initializes the contract. + fn new_init(&mut self) { + let caller = Self::env().caller(); + let value: Balance = Default::default(); + self.balances.insert(&caller, &value); + } + + /// Returns something. + #[ink(message)] + pub fn get(&self) { + // ... + } + } + + fn add(a: u32, b: u32) -> u32 { + a + b + } +} + +fn main() {} diff --git a/ink_linting/ui/pass/mapping-one-constructor.rs b/ink_linting/ui/pass/mapping-one-constructor.rs new file mode 100644 index 00000000..48544660 --- /dev/null +++ b/ink_linting/ui/pass/mapping-one-constructor.rs @@ -0,0 +1,52 @@ +// Copyright 2018-2022 Parity Technologies (UK) Ltd. +// This file is part of cargo-contract. +// +// cargo-contract is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// cargo-contract is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with cargo-contract. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +use ink_lang as ink; + +#[ink::contract] +mod my_contract { + use ink_storage::{traits::SpreadAllocate, Mapping}; + + #[ink(storage)] + #[derive(SpreadAllocate)] + pub struct MyContract { + balances: Mapping, + } + + impl MyContract { + #[ink(constructor)] + pub fn new() -> Self { + ink_lang::utils::initialize_contract(Self::new_init) + } + + /// Default initializes the contract. + fn new_init(&mut self) { + let caller = Self::env().caller(); + let value: Balance = Default::default(); + self.balances.insert(&caller, &value); + } + + /// Returns something. + #[ink(message)] + pub fn get(&self) { + // ... + } + } +} + +fn main() {} diff --git a/ink_linting/ui/pass/mapping-two-constructors.rs b/ink_linting/ui/pass/mapping-two-constructors.rs new file mode 100644 index 00000000..558d7e0a --- /dev/null +++ b/ink_linting/ui/pass/mapping-two-constructors.rs @@ -0,0 +1,60 @@ +// Copyright 2018-2022 Parity Technologies (UK) Ltd. +// This file is part of cargo-contract. +// +// cargo-contract is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// cargo-contract is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with cargo-contract. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +use ink_lang as ink; + +#[ink::contract] +mod my_contract { + use ink_storage::{traits::SpreadAllocate, Mapping}; + + #[ink(storage)] + #[derive(SpreadAllocate)] + pub struct MyContract { + balances: Mapping, + } + + impl MyContract { + /// The `initialize_contract` must be found, even if there is logic before it. + #[ink(constructor)] + pub fn new() -> Self { + let a = 1; + let b = 2; + assert_eq!(add(a, b), 3); + ink_lang::utils::initialize_contract(Self::new_init) + } + + /// Default initializes the contract. + fn new_init(&mut self) { + let caller = Self::env().caller(); + let value: Balance = Default::default(); + self.balances.insert(&caller, &value); + } + + /// Returns something. + #[ink(message)] + pub fn get(&self) { + // ... + } + } + + fn add(a: u32, b: u32) -> u32 { + a + b + } +} + +fn main() {} diff --git a/metadata/Cargo.toml b/metadata/Cargo.toml index d2507a42..0846e17f 100644 --- a/metadata/Cargo.toml +++ b/metadata/Cargo.toml @@ -2,8 +2,8 @@ name = "contract-metadata" version = "0.5.1" authors = ["Parity Technologies "] -edition = "2021" rust-version = "1.56.1" +edition = "2021" license = "Apache-2.0" readme = "README.md" diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 80882265..5fd307db 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -247,13 +247,6 @@ fn exec_cargo_for_wasm_target( ) -> Result<()> { util::assert_channel()?; - // set linker args via RUSTFLAGS. - // Currently will override user defined RUSTFLAGS from .cargo/config. See https://github.com/paritytech/cargo-contract/issues/98. - std::env::set_var( - "RUSTFLAGS", - "-C link-arg=-zstack-size=65536 -C link-arg=--import-memory -Clinker-plugin-lto", - ); - let cargo_build = |manifest_path: &ManifestPath| { let target_dir = &crate_metadata.target_directory; let target_dir = format!("--target-dir={}", target_dir.to_string_lossy()); @@ -272,7 +265,11 @@ fn exec_cargo_for_wasm_target( } else { args.push("-Zbuild-std-features=panic_immediate_abort"); } - util::invoke_cargo(command, &args, manifest_path.directory(), verbosity)?; + let env = Some(vec![( + "RUSTFLAGS", + "-C link-arg=-zstack-size=65536 -C link-arg=--import-memory -Clinker-plugin-lto", + )]); + util::invoke_cargo(command, &args, manifest_path.directory(), verbosity, env)?; Ok(()) }; @@ -298,8 +295,36 @@ fn exec_cargo_for_wasm_target( .using_temp(cargo_build)?; } - // clear RUSTFLAGS - std::env::remove_var("RUSTFLAGS"); + Ok(()) +} + +/// Executes `cargo dylint` with the ink! linting driver that is built during +/// the `build.rs`. +/// +/// We create a temporary folder, extract the linting driver there and run +/// `cargo dylint` with it. +fn exec_cargo_dylint(crate_metadata: &CrateMetadata, verbosity: Verbosity) -> Result<()> { + let tmp_dir = tempfile::Builder::new() + .prefix("cargo-contract-dylint_") + .tempdir()?; + log::debug!("Using temp workspace at '{}'", tmp_dir.path().display()); + + let template = include_bytes!(concat!(env!("OUT_DIR"), "/ink-dylint-driver.zip")); + crate::util::unzip(template, tmp_dir.path().to_path_buf(), None)?; + + let manifest_path = crate_metadata.manifest_path.cargo_arg(); + let args = vec!["ink_linting", &manifest_path]; + let tmp_dir_path = tmp_dir.path().as_os_str().to_string_lossy(); + let env = vec![ + ("DYLINT_LIBRARY_PATH", tmp_dir_path.as_ref()), + ("DYLINT_DRIVER_PATH", tmp_dir_path.as_ref()), + ]; + let working_dir = crate_metadata + .manifest_path + .directory() + .unwrap_or_else(|| Path::new(".")) + .canonicalize()?; + util::invoke_cargo("dylint", &args, Some(working_dir), verbosity, Some(env))?; Ok(()) } @@ -615,16 +640,15 @@ fn assert_compatible_ink_dependencies( ) -> Result<()> { for dependency in ["parity-scale-codec", "scale-info"].iter() { let args = ["-i", dependency, "--duplicates"]; - let _ = util::invoke_cargo("tree", &args, manifest_path.directory(), verbosity).map_err( - |_| { + let _ = util::invoke_cargo("tree", &args, manifest_path.directory(), verbosity, None) + .map_err(|_| { anyhow::anyhow!( "Mismatching versions of `{}` were found!\n\ Please ensure that your contract and your ink! dependencies use a compatible \ version of this package.", dependency ) - }, - )?; + })?; } Ok(()) } @@ -671,6 +695,14 @@ pub(crate) fn execute(args: ExecuteArgs) -> Result { verbosity, " {} {}", format!("[1/{}]", build_artifact.steps()).bold(), + "Checking ink! linting rules".bright_green().bold() + ); + exec_cargo_dylint(&crate_metadata, verbosity)?; + + maybe_println!( + verbosity, + " {} {}", + format!("[2/{}]", build_artifact.steps()).bold(), "Building cargo project".bright_green().bold() ); exec_cargo_for_wasm_target( @@ -685,7 +717,7 @@ pub(crate) fn execute(args: ExecuteArgs) -> Result { maybe_println!( verbosity, " {} {}", - format!("[2/{}]", build_artifact.steps()).bold(), + format!("[3/{}]", build_artifact.steps()).bold(), "Post processing wasm file".bright_green().bold() ); post_process_wasm(&crate_metadata)?; @@ -693,7 +725,7 @@ pub(crate) fn execute(args: ExecuteArgs) -> Result { maybe_println!( verbosity, " {} {}", - format!("[3/{}]", build_artifact.steps()).bold(), + format!("[4/{}]", build_artifact.steps()).bold(), "Optimizing wasm file".bright_green().bold() ); let optimization_result = @@ -704,6 +736,20 @@ pub(crate) fn execute(args: ExecuteArgs) -> Result { let (opt_result, metadata_result) = match build_artifact { BuildArtifacts::CheckOnly => { + maybe_println!( + verbosity, + " {} {}", + format!("[1/{}]", build_artifact.steps()).bold(), + "Checking ink! linting rules".bright_green().bold() + ); + exec_cargo_dylint(&crate_metadata, verbosity)?; + + maybe_println!( + verbosity, + " {} {}", + format!("[2/{}]", build_artifact.steps()).bold(), + "Executing `cargo check`".bright_green().bold() + ); exec_cargo_for_wasm_target( &crate_metadata, "check", @@ -1273,4 +1319,69 @@ mod tests_ci_only { Ok(()) }) } + + // This test has to be ignored until the next ink! rc. + // Before that we don't have the `__ink_dylint_…` markers available + // to actually run `dylint`. + #[test] + #[ignore] + fn dylint_must_find_issue() { + with_new_contract_project(|manifest_path| { + // given + let contract = r#" + #![cfg_attr(not(feature = "std"), no_std)] + + use ink_lang as ink; + + #[ink::contract] + mod fail_mapping_01 { + use ink_storage::{traits::SpreadAllocate, Mapping}; + + #[ink(storage)] + #[derive(SpreadAllocate)] + pub struct MyContract { + balances: Mapping, + } + + impl MyContract { + #[ink(constructor)] + pub fn new() -> Self { + Self { + balances: Default::default(), + } + } + + /// Returns the total token supply. + #[ink(message)] + pub fn get(&self) { + // ... + } + } + }"#; + let project_dir = manifest_path.directory().expect("directory must exist"); + let lib = project_dir.join("lib.rs"); + std::fs::write(&lib, contract)?; + + let args = crate::cmd::build::ExecuteArgs { + manifest_path, + build_artifact: BuildArtifacts::CheckOnly, + ..Default::default() + }; + + // when + let res = super::execute(args); + + // then + match res { + Err(err) => { + eprintln!("err: {:?}", err); + assert!(err.to_string().contains( + "help: add an `initialize_contract` function in this constructor" + )); + } + _ => panic!("build succeeded, but must fail!"), + }; + Ok(()) + }) + } } diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 539077af..421beba7 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -100,6 +100,7 @@ pub(crate) fn execute( ], crate_metadata.manifest_path.directory(), verbosity, + None, )?; let ink_meta: serde_json::Map = serde_json::from_slice(&stdout)?; diff --git a/src/cmd/new.rs b/src/cmd/new.rs index 75482bb0..624223e9 100644 --- a/src/cmd/new.rs +++ b/src/cmd/new.rs @@ -14,14 +14,9 @@ // You should have received a copy of the GNU General Public License // along with cargo-contract. If not, see . -use std::{ - env, fs, - io::{Cursor, Read, Seek, SeekFrom, Write}, - path::Path, -}; +use std::{env, fs, path::Path}; use anyhow::Result; -use heck::ToUpperCamelCase as _; pub(crate) fn execute

(name: &str, dir: Option

) -> Result<()> where @@ -51,56 +46,8 @@ where } let template = include_bytes!(concat!(env!("OUT_DIR"), "/template.zip")); - let mut cursor = Cursor::new(Vec::new()); - cursor.write_all(template)?; - cursor.seek(SeekFrom::Start(0))?; - - let mut archive = zip::ZipArchive::new(cursor)?; - - for i in 0..archive.len() { - let mut file = archive.by_index(i)?; - let mut contents = String::new(); - file.read_to_string(&mut contents)?; - - // replace template placeholders - let contents = contents.replace("{{name}}", name); - let contents = contents.replace("{{camel_name}}", &name.to_upper_camel_case()); - - let outpath = out_dir.join(file.name()); - - if (*file.name()).ends_with('/') { - fs::create_dir_all(&outpath)?; - } else { - if let Some(p) = outpath.parent() { - if !p.exists() { - fs::create_dir_all(&p)?; - } - } - let mut outfile = fs::OpenOptions::new() - .write(true) - .create_new(true) - .open(outpath.clone()) - .map_err(|e| { - if e.kind() == std::io::ErrorKind::AlreadyExists { - anyhow::anyhow!("New contract file {} already exists", file.name()) - } else { - anyhow::anyhow!(e) - } - })?; - - outfile.write_all(contents.as_bytes())?; - } - - // Get and set permissions - #[cfg(unix)] - { - use std::os::unix::fs::PermissionsExt; - - if let Some(mode) = file.unix_mode() { - fs::set_permissions(&outpath, fs::Permissions::from_mode(mode))?; - } - } - } + + crate::util::unzip(template, out_dir, Some(name))?; Ok(()) } @@ -177,7 +124,7 @@ mod tests { assert!(result.is_err(), "Should fail"); assert_eq!( result.err().unwrap().to_string(), - "New contract file .gitignore already exists" + "File .gitignore already exists" ); Ok(()) }) diff --git a/src/cmd/test.rs b/src/cmd/test.rs index 98b9dae1..49272723 100644 --- a/src/cmd/test.rs +++ b/src/cmd/test.rs @@ -65,7 +65,7 @@ pub(crate) fn execute(manifest_path: &ManifestPath, verbosity: Verbosity) -> Res "Running tests".bright_green().bold() ); - let stdout = util::invoke_cargo("test", &[""], manifest_path.directory(), verbosity)?; + let stdout = util::invoke_cargo("test", &[""], manifest_path.directory(), verbosity, None)?; Ok(TestResult { stdout, verbosity }) } diff --git a/src/util.rs b/src/util.rs index d373db1c..a696dcfc 100644 --- a/src/util.rs +++ b/src/util.rs @@ -16,8 +16,15 @@ use crate::Verbosity; use anyhow::{Context, Result}; +use heck::ToUpperCamelCase as _; use rustc_version::Channel; -use std::{ffi::OsStr, path::Path, process::Command}; +use std::{ + ffi::OsStr, + fs, + io::{Cursor, Read, Seek, SeekFrom, Write}, + path::{Path, PathBuf}, + process::Command, +}; /// Check whether the current rust channel is valid: `nightly` is recommended. pub fn assert_channel() -> Result<()> { @@ -43,6 +50,7 @@ pub(crate) fn invoke_cargo( args: I, working_dir: Option

, verbosity: Verbosity, + env: Option>, ) -> Result> where I: IntoIterator + std::fmt::Debug, @@ -51,6 +59,22 @@ where { let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_string()); let mut cmd = Command::new(cargo); + + if command == "dylint" { + // We need to remove those environment in case `cargo dylint` is invoked. + // This is because the ink! dylint driver crate found in `dylint` uses a + // fixed Rust toolchain via the `ink_linting/rust-toolchain` file. By + // removing this env variable we avoid issues with different Rust toolchains + // interfering with each other. + cmd.env_remove("CARGO_TARGET_DIR"); + } + + env.unwrap_or_default() + .iter() + .for_each(|(env_var, env_key)| { + cmd.env(env_var, env_key); + }); + if let Some(path) = working_dir { log::debug!("Setting cargo working dir to '{}'", path.as_ref().display()); cmd.current_dir(path); @@ -60,7 +84,14 @@ where cmd.args(args); match verbosity { Verbosity::Quiet => cmd.arg("--quiet"), - Verbosity::Verbose => cmd.arg("--verbose"), + Verbosity::Verbose => { + // `dylint` is verbose by default, it doesn't have a `--verbose` argument. + if command != "dylint" { + cmd.arg("--verbose") + } else { + &mut cmd + } + } Verbosity::Default => &mut cmd, }; @@ -189,3 +220,66 @@ pub mod tests { }) } } + +// Unzips the file at `template` to `out_dir`. +// +// In case `name` is set the zip file is treated as if it were a template for a new +// contract. Replacements in `Cargo.toml` for `name`-placeholders are attempted in +// that case. +pub fn unzip(template: &[u8], out_dir: PathBuf, name: Option<&str>) -> Result<()> { + let mut cursor = Cursor::new(Vec::new()); + cursor.write_all(template)?; + cursor.seek(SeekFrom::Start(0))?; + + let mut archive = zip::ZipArchive::new(cursor)?; + + for i in 0..archive.len() { + let mut file = archive.by_index(i)?; + let outpath = out_dir.join(file.name()); + + if (*file.name()).ends_with('/') { + fs::create_dir_all(&outpath)?; + } else { + if let Some(p) = outpath.parent() { + if !p.exists() { + fs::create_dir_all(&p)?; + } + } + let mut outfile = fs::OpenOptions::new() + .write(true) + .create_new(true) + .open(outpath.clone()) + .map_err(|e| { + if e.kind() == std::io::ErrorKind::AlreadyExists { + anyhow::anyhow!("File {} already exists", file.name(),) + } else { + anyhow::anyhow!(e) + } + })?; + + if let Some(name) = name { + let mut contents = String::new(); + file.read_to_string(&mut contents)?; + let contents = contents.replace("{{name}}", name); + let contents = contents.replace("{{camel_name}}", &name.to_upper_camel_case()); + outfile.write_all(contents.as_bytes())?; + } else { + let mut v = Vec::new(); + file.read_to_end(&mut v)?; + outfile.write_all(v.as_slice())?; + } + } + + // Get and set permissions + #[cfg(unix)] + { + use std::os::unix::fs::PermissionsExt; + + if let Some(mode) = file.unix_mode() { + fs::set_permissions(&outpath, fs::Permissions::from_mode(mode))?; + } + } + } + + Ok(()) +} diff --git a/src/workspace/manifest.rs b/src/workspace/manifest.rs index ad0f02ca..8a45a2b9 100644 --- a/src/workspace/manifest.rs +++ b/src/workspace/manifest.rs @@ -53,7 +53,15 @@ impl ManifestPath { /// Create an arg `--manifest-path=` for `cargo` command pub fn cargo_arg(&self) -> String { - format!("--manifest-path={}", self.path.to_string_lossy()) + format!( + "--manifest-path={}", + self.path + .canonicalize() + .unwrap_or_else(|err| { + panic!("Failed to canonicalize {:?}: {:?}", self.path, err); + }) + .to_string_lossy() + ) } /// The directory path of the manifest path. -- GitLab From 36c5c990dff127ea54c4ebfbb85e970ed446f822 Mon Sep 17 00:00:00 2001 From: CI system <> Date: Thu, 17 Feb 2022 20:42:00 +0100 Subject: [PATCH 02/42] CI: cache cargo installations; update versions --- .github/workflows/macos.yml | 19 +++++++++++++++---- .github/workflows/windows.yml | 19 +++++++++++++++---- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 184ef096..3e80b94e 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -26,7 +26,7 @@ jobs: steps: - name: Checkout sources & submodules - uses: actions/checkout@master + uses: actions/checkout@v2.4.0 with: fetch-depth: 1 submodules: recursive @@ -36,21 +36,32 @@ jobs: - name: Install toolchain id: toolchain - uses: actions-rs/toolchain@master + uses: actions-rs/toolchain@v1.0.7 with: profile: minimal toolchain: ${{ matrix.toolchain }} components: rust-src override: true + - name: Install cargo-dylint + uses: baptiste0928/cargo-install@v1 + with: + crate: cargo-dylint + version: 1 + + - name: Install dylint-link + uses: baptiste0928/cargo-install@v1 + with: + crate: dylint-link + version: 1 + - name: Rust Cache - uses: Swatinem/rust-cache@v1.2.0 + uses: Swatinem/rust-cache@v1.3.0 - name: Build contract template on ${{ matrix.platform }}-${{ matrix.toolchain }} run: | wasm-opt --version cargo -vV - cargo install cargo-dylint dylint-link cargo dylint --version cargo run -- contract --version cargo run -- contract new foobar diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 087efe73..79ae651b 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -32,28 +32,39 @@ jobs: pathInArchive: "binaryen-/bin/wasm-opt.exe" - name: Checkout sources & submodules - uses: actions/checkout@master + uses: actions/checkout@v2.4.0 with: fetch-depth: 1 submodules: recursive - name: Install toolchain id: toolchain - uses: actions-rs/toolchain@master + uses: actions-rs/toolchain@v1.0.7 with: profile: minimal toolchain: ${{ matrix.toolchain }} components: rust-src override: true + - name: Install cargo-dylint + uses: baptiste0928/cargo-install@v1 + with: + crate: cargo-dylint + version: 1 + + - name: Install dylint-link + uses: baptiste0928/cargo-install@v1 + with: + crate: dylint-link + version: 1 + - name: Rust Cache - uses: Swatinem/rust-cache@v1.2.0 + uses: Swatinem/rust-cache@v1.3.0 - name: Build contract template on ${{ matrix.platform }}-${{ matrix.toolchain }} run: | wasm-opt --version cargo -vV - cargo install cargo-dylint dylint-link cargo dylint --version cargo run -- contract --version cargo run -- contract new foobar -- GitLab From 203ae16c478eb6759e01af85f888797b80cd3953 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Fri, 18 Feb 2022 13:09:12 +0100 Subject: [PATCH 03/42] Apply suggestions from code review Co-authored-by: Sergejs Kostjucenko <85877331+sergejparity@users.noreply.github.com> --- .github/workflows/macos.yml | 4 ++-- .github/workflows/windows.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 3e80b94e..fec8250a 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -26,7 +26,7 @@ jobs: steps: - name: Checkout sources & submodules - uses: actions/checkout@v2.4.0 + uses: actions/checkout@v2 with: fetch-depth: 1 submodules: recursive @@ -36,7 +36,7 @@ jobs: - name: Install toolchain id: toolchain - uses: actions-rs/toolchain@v1.0.7 + uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: ${{ matrix.toolchain }} diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 79ae651b..ada95c81 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -32,14 +32,14 @@ jobs: pathInArchive: "binaryen-/bin/wasm-opt.exe" - name: Checkout sources & submodules - uses: actions/checkout@v2.4.0 + uses: actions/checkout@v2 with: fetch-depth: 1 submodules: recursive - name: Install toolchain id: toolchain - uses: actions-rs/toolchain@v1.0.7 + uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: ${{ matrix.toolchain }} -- GitLab From 618ea701187538e92eb3c68d000af5446e348b16 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Fri, 18 Feb 2022 14:25:13 +0100 Subject: [PATCH 04/42] Update changelog --- CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d2934edc..336f7cdd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Linting rules for smart contracts + +We are introducing a linter for ink! smart contracts in this release! +From now on `cargo-contract` checks if the ink! smart contract that is +`build` or `check`-ed follows certain rules. + +As a starting point we've only added one linting rule so far; it asserts correct +initialization of the [`ink_storage::Mapping`](https://paritytech.github.io/ink/ink_storage/struct.Mapping.html) +data structure. + +In order for the linting to work with your smart contract, the contract has to be +written in at least ink! 3.0.0-rc9. If it's older the linting will just always succeed. + +### Added +- Add linting to assert correct initialization of [`ink_storage::Mapping`](https://paritytech.github.io/ink/ink_storage/struct.Mapping.html) - [#431](https://github.com/paritytech/cargo-contract/pull/431) + ## [0.17.0] - 2022-01-19 ### Changed -- GitLab From 05367958d7da0f185aabfa2e9ac131e2f68fb4c7 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Fri, 18 Feb 2022 16:13:52 +0100 Subject: [PATCH 05/42] Check if `dylint` requirements are installed --- src/cmd/build.rs | 128 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 119 insertions(+), 9 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 6fc63e7a..a6dcdcc2 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -304,6 +304,8 @@ fn exec_cargo_for_wasm_target( /// We create a temporary folder, extract the linting driver there and run /// `cargo dylint` with it. fn exec_cargo_dylint(crate_metadata: &CrateMetadata, verbosity: Verbosity) -> Result<()> { + check_dylint_requirements(crate_metadata.manifest_path.directory().unwrap())?; + let tmp_dir = tempfile::Builder::new() .prefix("cargo-contract-dylint_") .tempdir()?; @@ -329,6 +331,52 @@ fn exec_cargo_dylint(crate_metadata: &CrateMetadata, verbosity: Verbosity) -> Re Ok(()) } +/// Checks if all requirements for `dylint` are installed. +/// +/// Those are an installed version of `cargo-dylint` and `dylint-link`. +fn check_dylint_requirements(_working_dir: &Path) -> Result<()> { + let execute_cmd = |cmd: &mut Command| { + // when testing this function we set the `PATH` to the `working_dir` + // so that we can have mocked binaries in there which are executed + // instead of the real ones. + #[cfg(test)] + cmd.env("PATH", _working_dir); + + cmd.stdout(std::process::Stdio::null()) + .stderr(std::process::Stdio::null()) + .spawn() + .unwrap_or_else(|_| panic!("Error executing `{:?}`", cmd)) + .wait() + .map(|res| res.success()) + .unwrap_or_else(|err| panic!("Error executing `{:?}`: {:?}", cmd, err)) + }; + + // when testing this function we should never fall back to a `cargo` specified + // in the env variable, as this would mess with the mocked binaries. + #[cfg(not(test))] + let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_string()); + #[cfg(test)] + let cargo = "cargo"; + + if !execute_cmd(Command::new(cargo).arg("dylint").arg("--version")) { + anyhow::bail!("cargo-dylint was not found!\n\ + Make sure it is installed and the binary is in your PATH environment.\n\n\ + You can install it by executing `cargo install cargo-dylint`." + .to_string() + .bright_yellow()); + } + + if !execute_cmd(Command::new("dylint-link").arg("--version")) { + anyhow::bail!("dylint-link was not found!\n\ + Make sure it is installed and the binary is in your PATH environment.\n\n\ + You can install it by executing `cargo install dylint-link`." + .to_string() + .bright_yellow()); + } + + Ok(()) +} + /// Ensures the Wasm memory import of a given module has the maximum number of pages. /// /// Iterates over the import section, finds the memory import entry if any and adjusts the maximum @@ -836,6 +884,20 @@ mod tests_ci_only { .any(|e| e.name() == "name") } + /// Creates an executable file at `path` with the content `content`. + /// + /// Currently works only on `unix`. + #[cfg(unix)] + fn create_executable(path: &Path, content: &str) { + { + let mut file = std::fs::File::create(&path).unwrap(); + file.write_all(content.as_bytes()) + .expect("writing of executable failed"); + } + std::fs::set_permissions(&path, std::fs::Permissions::from_mode(0o777)) + .expect("setting permissions failed"); + } + /// Creates an executable `wasm-opt-mocked` file which outputs /// "wasm-opt version `version`". /// @@ -845,15 +907,9 @@ mod tests_ci_only { #[cfg(unix)] fn mock_wasm_opt_version(tmp_dir: &Path, version: &str) -> PathBuf { let path = tmp_dir.join("wasm-opt-mocked"); - { - let mut file = std::fs::File::create(&path).unwrap(); - let version = format!("#!/bin/sh\necho \"wasm-opt version {}\"", version); - file.write_all(version.as_bytes()) - .expect("writing wasm-opt-mocked failed"); - } - std::fs::set_permissions(&path, std::fs::Permissions::from_mode(0o777)) - .expect("setting permissions failed"); - path + let content = format!("#!/bin/sh\necho \"wasm-opt version {}\"", version); + create_executable(&path, &content); + path.to_path_buf() } #[test] @@ -1384,4 +1440,58 @@ mod tests_ci_only { Ok(()) }) } + + #[cfg(unix)] + #[test] + fn missing_dylint_link_installation_must_be_detected() { + with_new_contract_project(|manifest_path| { + // given + let manifest_dir = manifest_path.directory().unwrap(); + + // mock an existing `cargo dylint` installation. + create_executable(&manifest_dir.join("cargo"), "#!/bin/sh\nexit 0"); + + // mock non-existing `dylint-link` binary + create_executable(&manifest_dir.join("dylint-link"), "#!/bin/sh\nexit 1"); + + // when + let args = crate::cmd::build::ExecuteArgs { + manifest_path, + ..Default::default() + }; + let res = super::execute(args).map(|_| ()).unwrap_err(); + + // then + assert!(format!("{:?}", res).contains("dylint-link was not found!")); + + Ok(()) + }) + } + + #[cfg(unix)] + #[test] + fn missing_cargo_dylint_installation_must_be_detected() { + with_new_contract_project(|manifest_path| { + // given + let manifest_dir = manifest_path.directory().unwrap(); + + // mock existing `dylint-link` binary + create_executable(&manifest_dir.join("dylint-link"), "#!/bin/sh\nexit 0"); + + // mock a non-existing `cargo dylint` installation. + create_executable(&manifest_dir.join("cargo"), "#!/bin/sh\nexit 1"); + + // when + let args = crate::cmd::build::ExecuteArgs { + manifest_path, + ..Default::default() + }; + let res = super::execute(args).map(|_| ()).unwrap_err(); + + // then + assert!(format!("{:?}", res).contains("cargo-dylint was not found!")); + + Ok(()) + }) + } } -- GitLab From 50357904c763f3fea3331755058236b8592493d5 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Fri, 18 Feb 2022 20:31:30 +0100 Subject: [PATCH 06/42] Make `clippy` happy --- src/cmd/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index a6dcdcc2..de1b1eba 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -909,7 +909,7 @@ mod tests_ci_only { let path = tmp_dir.join("wasm-opt-mocked"); let content = format!("#!/bin/sh\necho \"wasm-opt version {}\"", version); create_executable(&path, &content); - path.to_path_buf() + path } #[test] -- GitLab From 35107a8cdbb6bbb0a93128a9e10008b44750d007 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Fri, 18 Feb 2022 20:43:38 +0100 Subject: [PATCH 07/42] Make tests happy --- src/cmd/build.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index de1b1eba..b2ca2021 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -340,7 +340,11 @@ fn check_dylint_requirements(_working_dir: &Path) -> Result<()> { // so that we can have mocked binaries in there which are executed // instead of the real ones. #[cfg(test)] - cmd.env("PATH", _working_dir); + { + let path_env = std::env::var("PATH").unwrap(); + let path_env = format!("{}:{}", _working_dir.to_string_lossy(), path_env); + cmd.env("PATH", path_env); + } cmd.stdout(std::process::Stdio::null()) .stderr(std::process::Stdio::null()) -- GitLab From 36e85d1972a7b1f0dece8ec062e4edf5a48191b9 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Tue, 22 Feb 2022 15:02:57 +0100 Subject: [PATCH 08/42] Make `LICENSE` symlink --- ink_linting/LICENSE | 204 +------------------------------------------- 1 file changed, 1 insertion(+), 203 deletions(-) mode change 100644 => 120000 ink_linting/LICENSE diff --git a/ink_linting/LICENSE b/ink_linting/LICENSE deleted file mode 100644 index 6b0b1270..00000000 --- a/ink_linting/LICENSE +++ /dev/null @@ -1,203 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You 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 the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You 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 the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - diff --git a/ink_linting/LICENSE b/ink_linting/LICENSE new file mode 120000 index 00000000..99d5fc26 --- /dev/null +++ b/ink_linting/LICENSE @@ -0,0 +1 @@ +../metadata/LICENSE \ No newline at end of file -- GitLab From 2fc61c11465c7b1f40f22dc9d716f4d008a9ff45 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Tue, 22 Feb 2022 15:12:31 +0100 Subject: [PATCH 09/42] Make error handling and panic's consistent --- build.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/build.rs b/build.rs index b74d3093..ad57924e 100644 --- a/build.rs +++ b/build.rs @@ -81,10 +81,11 @@ fn main() { // // We still have to create an empty file though, due to the `include_bytes!` macro. File::create(dylint_driver_dst_file).unwrap_or_else(|err| { - panic!( + eprintln!( "Failed creating an empty ink-dylint-driver.zip file: {:?}", err ); + std::process::exit(1); }); std::process::exit(bool_to_exit_code(zipped_template)); } @@ -94,7 +95,8 @@ fn main() { let zipped_lints = build_dylint_driver(manifest_dir, out_dir, dylint_driver_dst_file) .map(|_| true) .unwrap_or_else(|err| { - panic!("Failed building dylint driver: {:?}", err); + eprintln!("Failed building dylint driver: {:?}", err); + std::process::exit(1); }); std::process::exit(bool_to_exit_code(zipped_template && zipped_lints)); } @@ -145,8 +147,7 @@ fn build_dylint_driver( let child = cmd // capture the stdout to return from this function as bytes .stdout(std::process::Stdio::piped()) - .spawn() - .unwrap_or_else(|_| panic!("Error executing `{:?}`", cmd)); + .spawn()?; let output = child.wait_with_output()?; if !output.status.success() { -- GitLab From 26edca5ef601f4c0871b970993dc971067b81aa4 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Tue, 22 Feb 2022 15:33:14 +0100 Subject: [PATCH 10/42] Improve code structure --- build.rs | 53 ++++++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/build.rs b/build.rs index ad57924e..75e3082d 100644 --- a/build.rs +++ b/build.rs @@ -73,33 +73,13 @@ fn main() { // by building the crate in `ink_linting/`. let dylint_driver_dst_file = out_dir.join("ink-dylint-driver.zip"); - #[cfg(feature = "cargo-clippy")] - { - // For `clippy` runs it is not necessary to build the `dylint` driver. - // Furthermore the fixed Rust nightly specified in `ink_linting/rust-toolchain` - // contains a bug that results in an `error[E0786]: found invalid metadata files` ICE. - // - // We still have to create an empty file though, due to the `include_bytes!` macro. - File::create(dylint_driver_dst_file).unwrap_or_else(|err| { - eprintln!( - "Failed creating an empty ink-dylint-driver.zip file: {:?}", - err - ); + let zipped_lints = build_dylint_driver(manifest_dir, out_dir, dylint_driver_dst_file) + .map(|_| true) + .unwrap_or_else(|err| { + eprintln!("Failed building dylint driver: {:?}", err); std::process::exit(1); }); - std::process::exit(bool_to_exit_code(zipped_template)); - } - - #[cfg(not(feature = "cargo-clippy"))] - { - let zipped_lints = build_dylint_driver(manifest_dir, out_dir, dylint_driver_dst_file) - .map(|_| true) - .unwrap_or_else(|err| { - eprintln!("Failed building dylint driver: {:?}", err); - std::process::exit(1); - }); - std::process::exit(bool_to_exit_code(zipped_template && zipped_lints)); - } + std::process::exit(bool_to_exit_code(zipped_template && zipped_lints)); } /// Returns the process exit code which corresponds to a boolean. @@ -110,6 +90,29 @@ fn bool_to_exit_code(val: bool) -> i32 { } } +/// Builds the crate in `ink_linting/`. This crate contains the `dylint` driver with ink! specific +/// linting rules. +#[cfg(feature = "cargo-clippy")] +fn build_dylint_driver( + _manifest_dir: PathBuf, + _out_dir: PathBuf, + dylint_driver_dst_file: PathBuf, +) -> Result<()> { + // For `clippy` runs it is not necessary to build the `dylint` driver. + // Furthermore the fixed Rust nightly specified in `ink_linting/rust-toolchain` + // contains a bug that results in an `error[E0786]: found invalid metadata files` ICE. + // + // We still have to create an empty file though, due to the `include_bytes!` macro. + File::create(dylint_driver_dst_file) + .map_err(|err| { + anyhow::anyhow!( + "Failed creating an empty ink-dylint-driver.zip file: {:?}", + err + ) + }) + .map(|_| ()) +} + /// Builds the crate in `ink_linting/`. This crate contains the `dylint` driver with ink! specific /// linting rules. #[cfg(not(feature = "cargo-clippy"))] -- GitLab From 26bf192902ff7828854ca3abcd3a5ac3d972508e Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Tue, 22 Feb 2022 15:33:56 +0100 Subject: [PATCH 11/42] Remove unneeded `--workspace` --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 87258d9e..3a687921 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -105,7 +105,7 @@ test-dylint: - cargo fmt --verbose --all -- --check - cargo clippy --verbose -- -D warnings; - - cargo test --verbose --workspace --all-features + - cargo test --verbose --all-features test: stage: test -- GitLab From 23af5eb81fc4774b0eb606db0abc9020b0a7308a Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Tue, 22 Feb 2022 15:37:11 +0100 Subject: [PATCH 12/42] Fix `mapping-two-constructor` test file --- .../ui/pass/mapping-two-constructors.rs | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/ink_linting/ui/pass/mapping-two-constructors.rs b/ink_linting/ui/pass/mapping-two-constructors.rs index 558d7e0a..f16cddfa 100644 --- a/ink_linting/ui/pass/mapping-two-constructors.rs +++ b/ink_linting/ui/pass/mapping-two-constructors.rs @@ -29,12 +29,9 @@ mod my_contract { } impl MyContract { - /// The `initialize_contract` must be found, even if there is logic before it. + /// First constructor which uses the `new_init` helper function. #[ink(constructor)] - pub fn new() -> Self { - let a = 1; - let b = 2; - assert_eq!(add(a, b), 3); + pub fn new1() -> Self { ink_lang::utils::initialize_contract(Self::new_init) } @@ -45,16 +42,22 @@ mod my_contract { self.balances.insert(&caller, &value); } + /// Second constructor which doesn't use the `new_init` helper function. + #[ink(constructor)] + pub fn new2() -> Self { + ink_lang::utils::initialize_contract(|contract: &mut Self| { + let caller = Self::env().caller(); + let value: Balance = Default::default(); + contract.balances.insert(&caller, &value); + }) + } + /// Returns something. #[ink(message)] pub fn get(&self) { // ... } } - - fn add(a: u32, b: u32) -> u32 { - a + b - } } fn main() {} -- GitLab From aeb5287644c4b45dbdbdd458bb23e32fc5d9c0d2 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Tue, 22 Feb 2022 16:17:39 +0100 Subject: [PATCH 13/42] Simplify `Option>` to `Vec` --- src/cmd/build.rs | 8 ++++---- src/cmd/metadata.rs | 2 +- src/cmd/test.rs | 2 +- src/util.rs | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index b2ca2021..7ec8e229 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -265,10 +265,10 @@ fn exec_cargo_for_wasm_target( } else { args.push("-Zbuild-std-features=panic_immediate_abort"); } - let env = Some(vec![( + let env = vec![( "RUSTFLAGS", "-C link-arg=-zstack-size=65536 -C link-arg=--import-memory -Clinker-plugin-lto", - )]); + )]; util::invoke_cargo(command, &args, manifest_path.directory(), verbosity, env)?; Ok(()) @@ -326,7 +326,7 @@ fn exec_cargo_dylint(crate_metadata: &CrateMetadata, verbosity: Verbosity) -> Re .directory() .unwrap_or_else(|| Path::new(".")) .canonicalize()?; - util::invoke_cargo("dylint", &args, Some(working_dir), verbosity, Some(env))?; + util::invoke_cargo("dylint", &args, Some(working_dir), verbosity, env)?; Ok(()) } @@ -692,7 +692,7 @@ fn assert_compatible_ink_dependencies( ) -> Result<()> { for dependency in ["parity-scale-codec", "scale-info"].iter() { let args = ["-i", dependency, "--duplicates"]; - let _ = util::invoke_cargo("tree", &args, manifest_path.directory(), verbosity, None) + let _ = util::invoke_cargo("tree", &args, manifest_path.directory(), verbosity, vec![]) .map_err(|_| { anyhow::anyhow!( "Mismatching versions of `{}` were found!\n\ diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 1d563c0b..85139880 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -100,7 +100,7 @@ pub(crate) fn execute( ], crate_metadata.manifest_path.directory(), verbosity, - None, + vec![], )?; let ink_meta: serde_json::Map = serde_json::from_slice(&stdout)?; diff --git a/src/cmd/test.rs b/src/cmd/test.rs index 8f47f742..bf624e41 100644 --- a/src/cmd/test.rs +++ b/src/cmd/test.rs @@ -65,7 +65,7 @@ pub(crate) fn execute(manifest_path: &ManifestPath, verbosity: Verbosity) -> Res "Running tests".bright_green().bold() ); - let stdout = util::invoke_cargo("test", &[""], manifest_path.directory(), verbosity, None)?; + let stdout = util::invoke_cargo("test", &[""], manifest_path.directory(), verbosity, vec![])?; Ok(TestResult { stdout, verbosity }) } diff --git a/src/util.rs b/src/util.rs index ac40a2ad..409bfb15 100644 --- a/src/util.rs +++ b/src/util.rs @@ -50,7 +50,7 @@ pub(crate) fn invoke_cargo( args: I, working_dir: Option

, verbosity: Verbosity, - env: Option>, + env: Vec<(&str, &str)>, ) -> Result> where I: IntoIterator + std::fmt::Debug, -- GitLab From 44fbfb91666fbadd8b5eec7de1bdf04be653f9f4 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Tue, 22 Feb 2022 18:41:34 +0100 Subject: [PATCH 14/42] Generalize unsetting of env variables in `invoke_cargo` --- src/cmd/build.rs | 14 +++++++++++--- src/util.rs | 35 ++++++++++++++++++----------------- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 7ec8e229..426d7ac2 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -267,7 +267,7 @@ fn exec_cargo_for_wasm_target( } let env = vec![( "RUSTFLAGS", - "-C link-arg=-zstack-size=65536 -C link-arg=--import-memory -Clinker-plugin-lto", + Some("-C link-arg=-zstack-size=65536 -C link-arg=--import-memory -Clinker-plugin-lto"), )]; util::invoke_cargo(command, &args, manifest_path.directory(), verbosity, env)?; @@ -318,8 +318,16 @@ fn exec_cargo_dylint(crate_metadata: &CrateMetadata, verbosity: Verbosity) -> Re let args = vec!["ink_linting", &manifest_path]; let tmp_dir_path = tmp_dir.path().as_os_str().to_string_lossy(); let env = vec![ - ("DYLINT_LIBRARY_PATH", tmp_dir_path.as_ref()), - ("DYLINT_DRIVER_PATH", tmp_dir_path.as_ref()), + ("DYLINT_LIBRARY_PATH", Some(tmp_dir_path.as_ref())), + ("DYLINT_DRIVER_PATH", Some(tmp_dir_path.as_ref())), + // We need to remove the `CARGO_TARGET_DIR` environment variable in + // case `cargo dylint` is invoked. + // + // This is because the ink! dylint driver crate found in `dylint` uses a + // fixed Rust toolchain via the `ink_linting/rust-toolchain` file. By + // removing this env variable we avoid issues with different Rust toolchains + // interfering with each other. + ("CARGO_TARGET_DIR", None), ]; let working_dir = crate_metadata .manifest_path diff --git a/src/util.rs b/src/util.rs index 409bfb15..a549f915 100644 --- a/src/util.rs +++ b/src/util.rs @@ -42,15 +42,24 @@ pub fn assert_channel() -> Result<()> { } } -/// Run cargo with the supplied args +/// Invokes `cargo` with the subcommand `command` and the supplied `args`. /// -/// If successful, returns the stdout bytes +/// In case `working_dir` is set, the command will be invoked with that folder +/// as the working directory. +/// +/// In case `env` is given environment variables can be either set or unset: +/// * To _set_ push an item a la `("VAR_NAME", Some("VAR_VALUE"))` to +/// the `env` vector. +/// * To _unset_ push an item a la `("VAR_NAME", None)` to the `env` +/// vector. +/// +/// If successful, returns the stdout bytes. pub(crate) fn invoke_cargo( command: &str, args: I, working_dir: Option

, verbosity: Verbosity, - env: Vec<(&str, &str)>, + env: Vec<(&str, Option<&str>)>, ) -> Result> where I: IntoIterator + std::fmt::Debug, @@ -60,20 +69,12 @@ where let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_string()); let mut cmd = Command::new(cargo); - if command == "dylint" { - // We need to remove those environment in case `cargo dylint` is invoked. - // This is because the ink! dylint driver crate found in `dylint` uses a - // fixed Rust toolchain via the `ink_linting/rust-toolchain` file. By - // removing this env variable we avoid issues with different Rust toolchains - // interfering with each other. - cmd.env_remove("CARGO_TARGET_DIR"); - } - - env.unwrap_or_default() - .iter() - .for_each(|(env_var, env_key)| { - cmd.env(env_var, env_key); - }); + env.iter().for_each(|(env_key, maybe_env_val)| { + match maybe_env_val { + Some(env_val) => cmd.env(env_key, env_val), + None => cmd.env_remove(env_key), + }; + }); if let Some(path) = working_dir { log::debug!("Setting cargo working dir to '{}'", path.as_ref().display()); -- GitLab From 424a1e9f9596f78a16ed99f763c2f8fb3f52522c Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Tue, 22 Feb 2022 18:48:53 +0100 Subject: [PATCH 15/42] Move special case of `dylint` verbosity to call site --- src/cmd/build.rs | 7 +++++++ src/main.rs | 2 +- src/util.rs | 1 - 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 426d7ac2..844eb14e 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -334,6 +334,13 @@ fn exec_cargo_dylint(crate_metadata: &CrateMetadata, verbosity: Verbosity) -> Re .directory() .unwrap_or_else(|| Path::new(".")) .canonicalize()?; + + let verbosity = if verbosity == Verbosity::Verbose { + // `dylint` is verbose by default, it doesn't have a `--verbose` argument, + Verbosity::Default + } else { + verbosity + }; util::invoke_cargo("dylint", &args, Some(working_dir), verbosity, env)?; Ok(()) diff --git a/src/main.rs b/src/main.rs index 241a2eed..eb7adacf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -140,7 +140,7 @@ pub struct VerbosityFlags { } /// Denotes if output should be printed to stdout. -#[derive(Clone, Copy, serde::Serialize)] +#[derive(Clone, Copy, serde::Serialize, Eq, PartialEq)] pub enum Verbosity { /// Use default output Default, diff --git a/src/util.rs b/src/util.rs index a549f915..59acf86e 100644 --- a/src/util.rs +++ b/src/util.rs @@ -86,7 +86,6 @@ where match verbosity { Verbosity::Quiet => cmd.arg("--quiet"), Verbosity::Verbose => { - // `dylint` is verbose by default, it doesn't have a `--verbose` argument. if command != "dylint" { cmd.arg("--verbose") } else { -- GitLab From f8f9b8f90db03ee6242eb84efbc994a6fb6b3a19 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Tue, 22 Feb 2022 19:04:41 +0100 Subject: [PATCH 16/42] Keep calm and return an `Err` --- src/cmd/build.rs | 16 +++++++++++----- src/cmd/metadata.rs | 2 +- src/workspace/manifest.rs | 16 ++++++---------- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 844eb14e..60807c7c 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -314,7 +314,7 @@ fn exec_cargo_dylint(crate_metadata: &CrateMetadata, verbosity: Verbosity) -> Re let template = include_bytes!(concat!(env!("OUT_DIR"), "/ink-dylint-driver.zip")); crate::util::unzip(template, tmp_dir.path().to_path_buf(), None)?; - let manifest_path = crate_metadata.manifest_path.cargo_arg(); + let manifest_path = crate_metadata.manifest_path.cargo_arg()?; let args = vec!["ink_linting", &manifest_path]; let tmp_dir_path = tmp_dir.path().as_os_str().to_string_lossy(); let env = vec![ @@ -364,10 +364,16 @@ fn check_dylint_requirements(_working_dir: &Path) -> Result<()> { cmd.stdout(std::process::Stdio::null()) .stderr(std::process::Stdio::null()) .spawn() - .unwrap_or_else(|_| panic!("Error executing `{:?}`", cmd)) + .map_err(|err| { + log::debug!("Error spawning `{:?}`", cmd); + err + })? .wait() .map(|res| res.success()) - .unwrap_or_else(|err| panic!("Error executing `{:?}`: {:?}", cmd, err)) + .map_err(|err| { + log::debug!("Error waiting for `{:?}`: {:?}", cmd, err); + err + }) }; // when testing this function we should never fall back to a `cargo` specified @@ -377,7 +383,7 @@ fn check_dylint_requirements(_working_dir: &Path) -> Result<()> { #[cfg(test)] let cargo = "cargo"; - if !execute_cmd(Command::new(cargo).arg("dylint").arg("--version")) { + if !execute_cmd(Command::new(cargo).arg("dylint").arg("--version"))? { anyhow::bail!("cargo-dylint was not found!\n\ Make sure it is installed and the binary is in your PATH environment.\n\n\ You can install it by executing `cargo install cargo-dylint`." @@ -385,7 +391,7 @@ fn check_dylint_requirements(_working_dir: &Path) -> Result<()> { .bright_yellow()); } - if !execute_cmd(Command::new("dylint-link").arg("--version")) { + if !execute_cmd(Command::new("dylint-link").arg("--version"))? { anyhow::bail!("dylint-link was not found!\n\ Make sure it is installed and the binary is in your PATH environment.\n\n\ You can install it by executing `cargo install dylint-link`." diff --git a/src/cmd/metadata.rs b/src/cmd/metadata.rs index 85139880..687ed8a5 100644 --- a/src/cmd/metadata.rs +++ b/src/cmd/metadata.rs @@ -93,7 +93,7 @@ pub(crate) fn execute( &[ "--package", "metadata-gen", - &manifest_path.cargo_arg(), + &manifest_path.cargo_arg()?, &target_dir_arg, "--release", &network.to_string(), diff --git a/src/workspace/manifest.rs b/src/workspace/manifest.rs index a3849e04..e9f5bf55 100644 --- a/src/workspace/manifest.rs +++ b/src/workspace/manifest.rs @@ -52,16 +52,12 @@ impl ManifestPath { } /// Create an arg `--manifest-path=` for `cargo` command - pub fn cargo_arg(&self) -> String { - format!( - "--manifest-path={}", - self.path - .canonicalize() - .unwrap_or_else(|err| { - panic!("Failed to canonicalize {:?}: {:?}", self.path, err); - }) - .to_string_lossy() - ) + pub fn cargo_arg(&self) -> Result { + let path = self + .path + .canonicalize() + .map_err(|err| anyhow::anyhow!("Failed to canonicalize {:?}: {:?}", self.path, err))?; + Ok(format!("--manifest-path={}", path.to_string_lossy())) } /// The directory path of the manifest path. -- GitLab From db679982ce3a02aea6ac5f26775a10869cfe4497 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 23 Feb 2022 03:18:51 +0100 Subject: [PATCH 17/42] Move checking for `dylint-link` to `build.rs` --- build.rs | 30 ++++++++++++++++++++++++++++++ src/cmd/build.rs | 35 ----------------------------------- 2 files changed, 30 insertions(+), 35 deletions(-) diff --git a/build.rs b/build.rs index 75e3082d..824d2aa8 100644 --- a/build.rs +++ b/build.rs @@ -68,6 +68,8 @@ fn main() { } }; + check_dylint_link_installed(); + // This zip file will contain the `dylint` driver, this is one file named in the form of // `libink_linting@nightly-2021-11-04-x86_64-unknown-linux-gnu.so`. This file is obtained // by building the crate in `ink_linting/`. @@ -327,3 +329,31 @@ fn get_platform() -> String { TARGET_ENV.map(|x| x.as_str()).unwrap_or(""), ) } + +fn check_dylint_link_installed() { + let execute_cmd = |cmd: &mut Command| { + cmd.stdout(std::process::Stdio::null()) + .stderr(std::process::Stdio::null()) + .spawn() + .map_err(|err| { + eprintln!("Error spawning `{:?}`", cmd); + err + })? + .wait() + .map(|res| res.success()) + .map_err(|err| { + eprintln!("Error waiting for `{:?}`: {:?}", cmd, err); + err + }) + }; + + let res = execute_cmd(Command::new("dylint-link").arg("--version")); + if res.is_err() || !res.expect("the `or` case will always will be `Ok`") { + eprintln!( + "dylint-link was not found!\n\ + Make sure it is installed and the binary is in your PATH environment.\n\n\ + You can install it by executing `cargo install dylint-link`." + ); + std::process::exit(1); + } +} diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 60807c7c..ba7ce772 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -391,14 +391,6 @@ fn check_dylint_requirements(_working_dir: &Path) -> Result<()> { .bright_yellow()); } - if !execute_cmd(Command::new("dylint-link").arg("--version"))? { - anyhow::bail!("dylint-link was not found!\n\ - Make sure it is installed and the binary is in your PATH environment.\n\n\ - You can install it by executing `cargo install dylint-link`." - .to_string() - .bright_yellow()); - } - Ok(()) } @@ -1466,33 +1458,6 @@ mod tests_ci_only { }) } - #[cfg(unix)] - #[test] - fn missing_dylint_link_installation_must_be_detected() { - with_new_contract_project(|manifest_path| { - // given - let manifest_dir = manifest_path.directory().unwrap(); - - // mock an existing `cargo dylint` installation. - create_executable(&manifest_dir.join("cargo"), "#!/bin/sh\nexit 0"); - - // mock non-existing `dylint-link` binary - create_executable(&manifest_dir.join("dylint-link"), "#!/bin/sh\nexit 1"); - - // when - let args = crate::cmd::build::ExecuteArgs { - manifest_path, - ..Default::default() - }; - let res = super::execute(args).map(|_| ()).unwrap_err(); - - // then - assert!(format!("{:?}", res).contains("dylint-link was not found!")); - - Ok(()) - }) - } - #[cfg(unix)] #[test] fn missing_cargo_dylint_installation_must_be_detected() { -- GitLab From 2065d20956c14563c94514b2a3932b4b56436337 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 23 Feb 2022 03:19:17 +0100 Subject: [PATCH 18/42] Add `ink_linting/Cargo.lock` --- ink_linting/Cargo.lock | 1425 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1425 insertions(+) create mode 100644 ink_linting/Cargo.lock diff --git a/ink_linting/Cargo.lock b/ink_linting/Cargo.lock new file mode 100644 index 00000000..915d4557 --- /dev/null +++ b/ink_linting/Cargo.lock @@ -0,0 +1,1425 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anyhow" +version = "1.0.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94a45b455c14666b85fc40a019e8ab9eb75e3a124e05494f5397122bc9eb06e0" + +[[package]] +name = "array-init" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6945cc5422176fc5e602e590c2878d2c2acd9a4fe20a4baa7c28022521698ec6" + +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" +dependencies = [ + "autocfg 1.1.0", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitvec" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1489fcb93a5bb47da0462ca93ad252ad6af2145cce58d10d46a83931ba9f016b" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "blake2" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b94ba84325db59637ffc528bbe8c7f86c02c57cff5c0e2b9b00f9a851f42f309" +dependencies = [ + "digest 0.10.3", +] + +[[package]] +name = "block-buffer" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" +dependencies = [ + "generic-array", +] + +[[package]] +name = "byte-slice-cast" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d30c751592b77c499e7bce34d99d67c2c11bdc0574e9a488ddade14150a4698" + +[[package]] +name = "camino" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f3132262930b0522068049f5870a856ab8affc80c70d08b6ecb785771a6fc23" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", +] + +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clippy_utils" +version = "0.1.58" +source = "git+https://github.com/rust-lang/rust-clippy?tag=rust-1.58.0#e18101137866b79045fee0ef996e696e68c920b4" +dependencies = [ + "if_chain", + "rustc-semver", +] + +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "compiletest_rs" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29843cb8d351febf86557681d049d1e1652b81a086a190fa1173c07fd17fbf83" +dependencies = [ + "diff", + "filetime", + "getopts", + "lazy_static", + "libc", + "log", + "miow", + "regex", + "rustfix", + "serde", + "serde_derive", + "serde_json", + "tester", + "winapi", +] + +[[package]] +name = "cpufeatures" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" +dependencies = [ + "libc", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-common" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" +dependencies = [ + "generic-array", + "typenum", +] + +[[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", +] + +[[package]] +name = "diff" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499" + +[[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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "dylint" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "893050152de22362e5e50525d9da750a8ee939cae9f476a26a7a55c5617ba047" +dependencies = [ + "ansi_term", + "anyhow", + "atty", + "cargo_metadata", + "dirs", + "dylint_internal", + "heck", + "lazy_static", + "log", + "semver", + "serde", + "serde_json", + "tempfile", + "walkdir", +] + +[[package]] +name = "dylint_internal" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "522be37595510d89d37096959ab258cc0dcc1867e64e956d41a1a48ff53e5892" +dependencies = [ + "ansi_term", + "anyhow", + "cargo_metadata", + "if_chain", + "log", + "sedregex", +] + +[[package]] +name = "dylint_linting" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15ec587418bda2f8e0dc6a40e21b2878c3901647f7148d5f833b2d657f46ea17" + +[[package]] +name = "dylint_testing" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b346641d5d618646f03e719d90857b88dc5077a7ba7b8b1e577a3fdaf6ea7137" +dependencies = [ + "anyhow", + "cargo_metadata", + "compiletest_rs", + "dylint", + "dylint_internal", + "env_logger", + "lazy_static", + "log", + "regex", + "serde_json", + "tempfile", +] + +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + +[[package]] +name = "env_logger" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "fastrand" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +dependencies = [ + "instant", +] + +[[package]] +name = "filetime" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "winapi", +] + +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "generic-array" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "getrandom" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "if_chain" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" + +[[package]] +name = "impl-serde" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4551f042f3438e64dbd6226b20527fc84a6e1fe65688b58746a2f53623f25f5c" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "ink_allocator" +version = "3.0.0-rc8" +source = "git+https://github.com/paritytech/ink#e345679f4a6888bf253d430374c8db518d957d7d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ink_env" +version = "3.0.0-rc8" +source = "git+https://github.com/paritytech/ink#e345679f4a6888bf253d430374c8db518d957d7d" +dependencies = [ + "arrayref", + "blake2", + "cfg-if", + "derive_more", + "ink_allocator", + "ink_metadata", + "ink_prelude", + "ink_primitives", + "num-traits", + "parity-scale-codec", + "paste", + "rand 0.8.5", + "rlibc", + "scale-info", + "secp256k1", + "sha2", + "sha3", + "static_assertions", +] + +[[package]] +name = "ink_eth_compatibility" +version = "3.0.0-rc8" +source = "git+https://github.com/paritytech/ink#e345679f4a6888bf253d430374c8db518d957d7d" +dependencies = [ + "ink_env", + "libsecp256k1", +] + +[[package]] +name = "ink_lang" +version = "3.0.0-rc8" +source = "git+https://github.com/paritytech/ink#e345679f4a6888bf253d430374c8db518d957d7d" +dependencies = [ + "derive_more", + "ink_env", + "ink_eth_compatibility", + "ink_lang_macro", + "ink_prelude", + "ink_primitives", + "ink_storage", + "parity-scale-codec", +] + +[[package]] +name = "ink_lang_codegen" +version = "3.0.0-rc8" +source = "git+https://github.com/paritytech/ink#e345679f4a6888bf253d430374c8db518d957d7d" +dependencies = [ + "blake2", + "derive_more", + "either", + "heck", + "impl-serde", + "ink_lang_ir", + "itertools", + "parity-scale-codec", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "ink_lang_ir" +version = "3.0.0-rc8" +source = "git+https://github.com/paritytech/ink#e345679f4a6888bf253d430374c8db518d957d7d" +dependencies = [ + "blake2", + "either", + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "ink_lang_macro" +version = "3.0.0-rc8" +source = "git+https://github.com/paritytech/ink#e345679f4a6888bf253d430374c8db518d957d7d" +dependencies = [ + "ink_lang_codegen", + "ink_lang_ir", + "ink_primitives", + "parity-scale-codec", + "proc-macro2", + "syn", +] + +[[package]] +name = "ink_linting" +version = "0.1.0" +dependencies = [ + "clippy_utils", + "dylint_linting", + "dylint_testing", + "if_chain", + "ink_env", + "ink_lang", + "ink_metadata", + "ink_primitives", + "ink_storage", + "log", + "parity-scale-codec", + "regex", + "scale-info", +] + +[[package]] +name = "ink_metadata" +version = "3.0.0-rc8" +source = "git+https://github.com/paritytech/ink#e345679f4a6888bf253d430374c8db518d957d7d" +dependencies = [ + "derive_more", + "impl-serde", + "ink_prelude", + "ink_primitives", + "scale-info", + "serde", +] + +[[package]] +name = "ink_prelude" +version = "3.0.0-rc8" +source = "git+https://github.com/paritytech/ink#e345679f4a6888bf253d430374c8db518d957d7d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ink_primitives" +version = "3.0.0-rc8" +source = "git+https://github.com/paritytech/ink#e345679f4a6888bf253d430374c8db518d957d7d" +dependencies = [ + "cfg-if", + "ink_prelude", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "ink_storage" +version = "3.0.0-rc8" +source = "git+https://github.com/paritytech/ink#e345679f4a6888bf253d430374c8db518d957d7d" +dependencies = [ + "array-init", + "cfg-if", + "derive_more", + "ink_env", + "ink_metadata", + "ink_prelude", + "ink_primitives", + "ink_storage_derive", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "ink_storage_derive" +version = "3.0.0-rc8" +source = "git+https://github.com/paritytech/ink#e345679f4a6888bf253d430374c8db518d957d7d" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "itertools" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + +[[package]] +name = "keccak" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06e509672465a0504304aa87f9f176f2b2b716ed8fb105ebe5c02dc6dce96a94" + +[[package]] +name = "libsecp256k1" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0452aac8bab02242429380e9b2f94ea20cea2b37e2c1777a1358799bbe97f37" +dependencies = [ + "arrayref", + "base64", + "digest 0.9.0", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.8.5", + "serde", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "miow" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +dependencies = [ + "winapi", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg 1.1.0", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "parity-scale-codec" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a7f3fcf5e45fc28b84dcdab6b983e77f197ec01f325a33f404ba6855afd1070" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6e626dc84025ff56bf1476ed0e30d10c84d7f89a475ef46ebabee1095a8fba" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "paste" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5" + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + +[[package]] +name = "proc-macro-crate" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dada8c9981fcf32929c3c0f0cd796a9284aca335565227ed88c83babb1d43dc" +dependencies = [ + "thiserror", + "toml", +] + +[[package]] +name = "proc-macro2" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" +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.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +dependencies = [ + "autocfg 0.1.8", + "libc", + "rand_chacha 0.1.1", + "rand_core 0.4.2", + "rand_hc", + "rand_isaac", + "rand_jitter", + "rand_os", + "rand_pcg", + "rand_xorshift", + "winapi", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.3", +] + +[[package]] +name = "rand_chacha" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +dependencies = [ + "autocfg 0.1.8", + "rand_core 0.3.1", +] + +[[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.3", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_jitter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" +dependencies = [ + "libc", + "rand_core 0.4.2", + "winapi", +] + +[[package]] +name = "rand_os" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +dependencies = [ + "cloudabi", + "fuchsia-cprng", + "libc", + "rand_core 0.4.2", + "rdrand", + "winapi", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +dependencies = [ + "autocfg 0.1.8", + "rand_core 0.4.2", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +dependencies = [ + "getrandom", + "redox_syscall", +] + +[[package]] +name = "regex" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "rlibc" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc874b127765f014d792f16763a81245ab80500e2ad921ed4ee9e82481ee08fe" + +[[package]] +name = "rustc-semver" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be1bdc7edf596692617627bbfeaba522131b18e06ca4df2b6b689e3c5d5ce84" + +[[package]] +name = "rustfix" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2c50b74badcddeb8f7652fa8323ce440b95286f8e4b64ebfd871c609672704e" +dependencies = [ + "anyhow", + "log", + "serde", + "serde_json", +] + +[[package]] +name = "rustversion" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" + +[[package]] +name = "ryu" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" + +[[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 = "scale-info" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d3b4d0b178e3af536f7988303bc73a0766c816de2138c08262015f8ec7be568" +dependencies = [ + "bitvec", + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", + "serde", +] + +[[package]] +name = "scale-info-derive" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7805950c36512db9e3251c970bb7ac425f326716941862205d612ab3b5e46e2" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "secp256k1" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab7883017d5b21f011ef8040ea9c6c7ac90834c0df26a69e4c0b06276151f125" +dependencies = [ + "rand 0.6.5", + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957da2573cde917463ece3570eab4a0b3f19de6f1646cde62e6fd3868f566036" +dependencies = [ + "cc", +] + +[[package]] +name = "sedregex" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19411e23596093f03bbd11dc45603b6329bb4bfec77b9fd13e2b9fc9b02efe3e" +dependencies = [ + "regex", +] + +[[package]] +name = "semver" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0486718e92ec9a68fbed73bb5ef687d71103b142595b406835649bebd33f72c7" +dependencies = [ + "serde", +] + +[[package]] +name = "serde" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99c3bd8169c58782adad9290a9af5939994036b76187f7b4f0e6de91dbbfc0ec" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.3", +] + +[[package]] +name = "sha3" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f935e31cf406e8c0e96c2815a5516181b7004ae8c5f296293221e9b1e356bd" +dependencies = [ + "digest 0.10.3", + "keccak", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "syn" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "tester" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0639d10d8f4615f223a57275cf40f9bdb7cfbb806bcb7f7cc56e3beb55a576eb" +dependencies = [ + "cfg-if", + "getopts", + "libc", + "num_cpus", + "term", +] + +[[package]] +name = "thiserror" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde", +] + +[[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + +[[package]] +name = "unicode-width" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[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.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[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 = "wyz" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b31594f29d27036c383b53b59ed3476874d518f0efb151b27a4c275141390e" +dependencies = [ + "tap", +] -- GitLab From 8367c5b4988b20fb3c931f1accc6798944cde2bd Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 23 Feb 2022 03:20:35 +0100 Subject: [PATCH 19/42] Move `bool_to_exit_code` inline --- build.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/build.rs b/build.rs index 824d2aa8..1afe3d6b 100644 --- a/build.rs +++ b/build.rs @@ -81,15 +81,12 @@ fn main() { eprintln!("Failed building dylint driver: {:?}", err); std::process::exit(1); }); - std::process::exit(bool_to_exit_code(zipped_template && zipped_lints)); -} -/// Returns the process exit code which corresponds to a boolean. -fn bool_to_exit_code(val: bool) -> i32 { - match val { + let exit_code = match zipped_template && zipped_lints { true => 0, false => 1, - } + }; + std::process::exit(exit_code); } /// Builds the crate in `ink_linting/`. This crate contains the `dylint` driver with ink! specific -- GitLab From 402a28d0ddf5f7bf7b2f6c28929b4c4515e63742 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 23 Feb 2022 03:25:14 +0100 Subject: [PATCH 20/42] Add test for non-fully-qualified path call of `initialize_contract` --- ink_linting/Cargo.toml | 6 ++- .../mapping-dont-use-fully-qualified-path.rs | 53 +++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 ink_linting/ui/pass/mapping-dont-use-fully-qualified-path.rs diff --git a/ink_linting/Cargo.toml b/ink_linting/Cargo.toml index cd85dd40..6cf5e002 100644 --- a/ink_linting/Cargo.toml +++ b/ink_linting/Cargo.toml @@ -70,9 +70,13 @@ name = "pass_mapping_two_constructors" path = "ui/pass/mapping-two-constructors.rs" [[example]] -name = "pass_mapping_03" +name = "pass_mapping_additional_logic_constructor" path = "ui/pass/mapping-additional-logic-constructor.rs" +[[example]] +name = "pass_dont_use_fully_qualified_path" +path = "ui/pass/mapping-dont-use-fully-qualified-path.rs" + [package.metadata.rust-analyzer] rustc_private = true diff --git a/ink_linting/ui/pass/mapping-dont-use-fully-qualified-path.rs b/ink_linting/ui/pass/mapping-dont-use-fully-qualified-path.rs new file mode 100644 index 00000000..0f3c84fd --- /dev/null +++ b/ink_linting/ui/pass/mapping-dont-use-fully-qualified-path.rs @@ -0,0 +1,53 @@ +// Copyright 2018-2022 Parity Technologies (UK) Ltd. +// This file is part of cargo-contract. +// +// cargo-contract is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// cargo-contract is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with cargo-contract. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +use ink_lang as ink; + +#[ink::contract] +mod my_contract { + use ink_storage::{traits::SpreadAllocate, Mapping}; + use ink_lang::utils::initialize_contract as foo; + + #[ink(storage)] + #[derive(SpreadAllocate)] + pub struct MyContract { + balances: Mapping, + } + + impl MyContract { + #[ink(constructor)] + pub fn new() -> Self { + foo(Self::new_init) + } + + /// Default initializes the contract. + fn new_init(&mut self) { + let caller = Self::env().caller(); + let value: Balance = Default::default(); + self.balances.insert(&caller, &value); + } + + /// Returns something. + #[ink(message)] + pub fn get(&self) { + // ... + } + } +} + +fn main() {} -- GitLab From 60287bdcc4fe46a131374d75ba43bd7245e77d7e Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 23 Feb 2022 03:43:45 +0100 Subject: [PATCH 21/42] Fix panic when no manifest path was supplied --- src/cmd/build.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index ba7ce772..01929e0d 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -304,7 +304,7 @@ fn exec_cargo_for_wasm_target( /// We create a temporary folder, extract the linting driver there and run /// `cargo dylint` with it. fn exec_cargo_dylint(crate_metadata: &CrateMetadata, verbosity: Verbosity) -> Result<()> { - check_dylint_requirements(crate_metadata.manifest_path.directory().unwrap())?; + check_dylint_requirements(crate_metadata.manifest_path.directory())?; let tmp_dir = tempfile::Builder::new() .prefix("cargo-contract-dylint_") @@ -347,17 +347,19 @@ fn exec_cargo_dylint(crate_metadata: &CrateMetadata, verbosity: Verbosity) -> Re } /// Checks if all requirements for `dylint` are installed. +/// The requirements are an installed version of `cargo-dylint` and `dylint-link`. /// -/// Those are an installed version of `cargo-dylint` and `dylint-link`. -fn check_dylint_requirements(_working_dir: &Path) -> Result<()> { +/// This function takes a `_working_dir` which is only used for unit tests. +fn check_dylint_requirements(_working_dir: Option<&Path>) -> Result<()> { let execute_cmd = |cmd: &mut Command| { // when testing this function we set the `PATH` to the `working_dir` // so that we can have mocked binaries in there which are executed // instead of the real ones. #[cfg(test)] { + let working_dir = _working_dir.unwrap_or_else(|| PathBuf::from(".").as_path()); let path_env = std::env::var("PATH").unwrap(); - let path_env = format!("{}:{}", _working_dir.to_string_lossy(), path_env); + let path_env = format!("{}:{}", working_dir.to_string_lossy(), path_env); cmd.env("PATH", path_env); } -- GitLab From d0071eea885f9705ca1d11dfa010c0549ccdfb7b Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 23 Feb 2022 04:23:59 +0100 Subject: [PATCH 22/42] Improve structure of `build.rs` --- build.rs | 113 +++++++++++++++++++++++------------------------ src/cmd/build.rs | 6 ++- 2 files changed, 61 insertions(+), 58 deletions(-) diff --git a/build.rs b/build.rs index 1afe3d6b..cb702168 100644 --- a/build.rs +++ b/build.rs @@ -35,64 +35,66 @@ use substrate_build_script_utils::rerun_if_git_head_changed; const DEFAULT_UNIX_PERMISSIONS: u32 = 0o755; fn main() { + generate_cargo_keys(); + rerun_if_git_head_changed(); + let manifest_dir: PathBuf = env::var("CARGO_MANIFEST_DIR") .expect("CARGO_MANIFEST_DIR should be set by cargo") .into(); let out_dir: PathBuf = env::var("OUT_DIR") .expect("OUT_DIR should be set by cargo") .into(); + let res = zip_template_and_build_dylint_driver(manifest_dir, out_dir); - generate_cargo_keys(); - rerun_if_git_head_changed(); + match res { + Ok(()) => std::process::exit(0), + Err(err) => { + eprintln!("Encountered error: {:?}", err); + std::process::exit(1) + } + } +} - let template_dir = manifest_dir.join("templates").join("new"); - let template_dst_file = out_dir.join("template.zip"); - println!( - "Creating template zip: template_dir '{}', destination archive '{}'", - template_dir.display(), - template_dst_file.display() - ); - let zipped_template = - match zip_dir(&template_dir, &template_dst_file, CompressionMethod::Stored) { - Ok(_) => { - println!( - "done: {} written to {}", - template_dir.display(), - template_dst_file.display() - ); - true - } - Err(e) => { - eprintln!("Error: {:?}", e); - false - } - }; - - check_dylint_link_installed(); +/// This method: +/// * Creates a zip archive of the `new` project template. +/// * Builds the `dylint` driver found in `ink_linting`, the compiled +/// driver is put into a zip archive as well. +fn zip_template_and_build_dylint_driver(manifest_dir: PathBuf, out_dir: PathBuf) -> Result<()> { + zip_template(&manifest_dir, &out_dir)?; + + check_dylint_link_installed()?; // This zip file will contain the `dylint` driver, this is one file named in the form of // `libink_linting@nightly-2021-11-04-x86_64-unknown-linux-gnu.so`. This file is obtained // by building the crate in `ink_linting/`. let dylint_driver_dst_file = out_dir.join("ink-dylint-driver.zip"); + build_and_zip_dylint_driver(manifest_dir, out_dir, dylint_driver_dst_file)?; - let zipped_lints = build_dylint_driver(manifest_dir, out_dir, dylint_driver_dst_file) - .map(|_| true) - .unwrap_or_else(|err| { - eprintln!("Failed building dylint driver: {:?}", err); - std::process::exit(1); - }); + Ok(()) +} - let exit_code = match zipped_template && zipped_lints { - true => 0, - false => 1, - }; - std::process::exit(exit_code); +/// Creates a zip archive `template.zip` of the `new` project template in `out_dir`. +fn zip_template(manifest_dir: &Path, out_dir: &Path) -> Result<()> { + let template_dir = manifest_dir.join("templates").join("new"); + let template_dst_file = out_dir.join("template.zip"); + println!( + "Creating template zip: template_dir '{}', destination archive '{}'", + template_dir.display(), + template_dst_file.display() + ); + zip_dir(&template_dir, &template_dst_file, CompressionMethod::Stored).map(|_| { + println!( + "Done: {} written to {}", + template_dir.display(), + template_dst_file.display() + ); + }) } /// Builds the crate in `ink_linting/`. This crate contains the `dylint` driver with ink! specific /// linting rules. #[cfg(feature = "cargo-clippy")] -fn build_dylint_driver( +fn build_and_zip_dylint_driver( _manifest_dir: PathBuf, _out_dir: PathBuf, dylint_driver_dst_file: PathBuf, @@ -115,7 +117,7 @@ fn build_dylint_driver( /// Builds the crate in `ink_linting/`. This crate contains the `dylint` driver with ink! specific /// linting rules. #[cfg(not(feature = "cargo-clippy"))] -fn build_dylint_driver( +fn build_and_zip_dylint_driver( manifest_dir: PathBuf, out_dir: PathBuf, dylint_driver_dst_file: PathBuf, @@ -165,24 +167,19 @@ fn build_dylint_driver( dylint_driver_dst_file.display() ); - match zip_dylint_driver( + zip_dylint_driver( &out_dir.join("release"), &dylint_driver_dst_file, CompressionMethod::Stored, - ) { - Ok(_) => { - println!( - "done: {} written to {}", - ink_dylint_driver_dir.display(), - dylint_driver_dst_file.display() - ); - Ok(()) - } - Err(e) => { - eprintln!("Error: {:?}", e); - Err(e) - } - } + ) + .map(|_| { + println!( + "Done: {} written to {}", + ink_dylint_driver_dir.display(), + dylint_driver_dst_file.display() + ); + () + }) } /// Creates a zip archive at `dst_file` with the content of the `src_dir`. @@ -327,7 +324,9 @@ fn get_platform() -> String { ) } -fn check_dylint_link_installed() { +/// Checks if `dylint-link` is installed, i.e. if the `dylint-link` executable +/// can be executed with a `--version` argument. +fn check_dylint_link_installed() -> Result<()> { let execute_cmd = |cmd: &mut Command| { cmd.stdout(std::process::Stdio::null()) .stderr(std::process::Stdio::null()) @@ -346,11 +345,11 @@ fn check_dylint_link_installed() { let res = execute_cmd(Command::new("dylint-link").arg("--version")); if res.is_err() || !res.expect("the `or` case will always will be `Ok`") { - eprintln!( + anyhow::bail!( "dylint-link was not found!\n\ Make sure it is installed and the binary is in your PATH environment.\n\n\ You can install it by executing `cargo install dylint-link`." ); - std::process::exit(1); } + Ok(()) } diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 01929e0d..f1aff89a 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -347,7 +347,11 @@ fn exec_cargo_dylint(crate_metadata: &CrateMetadata, verbosity: Verbosity) -> Re } /// Checks if all requirements for `dylint` are installed. -/// The requirements are an installed version of `cargo-dylint` and `dylint-link`. +/// +/// We require only an installed version of `cargo-dylint` here and don't +/// check for an installed version of `dylint-link`. This is because +/// `dylint-link` is only required for the `dylint` driver build process +/// in `build.rs`. /// /// This function takes a `_working_dir` which is only used for unit tests. fn check_dylint_requirements(_working_dir: Option<&Path>) -> Result<()> { -- GitLab From 87289ed43872f5e1007261c36fda3c69b4e14f33 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 23 Feb 2022 04:38:28 +0100 Subject: [PATCH 23/42] Make linting error message non-blaming --- ink_linting/src/mapping_initialized.rs | 4 ++-- ink_linting/ui/fail/mapping-nested-initialize-call.stderr | 4 ++-- ink_linting/ui/fail/mapping-one-constructor.stderr | 4 ++-- ink_linting/ui/fail/mapping-two-constructors-01.stderr | 4 ++-- ink_linting/ui/fail/mapping-two-constructors-02.stderr | 4 ++-- ink_linting/ui/pass/mapping-dont-use-fully-qualified-path.rs | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/ink_linting/src/mapping_initialized.rs b/ink_linting/src/mapping_initialized.rs index a684ccc5..bc2bb4a3 100644 --- a/ink_linting/src/mapping_initialized.rs +++ b/ink_linting/src/mapping_initialized.rs @@ -191,7 +191,7 @@ fn check_struct<'a>(cx: &LateContext<'a>, item: &'a Item, data: &VariantData) { MAPPING_INITIALIZED, item.span, &format!( - "you have declared an `#[ink(storage)]` on `{}` without initializing it in the contract constructor.", + "`#[ink(storage)]` on `{}` contains `ink_storage::Mapping` without initializing it in the contract constructor.", item.ident ), |diag| { @@ -201,7 +201,7 @@ fn check_struct<'a>(cx: &LateContext<'a>, item: &'a Item, data: &VariantData) { snippet, Applicability::Unspecified, ); - diag.span_help(marker.expect("marker must exist").span, "this field uses a `Mapping`"); + diag.span_help(marker.expect("marker must exist").span, "this field uses `ink_storage::Mapping`"); }); } } diff --git a/ink_linting/ui/fail/mapping-nested-initialize-call.stderr b/ink_linting/ui/fail/mapping-nested-initialize-call.stderr index cd11d830..2bce8d28 100644 --- a/ink_linting/ui/fail/mapping-nested-initialize-call.stderr +++ b/ink_linting/ui/fail/mapping-nested-initialize-call.stderr @@ -1,4 +1,4 @@ -error: you have declared an `#[ink(storage)]` on `MyContract` without initializing it in the contract constructor. +error: `#[ink(storage)]` on `MyContract` contains `ink_storage::Mapping` without initializing it in the contract constructor. --> $DIR/mapping-nested-initialize-call.rs:26:5 | LL | / #[derive(SpreadAllocate)] @@ -8,7 +8,7 @@ LL | | } | |_____^ | = note: `#[deny(mapping_initialized)]` on by default -help: this field uses a `Mapping` +help: this field uses `ink_storage::Mapping` --> $DIR/mapping-nested-initialize-call.rs:28:9 | LL | balances: Mapping, diff --git a/ink_linting/ui/fail/mapping-one-constructor.stderr b/ink_linting/ui/fail/mapping-one-constructor.stderr index 8e0a4d8a..c8f71934 100644 --- a/ink_linting/ui/fail/mapping-one-constructor.stderr +++ b/ink_linting/ui/fail/mapping-one-constructor.stderr @@ -1,4 +1,4 @@ -error: you have declared an `#[ink(storage)]` on `MyContract` without initializing it in the contract constructor. +error: `#[ink(storage)]` on `MyContract` contains `ink_storage::Mapping` without initializing it in the contract constructor. --> $DIR/mapping-one-constructor.rs:26:5 | LL | / #[derive(SpreadAllocate)] @@ -8,7 +8,7 @@ LL | | } | |_____^ | = note: `#[deny(mapping_initialized)]` on by default -help: this field uses a `Mapping` +help: this field uses `ink_storage::Mapping` --> $DIR/mapping-one-constructor.rs:28:9 | LL | balances: Mapping, diff --git a/ink_linting/ui/fail/mapping-two-constructors-01.stderr b/ink_linting/ui/fail/mapping-two-constructors-01.stderr index d174f423..4ce04088 100644 --- a/ink_linting/ui/fail/mapping-two-constructors-01.stderr +++ b/ink_linting/ui/fail/mapping-two-constructors-01.stderr @@ -1,4 +1,4 @@ -error: you have declared an `#[ink(storage)]` on `MyContract` without initializing it in the contract constructor. +error: `#[ink(storage)]` on `MyContract` contains `ink_storage::Mapping` without initializing it in the contract constructor. --> $DIR/mapping-two-constructors-01.rs:26:5 | LL | / #[derive(SpreadAllocate)] @@ -8,7 +8,7 @@ LL | | } | |_____^ | = note: `#[deny(mapping_initialized)]` on by default -help: this field uses a `Mapping` +help: this field uses `ink_storage::Mapping` --> $DIR/mapping-two-constructors-01.rs:28:9 | LL | balances: Mapping, diff --git a/ink_linting/ui/fail/mapping-two-constructors-02.stderr b/ink_linting/ui/fail/mapping-two-constructors-02.stderr index ff42f1f5..982f01e4 100644 --- a/ink_linting/ui/fail/mapping-two-constructors-02.stderr +++ b/ink_linting/ui/fail/mapping-two-constructors-02.stderr @@ -1,4 +1,4 @@ -error: you have declared an `#[ink(storage)]` on `MyContract` without initializing it in the contract constructor. +error: `#[ink(storage)]` on `MyContract` contains `ink_storage::Mapping` without initializing it in the contract constructor. --> $DIR/mapping-two-constructors-02.rs:26:5 | LL | / #[derive(SpreadAllocate)] @@ -8,7 +8,7 @@ LL | | } | |_____^ | = note: `#[deny(mapping_initialized)]` on by default -help: this field uses a `Mapping` +help: this field uses `ink_storage::Mapping` --> $DIR/mapping-two-constructors-02.rs:28:9 | LL | balances: Mapping, diff --git a/ink_linting/ui/pass/mapping-dont-use-fully-qualified-path.rs b/ink_linting/ui/pass/mapping-dont-use-fully-qualified-path.rs index 0f3c84fd..c56c189d 100644 --- a/ink_linting/ui/pass/mapping-dont-use-fully-qualified-path.rs +++ b/ink_linting/ui/pass/mapping-dont-use-fully-qualified-path.rs @@ -20,8 +20,8 @@ use ink_lang as ink; #[ink::contract] mod my_contract { - use ink_storage::{traits::SpreadAllocate, Mapping}; use ink_lang::utils::initialize_contract as foo; + use ink_storage::{traits::SpreadAllocate, Mapping}; #[ink(storage)] #[derive(SpreadAllocate)] -- GitLab From 1fc817c5de6c01428afc2a78217718d836630fce Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 23 Feb 2022 04:39:30 +0100 Subject: [PATCH 24/42] Remove incorrect note on not detecting indirections --- ink_linting/src/mapping_initialized.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/ink_linting/src/mapping_initialized.rs b/ink_linting/src/mapping_initialized.rs index bc2bb4a3..12b9d09d 100644 --- a/ink_linting/src/mapping_initialized.rs +++ b/ink_linting/src/mapping_initialized.rs @@ -302,9 +302,6 @@ impl<'tcx> Visitor<'tcx> for InkAttributeVisitor<'_, 'tcx> { /// on the first level of the `fn` ‒ no nested calls are found! So if you would /// call `initialize_contract` within a sub-function of the ink! constructor /// this is not recognized! -/// -/// Also the function call must be explicitly called `ink_lang::utils::initialize_contract(…)`, -/// the linter currently does not detected indirections. struct InitializeContractVisitor<'a, 'tcx> { cx: &'a LateContext<'tcx>, uses_initialize_contract: bool, -- GitLab From 16d77c61608fe07571ed97b15f4625e32ed822f1 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 23 Feb 2022 04:52:44 +0100 Subject: [PATCH 25/42] Make `clippy` happy --- src/cmd/build.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index f1aff89a..681b877c 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -361,7 +361,8 @@ fn check_dylint_requirements(_working_dir: Option<&Path>) -> Result<()> { // instead of the real ones. #[cfg(test)] { - let working_dir = _working_dir.unwrap_or_else(|| PathBuf::from(".").as_path()); + let default_dir = PathBuf::from("."); + let working_dir = _working_dir.unwrap_or(default_dir.as_path()); let path_env = std::env::var("PATH").unwrap(); let path_env = format!("{}:{}", working_dir.to_string_lossy(), path_env); cmd.env("PATH", path_env); -- GitLab From 98d25436959c53ff4ea6d736649257207bd9e839 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 23 Feb 2022 04:57:19 +0100 Subject: [PATCH 26/42] Impprove text --- src/cmd/build.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 681b877c..2f093851 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -547,7 +547,7 @@ fn do_optimization( let which = which::which("wasm-opt"); if which.is_err() { anyhow::bail!( - "wasm-opt not found! Make sure the binary is in your PATH environment.\n\ + "wasm-opt not found! Make sure the binary is in your PATH environment.\n\n\ We use this tool to optimize the size of your contract's Wasm binary.\n\n\ wasm-opt is part of the binaryen package. You can find detailed\n\ installation instructions on https://github.com/WebAssembly/binaryen#tools.\n\n\ @@ -562,7 +562,7 @@ fn do_optimization( } let wasm_opt_path = which .as_ref() - .expect("we just checked if which returned an err; qed") + .expect("we just checked if `which` returned an err; qed") .as_path(); log::info!("Path to wasm-opt executable: {}", wasm_opt_path.display()); -- GitLab From b1be397afea5d2abc5b7e69d538b7792968995f9 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 23 Feb 2022 05:16:43 +0100 Subject: [PATCH 27/42] Build `ink_linting` with `--locked` --- build.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/build.rs b/build.rs index cb702168..6d67c888 100644 --- a/build.rs +++ b/build.rs @@ -131,7 +131,13 @@ fn build_and_zip_dylint_driver( ink_dylint_driver_dir.join("Cargo.toml").display() ); let target_dir = format!("--target-dir={}", out_dir.display()); - cmd.args(vec!["build", "--release", &target_dir, &manifest_arg]); + cmd.args(vec![ + "build", + "--release", + "--locked", + &target_dir, + &manifest_arg, + ]); // We need to remove those environment variables because `dylint` uses a // fixed Rust toolchain via the `ink_linting/rust-toolchain` file. By removing -- GitLab From b59983137305eeb2df68c38696f13bccfd849ba4 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 23 Feb 2022 05:17:48 +0100 Subject: [PATCH 28/42] Fix path separators for Windows CI --- .github/workflows/windows.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index ada95c81..6abe3c73 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -68,10 +68,10 @@ jobs: cargo dylint --version cargo run -- contract --version cargo run -- contract new foobar - echo "[workspace]" >> foobar/Cargo.toml - cargo run -- contract build --manifest-path=foobar/Cargo.toml - cargo run -- contract check --manifest-path=foobar/Cargo.toml - cargo run -- contract test --manifest-path=foobar/Cargo.toml + echo "[workspace]" >> foobar\Cargo.toml + cargo run -- contract build --manifest-path=foobar\Cargo.toml + cargo run -- contract check --manifest-path=foobar\Cargo.toml + cargo run -- contract test --manifest-path=foobar\Cargo.toml # This stage has to be deactivated until https://github.com/Vurich/crunchy/pull/10 # is merged and released. -- GitLab From 892f459e1f5b92f0acbb25c4f16fe2d2783d5ee7 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 23 Feb 2022 05:30:44 +0100 Subject: [PATCH 29/42] Revert "Fix path separators for Windows CI" This reverts commit b59983137305eeb2df68c38696f13bccfd849ba4. --- .github/workflows/windows.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 6abe3c73..ada95c81 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -68,10 +68,10 @@ jobs: cargo dylint --version cargo run -- contract --version cargo run -- contract new foobar - echo "[workspace]" >> foobar\Cargo.toml - cargo run -- contract build --manifest-path=foobar\Cargo.toml - cargo run -- contract check --manifest-path=foobar\Cargo.toml - cargo run -- contract test --manifest-path=foobar\Cargo.toml + echo "[workspace]" >> foobar/Cargo.toml + cargo run -- contract build --manifest-path=foobar/Cargo.toml + cargo run -- contract check --manifest-path=foobar/Cargo.toml + cargo run -- contract test --manifest-path=foobar/Cargo.toml # This stage has to be deactivated until https://github.com/Vurich/crunchy/pull/10 # is merged and released. -- GitLab From 03a5fbab79b498bf23f5bb7d250c3284cca67750 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 23 Feb 2022 05:33:09 +0100 Subject: [PATCH 30/42] Revert me: Debug failing Windows CI --- build.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/build.rs b/build.rs index 6d67c888..f81592da 100644 --- a/build.rs +++ b/build.rs @@ -350,6 +350,7 @@ fn check_dylint_link_installed() -> Result<()> { }; let res = execute_cmd(Command::new("dylint-link").arg("--version")); + eprintln!("res: {:?}", res); if res.is_err() || !res.expect("the `or` case will always will be `Ok`") { anyhow::bail!( "dylint-link was not found!\n\ -- GitLab From 78db3f5ed27e2c730ef6670f30e6f6f802d91c0b Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 23 Feb 2022 05:45:44 +0100 Subject: [PATCH 31/42] Revert me: Debug failing Windows CI --- build.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/build.rs b/build.rs index f81592da..6216ef58 100644 --- a/build.rs +++ b/build.rs @@ -341,8 +341,15 @@ fn check_dylint_link_installed() -> Result<()> { eprintln!("Error spawning `{:?}`", cmd); err })? - .wait() - .map(|res| res.success()) + .wait_with_output() + .map(|res| { + let output = format!( + "{}", + std::str::from_utf8(&res.stdout).expect("conversion must work") + ); + eprintln!("output: {:?}", output); + res.status.success() + }) .map_err(|err| { eprintln!("Error waiting for `{:?}`: {:?}", cmd, err); err -- GitLab From 7a26bc986b1fdc62ca0af7762c8697116f41c1a7 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 23 Feb 2022 05:57:17 +0100 Subject: [PATCH 32/42] Revert me: Debug failing Windows CI --- .github/workflows/windows.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index ada95c81..c5238f9b 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -63,6 +63,8 @@ jobs: - name: Build contract template on ${{ matrix.platform }}-${{ matrix.toolchain }} run: | + dylint-link + dylint-link --version wasm-opt --version cargo -vV cargo dylint --version -- GitLab From cea5ab5c84fcd7b3bb91c2f15e3ada8b4c659afe Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 23 Feb 2022 06:50:18 +0100 Subject: [PATCH 33/42] Revert me: Debug failing Windows CI --- .github/workflows/windows.yml | 4 ++-- build.rs | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index c5238f9b..649e962b 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -63,8 +63,8 @@ jobs: - name: Build contract template on ${{ matrix.platform }}-${{ matrix.toolchain }} run: | - dylint-link - dylint-link --version + RUSTUP_TOOLCHAIN=nightly dylint-link + RUSTUP_TOOLCHAIN=nightly dylint-link --version wasm-opt --version cargo -vV cargo dylint --version diff --git a/build.rs b/build.rs index 6216ef58..d042d8e6 100644 --- a/build.rs +++ b/build.rs @@ -143,6 +143,7 @@ fn build_and_zip_dylint_driver( // fixed Rust toolchain via the `ink_linting/rust-toolchain` file. By removing // these env variables we avoid issues with different Rust toolchains // interfering with each other. + #[cfg(not(windows))] cmd.env_remove("RUSTUP_TOOLCHAIN"); cmd.env_remove("CARGO_TARGET_DIR"); @@ -343,10 +344,7 @@ fn check_dylint_link_installed() -> Result<()> { })? .wait_with_output() .map(|res| { - let output = format!( - "{}", - std::str::from_utf8(&res.stdout).expect("conversion must work") - ); + let output = std::str::from_utf8(&res.stdout).expect("conversion must work"); eprintln!("output: {:?}", output); res.status.success() }) -- GitLab From 14af20ef91c50be6cd8e1225936fbfd9d3a60d9f Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 23 Feb 2022 06:53:26 +0100 Subject: [PATCH 34/42] Revert me: Debug failing Windows CI --- .github/workflows/windows.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 649e962b..d7440e45 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -62,9 +62,11 @@ jobs: uses: Swatinem/rust-cache@v1.3.0 - name: Build contract template on ${{ matrix.platform }}-${{ matrix.toolchain }} + env: + RUSTUP_TOOLCHAIN: "nightly" run: | - RUSTUP_TOOLCHAIN=nightly dylint-link - RUSTUP_TOOLCHAIN=nightly dylint-link --version + dylint-link + dylint-link --version wasm-opt --version cargo -vV cargo dylint --version -- GitLab From f60e68282bb3b951f5502b18027636b3285e79cb Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 23 Feb 2022 08:21:25 +0100 Subject: [PATCH 35/42] Revert me: Debug failing Windows CI --- .github/workflows/windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index d7440e45..42069573 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -63,7 +63,7 @@ jobs: - name: Build contract template on ${{ matrix.platform }}-${{ matrix.toolchain }} env: - RUSTUP_TOOLCHAIN: "nightly" + RUSTUP_TOOLCHAIN: "nightly-x86_64-pc-windows-msvc" run: | dylint-link dylint-link --version -- GitLab From 29b27a2732d9b7bf6c0f86276e6820af5a0fc8e6 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 23 Feb 2022 09:00:14 +0100 Subject: [PATCH 36/42] Revert me: Debug failing Windows CI --- build.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.rs b/build.rs index d042d8e6..f71ba257 100644 --- a/build.rs +++ b/build.rs @@ -143,7 +143,6 @@ fn build_and_zip_dylint_driver( // fixed Rust toolchain via the `ink_linting/rust-toolchain` file. By removing // these env variables we avoid issues with different Rust toolchains // interfering with each other. - #[cfg(not(windows))] cmd.env_remove("RUSTUP_TOOLCHAIN"); cmd.env_remove("CARGO_TARGET_DIR"); @@ -335,6 +334,8 @@ fn get_platform() -> String { /// can be executed with a `--version` argument. fn check_dylint_link_installed() -> Result<()> { let execute_cmd = |cmd: &mut Command| { + #[cfg(windows)] + cmd.env("RUSTUP_TOOLCHAIN", "nightly-x86_64-pc-windows-msvc"); cmd.stdout(std::process::Stdio::null()) .stderr(std::process::Stdio::null()) .spawn() -- GitLab From 81bde92d823ebfb6c352d5c5a70cd5c45fa4ba42 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 23 Feb 2022 09:07:05 +0100 Subject: [PATCH 37/42] Use `which` for detecting `dylint-link` installation --- .github/workflows/windows.yml | 4 ---- Cargo.toml | 1 + build.rs | 27 ++------------------------- 3 files changed, 3 insertions(+), 29 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 42069573..ada95c81 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -62,11 +62,7 @@ jobs: uses: Swatinem/rust-cache@v1.3.0 - name: Build contract template on ${{ matrix.platform }}-${{ matrix.toolchain }} - env: - RUSTUP_TOOLCHAIN: "nightly-x86_64-pc-windows-msvc" run: | - dylint-link - dylint-link --version wasm-opt --version cargo -vV cargo dylint --version diff --git a/Cargo.toml b/Cargo.toml index 1abbdfd7..2e3d43f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,6 +67,7 @@ zip = { version = "0.5.13", default-features = false } walkdir = "2.3.2" substrate-build-script-utils = "3.0.0" platforms = "2.0.0" +which = "4.2.4" [dev-dependencies] assert_cmd = "2.0.4" diff --git a/build.rs b/build.rs index f71ba257..be646624 100644 --- a/build.rs +++ b/build.rs @@ -333,31 +333,8 @@ fn get_platform() -> String { /// Checks if `dylint-link` is installed, i.e. if the `dylint-link` executable /// can be executed with a `--version` argument. fn check_dylint_link_installed() -> Result<()> { - let execute_cmd = |cmd: &mut Command| { - #[cfg(windows)] - cmd.env("RUSTUP_TOOLCHAIN", "nightly-x86_64-pc-windows-msvc"); - cmd.stdout(std::process::Stdio::null()) - .stderr(std::process::Stdio::null()) - .spawn() - .map_err(|err| { - eprintln!("Error spawning `{:?}`", cmd); - err - })? - .wait_with_output() - .map(|res| { - let output = std::str::from_utf8(&res.stdout).expect("conversion must work"); - eprintln!("output: {:?}", output); - res.status.success() - }) - .map_err(|err| { - eprintln!("Error waiting for `{:?}`: {:?}", cmd, err); - err - }) - }; - - let res = execute_cmd(Command::new("dylint-link").arg("--version")); - eprintln!("res: {:?}", res); - if res.is_err() || !res.expect("the `or` case will always will be `Ok`") { + let which = which::which("dylint-link"); + if which.is_err() { anyhow::bail!( "dylint-link was not found!\n\ Make sure it is installed and the binary is in your PATH environment.\n\n\ -- GitLab From d0d209fe60972fa9d242767079423c0b9913f3f0 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 23 Feb 2022 15:24:00 +0100 Subject: [PATCH 38/42] Remove `DYLINT_DRIVER_PATH` --- src/cmd/build.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 2f093851..50dc1831 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -319,7 +319,6 @@ fn exec_cargo_dylint(crate_metadata: &CrateMetadata, verbosity: Verbosity) -> Re let tmp_dir_path = tmp_dir.path().as_os_str().to_string_lossy(); let env = vec![ ("DYLINT_LIBRARY_PATH", Some(tmp_dir_path.as_ref())), - ("DYLINT_DRIVER_PATH", Some(tmp_dir_path.as_ref())), // We need to remove the `CARGO_TARGET_DIR` environment variable in // case `cargo dylint` is invoked. // -- GitLab From 0ea941711793c442f3db4f94e8c8cdfcb17808dd Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 23 Feb 2022 15:24:58 +0100 Subject: [PATCH 39/42] Add `--lib` --- src/cmd/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 50dc1831..5887fcbb 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -315,7 +315,7 @@ fn exec_cargo_dylint(crate_metadata: &CrateMetadata, verbosity: Verbosity) -> Re crate::util::unzip(template, tmp_dir.path().to_path_buf(), None)?; let manifest_path = crate_metadata.manifest_path.cargo_arg()?; - let args = vec!["ink_linting", &manifest_path]; + let args = vec!["--lib", "ink_linting", &manifest_path]; let tmp_dir_path = tmp_dir.path().as_os_str().to_string_lossy(); let env = vec![ ("DYLINT_LIBRARY_PATH", Some(tmp_dir_path.as_ref())), -- GitLab From a00c562bca499f70de99151f9596219a2c261f81 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 23 Feb 2022 17:12:02 +0100 Subject: [PATCH 40/42] Revert "Remove `DYLINT_DRIVER_PATH`" This reverts commit d0d209fe60972fa9d242767079423c0b9913f3f0. --- src/cmd/build.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 5887fcbb..e9736e65 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -319,6 +319,7 @@ fn exec_cargo_dylint(crate_metadata: &CrateMetadata, verbosity: Verbosity) -> Re let tmp_dir_path = tmp_dir.path().as_os_str().to_string_lossy(); let env = vec![ ("DYLINT_LIBRARY_PATH", Some(tmp_dir_path.as_ref())), + ("DYLINT_DRIVER_PATH", Some(tmp_dir_path.as_ref())), // We need to remove the `CARGO_TARGET_DIR` environment variable in // case `cargo dylint` is invoked. // -- GitLab From 959eb446c524f39f1d9326f3c67b7cd3d0330a4f Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 23 Feb 2022 17:14:22 +0100 Subject: [PATCH 41/42] Use temporary `DYLINT_DRIVER_PATH` path during tests --- src/cmd/build.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index e9736e65..2556a7b1 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -319,6 +319,10 @@ fn exec_cargo_dylint(crate_metadata: &CrateMetadata, verbosity: Verbosity) -> Re let tmp_dir_path = tmp_dir.path().as_os_str().to_string_lossy(); let env = vec![ ("DYLINT_LIBRARY_PATH", Some(tmp_dir_path.as_ref())), + // For tests we need to set the `DYLINT_DRIVER_PATH` to a tmp folder, + // otherwise tests running in parallel will try to write to the same + // file at the same time which will result in a `Text file busy` error. + #[cfg(test)] ("DYLINT_DRIVER_PATH", Some(tmp_dir_path.as_ref())), // We need to remove the `CARGO_TARGET_DIR` environment variable in // case `cargo dylint` is invoked. -- GitLab From d417899456c9df3a66e81f02fb14b15c3c2c267a Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Wed, 23 Feb 2022 17:15:31 +0100 Subject: [PATCH 42/42] Give `template` variable a speaking name --- src/cmd/build.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 2556a7b1..f0136753 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -311,8 +311,8 @@ fn exec_cargo_dylint(crate_metadata: &CrateMetadata, verbosity: Verbosity) -> Re .tempdir()?; log::debug!("Using temp workspace at '{}'", tmp_dir.path().display()); - let template = include_bytes!(concat!(env!("OUT_DIR"), "/ink-dylint-driver.zip")); - crate::util::unzip(template, tmp_dir.path().to_path_buf(), None)?; + let driver = include_bytes!(concat!(env!("OUT_DIR"), "/ink-dylint-driver.zip")); + crate::util::unzip(driver, tmp_dir.path().to_path_buf(), None)?; let manifest_path = crate_metadata.manifest_path.cargo_arg()?; let args = vec!["--lib", "ink_linting", &manifest_path]; -- GitLab