diff --git a/Cargo.lock b/Cargo.lock index 4999ce711da48f57a05a91c48aa0931bc74a68a1..03b037a421505f885a68b4aef9ead1292bf22859 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,19 +27,13 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -[[package]] -name = "ahash" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217" - [[package]] name = "ahash" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "getrandom 0.2.4", + "getrandom 0.2.3", "once_cell", "version_check", ] @@ -53,24 +47,13 @@ dependencies = [ "memchr", ] -[[package]] -name = "alga" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f823d037a7ec6ea2197046bafd4ae150e6bc36f9ca347404f46a46823fa84f2" -dependencies = [ - "approx", - "num-complex", - "num-traits", -] - [[package]] name = "ansi_term" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -80,13 +63,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94a45b455c14666b85fc40a019e8ab9eb75e3a124e05494f5397122bc9eb06e0" [[package]] -name = "approx" -version = "0.3.2" +name = "array-init" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3" -dependencies = [ - "num-traits", -] +checksum = "6945cc5422176fc5e602e590c2878d2c2acd9a4fe20a4baa7c28022521698ec6" [[package]] name = "arrayref" @@ -115,12 +95,36 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +[[package]] +name = "assert_cmd" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93ae1ddd39efd67689deb1979d80bad3bf7f2b09c6e6117c8d1f2443b5e2f83e" +dependencies = [ + "bstr", + "doc-comment", + "predicates", + "predicates-core", + "predicates-tree", + "wait-timeout", +] + [[package]] name = "assert_matches" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" +[[package]] +name = "async-attributes" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" +dependencies = [ + "quote", + "syn", +] + [[package]] name = "async-channel" version = "1.6.1" @@ -160,6 +164,7 @@ dependencies = [ "futures-lite", "num_cpus", "once_cell", + "tokio", ] [[package]] @@ -176,9 +181,9 @@ dependencies = [ "parking", "polling", "slab", - "socket2 0.4.2", + "socket2", "waker-fn", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -205,6 +210,7 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8056f1455169ab86dd47b47391e4ab0cbd25410a70e9fe675544f49bafaf952" dependencies = [ + "async-attributes", "async-channel", "async-global-executor", "async-io", @@ -220,7 +226,7 @@ dependencies = [ "memchr", "num_cpus", "once_cell", - "pin-project-lite 0.2.8", + "pin-project-lite", "pin-utils", "slab", "wasm-bindgen-futures", @@ -233,15 +239,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0" [[package]] -name = "async-tls" -version = "0.6.0" +name = "async-trait" +version = "0.1.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce6977f57fa68da77ffe5542950d47e9c23d65f5bc7cb0a9f8700996913eec7" +checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" dependencies = [ - "futures", - "rustls", - "webpki", - "webpki-roots", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -258,15 +263,9 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi", "libc", - "winapi 0.3.9", + "winapi", ] -[[package]] -name = "autocfg" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" - [[package]] name = "autocfg" version = "1.0.1" @@ -281,7 +280,7 @@ checksum = "321629d8ba6513061f26707241fa9bc89524ff1cd7a915a97ef0c62c666ce1b6" dependencies = [ "addr2line", "cc", - "cfg-if 1.0.0", + "cfg-if", "libc", "miniz_oxide", "object", @@ -290,24 +289,24 @@ dependencies = [ [[package]] name = "base58" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" +checksum = "6107fe1be6682a68940da878d9e9f5e90ca5745b3dec9fd1bb393c8777d4f581" [[package]] name = "base64" -version = "0.10.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -dependencies = [ - "byteorder", -] +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] -name = "base64" -version = "0.11.0" +name = "beef" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" +checksum = "bed554bd50246729a1ec158d08aa3235d1b69d94ad120ebe187e28894787e736" +dependencies = [ + "serde", +] [[package]] name = "bitflags" @@ -315,30 +314,14 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "bitmask" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5da9b3d9f6f585199287a473f4f8dfab6566cf827d15c00c219f53c645687ead" - -[[package]] -name = "bitvec" -version = "0.17.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41262f11d771fd4a61aa3ce019fca363b4b6c282fca9da2a31186d3965a47a5c" -dependencies = [ - "either", - "radium 0.3.0", -] - [[package]] name = "bitvec" version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7774144344a4faa177370406a7ff5f1da24303817368584c6206c8303eb07848" dependencies = [ - "funty 1.1.0", - "radium 0.6.2", + "funty", + "radium", "tap", "wyz", ] @@ -380,7 +363,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "generic-array 0.14.5", + "generic-array 0.14.4", ] [[package]] @@ -389,7 +372,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1d36a02058e76b040de25a4464ba1c80935655595b661505c8b39b664828b95" dependencies = [ - "generic-array 0.14.5", + "generic-array 0.14.4", ] [[package]] @@ -416,10 +399,13 @@ dependencies = [ ] [[package]] -name = "bs58" -version = "0.3.1" +name = "brownstone" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb" +checksum = "030ea61398f34f1395ccbeb046fb68c87b631d1f34567fed0f0f11fa35d18d8d" +dependencies = [ + "arrayvec 0.7.2", +] [[package]] name = "bstr" @@ -427,20 +413,17 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" dependencies = [ + "lazy_static", "memchr", + "regex-automata", + "serde", ] [[package]] name = "bumpalo" -version = "3.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" - -[[package]] -name = "byte-slice-cast" -version = "0.3.5" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0a5e3906bcbf133e33c1d4d95afc664ad37fbdb9f6568d8043e7ea8c27d93d3" +checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c" [[package]] name = "byte-slice-cast" @@ -460,12 +443,6 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" -[[package]] -name = "bytes" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" - [[package]] name = "bytes" version = "1.1.0" @@ -480,9 +457,9 @@ checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" [[package]] name = "camino" -version = "1.0.7" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f3132262930b0522068049f5870a856ab8affc80c70d08b6ecb785771a6fc23" +checksum = "52d74260d9bf6944e2208aa46841b4b8f0d7ffc0849a06837b2f510337f86b2b" dependencies = [ "serde", ] @@ -492,6 +469,7 @@ name = "cargo-contract" version = "0.17.0" dependencies = [ "anyhow", + "assert_cmd", "assert_matches", "async-std", "blake2", @@ -499,26 +477,41 @@ dependencies = [ "colored", "contract-metadata", "env_logger", - "funty 2.0.0", + "escape8259", "futures", "heck 0.4.0", "hex", "impl-serde", + "indexmap", + "ink_env", + "ink_lang", + "ink_metadata", + "ink_primitives", + "ink_storage", + "itertools", + "jsonrpsee 0.6.1", "log", - "parity-scale-codec 2.3.1", - "parity-wasm 0.42.2", + "nom", + "nom-supreme", + "pallet-contracts-primitives", + "parity-scale-codec", + "parity-wasm", "platforms 2.0.0", + "predicates", "pretty_assertions", "regex", "rustc_version", + "scale-info", "semver", "serde", "serde_json", - "sp-core", + "sp-core 5.0.0", + "sp-runtime 5.0.0", "structopt", "substrate-build-script-utils", - "substrate-subxt", + "subxt", "tempfile", + "thiserror", "toml", "url", "wabt", @@ -549,6 +542,15 @@ dependencies = [ "serde_json", ] +[[package]] +name = "cast" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a" +dependencies = [ + "rustc_version", +] + [[package]] name = "cc" version = "1.0.72" @@ -557,15 +559,15 @@ checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" [[package]] name = "cfg-if" -version = "0.1.10" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "cfg-if" -version = "1.0.0" +name = "chameleon" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "12bd83544cd11113170ce1eee45383928f3f720bc8b305af18c2a3da3547e1ae" [[package]] name = "chrono" @@ -576,7 +578,7 @@ dependencies = [ "libc", "num-integer", "num-traits", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -588,26 +590,17 @@ dependencies = [ "ansi_term", "atty", "bitflags", - "strsim", + "strsim 0.8.0", "textwrap", "unicode-width", "vec_map", ] -[[package]] -name = "cloudabi" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -dependencies = [ - "bitflags", -] - [[package]] name = "cmake" -version = "0.1.48" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8ad8cef104ac57b68b89df3208164d228503abbdce70f6880ffa3d970e7443a" +checksum = "b7b858541263efe664aead4a5209a4ae5c5d2811167d4ed4ee0944503f8d2089" dependencies = [ "cc", ] @@ -620,7 +613,7 @@ checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" dependencies = [ "atty", "lazy_static", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -656,6 +649,22 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "core-foundation" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + [[package]] name = "cpufeatures" version = "0.2.1" @@ -671,16 +680,86 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "738c290dfaea84fc1ca15ad9c168d083b05a714e1efddd8edaab678dc28d2836" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", +] + +[[package]] +name = "criterion" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10" +dependencies = [ + "atty", + "cast", + "clap", + "criterion-plot", + "csv", + "itertools", + "lazy_static", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_cbor", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57" +dependencies = [ + "cast", + "itertools", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "lazy_static", + "memoffset", + "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.6" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcae03edb34f947e64acdb1c33ec169824e20657e9ecb61cef6c8c74dcb8120" +checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "lazy_static", ] @@ -696,17 +775,17 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d6b536309245c849479fba3da410962a43ed8e51c26b729208ec0ac2798d0" dependencies = [ - "generic-array 0.14.5", + "generic-array 0.14.4", ] [[package]] name = "crypto-mac" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" dependencies = [ - "generic-array 0.12.4", - "subtle 1.0.0", + "generic-array 0.14.4", + "subtle", ] [[package]] @@ -715,8 +794,30 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" dependencies = [ - "generic-array 0.14.5", - "subtle 2.4.1", + "generic-array 0.14.4", + "subtle", +] + +[[package]] +name = "csv" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" +dependencies = [ + "bstr", + "csv-core", + "itoa 0.4.8", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +dependencies = [ + "memchr", ] [[package]] @@ -738,7 +839,7 @@ dependencies = [ "byteorder", "digest 0.8.1", "rand_core 0.5.1", - "subtle 2.4.1", + "subtle", "zeroize", ] @@ -751,10 +852,56 @@ dependencies = [ "byteorder", "digest 0.9.0", "rand_core 0.5.1", - "subtle 2.4.1", + "subtle", "zeroize", ] +[[package]] +name = "darling" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -774,6 +921,12 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499" +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + [[package]] name = "digest" version = "0.8.1" @@ -789,7 +942,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array 0.14.5", + "generic-array 0.14.4", ] [[package]] @@ -800,10 +953,22 @@ checksum = "b697d66081d42af4fba142d56918a3cb21dc8eb63372c6b85d14f44fb9c5979b" dependencies = [ "block-buffer 0.10.0", "crypto-common", - "generic-array 0.14.5", - "subtle 2.4.1", + "generic-array 0.14.4", + "subtle", ] +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "downcast-rs" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" + [[package]] name = "dyn-clonable" version = "0.9.0" @@ -850,7 +1015,7 @@ dependencies = [ "ed25519", "rand 0.7.3", "serde", - "sha2 0.9.9", + "sha2 0.9.8", "zeroize", ] @@ -880,32 +1045,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68b91989ae21441195d7d9b9993a2f9295c7e1a8c96255d8b729accddc124797" [[package]] -name = "event-listener" -version = "2.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59" - -[[package]] -name = "failure" -version = "0.1.8" +name = "escape8259" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" +checksum = "8edd65c008c6e97290e463c336e0c3fe109a91accb0e6b3e9e353d1605bd58b8" dependencies = [ - "backtrace", - "failure_derive", + "rustversion", ] [[package]] -name = "failure_derive" -version = "0.1.8" +name = "event-listener" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] +checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59" [[package]] name = "fake-simd" @@ -924,16 +1076,25 @@ dependencies = [ [[package]] name = "fixed-hash" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11498d382790b7a8f2fd211780bec78619bba81cdad3a283997c0c41f836759c" +checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" dependencies = [ "byteorder", - "rand 0.7.3", + "rand 0.8.4", "rustc-hex", "static_assertions", ] +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +dependencies = [ + "num-traits", +] + [[package]] name = "fnv" version = "1.0.7" @@ -951,149 +1112,23 @@ dependencies = [ ] [[package]] -name = "frame-benchmarking" -version = "2.0.1" +name = "frame-metadata" +version = "14.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52b94f3dd88fd10ea9eb8bf6731ee22787deeb620c158766061ec1fc54170cda" +checksum = "37ed5e5c346de62ca5c184b4325a6600d1eaca210666e4606fe4e449574978d0" dependencies = [ - "frame-support", - "frame-system", - "linregress", - "parity-scale-codec 1.3.7", - "paste", - "sp-api", - "sp-io", - "sp-runtime", - "sp-runtime-interface", - "sp-std", - "sp-storage", + "cfg-if", + "parity-scale-codec", + "scale-info", + "serde", ] [[package]] -name = "frame-metadata" -version = "12.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61200390d9eb6bac07a60adafa6961ef250f9022970fabb2412183fc96ba5f6b" -dependencies = [ - "parity-scale-codec 1.3.7", - "serde", - "sp-core", - "sp-std", -] - -[[package]] -name = "frame-support" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a569b3964b996dae5a9aab81a04a65f81a386645db1f16583647fc67190b0748" -dependencies = [ - "bitmask", - "frame-metadata", - "frame-support-procedural", - "impl-trait-for-tuples 0.1.3", - "log", - "once_cell", - "parity-scale-codec 1.3.7", - "paste", - "serde", - "smallvec", - "sp-arithmetic", - "sp-core", - "sp-inherents", - "sp-io", - "sp-runtime", - "sp-state-machine", - "sp-std", - "sp-tracing", -] - -[[package]] -name = "frame-support-procedural" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c107da590c5cf22f9bb96193812256e59c60f73786a72429660142d9000c07b" -dependencies = [ - "frame-support-procedural-tools", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "frame-support-procedural-tools" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb23ac15b9dfe806c1da92d6c8710fa09371ec61e13f4eadfdeef55e3d6b155b" -dependencies = [ - "frame-support-procedural-tools-derive", - "proc-macro-crate 0.1.5", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "frame-support-procedural-tools-derive" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66fb72ae75d457bfcb457e1098cf18134967e9069ecc4bba2c77416924b44843" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "frame-system" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bd441142244193759326c7311d075716d1aaa98a9ad50491af923a4c6e42f3b" -dependencies = [ - "frame-support", - "impl-trait-for-tuples 0.1.3", - "parity-scale-codec 1.3.7", - "serde", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", - "sp-version", -] - -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -dependencies = [ - "bitflags", - "fuchsia-zircon-sys", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" - -[[package]] -name = "funty" -version = "1.1.0" +name = "funty" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - [[package]] name = "futures" version = "0.3.21" @@ -1154,7 +1189,7 @@ dependencies = [ "futures-io", "memchr", "parking", - "pin-project-lite 0.2.8", + "pin-project-lite", "waker-fn", ] @@ -1181,12 +1216,6 @@ version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" -[[package]] -name = "futures-timer" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" - [[package]] name = "futures-util" version = "0.3.21" @@ -1200,7 +1229,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.8", + "pin-project-lite", "pin-utils", "slab", ] @@ -1216,9 +1245,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.5" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" dependencies = [ "typenum", "version_check", @@ -1230,18 +1259,20 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", + "js-sys", "libc", "wasi 0.9.0+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.2.4" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "wasi 0.10.2+wasi-snapshot-preview1", ] @@ -1258,19 +1289,6 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" -[[package]] -name = "globset" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10463d9ff00a2a068db14231982f5132edebad0d7660cd956a1c30292dbcbfbd" -dependencies = [ - "aho-corasick", - "bstr", - "fnv", - "log", - "regex", -] - [[package]] name = "gloo-timers" version = "0.2.2" @@ -1285,24 +1303,10 @@ dependencies = [ ] [[package]] -name = "h2" -version = "0.2.7" +name = "half" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e4728fd124914ad25e99e3d15a9361a879f6620f63cb56bbb08f95abb97a535" -dependencies = [ - "bytes 0.5.6", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", - "tracing-futures", -] +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] name = "hash-db" @@ -1319,33 +1323,13 @@ dependencies = [ "crunchy", ] -[[package]] -name = "hashbrown" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96282e96bfcd3da0d3aa9938bedf1e50df3269b6db08b4876d2da0bb1a0841cf" -dependencies = [ - "ahash 0.3.8", - "autocfg 1.0.1", -] - -[[package]] -name = "hashbrown" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25" -dependencies = [ - "ahash 0.3.8", - "autocfg 1.0.1", -] - [[package]] name = "hashbrown" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" dependencies = [ - "ahash 0.7.6", + "ahash", ] [[package]] @@ -1380,12 +1364,12 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hmac" -version = "0.7.1" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" dependencies = [ - "crypto-mac 0.7.0", - "digest 0.8.1", + "crypto-mac 0.8.0", + "digest 0.9.0", ] [[package]] @@ -1400,34 +1384,35 @@ dependencies = [ [[package]] name = "hmac-drbg" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6e570451493f10f6581b48cdd530413b63ea9e780f544bfd3bdcaa0d89d1a7b" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" dependencies = [ - "digest 0.8.1", - "generic-array 0.12.4", - "hmac 0.7.1", + "digest 0.9.0", + "generic-array 0.14.4", + "hmac 0.8.1", ] [[package]] name = "http" -version = "0.2.6" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" +checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b" dependencies = [ - "bytes 1.1.0", + "bytes", "fnv", - "itoa 1.0.1", + "itoa 0.4.8", ] [[package]] name = "http-body" -version = "0.3.1" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" +checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" dependencies = [ - "bytes 0.5.6", + "bytes", "http", + "pin-project-lite", ] [[package]] @@ -1438,9 +1423,9 @@ checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" [[package]] name = "httpdate" -version = "0.3.2" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "humantime" @@ -1450,28 +1435,32 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.13.10" +version = "0.14.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a6f157065790a3ed2f88679250419b5cdd96e714a0d65f7797fd337186e96bb" +checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55" dependencies = [ - "bytes 0.5.6", + "bytes", "futures-channel", "futures-core", "futures-util", - "h2", "http", "http-body", "httparse", "httpdate", "itoa 0.4.8", - "pin-project 1.0.10", - "socket2 0.3.19", + "pin-project-lite", "tokio", "tower-service", "tracing", "want", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.2.3" @@ -1485,11 +1474,11 @@ dependencies = [ [[package]] name = "impl-codec" -version = "0.4.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1be51a921b067b0eaca2fad532d9400041561aa922221cc65f95a85641c6bf53" +checksum = "161ebdfec3c8e3b52bf61c4f3550a1eea4f9579d10dc1b936f3171ebdcd6c443" dependencies = [ - "parity-scale-codec 1.3.7", + "parity-scale-codec", ] [[package]] @@ -1503,9 +1492,9 @@ dependencies = [ [[package]] name = "impl-trait-for-tuples" -version = "0.1.3" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef5550a42e3740a0e71f909d4c861056a284060af885ae7aa6242820f920d9d" +checksum = "d5dacb10c5b3bb92d46ba347505a9041e676bb20ad220101326bffb0c93031ee" dependencies = [ "proc-macro2", "quote", @@ -1513,15 +1502,10 @@ dependencies = [ ] [[package]] -name = "impl-trait-for-tuples" -version = "0.2.1" +name = "indent_write" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5dacb10c5b3bb92d46ba347505a9041e676bb20ad220101326bffb0c93031ee" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] +checksum = "0cfe9645a18782869361d9c8732246be7b410ad4e919d3609ebabdac00ba12c3" [[package]] name = "indexmap" @@ -1529,180 +1513,445 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" dependencies = [ - "autocfg 1.0.1", - "hashbrown 0.11.2", + "autocfg", + "hashbrown", ] [[package]] -name = "instant" -version = "0.1.12" +name = "ink_allocator" +version = "3.0.0-rc8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "252dfca0640dbf5927945aacdda0b6ff8c8ee51b317b37958dd6a06c13016a36" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] -name = "integer-sqrt" -version = "0.1.5" +name = "ink_env" +version = "3.0.0-rc8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" +checksum = "4b9965157c1f970869e34e8c00d141d89286e093f3096ef4310dc111fff5d626" dependencies = [ + "arrayref", + "blake2", + "cfg-if", + "derive_more", + "ink_allocator", + "ink_metadata", + "ink_prelude", + "ink_primitives", "num-traits", + "parity-scale-codec", + "paste", + "rand 0.8.4", + "rlibc", + "scale-info", + "secp256k1", + "sha2 0.10.1", + "sha3", + "static_assertions", ] [[package]] -name = "iovec" -version = "0.1.4" +name = "ink_eth_compatibility" +version = "3.0.0-rc8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +checksum = "332389adf5bd0076bb21bf00294698148b333a4e06004bc1efe53534232aacb6" dependencies = [ - "libc", + "ink_env", + "libsecp256k1", ] [[package]] -name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - -[[package]] -name = "itoa" -version = "1.0.1" +name = "ink_lang" +version = "3.0.0-rc8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +checksum = "3303fea1fe4fb452cf759cc15712714ec668df9e2a0aef21d35889d0af502437" +dependencies = [ + "derive_more", + "ink_env", + "ink_eth_compatibility", + "ink_lang_macro", + "ink_metadata", + "ink_prelude", + "ink_primitives", + "ink_storage", + "parity-scale-codec", +] [[package]] -name = "js-sys" -version = "0.3.56" +name = "ink_lang_codegen" +version = "3.0.0-rc8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" +checksum = "363510caaf5c82f602aa5e16792159bba866707c0f3de3ae4886052fe15631bc" dependencies = [ - "wasm-bindgen", + "blake2", + "derive_more", + "either", + "heck 0.4.0", + "impl-serde", + "ink_lang_ir", + "itertools", + "parity-scale-codec", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "jsonrpsee" -version = "0.1.0" +name = "ink_lang_ir" +version = "3.0.0-rc8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc8a1da5a54b417cfb7edb9f932024d833dc333de50c21c0e1b28d0e8b4f853" +checksum = "dc1b505e8e9be97e6ec8f57c1e3420fb25aa93344f5bcefa5757873290feb5fa" dependencies = [ - "async-std", - "async-tls", - "bs58", - "bytes 0.5.6", - "fnv", - "futures", - "futures-timer", - "globset", - "hashbrown 0.7.2", - "hyper", - "jsonrpsee-proc-macros", - "lazy_static", - "log", - "parking_lot 0.10.2", - "pin-project 0.4.29", - "rand 0.7.3", - "serde", - "serde_json", - "smallvec", - "soketto", - "thiserror", - "tokio", - "unicase", - "url", - "webpki", + "blake2", + "either", + "itertools", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "jsonrpsee-proc-macros" -version = "0.1.0" +name = "ink_lang_macro" +version = "3.0.0-rc8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1ed1b5f6937dd2c6c79a9ac6e0e3f41bbc64edb5d443840bdc73e606009ed70" +checksum = "6a7636e2d927f6289c81d655eb7f5418edf52e598843139dff229ad3459a113c" dependencies = [ - "Inflector", + "ink_lang_codegen", + "ink_lang_ir", + "ink_primitives", + "parity-scale-codec", "proc-macro2", - "quote", "syn", ] [[package]] -name = "keccak" -version = "0.1.0" +name = "ink_metadata" +version = "3.0.0-rc8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" +checksum = "e0e2c335905d3454f2eb01fd3c3678e60f4c391b3b4180350206a9e35a9837e8" +dependencies = [ + "derive_more", + "impl-serde", + "ink_prelude", + "ink_primitives", + "scale-info", + "serde", +] [[package]] -name = "kernel32-sys" -version = "0.2.2" +name = "ink_prelude" +version = "3.0.0-rc8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +checksum = "622cecf655344080352db5099a366eeb1d84f93cbe3980e204fff61af66de976" dependencies = [ - "winapi 0.2.8", - "winapi-build", + "cfg-if", ] [[package]] -name = "kv-log-macro" -version = "1.0.7" +name = "ink_primitives" +version = "3.0.0-rc8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +checksum = "6303fbbe30b4c6bbe01ff36cce29e37961095574260d5958017ce9346834c77e" dependencies = [ - "log", + "cfg-if", + "ink_prelude", + "parity-scale-codec", + "scale-info", ] [[package]] -name = "lazy_static" -version = "1.4.0" +name = "ink_storage" +version = "3.0.0-rc8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "6181ac6e3a74e681e8d5474565ed857d6279278d675ac58b5fcaa9a9d4504ba0" +dependencies = [ + "array-init", + "cfg-if", + "criterion", + "derive_more", + "ink_env", + "ink_metadata", + "ink_prelude", + "ink_primitives", + "ink_storage_derive", + "parity-scale-codec", + "scale-info", +] [[package]] -name = "libc" -version = "0.2.112" +name = "ink_storage_derive" +version = "3.0.0-rc8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" +checksum = "537d9afcb6cf564f4ed257c0a6c1b5b5d7f2440adbad5dc08f0c8942b52aec73" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] [[package]] -name = "libm" -version = "0.2.1" +name = "instant" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "integer-sqrt" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" +dependencies = [ + "num-traits", +] + +[[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 = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + +[[package]] +name = "joinery" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72167d68f5fce3b8655487b8038691a3c9984ee769590f93f2a631f4ad64e4f5" + +[[package]] +name = "js-sys" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "jsonrpsee" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ceafa2f3d8cb796bf63364691fb875b079814064306cfd4cb067f95f800a673f" +dependencies = [ + "jsonrpsee-types 0.6.1", + "jsonrpsee-utils", + "jsonrpsee-ws-client", +] + +[[package]] +name = "jsonrpsee" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05fd8cd6c6b1bbd06881d2cf88f1fc83cc36c98f2219090f839115fb4a956cb9" +dependencies = [ + "jsonrpsee-client-transport", + "jsonrpsee-core", +] + +[[package]] +name = "jsonrpsee-client-transport" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3303cdf246e6ab76e2866fb3d9acb6c76a068b1b28bd923a1b7a8122257ad7b5" +dependencies = [ + "futures", + "http", + "jsonrpsee-core", + "jsonrpsee-types 0.8.0", + "pin-project", + "rustls-native-certs", + "soketto", + "thiserror", + "tokio", + "tokio-rustls", + "tokio-util", + "tracing", + "webpki-roots", +] + +[[package]] +name = "jsonrpsee-core" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f220b5a238dc7992b90f1144fbf6eaa585872c9376afe6fe6863ffead6191bf3" +dependencies = [ + "anyhow", + "arrayvec 0.7.2", + "async-trait", + "beef", + "futures-channel", + "futures-util", + "hyper", + "jsonrpsee-types 0.8.0", + "rustc-hash", + "serde", + "serde_json", + "soketto", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "jsonrpsee-types" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7589284e20eb3f40544c672370512e239d9704d6bfa2d3e7a7a7cd505a56e69" +dependencies = [ + "anyhow", + "async-trait", + "beef", + "futures-channel", + "futures-util", + "hyper", + "serde", + "serde_json", + "soketto", + "thiserror", + "tracing", +] + +[[package]] +name = "jsonrpsee-types" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b3f601bbbe45cd63f5407b6f7d7950e08a7d4f82aa699ff41a4a5e9e54df58" +dependencies = [ + "anyhow", + "beef", + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "jsonrpsee-utils" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbc508d9e6169a81d2913035e8c97f2c49f699134cd3d93efa13c4457aa76252" +dependencies = [ + "arrayvec 0.7.2", + "beef", + "jsonrpsee-types 0.6.1", +] + +[[package]] +name = "jsonrpsee-ws-client" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9267225fdfda02df5c5a9793c90cfe9f2ae5f91d42d4da78bd64f0116a28e9a" +dependencies = [ + "async-trait", + "fnv", + "futures", + "http", + "jsonrpsee-types 0.6.1", + "pin-project", + "rustls-native-certs", + "serde", + "serde_json", + "soketto", + "thiserror", + "tokio", + "tokio-rustls", + "tokio-util", + "tracing", + "webpki-roots", +] + +[[package]] +name = "keccak" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" + +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + +[[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.112" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" [[package]] name = "libsecp256k1" -version = "0.3.5" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc1e2c808481a63dc6da2074752fdd4336a3c8fcc68b83db6f1fd5224ae7962" +checksum = "b0452aac8bab02242429380e9b2f94ea20cea2b37e2c1777a1358799bbe97f37" dependencies = [ "arrayref", - "crunchy", - "digest 0.8.1", + "base64", + "digest 0.9.0", "hmac-drbg", - "rand 0.7.3", - "sha2 0.8.2", - "subtle 2.4.1", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.8.4", + "serde", + "sha2 0.9.8", "typenum", ] [[package]] -name = "linregress" -version = "0.1.7" +name = "libsecp256k1-core" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9290cf6f928576eeb9c096c6fad9d8d452a0a1a70a2bbffa6e36064eedc0aac9" +checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" dependencies = [ - "failure", - "nalgebra", - "statrs", + "crunchy", + "digest 0.9.0", + "subtle", ] [[package]] -name = "lock_api" -version = "0.3.4" +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" +checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" dependencies = [ - "scopeguard", + "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]] @@ -1720,7 +1969,7 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "value-bag", ] @@ -1740,28 +1989,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] -name = "matrixmultiply" -version = "0.2.4" +name = "memchr" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "916806ba0031cd542105d916a97c8572e1fa6dd79c9c51e7eb43a09ec2dd84c1" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" dependencies = [ - "rawpointer", + "autocfg", ] [[package]] -name = "memchr" -version = "2.4.1" +name = "memory-db" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "de006e09d04fc301a5f7e817b75aa49801c4479a8af753764416b085337ddcc5" +dependencies = [ + "hash-db", + "hashbrown", + "parity-util-mem", +] [[package]] name = "memory-db" -version = "0.24.1" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f36ddb0b2cdc25d38babba472108798e3477f02be5165f038c5e393e50c57a" +checksum = "d505169b746dacf02f7d14d8c80b34edfd8212159c63d23c977739a0d960c626" dependencies = [ "hash-db", - "hashbrown 0.8.2", + "hashbrown", "parity-util-mem", ] @@ -1783,6 +2043,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.4.4" @@ -1790,92 +2056,84 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" dependencies = [ "adler", - "autocfg 1.0.1", + "autocfg", ] [[package]] name = "mio" -version = "0.6.23" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" +checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" dependencies = [ - "cfg-if 0.1.10", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", "libc", "log", "miow", - "net2", - "slab", - "winapi 0.2.8", + "ntapi", + "winapi", ] [[package]] name = "miow" -version = "0.2.2" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", + "winapi", ] [[package]] -name = "nalgebra" -version = "0.18.1" +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + +[[package]] +name = "nom" +version = "7.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaa9fddbc34c8c35dd2108515587b8ce0cab396f17977b8c738568e4edb521a2" +checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109" dependencies = [ - "alga", - "approx", - "generic-array 0.12.4", - "matrixmultiply", - "num-complex", - "num-rational", - "num-traits", - "rand 0.6.5", - "typenum", + "memchr", + "minimal-lexical", + "version_check", ] [[package]] -name = "net2" -version = "0.2.37" +name = "nom-supreme" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" +checksum = "aadc66631948f6b65da03be4c4cd8bd104d481697ecbb9bbd65719b1ec60bc9f" dependencies = [ - "cfg-if 0.1.10", - "libc", - "winapi 0.3.9", + "brownstone", + "indent_write", + "joinery", + "memchr", + "nom", ] [[package]] -name = "nodrop" -version = "0.1.14" +name = "normalize-line-endings" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" [[package]] -name = "num-bigint" -version = "0.2.6" +name = "ntapi" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" +checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" dependencies = [ - "autocfg 1.0.1", - "num-integer", - "num-traits", + "winapi", ] [[package]] -name = "num-complex" -version = "0.2.4" +name = "num-bigint" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" +checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" dependencies = [ - "autocfg 1.0.1", + "autocfg", + "num-integer", "num-traits", ] @@ -1885,7 +2143,7 @@ version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" dependencies = [ - "autocfg 1.0.1", + "autocfg", "num-traits", ] @@ -1895,7 +2153,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" dependencies = [ - "autocfg 1.0.1", + "autocfg", "num-bigint", "num-integer", "num-traits", @@ -1907,8 +2165,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" dependencies = [ - "autocfg 1.0.1", - "libm", + "autocfg", ] [[package]] @@ -1935,9 +2192,12 @@ name = "once_cell" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" -dependencies = [ - "parking_lot 0.11.2", -] + +[[package]] +name = "oorandom" +version = "11.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] name = "opaque-debug" @@ -1952,118 +2212,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] -name = "output_vt100" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "pallet-authorship" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4b04a80b2d09fcaacaea6190926012348df6ddb225690de098cb8c4cf3fd19b" -dependencies = [ - "frame-support", - "frame-system", - "impl-trait-for-tuples 0.1.3", - "parity-scale-codec 1.3.7", - "sp-authorship", - "sp-inherents", - "sp-runtime", - "sp-std", -] - -[[package]] -name = "pallet-indices" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f204e45af958dd3bd8fe0e884a00c30fa745b653cc8ed7fe33f9f8db536fd58e" -dependencies = [ - "frame-support", - "frame-system", - "parity-scale-codec 1.3.7", - "serde", - "sp-core", - "sp-io", - "sp-keyring", - "sp-runtime", - "sp-std", -] - -[[package]] -name = "pallet-session" -version = "2.0.1" +name = "openssl-probe" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d239080d33f284a388b8510ffff3d08452314515e122c2f979d8989578e638aa" -dependencies = [ - "frame-support", - "frame-system", - "impl-trait-for-tuples 0.1.3", - "pallet-timestamp", - "parity-scale-codec 1.3.7", - "serde", - "sp-core", - "sp-io", - "sp-runtime", - "sp-session", - "sp-staking", - "sp-std", - "sp-trie", -] +checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" [[package]] -name = "pallet-staking" -version = "2.0.1" +name = "output_vt100" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "def1b8639275c25dd621ae68a18c25d14f14992031c360eff98dd6a1d0095213" +checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" dependencies = [ - "frame-support", - "frame-system", - "pallet-authorship", - "pallet-session", - "parity-scale-codec 1.3.7", - "serde", - "sp-application-crypto", - "sp-io", - "sp-npos-elections", - "sp-runtime", - "sp-staking", - "sp-std", - "static_assertions", + "winapi", ] [[package]] -name = "pallet-timestamp" -version = "2.0.1" +name = "pallet-contracts-primitives" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e206c754d6cd6d8e6e79ba2ea1a55f72af68be106e7d725d367c11c52c96da32" +checksum = "e22d9d2bb8e33ca590237fa5ffa9363236bb49498b6c7498a68f560d897f9095" dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", - "impl-trait-for-tuples 0.1.3", - "parity-scale-codec 1.3.7", + "bitflags", + "parity-scale-codec", + "scale-info", "serde", - "sp-inherents", - "sp-runtime", + "sp-core 5.0.0", + "sp-rpc", + "sp-runtime 5.0.0", "sp-std", - "sp-timestamp", -] - -[[package]] -name = "parity-scale-codec" -version = "1.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4b26b16c7687c3075982af47719e481815df30bc544f7a6690763a25ca16e9d" -dependencies = [ - "arrayvec 0.5.2", - "bitvec 0.17.4", - "byte-slice-cast 0.3.5", - "parity-scale-codec-derive 1.2.3", - "serde", ] [[package]] @@ -2073,25 +2249,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "373b1a4c1338d9cd3d1fa53b3a11bdab5ab6bd80a20f7f7becd76953ae2be909" dependencies = [ "arrayvec 0.7.2", - "bitvec 0.20.4", - "byte-slice-cast 1.2.0", - "impl-trait-for-tuples 0.2.1", - "parity-scale-codec-derive 2.3.1", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", "serde", ] -[[package]] -name = "parity-scale-codec-derive" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c41512944b1faff334a5f1b9447611bf4ef40638ccb6328173dacefb338e878c" -dependencies = [ - "proc-macro-crate 0.1.5", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "parity-scale-codec-derive" version = "2.3.1" @@ -2106,17 +2270,17 @@ dependencies = [ [[package]] name = "parity-util-mem" -version = "0.7.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297ff91fa36aec49ce183484b102f6b75b46776822bd81525bfc4cc9b0dd0f5c" +checksum = "6f4cb4e169446179cbc6b8b6320cc9fca49bd2e94e8db25f25f200a8ea774770" dependencies = [ - "cfg-if 0.1.10", - "hashbrown 0.8.2", - "impl-trait-for-tuples 0.1.3", + "cfg-if", + "hashbrown", + "impl-trait-for-tuples", "parity-util-mem-derive", - "parking_lot 0.10.2", + "parking_lot", "primitive-types", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2130,12 +2294,6 @@ dependencies = [ "synstructure", ] -[[package]] -name = "parity-wasm" -version = "0.41.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc878dac00da22f8f61e7af3157988424567ab01d9920b962ef7dcbd7cd865" - [[package]] name = "parity-wasm" version = "0.42.2" @@ -2148,16 +2306,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" -[[package]] -name = "parking_lot" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e" -dependencies = [ - "lock_api 0.3.4", - "parking_lot_core 0.7.2", -] - [[package]] name = "parking_lot" version = "0.11.2" @@ -2165,22 +2313,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", - "lock_api 0.4.5", - "parking_lot_core 0.8.5", -] - -[[package]] -name = "parking_lot_core" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" -dependencies = [ - "cfg-if 0.1.10", - "cloudabi", - "libc", - "redox_syscall 0.1.57", - "smallvec", - "winapi 0.3.9", + "lock_api", + "parking_lot_core", ] [[package]] @@ -2189,41 +2323,27 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "instant", "libc", - "redox_syscall 0.2.10", + "redox_syscall", "smallvec", - "winapi 0.3.9", + "winapi", ] [[package]] name = "paste" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880" -dependencies = [ - "paste-impl", - "proc-macro-hack", -] - -[[package]] -name = "paste-impl" -version = "0.1.18" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6" -dependencies = [ - "proc-macro-hack", -] +checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5" [[package]] name = "pbkdf2" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" +checksum = "216eaa586a190f0a738f2f918511eecfa90f13295abec0e457cdebcceda80cbd" dependencies = [ - "byteorder", - "crypto-mac 0.7.0", + "crypto-mac 0.8.0", ] [[package]] @@ -2243,38 +2363,18 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] name = "pin-project" -version = "0.4.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9615c18d31137579e9ff063499264ddc1278e7b1982757ebc111028c4d1dc909" -dependencies = [ - "pin-project-internal 0.4.29", -] - -[[package]] -name = "pin-project" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" -dependencies = [ - "pin-project-internal 1.0.10", -] - -[[package]] -name = "pin-project-internal" -version = "0.4.29" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "044964427019eed9d49d9d5bbce6047ef18f37100ea400912a9fa4a3523ab12a" +checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08" dependencies = [ - "proc-macro2", - "quote", - "syn", + "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.10" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" +checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389" dependencies = [ "proc-macro2", "quote", @@ -2283,15 +2383,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" - -[[package]] -name = "pin-project-lite" -version = "0.2.8" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" +checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" [[package]] name = "pin-utils" @@ -2311,24 +2405,82 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8d0eef3571242013a0d5dc84861c3ae4a652e56e12adf8bdc26ff5f8cb34c94" +[[package]] +name = "plotters" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a3fd9ec30b9749ce28cd91f255d569591cdf937fe280c312143e3c4bad6f2a" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c" + +[[package]] +name = "plotters-svg" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521fa9638fa597e1dc53e9412a4f9cefb01187ee1f7413076f9e6749e2885ba9" +dependencies = [ + "plotters-backend", +] + [[package]] name = "polling" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "log", "wepoll-ffi", - "winapi 0.3.9", + "winapi", ] [[package]] name = "ppv-lite86" -version = "0.2.16" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" + +[[package]] +name = "predicates" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5aab5be6e4732b473071984b3164dbbfb7a3674d30ea5ff44410b6bcd960c3c" +dependencies = [ + "difflib", + "float-cmp", + "itertools", + "normalize-line-endings", + "predicates-core", + "regex", +] + +[[package]] +name = "predicates-core" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57e35a3326b75e49aa85f5dc6ec15b41108cf5aee58eabb1f274dd18b73c2451" + +[[package]] +name = "predicates-tree" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "338c7be2905b732ae3984a2f40032b5e94fd8f52505b186c7d4d68d193445df7" +dependencies = [ + "predicates-core", + "termtree", +] [[package]] name = "pretty_assertions" @@ -2344,13 +2496,14 @@ dependencies = [ [[package]] name = "primitive-types" -version = "0.7.3" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd39dcacf71411ba488570da7bbc89b717225e46478b30ba99b92db6b149809" +checksum = "05e4722c697a58a99d5d06a08c30821d7c082a4632198de1eaa5a6c22ef42373" dependencies = [ "fixed-hash", "impl-codec", "impl-serde", + "scale-info", "uint", ] @@ -2397,74 +2550,30 @@ dependencies = [ "version_check", ] -[[package]] -name = "proc-macro-hack" -version = "0.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" - [[package]] name = "proc-macro2" -version = "1.0.36" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +checksum = "2f84e92c0f7c9d58328b85a78557813e4bd845130db68d7184635344399423b1" dependencies = [ "unicode-xid", ] [[package]] name = "quote" -version = "1.0.14" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d" +checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" dependencies = [ "proc-macro2", ] -[[package]] -name = "radium" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "def50a86306165861203e7f84ecffbbdfdea79f0e51039b33de1e952358c47ac" - [[package]] name = "radium" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb" -[[package]] -name = "rand" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" -dependencies = [ - "cloudabi", - "fuchsia-cprng", - "libc", - "rand_core 0.3.1", - "winapi 0.3.9", -] - -[[package]] -name = "rand" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -dependencies = [ - "autocfg 0.1.7", - "libc", - "rand_chacha 0.1.1", - "rand_core 0.4.2", - "rand_hc 0.1.0", - "rand_isaac", - "rand_jitter", - "rand_os", - "rand_pcg 0.1.2", - "rand_xorshift", - "winapi 0.3.9", -] - [[package]] name = "rand" version = "0.7.3" @@ -2476,7 +2585,7 @@ dependencies = [ "rand_chacha 0.2.2", "rand_core 0.5.1", "rand_hc 0.2.0", - "rand_pcg 0.2.1", + "rand_pcg", ] [[package]] @@ -2491,16 +2600,6 @@ dependencies = [ "rand_hc 0.3.1", ] -[[package]] -name = "rand_chacha" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -dependencies = [ - "autocfg 0.1.7", - "rand_core 0.3.1", -] - [[package]] name = "rand_chacha" version = "0.2.2" @@ -2521,21 +2620,6 @@ dependencies = [ "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.5.1" @@ -2551,16 +2635,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "getrandom 0.2.4", -] - -[[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", + "getrandom 0.2.3", ] [[package]] @@ -2581,50 +2656,6 @@ dependencies = [ "rand_core 0.6.3", ] -[[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 0.3.9", -] - -[[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 0.3.9", -] - -[[package]] -name = "rand_pcg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -dependencies = [ - "autocfg 0.1.7", - "rand_core 0.4.2", -] - [[package]] name = "rand_pcg" version = "0.2.1" @@ -2635,35 +2666,30 @@ dependencies = [ ] [[package]] -name = "rand_xorshift" -version = "0.1.1" +name = "rayon" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" dependencies = [ - "rand_core 0.3.1", + "autocfg", + "crossbeam-deque", + "either", + "rayon-core", ] [[package]] -name = "rawpointer" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" - -[[package]] -name = "rdrand" -version = "0.4.0" +name = "rayon-core" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" dependencies = [ - "rand_core 0.3.1", + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "lazy_static", + "num_cpus", ] -[[package]] -name = "redox_syscall" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" - [[package]] name = "redox_syscall" version = "0.2.10" @@ -2725,7 +2751,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2740,9 +2766,15 @@ dependencies = [ "spin", "untrusted", "web-sys", - "winapi 0.3.9", + "winapi", ] +[[package]] +name = "rlibc" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc874b127765f014d792f16763a81245ab80500e2ad921ed4ee9e82481ee08fe" + [[package]] name = "rustc-demangle" version = "0.1.21" @@ -2772,17 +2804,43 @@ dependencies = [ [[package]] name = "rustls" -version = "0.16.0" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b25a18b1bf7387f0145e7f8324e700805aade3842dd3db2e74e4cdeb4677c09e" +checksum = "d37e5e2290f3e040b594b1a9e04377c2c671f1a1cfd9bfdef82106ac1c113f84" dependencies = [ - "base64 0.10.1", "log", "ring", "sct", "webpki", ] +[[package]] +name = "rustls-native-certs" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca9ebdfa27d3fc180e42879037b5338ab1c040c06affd00d8338598e7800943" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" +dependencies = [ + "base64", +] + +[[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" @@ -2798,6 +2856,42 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scale-info" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c55b744399c25532d63a0d2789b109df8d46fc93752d46b0782991a931a782f" +dependencies = [ + "bitvec", + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", + "serde", +] + +[[package]] +name = "scale-info-derive" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baeb2780690380592f86205aa4ee49815feb2acad8c2f59e6dd207148c3f1fcd" +dependencies = [ + "proc-macro-crate 1.1.0", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "schannel" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +dependencies = [ + "lazy_static", + "winapi", +] + [[package]] name = "schnorrkel" version = "0.9.1" @@ -2812,7 +2906,7 @@ dependencies = [ "rand 0.7.3", "rand_core 0.5.1", "sha2 0.8.2", - "subtle 2.4.1", + "subtle", "zeroize", ] @@ -2824,23 +2918,64 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "sct" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" dependencies = [ "ring", "untrusted", ] +[[package]] +name = "secp256k1" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab7883017d5b21f011ef8040ea9c6c7ac90834c0df26a69e4c0b06276151f125" +dependencies = [ + "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 = "secrecy" -version = "0.6.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9182278ed645df3477a9c27bfee0621c621aa16f6972635f7f795dae3d81070f" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" dependencies = [ "zeroize", ] +[[package]] +name = "security-framework" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525bc1abfda2e1998d152c45cf13e696f76d0a4972310b22fac1658b05df7c87" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9dd14d83160b528b7bfd66439110573efcfbe281b17fc2ca9f39f550d619c7e" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "semver" version = "1.0.5" @@ -2859,6 +2994,16 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half", + "serde", +] + [[package]] name = "serde_derive" version = "1.0.136" @@ -2882,20 +3027,18 @@ dependencies = [ ] [[package]] -name = "sha1" -version = "0.6.1" +name = "sha-1" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" dependencies = [ - "sha1_smol", + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug 0.3.0", ] -[[package]] -name = "sha1_smol" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" - [[package]] name = "sha2" version = "0.8.2" @@ -2910,17 +3053,38 @@ dependencies = [ [[package]] name = "sha2" -version = "0.9.9" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa" dependencies = [ "block-buffer 0.9.0", - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.9.0", "opaque-debug 0.3.0", ] +[[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.1", +] + +[[package]] +name = "sha3" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f935e31cf406e8c0e96c2815a5516181b7004ae8c5f296293221e9b1e356bd" +dependencies = [ + "digest 0.10.1", + "keccak", +] + [[package]] name = "sharded-slab" version = "0.1.4" @@ -2932,9 +3096,9 @@ dependencies = [ [[package]] name = "signature" -version = "1.5.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f054c6c1a6e95179d6f23ed974060dcefb2d9388bb7256900badad682c499de4" +checksum = "02658e48d89f2bec991f9a78e69cfa4c316f8d6a6c4ec12fae1aeb263d486788" [[package]] name = "slab" @@ -2944,20 +3108,9 @@ checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" [[package]] name = "smallvec" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" - -[[package]] -name = "socket2" -version = "0.3.19" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "winapi 0.3.9", -] +checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" [[package]] name = "socket2" @@ -2966,106 +3119,127 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" dependencies = [ "libc", - "winapi 0.3.9", + "winapi", ] [[package]] name = "soketto" -version = "0.3.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c9dab3f95c9ebdf3a88268c19af668f637a3c5039c2c56ff2d40b1b2d64a25b" +checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" dependencies = [ - "base64 0.11.0", - "bytes 0.5.6", + "base64", + "bytes", "futures", - "http", "httparse", "log", - "rand 0.7.3", - "sha1", - "smallvec", - "static_assertions", - "thiserror", + "rand 0.8.4", + "sha-1", ] [[package]] -name = "sp-api" -version = "2.0.1" +name = "sp-application-crypto" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8496732f255ef290eee6d438ebd0ecdbfe31ec8246e31870a4faf44df76b6280" +checksum = "d0a11468fbf1d08502f95a69388b16e927a872df556085b5be7e5c55cdd3022c" dependencies = [ - "hash-db", - "parity-scale-codec 1.3.7", - "sp-api-proc-macro", - "sp-core", - "sp-runtime", - "sp-state-machine", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core 4.0.0", + "sp-io 4.0.0", "sp-std", - "sp-version", -] - -[[package]] -name = "sp-api-proc-macro" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c863d32b9e36849f2fc76efad959924561b2fcb15b3abdebb3d3f48a94074a00" -dependencies = [ - "blake2-rfc", - "proc-macro-crate 0.1.5", - "proc-macro2", - "quote", - "syn", ] [[package]] name = "sp-application-crypto" -version = "2.0.1" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda2660cca492b58328d6a057bf5ba6c8a58e9f6e079a2f603b623d030300841" +checksum = "69c8dfffb7a15ac2c802bc9ce972b8449c8ce0a15254ae4d77a012a3a8c278d1" dependencies = [ - "parity-scale-codec 1.3.7", + "parity-scale-codec", + "scale-info", "serde", - "sp-core", - "sp-io", + "sp-core 5.0.0", + "sp-io 5.0.0", "sp-std", ] [[package]] name = "sp-arithmetic" -version = "2.0.1" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c4d204b1cf8e1d4826804ffbd2edd2c4df385ee3046fa4581f09bc18977ea89" +checksum = "aa92b9707afdaa807bcb985fcc70645ebbe6fbb2442620d61dc47e7f3553a7ae" dependencies = [ "integer-sqrt", "num-traits", - "parity-scale-codec 1.3.7", + "parity-scale-codec", + "scale-info", "serde", "sp-debug-derive", "sp-std", + "static_assertions", ] [[package]] -name = "sp-authorship" -version = "2.0.1" +name = "sp-core" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c99612989f07a55a160b1d041cac74c9089f97b3d0e0244cdde4ed3e00560ff" +checksum = "8295f7e800feaa16453768efb63c3063401ec765590f8f6ac9fac808a790435e" dependencies = [ - "parity-scale-codec 1.3.7", - "sp-inherents", - "sp-runtime", + "base58", + "bitflags", + "blake2-rfc", + "byteorder", + "dyn-clonable", + "ed25519-dalek", + "futures", + "hash-db", + "hash256-std-hasher", + "hex", + "impl-serde", + "lazy_static", + "libsecp256k1", + "log", + "merlin", + "num-traits", + "parity-scale-codec", + "parity-util-mem", + "parking_lot", + "primitive-types", + "rand 0.7.3", + "regex", + "scale-info", + "schnorrkel", + "secrecy", + "serde", + "sha2 0.9.8", + "sp-core-hashing", + "sp-debug-derive", + "sp-externalities 0.10.0", + "sp-runtime-interface 4.0.0", "sp-std", + "sp-storage 4.0.0", + "ss58-registry", + "substrate-bip39", + "thiserror", + "tiny-bip39", + "tiny-keccak", + "twox-hash", + "wasmi", + "zeroize", ] [[package]] name = "sp-core" -version = "2.0.1" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb1b8a5031e866ebee7535446915c83e8f676c68dcc8555f0c0f149ff4b48035" +checksum = "2e2a372e6c3a40464f490f76843dfc331d08e43f7672d73377c0458f5b5db7ed" dependencies = [ "base58", + "bitflags", "blake2-rfc", "byteorder", - "derive_more", "dyn-clonable", "ed25519-dalek", "futures", @@ -3078,22 +3252,26 @@ dependencies = [ "log", "merlin", "num-traits", - "parity-scale-codec 1.3.7", + "parity-scale-codec", "parity-util-mem", - "parking_lot 0.10.2", + "parking_lot", "primitive-types", "rand 0.7.3", "regex", + "scale-info", "schnorrkel", "secrecy", "serde", - "sha2 0.8.2", + "sha2 0.10.1", + "sp-core-hashing", "sp-debug-derive", - "sp-externalities", - "sp-runtime-interface", + "sp-externalities 0.11.0", + "sp-runtime-interface 5.0.0", "sp-std", - "sp-storage", + "sp-storage 5.0.0", + "ss58-registry", "substrate-bip39", + "thiserror", "tiny-bip39", "tiny-keccak", "twox-hash", @@ -3101,11 +3279,25 @@ dependencies = [ "zeroize", ] +[[package]] +name = "sp-core-hashing" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec864a6a67249f0c8dd3d5acab43623a61677e85ff4f2f9b04b802d2fe780e83" +dependencies = [ + "blake2-rfc", + "byteorder", + "sha2 0.9.8", + "sp-std", + "tiny-keccak", + "twox-hash", +] + [[package]] name = "sp-debug-derive" -version = "2.0.1" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "558a1a24f2feab950ce382923b62879f253207c6cbf7832eb1e47dba5f57fba8" +checksum = "d676664972e22a0796176e81e7bec41df461d1edf52090955cdab55f2c956ff2" dependencies = [ "proc-macro2", "quote", @@ -3114,224 +3306,291 @@ dependencies = [ [[package]] name = "sp-externalities" -version = "0.8.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "144c39acb7affd7a9ce478e289157b9a6c225e3f08a7d4d2f4fee85cc3899684" +checksum = "54226438dbff5ced9718b51eb44b7f38fe139c40a923a088275914519bf451d3" dependencies = [ "environmental", - "parity-scale-codec 1.3.7", + "parity-scale-codec", "sp-std", - "sp-storage", + "sp-storage 4.0.0", ] [[package]] -name = "sp-inherents" -version = "2.0.1" +name = "sp-externalities" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ebcf5925a850392cb044af9b8da20dc0610e613ff15607b3b96bed6461f9193" +checksum = "54f0fe949490000a97f367dc2acf4d2e7d0473ec0e13ce1775d0804bb64d3c98" dependencies = [ - "derive_more", - "parity-scale-codec 1.3.7", - "parking_lot 0.10.2", - "sp-core", + "environmental", + "parity-scale-codec", "sp-std", + "sp-storage 5.0.0", ] [[package]] name = "sp-io" -version = "2.0.1" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bffbebdeacf0a313ac65e043c37e37d98b48ea75cd1e8ab9ba40a925fecb616b" +checksum = "cfe902ca84673ea25897b04f1bae4db2955a0e01105fc115df3cfd5447f78848" dependencies = [ "futures", "hash-db", "libsecp256k1", "log", - "parity-scale-codec 1.3.7", - "parking_lot 0.10.2", - "sp-core", - "sp-externalities", - "sp-runtime-interface", - "sp-state-machine", + "parity-scale-codec", + "parking_lot", + "sp-core 4.0.0", + "sp-externalities 0.10.0", + "sp-keystore 0.10.0", + "sp-runtime-interface 4.0.0", + "sp-state-machine 0.10.0", "sp-std", "sp-tracing", - "sp-trie", - "sp-wasm-interface", + "sp-trie 4.0.0", + "sp-wasm-interface 4.0.0", "tracing", "tracing-core", ] [[package]] -name = "sp-keyring" -version = "2.0.1" +name = "sp-io" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9741dcf007b33496e1add259fae40d59cfe64847bf992d2605edcecd8ae6d0c2" +checksum = "dece853333a36d405be49d72a5190c1aa3fa6fbc442a8f28c59b50c0351b21d6" dependencies = [ - "lazy_static", - "sp-core", - "sp-runtime", - "strum", + "futures", + "hash-db", + "libsecp256k1", + "log", + "parity-scale-codec", + "parking_lot", + "sp-core 5.0.0", + "sp-externalities 0.11.0", + "sp-keystore 0.11.0", + "sp-runtime-interface 5.0.0", + "sp-state-machine 0.11.0", + "sp-std", + "sp-tracing", + "sp-trie 5.0.0", + "sp-wasm-interface 5.0.0", + "tracing", + "tracing-core", ] [[package]] -name = "sp-npos-elections" -version = "2.0.1" +name = "sp-keystore" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "404f9b99ff38395d48bf2f041096fc5dbc1b892a8c314314c7bf66a0dfb5622c" +checksum = "d37621e7224fff35ca9eb235e3edfe0a4a556408a23901f5f4a23f7b435c0c66" dependencies = [ - "parity-scale-codec 1.3.7", - "serde", - "sp-arithmetic", - "sp-npos-elections-compact", - "sp-std", + "async-trait", + "derive_more", + "futures", + "merlin", + "parity-scale-codec", + "parking_lot", + "schnorrkel", + "sp-core 4.0.0", + "sp-externalities 0.10.0", ] [[package]] -name = "sp-npos-elections-compact" -version = "2.0.1" +name = "sp-keystore" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4ac5b8443203fbc6472f08f376b3b09307dc3ae1b0c1a91776a3b934f1314ce" +checksum = "a3c3376dede1940014254f6d10c9fca20c4deb1fae930a98edfdab0190a06ed4" dependencies = [ - "proc-macro-crate 0.1.5", - "proc-macro2", - "quote", - "syn", + "async-trait", + "futures", + "merlin", + "parity-scale-codec", + "parking_lot", + "schnorrkel", + "sp-core 5.0.0", + "sp-externalities 0.11.0", + "thiserror", ] [[package]] name = "sp-panic-handler" -version = "2.0.1" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1055031d4994705cd9eca38602fea1ed88f6916c0979f85352c3d540baedb2e8" +checksum = "2101f3c555fceafcfcfb0e61c55ea9ed80dc60bd77d54d9f25b369edb029e9a4" dependencies = [ "backtrace", - "log", + "lazy_static", + "regex", ] [[package]] name = "sp-rpc" -version = "2.0.1" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "009f2b8ae311ff2c5f319e545492f26a3954fc84f477f85e2c3dd49fde605cf9" +checksum = "8e3864afd75c4c83f060d8c61f9cd51b986eee5feef67921e99cd139a4072ddc" dependencies = [ + "rustc-hash", "serde", - "sp-core", + "sp-core 5.0.0", ] [[package]] name = "sp-runtime" -version = "2.0.1" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c31cd604c0fc105f764ef77eb38a9d0bf71e7bd289f28fd09f32f7132c3c46f" +dependencies = [ + "either", + "hash256-std-hasher", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "parity-util-mem", + "paste", + "rand 0.7.3", + "scale-info", + "serde", + "sp-application-crypto 4.0.0", + "sp-arithmetic", + "sp-core 4.0.0", + "sp-io 4.0.0", + "sp-std", +] + +[[package]] +name = "sp-runtime" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85d8d12cba8cb9c50d8c0eee517d74044c22faa9322260e88dccb5bd06bf0762" +checksum = "3772a765d076ac548c0c37f6d84dc8873bf64d0cfcf8b7b7322b5374d635ceff" dependencies = [ "either", "hash256-std-hasher", - "impl-trait-for-tuples 0.1.3", + "impl-trait-for-tuples", "log", - "parity-scale-codec 1.3.7", + "parity-scale-codec", "parity-util-mem", "paste", "rand 0.7.3", + "scale-info", "serde", - "sp-application-crypto", + "sp-application-crypto 5.0.0", "sp-arithmetic", - "sp-core", - "sp-inherents", - "sp-io", + "sp-core 5.0.0", + "sp-io 5.0.0", "sp-std", ] [[package]] name = "sp-runtime-interface" -version = "2.0.1" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb6574401a7b5c89111b417efecbc9f0c3d38c2c539ce3a964b8393769c3e15" +checksum = "7e0176151f1195b386ddb4e07d716713e1e29f36b65c0e6e91fe354fc2cec84d" dependencies = [ - "parity-scale-codec 1.3.7", + "impl-trait-for-tuples", + "parity-scale-codec", "primitive-types", - "sp-externalities", + "sp-externalities 0.10.0", "sp-runtime-interface-proc-macro", "sp-std", - "sp-storage", + "sp-storage 4.0.0", "sp-tracing", - "sp-wasm-interface", + "sp-wasm-interface 4.0.0", "static_assertions", ] [[package]] -name = "sp-runtime-interface-proc-macro" -version = "2.0.1" +name = "sp-runtime-interface" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d724b1feca629bf958dc0db0453225e59d9b2098fe5a47f86cd964cbc116d89d" +checksum = "ab1f6625996742e3e5c0e6a6a2b5c0db363e2c52f4a71ea6cd6d963a10a4bdd6" dependencies = [ - "Inflector", - "proc-macro-crate 0.1.5", - "proc-macro2", - "quote", - "syn", + "impl-trait-for-tuples", + "parity-scale-codec", + "primitive-types", + "sp-externalities 0.11.0", + "sp-runtime-interface-proc-macro", + "sp-std", + "sp-storage 5.0.0", + "sp-tracing", + "sp-wasm-interface 5.0.0", + "static_assertions", ] [[package]] -name = "sp-session" -version = "2.0.1" +name = "sp-runtime-interface-proc-macro" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "242e7e9069cfd163b6ceb22c2d1aba7a09144ac8360f07270739ca7917520b69" +checksum = "2b58cc6060b2d2f35061db5b4172f4a47353c3f01a89f281699a6c3f05d1267a" dependencies = [ - "parity-scale-codec 1.3.7", - "sp-api", - "sp-core", - "sp-runtime", - "sp-staking", - "sp-std", + "Inflector", + "proc-macro-crate 1.1.0", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "sp-staking" -version = "2.0.1" +name = "sp-state-machine" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6abfd1a33f36879117b5f511ac066e265258028d1190088be89924794967f395" +checksum = "f3e3d9e8443f9d92348d779b06029603fbe536a59a05a0d8593ea2d3711c2330" dependencies = [ - "parity-scale-codec 1.3.7", - "sp-runtime", + "hash-db", + "log", + "num-traits", + "parity-scale-codec", + "parking_lot", + "rand 0.7.3", + "smallvec", + "sp-core 4.0.0", + "sp-externalities 0.10.0", + "sp-panic-handler", "sp-std", + "sp-trie 4.0.0", + "thiserror", + "tracing", + "trie-db 0.22.6", + "trie-root 0.16.0", ] [[package]] name = "sp-state-machine" -version = "0.8.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "095a8c33f70151e561c53fdaca23ad19cc059088807a25be0d60d04fb2ededea" +checksum = "1e66851fd082cccc6f66dddf6eda458f30766a3febd769f1b5592120aa8072fd" dependencies = [ "hash-db", "log", "num-traits", - "parity-scale-codec 1.3.7", - "parking_lot 0.10.2", + "parity-scale-codec", + "parking_lot", "rand 0.7.3", "smallvec", - "sp-core", - "sp-externalities", + "sp-core 5.0.0", + "sp-externalities 0.11.0", "sp-panic-handler", "sp-std", - "sp-trie", - "trie-db", - "trie-root", + "sp-trie 5.0.0", + "thiserror", + "tracing", + "trie-db 0.23.0", + "trie-root 0.17.0", ] [[package]] name = "sp-std" -version = "2.0.1" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2585fb8f5f4fde53c2f9ccebac4517da4dc435373a8fcaf5db7f54b798da66c2" +checksum = "14804d6069ee7a388240b665f17908d98386ffb0b5d39f89a4099fc7a2a4c03f" [[package]] name = "sp-storage" -version = "2.0.1" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "781cc04c8d61c7bb1c269ca68d5d001fcaafbca8a21af46f87bf2e79a749c295" +checksum = "851e1315a935cd5a0ce1bb6e41b0d611ac2370ede860d551f9f133007487043a" dependencies = [ "impl-serde", - "parity-scale-codec 1.3.7", + "parity-scale-codec", "ref-cast", "serde", "sp-debug-derive", @@ -3339,28 +3598,26 @@ dependencies = [ ] [[package]] -name = "sp-timestamp" -version = "2.0.1" +name = "sp-storage" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d86fb8fd203faa146ba06b0d88c60f9bcb4c1dcbe49f64e36d4038893018536" +checksum = "838ec2a757a8e7b903684a71f649dfbd6449d91e3e5d93979fc8d2ee77d56fee" dependencies = [ - "impl-trait-for-tuples 0.1.3", - "parity-scale-codec 1.3.7", - "sp-api", - "sp-inherents", - "sp-runtime", + "impl-serde", + "parity-scale-codec", + "ref-cast", + "serde", + "sp-debug-derive", "sp-std", - "wasm-timer", ] [[package]] name = "sp-tracing" -version = "2.0.1" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c574a06ac032f3c6fc29ae61ae1292546499342219c256098914f6110312f6f4" +checksum = "a4688fceac497cee7e9b72c387fef20fa517e2bf6a3bf52a4a45dcc9391d6201" dependencies = [ - "log", - "parity-scale-codec 1.3.7", + "parity-scale-codec", "sp-std", "tracing", "tracing-core", @@ -3369,40 +3626,86 @@ dependencies = [ [[package]] name = "sp-trie" -version = "2.0.1" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "feb344969de755877440fccb691860acedd565061774d289886ff9c690206cc0" +dependencies = [ + "hash-db", + "memory-db 0.27.0", + "parity-scale-codec", + "scale-info", + "sp-core 4.0.0", + "sp-std", + "trie-db 0.22.6", + "trie-root 0.16.0", +] + +[[package]] +name = "sp-trie" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "311f320e1a1d6d961664af519d343d7a0493d9fe2f81dc3de488841e4fbaaa46" +checksum = "8a7ad44bbb93fb9af94ea9869ec13602884f7d2360c245377aed7c6c92c6834e" dependencies = [ "hash-db", - "memory-db", - "parity-scale-codec 1.3.7", - "sp-core", + "memory-db 0.28.0", + "parity-scale-codec", + "scale-info", + "sp-core 5.0.0", "sp-std", - "trie-db", - "trie-root", + "trie-db 0.23.0", + "trie-root 0.17.0", ] [[package]] name = "sp-version" -version = "2.0.1" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d5fb7fa5f747a7d1b1854a1b69b813a9df6425ab0f0a9876cbddea8c6b9ab34" +checksum = "8b57388721427e65bdfadf636eebf444a6f84f7a05b56af2e7c6928cf554c618" dependencies = [ "impl-serde", - "parity-scale-codec 1.3.7", + "parity-scale-codec", + "parity-wasm", + "scale-info", "serde", - "sp-runtime", + "sp-runtime 4.0.0", + "sp-std", + "sp-version-proc-macro", + "thiserror", +] + +[[package]] +name = "sp-version-proc-macro" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fcafba97053cfa9fa366e6b30fd0d0e9d15530c4a738efaa117a4d5707d147" +dependencies = [ + "parity-scale-codec", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sp-wasm-interface" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89a5b0fe5b5bd3259e914edc35b33b6f7b4b0c803981290256e8ed75eecf1b27" +dependencies = [ + "impl-trait-for-tuples", + "parity-scale-codec", "sp-std", + "wasmi", ] [[package]] name = "sp-wasm-interface" -version = "2.0.1" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "554daa08d61bb3bf2d81ac79b7ae089733339fc8fdc129dc21d074195f1219be" +checksum = "60951479e2f26018c4c315a6f48956b9e2a3803953517bf8930e69b9a7a159df" dependencies = [ - "impl-trait-for-tuples 0.1.3", - "parity-scale-codec 1.3.7", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", "sp-std", "wasmi", ] @@ -3413,6 +3716,20 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "ss58-registry" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8319f44e20b42e5c11b88b1ad4130c35fe2974665a007b08b02322070177136a" +dependencies = [ + "Inflector", + "proc-macro2", + "quote", + "serde", + "serde_json", + "unicode-xid", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -3420,19 +3737,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] -name = "statrs" -version = "0.10.0" +name = "strsim" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10102ac8d55e35db2b3fafc26f81ba8647da2e15879ab686a67e6d19af2685e8" -dependencies = [ - "rand 0.5.6", -] +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "strsim" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "structopt" @@ -3458,27 +3772,6 @@ dependencies = [ "syn", ] -[[package]] -name = "strum" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6138f8f88a16d90134763314e3fc76fa3ed6a7db4725d6acf9a3ef95a3188d22" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0054a7df764039a6cd8592b9de84be4bec368ff081d203a7d5371cbfa8e65c81" -dependencies = [ - "heck 0.3.3", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "substrate-bip39" version = "0.4.4" @@ -3488,7 +3781,7 @@ dependencies = [ "hmac 0.11.0", "pbkdf2 0.8.0", "schnorrkel", - "sha2 0.9.9", + "sha2 0.9.8", "zeroize", ] @@ -3502,66 +3795,82 @@ dependencies = [ ] [[package]] -name = "substrate-subxt" -version = "0.14.0" +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "subxt" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7745e786bcfe0223008d20a3a9d61c7b80b9651d19180e835a377a19c007845e" +checksum = "2bd89701863271876fecd8e3abae2c639f7a6b94bf316468d14c33b198e6ecf9" dependencies = [ + "async-trait", + "bitvec", + "chameleon", + "derivative", "frame-metadata", - "frame-support", "futures", "hex", - "jsonrpsee", + "jsonrpsee 0.8.0", "log", "num-traits", - "pallet-indices", - "pallet-staking", - "parity-scale-codec 1.3.7", + "parity-scale-codec", + "scale-info", "serde", "serde_json", - "sp-application-crypto", - "sp-core", - "sp-rpc", - "sp-runtime", - "sp-std", + "sp-core 5.0.0", + "sp-runtime 5.0.0", "sp-version", - "substrate-subxt-proc-macro", + "subxt-macro", "thiserror", - "url", ] [[package]] -name = "substrate-subxt-proc-macro" -version = "0.14.0" +name = "subxt-codegen" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d47ddc15af08feb25287ba1eea618773192d9e9b28eef6ce615f51cf342fd147" +checksum = "a543285728058f878d45f652c1d3c6653dc126dffe678bc1fbe0021d82f853d8" dependencies = [ + "async-trait", + "darling", + "frame-metadata", "heck 0.3.3", + "parity-scale-codec", "proc-macro-crate 0.1.5", "proc-macro-error", "proc-macro2", "quote", + "scale-info", "syn", - "synstructure", ] [[package]] -name = "subtle" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" - -[[package]] -name = "subtle" -version = "2.4.1" +name = "subxt-macro" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +checksum = "4780536dce546910bd9fb691397434c4267885f25bc8870697cce5e210621966" +dependencies = [ + "async-trait", + "darling", + "frame-metadata", + "heck 0.3.3", + "parity-scale-codec", + "proc-macro-crate 0.1.5", + "proc-macro-error", + "proc-macro2", + "quote", + "scale-info", + "subxt-codegen", + "syn", +] [[package]] name = "syn" -version = "1.0.86" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" +checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" dependencies = [ "proc-macro2", "quote", @@ -3592,12 +3901,12 @@ version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "fastrand", "libc", - "redox_syscall 0.2.10", + "redox_syscall", "remove_dir_all", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -3609,6 +3918,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "termtree" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13a4ec180a2de59b57434704ccfad967f789b12737738798fa08798cd5824c16" + [[package]] name = "textwrap" version = "0.11.0" @@ -3649,18 +3964,21 @@ dependencies = [ [[package]] name = "tiny-bip39" -version = "0.7.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0165e045cc2ae1660270ca65e1676dbaab60feb0f91b10f7d0665e9b47e31f2" +checksum = "ffc59cb9dfc85bb312c3a78fd6aa8a8582e310b0fa885d5bb877f6dcc601839d" dependencies = [ - "failure", - "hmac 0.7.1", + "anyhow", + "hmac 0.8.1", "once_cell", - "pbkdf2 0.3.0", + "pbkdf2 0.4.0", "rand 0.7.3", "rustc-hash", - "sha2 0.8.2", + "sha2 0.9.8", + "thiserror", "unicode-normalization", + "wasm-bindgen", + "zeroize", ] [[package]] @@ -3672,6 +3990,16 @@ dependencies = [ "crunchy", ] +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "tinyvec" version = "1.5.1" @@ -3689,32 +4017,52 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "0.2.25" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6703a273949a90131b290be1fe7b039d0fc884aa1935860dfcbe056f28cd8092" +checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838" dependencies = [ - "bytes 0.5.6", - "fnv", - "futures-core", - "iovec", - "lazy_static", - "memchr", + "libc", "mio", - "pin-project-lite 0.1.12", - "slab", + "num_cpus", + "pin-project-lite", + "tokio-macros", + "winapi", +] + +[[package]] +name = "tokio-macros" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-rustls" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a27d5f2b839802bd8267fa19b0530f5a08b9c08cd417976be2a65d130fe1c11b" +dependencies = [ + "rustls", + "tokio", + "webpki", ] [[package]] name = "tokio-util" -version = "0.3.1" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" +checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" dependencies = [ - "bytes 0.5.6", + "bytes", "futures-core", + "futures-io", "futures-sink", "log", - "pin-project-lite 0.1.12", + "pin-project-lite", "tokio", ] @@ -3739,29 +4087,30 @@ version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" dependencies = [ - "cfg-if 1.0.0", - "log", - "pin-project-lite 0.2.8", + "cfg-if", + "pin-project-lite", + "tracing-attributes", "tracing-core", ] [[package]] -name = "tracing-core" -version = "0.1.21" +name = "tracing-attributes" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" +checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e" dependencies = [ - "lazy_static", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "tracing-futures" -version = "0.2.5" +name = "tracing-core" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" dependencies = [ - "pin-project 1.0.10", - "tracing", + "lazy_static", ] [[package]] @@ -3814,7 +4163,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9eac131e334e81b6b3be07399482042838adcd7957aa0010231d0813e39e02fa" dependencies = [ "hash-db", - "hashbrown 0.11.2", + "hashbrown", + "log", + "rustc-hex", + "smallvec", +] + +[[package]] +name = "trie-db" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ddae50680c12ef75bfbf58416ca6622fa43d879553f6cb2ed1a817346e1ffe" +dependencies = [ + "hash-db", + "hashbrown", "log", "rustc-hex", "smallvec", @@ -3829,6 +4191,15 @@ dependencies = [ "hash-db", ] +[[package]] +name = "trie-root" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a36c5ca3911ed3c9a5416ee6c679042064b93fc637ded67e25f92e68d783891" +dependencies = [ + "hash-db", +] + [[package]] name = "try-lock" version = "0.2.3" @@ -3841,38 +4212,29 @@ version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ee73e6e4924fe940354b8d4d98cad5231175d615cd855b758adc658c0aac6a0" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "rand 0.8.4", "static_assertions", ] [[package]] name = "typenum" -version = "1.15.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" [[package]] name = "uint" -version = "0.8.5" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9db035e67dfaf7edd9aebfe8676afcd63eed53c8a4044fed514c8cccf1835177" +checksum = "6470ab50f482bde894a037a57064480a246dbfdd5960bd65a44824693f08da5f" dependencies = [ "byteorder", "crunchy", - "rustc-hex", + "hex", "static_assertions", ] -[[package]] -name = "unicase" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" -dependencies = [ - "version_check", -] - [[package]] name = "unicode-bidi" version = "0.3.7" @@ -3943,9 +4305,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" [[package]] name = "wabt" @@ -3970,6 +4332,15 @@ dependencies = [ "glob", ] +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + [[package]] name = "waker-fn" version = "1.1.0" @@ -3983,7 +4354,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" dependencies = [ "same-file", - "winapi 0.3.9", + "winapi", "winapi-util", ] @@ -4011,19 +4382,19 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "wasm-bindgen" -version = "0.2.79" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" +checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.79" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" +checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" dependencies = [ "bumpalo", "lazy_static", @@ -4036,11 +4407,11 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.29" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395" +checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "wasm-bindgen", "web-sys", @@ -4048,9 +4419,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.79" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" +checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4058,9 +4429,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.79" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" +checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" dependencies = [ "proc-macro2", "quote", @@ -4071,53 +4442,39 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" - -[[package]] -name = "wasm-timer" -version = "0.2.5" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" -dependencies = [ - "futures", - "js-sys", - "parking_lot 0.11.2", - "pin-utils", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] +checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" [[package]] name = "wasmi" -version = "0.6.2" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf617d864d25af3587aa745529f7aaa541066c876d57e050c0d0c85c61c92aff" +checksum = "ca00c5147c319a8ec91ec1a0edbec31e566ce2c9cc93b3f9bb86a9efd0eb795d" dependencies = [ + "downcast-rs", "libc", "memory_units", "num-rational", "num-traits", - "parity-wasm 0.41.0", + "parity-wasm", "wasmi-validation", ] [[package]] name = "wasmi-validation" -version = "0.3.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea78c597064ba73596099281e2f4cfc019075122a65cdda3205af94f0b264d93" +checksum = "165343ecd6c018fc09ebcae280752702c9a2ef3e6f8d02f1cfcbdb53ef6d7937" dependencies = [ - "parity-wasm 0.41.0", + "parity-wasm", ] [[package]] name = "web-sys" -version = "0.3.56" +version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb" +checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" dependencies = [ "js-sys", "wasm-bindgen", @@ -4125,9 +4482,9 @@ dependencies = [ [[package]] name = "webpki" -version = "0.21.4" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" dependencies = [ "ring", "untrusted", @@ -4135,9 +4492,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.17.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a262ae37dd9d60f60dd473d1158f9fbebf110ba7b6a5051c8160460f6043718b" +checksum = "c475786c6f47219345717a043a37ec04cb4bc185e28853adcc4fa0a947eba630" dependencies = [ "webpki", ] @@ -4162,12 +4519,6 @@ dependencies = [ "libc", ] -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - [[package]] name = "winapi" version = "0.3.9" @@ -4178,12 +4529,6 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -4196,7 +4541,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -4205,16 +4550,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "ws2_32-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - [[package]] name = "wyz" version = "0.2.0" @@ -4223,18 +4558,18 @@ checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" [[package]] name = "zeroize" -version = "1.5.0" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc222aec311c323c717f56060324f32b82da1ce1dd81d9a09aa6a9030bfe08db" +checksum = "d68d9dcec5f9b43a30d38c49f91dfedfaac384cb8f085faca366c26207dd1619" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" -version = "1.3.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81e8f13fef10b63c06356d65d416b070798ddabcadc10d3ece0c5be9b3c7eddb" +checksum = "65f1a51723ec88c66d5d1fe80c841f17f63587d6691901d66be9bec6c3b51f73" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index e9be17da0f3cb76619dcb9062e1f0bd7b6c411b2..a3c9cf05bd6f5a5fd3b777396451ae686b093452 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,7 @@ heck = "0.4.0" zip = { version = "0.5.13", default-features = false } parity-wasm = "0.42.2" cargo_metadata = "0.14.1" -codec = { package = "parity-scale-codec", version = "2.3.1", features = ["derive"] } +scale = { package = "parity-scale-codec", version = "2.3.1", features = ["derive"] } which = "4.2.4" colored = "2.0.0" toml = "0.5.8" @@ -43,14 +43,24 @@ url = { version = "2.2.2", features = ["serde"] } impl-serde = "0.3.2" regex = "1.5.4" -# dependencies for optional extrinsics feature -async-std = { version = "1.10.0", optional = true } -sp-core = { version = "2.0.1", optional = true } -subxt = { version = "0.14.0", package = "substrate-subxt", optional = true } -futures = { version = "0.3.21", optional = true } -hex = { version = "0.4.3", optional = true } - -funty = "2.0.0" +# dependencies for extrinsics (deploying and calling a contract) +async-std = { version = "1.10.0", features = ["attributes", "tokio1"] } +ink_metadata = { version = "3.0.0-rc8", features = ["derive"] } +ink_env = "3.0.0-rc8" +scale-info = { version = "1.0.0", default-features = false, features = ["derive"] } +sp-core = "5.0.0" +sp-runtime = "5.0.0" +pallet-contracts-primitives = "5.0.0" +subxt = "0.17.0" +futures = "0.3.19" +hex = "0.4.3" +jsonrpsee = { version = "0.6.1", features = ["ws-client"] } +nom = "7.1.0" +nom-supreme = "0.6.0" +indexmap = "1.8.0" +thiserror = "1.0.30" +escape8259 = "0.5.1" +itertools = "0.10.3" [build-dependencies] anyhow = "1.0.53" @@ -60,19 +70,28 @@ substrate-build-script-utils = "3.0.0" platforms = "2.0.0" [dev-dependencies] +assert_cmd = "2.0.4" assert_matches = "1.5.0" pretty_assertions = "1.1.0" wabt = "0.10.0" +regex = "1.5.4" +predicates = "2.1.1" -[features] -default = [] +ink_primitives = "3.0.0-rc8" +ink_storage = "3.0.0-rc8" +ink_lang = "3.0.0-rc8" -# Enable this for (experimental) commands to deploy, instantiate and call contracts. -# -# Disabled by default -extrinsics = ["sp-core", "subxt", "async-std", "futures", "hex"] +[features] +# This `std` feature is required for testing using an inline contract's metadata, because `ink!` annotates the metadata +# generation code with `#[cfg(feature = "std")]`. +default = ["std"] +std = [] # Enable this to execute long running tests, which usually are only run on the CI server # # Disabled by default test-ci-only = [] + +# Enable this to execute tests which depend on a locally running contracts enabed chain +# e.g.https://github.com/paritytech/canvas-node +integration-tests = [] diff --git a/README.md b/README.md index 132655afa565cac336b6f54205b97cc7942b104f..3ef662a3ae84da141127b461a3542146ee97079f 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,18 @@ artifact to the `target/` directory. Runs test suites defined for a smart contract off-chain. +##### `cargo contract upload` + +Upload a contract to a `pallet-contracts` enabled chain. See [extrinsics](docs/extrinsics.md). + +##### `cargo contract instantiate` + +Create an instance of a contract on chain. See [extrinsics](docs/extrinsics.md). + +##### `cargo contract call` + +Invoke a message on an existing contract on chain. See [extrinsics](docs/extrinsics.md). + ## License The entire code within this repository is licensed under the [GPLv3](LICENSE). diff --git a/docs/extrinsics.md b/docs/extrinsics.md new file mode 100644 index 0000000000000000000000000000000000000000..3a4ce0ba65727012447c218b52ebd352ae60a1a7 --- /dev/null +++ b/docs/extrinsics.md @@ -0,0 +1,103 @@ +# Extrinsics +`cargo-contract` provides CLI support for uploading, instantiating and calling your contracts directly from the command +line. + +## Common arguments + +``` +--suri +``` +The Secret URI used for signing the extrinsic. For development chains, the well known endowed accounts can be used e.g. +`//Alice`. For other accounts, the actual secret key must be provided e.g. an `0x` prefixed 64 bit hex string, or the +seed phrase. See usage of [`subkey`](https://docs.substrate.io/v3/tools/subkey/) for examples, and docs for the expected +values in the [parsing code](https://docs.rs/sp-core/latest/sp_core/crypto/trait.Pair.html#method.from_string_with_seed). + +:warning: **WARNING** :warning: + +It is strongly recommended NOT to use secret keys from actual value bearing chains on the command line, since they are +visible on screen and are often saved to the command line shell's history. For now this tool should only be used for +development and testnets. It is a priority to implement a safer method of signing here before using this tool with value +bearing chains. + +``` +--password +``` +*Optional*. The password for the `--suri`, see https://docs.substrate.io/v3/tools/subkey/#password-protected-keys. + +``` +--manifest-path +``` +*Optional*. The path to the `Cargo.toml` of the contract crate. Use this to run commands on a contract from outside of +its project directory. + +``` +--url +``` +*Optional*. The websockets url of an RPC node on the target chain. Defaults to a locally running node at +"ws://localhost:9944". + +``` +---dry-run +``` +*Optional*. All extrinsic commands can be run without altering the chain state. Useful for testing if a command will be +successful, estimating gas costs or querying the result of `ink!` readonly messages. + +``` +--storage-deposit-limit +``` +*Optional*. The maximum amount of balance that can be charged from the caller to pay for the storage consumed. + +## Commands + +### `upload` + +Upload the Wasm code of the contract to the target chain. Invokes the [`upload_code`](https://github.com/paritytech/substrate/blob/master/frame/contracts/src/lib.rs#L509) +dispatchable. + +e.g. `cargo contract upload --suri //Alice` + +Assumes that `cargo contract build` has already been run to produce the contract artifacts. + +### `instantiate` + +Create an instance of a contract on chain. If the code has already been uploaded via `upload`, specify the resulting +`--code-hash` which will result in a call to [`instantiate`](https://github.com/paritytech/substrate/blob/master/frame/contracts/src/lib.rs#L460). +If no `--code-hash` is specified it will attempt to both upload the code and instantiate via the +[`instantiate_with_code`](https://github.com/paritytech/substrate/blob/master/frame/contracts/src/lib.rs#L419) +dispatchable. + +e.g. +``` +cargo contract instantiate \ + --constructor new \ + --args false \ + --suri //Alice \ + --code-hash 0xbc1b42256696c8a4187ec3ed79fc602789fc11287c4c30926f5e31ed8169574e +``` +- `--constructor` the name of the contract constructor method to invoke. +- `--args` accepts a space separated list of values, encoded in order as the arguments of the constructor to invoke. +- `--code-hash` the hash of the uploaded code, returned from a call to `contract upload` or a previous +`contract instantiate` + +### `call` + +Invoke a message on an instance of a contract via the [`call`](https://github.com/paritytech/substrate/blob/master/frame/contracts/src/lib.rs#L359) +dispatchable. + +e.g. +``` +cargo contract call \ + --contract 5FKy7RwXBCCACCEPjM5WugkhUd787FjdgieTkdj7TPngJzxN \ + --message transfer \ + --args 5FKy7RwXBCCACCEPjM5WugkhUd787FjdgieTkdj7TPngJzxN 1000 \ + --suri //Alice +``` + +- `--contract` the account id of the contract to invoke, returned after a successful `contract instantiate`. +- `--message` the name of the contract message to invoke. +- `--args` accepts a space separated list of values, encoded in order as the arguments of the message to invoke. + + + + + diff --git a/src/cmd/deploy.rs b/src/cmd/deploy.rs deleted file mode 100644 index 2c58f754c8102e8f64ef781083cce7dfe8837e1a..0000000000000000000000000000000000000000 --- a/src/cmd/deploy.rs +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2018-2021 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 std::{fs, io::Read, path::PathBuf}; - -use anyhow::{Context, Result}; -use sp_core::H256; -use subxt::{contracts::*, ClientBuilder, DefaultNodeRuntime}; - -use crate::{crate_metadata, ExtrinsicOpts}; - -/// Load the wasm blob from the specified path. -/// -/// Defaults to the target contract wasm in the current project, inferred via the crate metadata. -fn load_contract_code(path: Option<&PathBuf>) -> Result> { - let contract_wasm_path = match path { - Some(path) => path.clone(), - None => { - let metadata = crate_metadata::CrateMetadata::collect(&Default::default())?; - metadata.dest_wasm - } - }; - log::info!("Contract code path: {}", contract_wasm_path.display()); - let mut data = Vec::new(); - let mut file = fs::File::open(&contract_wasm_path) - .context(format!("Failed to open {}", contract_wasm_path.display()))?; - file.read_to_end(&mut data)?; - - Ok(data) -} - -/// Put contract code to a smart contract enabled substrate chain. -/// Returns the code hash of the deployed contract if successful. -/// -/// Optionally supply the contract wasm path, defaults to destination contract file inferred from -/// Cargo.toml of the current contract project. -/// -/// Creates an extrinsic with the `Contracts::put_code` Call, submits via RPC, then waits for -/// the `ContractsEvent::CodeStored` event. -pub(crate) fn execute_deploy( - extrinsic_opts: &ExtrinsicOpts, - contract_wasm_path: Option<&PathBuf>, -) -> Result { - let code = load_contract_code(contract_wasm_path)?; - - async_std::task::block_on(async move { - let cli = ClientBuilder::::new() - .set_url(&extrinsic_opts.url.to_string()) - .build() - .await?; - let signer = extrinsic_opts.signer()?; - - let events = cli.put_code_and_watch(&signer, &code).await?; - let code_stored = events - .code_stored()? - .context("Failed to find CodeStored event")?; - - Ok(code_stored.code_hash) - }) -} - -#[cfg(test)] -mod tests { - use std::{fs, io::Write}; - - use crate::{cmd::deploy::execute_deploy, util::tests::with_tmp_dir, ExtrinsicOpts}; - use assert_matches::assert_matches; - - const CONTRACT: &str = r#" -(module - (func (export "call")) - (func (export "deploy")) -) -"#; - - #[test] - #[ignore] // depends on a local substrate node running - fn deploy_contract() { - with_tmp_dir(|path| { - let wasm = wabt::wat2wasm(CONTRACT).expect("invalid wabt"); - - let wasm_path = path.join("test.wasm"); - let mut file = fs::File::create(&wasm_path).unwrap(); - let _ = file.write_all(&wasm); - - let url = url::Url::parse("ws://localhost:9944").unwrap(); - let extrinsic_opts = ExtrinsicOpts { - url, - suri: "//Alice".into(), - password: None, - }; - let result = execute_deploy(&extrinsic_opts, Some(&wasm_path)); - - assert_matches!(result, Ok(_)); - Ok(()) - }) - } -} diff --git a/src/cmd/extrinsics/call.rs b/src/cmd/extrinsics/call.rs new file mode 100644 index 0000000000000000000000000000000000000000..9168c7812157a58cfcf941ac84b9b7389cd73b2c --- /dev/null +++ b/src/cmd/extrinsics/call.rs @@ -0,0 +1,175 @@ +// Copyright 2018-2020 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 super::{ + display_contract_exec_result, display_events, load_metadata, parse_balance, + wait_for_success_and_handle_error, Balance, ContractMessageTranscoder, ExtrinsicOpts, + PairSigner, RuntimeApi, EXEC_RESULT_MAX_KEY_COL_WIDTH, +}; +use crate::name_value_println; +use anyhow::Result; +use jsonrpsee::{ + types::{to_json_value, traits::Client as _}, + ws_client::WsClientBuilder, +}; +use serde::Serialize; +use sp_core::Bytes; +use std::fmt::Debug; +use structopt::StructOpt; +use subxt::{rpc::NumberOrHex, ClientBuilder, Config, DefaultConfig, Signer}; + +type ContractExecResult = pallet_contracts_primitives::ContractExecResult; + +#[derive(Debug, StructOpt)] +#[structopt(name = "call", about = "Call a contract")] +pub struct CallCommand { + /// The address of the the contract to call. + #[structopt(name = "contract", long, env = "CONTRACT")] + contract: ::AccountId, + /// The name of the contract message to call. + #[structopt(long, short)] + message: String, + /// The arguments of the contract message to call. + #[structopt(long)] + args: Vec, + #[structopt(flatten)] + extrinsic_opts: ExtrinsicOpts, + /// Maximum amount of gas to be used for this command. + #[structopt(name = "gas", long, default_value = "50000000000")] + gas_limit: u64, + /// The value to be transferred as part of the call. + #[structopt(name = "value", long, parse(try_from_str = parse_balance), default_value = "0")] + value: Balance, +} + +impl CallCommand { + pub fn run(&self) -> Result<()> { + let (_, contract_metadata) = load_metadata(self.extrinsic_opts.manifest_path.as_ref())?; + let transcoder = ContractMessageTranscoder::new(&contract_metadata); + let call_data = transcoder.encode(&self.message, &self.args)?; + let signer = super::pair_signer(self.extrinsic_opts.signer()?); + + async_std::task::block_on(async { + if self.extrinsic_opts.dry_run { + self.call_rpc(call_data, &signer, &transcoder).await + } else { + self.call(call_data, &signer, &transcoder).await + } + }) + } + + async fn call_rpc( + &self, + data: Vec, + signer: &PairSigner, + transcoder: &ContractMessageTranscoder<'_>, + ) -> Result<()> { + let url = self.extrinsic_opts.url.to_string(); + let cli = WsClientBuilder::default().build(&url).await?; + let storage_deposit_limit = self + .extrinsic_opts + .storage_deposit_limit + .as_ref() + .map(|limit| NumberOrHex::Hex((*limit).into())); + let call_request = RpcCallRequest { + origin: signer.account_id().clone(), + dest: self.contract.clone(), + value: NumberOrHex::Hex(self.value.into()), + gas_limit: NumberOrHex::Number(self.gas_limit), + storage_deposit_limit, + input_data: Bytes(data), + }; + let params = vec![to_json_value(call_request)?]; + let result: ContractExecResult = cli.request("contracts_call", Some(params.into())).await?; + + match result.result { + Ok(ref ret_val) => { + let value = transcoder.decode_return(&self.message, &mut &ret_val.data.0[..])?; + name_value_println!( + "Result", + String::from("Success!"), + EXEC_RESULT_MAX_KEY_COL_WIDTH + ); + name_value_println!( + "Reverted", + format!("{:?}", ret_val.did_revert()), + EXEC_RESULT_MAX_KEY_COL_WIDTH + ); + name_value_println!("Data", format!("{}", value), EXEC_RESULT_MAX_KEY_COL_WIDTH); + } + Err(err) => { + name_value_println!( + "Result", + format!("Error: {:?}", err), + EXEC_RESULT_MAX_KEY_COL_WIDTH + ); + } + } + display_contract_exec_result(&result)?; + Ok(()) + } + + async fn call( + &self, + data: Vec, + signer: &PairSigner, + transcoder: &ContractMessageTranscoder<'_>, + ) -> Result<()> { + let url = self.extrinsic_opts.url.to_string(); + let api = ClientBuilder::new() + .set_url(&url) + .build() + .await? + .to_runtime_api::(); + + log::debug!("calling contract {:?}", self.contract); + let tx_progress = api + .tx() + .contracts() + .call( + self.contract.clone().into(), + self.value, + self.gas_limit, + self.extrinsic_opts.storage_deposit_limit, + data, + ) + .sign_and_submit_then_watch(signer) + .await?; + + let result = wait_for_success_and_handle_error(tx_progress).await?; + + display_events( + &result, + transcoder, + api.client.metadata(), + &self.extrinsic_opts.verbosity()?, + ) + } +} + +/// A struct that encodes RPC parameters required for a call to a smart-contract. +/// +/// Copied from pallet-contracts-rpc +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct RpcCallRequest { + origin: ::AccountId, + dest: ::AccountId, + value: NumberOrHex, + gas_limit: NumberOrHex, + storage_deposit_limit: Option, + input_data: Bytes, +} diff --git a/src/cmd/extrinsics/events.rs b/src/cmd/extrinsics/events.rs new file mode 100644 index 0000000000000000000000000000000000000000..5b00baad439f75ef2ea1a2a361c93ab5dae78b43 --- /dev/null +++ b/src/cmd/extrinsics/events.rs @@ -0,0 +1,98 @@ +// Copyright 2018-2020 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 super::{ + runtime_api::api::contracts::events::ContractEmitted, + transcode::{env_types, ContractMessageTranscoder, TranscoderBuilder}, +}; +use crate::{maybe_println, Verbosity, DEFAULT_KEY_COL_WIDTH}; +use colored::Colorize as _; + +use anyhow::Result; +use scale::Input; +use subxt::{self, DefaultConfig, Event, TransactionEvents}; + +pub fn display_events( + result: &TransactionEvents, + transcoder: &ContractMessageTranscoder, + subxt_metadata: &subxt::Metadata, + verbosity: &Verbosity, +) -> Result<()> { + if matches!(verbosity, Verbosity::Quiet) { + return Ok(()); + } + + if matches!(verbosity, Verbosity::Verbose) { + println!("VERBOSE") + } + + let runtime_metadata = subxt_metadata.runtime_metadata(); + let events_transcoder = TranscoderBuilder::new(&runtime_metadata.types) + .register_custom_type::(env_types::AccountId) + .done(); + + const EVENT_FIELD_INDENT: usize = DEFAULT_KEY_COL_WIDTH - 3; + + for event in result.as_slice() { + log::debug!("displaying event {}::{}", event.pallet, event.variant); + + let event_metadata = subxt_metadata.event(event.pallet_index, event.variant_index)?; + let event_fields = event_metadata.variant().fields(); + + println!( + "{:>width$} {} ➜ {}", + "Event".bright_green().bold(), + event.pallet.bright_white(), + event.variant.bright_white().bold(), + width = DEFAULT_KEY_COL_WIDTH + ); + let event_data = &mut &event.data[..]; + let mut unnamed_field_name = 0; + for field in event_fields { + if ::is_event(&event.pallet, &event.variant) + && field.name() == Some(&"data".to_string()) + { + // data is a byte vec so the first byte is the length. + let _data_len = event_data.read_byte()?; + let contract_event = transcoder.decode_contract_event(event_data)?; + maybe_println!( + verbosity, + "{:width$}{}", + "", + format!("{}: {}", "data".bright_white(), contract_event), + width = EVENT_FIELD_INDENT + ); + } else { + let field_name = field.name().cloned().unwrap_or_else(|| { + let name = unnamed_field_name.to_string(); + unnamed_field_name += 1; + name + }); + + let decoded_field = events_transcoder.decode(field.ty().id(), event_data)?; + maybe_println!( + verbosity, + "{:width$}{}", + "", + format!("{}: {}", field_name.bright_white(), decoded_field), + width = EVENT_FIELD_INDENT + ); + } + } + } + println!(); + Ok(()) +} diff --git a/src/cmd/extrinsics/instantiate.rs b/src/cmd/extrinsics/instantiate.rs new file mode 100644 index 0000000000000000000000000000000000000000..06bd4814fd93e5f30e05ec7f04877fc07899b63e --- /dev/null +++ b/src/cmd/extrinsics/instantiate.rs @@ -0,0 +1,349 @@ +// Copyright 2018-2020 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 super::{ + display_contract_exec_result, display_events, parse_balance, runtime_api::api, + wait_for_success_and_handle_error, Balance, CodeHash, ContractAccount, + ContractMessageTranscoder, ExtrinsicOpts, PairSigner, RuntimeApi, + EXEC_RESULT_MAX_KEY_COL_WIDTH, +}; +use crate::{name_value_println, util::decode_hex, Verbosity}; +use anyhow::{anyhow, Context, Result}; +use jsonrpsee::{ + types::{to_json_value, traits::Client as _}, + ws_client::WsClientBuilder, +}; +use serde::Serialize; +use sp_core::{crypto::Ss58Codec, Bytes}; +use std::{ + fs, + path::{Path, PathBuf}, +}; +use structopt::StructOpt; +use subxt::{rpc::NumberOrHex, ClientBuilder, Config, DefaultConfig, Signer}; + +type ContractInstantiateResult = + pallet_contracts_primitives::ContractInstantiateResult; + +#[derive(Debug, StructOpt)] +pub struct InstantiateCommand { + /// Path to wasm contract code, defaults to `./target/ink/.wasm`. + /// Use to instantiate contracts which have not yet been uploaded. + /// If the contract has already been uploaded use `--code-hash` instead. + #[structopt(parse(from_os_str))] + wasm_path: Option, + /// The hash of the smart contract code already uploaded to the chain. + /// If the contract has not already been uploaded use `--wasm-path` or run the `upload` command + /// first. + #[structopt(long, parse(try_from_str = parse_code_hash))] + code_hash: Option<::Hash>, + /// The name of the contract constructor to call + #[structopt(name = "constructor", long, default_value = "new")] + constructor: String, + /// The constructor arguments, encoded as strings + #[structopt(long)] + args: Vec, + #[structopt(flatten)] + extrinsic_opts: ExtrinsicOpts, + /// Transfers an initial balance to the instantiated contract + #[structopt(name = "value", long, default_value = "0", parse(try_from_str = parse_balance))] + value: Balance, + /// Maximum amount of gas to be used for this command + #[structopt(name = "gas", long, default_value = "50000000000")] + gas_limit: u64, + /// A salt used in the address derivation of the new contract. Use to create multiple instances + /// of the same contract code from the same account. + #[structopt(long, parse(try_from_str = parse_hex_bytes))] + salt: Option, +} + +/// Parse a hex encoded 32 byte hash. Returns error if not exactly 32 bytes. +fn parse_code_hash(input: &str) -> Result<::Hash> { + let bytes = decode_hex(input)?; + if bytes.len() != 32 { + anyhow::bail!("Code hash should be 32 bytes in length") + } + let mut arr = [0u8; 32]; + arr.copy_from_slice(&bytes); + Ok(arr.into()) +} + +/// Parse hex encoded bytes. +fn parse_hex_bytes(input: &str) -> Result { + let bytes = decode_hex(input)?; + Ok(bytes.into()) +} + +impl InstantiateCommand { + /// Instantiate a contract stored at the supplied code hash. + /// Returns the account id of the instantiated contract if successful. + /// + /// Creates an extrinsic with the `Contracts::instantiate` Call, submits via RPC, then waits for + /// the `ContractsEvent::Instantiated` event. + pub fn run(&self) -> Result<()> { + let (crate_metadata, contract_metadata) = + super::load_metadata(self.extrinsic_opts.manifest_path.as_ref())?; + let transcoder = ContractMessageTranscoder::new(&contract_metadata); + let data = transcoder.encode(&self.constructor, &self.args)?; + let signer = super::pair_signer(self.extrinsic_opts.signer()?); + let url = self.extrinsic_opts.url.clone(); + let verbosity = self.extrinsic_opts.verbosity()?; + + fn load_code(wasm_path: &Path) -> Result { + log::info!("Contract code path: {}", wasm_path.display()); + let code = fs::read(&wasm_path) + .context(format!("Failed to read from {}", wasm_path.display()))?; + Ok(Code::Upload(code.into())) + } + + let code = match (self.wasm_path.as_ref(), self.code_hash.as_ref()) { + (Some(_), Some(_)) => Err(anyhow!( + "Specify either `--wasm-path` or `--code-hash` but not both" + )), + (Some(wasm_path), None) => load_code(wasm_path), + (None, None) => { + // default to the target contract wasm in the current project, + // inferred via the crate metadata. + load_code(&crate_metadata.dest_wasm) + } + (None, Some(code_hash)) => Ok(Code::Existing(*code_hash)), + }?; + let salt = self.salt.clone().unwrap_or_else(|| Bytes(Vec::new())); + + let args = InstantiateArgs { + value: self.value, + gas_limit: self.gas_limit, + storage_deposit_limit: self.extrinsic_opts.storage_deposit_limit, + data, + salt, + }; + + let exec = Exec { + args, + url, + verbosity, + signer, + transcoder, + }; + + async_std::task::block_on(async move { exec.exec(code, self.extrinsic_opts.dry_run).await }) + } +} + +struct InstantiateArgs { + value: super::Balance, + gas_limit: u64, + storage_deposit_limit: Option, + data: Vec, + salt: Bytes, +} + +pub struct Exec<'a> { + args: InstantiateArgs, + verbosity: Verbosity, + url: url::Url, + signer: PairSigner, + transcoder: ContractMessageTranscoder<'a>, +} + +impl<'a> Exec<'a> { + async fn subxt_api(&self) -> Result { + let api = ClientBuilder::new() + .set_url(self.url.to_string()) + .build() + .await? + .to_runtime_api::(); + Ok(api) + } + + async fn exec(&self, code: Code, dry_run: bool) -> Result<()> { + if dry_run { + let result = self.instantiate_dry_run(code).await?; + match result.result { + Ok(ref ret_val) => { + name_value_println!( + "Result", + String::from("Success!"), + EXEC_RESULT_MAX_KEY_COL_WIDTH + ); + name_value_println!( + "Contract", + ret_val.account_id.to_ss58check(), + EXEC_RESULT_MAX_KEY_COL_WIDTH + ); + name_value_println!( + "Reverted", + format!("{:?}", ret_val.result.did_revert()), + EXEC_RESULT_MAX_KEY_COL_WIDTH + ); + name_value_println!( + "Data", + format!("{:?}", ret_val.result.data), + EXEC_RESULT_MAX_KEY_COL_WIDTH + ); + } + Err(err) => { + name_value_println!( + "Result", + format!("Error: {:?}", err), + EXEC_RESULT_MAX_KEY_COL_WIDTH + ); + } + } + display_contract_exec_result(&result)?; + return Ok(()); + } + + match code { + Code::Upload(code) => { + let (code_hash, contract_account) = self.instantiate_with_code(code).await?; + name_value_println!("Code hash", format!("{:?}", code_hash)); + name_value_println!("Contract", contract_account.to_ss58check()); + } + Code::Existing(code_hash) => { + let contract_account = self.instantiate(code_hash).await?; + name_value_println!("Contract", contract_account.to_ss58check()); + } + } + Ok(()) + } + + async fn instantiate_with_code(&self, code: Bytes) -> Result<(CodeHash, ContractAccount)> { + let api = self.subxt_api().await?; + let tx_progress = api + .tx() + .contracts() + .instantiate_with_code( + self.args.value, + self.args.gas_limit, + self.args.storage_deposit_limit, + code.to_vec(), + self.args.data.clone(), + self.args.salt.0.clone(), + ) + .sign_and_submit_then_watch(&self.signer) + .await?; + + let result = wait_for_success_and_handle_error(tx_progress).await?; + + let metadata = api.client.metadata(); + + display_events(&result, &self.transcoder, metadata, &self.verbosity)?; + + let code_stored = result + .find_first_event::()? + .ok_or(anyhow!("Failed to find CodeStored event"))?; + let instantiated = result + .find_first_event::()? + .ok_or(anyhow!("Failed to find Instantiated event"))?; + + Ok((code_stored.code_hash, instantiated.contract)) + } + + async fn instantiate(&self, code_hash: CodeHash) -> Result { + let api = self.subxt_api().await?; + let tx_progress = api + .tx() + .contracts() + .instantiate( + self.args.value, + self.args.gas_limit, + self.args.storage_deposit_limit, + code_hash, + self.args.data.clone(), + self.args.salt.0.clone(), + ) + .sign_and_submit_then_watch(&self.signer) + .await?; + + let result = wait_for_success_and_handle_error(tx_progress).await?; + + let metadata = api.client.metadata(); + display_events(&result, &self.transcoder, metadata, &self.verbosity)?; + + let instantiated = result + .find_first_event::()? + .ok_or(anyhow!("Failed to find Instantiated event"))?; + + Ok(instantiated.contract) + } + + async fn instantiate_dry_run(&self, code: Code) -> Result { + let url = self.url.to_string(); + let cli = WsClientBuilder::default().build(&url).await?; + let storage_deposit_limit = self + .args + .storage_deposit_limit + .as_ref() + .map(|limit| NumberOrHex::Hex((*limit).into())); + let call_request = InstantiateRequest { + origin: self.signer.account_id().clone(), + value: NumberOrHex::Hex(self.args.value.into()), + gas_limit: NumberOrHex::Number(self.args.gas_limit), + storage_deposit_limit, + code, + data: self.args.data.clone().into(), + salt: self.args.salt.clone(), + }; + let params = vec![to_json_value(call_request)?]; + let result: ContractInstantiateResult = cli + .request("contracts_instantiate", Some(params.into())) + .await?; + Ok(result) + } +} + +/// A struct that encodes RPC parameters required to instantiate a new smart-contract. +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct InstantiateRequest { + origin: ::AccountId, + value: NumberOrHex, + gas_limit: NumberOrHex, + storage_deposit_limit: Option, + code: Code, + data: Bytes, + salt: Bytes, +} + +/// Reference to an existing code hash or a new wasm module. +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +enum Code { + /// A wasm module as raw bytes. + Upload(Bytes), + /// The code hash of an on-chain wasm blob. + Existing(::Hash), +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn parse_code_hash_works() { + // with 0x prefix + assert!(parse_code_hash( + "0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d" + ) + .is_ok()); + // without 0x prefix + assert!( + parse_code_hash("d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d") + .is_ok() + ) + } +} diff --git a/src/cmd/extrinsics/integration_tests.rs b/src/cmd/extrinsics/integration_tests.rs new file mode 100644 index 0000000000000000000000000000000000000000..df77309815fb6f3353ed52b0ae30d026e8db1aa4 --- /dev/null +++ b/src/cmd/extrinsics/integration_tests.rs @@ -0,0 +1,227 @@ +// Copyright 2018-2020 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 anyhow::Result; +use predicates::prelude::*; +use std::{ffi::OsStr, path::Path, process, str, thread, time}; +use subxt::{Client, ClientBuilder}; + +const CONTRACTS_NODE: &str = "substrate-contracts-node"; + +/// Create a `cargo contract` command +fn cargo_contract(path: &Path) -> assert_cmd::Command { + let mut cmd = assert_cmd::Command::cargo_bin("cargo-contract").unwrap(); + cmd.current_dir(path).arg("contract"); + cmd +} + +/// Spawn and manage an instance of a compatible contracts enabled chain node. +#[allow(dead_code)] +struct ContractsNodeProcess { + proc: process::Child, + tmp_dir: tempfile::TempDir, + client: Client, +} + +impl Drop for ContractsNodeProcess { + fn drop(&mut self) { + self.kill() + } +} + +impl ContractsNodeProcess { + async fn spawn(program: S) -> Result + where + S: AsRef, + { + let tmp_dir = tempfile::Builder::new() + .prefix("cargo-contract.cli.test.node") + .tempdir()?; + + let mut proc = process::Command::new(program) + .env("RUST_LOG", "error") + .arg("--dev") + .arg(format!("--base-path={}", tmp_dir.path().to_string_lossy())) + .spawn()?; + // wait for rpc to be initialized + const MAX_ATTEMPTS: u32 = 10; + let mut attempts = 1; + let client = loop { + thread::sleep(time::Duration::from_secs(1)); + log::info!( + "Connecting to contracts enabled node, attempt {}/{}", + attempts, + MAX_ATTEMPTS + ); + let result = ClientBuilder::new().build().await; + if let Ok(client) = result { + break Ok(client); + } + if attempts < MAX_ATTEMPTS { + attempts += 1; + continue; + } + if let Err(err) = result { + break Err(err); + } + }; + match client { + Ok(client) => Ok(Self { + proc, + client, + tmp_dir, + }), + Err(err) => { + let err = anyhow::anyhow!( + "Failed to connect to node rpc after {} attempts: {}", + attempts, + err + ); + log::error!("{}", err); + proc.kill()?; + Err(err) + } + } + } + + fn kill(&mut self) { + log::info!("Killing contracts node process {}", self.proc.id()); + if let Err(err) = self.proc.kill() { + log::error!( + "Error killing contracts node process {}: {}", + self.proc.id(), + err + ) + } + } +} + +/// Sanity test the whole lifecycle of: +/// new -> build -> upload -> instantiate -> call +/// +/// # Note +/// +/// Requires [substrate-contracts-node](https://github.com/paritytech/substrate-contracts-node/) to +/// be installed and available on the `PATH`, and the no other process running using the default +/// port `9944`. +/// +/// ** This test is ignored for now since the substrate-contracts-node is not installed on CI ** +/// It will be addressed in a follow up PR, for now it can be run locally by commenting out the +/// `ignore` attribute below +#[ignore] +#[async_std::test] +async fn build_upload_instantiate_call() { + env_logger::try_init().ok(); + + let tmp_dir = tempfile::Builder::new() + .prefix("cargo-contract.cli.test.") + .tempdir() + .expect("temporary directory creation failed"); + + // Spawn the contracts node + let node_process = ContractsNodeProcess::spawn(CONTRACTS_NODE) + .await + .expect("Error spawning contracts node"); + + log::info!( + "Creating new contract in temporary directory {}", + tmp_dir.path().to_string_lossy() + ); + + // cargo contract new flipper + cargo_contract(tmp_dir.path()) + .arg("new") + .arg("flipper") + .assert() + .success(); + + // cd flipper + let mut project_path = tmp_dir.path().to_path_buf(); + project_path.push("flipper"); + + log::info!("Building contract in {}", project_path.to_string_lossy()); + cargo_contract(project_path.as_path()) + .arg("build") + .assert() + .success(); + + log::info!("Uploading the code to the substrate-contracts-node chain"); + let output = cargo_contract(project_path.as_path()) + .arg("upload") + .args(&["--suri", "//Alice"]) + .output() + .expect("failed to execute process"); + println!("status: {}", output.status); + let stdout = str::from_utf8(&output.stdout).unwrap(); + let stderr = str::from_utf8(&output.stderr).unwrap(); + assert!(output.status.success(), "upload code failed: {}", stderr); + + // find the code hash in the output + let regex = regex::Regex::new("0x([0-9A-Fa-f]+)").unwrap(); + let caps = regex.captures(stdout).expect("Failed to find codehash"); + let code_hash = caps.get(1).unwrap().as_str(); + assert_eq!(64, code_hash.len()); + + log::info!("Instantiating the contract with code hash `{}`", code_hash); + let output = cargo_contract(project_path.as_path()) + .arg("instantiate") + .args(&["--constructor", "new"]) + .args(&["--args", "true"]) + .args(&["--code-hash", code_hash]) + .args(&["--suri", "//Alice"]) + .output() + .expect("failed to execute process"); + let stdout = str::from_utf8(&output.stdout).unwrap(); + let stderr = str::from_utf8(&output.stderr).unwrap(); + assert!(output.status.success(), "instantiate failed: {}", stderr); + + // find the contract address in the output + let regex = regex::Regex::new("Contract ([0-9A-Za-z]+)").unwrap(); + let caps = regex + .captures(stdout) + .expect("contract account regex capture"); + let contract_account = caps.get(1).unwrap().as_str(); + assert_eq!(48, contract_account.len(), "{:?}", stdout); + + let call_get_rpc = |expected: bool| { + cargo_contract(project_path.as_path()) + .arg("call") + .args(&["--message", "get"]) + .args(&["--contract", contract_account]) + .args(&["--suri", "//Alice"]) + .arg("--dry-run") + .assert() + .stdout(predicate::str::contains(expected.to_string())); + }; + + // call the `get` message via rpc to assert that it was set to the initial value + call_get_rpc(true); + + log::info!("Calling flip on the contract `{}`", contract_account); + cargo_contract(project_path.as_path()) + .arg("call") + .args(&["--message", "flip"]) + .args(&["--contract", contract_account]) + .args(&["--suri", "//Alice"]) + .assert() + .stdout(predicate::str::contains("ExtrinsicSuccess")); + + // call the `get` message via rpc to assert that the value has been flipped + call_get_rpc(false); + + // prevent the node_process from being dropped and killed + let _ = node_process; +} diff --git a/src/cmd/extrinsics/mod.rs b/src/cmd/extrinsics/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..77c49dfbfa52cb668d9dccfa0720d56f869ab34a --- /dev/null +++ b/src/cmd/extrinsics/mod.rs @@ -0,0 +1,207 @@ +// Copyright 2018-2020 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 . + +mod call; +mod events; +mod instantiate; +mod runtime_api; +mod transcode; +mod upload; + +#[cfg(test)] +#[cfg(feature = "integration-tests")] +mod integration_tests; + +use anyhow::{anyhow, Context, Result}; +use std::{fs::File, path::PathBuf}; + +use self::{events::display_events, transcode::ContractMessageTranscoder}; +use crate::{ + crate_metadata::CrateMetadata, name_value_println, workspace::ManifestPath, Verbosity, + VerbosityFlags, +}; +use pallet_contracts_primitives::ContractResult; +use sp_core::{crypto::Pair, sr25519}; +use structopt::StructOpt; +use subxt::{Config, DefaultConfig}; + +pub use call::CallCommand; +pub use instantiate::InstantiateCommand; +pub use upload::UploadCommand; + +type Balance = u128; +type CodeHash = ::Hash; +type ContractAccount = ::AccountId; +type PairSigner = subxt::PairSigner; +type SignedExtra = subxt::DefaultExtra; +type RuntimeApi = runtime_api::api::RuntimeApi; + +/// Arguments required for creating and sending an extrinsic to a substrate node +#[derive(Clone, Debug, StructOpt)] +pub struct ExtrinsicOpts { + /// Path to the Cargo.toml of the contract + #[structopt(long, parse(from_os_str))] + manifest_path: Option, + /// Websockets url of a substrate node + #[structopt( + name = "url", + long, + parse(try_from_str), + default_value = "ws://localhost:9944" + )] + url: url::Url, + /// Secret key URI for the account deploying the contract. + #[structopt(name = "suri", long, short)] + suri: String, + /// Password for the secret key + #[structopt(name = "password", long, short)] + password: Option, + #[structopt(flatten)] + verbosity: VerbosityFlags, + /// Dry-run the extrinsic via rpc, instead of as an extrinsic. Chain state will not be mutated. + #[structopt(long, short = "rpc")] + dry_run: bool, + /// The maximum amount of balance that can be charged from the caller to pay for the storage + /// consumed. + #[structopt(long, parse(try_from_str = parse_balance))] + storage_deposit_limit: Option, +} + +impl ExtrinsicOpts { + pub fn signer(&self) -> Result { + sr25519::Pair::from_string(&self.suri, self.password.as_ref().map(String::as_ref)) + .map_err(|_| anyhow::anyhow!("Secret string error")) + } + + /// Returns the verbosity + pub fn verbosity(&self) -> Result { + TryFrom::try_from(&self.verbosity) + } +} + +/// For a contract project with its `Cargo.toml` at the specified `manifest_path`, load the cargo +/// [`CrateMetadata`] along with the contract metadata [`ink_metadata::InkProject`]. +pub fn load_metadata( + manifest_path: Option<&PathBuf>, +) -> Result<(CrateMetadata, ink_metadata::InkProject)> { + let manifest_path = ManifestPath::try_from(manifest_path)?; + let crate_metadata = CrateMetadata::collect(&manifest_path)?; + let path = crate_metadata.metadata_path(); + + if !path.exists() { + return Err(anyhow!( + "Metadata file not found. Try building with `cargo contract build`." + )); + } + + let file = + File::open(&path).context(format!("Failed to open metadata file {}", path.display()))?; + let metadata: contract_metadata::ContractMetadata = serde_json::from_reader(file).context( + format!("Failed to deserialize metadata file {}", path.display()), + )?; + let ink_metadata = + serde_json::from_value(serde_json::Value::Object(metadata.abi)).context(format!( + "Failed to deserialize ink project metadata from file {}", + path.display() + ))?; + if let ink_metadata::MetadataVersioned::V3(ink_project) = ink_metadata { + Ok((crate_metadata, ink_project)) + } else { + Err(anyhow!("Unsupported ink metadata version. Expected V1")) + } +} + +/// Parse Rust style integer balance literals which can contain underscores. +fn parse_balance(input: &str) -> Result { + input + .replace('_', "") + .parse::() + .map_err(Into::into) +} + +/// Create a new [`PairSigner`] from the given [`sr25519::Pair`]. +pub fn pair_signer(pair: sr25519::Pair) -> PairSigner { + PairSigner::new(pair) +} + +const STORAGE_DEPOSIT_KEY: &str = "Storage Deposit"; +pub const EXEC_RESULT_MAX_KEY_COL_WIDTH: usize = STORAGE_DEPOSIT_KEY.len() + 1; + +/// Print to stdout the fields of the result of a `instantiate` or `call` dry-run via RPC. +pub fn display_contract_exec_result(result: &ContractResult) -> Result<()> { + let mut debug_message_lines = std::str::from_utf8(&result.debug_message) + .context("Error decoding UTF8 debug message bytes")? + .lines(); + name_value_println!( + "Gas Consumed", + format!("{:?}", result.gas_consumed), + EXEC_RESULT_MAX_KEY_COL_WIDTH + ); + name_value_println!( + "Gas Required", + format!("{:?}", result.gas_required), + EXEC_RESULT_MAX_KEY_COL_WIDTH + ); + name_value_println!( + STORAGE_DEPOSIT_KEY, + format!("{:?}", result.storage_deposit), + EXEC_RESULT_MAX_KEY_COL_WIDTH + ); + + // print debug messages aligned, only first line has key + if let Some(debug_message) = debug_message_lines.next() { + name_value_println!( + "Debug Message", + format!("{}", debug_message), + EXEC_RESULT_MAX_KEY_COL_WIDTH + ); + } + + for debug_message in debug_message_lines { + name_value_println!( + "", + format!("{}", debug_message), + EXEC_RESULT_MAX_KEY_COL_WIDTH + ); + } + Ok(()) +} + +/// Wait for the transaction to be included successfully into a block. +/// +/// # Errors +/// +/// If a runtime Module error occurs, this will only display the pallet and error indices. Dynamic +/// lookups of the actual error will be available once the following issue is resolved: +/// . +/// +/// # Finality +/// +/// Currently this will report success once the transaction is included in a block. In the future +/// there could be a flag to wait for finality before reporting success. +async fn wait_for_success_and_handle_error( + tx_progress: subxt::TransactionProgress<'_, T, runtime_api::api::DispatchError>, +) -> Result> +where + T: Config, +{ + tx_progress + .wait_for_in_block() + .await? + .wait_for_success() + .await + .map_err(Into::into) +} diff --git a/src/cmd/extrinsics/runtime_api/contracts_runtime.scale b/src/cmd/extrinsics/runtime_api/contracts_runtime.scale new file mode 100644 index 0000000000000000000000000000000000000000..328f70ed12bc456e4e2ccc33abd71e01a3845878 Binary files /dev/null and b/src/cmd/extrinsics/runtime_api/contracts_runtime.scale differ diff --git a/src/cmd/extrinsics/runtime_api/mod.rs b/src/cmd/extrinsics/runtime_api/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..024b30bbb4bafc270fa6dbb5a2b974dc1afaa8af --- /dev/null +++ b/src/cmd/extrinsics/runtime_api/mod.rs @@ -0,0 +1,18 @@ +// Copyright 2018-2020 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 . + +#[subxt::subxt(runtime_metadata_path = "src/cmd/extrinsics/runtime_api/contracts_runtime.scale")] +pub mod api {} diff --git a/src/cmd/extrinsics/transcode/decode.rs b/src/cmd/extrinsics/transcode/decode.rs new file mode 100644 index 0000000000000000000000000000000000000000..06c34a30967c27fa0b4f9ca681b90ddd275e97ec --- /dev/null +++ b/src/cmd/extrinsics/transcode/decode.rs @@ -0,0 +1,278 @@ +// Copyright 2018-2020 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 super::{ + env_types::EnvTypesTranscoder, + scon::{Map, Tuple, Value}, + CompositeTypeFields, +}; +use anyhow::Result; +use scale::{Compact, Decode, Input}; +use scale_info::{ + form::{Form, PortableForm}, + Field, PortableRegistry, Type, TypeDef, TypeDefCompact, TypeDefPrimitive, TypeDefVariant, +}; + +pub struct Decoder<'a> { + registry: &'a PortableRegistry, + env_types: &'a EnvTypesTranscoder, +} + +impl<'a> Decoder<'a> { + pub fn new(registry: &'a PortableRegistry, env_types: &'a EnvTypesTranscoder) -> Self { + Self { + registry, + env_types, + } + } + + pub fn decode(&self, type_id: u32, input: &mut &[u8]) -> Result { + let ty = self + .registry + .resolve(type_id) + .ok_or_else(|| anyhow::anyhow!("Failed to resolve type with id `{:?}`", type_id))?; + log::debug!( + "Decoding input with type id `{:?}` and definition `{:?}`", + type_id, + ty + ); + match self.env_types.try_decode(type_id, input) { + // Value was decoded with custom decoder for type. + Ok(Some(value)) => Ok(value), + // No custom decoder registered so attempt default decoding. + Ok(None) => self.decode_type(ty, input), + Err(e) => Err(e), + } + } + + fn decode_seq( + &self, + ty: &::Type, + len: usize, + input: &mut &[u8], + ) -> Result { + let ty = self + .registry + .resolve(ty.id()) + .ok_or_else(|| anyhow::anyhow!("Failed to find type with id '{}'", ty.id()))?; + + if *ty.type_def() == TypeDef::Primitive(TypeDefPrimitive::U8) { + let mut bytes = vec![0u8; len]; + input.read(&mut bytes)?; + Ok(Value::Bytes(bytes.into())) + } else { + let mut elems = Vec::new(); + while elems.len() < len as usize { + let elem = self.decode_type(ty, input)?; + elems.push(elem) + } + Ok(Value::Seq(elems.into())) + } + } + + fn decode_type(&self, ty: &Type, input: &mut &[u8]) -> Result { + match ty.type_def() { + TypeDef::Composite(composite) => { + let ident = ty.path().segments().last().map(|s| s.as_str()); + self.decode_composite(ident, composite.fields(), input) + } + TypeDef::Tuple(tuple) => { + let mut elems = Vec::new(); + for field_type in tuple.fields() { + let value = self.decode(field_type.id(), input)?; + elems.push(value); + } + Ok(Value::Tuple(Tuple::new( + None, + elems.into_iter().collect::>(), + ))) + } + TypeDef::Variant(variant) => self.decode_variant_type(variant, input), + TypeDef::Array(array) => { + self.decode_seq(array.type_param(), array.len() as usize, input) + } + TypeDef::Sequence(sequence) => { + let len = >::decode(input)?; + self.decode_seq(sequence.type_param(), len.0 as usize, input) + } + TypeDef::Primitive(primitive) => self.decode_primitive(primitive, input), + TypeDef::Compact(compact) => self.decode_compact(compact, input), + TypeDef::BitSequence(_) => Err(anyhow::anyhow!("bitvec decoding not yet supported")), + } + } + + pub fn decode_composite( + &self, + ident: Option<&str>, + fields: &[Field], + input: &mut &[u8], + ) -> Result { + let struct_type = CompositeTypeFields::from_fields(fields)?; + + match struct_type { + CompositeTypeFields::Named(fields) => { + let mut map = Vec::new(); + for field in fields { + let value = self.decode(field.field().ty().id(), input)?; + map.push((Value::String(field.name().to_string()), value)); + } + Ok(Value::Map(Map::new(ident, map.into_iter().collect()))) + } + CompositeTypeFields::Unnamed(fields) => { + let mut tuple = Vec::new(); + for field in &fields { + let value = self.decode(field.ty().id(), input)?; + tuple.push(value); + } + Ok(Value::Tuple(Tuple::new( + ident, + tuple.into_iter().collect::>(), + ))) + } + CompositeTypeFields::NoFields => Ok(Value::Tuple(Tuple::new(ident, Vec::new()))), + } + } + + fn decode_variant_type( + &self, + variant_type: &TypeDefVariant, + input: &mut &[u8], + ) -> Result { + let discriminant = input.read_byte()?; + let variant = variant_type + .variants() + .get(discriminant as usize) + .ok_or_else(|| { + anyhow::anyhow!("No variant found with discriminant {}", discriminant) + })?; + + let mut named = Vec::new(); + let mut unnamed = Vec::new(); + for field in variant.fields() { + let value = self.decode(field.ty().id(), input)?; + if let Some(name) = field.name() { + named.push((Value::String(name.to_owned()), value)); + } else { + unnamed.push(value); + } + } + if !named.is_empty() && !unnamed.is_empty() { + Err(anyhow::anyhow!( + "Variant must have either all named or all unnamed fields" + )) + } else if !named.is_empty() { + Ok(Value::Map(Map::new( + Some(variant.name()), + named.into_iter().collect(), + ))) + } else { + Ok(Value::Tuple(Tuple::new(Some(variant.name()), unnamed))) + } + } + + fn decode_primitive(&self, primitive: &TypeDefPrimitive, input: &mut &[u8]) -> Result { + match primitive { + TypeDefPrimitive::Bool => Ok(Value::Bool(bool::decode(input)?)), + TypeDefPrimitive::Char => Err(anyhow::anyhow!("scale codec not implemented for char")), + TypeDefPrimitive::Str => Ok(Value::String(String::decode(input)?)), + TypeDefPrimitive::U8 => decode_uint::(input), + TypeDefPrimitive::U16 => decode_uint::(input), + TypeDefPrimitive::U32 => decode_uint::(input), + TypeDefPrimitive::U64 => decode_uint::(input), + TypeDefPrimitive::U128 => decode_uint::(input), + TypeDefPrimitive::U256 => Err(anyhow::anyhow!("U256 currently not supported")), + TypeDefPrimitive::I8 => decode_int::(input), + TypeDefPrimitive::I16 => decode_int::(input), + TypeDefPrimitive::I32 => decode_int::(input), + TypeDefPrimitive::I64 => decode_int::(input), + TypeDefPrimitive::I128 => decode_int::(input), + TypeDefPrimitive::I256 => Err(anyhow::anyhow!("I256 currently not supported")), + } + } + + fn decode_compact( + &self, + compact: &TypeDefCompact, + input: &mut &[u8], + ) -> Result { + let mut decode_compact_primitive = |primitive: &TypeDefPrimitive| match primitive { + TypeDefPrimitive::U8 => Ok(Value::UInt(Compact::::decode(input)?.0.into())), + TypeDefPrimitive::U16 => Ok(Value::UInt(Compact::::decode(input)?.0.into())), + TypeDefPrimitive::U32 => Ok(Value::UInt(Compact::::decode(input)?.0.into())), + TypeDefPrimitive::U64 => Ok(Value::UInt(Compact::::decode(input)?.0.into())), + TypeDefPrimitive::U128 => Ok(Value::UInt(Compact::::decode(input)?.into())), + prim => Err(anyhow::anyhow!( + "{:?} not supported. Expected unsigned int primitive.", + prim + )), + }; + + let type_id = compact.type_param().id(); + let ty = self + .registry + .resolve(type_id) + .ok_or_else(|| anyhow::anyhow!("Failed to resolve type with id `{:?}`", type_id))?; + match ty.type_def() { + TypeDef::Primitive(primitive) => decode_compact_primitive(primitive), + TypeDef::Composite(composite) => match composite.fields() { + [field] => { + let type_id = field.ty().id(); + let field_ty = self.registry.resolve(type_id).ok_or_else(|| { + anyhow::anyhow!("Failed to resolve type with id `{:?}`", type_id) + })?; + if let TypeDef::Primitive(primitive) = field_ty.type_def() { + let struct_ident = ty.path().segments().last().map(|s| s.as_str()); + let field_value = decode_compact_primitive(primitive)?; + let compact_composite = match field.name() { + Some(name) => Value::Map(Map::new( + struct_ident, + vec![(Value::String(name.to_string()), field_value)] + .into_iter() + .collect(), + )), + None => Value::Tuple(Tuple::new(struct_ident, vec![field_value])), + }; + Ok(compact_composite) + } else { + Err(anyhow::anyhow!( + "Composite type must have a single primitive field" + )) + } + } + _ => Err(anyhow::anyhow!("Composite type must have a single field")), + }, + _ => Err(anyhow::anyhow!( + "Compact type must be a primitive or a composite type" + )), + } + } +} + +fn decode_uint(input: &mut &[u8]) -> Result +where + T: Decode + Into, +{ + let decoded = T::decode(input)?; + Ok(Value::UInt(decoded.into())) +} + +fn decode_int(input: &mut &[u8]) -> Result +where + T: Decode + Into, +{ + let decoded = T::decode(input)?; + Ok(Value::Int(decoded.into())) +} diff --git a/src/cmd/extrinsics/transcode/encode.rs b/src/cmd/extrinsics/transcode/encode.rs new file mode 100644 index 0000000000000000000000000000000000000000..d64c1e9189cae8d596c909ba8fb06b8e2d86cf20 --- /dev/null +++ b/src/cmd/extrinsics/transcode/encode.rs @@ -0,0 +1,428 @@ +// Copyright 2018-2020 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 super::{env_types::EnvTypesTranscoder, scon::Value, CompositeTypeFields}; +use anyhow::Result; +use itertools::Itertools; +use scale::{Compact, Encode, Output}; +use scale_info::{ + form::{Form, PortableForm}, + Field, PortableRegistry, TypeDef, TypeDefCompact, TypeDefPrimitive, TypeDefTuple, + TypeDefVariant, +}; +use std::{ + convert::{TryFrom, TryInto}, + error::Error, + fmt::Debug, + str::FromStr, +}; + +pub struct Encoder<'a> { + registry: &'a PortableRegistry, + env_types: &'a EnvTypesTranscoder, +} + +impl<'a> Encoder<'a> { + pub fn new(registry: &'a PortableRegistry, env_types: &'a EnvTypesTranscoder) -> Self { + Self { + registry, + env_types, + } + } + + pub fn encode(&self, type_id: u32, value: &Value, output: &mut O) -> Result<()> + where + O: Output + Debug, + { + let ty = self + .registry + .resolve(type_id) + .ok_or_else(|| anyhow::anyhow!("Failed to resolve type with id '{:?}'", type_id))?; + + log::debug!( + "Encoding value `{:?}` with type id `{:?}` and definition `{:?}`", + value, + type_id, + ty.type_def(), + ); + if !self.env_types.try_encode(type_id, value, output)? { + self.encode_type(ty.type_def(), value, output) + .map_err(|e| anyhow::anyhow!("Error encoding value for {:?}: {}", ty, e))? + } + Ok(()) + } + + fn encode_type( + &self, + type_def: &TypeDef, + value: &Value, + output: &mut O, + ) -> Result<()> { + match type_def { + TypeDef::Composite(composite) => { + self.encode_composite(composite.fields(), value, output) + } + TypeDef::Variant(variant) => self.encode_variant_type(variant, value, output), + TypeDef::Array(array) => self.encode_seq(array.type_param(), value, false, output), + TypeDef::Tuple(tuple) => self.encode_tuple(tuple, value, output), + TypeDef::Sequence(sequence) => { + self.encode_seq(sequence.type_param(), value, true, output) + } + TypeDef::Primitive(primitive) => self.encode_primitive(primitive, value, output), + TypeDef::Compact(compact) => self.encode_compact(compact, value, output), + TypeDef::BitSequence(_) => Err(anyhow::anyhow!("bitvec encoding not yet supported")), + } + } + + fn encode_composite( + &self, + fields: &[Field], + value: &Value, + output: &mut O, + ) -> Result<()> { + let struct_type = CompositeTypeFields::from_fields(fields)?; + + match value { + Value::Map(map) => match struct_type { + CompositeTypeFields::Unnamed(fields) => { + for (field, value) in fields.iter().zip(map.values()) { + self.encode(field.ty().id(), value, output)?; + } + Ok(()) + } + CompositeTypeFields::NoFields => Ok(()), + CompositeTypeFields::Named(named_fields) => { + for named_field in named_fields { + let field_name = named_field.name(); + let value = map.get_by_str(field_name).ok_or_else(|| { + anyhow::anyhow!("Missing a field named `{}`", field_name) + })?; + self.encode(named_field.field().ty().id(), value, output) + .map_err(|e| { + anyhow::anyhow!("Error encoding field `{}`: {}", field_name, e) + })?; + } + Ok(()) + } + }, + Value::Tuple(tuple) => match struct_type { + CompositeTypeFields::Unnamed(fields) => { + for (field, value) in fields.iter().zip(tuple.values()) { + self.encode(field.ty().id(), value, output)?; + } + Ok(()) + } + CompositeTypeFields::NoFields => Ok(()), + CompositeTypeFields::Named(_) => { + return Err(anyhow::anyhow!("Type is a struct requiring named fields")) + } + }, + v => { + if let Ok(single_field) = fields.iter().exactly_one() { + self.encode(single_field.ty().id(), value, output) + } else { + Err(anyhow::anyhow!( + "Expected a Map or a Tuple or a single Value for a composite data type, found {:?}", + v + )) + } + } + } + } + + fn encode_tuple( + &self, + tuple: &TypeDefTuple, + value: &Value, + output: &mut O, + ) -> Result<()> { + match value { + Value::Tuple(tuple_val) => { + for (field_type, value) in tuple.fields().iter().zip(tuple_val.values()) { + self.encode(field_type.id(), value, output)?; + } + Ok(()) + } + v => { + if let Ok(single_field) = tuple.fields().iter().exactly_one() { + self.encode(single_field.id(), value, output) + } else { + Err(anyhow::anyhow!( + "Expected a Tuple or a single Value for a tuple data type, found {:?}", + v + )) + } + } + } + } + + fn encode_variant_type( + &self, + variant_def: &TypeDefVariant, + value: &Value, + output: &mut O, + ) -> Result<()> { + let variant_ident = match value { + Value::Map(map) => map + .ident() + .ok_or(anyhow::anyhow!("Missing enum variant identifier for map")), + Value::Tuple(tuple) => tuple + .ident() + .ok_or(anyhow::anyhow!("Missing enum variant identifier for tuple")), + v => Err(anyhow::anyhow!("Invalid enum variant value '{:?}'", v)), + }?; + + let (index, variant) = variant_def + .variants() + .iter() + .find_position(|v| v.name() == &variant_ident) + .ok_or_else(|| anyhow::anyhow!("No variant '{}' found", variant_ident))?; + + let index: u8 = index + .try_into() + .map_err(|_| anyhow::anyhow!("Variant index > 255"))?; + output.push_byte(index); + + self.encode_composite(variant.fields(), value, output) + } + + fn encode_seq( + &self, + ty: &::Type, + value: &Value, + encode_len: bool, + output: &mut O, + ) -> Result<()> { + let ty = self + .registry + .resolve(ty.id()) + .ok_or_else(|| anyhow::anyhow!("Failed to find type with id '{}'", ty.id()))?; + match value { + Value::Seq(values) => { + if encode_len { + Compact(values.len() as u32).encode_to(output); + } + for value in values.elems() { + self.encode_type(ty.type_def(), value, output)?; + } + } + Value::Bytes(bytes) => { + if encode_len { + Compact(bytes.bytes().len() as u32).encode_to(output); + } + for byte in bytes.bytes() { + output.push_byte(*byte); + } + } + value => return Err(anyhow::anyhow!("{:?} cannot be encoded as an array", value)), + } + Ok(()) + } + + fn encode_primitive( + &self, + primitive: &TypeDefPrimitive, + value: &Value, + output: &mut O, + ) -> Result<()> { + match primitive { + TypeDefPrimitive::Bool => { + if let Value::Bool(b) = value { + b.encode_to(output); + Ok(()) + } else { + Err(anyhow::anyhow!("Expected a bool value")) + } + } + TypeDefPrimitive::Char => Err(anyhow::anyhow!("scale codec not implemented for char")), + TypeDefPrimitive::Str => { + if let Value::String(s) = value { + s.encode_to(output); + Ok(()) + } else { + Err(anyhow::anyhow!("Expected a String value")) + } + } + TypeDefPrimitive::U8 => encode_uint::(value, "u8", output), + TypeDefPrimitive::U16 => encode_uint::(value, "u16", output), + TypeDefPrimitive::U32 => encode_uint::(value, "u32", output), + TypeDefPrimitive::U64 => encode_uint::(value, "u64", output), + TypeDefPrimitive::U128 => encode_uint::(value, "u128", output), + TypeDefPrimitive::U256 => Err(anyhow::anyhow!("U256 currently not supported")), + TypeDefPrimitive::I8 => encode_int::(value, "i8", output), + TypeDefPrimitive::I16 => encode_int::(value, "i16", output), + TypeDefPrimitive::I32 => encode_int::(value, "i32", output), + TypeDefPrimitive::I64 => encode_int::(value, "i64", output), + TypeDefPrimitive::I128 => encode_int::(value, "i128", output), + TypeDefPrimitive::I256 => Err(anyhow::anyhow!("I256 currently not supported")), + } + } + + fn encode_compact( + &self, + compact: &TypeDefCompact, + value: &Value, + output: &mut O, + ) -> Result<()> { + let mut encode_compact_primitive = + |primitive: &TypeDefPrimitive, value: &Value| match primitive { + TypeDefPrimitive::U8 => { + let uint = uint_from_value::(value, "u8")?; + Compact(uint).encode_to(output); + Ok(()) + } + TypeDefPrimitive::U16 => { + let uint = uint_from_value::(value, "u16")?; + Compact(uint).encode_to(output); + Ok(()) + } + TypeDefPrimitive::U32 => { + let uint = uint_from_value::(value, "u32")?; + Compact(uint).encode_to(output); + Ok(()) + } + TypeDefPrimitive::U64 => { + let uint = uint_from_value::(value, "u64")?; + Compact(uint).encode_to(output); + Ok(()) + } + TypeDefPrimitive::U128 => { + let uint = uint_from_value::(value, "u128")?; + Compact(uint).encode_to(output); + Ok(()) + } + _ => Err(anyhow::anyhow!( + "Compact encoding not supported for {:?}", + primitive + )), + }; + + let ty = self + .registry + .resolve(compact.type_param().id()) + .ok_or_else(|| { + anyhow::anyhow!( + "Failed to resolve type with id '{:?}'", + compact.type_param().id() + ) + })?; + match ty.type_def() { + TypeDef::Primitive(primitive) => encode_compact_primitive(primitive, value), + TypeDef::Composite(composite) => match composite.fields() { + [field] => { + let type_id = field.ty().id(); + let field_ty = self.registry.resolve(type_id).ok_or_else(|| { + anyhow::anyhow!("Failed to resolve type with id `{:?}`", type_id) + })?; + if let TypeDef::Primitive(primitive) = field_ty.type_def() { + let field_values: Vec<_> = match value { + Value::Map(map) => Ok(map.values().collect()), + Value::Tuple(tuple) => Ok(tuple.values().collect()), + x => Err(anyhow::anyhow!( + "Compact composite value must be a Map or a Tuple. Found {}", + x + )), + }?; + if field_values.len() == 1 { + let field_value = field_values[0]; + encode_compact_primitive(primitive, field_value) + } else { + Err(anyhow::anyhow!( + "Compact composite value must have a single field" + )) + } + } else { + Err(anyhow::anyhow!( + "Composite type must have a single primitive field" + )) + } + } + _ => Err(anyhow::anyhow!("Composite type must have a single field")), + }, + _ => Err(anyhow::anyhow!( + "Compact type must be a primitive or a composite type" + )), + } + } +} + +fn uint_from_value(value: &Value, expected: &str) -> Result +where + T: TryFrom + FromStr, + >::Error: Error + Send + Sync + 'static, + ::Err: Error + Send + Sync + 'static, +{ + match value { + Value::UInt(i) => { + let uint = (*i).try_into()?; + Ok(uint) + } + Value::String(s) => { + let sanitized = s.replace(&['_', ','][..], ""); + let uint = T::from_str(&sanitized)?; + Ok(uint) + } + _ => Err(anyhow::anyhow!( + "Expected a {} or a String value, got {}", + expected, + value + )), + } +} + +fn encode_uint(value: &Value, expected: &str, output: &mut O) -> Result<()> +where + T: TryFrom + FromStr + Encode, + >::Error: Error + Send + Sync + 'static, + ::Err: Error + Send + Sync + 'static, + O: Output, +{ + let uint: T = uint_from_value(value, expected)?; + uint.encode_to(output); + Ok(()) +} + +fn encode_int(value: &Value, expected: &str, output: &mut O) -> Result<()> +where + T: TryFrom + TryFrom + FromStr + Encode, + >::Error: Error + Send + Sync + 'static, + >::Error: Error + Send + Sync + 'static, + ::Err: Error + Send + Sync + 'static, + O: Output, +{ + let int = match value { + Value::Int(i) => { + let i: T = (*i).try_into()?; + Ok(i) + } + Value::UInt(u) => { + let i: T = (*u).try_into()?; + Ok(i) + } + Value::String(s) => { + let sanitized = s.replace(&['_', ','][..], ""); + let i = T::from_str(&sanitized)?; + Ok(i) + } + _ => Err(anyhow::anyhow!( + "Expected a {} or a String value, got {}", + expected, + value + )), + }?; + int.encode_to(output); + Ok(()) +} diff --git a/src/cmd/extrinsics/transcode/env_types.rs b/src/cmd/extrinsics/transcode/env_types.rs new file mode 100644 index 0000000000000000000000000000000000000000..9989c7c0070a029e4d818d57a7e2ab2696486895 --- /dev/null +++ b/src/cmd/extrinsics/transcode/env_types.rs @@ -0,0 +1,141 @@ +// Copyright 2018-2020 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 super::scon::Value; +use anyhow::Result; +use scale::{Decode, Encode, Output}; +use scale_info::{form::PortableForm, IntoPortable, Path, TypeInfo}; +use sp_core::crypto::{AccountId32, Ss58Codec}; +use std::{boxed::Box, collections::HashMap, convert::TryFrom, str::FromStr}; + +/// Provides custom encoding and decoding for predefined environment types. +#[derive(Default)] +pub struct EnvTypesTranscoder { + transcoders: HashMap>, +} + +impl EnvTypesTranscoder { + /// Construct an `EnvTypesTranscoder` from the given type registry. + pub fn new(transcoders: HashMap>) -> Self { + Self { transcoders } + } + + /// If the given type id is for a type with custom encoding, encodes the given value with the + /// custom encoder and returns `true`. Otherwise returns `false`. + /// + /// # Errors + /// + /// - If the custom encoding fails. + pub fn try_encode(&self, type_id: u32, value: &Value, output: &mut O) -> Result + where + O: Output, + { + match self.transcoders.get(&type_id) { + Some(transcoder) => { + log::debug!("Encoding type {:?} with custom encoder", type_id); + let encoded_env_type = transcoder.encode_value(value)?; + output.write(&encoded_env_type); + Ok(true) + } + None => Ok(false), + } + } + + /// If the given type lookup id is for an environment type with custom + /// decoding, decodes the given input with the custom decoder and returns + /// `Some(value)`. Otherwise returns `None`. + /// + /// # Errors + /// + /// - If the custom decoding fails. + pub fn try_decode(&self, type_id: u32, input: &mut &[u8]) -> Result> { + match self.transcoders.get(&type_id) { + Some(transcoder) => { + log::debug!("Decoding type {:?} with custom decoder", type_id); + let decoded = transcoder.decode_value(input)?; + Ok(Some(decoded)) + } + None => { + log::debug!("No custom decoder found for type {:?}", type_id); + Ok(None) + } + } + } +} + +/// Implement this trait to define custom transcoding for a type in a `scale-info` type registry. +pub trait CustomTypeTranscoder { + fn aliases(&self) -> &[&str]; + fn encode_value(&self, value: &Value) -> Result>; + fn decode_value(&self, input: &mut &[u8]) -> Result; +} + +#[derive(Clone, Debug, Eq, PartialEq, Hash)] +pub struct PathKey(Vec); + +impl PathKey { + pub fn from_type() -> Self + where + T: TypeInfo, + { + let type_info = T::type_info(); + let path = type_info + .path() + .clone() + .into_portable(&mut Default::default()); + PathKey::from(&path) + } +} + +impl From<&Path> for PathKey { + fn from(path: &Path) -> Self { + PathKey(path.segments().to_vec()) + } +} + +pub type TypesByPath = HashMap; + +pub struct AccountId; + +impl CustomTypeTranscoder for AccountId { + fn aliases(&self) -> &[&'static str] { + &["AccountId"] + } + fn encode_value(&self, value: &Value) -> Result> { + let account_id = match value { + Value::Literal(literal) => AccountId32::from_str(literal).map_err(|e| { + anyhow::anyhow!("Error parsing AccountId from literal `{}`: {}", literal, e) + })?, + Value::String(string) => AccountId32::from_str(string).map_err(|e| { + anyhow::anyhow!("Error parsing AccountId from string '{}': {}", string, e) + })?, + Value::Bytes(bytes) => AccountId32::try_from(bytes.bytes()).map_err(|_| { + anyhow::anyhow!("Error converting bytes `{:?}` to AccountId", bytes) + })?, + _ => { + return Err(anyhow::anyhow!( + "Expected a string or a literal for an AccountId" + )) + } + }; + Ok(account_id.encode()) + } + + fn decode_value(&self, input: &mut &[u8]) -> Result { + let account_id = AccountId32::decode(input)?; + Ok(Value::Literal(account_id.to_ss58check())) + } +} diff --git a/src/cmd/extrinsics/transcode/mod.rs b/src/cmd/extrinsics/transcode/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..5bc5072966564501a9713c02e4d5306e6aefef36 --- /dev/null +++ b/src/cmd/extrinsics/transcode/mod.rs @@ -0,0 +1,368 @@ +// Copyright 2018-2020 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 . + +//! For interacting with contracts from the command line, arguments need to be "transcoded" from +//! the string representation to the SCALE encoded representation. +//! +//! e.g. `"false" -> 0x00` +//! +//! And for displaying SCALE encoded data from events and RPC responses, it must be "transcoded" +//! in the other direction from the SCALE encoded representation to a human readable string. +//! +//! e.g. `0x00 -> "false"` +//! +//! Transcoding depends on [`scale-info`](https://github.com/paritytech/scale-info/) metadata in +//! order to dynamically determine the expected types. +//! +//! # Encoding +//! +//! First the string is parsed into an intermediate [`Value`]: +//! +//! `"false" -> Value::Bool(false)` +//! +//! This value is then matched with the metadata for the expected type in that context. e.g. the +//! [flipper](https://github.com/paritytech/ink/blob/master/examples/flipper/lib.rs) contract +//! accepts a `bool` argument to its `new` constructor, which will be reflected in the contract +//! metadata as [`scale_info::TypeDefPrimitive::Bool`]. +//! +//! ```no_compile +//! #[ink(constructor)] +//! pub fn new(init_value: bool) -> Self { +//! Self { value: init_value } +//! } +//! ``` +//! +//! The parsed `Value::Bool(false)` argument value is then matched with the +//! [`scale_info::TypeDefPrimitive::Bool`] type metadata, and then the value can be safely encoded +//! as a `bool`, resulting in `0x00`, which can then be appended as data to the message to invoke +//! the constructor. +//! +//! # Decoding +//! +//! First the type of the SCALE encoded data is determined from the metadata. e.g. the return type +//! of a message when it is invoked as a "dry run" over RPC: +//! +//! ```no_compile +//! #[ink(message)] +//! pub fn get(&self) -> bool { +//! self.value +//! } +//! ``` +//! +//! The metadata will define the return type as [`scale_info::TypeDefPrimitive::Bool`], so that when +//! the raw data is received it can be decoded into the correct [`Value`], which is then converted +//! to a string for displaying to the user: +//! +//! `0x00 -> Value::Bool(false) -> "false"` +//! +//! # SCALE Object Notation (SCON) +//! +//! Complex types can be represented as strings using `SCON` for human-computer interaction. It is +//! intended to be similar to Rust syntax for instantiating types. e.g. +//! +//! `Foo { a: false, b: [0, 1, 2], c: "bar", d: (0, 1) }` +//! +//! This string could be parsed into a [`Value::Map`] and together with +//! [`scale_info::TypeDefComposite`] metadata could be transcoded into SCALE encoded bytes. +//! +//! As with the example for the primitive `bool` above, this works in the other direction for +//! decoding SCALE encoded bytes and converting them into a human readable string. + +mod decode; +mod encode; +pub mod env_types; +mod scon; +mod transcoder; + +pub use self::{ + scon::{Map, Value}, + transcoder::{Transcoder, TranscoderBuilder}, +}; + +use anyhow::Result; +use ink_metadata::{ConstructorSpec, InkProject, MessageSpec}; +use scale::Input; +use scale_info::{ + form::{Form, PortableForm}, + Field, +}; +use std::fmt::Debug; + +/// Encode strings to SCALE encoded smart contract calls. +/// Decode SCALE encoded smart contract events and return values into `Value` objects. +pub struct ContractMessageTranscoder<'a> { + metadata: &'a InkProject, + transcoder: Transcoder<'a>, +} + +impl<'a> ContractMessageTranscoder<'a> { + pub fn new(metadata: &'a InkProject) -> Self { + let transcoder = TranscoderBuilder::new(metadata.registry()) + .register_custom_type::<::AccountId, _>(env_types::AccountId) + .done(); + Self { + metadata, + transcoder, + } + } + + pub fn encode(&self, name: &str, args: I) -> Result> + where + I: IntoIterator, + S: AsRef + Debug, + { + let (selector, spec_args) = match ( + self.find_constructor_spec(name), + self.find_message_spec(name), + ) { + (Some(c), None) => (c.selector(), c.args()), + (None, Some(m)) => (m.selector(), m.args()), + (Some(_), Some(_)) => { + return Err(anyhow::anyhow!( + "Invalid metadata: both a constructor and message found with name '{}'", + name + )) + } + (None, None) => { + return Err(anyhow::anyhow!( + "No constructor or message with the name '{}' found", + name + )) + } + }; + + let mut encoded = selector.to_bytes().to_vec(); + for (spec, arg) in spec_args.iter().zip(args) { + let value = scon::parse_value(arg.as_ref())?; + self.transcoder + .encode(spec.ty().ty().id(), &value, &mut encoded)?; + } + Ok(encoded) + } + + fn constructors(&self) -> impl Iterator> { + self.metadata.spec().constructors().iter() + } + + fn messages(&self) -> impl Iterator> { + self.metadata.spec().messages().iter() + } + + fn find_message_spec(&self, name: &str) -> Option<&MessageSpec> { + self.messages() + .find(|msg| msg.label().contains(&name.to_string())) + } + + fn find_constructor_spec(&self, name: &str) -> Option<&ConstructorSpec> { + self.constructors() + .find(|msg| msg.label().contains(&name.to_string())) + } + + pub fn decode_contract_event(&self, data: &mut &[u8]) -> Result { + let variant_index = data.read_byte()?; + let event_spec = self + .metadata + .spec() + .events() + .get(variant_index as usize) + .ok_or_else(|| { + anyhow::anyhow!( + "Event variant {} not found in contract metadata", + variant_index + ) + })?; + + let mut args = Vec::new(); + for arg in event_spec.args() { + let name = arg.label().to_string(); + let value = self.transcoder.decode(arg.ty().ty().id(), data)?; + args.push((Value::String(name), value)); + } + + let name = event_spec.label().to_string(); + let map = Map::new(Some(&name), args.into_iter().collect()); + + Ok(Value::Map(map)) + } + + pub fn decode_return(&self, name: &str, data: &mut &[u8]) -> Result { + let msg_spec = self + .find_message_spec(name) + .ok_or_else(|| anyhow::anyhow!("Failed to find message spec with name '{}'", name))?; + if let Some(return_ty) = msg_spec.return_type().opt_type() { + self.transcoder.decode(return_ty.ty().id(), data) + } else { + Ok(Value::Unit) + } + } +} + +#[derive(Debug)] +pub enum CompositeTypeFields { + Named(Vec), + Unnamed(Vec>), + NoFields, +} + +#[derive(Debug)] +pub struct CompositeTypeNamedField { + name: ::String, + field: Field, +} + +impl CompositeTypeNamedField { + pub fn name(&self) -> &str { + &self.name + } + + pub fn field(&self) -> &Field { + &self.field + } +} + +impl CompositeTypeFields { + pub fn from_fields(fields: &[Field]) -> Result { + if fields.iter().next().is_none() { + Ok(Self::NoFields) + } else if fields.iter().all(|f| f.name().is_some()) { + let fields = fields + .iter() + .map(|field| CompositeTypeNamedField { + name: field + .name() + .expect("All fields have a name; qed") + .to_owned(), + field: field.clone(), + }) + .collect(); + Ok(Self::Named(fields)) + } else if fields.iter().all(|f| f.name().is_none()) { + Ok(Self::Unnamed(fields.to_vec())) + } else { + Err(anyhow::anyhow!( + "Struct fields should either be all named or all unnamed" + )) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use scale::Encode; + use scon::Value; + use std::str::FromStr; + + use ink_lang as ink; + + #[ink::contract] + pub mod flipper { + #[ink(storage)] + pub struct Flipper { + value: bool, + } + + impl Flipper { + /// Creates a new flipper smart contract initialized with the given value. + #[ink(constructor)] + pub fn new(init_value: bool) -> Self { + Self { value: init_value } + } + + /// Creates a new flipper smart contract initialized to `false`. + #[ink(constructor)] + pub fn default() -> Self { + Self::new(Default::default()) + } + + /// Flips the current value of the Flipper's bool. + #[ink(message)] + pub fn flip(&mut self) { + self.value = !self.value; + } + + /// Returns the current value of the Flipper's bool. + #[ink(message)] + pub fn get(&self) -> bool { + self.value + } + + /// Dummy setter which receives the env type AccountId. + #[ink(message)] + pub fn set_account_id(&self, account_id: AccountId) { + let _ = account_id; + } + } + } + + fn generate_metadata() -> ink_metadata::InkProject { + extern "Rust" { + fn __ink_generate_metadata() -> ink_metadata::MetadataVersioned; + } + let metadata_versioned = unsafe { __ink_generate_metadata() }; + if let ink_metadata::MetadataVersioned::V3(ink_project) = metadata_versioned { + ink_project + } else { + panic!("Expected metadata V3"); + } + } + + #[test] + fn encode_single_primitive_arg() -> Result<()> { + let metadata = generate_metadata(); + let transcoder = ContractMessageTranscoder::new(&metadata); + + let encoded = transcoder.encode("new", &["true"])?; + // encoded args follow the 4 byte selector + let encoded_args = &encoded[4..]; + + assert_eq!(true.encode(), encoded_args); + Ok(()) + } + + #[test] + fn encode_account_id_custom_ss58_encoding() -> Result<()> { + let metadata = generate_metadata(); + let transcoder = ContractMessageTranscoder::new(&metadata); + + let encoded = transcoder.encode( + "set_account_id", + &["5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"], + )?; + + // encoded args follow the 4 byte selector + let encoded_args = &encoded[4..]; + + let expected = sp_core::crypto::AccountId32::from_str( + "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", + ) + .unwrap(); + assert_eq!(expected.encode(), encoded_args); + Ok(()) + } + + #[test] + fn decode_primitive_return() -> Result<()> { + let metadata = generate_metadata(); + let transcoder = ContractMessageTranscoder::new(&metadata); + + let encoded = true.encode(); + let decoded = transcoder.decode_return("get", &mut &encoded[..])?; + + assert_eq!(Value::Bool(true), decoded); + Ok(()) + } +} diff --git a/src/cmd/extrinsics/transcode/scon/display.rs b/src/cmd/extrinsics/transcode/scon/display.rs new file mode 100644 index 0000000000000000000000000000000000000000..1f35733d596c7fbd8aabd7d99a9ae073307d29f5 --- /dev/null +++ b/src/cmd/extrinsics/transcode/scon/display.rs @@ -0,0 +1,137 @@ +// Copyright 2018-2020 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 super::{Bytes, Map, Seq, Tuple, Value}; +use std::fmt::{Debug, Display, Formatter, LowerHex, Result}; + +/// Wraps Value for custom Debug impl to provide pretty-printed Display +struct DisplayValue<'a>(&'a Value); + +impl<'a> Debug for DisplayValue<'a> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + match &self.0 { + Value::Bool(boolean) => ::fmt(boolean, f), + Value::Char(character) => ::fmt(character, f), + Value::UInt(uint) => ::fmt(uint, f), + Value::Int(integer) => ::fmt(integer, f), + Value::Map(map) => ::fmt(&DisplayMap(map), f), + Value::Tuple(tuple) => ::fmt(&DisplayTuple(tuple), f), + Value::String(string) => ::fmt(string, f), + Value::Seq(seq) => ::fmt(&DisplaySeq(seq), f), + Value::Bytes(bytes) => ::fmt(bytes, f), + Value::Literal(literal) => ::fmt(literal, f), + Value::Unit => write!(f, "()"), + } + } +} + +impl Display for Value { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + match self { + Value::String(string) => ::fmt(string, f), + value => ::fmt(&DisplayValue(value), f), + } + } +} + +struct DisplayMap<'a>(&'a Map); + +impl<'a> Debug for DisplayMap<'a> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + match self.0.ident { + Some(ref name) => { + let mut builder = f.debug_struct(name); + for (name, value) in self.0.map.iter() { + builder.field(&format!("{}", name), &DisplayValue(value)); + } + builder.finish() + } + None => { + let mut builder = f.debug_map(); + for (name, value) in self.0.map.iter() { + builder.entry(name, &DisplayValue(value)); + } + builder.finish() + } + } + } +} + +struct DisplayTuple<'a>(&'a Tuple); + +impl<'a> Debug for DisplayTuple<'a> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + let name = self.0.ident.as_ref().map_or("", |s| s.as_str()); + let mut builder = f.debug_tuple(name); + for value in self.0.values.iter() { + builder.field(&DisplayValue(value)); + } + builder.finish() + } +} + +struct DisplaySeq<'a>(&'a Seq); + +impl<'a> Debug for DisplaySeq<'a> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + let mut builder = f.debug_list(); + for elem in &self.0.elems { + builder.entry(&DisplayValue(elem)); + } + builder.finish() + } +} + +impl Debug for Bytes { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + write!(f, "{:#x}", self) + } +} + +impl LowerHex for Bytes { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + if f.alternate() { + write!(f, "0x{}", hex::encode(&self.bytes)) + } else { + write!(f, "{}", hex::encode(&self.bytes)) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn display_map() { + let map = Value::Map(Map::new( + Some("M"), + vec![(Value::String("a".into()), Value::UInt(1))] + .into_iter() + .collect(), + )); + assert_eq!( + r#"M { a: 1 }"#, + format!("{}", map), + "non-alternate same line" + ); + assert_eq!( + "M {\n a: 1,\n}", + format!("{:#}", map), + "alternate indented (pretty)" + ); + } +} diff --git a/src/cmd/extrinsics/transcode/scon/mod.rs b/src/cmd/extrinsics/transcode/scon/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..5d4acebd4cfedd59435b574241feb0f95b40fd72 --- /dev/null +++ b/src/cmd/extrinsics/transcode/scon/mod.rs @@ -0,0 +1,212 @@ +// Copyright 2018-2020 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 . + +//! SCALE Object Notation (SCON) + +mod display; +mod parse; + +use indexmap::IndexMap; + +use std::{ + cmp::{Eq, Ordering}, + hash::{Hash, Hasher}, + iter::FromIterator, + ops::{Index, IndexMut}, +}; + +pub use self::parse::parse_value; + +#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub enum Value { + Bool(bool), + Char(char), + UInt(u128), + Int(i128), + Map(Map), + Tuple(Tuple), + String(String), + Seq(Seq), + Bytes(Bytes), + Literal(String), + Unit, +} + +#[derive(Clone, Debug)] +pub struct Map { + ident: Option, + map: IndexMap, +} + +impl Eq for Map {} + +impl Hash for Map { + fn hash(&self, state: &mut H) { + self.iter().for_each(|x| x.hash(state)); + } +} + +impl Index<&Value> for Map { + type Output = Value; + + fn index(&self, index: &Value) -> &Self::Output { + &self.map[index] + } +} + +impl IndexMut<&Value> for Map { + fn index_mut(&mut self, index: &Value) -> &mut Self::Output { + self.map.get_mut(index).expect("no entry found for key") + } +} + +impl Ord for Map { + fn cmp(&self, other: &Map) -> Ordering { + self.iter().cmp(other.iter()) + } +} + +/// Note: equality is only given if both values and order of values match +impl PartialEq for Map { + fn eq(&self, other: &Map) -> bool { + if self.map.len() != other.map.len() { + return false; + } + self.iter().zip(other.iter()).all(|(a, b)| a == b) + } +} + +impl PartialOrd for Map { + fn partial_cmp(&self, other: &Map) -> Option { + self.iter().partial_cmp(other.iter()) + } +} + +impl FromIterator<(Value, Value)> for Map { + fn from_iter>(iter: T) -> Self { + Map::new(None, IndexMap::from_iter(iter)) + } +} + +impl Map { + /// Creates a new, empty `Map`. + pub fn new(ident: Option<&str>, map: IndexMap) -> Map { + Map { + ident: ident.map(|s| s.to_string()), + map, + } + } + + /// Return the identifier of the [`Map`]. + pub fn ident(&self) -> Option { + self.ident.clone() + } + + /// Iterate all key-value pairs. + pub fn iter(&self) -> impl Iterator + DoubleEndedIterator { + self.map.iter() + } + + /// Return an iterator over the map's values + pub fn values(&self) -> impl Iterator { + self.map.values() + } + + /// Return a reference to the value stored for string key, if it is present, else None. + pub fn get_by_str(&self, key: &str) -> Option<&Value> { + self.map.get(&Value::String(key.to_string())) + } +} + +#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct Tuple { + ident: Option, + values: Vec, +} + +impl From> for Tuple { + fn from(values: Vec) -> Self { + Tuple { + ident: None, + values, + } + } +} + +impl Tuple { + pub fn new(ident: Option<&str>, values: Vec) -> Self { + Tuple { + ident: ident.map(|s| s.into()), + values, + } + } + + pub fn ident(&self) -> Option { + self.ident.clone() + } + + /// Returns an iterator over the tuple's values + pub fn values(&self) -> impl Iterator { + self.values.iter() + } +} + +#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct Seq { + elems: Vec, +} + +impl From> for Seq { + fn from(elems: Vec) -> Self { + Self::new(elems) + } +} + +impl Seq { + pub fn new(elems: Vec) -> Self { + Seq { elems } + } + + pub fn elems(&self) -> &[Value] { + &self.elems + } + + pub fn len(&self) -> usize { + self.elems.len() + } +} + +#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct Bytes { + bytes: Vec, +} + +impl From> for Bytes { + fn from(bytes: Vec) -> Self { + Self { bytes } + } +} + +impl Bytes { + pub fn from_hex_string(s: &str) -> Result { + let bytes = crate::util::decode_hex(s)?; + Ok(Self { bytes }) + } + + pub fn bytes(&self) -> &[u8] { + &self.bytes + } +} diff --git a/src/cmd/extrinsics/transcode/scon/parse.rs b/src/cmd/extrinsics/transcode/scon/parse.rs new file mode 100644 index 0000000000000000000000000000000000000000..173fba18d7e74320d9a9053985b55e366e79efc2 --- /dev/null +++ b/src/cmd/extrinsics/transcode/scon/parse.rs @@ -0,0 +1,581 @@ +// Copyright 2018-2020 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 super::{Bytes, Map, Tuple, Value}; +use escape8259::unescape; +use nom::{ + branch::alt, + bytes::complete::{tag, take_while1}, + character::complete::{alphanumeric1, anychar, char, digit1, hex_digit1, multispace0}, + multi::{many0, separated_list0}, + sequence::{delimited, pair, separated_pair, tuple}, + AsChar, IResult, Parser, +}; +use nom_supreme::{error::ErrorTree, ParserExt}; + +/// Attempt to parse a SCON value +pub fn parse_value(input: &str) -> anyhow::Result { + let (_, value) = + scon_value(input).map_err(|err| anyhow::anyhow!("Error parsing Value: {}", err))?; + Ok(value) +} + +fn scon_value(input: &str) -> IResult<&str, Value, ErrorTree<&str>> { + ws(alt(( + scon_unit, + scon_bytes, + scon_seq, + scon_tuple, + scon_map, + scon_string, + scon_literal, + scon_integer, + scon_bool, + scon_char, + scon_unit_tuple, + ))) + .context("Value") + .parse(input) +} + +fn scon_string(input: &str) -> IResult<&str, Value, ErrorTree<&str>> { + #[derive(Debug)] + struct UnescapeError(String); + impl std::error::Error for UnescapeError {} + + impl std::fmt::Display for UnescapeError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "Error unescaping string '{}'", self.0) + } + } + + // One or more unescaped text characters + let nonescaped_string = take_while1(|c| { + let cv = c as u32; + // A character that is: + // NOT a control character (0x00 - 0x1F) + // NOT a quote character (0x22) + // NOT a backslash character (0x5C) + // Is within the unicode range (< 0x10FFFF) (this is already guaranteed by Rust char) + (cv >= 0x20) && (cv != 0x22) && (cv != 0x5C) + }); + + // There are only two types of escape allowed by RFC 8259. + // - single-character escapes \" \\ \/ \b \f \n \r \t + // - general-purpose \uXXXX + // Note: we don't enforce that escape codes are valid here. + // There must be a decoder later on. + let escape_code = pair( + tag("\\"), + alt(( + tag("\""), + tag("\\"), + tag("/"), + tag("b"), + tag("f"), + tag("n"), + tag("r"), + tag("t"), + tag("u"), + )), + ) + .recognize(); + + many0(alt((nonescaped_string, escape_code))) + .recognize() + .delimited_by(tag("\"")) + .map_res::<_, _, UnescapeError>(|s: &str| { + let unescaped = unescape(s).map_err(|_| UnescapeError(s.to_string()))?; + Ok(Value::String(unescaped)) + }) + .parse(input) +} + +fn rust_ident(input: &str) -> IResult<&str, &str, ErrorTree<&str>> { + let alpha_or_underscore = anychar.verify(|c: &char| c.is_alpha() || *c == '_'); + + take_while1(|c: char| c.is_alphanumeric() || c == '_') + .preceded_by(alpha_or_underscore.peek()) + .parse(input) +} + +/// Parse a signed or unsigned integer literal, supports optional Rust style underscore separators. +fn scon_integer(input: &str) -> IResult<&str, Value, ErrorTree<&str>> { + let sign = alt((char('+'), char('-'))); + pair(sign.opt(), separated_list0(char('_'), digit1)) + .map_res(|(sign, parts)| { + let digits = parts.join(""); + if let Some(sign) = sign { + let s = format!("{}{}", sign, digits); + s.parse::().map(Value::Int) + } else { + digits.parse::().map(Value::UInt) + } + }) + .parse(input) +} + +fn scon_unit(input: &str) -> IResult<&str, Value, ErrorTree<&str>> { + let (i, _) = tag("()").parse(input)?; + Ok((i, Value::Unit)) +} + +fn scon_bool(input: &str) -> IResult<&str, Value, ErrorTree<&str>> { + alt(( + tag("false").value(Value::Bool(false)), + tag("true").value(Value::Bool(true)), + )) + .parse(input) +} + +fn scon_char(input: &str) -> IResult<&str, Value, ErrorTree<&str>> { + anychar + .delimited_by(char('\'')) + .map(Value::Char) + .parse(input) +} + +fn scon_seq(input: &str) -> IResult<&str, Value, ErrorTree<&str>> { + separated_list0(ws(char(',')), scon_value) + .preceded_by(ws(char('['))) + .terminated(pair(ws(char(',')).opt(), ws(char(']')))) + .map(|seq| Value::Seq(seq.into())) + .parse(input) +} + +fn scon_tuple(input: &str) -> IResult<&str, Value, ErrorTree<&str>> { + let tuple_body = separated_list0(ws(char(',')), scon_value) + .preceded_by(ws(char('('))) + .terminated(pair(ws(char(',')).opt(), ws(char(')')))); + + tuple((ws(rust_ident).opt(), tuple_body)) + .map(|(ident, v)| Value::Tuple(Tuple::new(ident, v.into_iter().collect()))) + .parse(input) +} + +/// Parse a rust ident on its own which could represent a struct with no fields or a enum unit +/// variant e.g. "None" +fn scon_unit_tuple(input: &str) -> IResult<&str, Value, ErrorTree<&str>> { + rust_ident + .map(|ident| Value::Tuple(Tuple::new(Some(ident), Vec::new()))) + .parse(input) +} + +fn scon_map(input: &str) -> IResult<&str, Value, ErrorTree<&str>> { + let opening = alt((tag("("), tag("{"))); + let closing = alt((tag(")"), tag("}"))); + + let ident_key = rust_ident.map(|s| Value::String(s.into())); + let scon_map_key = ws(alt((ident_key, scon_string, scon_integer))); + + let map_body = separated_list0( + ws(char(',')), + separated_pair(scon_map_key, ws(char(':')), scon_value), + ) + .preceded_by(ws(opening)) + .terminated(pair(ws(char(',')).opt(), ws(closing))); + + tuple((ws(rust_ident).opt(), map_body)) + .map(|(ident, v)| Value::Map(Map::new(ident, v.into_iter().collect()))) + .parse(input) +} + +fn scon_bytes(input: &str) -> IResult<&str, Value, ErrorTree<&str>> { + tag("0x") + .precedes(hex_digit1) + .map_res::<_, _, hex::FromHexError>(|byte_str| { + let bytes = Bytes::from_hex_string(byte_str)?; + Ok(Value::Bytes(bytes)) + }) + .parse(input) +} + +/// Parse any alphanumeric literal with more than 39 characters (the length of `u128::MAX`) +/// +/// This is suitable for capturing e.g. Base58 encoded literals for Substrate addresses +fn scon_literal(input: &str) -> IResult<&str, Value, ErrorTree<&str>> { + const MAX_UINT_LEN: usize = 39; + alphanumeric1 + .verify(|s: &&str| s.len() > MAX_UINT_LEN) + .recognize() + .map(|literal: &str| Value::Literal(literal.to_string())) + .parse(input) +} + +fn ws(f: F) -> impl FnMut(I) -> IResult +where + F: FnMut(I) -> IResult, + I: nom::InputTakeAtPosition, + ::Item: nom::AsChar + Clone, + E: nom::error::ParseError, +{ + delimited(multispace0, f, multispace0) +} + +#[cfg(test)] +mod tests { + use super::*; + use assert_matches::assert_matches; + + fn assert_scon_value(input: &str, expected: Value) { + assert_eq!(scon_value(input).unwrap(), ("", expected)); + } + + #[test] + fn test_parse_value() { + assert_eq!(parse_value("true").unwrap(), Value::Bool(true)) + } + + #[test] + fn test_unit() { + assert_eq!(scon_value("()").unwrap(), ("", Value::Unit)); + } + + #[test] + fn test_bool() { + assert_eq!(scon_bool("false").unwrap(), ("", Value::Bool(false))); + assert_eq!(scon_bool("true").unwrap(), ("", Value::Bool(true))); + assert!(scon_bool("foo").is_err()); + } + + #[test] + fn test_integer() { + assert_eq!(scon_integer("42").unwrap(), ("", Value::UInt(42))); + assert_eq!(scon_integer("-123").unwrap(), ("", Value::Int(-123))); + assert_eq!(scon_integer("+456").unwrap(), ("", Value::Int(456))); + assert_eq!(scon_integer("0").unwrap(), ("", Value::UInt(0))); + assert_eq!(scon_integer("01").unwrap(), ("", Value::UInt(1))); + assert_eq!( + scon_integer("340282366920938463463374607431768211455").unwrap(), + ("", Value::UInt(340282366920938463463374607431768211455)) + ); + + // underscore separators + assert_eq!( + scon_integer("1_000_000").unwrap(), + ("", Value::UInt(1_000_000)) + ); + assert_eq!( + scon_integer("-2_000_000").unwrap(), + ("", Value::Int(-2_000_000)) + ); + assert_eq!( + scon_integer("+3_000_000").unwrap(), + ("", Value::Int(3_000_000)) + ); + assert_eq!( + scon_integer("340_282_366_920_938_463_463_374_607_431_768_211_455").unwrap(), + ("", Value::UInt(340282366920938463463374607431768211455)) + ); + + // too many digits + assert_matches!( + scon_integer("3402823669209384634633746074317682114550"), + Err(nom::Err::Error(_)) + ); + assert_matches!(scon_integer("abc123"), Err(nom::Err::Error(_))); + } + + #[test] + fn test_string() { + // Plain Unicode strings with no escaping + assert_eq!( + scon_string(r#""""#).unwrap(), + ("", Value::String("".into())) + ); + assert_eq!( + scon_string(r#""Hello""#).unwrap(), + ("", Value::String("Hello".into())) + ); + assert_eq!( + scon_string(r#""の""#).unwrap(), + ("", Value::String("の".into())) + ); + assert_eq!( + scon_string(r#""𝄞""#).unwrap(), + ("", Value::String("𝄞".into())) + ); + + // valid 2-character escapes + assert_eq!( + scon_string(r#"" \\ ""#).unwrap(), + ("", Value::String(" \\ ".into())) + ); + assert_eq!( + scon_string(r#"" \" ""#).unwrap(), + ("", Value::String(" \" ".into())) + ); + + // valid 6-character escapes + assert_eq!( + scon_string(r#""\u0000""#).unwrap(), + ("", Value::String("\x00".into())) + ); + assert_eq!( + scon_string(r#""\u00DF""#).unwrap(), + ("", Value::String("ß".into())) + ); + assert_eq!( + scon_string(r#""\uD834\uDD1E""#).unwrap(), + ("", Value::String("𝄞".into())) + ); + + // Invalid because surrogate characters must come in pairs + assert!(scon_string(r#""\ud800""#).is_err()); + // Unknown 2-character escape + assert!(scon_string(r#""\x""#).is_err()); + // Not enough hex digits + assert!(scon_string(r#""\u""#).is_err()); + assert!(scon_string(r#""\u001""#).is_err()); + // Naked control character + assert!(scon_string(r#""\x0a""#).is_err()); + // Not a JSON string because it's not wrapped in quotes + assert!(scon_string("abc").is_err()); + // An unterminated string (because the trailing quote is escaped) + assert!(scon_string(r#""\""#).is_err()); + + // Parses correctly but has escape errors due to incomplete surrogate pair. + assert_matches!(scon_string(r#""\ud800""#), Err(nom::Err::Error(_))); + } + + #[test] + fn test_seq() { + assert_eq!(scon_value("[ ]").unwrap(), ("", Value::Seq(vec![].into()))); + assert_eq!( + scon_value("[ 1 ]").unwrap(), + ("", Value::Seq(vec![Value::UInt(1)].into())) + ); + + let expected = Value::Seq(vec![Value::UInt(1), Value::String("x".into())].into()); + assert_eq!(scon_value(r#" [ 1 , "x" ] "#).unwrap(), ("", expected)); + + let trailing = r#"["a", "b",]"#; + assert_eq!( + scon_value(trailing).unwrap(), + ( + "", + Value::Seq(vec![Value::String("a".into()), Value::String("b".into())].into()) + ) + ); + } + + #[test] + fn test_rust_ident() { + assert_eq!(rust_ident("a").unwrap(), ("", "a")); + assert_eq!(rust_ident("a:").unwrap(), (":", "a")); + assert_eq!(rust_ident("Ok").unwrap(), ("", "Ok")); + assert_eq!(rust_ident("_ok").unwrap(), ("", "_ok")); + assert_eq!(rust_ident("im_ok").unwrap(), ("", "im_ok")); + assert_eq!(rust_ident("im_ok_").unwrap(), ("", "im_ok_")); + assert_eq!(rust_ident("im_ok_123abc").unwrap(), ("", "im_ok_123abc")); + assert!(rust_ident("1notok").is_err()); + } + + #[test] + fn test_literal() { + assert_eq!( + scon_literal("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY").unwrap(), + ( + "", + Value::Literal("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY".into()) + ) + ); + assert_eq!( + scon_literal("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY").unwrap(), + ( + "", + Value::Literal("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY".into()) + ) + ); + + assert_scon_value( + "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", + Value::Literal("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY".into()), + ); + } + + #[test] + fn test_map() { + assert_eq!( + scon_value("Foo {}").unwrap(), + ("", Value::Map(Map::new(Some("Foo"), Default::default()))) + ); + assert_eq!( + scon_value("Foo{}").unwrap(), + ("", Value::Map(Map::new(Some("Foo"), Default::default()))) + ); + + assert_eq!(rust_ident("a:").unwrap(), (":", "a")); + + assert_eq!( + scon_value(r#"(a: 1)"#).unwrap(), + ( + "", + Value::Map(Map::new( + None, + vec![(Value::String("a".into()), Value::UInt(1)),] + .into_iter() + .collect() + )) + ) + ); + + assert_eq!( + scon_value(r#"A (a: 1, b: "bar")"#).unwrap(), + ( + "", + Value::Map(Map::new( + Some("A"), + vec![ + (Value::String("a".into()), Value::UInt(1)), + (Value::String("b".into()), Value::String("bar".into())), + ] + .into_iter() + .collect() + )) + ) + ); + + assert_eq!( + scon_value(r#"B(a: 1)"#).unwrap(), + ( + "", + Value::Map(Map::new( + Some("B"), + vec![(Value::String("a".into()), Value::UInt(1)),] + .into_iter() + .collect() + )) + ) + ); + + assert_eq!( + scon_value(r#"Struct { a : 1 }"#).unwrap(), + ( + "", + Value::Map(Map::new( + Some("Struct"), + vec![(Value::String("a".into()), Value::UInt(1)),] + .into_iter() + .collect() + )) + ) + ); + + let map = r#"Mixed { + 1: "a", + "b": 2, + c: true, + }"#; + + assert_eq!( + scon_value(map).unwrap(), + ( + "", + Value::Map(Map::new( + Some("Mixed"), + vec![ + (Value::UInt(1), Value::String("a".into())), + (Value::String("b".into()), Value::UInt(2)), + (Value::String("c".into()), Value::Bool(true)), + // (Value::String("d".into()), Value::Literal("5ALiteral".into())), + ] + .into_iter() + .collect() + )) + ) + ); + } + + #[test] + fn test_tuple() { + assert_scon_value("Foo ()", Value::Tuple(Tuple::new(Some("Foo"), vec![]))); + assert_scon_value("Foo()", Value::Tuple(Tuple::new(Some("Foo"), vec![]))); + assert_scon_value("Foo", Value::Tuple(Tuple::new(Some("Foo"), vec![]))); + + assert_scon_value( + r#"B("a")"#, + Value::Tuple(Tuple::new(Some("B"), vec![Value::String("a".into())])), + ); + assert_scon_value( + r#"B("a", 10, true)"#, + Value::Tuple(Tuple::new( + Some("B"), + vec![ + Value::String("a".into()), + Value::UInt(10), + Value::Bool(true), + ], + )), + ); + + assert_scon_value( + r#"Mixed ("a", 10, ["a", "b", "c"],)"#, + Value::Tuple(Tuple::new( + Some("Mixed"), + vec![ + Value::String("a".into()), + Value::UInt(10), + Value::Seq( + vec![ + Value::String("a".into()), + Value::String("b".into()), + Value::String("c".into()), + ] + .into(), + ), + ], + )), + ); + + assert_scon_value( + r#"(Nested("a", 10))"#, + Value::Tuple(Tuple::new( + None, + vec![Value::Tuple(Tuple::new( + Some("Nested"), + vec![Value::String("a".into()), Value::UInt(10)], + ))], + )), + ) + } + + #[test] + fn test_option() { + assert_scon_value( + r#"Some("a")"#, + Value::Tuple(Tuple::new(Some("Some"), vec![Value::String("a".into())])), + ); + assert_scon_value( + r#"None"#, + Value::Tuple(Tuple::new(Some("None"), Vec::new())), + ); + } + + #[test] + fn test_char() { + assert_scon_value(r#"'c'"#, Value::Char('c')); + } + + #[test] + fn test_bytes() { + assert_scon_value(r#"0x0000"#, Value::Bytes(vec![0u8; 2].into())); + assert_scon_value( + r#"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"#, + Value::Bytes(vec![255u8; 23].into()), + ); + } +} diff --git a/src/cmd/extrinsics/transcode/transcoder.rs b/src/cmd/extrinsics/transcode/transcoder.rs new file mode 100644 index 0000000000000000000000000000000000000000..2bd8570a5dc48b5885eaa819c0a9e2def749995d --- /dev/null +++ b/src/cmd/extrinsics/transcode/transcoder.rs @@ -0,0 +1,609 @@ +// Copyright 2018-2020 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 super::{ + decode::Decoder, + encode::Encoder, + env_types::{CustomTypeTranscoder, EnvTypesTranscoder, PathKey, TypesByPath}, + scon::Value, +}; + +use anyhow::Result; +use scale::Output; +use scale_info::{PortableRegistry, TypeInfo}; +use std::{collections::HashMap, fmt::Debug}; + +/// Encode strings to SCALE encoded output. +/// Decode SCALE encoded input into `Value` objects. +pub struct Transcoder<'a> { + registry: &'a PortableRegistry, + env_types: EnvTypesTranscoder, +} + +impl<'a> Transcoder<'a> { + pub fn new(registry: &'a PortableRegistry, env_types: EnvTypesTranscoder) -> Self { + Self { + registry, + env_types, + } + } + + pub fn encoder(&self) -> Encoder { + Encoder::new(self.registry, &self.env_types) + } + + pub fn encode(&self, type_id: u32, value: &Value, output: &mut O) -> Result<()> + where + O: Output + Debug, + { + self.encoder().encode(type_id, value, output) + } + + pub fn decoder(&self) -> Decoder { + Decoder::new(self.registry, &self.env_types) + } + + pub fn decode(&self, type_id: u32, input: &mut &[u8]) -> Result { + self.decoder().decode(type_id, input) + } +} + +/// Construct a [`Transcoder`], allows registering custom transcoders for certain types. +pub struct TranscoderBuilder<'a> { + registry: &'a PortableRegistry, + types_by_path: TypesByPath, + transcoders: HashMap>, +} + +impl<'a> TranscoderBuilder<'a> { + pub fn new(registry: &'a PortableRegistry) -> Self { + let types_by_path = registry + .types() + .iter() + .map(|ty| (PathKey::from(ty.ty().path()), ty.id())) + .collect::(); + Self { + registry, + types_by_path, + transcoders: HashMap::new(), + } + } + + pub fn register_custom_type(self, transcoder: U) -> Self + where + T: TypeInfo + 'static, + U: CustomTypeTranscoder + 'static, + { + let mut this = self; + + let path_key = PathKey::from_type::(); + let type_id = this.types_by_path.get(&path_key); + + match type_id { + Some(type_id) => { + let existing = this.transcoders.insert(*type_id, Box::new(transcoder)); + log::debug!("Registered environment type `{:?}`", type_id); + if existing.is_some() { + panic!( + "Attempted to register transcoder with existing type id {:?}", + type_id + ); + } + } + None => { + // if the type is not present in the registry, it just means it has not been used. + log::info!("No matching type in registry for path {:?}.", path_key); + } + } + this + } + + pub fn done(self) -> Transcoder<'a> { + let env_types_transcoder = EnvTypesTranscoder::new(self.transcoders); + Transcoder::new(self.registry, env_types_transcoder) + } +} + +#[cfg(test)] +mod tests { + use super::super::scon::{self, Map, Tuple, Value}; + use super::*; + use crate::cmd::extrinsics::transcode; + use scale::Encode; + use scale_info::{MetaType, Registry, TypeInfo}; + + fn registry_with_type() -> Result<(PortableRegistry, u32)> + where + T: scale_info::TypeInfo + 'static, + { + let mut registry = Registry::new(); + let type_id = registry.register_type(&MetaType::new::()); + let registry: PortableRegistry = registry.into(); + + Ok((registry, type_id.id())) + } + + fn transcode_roundtrip(input: &str, expected_output: Value) -> Result<()> + where + T: scale_info::TypeInfo + 'static, + { + let (registry, ty) = registry_with_type::()?; + let transcoder = TranscoderBuilder::new(®istry) + .register_custom_type::(transcode::env_types::AccountId) + .done(); + + let value = scon::parse_value(input)?; + + let mut output = Vec::new(); + transcoder.encode(ty, &value, &mut output)?; + let decoded = transcoder.decode(ty, &mut &output[..])?; + assert_eq!(expected_output, decoded, "decoding"); + Ok(()) + } + + #[test] + fn transcode_bool() -> Result<()> { + transcode_roundtrip::("true", Value::Bool(true))?; + transcode_roundtrip::("false", Value::Bool(false)) + } + + #[test] + fn transcode_char_unsupported() -> Result<()> { + let (registry, ty) = registry_with_type::()?; + let transcoder = Transcoder::new(®istry, Default::default()); + let encoded = u32::from('c').encode(); + + assert!(transcoder + .encode(ty, &Value::Char('c'), &mut Vec::new()) + .is_err()); + assert!(transcoder.decode(ty, &mut &encoded[..]).is_err()); + Ok(()) + } + + #[test] + fn transcode_str() -> Result<()> { + transcode_roundtrip::("\"ink!\"", Value::String("ink!".to_string())) + } + + #[test] + fn transcode_unsigned_integers() -> Result<()> { + transcode_roundtrip::("0", Value::UInt(0))?; + transcode_roundtrip::("255", Value::UInt(255))?; + + transcode_roundtrip::("0", Value::UInt(0))?; + transcode_roundtrip::("65535", Value::UInt(65535))?; + + transcode_roundtrip::("0", Value::UInt(0))?; + transcode_roundtrip::("4294967295", Value::UInt(4294967295))?; + + transcode_roundtrip::("0", Value::UInt(0))?; + transcode_roundtrip::( + "\"18_446_744_073_709_551_615\"", + Value::UInt(18446744073709551615), + )?; + + transcode_roundtrip::("0", Value::UInt(0))?; + transcode_roundtrip::( + "\"340_282_366_920_938_463_463_374_607_431_768_211_455\"", + Value::UInt(340282366920938463463374607431768211455), + ) + } + + #[test] + fn transcode_integers() -> Result<()> { + transcode_roundtrip::("-128", Value::Int(i8::min_value().into()))?; + transcode_roundtrip::("127", Value::Int(i8::max_value().into()))?; + + transcode_roundtrip::("-32768", Value::Int(i16::min_value().into()))?; + transcode_roundtrip::("32767", Value::Int(i16::max_value().into()))?; + + transcode_roundtrip::("-2147483648", Value::Int(i32::min_value().into()))?; + transcode_roundtrip::("2147483647", Value::Int(i32::max_value().into()))?; + + transcode_roundtrip::("-9223372036854775808", Value::Int(i64::min_value().into()))?; + transcode_roundtrip::( + "\"9_223_372_036_854_775_807\"", + Value::Int(i64::max_value().into()), + )?; + + transcode_roundtrip::( + "-170141183460469231731687303715884105728", + Value::Int(i128::min_value()), + )?; + transcode_roundtrip::( + "\"170141183460469231731687303715884105727\"", + Value::Int(i128::max_value()), + ) + } + + #[test] + fn transcode_byte_array() -> Result<()> { + transcode_roundtrip::<[u8; 2]>(r#"0x0000"#, Value::Bytes(vec![0x00, 0x00].into()))?; + transcode_roundtrip::<[u8; 4]>( + r#"0xDEADBEEF"#, + Value::Bytes(vec![0xDE, 0xAD, 0xBE, 0xEF].into()), + )?; + transcode_roundtrip::<[u8; 4]>( + r#"0xdeadbeef"#, + Value::Bytes(vec![0xDE, 0xAD, 0xBE, 0xEF].into()), + ) + } + + #[test] + fn transcode_array() -> Result<()> { + transcode_roundtrip::<[u32; 3]>( + "[1, 2, 3]", + Value::Seq(vec![Value::UInt(1), Value::UInt(2), Value::UInt(3)].into()), + )?; + transcode_roundtrip::<[String; 2]>( + "[\"hello\", \"world\"]", + Value::Seq( + vec![ + Value::String("hello".to_string()), + Value::String("world".to_string()), + ] + .into(), + ), + ) + } + + #[test] + fn transcode_seq() -> Result<()> { + transcode_roundtrip::>( + "[1, 2, 3]", + Value::Seq(vec![Value::UInt(1), Value::UInt(2), Value::UInt(3)].into()), + )?; + transcode_roundtrip::>( + "[\"hello\", \"world\"]", + Value::Seq( + vec![ + Value::String("hello".to_string()), + Value::String("world".to_string()), + ] + .into(), + ), + ) + } + + #[test] + fn transcode_tuple() -> Result<()> { + transcode_roundtrip::<(u32, String, [u8; 4])>( + r#"(1, "ink!", 0xDEADBEEF)"#, + Value::Tuple(Tuple::new( + None, + vec![ + Value::UInt(1), + Value::String("ink!".to_string()), + Value::Bytes(vec![0xDE, 0xAD, 0xBE, 0xEF].into()), + ], + )), + ) + } + + #[test] + fn transcode_composite_struct() -> Result<()> { + #[allow(dead_code)] + #[derive(TypeInfo)] + struct S { + a: u32, + b: String, + c: [u8; 4], + // recursive struct ref + d: Vec, + } + + transcode_roundtrip::( + r#"S(a: 1, b: "ink!", c: 0xDEADBEEF, d: [S(a: 2, b: "ink!", c: 0xDEADBEEF, d: [])])"#, + Value::Map( + vec![ + (Value::String("a".to_string()), Value::UInt(1)), + ( + Value::String("b".to_string()), + Value::String("ink!".to_string()), + ), + ( + Value::String("c".to_string()), + Value::Bytes(vec![0xDE, 0xAD, 0xBE, 0xEF].into()), + ), + ( + Value::String("d".to_string()), + Value::Seq( + vec![Value::Map( + vec![ + (Value::String("a".to_string()), Value::UInt(2)), + ( + Value::String("b".to_string()), + Value::String("ink!".to_string()), + ), + ( + Value::String("c".to_string()), + Value::Bytes(vec![0xDE, 0xAD, 0xBE, 0xEF].into()), + ), + ( + Value::String("d".to_string()), + Value::Seq( + Vec::new().into_iter().collect::>().into(), + ), + ), + ] + .into_iter() + .collect(), + )] + .into(), + ), + ), + ] + .into_iter() + .collect(), + ), + ) + } + + #[test] + fn transcode_composite_struct_nested() -> Result<()> { + #[allow(dead_code)] + #[derive(TypeInfo)] + struct S { + nested: Nested, + } + + #[allow(dead_code)] + #[derive(TypeInfo)] + struct Nested(u32); + + transcode_roundtrip::( + r#"S { nested: Nested(33) }"#, + Value::Map(Map::new( + Some("S"), + vec![( + Value::String("nested".to_string()), + Value::Tuple(Tuple::new( + Some("Nested"), + vec![Value::UInt(33)].into_iter().collect(), + )), + )] + .into_iter() + .collect(), + )), + ) + } + + #[test] + fn transcode_composite_struct_out_of_order_fields() -> Result<()> { + #[allow(dead_code)] + #[derive(TypeInfo)] + struct S { + a: u32, + b: String, + c: [u8; 4], + } + + transcode_roundtrip::( + r#"S(b: "ink!", a: 1, c: 0xDEADBEEF)"#, + Value::Map( + vec![ + (Value::String("a".to_string()), Value::UInt(1)), + ( + Value::String("b".to_string()), + Value::String("ink!".to_string()), + ), + ( + Value::String("c".to_string()), + Value::Bytes(vec![0xDE, 0xAD, 0xBE, 0xEF].into()), + ), + ] + .into_iter() + .collect(), + ), + ) + } + + #[test] + fn transcode_composite_tuple_struct() -> Result<()> { + #[allow(dead_code)] + #[derive(TypeInfo)] + struct S(u32, String, [u8; 4]); + + transcode_roundtrip::( + r#"S(1, "ink!", 0xDEADBEEF)"#, + Value::Tuple(Tuple::new( + Some("S"), + vec![ + Value::UInt(1), + Value::String("ink!".to_string()), + Value::Bytes(vec![0xDE, 0xAD, 0xBE, 0xEF].into()), + ], + )), + ) + } + + #[test] + fn transcode_composite_single_field_struct() -> Result<()> { + #[allow(dead_code)] + #[derive(TypeInfo)] + struct S([u8; 4]); + + transcode_roundtrip::( + r#"0xDEADBEEF"#, + Value::Tuple(Tuple::new( + Some("S"), + vec![Value::Bytes(vec![0xDE, 0xAD, 0xBE, 0xEF].into())], + )), + ) + } + + #[test] + fn transcode_composite_single_field_tuple() -> Result<()> { + transcode_roundtrip::<([u8; 4],)>( + r#"0xDEADBEEF"#, + Value::Tuple(Tuple::new( + None, + vec![Value::Bytes(vec![0xDE, 0xAD, 0xBE, 0xEF].into())], + )), + ) + } + + #[test] + fn transcode_enum_variant_tuple() -> Result<()> { + #[derive(TypeInfo)] + #[allow(dead_code)] + enum E { + A(u32, String), + B { a: [u8; 4], b: Vec }, + C, + } + + transcode_roundtrip::( + r#"A(1, "2")"#, + Value::Tuple(Tuple::new( + Some("A"), + vec![Value::UInt(1), Value::String("2".into())], + )), + ) + } + + #[test] + fn transcode_enum_variant_map() -> Result<()> { + #[derive(TypeInfo)] + #[allow(dead_code)] + enum E { + A { a: u32, b: bool }, + } + + transcode_roundtrip::( + r#"A { a: 33, b: false }"#, + Value::Map(Map::new( + Some("A"), + vec![ + (Value::String("a".to_string()), Value::UInt(33)), + (Value::String("b".to_string()), Value::Bool(false)), + ] + .into_iter() + .collect(), + )), + ) + } + + #[test] + fn transcode_enum_variant_map_out_of_order_fields() -> Result<()> { + #[derive(TypeInfo)] + #[allow(dead_code)] + enum E { + A { a: u32, b: bool }, + } + + transcode_roundtrip::( + r#"A { a: 33, b: false }"#, + Value::Map(Map::new( + Some("A"), + vec![ + (Value::String("a".to_string()), Value::UInt(33)), + (Value::String("b".to_string()), Value::Bool(false)), + ] + .into_iter() + .collect(), + )), + ) + } + + #[test] + fn transcode_option() -> Result<()> { + transcode_roundtrip::>( + r#"Some(32)"#, + Value::Tuple(Tuple::new(Some("Some"), vec![Value::UInt(32)])), + )?; + + transcode_roundtrip::>( + r#"None"#, + Value::Tuple(Tuple::new(Some("None"), Vec::new())), + ) + } + + #[test] + fn transcode_account_id_custom_ss58_encoding() -> Result<()> { + env_logger::init(); + + type AccountId = sp_runtime::AccountId32; + + #[allow(dead_code)] + #[derive(TypeInfo)] + struct S { + no_alias: sp_runtime::AccountId32, + aliased: AccountId, + } + + transcode_roundtrip::( + r#"S( + no_alias: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY, + aliased: 5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty, + )"#, + Value::Map(Map::new( + Some("S"), + vec![ + ( + Value::String("no_alias".into()), + Value::Literal("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY".into()), + ), + ( + Value::String("aliased".into()), + Value::Literal("5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty".into()), + ), + ] + .into_iter() + .collect(), + )), + ) + } + + #[test] + fn transcode_compact_primitives() -> Result<()> { + transcode_roundtrip::>(r#"33"#, Value::UInt(33))?; + + transcode_roundtrip::>(r#"33"#, Value::UInt(33))?; + + transcode_roundtrip::>(r#"33"#, Value::UInt(33))?; + + transcode_roundtrip::>(r#"33"#, Value::UInt(33))?; + + transcode_roundtrip::>(r#"33"#, Value::UInt(33)) + } + + #[test] + fn transcode_compact_struct() -> Result<()> { + #[derive(scale::Encode, scale::CompactAs, TypeInfo)] + struct CompactStruct(u32); + + #[allow(dead_code)] + #[derive(scale::Encode, TypeInfo)] + struct S { + #[codec(compact)] + a: CompactStruct, + } + + transcode_roundtrip::( + r#"S { a: CompactStruct(33) }"#, + Value::Map(Map::new( + Some("S"), + vec![( + Value::String("a".to_string()), + Value::Tuple(Tuple::new(Some("CompactStruct"), vec![Value::UInt(33)])), + )] + .into_iter() + .collect(), + )), + ) + } +} diff --git a/src/cmd/extrinsics/upload.rs b/src/cmd/extrinsics/upload.rs new file mode 100644 index 0000000000000000000000000000000000000000..a41cc6cc3343ae53b5ca10ec003a0ad7edeb3304 --- /dev/null +++ b/src/cmd/extrinsics/upload.rs @@ -0,0 +1,150 @@ +// Copyright 2018-2020 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 super::{ + display_events, runtime_api::api, wait_for_success_and_handle_error, Balance, CodeHash, + ContractMessageTranscoder, ExtrinsicOpts, PairSigner, RuntimeApi, +}; +use crate::name_value_println; +use anyhow::{Context, Result}; +use jsonrpsee::{ + types::{to_json_value, traits::Client as _}, + ws_client::WsClientBuilder, +}; +use serde::Serialize; +use sp_core::Bytes; +use std::{fmt::Debug, path::PathBuf}; +use structopt::StructOpt; +use subxt::{rpc::NumberOrHex, ClientBuilder, Config, DefaultConfig, Signer, TransactionEvents}; + +type CodeUploadResult = pallet_contracts_primitives::CodeUploadResult; +type CodeUploadReturnValue = pallet_contracts_primitives::CodeUploadReturnValue; + +#[derive(Debug, StructOpt)] +#[structopt(name = "upload", about = "Upload a contract's code")] +pub struct UploadCommand { + /// Path to wasm contract code, defaults to `./target/ink/.wasm`. + #[structopt(parse(from_os_str))] + wasm_path: Option, + #[structopt(flatten)] + extrinsic_opts: ExtrinsicOpts, +} + +impl UploadCommand { + pub fn run(&self) -> Result<()> { + let (crate_metadata, contract_metadata) = + super::load_metadata(self.extrinsic_opts.manifest_path.as_ref())?; + let transcoder = ContractMessageTranscoder::new(&contract_metadata); + let signer = super::pair_signer(self.extrinsic_opts.signer()?); + + let wasm_path = match &self.wasm_path { + Some(wasm_path) => wasm_path.clone(), + None => crate_metadata.dest_wasm, + }; + + log::info!("Contract code path: {}", wasm_path.display()); + let code = std::fs::read(&wasm_path) + .context(format!("Failed to read from {}", wasm_path.display()))?; + + async_std::task::block_on(async { + if self.extrinsic_opts.dry_run { + let result = self.upload_code_rpc(code, &signer).await?; + + name_value_println!("Code hash", format!("{:?}", result.code_hash)); + name_value_println!("Deposit", format!("{:?}", result.deposit)); + + Ok(()) + } else { + let result = self.upload_code(code, &signer, &transcoder).await?; + + let code_stored = result + .find_first_event::()? + .ok_or(anyhow::anyhow!("Failed to find CodeStored event"))?; + + name_value_println!("Code hash", format!("{:?}", code_stored.code_hash)); + + Ok(()) + } + }) + } + + async fn upload_code_rpc( + &self, + code: Vec, + signer: &PairSigner, + ) -> Result { + let url = self.extrinsic_opts.url.to_string(); + let cli = WsClientBuilder::default().build(&url).await?; + let storage_deposit_limit = self + .extrinsic_opts + .storage_deposit_limit + .as_ref() + .map(|limit| NumberOrHex::Hex((*limit).into())); + let call_request = CodeUploadRequest { + origin: signer.account_id().clone(), + code: Bytes(code), + storage_deposit_limit, + }; + let params = vec![to_json_value(call_request)?]; + + let result: CodeUploadResult = cli + .request("contracts_upload_code", Some(params.into())) + .await?; + + result.map_err(|e| anyhow::anyhow!("Failed to execute call via rpc: {:?}", e)) + } + + async fn upload_code( + &self, + code: Vec, + signer: &PairSigner, + transcoder: &ContractMessageTranscoder<'_>, + ) -> Result> { + let url = self.extrinsic_opts.url.to_string(); + let api = ClientBuilder::new() + .set_url(&url) + .build() + .await? + .to_runtime_api::(); + + let tx_progress = api + .tx() + .contracts() + .upload_code(code, self.extrinsic_opts.storage_deposit_limit) + .sign_and_submit_then_watch(signer) + .await?; + + let result = wait_for_success_and_handle_error(tx_progress).await?; + + display_events( + &result, + transcoder, + api.client.metadata(), + &self.extrinsic_opts.verbosity()?, + )?; + + Ok(result) + } +} + +/// A struct that encodes RPC parameters required for a call to upload a new code. +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct CodeUploadRequest { + origin: ::AccountId, + code: Bytes, + storage_deposit_limit: Option, +} diff --git a/src/cmd/instantiate.rs b/src/cmd/instantiate.rs deleted file mode 100644 index f451dab100656b46b1839e3f62b50f3ccf5b4a52..0000000000000000000000000000000000000000 --- a/src/cmd/instantiate.rs +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2018-2021 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 anyhow::{Context, Result}; -use subxt::{balances::Balances, contracts::*, system::System, ClientBuilder, DefaultNodeRuntime}; - -use crate::{ExtrinsicOpts, HexData}; - -/// Instantiate a contract stored at the supplied code hash. -/// Returns the account id of the instantiated contract if successful. -/// -/// Creates an extrinsic with the `Contracts::instantiate` Call, submits via RPC, then waits for -/// the `ContractsEvent::Instantiated` event. -pub(crate) fn execute_instantiate( - extrinsic_opts: &ExtrinsicOpts, - endowment: ::Balance, - gas_limit: u64, - code_hash: ::Hash, - data: HexData, -) -> Result<::AccountId> { - async_std::task::block_on(async move { - let cli = ClientBuilder::::new() - .set_url(&extrinsic_opts.url.to_string()) - .build() - .await?; - let signer = extrinsic_opts.signer()?; - - let events = cli - .instantiate_and_watch(&signer, endowment, gas_limit, &code_hash, &data.0) - .await?; - let instantiated = events - .instantiated()? - .context("Failed to find Instantiated event")?; - - Ok(instantiated.contract) - }) -} - -#[cfg(test)] -mod tests { - use std::{fs, io::Write}; - - use crate::{cmd::deploy::execute_deploy, util::tests::with_tmp_dir, ExtrinsicOpts, HexData}; - use assert_matches::assert_matches; - - const CONTRACT: &str = r#" -(module - (func (export "call")) - (func (export "deploy")) -) -"#; - - #[test] - #[ignore] // depends on a local substrate node running - fn instantiate_contract() { - with_tmp_dir(|path| { - let wasm = wabt::wat2wasm(CONTRACT).expect("invalid wabt"); - - let wasm_path = path.join("test.wasm"); - let mut file = fs::File::create(&wasm_path).unwrap(); - let _ = file.write_all(&wasm); - - let url = url::Url::parse("ws://localhost:9944").unwrap(); - let extrinsic_opts = ExtrinsicOpts { - url, - suri: "//Alice".into(), - password: None, - }; - let code_hash = - execute_deploy(&extrinsic_opts, Some(&wasm_path)).expect("Deploy should succeed"); - - let gas_limit = 500_000_000; - let result = super::execute_instantiate( - &extrinsic_opts, - 100000000000000, - gas_limit, - code_hash, - HexData::default(), - ); - - assert_matches!(result, Ok(_)); - Ok(()) - }) - } -} diff --git a/src/cmd/mod.rs b/src/cmd/mod.rs index b507a9c5ce70a430bec0fcca886e141c06d4e433..c40b2f11486f2f8882bcc646892c49c2c0ca4f8a 100644 --- a/src/cmd/mod.rs +++ b/src/cmd/mod.rs @@ -15,10 +15,6 @@ // along with cargo-contract. If not, see . pub mod build; -#[cfg(feature = "extrinsics")] -mod deploy; -#[cfg(feature = "extrinsics")] -mod instantiate; pub mod metadata; pub mod new; pub mod test; @@ -27,5 +23,6 @@ pub(crate) use self::{ build::{BuildCommand, CheckCommand}, test::TestCommand, }; -#[cfg(feature = "extrinsics")] -pub(crate) use self::{deploy::execute_deploy, instantiate::execute_instantiate}; +mod extrinsics; + +pub(crate) use self::extrinsics::{CallCommand, InstantiateCommand, UploadCommand}; diff --git a/src/cmd/new.rs b/src/cmd/new.rs index a2fbae4b3fecaad8990a06beb46a988f53b42c62..75482bb058a986c1d5ef6860b0f13ccc4e2787b3 100644 --- a/src/cmd/new.rs +++ b/src/cmd/new.rs @@ -23,7 +23,7 @@ use std::{ use anyhow::Result; use heck::ToUpperCamelCase as _; -pub(crate) fn execute

(name: &str, dir: Option

) -> Result> +pub(crate) fn execute

(name: &str, dir: Option

) -> Result<()> where P: AsRef, { @@ -68,7 +68,7 @@ where let outpath = out_dir.join(file.name()); - if (&*file.name()).ends_with('/') { + if (*file.name()).ends_with('/') { fs::create_dir_all(&outpath)?; } else { if let Some(p) = outpath.parent() { @@ -102,7 +102,7 @@ where } } - Ok(Some(format!("Created contract {}", name))) + Ok(()) } #[cfg(test)] diff --git a/src/crate_metadata.rs b/src/crate_metadata.rs index 9f081564b9fbe2b22d9d7ab43dd6142c37d6fb9e..1b7a1ec243e87cbd5743acaf586e418d83658380 100644 --- a/src/crate_metadata.rs +++ b/src/crate_metadata.rs @@ -23,6 +23,8 @@ use std::{fs, path::PathBuf}; use toml::value; use url::Url; +const METADATA_FILE: &str = "metadata.json"; + /// Relevant metadata obtained from Cargo.toml. #[derive(Debug)] pub struct CrateMetadata { @@ -111,10 +113,19 @@ impl CrateMetadata { }; Ok(crate_metadata) } + + /// Get the path of the contract metadata file + pub fn metadata_path(&self) -> PathBuf { + self.target_directory.join(METADATA_FILE) + } } /// Get the result of `cargo metadata`, together with the root package id. fn get_cargo_metadata(manifest_path: &ManifestPath) -> Result<(CargoMetadata, Package)> { + log::info!( + "Fetching cargo metadata for {}", + manifest_path.as_ref().to_string_lossy() + ); let mut cmd = MetadataCommand::new(); let metadata = cmd .manifest_path(manifest_path.as_ref()) diff --git a/src/main.rs b/src/main.rs index 98db48ebea605ca41fa5b288178ce4e45faf3b81..774061d41e0c91af78cccd2df5f404039a006dfd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,20 +20,21 @@ mod util; mod validate_wasm; mod workspace; -use self::workspace::ManifestPath; - -use crate::cmd::{metadata::MetadataResult, BuildCommand, CheckCommand, TestCommand}; +use self::{ + cmd::{ + metadata::MetadataResult, BuildCommand, CallCommand, CheckCommand, InstantiateCommand, + TestCommand, UploadCommand, + }, + util::DEFAULT_KEY_COL_WIDTH, + workspace::ManifestPath, +}; -#[cfg(feature = "extrinsics")] -use sp_core::{crypto::Pair, sr25519, H256}; use std::{ convert::TryFrom, fmt::{Display, Formatter, Result as DisplayResult}, path::PathBuf, str::FromStr, }; -#[cfg(feature = "extrinsics")] -use subxt::PairSigner; use anyhow::{Error, Result}; use colored::Colorize; @@ -61,7 +62,6 @@ pub(crate) struct ContractArgs { #[derive(Debug, Default, Clone, PartialEq, Eq)] pub(crate) struct HexData(pub Vec); -#[cfg(feature = "extrinsics")] impl std::str::FromStr for HexData { type Err = hex::FromHexError; @@ -70,36 +70,6 @@ impl std::str::FromStr for HexData { } } -/// Arguments required for creating and sending an extrinsic to a substrate node -#[cfg(feature = "extrinsics")] -#[derive(Debug, StructOpt)] -pub(crate) struct ExtrinsicOpts { - /// Websockets url of a substrate node - #[structopt( - name = "url", - long, - parse(try_from_str), - default_value = "ws://localhost:9944" - )] - url: url::Url, - /// Secret key URI for the account deploying the contract. - #[structopt(name = "suri", long, short)] - suri: String, - /// Password for the secret key - #[structopt(name = "password", long, short)] - password: Option, -} - -#[cfg(feature = "extrinsics")] -impl ExtrinsicOpts { - pub fn signer(&self) -> Result> { - let pair = - sr25519::Pair::from_string(&self.suri, self.password.as_ref().map(String::as_ref)) - .map_err(|_| anyhow::anyhow!("Secret string error"))?; - Ok(PairSigner::new(pair)) - } -} - #[derive(Clone, Copy, Debug, PartialEq)] pub enum OptimizationPasses { Zero, @@ -477,46 +447,15 @@ enum Command { /// Test the smart contract off-chain #[structopt(name = "test")] Test(TestCommand), - /// Upload the smart contract code to the chain - #[cfg(feature = "extrinsics")] - #[structopt(name = "deploy")] - Deploy { - #[structopt(flatten)] - extrinsic_opts: ExtrinsicOpts, - /// Path to wasm contract code, defaults to `./target/ink/.wasm` - #[structopt(parse(from_os_str))] - wasm_path: Option, - }, - /// Instantiate a deployed smart contract - #[cfg(feature = "extrinsics")] + /// Upload contract code + #[structopt(name = "upload")] + Upload(UploadCommand), + /// Instantiate a contract #[structopt(name = "instantiate")] - Instantiate { - #[structopt(flatten)] - extrinsic_opts: ExtrinsicOpts, - /// Transfers an initial balance to the instantiated contract - #[structopt(name = "endowment", long, default_value = "0")] - endowment: u128, - /// Maximum amount of gas to be used for this command - #[structopt(name = "gas", long, default_value = "500000000")] - gas_limit: u64, - /// The hash of the smart contract code already uploaded to the chain - #[structopt(long, parse(try_from_str = parse_code_hash))] - code_hash: H256, - /// Hex encoded data to call a contract constructor - #[structopt(long)] - data: HexData, - }, -} - -#[cfg(feature = "extrinsics")] -fn parse_code_hash(input: &str) -> Result { - let bytes = hex::decode(input)?; - if bytes.len() != 32 { - anyhow::bail!("Code hash should be 32 bytes in length") - } - let mut arr = [0u8; 32]; - arr.copy_from_slice(&bytes); - Ok(H256(arr)) + Instantiate(InstantiateCommand), + /// Call a contract + #[structopt(name = "call")] + Call(CallCommand), } fn main() { @@ -524,11 +463,7 @@ fn main() { let Opts::Contract(args) = Opts::from_args(); match exec(args.cmd) { - Ok(maybe_msg) => { - if let Some(msg) = maybe_msg { - println!("\t{}", msg) - } - } + Ok(()) => {} Err(err) => { eprintln!( "{} {}", @@ -540,19 +475,22 @@ fn main() { } } -fn exec(cmd: Command) -> Result> { +fn exec(cmd: Command) -> Result<()> { match &cmd { - Command::New { name, target_dir } => cmd::new::execute(name, target_dir.as_ref()), + Command::New { name, target_dir } => { + cmd::new::execute(name, target_dir.as_ref())?; + println!("Created contract {}", name); + Ok(()) + } Command::Build(build) => { let result = build.exec()?; if matches!(result.output_type, OutputType::Json) { - Ok(Some(result.serialize_json()?)) + println!("{}", result.serialize_json()?) } else if result.verbosity.is_verbose() { - Ok(Some(result.display())) - } else { - Ok(None) + println!("{}", result.display()) } + Ok(()) } Command::Check(check) => { let res = check.exec()?; @@ -561,46 +499,20 @@ fn exec(cmd: Command) -> Result> { "no dest_wasm must be on the generation result" ); if res.verbosity.is_verbose() { - Ok(Some( - "\nYour contract's code was built successfully.".to_string(), - )) - } else { - Ok(None) + println!("\nYour contract's code was built successfully.") } + Ok(()) } Command::Test(test) => { let res = test.exec()?; if res.verbosity.is_verbose() { - Ok(Some(res.display()?)) - } else { - Ok(None) + println!("{}", res.display()?) } + Ok(()) } - #[cfg(feature = "extrinsics")] - Command::Deploy { - extrinsic_opts, - wasm_path, - } => { - let code_hash = cmd::execute_deploy(extrinsic_opts, wasm_path.as_ref())?; - Ok(Some(format!("Code hash: {:?}", code_hash))) - } - #[cfg(feature = "extrinsics")] - Command::Instantiate { - extrinsic_opts, - endowment, - code_hash, - gas_limit, - data, - } => { - let contract_account = cmd::execute_instantiate( - extrinsic_opts, - *endowment, - *gas_limit, - *code_hash, - data.clone(), - )?; - Ok(Some(format!("Contract account: {:?}", contract_account))) - } + Command::Upload(upload) => upload.run(), + Command::Instantiate(instantiate) => instantiate.run(), + Command::Call(call) => call.run(), } } diff --git a/src/util.rs b/src/util.rs index 9d6e70211c113a0ca81d7e0aad0cd7bfa80a76ea..d373db1cd89f19601a426424ca1f7febbd7b3287 100644 --- a/src/util.rs +++ b/src/util.rs @@ -92,16 +92,44 @@ pub(crate) fn base_name(path: &Path) -> &str { .expect("must be valid utf-8") } +/// Decode hex string with or without 0x prefix +pub fn decode_hex(input: &str) -> Result, hex::FromHexError> { + if input.starts_with("0x") { + hex::decode(input.trim_start_matches("0x")) + } else { + hex::decode(input) + } +} + /// Prints to stdout if `verbosity.is_verbose()` is `true`. #[macro_export] macro_rules! maybe_println { ($verbosity:expr, $($msg:tt)*) => { if $verbosity.is_verbose() { - println!($($msg)*); + ::std::println!($($msg)*); } }; } +pub const DEFAULT_KEY_COL_WIDTH: usize = 13; + +/// Pretty print name value, name right aligned with colour. +#[macro_export] +macro_rules! name_value_println { + ($name:tt, $value:expr, $width:expr) => {{ + use colored::Colorize as _; + ::std::println!( + "{:>width$} {}", + $name.bright_purple().bold(), + $value.bright_white(), + width = $width, + ); + }}; + ($name:tt, $value:expr) => { + $crate::name_value_println!($name, $value, $crate::DEFAULT_KEY_COL_WIDTH) + }; +} + #[cfg(test)] pub mod tests { use crate::ManifestPath; diff --git a/src/validate_wasm.rs b/src/validate_wasm.rs index daec2eabf2f0ef0a4468b421ebeb713b7492aaf4..2d0fe74d86ac9cfaa082b555263647c3ed95f890 100644 --- a/src/validate_wasm.rs +++ b/src/validate_wasm.rs @@ -37,7 +37,7 @@ const INK_ENFORCE_ERR: &str = "__ink_enforce_error_"; /// [here](https://github.com/paritytech/ink/blob/master/crates/lang/codegen/src/generator/cross_calling.rs). /// This type must be compatible with the ink! version in order to decode /// the error encoded in the marker. -#[derive(codec::Encode, codec::Decode)] +#[derive(scale::Encode, scale::Decode)] pub enum EnforcedErrors { /// The below error represents calling a `&mut self` message in a context that /// only allows for `&self` messages. This may happen under certain circumstances @@ -147,7 +147,7 @@ fn parse_linker_error(field: &str) -> String { .strip_prefix(INK_ENFORCE_ERR) .expect("error marker must exist as prefix"); let hex = serde_hex::from_hex(encoded).expect("decoding hex failed"); - let decoded = ::decode(&mut &hex[..]).expect( + let decoded = ::decode(&mut &hex[..]).expect( "The `EnforcedError` object could not be decoded. The probable\ cause is a mismatch between the ink! definition of the type and the\ local `cargo-contract` definition.", @@ -171,7 +171,7 @@ fn parse_linker_error(field: &str) -> String { with the scope in which it is called. The receiver is `{}`.", trait_ident, message_ident, - serde_hex::to_hex(&codec::Encode::encode(&message_selector), false), + serde_hex::to_hex(&scale::Encode::encode(&message_selector), false), receiver ) } @@ -186,7 +186,7 @@ fn parse_linker_error(field: &str) -> String { Constructor never need to be forwarded, please check if this is the case.", trait_ident, constructor_ident, - serde_hex::to_hex(&codec::Encode::encode(&constructor_selector), false) + serde_hex::to_hex(&scale::Encode::encode(&constructor_selector), false) ) } }