diff --git a/Cargo.lock b/Cargo.lock index 2439b066f7fb..feff492e5ac3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -541,6 +541,20 @@ dependencies = [ "scale-info", ] +[[package]] +name = "ark-scale" +version = "0.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f69c00b3b529be29528a6f2fd5fa7b1790f8bed81b9cdca17e326538545a179" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", + "parity-scale-codec", + "scale-info", +] + [[package]] name = "ark-secret-scalar" version = "0.0.2" @@ -655,7 +669,7 @@ dependencies = [ "num-traits", "rusticata-macros", "thiserror", - "time 0.3.27", + "time", ] [[package]] @@ -671,7 +685,7 @@ dependencies = [ "num-traits", "rusticata-macros", "thiserror", - "time 0.3.27", + "time", ] [[package]] @@ -1290,7 +1304,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -1307,7 +1321,7 @@ checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -1483,7 +1497,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -2653,15 +2667,14 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.27" +version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f56b4c72906975ca04becb8a30e102dfecddd0c06181e3e95ddc444be28881f8" +checksum = "defd4e7873dbddba6c7c91e199c7fcb946abc4a6a4ac3195400bcfb01b5de877" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", - "time 0.1.45", "wasm-bindgen", "windows-targets 0.48.5", ] @@ -2825,7 +2838,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -3951,10 +3964,10 @@ dependencies = [ name = "cumulus-pallet-parachain-system-proc-macro" version = "0.1.0" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -4446,7 +4459,7 @@ checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -4486,7 +4499,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -4503,7 +4516,7 @@ checksum = "50c49547d73ba8dcfd4ad7325d64c6d5391ff4224d498fc39a6f3f49825a530d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -4666,6 +4679,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive-syn-parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + [[package]] name = "derive_builder" version = "0.11.2" @@ -4802,7 +4826,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -4818,7 +4842,7 @@ source = "git+https://github.com/w3f/ring-vrf?rev=cbc342e#cbc342e95d3cbcd3c5ba8d dependencies = [ "ark-ec", "ark-ff", - "ark-scale", + "ark-scale 0.0.11", "ark-secret-scalar", "ark-serialize", "ark-std", @@ -4845,28 +4869,28 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "docify" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4235e9b248e2ba4b92007fe9c646f3adf0ffde16dc74713eacc92b8bc58d8d2f" +checksum = "43a2f138ad521dc4a2ced1a4576148a6a610b4c5923933b062a263130a6802ce" dependencies = [ "docify_macros", ] [[package]] name = "docify_macros" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47020e12d7c7505670d1363dd53d6c23724f71a90a3ae32ff8eba40de8404626" +checksum = "1a081e51fb188742f5a7a1164ad752121abcb22874b21e2c3b0dd040c515fdad" dependencies = [ "common-path", - "derive-syn-parse", + "derive-syn-parse 0.2.0", "once_cell", "proc-macro2", "quote", "regex", - "syn 2.0.38", + "syn 2.0.60", "termcolor", - "toml 0.7.6", + "toml 0.8.2", "walkdir", ] @@ -5119,7 +5143,7 @@ checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -5130,7 +5154,7 @@ checksum = "c2ad8cef1d801a4686bfd8919f0b30eac4c8e48968c437a6405ded4fb5272d2b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -5173,9 +5197,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "erased-serde" -version = "0.3.30" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "837c0466252947ada828b975e12daf82e18bb5444e4df87be6038d4469e2a3d2" +checksum = "2b73807008a3c7f171cc40312f37d95ef0396e048b5848d775f54b1a4dd4a0d3" dependencies = [ "serde", ] @@ -5275,7 +5299,7 @@ dependencies = [ "fs-err", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -5333,7 +5357,7 @@ checksum = "f5aa1e3ae159e592ad222dc90c5acbad632b527779ba88486abe92782ab268bd" dependencies = [ "expander 0.0.4", "indexmap 1.9.3", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "syn 1.0.109", @@ -5656,12 +5680,12 @@ dependencies = [ "frame-election-provider-support", "frame-support", "parity-scale-codec", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "scale-info", "sp-arithmetic", - "syn 2.0.38", + "syn 2.0.60", "trybuild", ] @@ -5804,7 +5828,7 @@ version = "4.0.0-dev" dependencies = [ "Inflector", "cfg-expr", - "derive-syn-parse", + "derive-syn-parse 0.1.5", "expander 2.0.0", "frame-support-procedural-tools", "itertools 0.10.5", @@ -5813,7 +5837,7 @@ dependencies = [ "proc-macro2", "quote", "sp-core-hashing", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -5821,10 +5845,10 @@ name = "frame-support-procedural-tools" version = "4.0.0-dev" dependencies = [ "frame-support-procedural-tools-derive", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -5833,7 +5857,7 @@ version = "3.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -5977,7 +6001,7 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eeb4ed9e12f43b7fa0baae3f9cdda28352770132ef2e09a23760c29cae8bd47" dependencies = [ - "rustix 0.38.21", + "rustix 0.38.25", "windows-sys 0.48.0", ] @@ -6065,7 +6089,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -6928,7 +6952,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi 0.3.2", - "rustix 0.38.21", + "rustix 0.38.25", "windows-sys 0.48.0", ] @@ -7090,7 +7114,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44e8ab85614a08792b9bff6c8feee23be78c98d0182d4c622c05256ab553892a" dependencies = [ "heck", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "syn 1.0.109", @@ -7383,9 +7407,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.149" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libflate" @@ -7969,9 +7993,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.10" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lioness" @@ -8015,9 +8039,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" dependencies = [ "serde", "value-bag", @@ -8094,7 +8118,7 @@ dependencies = [ "macro_magic_core", "macro_magic_macros", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -8104,11 +8128,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "468155613a44cfd825f1fb0ffa532b018253920d404e6fca1e8d43155198a46d" dependencies = [ "const-random", - "derive-syn-parse", + "derive-syn-parse 0.1.5", "macro_magic_core_macros", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -8119,7 +8143,7 @@ checksum = "9ea73aa640dc01d62a590d48c0c3521ed739d53b27f919b25c3551e233481654" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -8130,7 +8154,7 @@ checksum = "ef9d79ae96aaba821963320eb2b6e34d17df1e5a83d8a1985c29cc5be59577b3" dependencies = [ "macro_magic_core", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -8154,6 +8178,15 @@ dependencies = [ "regex-automata 0.1.10", ] +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + [[package]] name = "matches" version = "0.1.10" @@ -8517,7 +8550,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc076939022111618a5026d3be019fd8b366e76314538ff9a1b59ffbcbf98bcd" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro-error", "proc-macro2", "quote", @@ -8846,7 +8879,7 @@ dependencies = [ "itertools 0.10.5", "tar", "tempfile", - "toml_edit", + "toml_edit 0.19.14", ] [[package]] @@ -8953,6 +8986,16 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "num" version = "0.4.1" @@ -9161,7 +9204,7 @@ dependencies = [ "itertools 0.11.0", "layout-rs", "petgraph", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "syn 1.0.109", @@ -9178,12 +9221,12 @@ dependencies = [ [[package]] name = "os_pipe" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ae859aa07428ca9a929b936690f8b12dc5f11dd8c6992a18ca93919f28bc177" +checksum = "57119c3b893986491ec9aa85056780d3a0f3cf4da7cc09dd3650dbd6c6738fb9" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -9192,6 +9235,12 @@ version = "6.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "owo-colors" version = "3.5.0" @@ -9854,7 +9903,7 @@ version = "4.0.0-dev" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -10962,11 +11011,11 @@ dependencies = [ name = "pallet-staking-reward-curve" version = "4.0.0-dev" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "sp-runtime", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -11566,7 +11615,7 @@ version = "3.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a296c3079b5fefbc499e1de58dc26c09b1b9a5952d26694ee89f04a43ebbb3e" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "syn 1.0.109", @@ -11838,7 +11887,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -11879,7 +11928,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -13573,6 +13622,43 @@ dependencies = [ "westend-runtime", ] +[[package]] +name = "polkavm-common" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d9428a5cfcc85c5d7b9fc4b6a18c4b802d0173d768182a51cc7751640f08b92" + +[[package]] +name = "polkavm-derive" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae8c4bea6f3e11cd89bb18bcdddac10bd9a24015399bd1c485ad68a985a19606" +dependencies = [ + "polkavm-derive-impl-macro", +] + +[[package]] +name = "polkavm-derive-impl" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c4fdfc49717fb9a196e74a5d28e0bc764eb394a2c803eb11133a31ac996c60c" +dependencies = [ + "polkavm-common", + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "polkavm-derive-impl-macro" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ba81f7b5faac81e528eb6158a6f3c9e0bb1008e0ffa19653bc8dea925ecb429" +dependencies = [ + "polkavm-derive-impl", + "syn 2.0.60", +] + [[package]] name = "polling" version = "2.8.0" @@ -13745,7 +13831,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c64d9ba0963cdcea2e1b2230fbae2bab30eb25a174be395c41e764bfb65dd62" dependencies = [ "proc-macro2", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -13786,7 +13872,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ "once_cell", - "toml_edit", + "toml_edit 0.19.14", +] + +[[package]] +name = "proc-macro-crate" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit 0.21.1", ] [[package]] @@ -13827,14 +13922,14 @@ checksum = "9b698b0b09d40e9b7c1a47b132d66a8b54bcd20583d9b6d06e4535e383b4405c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" dependencies = [ "unicode-ident", ] @@ -13851,7 +13946,7 @@ dependencies = [ "hex", "lazy_static", "procfs-core", - "rustix 0.38.21", + "rustix 0.38.25", ] [[package]] @@ -13899,7 +13994,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -14057,9 +14152,9 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.9.5" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c956be1b23f4261676aed05a0046e204e8a6836e50203902683a718af0797989" +checksum = "f31999cfc7927c4e212e60fd50934ab40e8e8bfd2d493d6095d2d306bc0764d9" dependencies = [ "bytes", "rand 0.8.5", @@ -14075,9 +14170,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -14214,7 +14309,7 @@ checksum = "6413f3de1edee53342e6138e75b56d32e7bc6e332b3bd62d497b1929d4cfbcdd" dependencies = [ "pem", "ring 0.16.20", - "time 0.3.27", + "time", "x509-parser 0.13.2", "yasna", ] @@ -14227,7 +14322,7 @@ checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" dependencies = [ "pem", "ring 0.16.20", - "time 0.3.27", + "time", "yasna", ] @@ -14290,7 +14385,7 @@ checksum = "7f7473c2cfcf90008193dd0e3e16599455cb601a9fce322b5bb55de799664925" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -14849,14 +14944,14 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.21" +version = "0.38.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" dependencies = [ "bitflags 2.4.0", "errno", "libc", - "linux-raw-sys 0.4.10", + "linux-raw-sys 0.4.13", "windows-sys 0.48.0", ] @@ -15011,16 +15106,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "sc-allocator" -version = "4.1.0-dev" -dependencies = [ - "log", - "sp-core", - "sp-wasm-interface 14.0.0", - "thiserror", -] - [[package]] name = "sc-authority-discovery" version = "0.10.0-dev" @@ -15123,10 +15208,10 @@ dependencies = [ name = "sc-chain-spec-derive" version = "4.0.0-dev" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -15632,7 +15717,7 @@ dependencies = [ "substrate-test-runtime", "tempfile", "tracing", - "tracing-subscriber", + "tracing-subscriber 0.2.25", "wasmi 0.13.2", "wat", ] @@ -15641,7 +15726,7 @@ dependencies = [ name = "sc-executor-common" version = "0.10.0-dev" dependencies = [ - "sc-allocator", + "sp-allocator", "sp-maybe-compressed-blob", "sp-wasm-interface 14.0.0", "thiserror", @@ -15661,9 +15746,9 @@ dependencies = [ "parking_lot 0.12.1", "paste", "rustix 0.36.15", - "sc-allocator", "sc-executor-common", "sc-runtime-test", + "sp-allocator", "sp-io", "sp-runtime-interface 17.0.0", "sp-wasm-interface 14.0.0", @@ -16366,18 +16451,18 @@ dependencies = [ "sp-tracing 10.0.0", "thiserror", "tracing", - "tracing-log", - "tracing-subscriber", + "tracing-log 0.1.3", + "tracing-subscriber 0.2.25", ] [[package]] name = "sc-tracing-proc-macro" version = "4.0.0-dev" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -16464,7 +16549,7 @@ version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "syn 1.0.109", @@ -16731,22 +16816,22 @@ checksum = "f97841a747eef040fcd2e7b3b9a220a7205926e60488e673d9e4926d27772ce5" [[package]] name = "serde" -version = "1.0.188" +version = "1.0.199" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "0c9f6e76df036c77cd94996771fb40db98187f096dd0b9af39c6c6e452ba966a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.199" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "11bd257a6541e141e42ca6d24ae26f7714887b47e89aa739099104c7e4d3b7fc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -16760,9 +16845,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" dependencies = [ "itoa", "ryu", @@ -16812,7 +16897,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -17219,6 +17304,16 @@ dependencies = [ "sha-1 0.9.8", ] +[[package]] +name = "sp-allocator" +version = "4.1.0-dev" +dependencies = [ + "log", + "parity-scale-codec", + "sp-wasm-interface-common", + "thiserror", +] + [[package]] name = "sp-api" version = "4.0.0-dev" @@ -17248,10 +17343,10 @@ dependencies = [ "assert_matches", "blake2 0.10.6", "expander 2.0.0", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -17334,7 +17429,7 @@ version = "0.4.2" source = "git+https://github.com/paritytech/arkworks-substrate#caa2eed74beb885dd07c7db5f916f2281dad818f" dependencies = [ "ark-bls12-381-ext", - "sp-crypto-ec-utils 0.4.1 (git+https://github.com/paritytech/polkadot-sdk)", + "sp-crypto-ec-utils 0.10.0", ] [[package]] @@ -17343,7 +17438,7 @@ version = "0.4.2" source = "git+https://github.com/paritytech/arkworks-substrate#caa2eed74beb885dd07c7db5f916f2281dad818f" dependencies = [ "ark-ed-on-bls12-381-bandersnatch-ext", - "sp-crypto-ec-utils 0.4.1 (git+https://github.com/paritytech/polkadot-sdk)", + "sp-crypto-ec-utils 0.10.0", ] [[package]] @@ -17543,6 +17638,7 @@ dependencies = [ "secrecy", "serde", "serde_json", + "sp-allocator", "sp-core-hashing", "sp-core-hashing-proc-macro", "sp-debug-derive 8.0.0", @@ -17576,7 +17672,7 @@ version = "9.0.0" dependencies = [ "quote", "sp-core-hashing", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -17594,15 +17690,15 @@ dependencies = [ "ark-ed-on-bls12-377-ext", "ark-ed-on-bls12-381-bandersnatch", "ark-ed-on-bls12-381-bandersnatch-ext", - "ark-scale", + "ark-scale 0.0.11", "sp-runtime-interface 17.0.0", "sp-std 8.0.0", ] [[package]] name = "sp-crypto-ec-utils" -version = "0.4.1" -source = "git+https://github.com/paritytech/polkadot-sdk#fe9435db2fda7c9e2f4e29521564c72cac38f59b" +version = "0.10.0" +source = "git+https://github.com/paritytech/polkadot-sdk#f34d8e3cf033e2a22a41b505c437972a5dc83d78" dependencies = [ "ark-bls12-377", "ark-bls12-377-ext", @@ -17615,9 +17711,8 @@ dependencies = [ "ark-ed-on-bls12-377-ext", "ark-ed-on-bls12-381-bandersnatch", "ark-ed-on-bls12-381-bandersnatch-ext", - "ark-scale", - "sp-runtime-interface 17.0.0 (git+https://github.com/paritytech/polkadot-sdk)", - "sp-std 8.0.0 (git+https://github.com/paritytech/polkadot-sdk)", + "ark-scale 0.0.12", + "sp-runtime-interface 24.0.0", ] [[package]] @@ -17634,17 +17729,17 @@ version = "8.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] name = "sp-debug-derive" -version = "8.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#fe9435db2fda7c9e2f4e29521564c72cac38f59b" +version = "14.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk#f34d8e3cf033e2a22a41b505c437972a5dc83d78" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -17659,13 +17754,12 @@ dependencies = [ [[package]] name = "sp-externalities" -version = "0.19.0" -source = "git+https://github.com/paritytech/polkadot-sdk#fe9435db2fda7c9e2f4e29521564c72cac38f59b" +version = "0.25.0" +source = "git+https://github.com/paritytech/polkadot-sdk#f34d8e3cf033e2a22a41b505c437972a5dc83d78" dependencies = [ "environmental", "parity-scale-codec", - "sp-std 8.0.0 (git+https://github.com/paritytech/polkadot-sdk)", - "sp-storage 13.0.0 (git+https://github.com/paritytech/polkadot-sdk)", + "sp-storage 19.0.0", ] [[package]] @@ -17891,19 +17985,20 @@ dependencies = [ [[package]] name = "sp-runtime-interface" -version = "17.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#fe9435db2fda7c9e2f4e29521564c72cac38f59b" +version = "24.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk#f34d8e3cf033e2a22a41b505c437972a5dc83d78" dependencies = [ "bytes", "impl-trait-for-tuples", "parity-scale-codec", + "polkavm-derive", "primitive-types", - "sp-externalities 0.19.0 (git+https://github.com/paritytech/polkadot-sdk)", - "sp-runtime-interface-proc-macro 11.0.0 (git+https://github.com/paritytech/polkadot-sdk)", - "sp-std 8.0.0 (git+https://github.com/paritytech/polkadot-sdk)", - "sp-storage 13.0.0 (git+https://github.com/paritytech/polkadot-sdk)", - "sp-tracing 10.0.0 (git+https://github.com/paritytech/polkadot-sdk)", - "sp-wasm-interface 14.0.0 (git+https://github.com/paritytech/polkadot-sdk)", + "sp-externalities 0.25.0", + "sp-runtime-interface-proc-macro 17.0.0", + "sp-std 14.0.0", + "sp-storage 19.0.0", + "sp-tracing 16.0.0", + "sp-wasm-interface 20.0.0", "static_assertions", ] @@ -17912,22 +18007,23 @@ name = "sp-runtime-interface-proc-macro" version = "11.0.0" dependencies = [ "Inflector", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] name = "sp-runtime-interface-proc-macro" -version = "11.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#fe9435db2fda7c9e2f4e29521564c72cac38f59b" +version = "17.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk#f34d8e3cf033e2a22a41b505c437972a5dc83d78" dependencies = [ "Inflector", - "proc-macro-crate", + "expander 2.0.0", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -18048,8 +18144,8 @@ version = "8.0.0" [[package]] name = "sp-std" -version = "8.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#fe9435db2fda7c9e2f4e29521564c72cac38f59b" +version = "14.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk#f34d8e3cf033e2a22a41b505c437972a5dc83d78" [[package]] name = "sp-storage" @@ -18065,15 +18161,14 @@ dependencies = [ [[package]] name = "sp-storage" -version = "13.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#fe9435db2fda7c9e2f4e29521564c72cac38f59b" +version = "19.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk#f34d8e3cf033e2a22a41b505c437972a5dc83d78" dependencies = [ "impl-serde", "parity-scale-codec", "ref-cast", "serde", - "sp-debug-derive 8.0.0 (git+https://github.com/paritytech/polkadot-sdk)", - "sp-std 8.0.0 (git+https://github.com/paritytech/polkadot-sdk)", + "sp-debug-derive 14.0.0", ] [[package]] @@ -18109,19 +18204,18 @@ dependencies = [ "sp-std 8.0.0", "tracing", "tracing-core", - "tracing-subscriber", + "tracing-subscriber 0.2.25", ] [[package]] name = "sp-tracing" -version = "10.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#fe9435db2fda7c9e2f4e29521564c72cac38f59b" +version = "16.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk#f34d8e3cf033e2a22a41b505c437972a5dc83d78" dependencies = [ "parity-scale-codec", - "sp-std 8.0.0 (git+https://github.com/paritytech/polkadot-sdk)", "tracing", "tracing-core", - "tracing-subscriber", + "tracing-subscriber 0.3.18", ] [[package]] @@ -18198,7 +18292,7 @@ dependencies = [ "proc-macro2", "quote", "sp-version", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -18209,21 +18303,29 @@ dependencies = [ "impl-trait-for-tuples", "log", "parity-scale-codec", + "sp-allocator", "sp-std 8.0.0", + "sp-wasm-interface-common", "wasmtime", ] [[package]] name = "sp-wasm-interface" -version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#fe9435db2fda7c9e2f4e29521564c72cac38f59b" +version = "20.0.0" +source = "git+https://github.com/paritytech/polkadot-sdk#f34d8e3cf033e2a22a41b505c437972a5dc83d78" dependencies = [ - "anyhow", "impl-trait-for-tuples", "log", "parity-scale-codec", - "sp-std 8.0.0 (git+https://github.com/paritytech/polkadot-sdk)", - "wasmtime", +] + +[[package]] +name = "sp-wasm-interface-common" +version = "7.0.0" +dependencies = [ + "parity-scale-codec", + "sp-std 8.0.0", + "wasmi 0.13.2", ] [[package]] @@ -19082,9 +19184,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.38" +version = "2.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" dependencies = [ "proc-macro2", "quote", @@ -19156,7 +19258,7 @@ dependencies = [ "cfg-if", "fastrand 2.0.0", "redox_syscall 0.3.5", - "rustix 0.38.21", + "rustix 0.38.25", "windows-sys 0.48.0", ] @@ -19175,7 +19277,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" dependencies = [ - "rustix 0.38.21", + "rustix 0.38.25", "windows-sys 0.48.0", ] @@ -19352,7 +19454,7 @@ checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -19424,17 +19526,6 @@ dependencies = [ "tikv-jemalloc-sys", ] -[[package]] -name = "time" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", -] - [[package]] name = "time" version = "0.3.27" @@ -19524,7 +19615,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -19618,14 +19709,26 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.19.14", +] + +[[package]] +name = "toml" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.20.2", ] [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" dependencies = [ "serde", ] @@ -19643,6 +19746,30 @@ dependencies = [ "winnow", ] +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap 2.0.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap 2.0.0", + "toml_datetime", + "winnow", +] + [[package]] name = "tower" version = "0.4.13" @@ -19705,14 +19832,14 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -19744,10 +19871,10 @@ version = "1.0.0" dependencies = [ "assert_matches", "expander 2.0.0", - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] @@ -19761,6 +19888,17 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + [[package]] name = "tracing-serde" version = "0.1.3" @@ -19780,7 +19918,7 @@ dependencies = [ "ansi_term", "chrono", "lazy_static", - "matchers", + "matchers 0.0.1", "parking_lot 0.11.2", "regex", "serde", @@ -19790,10 +19928,28 @@ dependencies = [ "thread_local", "tracing", "tracing-core", - "tracing-log", + "tracing-log 0.1.3", "tracing-serde", ] +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers 0.1.0", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log 0.2.0", +] + [[package]] name = "trie-bench" version = "0.38.0" @@ -20142,9 +20298,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "value-bag" -version = "1.4.1" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d92ccd67fb88503048c01b59152a04effd0782d035a83a6d256ce6085f08f4a3" +checksum = "74797339c3b98616c009c7c3eb53a0ce41e85c8ec66bd3db96ed132d20cfdee8" dependencies = [ "value-bag-serde1", "value-bag-sval2", @@ -20152,9 +20308,9 @@ dependencies = [ [[package]] name = "value-bag-serde1" -version = "1.4.1" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0b9f3feef403a50d4d67e9741a6d8fc688bcbb4e4f31bd4aab72cc690284394" +checksum = "cc35703541cbccb5278ef7b589d79439fc808ff0b5867195a3230f9a47421d39" dependencies = [ "erased-serde", "serde", @@ -20163,9 +20319,9 @@ dependencies = [ [[package]] name = "value-bag-sval2" -version = "1.4.1" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b24f4146b6f3361e91cbf527d1fb35e9376c3c0cef72ca5ec5af6d640fad7d" +checksum = "285b43c29d0b4c0e65aad24561baee67a1b69dc9be9375d4a85138cbf556f7f8" dependencies = [ "sval", "sval_buffer", @@ -20267,12 +20423,6 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -20302,7 +20452,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", "wasm-bindgen-shared", ] @@ -20336,7 +20486,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -20806,7 +20956,7 @@ dependencies = [ "sha2 0.10.7", "stun", "thiserror", - "time 0.3.27", + "time", "tokio", "turn", "url", @@ -21242,6 +21392,15 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.5", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -21272,6 +21431,22 @@ dependencies = [ "windows_x86_64_msvc 0.48.5", ] +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -21284,6 +21459,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + [[package]] name = "windows_aarch64_msvc" version = "0.34.0" @@ -21302,6 +21483,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + [[package]] name = "windows_i686_gnu" version = "0.34.0" @@ -21320,6 +21507,18 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + [[package]] name = "windows_i686_msvc" version = "0.34.0" @@ -21338,6 +21537,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + [[package]] name = "windows_x86_64_gnu" version = "0.34.0" @@ -21356,6 +21561,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -21368,6 +21579,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + [[package]] name = "windows_x86_64_msvc" version = "0.34.0" @@ -21386,6 +21603,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + [[package]] name = "winnow" version = "0.5.15" @@ -21453,7 +21676,7 @@ dependencies = [ "ring 0.16.20", "rusticata-macros", "thiserror", - "time 0.3.27", + "time", ] [[package]] @@ -21471,7 +21694,7 @@ dependencies = [ "oid-registry 0.6.1", "rusticata-macros", "thiserror", - "time 0.3.27", + "time", ] [[package]] @@ -21543,7 +21766,7 @@ dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", "trybuild", ] @@ -21643,7 +21866,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" dependencies = [ - "time 0.3.27", + "time", ] [[package]] @@ -21663,7 +21886,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.60", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index ed252e07053f..876ceb648c83 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -206,7 +206,6 @@ members = [ "substrate/bin/node/testing", "substrate/bin/utils/chain-spec-builder", "substrate/bin/utils/subkey", - "substrate/client/allocator", "substrate/client/api", "substrate/client/authority-discovery", "substrate/client/basic-authorship", @@ -386,6 +385,7 @@ members = [ "substrate/frame/utility", "substrate/frame/vesting", "substrate/frame/whitelist", + "substrate/primitives/allocator", "substrate/primitives/api", "substrate/primitives/api/proc-macro", "substrate/primitives/api/test", diff --git a/substrate/client/allocator/Cargo.toml b/substrate/client/allocator/Cargo.toml deleted file mode 100644 index 31c714180ce5..000000000000 --- a/substrate/client/allocator/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "sc-allocator" -version = "4.1.0-dev" -authors.workspace = true -edition.workspace = true -license = "Apache-2.0" -homepage = "https://substrate.io" -repository.workspace = true -description = "Collection of allocator implementations." -documentation = "https://docs.rs/sc-allocator" -readme = "README.md" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[dependencies] -log = "0.4.17" -thiserror = "1.0.48" -sp-core = { path = "../../primitives/core" } -sp-wasm-interface = { path = "../../primitives/wasm-interface" } diff --git a/substrate/client/executor/common/Cargo.toml b/substrate/client/executor/common/Cargo.toml index 5118279b43b4..501bfd55dd92 100644 --- a/substrate/client/executor/common/Cargo.toml +++ b/substrate/client/executor/common/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] thiserror = "1.0.48" wasm-instrument = "0.3" -sc-allocator = { path = "../../allocator" } +sp-allocator = { path = "../../../primitives/allocator" } sp-maybe-compressed-blob = { path = "../../../primitives/maybe-compressed-blob" } sp-wasm-interface = { path = "../../../primitives/wasm-interface" } diff --git a/substrate/client/executor/common/src/error.rs b/substrate/client/executor/common/src/error.rs index 2a0dc364b410..62d2283a678e 100644 --- a/substrate/client/executor/common/src/error.rs +++ b/substrate/client/executor/common/src/error.rs @@ -59,7 +59,7 @@ pub enum Error { Other(String), #[error(transparent)] - Allocator(#[from] sc_allocator::Error), + Allocator(#[from] sp_allocator::Error), #[error("Host function {0} execution failed with: {1}")] FunctionExecution(String, String), diff --git a/substrate/client/executor/common/src/util.rs b/substrate/client/executor/common/src/util.rs index 34967f86595d..ac6e957ebb04 100644 --- a/substrate/client/executor/common/src/util.rs +++ b/substrate/client/executor/common/src/util.rs @@ -20,14 +20,6 @@ use crate::error::Result; use sp_wasm_interface::Pointer; -use std::ops::Range; - -/// Construct a range from an offset to a data length after the offset. -/// Returns None if the end of the range would exceed some maximum offset. -pub fn checked_range(offset: usize, len: usize, max: usize) -> Option> { - let end = offset.checked_add(len)?; - (end <= max).then(|| offset..end) -} /// Provides safe memory access interface using an external buffer pub trait MemoryTransfer { diff --git a/substrate/client/executor/common/src/wasm_runtime.rs b/substrate/client/executor/common/src/wasm_runtime.rs index d8e142b9d559..bbe20cc60584 100644 --- a/substrate/client/executor/common/src/wasm_runtime.rs +++ b/substrate/client/executor/common/src/wasm_runtime.rs @@ -21,7 +21,7 @@ use crate::error::Error; use sp_wasm_interface::Value; -pub use sc_allocator::AllocationStats; +pub use sp_allocator::AllocationStats; /// Default heap allocation strategy. pub const DEFAULT_HEAP_ALLOC_STRATEGY: HeapAllocStrategy = diff --git a/substrate/client/executor/wasmi/Cargo.toml b/substrate/client/executor/wasmi/Cargo.toml index 0b00bb6cead7..943b65101748 100644 --- a/substrate/client/executor/wasmi/Cargo.toml +++ b/substrate/client/executor/wasmi/Cargo.toml @@ -17,6 +17,6 @@ targets = ["x86_64-unknown-linux-gnu"] log = "0.4.17" wasmi = { git = "https://github.com/gear-tech/wasmi", branch = "v0.13.2-sign-ext", features = ["virtual_memory"] } sc-executor-common = { version = "0.10.0-dev", path = "../common" } -sp-allocator = { version = "4.1.0-dev", path = "../../../primitives/allocator" } +sp-allocator = { path = "../../primitives/allocator" } sp-runtime-interface = { version = "7.0.0", path = "../../../primitives/runtime-interface" } sp-wasm-interface = { version = "7.0.0", path = "../../../primitives/wasm-interface" } diff --git a/substrate/client/executor/wasmtime/Cargo.toml b/substrate/client/executor/wasmtime/Cargo.toml index 261d52c0ede3..37981154b24f 100644 --- a/substrate/client/executor/wasmtime/Cargo.toml +++ b/substrate/client/executor/wasmtime/Cargo.toml @@ -28,7 +28,7 @@ wasmtime = { version = "8.0.1", default-features = false, features = [ "pooling-allocator" ] } anyhow = "1.0.68" -sc-allocator = { path = "../../allocator" } +sp-allocator = { path = "../../../primitives/allocator" } sc-executor-common = { path = "../common" } sp-runtime-interface = { path = "../../../primitives/runtime-interface" } sp-wasm-interface = { path = "../../../primitives/wasm-interface", features = ["wasmtime"] } diff --git a/substrate/client/executor/wasmtime/src/host.rs b/substrate/client/executor/wasmtime/src/host.rs index f8c78cbb660e..2cc6c7ba7063 100644 --- a/substrate/client/executor/wasmtime/src/host.rs +++ b/substrate/client/executor/wasmtime/src/host.rs @@ -21,41 +21,10 @@ use wasmtime::Caller; -use sc_allocator::{AllocationStats, FreeingBumpHeapAllocator}; -use sp_wasm_interface::{Pointer, WordSize}; +pub use sp_wasm_interface::HostState; +use sp_wasm_interface::{util, FunctionContextToken, Pointer, WordSize}; -use crate::{instance_wrapper::MemoryWrapper, runtime::StoreData, util}; - -/// The state required to construct a HostContext context. The context only lasts for one host -/// call, whereas the state is maintained for the duration of a Wasm runtime call, which may make -/// many different host calls that must share state. -pub struct HostState { - /// The allocator instance to keep track of allocated memory. - /// - /// This is stored as an `Option` as we need to temporarily set this to `None` when we are - /// allocating/deallocating memory. The problem being that we can only mutable access `caller` - /// once. - allocator: Option, - panic_message: Option, -} - -impl HostState { - /// Constructs a new `HostState`. - pub fn new(allocator: FreeingBumpHeapAllocator) -> Self { - HostState { allocator: Some(allocator), panic_message: None } - } - - /// Takes the error message out of the host state, leaving a `None` in its place. - pub fn take_panic_message(&mut self) -> Option { - self.panic_message.take() - } - - pub(crate) fn allocation_stats(&self) -> AllocationStats { - self.allocator.as_ref() - .expect("Allocator is always set and only unavailable when doing an allocation/deallocation; qed") - .stats() - } -} +use crate::runtime::StoreData; /// A `HostContext` implements `FunctionContext` for making host calls from a Wasmtime /// runtime. The `HostContext` exists only for the lifetime of the call and borrows state from @@ -64,15 +33,6 @@ pub(crate) struct HostContext<'a> { pub(crate) caller: Caller<'a, StoreData>, } -impl<'a> HostContext<'a> { - fn host_state_mut(&mut self) -> &mut HostState { - self.caller - .data_mut() - .host_state_mut() - .expect("host state is not empty when calling a function in wasm; qed") - } -} - impl<'a> sp_wasm_interface::FunctionContext for HostContext<'a> { fn read_memory_into( &self, @@ -87,42 +47,27 @@ impl<'a> sp_wasm_interface::FunctionContext for HostContext<'a> { } fn allocate_memory(&mut self, size: WordSize) -> sp_wasm_interface::Result> { - let memory = self.caller.data().memory(); - let mut allocator = self - .host_state_mut() - .allocator - .take() - .expect("allocator is not empty when calling a function in wasm; qed"); - - // We can not return on error early, as we need to store back allocator. - let res = allocator - .allocate(&mut MemoryWrapper(&memory, &mut self.caller), size) - .map_err(|e| e.to_string()); - - self.host_state_mut().allocator = Some(allocator); - - res + util::allocate_memory(&mut self.caller, size) } fn deallocate_memory(&mut self, ptr: Pointer) -> sp_wasm_interface::Result<()> { - let memory = self.caller.data().memory(); - let mut allocator = self - .host_state_mut() - .allocator - .take() - .expect("allocator is not empty when calling a function in wasm; qed"); - - // We can not return on error early, as we need to store back allocator. - let res = allocator - .deallocate(&mut MemoryWrapper(&memory, &mut self.caller), ptr) - .map_err(|e| e.to_string()); - - self.host_state_mut().allocator = Some(allocator); - - res + util::deallocate_memory(&mut self.caller, ptr) } fn register_panic_error_message(&mut self, message: &str) { - self.host_state_mut().panic_message = Some(message.to_owned()); + self.caller + .data_mut() + .host_state_mut() + .expect("host state is not empty when calling a function in wasm; qed") + .panic_message = Some(message.to_owned()); + } + + fn with_caller_mut_impl( + &mut self, + _: FunctionContextToken, + context: *mut (), + callback: fn(*mut (), &mut Caller), + ) { + callback(context, &mut self.caller) } } diff --git a/substrate/client/executor/wasmtime/src/instance_wrapper.rs b/substrate/client/executor/wasmtime/src/instance_wrapper.rs index 8852532adbca..00eda1f3c35b 100644 --- a/substrate/client/executor/wasmtime/src/instance_wrapper.rs +++ b/substrate/client/executor/wasmtime/src/instance_wrapper.rs @@ -65,10 +65,12 @@ impl EntryPoint { let data_len = u32::from(data_len); match self.call_type { - EntryPointType::Direct { ref entrypoint } => - entrypoint.call(&mut *store, (data_ptr, data_len)), - EntryPointType::Wrapped { func, ref dispatcher } => - dispatcher.call(&mut *store, (func, data_ptr, data_len)), + EntryPointType::Direct { ref entrypoint } => { + entrypoint.call(&mut *store, (data_ptr, data_len)) + }, + EntryPointType::Wrapped { func, ref dispatcher } => { + dispatcher.call(&mut *store, (func, data_ptr, data_len)) + }, } .map_err(|trap| { let host_state = store @@ -114,41 +116,6 @@ impl EntryPoint { } } -/// Wrapper around [`Memory`] that implements [`sc_allocator::Memory`]. -pub(crate) struct MemoryWrapper<'a, C>(pub &'a wasmtime::Memory, pub &'a mut C); - -impl sc_allocator::Memory for MemoryWrapper<'_, C> { - fn with_access_mut(&mut self, run: impl FnOnce(&mut [u8]) -> R) -> R { - run(self.0.data_mut(&mut self.1)) - } - - fn with_access(&self, run: impl FnOnce(&[u8]) -> R) -> R { - run(self.0.data(&self.1)) - } - - fn grow(&mut self, additional: u32) -> std::result::Result<(), ()> { - self.0 - .grow(&mut self.1, additional as u64) - .map_err(|e| { - log::error!( - target: "wasm-executor", - "Failed to grow memory by {} pages: {}", - additional, - e, - ) - }) - .map(drop) - } - - fn pages(&self) -> u32 { - self.0.size(&self.1) as u32 - } - - fn max_pages(&self) -> Option { - self.0.ty(&self.1).maximum().map(|p| p as _) - } -} - /// Wrap the given WebAssembly Instance of a wasm module with Substrate-runtime. /// /// This struct is a handy wrapper around a wasmtime `Instance` that provides substrate specific diff --git a/substrate/client/executor/wasmtime/src/runtime.rs b/substrate/client/executor/wasmtime/src/runtime.rs index ac88663f4e79..beb8c8b37299 100644 --- a/substrate/client/executor/wasmtime/src/runtime.rs +++ b/substrate/client/executor/wasmtime/src/runtime.rs @@ -20,20 +20,22 @@ use crate::{ host::HostState, - instance_wrapper::{EntryPoint, InstanceWrapper, MemoryWrapper}, - util::{self, replace_strategy_if_broken}, + instance_wrapper::{EntryPoint, InstanceWrapper}, + util::replace_strategy_if_broken, }; use parking_lot::Mutex; -use sc_allocator::{AllocationStats, FreeingBumpHeapAllocator}; use sc_executor_common::{ - error::{Error, Result, WasmError}, + error::{Result, WasmError}, runtime_blob::RuntimeBlob, - util::checked_range, wasm_runtime::{HeapAllocStrategy, InvokeMethod, WasmInstance, WasmModule}, }; +use sp_allocator::{AllocationStats, FreeingBumpHeapAllocator}; use sp_runtime_interface::unpack_ptr_and_len; -use sp_wasm_interface::{HostFunctions, Pointer, Value, WordSize}; +pub use sp_wasm_interface::StoreData; +use sp_wasm_interface::{ + util as memory_util, HostFunctions, MemoryWrapper, Pointer, Value, WordSize, +}; use std::{ path::{Path, PathBuf}, sync::{ @@ -45,28 +47,6 @@ use wasmtime::{AsContext, Engine, Memory, Table}; const MAX_INSTANCE_COUNT: u32 = 64; -#[derive(Default)] -pub(crate) struct StoreData { - /// This will only be set when we call into the runtime. - pub(crate) host_state: Option, - /// This will be always set once the store is initialized. - pub(crate) memory: Option, - /// This will be set only if the runtime actually contains a table. - pub(crate) table: Option, -} - -impl StoreData { - /// Returns a mutable reference to the host state. - pub fn host_state_mut(&mut self) -> Option<&mut HostState> { - self.host_state.as_mut() - } - - /// Returns the host memory. - pub fn memory(&self) -> Memory { - self.memory.expect("memory is always set; qed") - } -} - pub(crate) type Store = wasmtime::Store; enum Strategy { @@ -194,8 +174,9 @@ impl WasmInstance for WasmtimeInstance { fn get_global_const(&mut self, name: &str) -> Result> { match &mut self.strategy { - Strategy::RecreateInstance(ref mut instance_creator) => - instance_creator.instantiate()?.get_global_val(name), + Strategy::RecreateInstance(ref mut instance_creator) => { + instance_creator.instantiate()?.get_global_val(name) + }, } } } @@ -298,8 +279,9 @@ fn common_config(semantics: &Semantics) -> std::result::Result - maximum_pages.map(|p| p as u64 * WASM_PAGE_SIZE).unwrap_or(u64::MAX), + HeapAllocStrategy::Dynamic { maximum_pages } => { + maximum_pages.map(|p| p as u64 * WASM_PAGE_SIZE).unwrap_or(u64::MAX) + }, HeapAllocStrategy::Static { .. } => u64::MAX, }); @@ -307,8 +289,9 @@ fn common_config(semantics: &Semantics) -> std::result::Result - maximum_pages.map(|p| p as u64).unwrap_or(MAX_WASM_PAGES), + HeapAllocStrategy::Dynamic { maximum_pages } => { + maximum_pages.map(|p| p as u64).unwrap_or(MAX_WASM_PAGES) + }, HeapAllocStrategy::Static { .. } => MAX_WASM_PAGES, }; @@ -604,11 +587,12 @@ where .map_err(|e| WasmError::Other(format!("cannot create module: {:#}", e)))?; match config.semantics.instantiation_strategy { - InstantiationStrategy::Pooling | - InstantiationStrategy::PoolingCopyOnWrite | - InstantiationStrategy::RecreateInstance | - InstantiationStrategy::RecreateInstanceCopyOnWrite => - (module, InternalInstantiationStrategy::Builtin), + InstantiationStrategy::Pooling + | InstantiationStrategy::PoolingCopyOnWrite + | InstantiationStrategy::RecreateInstance + | InstantiationStrategy::RecreateInstanceCopyOnWrite => { + (module, InternalInstantiationStrategy::Builtin) + }, } }, CodeSupplyMode::Precompiled(compiled_artifact_path) => { @@ -723,8 +707,8 @@ fn inject_input_data( let mut ctx = instance.store_mut(); let memory = ctx.data().memory(); let data_len = data.len() as WordSize; - let data_ptr = allocator.allocate(&mut MemoryWrapper(&memory, &mut ctx), data_len)?; - util::write_memory_from(instance.store_mut(), data_ptr, data)?; + let data_ptr = allocator.allocate(&mut MemoryWrapper::from((&memory, &mut ctx)), data_len)?; + memory_util::write_memory_from(instance.store_mut(), data_ptr, data)?; Ok((data_ptr, data_len)) } @@ -741,11 +725,11 @@ fn extract_output_data( // // Get the size of the WASM memory in bytes. let memory_size = ctx.as_context().data().memory().data_size(ctx); - if checked_range(output_ptr as usize, output_len as usize, memory_size).is_none() { - Err(Error::OutputExceedsBounds)? + if memory_util::checked_range(output_ptr as usize, output_len as usize, memory_size).is_none() { + Err(WasmError::Other("output exceeds bounds of wasm memory".into()))? } let mut output = vec![0; output_len as usize]; - util::read_memory_into(ctx, Pointer::new(output_ptr), &mut output)?; + memory_util::read_memory_into(ctx, Pointer::new(output_ptr), &mut output)?; Ok(output) } diff --git a/substrate/client/executor/wasmtime/src/util.rs b/substrate/client/executor/wasmtime/src/util.rs index 7af554c35e1b..d63eedaf3e4d 100644 --- a/substrate/client/executor/wasmtime/src/util.rs +++ b/substrate/client/executor/wasmtime/src/util.rs @@ -19,11 +19,35 @@ use crate::{runtime::StoreData, InstantiationStrategy}; use sc_executor_common::{ error::{Error, Result}, - util::checked_range, }; -use sp_wasm_interface::Pointer; +use sp_wasm_interface::util as memory_util; +use sp_wasm_interface::{Pointer, Value}; use wasmtime::{AsContext, AsContextMut}; +/// Converts a [`wasmtime::Val`] into a substrate runtime interface [`Value`]. +/// +/// Panics if the given value doesn't have a corresponding variant in `Value`. +pub fn from_wasmtime_val(val: wasmtime::Val) -> Value { + match val { + wasmtime::Val::I32(v) => Value::I32(v), + wasmtime::Val::I64(v) => Value::I64(v), + wasmtime::Val::F32(f_bits) => Value::F32(f_bits), + wasmtime::Val::F64(f_bits) => Value::F64(f_bits), + v => panic!("Given value type is unsupported by Substrate: {:?}", v), + } +} + +/// Converts a sp_wasm_interface's [`Value`] into the corresponding variant in wasmtime's +/// [`wasmtime::Val`]. +pub fn into_wasmtime_val(value: Value) -> wasmtime::Val { + match value { + Value::I32(v) => wasmtime::Val::I32(v), + Value::I64(v) => wasmtime::Val::I64(v), + Value::F32(f_bits) => wasmtime::Val::F32(f_bits), + Value::F64(f_bits) => wasmtime::Val::F64(f_bits), + } +} + /// Read data from the instance memory into a slice. /// /// Returns an error if the read would go out of the memory bounds. @@ -34,7 +58,7 @@ pub(crate) fn read_memory_into( ) -> Result<()> { let memory = ctx.as_context().data().memory().data(&ctx); - let range = checked_range(address.into(), dest.len(), memory.len()) + let range = memory_util::checked_range(address.into(), dest.len(), memory.len()) .ok_or_else(|| Error::Other("memory read is out of bounds".into()))?; dest.copy_from_slice(&memory[range]); Ok(()) @@ -51,7 +75,7 @@ pub(crate) fn write_memory_from( let memory = ctx.as_context().data().memory(); let memory = memory.data_mut(&mut ctx); - let range = checked_range(address.into(), data.len(), memory.len()) + let range = memory_util::checked_range(address.into(), data.len(), memory.len()) .ok_or_else(|| Error::Other("memory write is out of bounds".into()))?; memory[range].copy_from_slice(data); Ok(()) @@ -116,8 +140,9 @@ pub(crate) fn replace_strategy_if_broken(strategy: &mut InstantiationStrategy) { // These strategies require a working `madvise` to be sound. InstantiationStrategy::PoolingCopyOnWrite => InstantiationStrategy::Pooling, - InstantiationStrategy::RecreateInstanceCopyOnWrite => - InstantiationStrategy::RecreateInstance, + InstantiationStrategy::RecreateInstanceCopyOnWrite => { + InstantiationStrategy::RecreateInstance + }, }; use std::sync::OnceLock; diff --git a/substrate/primitives/allocator/Cargo.toml b/substrate/primitives/allocator/Cargo.toml new file mode 100644 index 000000000000..18241f38901b --- /dev/null +++ b/substrate/primitives/allocator/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "sp-allocator" +version = "4.1.0-dev" +authors = ["Parity Technologies "] +edition = "2021" +license = "Apache-2.0" +homepage = "https://substrate.io" +repository = "https://github.com/paritytech/substrate/" +description = "Collection of allocator implementations." +documentation = "https://docs.rs/sc-allocator" +readme = "README.md" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +log = { version = "0.4.17", default-features = false } +thiserror = { version = "1.0.30", optional = true } +codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false, features = ["derive"] } +sp-wasm-interface-common = { version = "7.0.0", path = "../wasm-interface-common", default-features = false } + +[features] +default = [ "std" ] +std = [ "codec/std", "log/std", "sp-wasm-interface-common/std", "thiserror" ] diff --git a/substrate/client/allocator/README.md b/substrate/primitives/allocator/README.md similarity index 100% rename from substrate/client/allocator/README.md rename to substrate/primitives/allocator/README.md diff --git a/substrate/client/allocator/src/error.rs b/substrate/primitives/allocator/src/error.rs similarity index 100% rename from substrate/client/allocator/src/error.rs rename to substrate/primitives/allocator/src/error.rs diff --git a/substrate/client/allocator/src/freeing_bump.rs b/substrate/primitives/allocator/src/freeing_bump.rs similarity index 98% rename from substrate/client/allocator/src/freeing_bump.rs rename to substrate/primitives/allocator/src/freeing_bump.rs index 144c0764540d..f380196bd97f 100644 --- a/substrate/client/allocator/src/freeing_bump.rs +++ b/substrate/primitives/allocator/src/freeing_bump.rs @@ -67,9 +67,8 @@ //! wasted. This is more pronounced (in terms of absolute heap amounts) with larger allocation //! sizes. -use crate::{Error, Memory, MAX_WASM_PAGES, PAGE_SIZE}; -pub use sp_core::MAX_POSSIBLE_ALLOCATION; -use sp_wasm_interface::{Pointer, WordSize}; +use crate::{Error, Memory, MAX_POSSIBLE_ALLOCATION, MAX_WASM_PAGES, PAGE_SIZE}; +use sp_wasm_interface_common::{Pointer, WordSize}; use std::{ cmp::{max, min}, mem, @@ -142,7 +141,7 @@ impl Order { fn from_size(size: u32) -> Result { let clamped_size = if size > MAX_POSSIBLE_ALLOCATION { log::warn!(target: LOG_TARGET, "going to fail due to allocating {:?}", size); - return Err(Error::RequestedAllocationTooLarge) + return Err(Error::RequestedAllocationTooLarge); } else if size < MIN_POSSIBLE_ALLOCATION { MIN_POSSIBLE_ALLOCATION } else { @@ -411,7 +410,7 @@ impl FreeingBumpHeapAllocator { size: WordSize, ) -> Result, Error> { if self.poisoned { - return Err(error("the allocator has been poisoned")) + return Err(error("the allocator has been poisoned")); } let bomb = PoisonBomb { poisoned: &mut self.poisoned }; @@ -421,10 +420,10 @@ impl FreeingBumpHeapAllocator { let header_ptr: u32 = match self.free_lists[order] { Link::Ptr(header_ptr) => { - if (u64::from(header_ptr) + u64::from(order.size()) + u64::from(HEADER_SIZE)) > - mem.size() + if (u64::from(header_ptr) + u64::from(order.size()) + u64::from(HEADER_SIZE)) + > mem.size() { - return Err(error("Invalid header pointer detected")) + return Err(error("Invalid header pointer detected")); } // Remove this header from the free list. @@ -469,7 +468,7 @@ impl FreeingBumpHeapAllocator { /// - `ptr` - pointer to the allocated chunk pub fn deallocate(&mut self, mem: &mut impl Memory, ptr: Pointer) -> Result<(), Error> { if self.poisoned { - return Err(error("the allocator has been poisoned")) + return Err(error("the allocator has been poisoned")); } let bomb = PoisonBomb { poisoned: &mut self.poisoned }; @@ -529,14 +528,14 @@ impl FreeingBumpHeapAllocator { "Wasm pages ({current_pages}) are already at the maximum.", ); - return Err(Error::AllocatorOutOfSpace) + return Err(Error::AllocatorOutOfSpace); } else if required_pages > max_pages { log::debug!( target: LOG_TARGET, "Failed to grow memory from {current_pages} pages to at least {required_pages}\ pages due to the maximum limit of {max_pages} pages", ); - return Err(Error::AllocatorOutOfSpace) + return Err(Error::AllocatorOutOfSpace); } // Ideally we want to double our current number of pages, @@ -551,7 +550,7 @@ impl FreeingBumpHeapAllocator { "Failed to grow memory from {current_pages} pages to {next_pages} pages", ); - return Err(Error::AllocatorOutOfSpace) + return Err(Error::AllocatorOutOfSpace); } debug_assert_eq!(memory.pages(), next_pages, "Number of pages should have increased!"); @@ -567,7 +566,7 @@ impl FreeingBumpHeapAllocator { mem: &mut impl Memory, ) -> Result<(), Error> { if mem.size() < *last_observed_memory_size { - return Err(Error::MemoryShrinked) + return Err(Error::MemoryShrinked); } *last_observed_memory_size = mem.size(); Ok(()) diff --git a/substrate/client/allocator/src/lib.rs b/substrate/primitives/allocator/src/lib.rs similarity index 86% rename from substrate/client/allocator/src/lib.rs rename to substrate/primitives/allocator/src/lib.rs index e50d7d54c8e9..d8fc749b5546 100644 --- a/substrate/client/allocator/src/lib.rs +++ b/substrate/primitives/allocator/src/lib.rs @@ -20,12 +20,17 @@ //! This crate provides the following allocator implementations: //! - A freeing-bump allocator: [`FreeingBumpHeapAllocator`](freeing_bump::FreeingBumpHeapAllocator) +#![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_docs)] +#[cfg(feature = "std")] mod error; +#[cfg(feature = "std")] mod freeing_bump; +#[cfg(feature = "std")] pub use error::Error; +#[cfg(feature = "std")] pub use freeing_bump::{AllocationStats, FreeingBumpHeapAllocator}; /// The size of one wasm page in bytes. @@ -59,3 +64,9 @@ pub trait Memory { /// If `None` is returned, there is no maximum (besides the maximum defined in the wasm spec). fn max_pages(&self) -> Option; } + +/// The maximum number of bytes that can be allocated at one time. +// The maximum possible allocation size was chosen rather arbitrary, 32 MiB should be enough for +// everybody. +// 2^25 bytes, 32 MiB +pub const MAX_POSSIBLE_ALLOCATION: u32 = 33_554_432; diff --git a/substrate/primitives/core/Cargo.toml b/substrate/primitives/core/Cargo.toml index 79df81e62c66..146160507583 100644 --- a/substrate/primitives/core/Cargo.toml +++ b/substrate/primitives/core/Cargo.toml @@ -52,6 +52,7 @@ libsecp256k1 = { version = "0.7", default-features = false, features = ["static- schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated", "u64_backend"], default-features = false } merlin = { version = "2.0", default-features = false } secp256k1 = { version = "0.24.0", default-features = false, features = ["recovery", "alloc"], optional = true } +sp-allocator = { version = "4.1.0-dev", path = "../allocator", default-features = false } sp-core-hashing = { path = "hashing", default-features = false, optional = true } sp-runtime-interface = { path = "../runtime-interface", default-features = false} diff --git a/substrate/primitives/core/src/lib.rs b/substrate/primitives/core/src/lib.rs index ec0641c54668..773b413d235d 100644 --- a/substrate/primitives/core/src/lib.rs +++ b/substrate/primitives/core/src/lib.rs @@ -399,10 +399,7 @@ macro_rules! impl_maybe_marker_std_or_serde { } } -/// The maximum number of bytes that can be allocated at one time. -// The maximum possible allocation size was chosen rather arbitrary, 32 MiB should be enough for -// everybody. -pub const MAX_POSSIBLE_ALLOCATION: u32 = 33554432; // 2^25 bytes, 32 MiB +pub use sp_allocator::MAX_POSSIBLE_ALLOCATION; /// Generates a macro for checking if a certain feature is enabled. /// diff --git a/substrate/primitives/wasm-interface-common/Cargo.toml b/substrate/primitives/wasm-interface-common/Cargo.toml new file mode 100644 index 000000000000..0d319e9591b6 --- /dev/null +++ b/substrate/primitives/wasm-interface-common/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "sp-wasm-interface-common" +version = "7.0.0" +authors = ["Parity Technologies "] +edition = "2021" +license = "Apache-2.0" +homepage = "https://substrate.io" +repository = "https://github.com/paritytech/substrate/" +description = "Types and traits for interfacing between the host and the wasm runtime." +documentation = "https://docs.rs/sp-wasm-interface" +readme = "README.md" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false, features = ["derive"] } +wasmi = { git = "https://github.com/gear-tech/wasmi", branch = "v0.13.2-sign-ext", default-features = false, optional = true } +sp-std = { version = "8.0.0", default-features = false, path = "../std" } + +[features] +default = [ "std" ] +std = [ "codec/std", "sp-std/std", "wasmi/std" ] diff --git a/substrate/primitives/wasm-interface-common/README.md b/substrate/primitives/wasm-interface-common/README.md new file mode 100644 index 000000000000..7e6c46581ae4 --- /dev/null +++ b/substrate/primitives/wasm-interface-common/README.md @@ -0,0 +1,3 @@ +Types and traits for interfacing between the host and the wasm runtime. + +License: Apache-2.0 \ No newline at end of file diff --git a/substrate/primitives/wasm-interface-common/src/lib.rs b/substrate/primitives/wasm-interface-common/src/lib.rs new file mode 100644 index 000000000000..18d5a9759203 --- /dev/null +++ b/substrate/primitives/wasm-interface-common/src/lib.rs @@ -0,0 +1,346 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Types and traits for interfacing between the host and the wasm runtime. + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::borrow::Cow; +use core::{mem, marker::PhantomData}; + +pub mod util; + +#[cfg(feature = "wasmi")] +pub use wasmi; + +#[cfg(feature = "wasmi")] +pub mod wasmi_impl; + +/// Value types supported by Substrate on the boundary between host/Wasm. +#[derive(Copy, Clone, PartialEq, Debug, Eq)] +pub enum ValueType { + /// An `i32` value type. + I32, + /// An `i64` value type. + I64, + /// An `f32` value type. + F32, + /// An `f64` value type. + F64, +} + +impl From for u8 { + fn from(val: ValueType) -> u8 { + match val { + ValueType::I32 => 0, + ValueType::I64 => 1, + ValueType::F32 => 2, + ValueType::F64 => 3, + } + } +} + +impl TryFrom for ValueType { + type Error = (); + + fn try_from(val: u8) -> core::result::Result { + match val { + 0 => Ok(Self::I32), + 1 => Ok(Self::I64), + 2 => Ok(Self::F32), + 3 => Ok(Self::F64), + _ => Err(()), + } + } +} + +/// Values supported by Substrate on the boundary between host/Wasm. +#[derive(PartialEq, Debug, Clone, Copy, codec::Encode, codec::Decode)] +pub enum Value { + /// A 32-bit integer. + I32(i32), + /// A 64-bit integer. + I64(i64), + /// A 32-bit floating-point number stored as raw bit pattern. + /// + /// You can materialize this value using `f32::from_bits`. + F32(u32), + /// A 64-bit floating-point number stored as raw bit pattern. + /// + /// You can materialize this value using `f64::from_bits`. + F64(u64), +} + +impl Value { + /// Returns the type of this value. + pub fn value_type(&self) -> ValueType { + match self { + Value::I32(_) => ValueType::I32, + Value::I64(_) => ValueType::I64, + Value::F32(_) => ValueType::F32, + Value::F64(_) => ValueType::F64, + } + } + + /// Return `Self` as `i32`. + pub fn as_i32(&self) -> Option { + match self { + Self::I32(val) => Some(*val), + _ => None, + } + } +} + +/// Something that can be converted into a wasm compatible `Value`. +pub trait IntoValue { + /// The type of the value in wasm. + const VALUE_TYPE: ValueType; + + /// Convert `self` into a wasm `Value`. + fn into_value(self) -> Value; +} + +/// Something that can may be created from a wasm `Value`. +pub trait TryFromValue: Sized { + /// Try to convert the given `Value` into `Self`. + fn try_from_value(val: Value) -> Option; +} + +macro_rules! impl_into_and_from_value { + ( + $( + $type:ty, $( < $gen:ident >, )? $value_variant:ident, + )* + ) => { + $( + impl $( <$gen> )? IntoValue for $type { + const VALUE_TYPE: ValueType = ValueType::$value_variant; + fn into_value(self) -> Value { Value::$value_variant(self as _) } + } + + impl $( <$gen> )? TryFromValue for $type { + fn try_from_value(val: Value) -> Option { + match val { + Value::$value_variant(val) => Some(val as _), + _ => None, + } + } + } + )* + } +} + +impl_into_and_from_value! { + u8, I32, + u16, I32, + u32, I32, + u64, I64, + i8, I32, + i16, I32, + i32, I32, + i64, I64, +} + +/// Provides `Sealed` trait to prevent implementing trait `PointerType` and `WasmTy` outside of this +/// crate. +mod private { + pub trait Sealed {} + + impl Sealed for u8 {} + impl Sealed for u16 {} + impl Sealed for u32 {} + impl Sealed for u64 {} + + impl Sealed for i32 {} + impl Sealed for i64 {} +} + +/// Something that can be wrapped in a wasm `Pointer`. +/// +/// This trait is sealed. +pub trait PointerType: Sized + private::Sealed { + /// The size of the type in wasm. + const SIZE: u32 = mem::size_of::() as u32; +} + +impl PointerType for u8 {} +impl PointerType for u16 {} +impl PointerType for u32 {} +impl PointerType for u64 {} + +/// Type to represent a pointer in wasm at the host. +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct Pointer { + ptr: u32, + _marker: PhantomData, +} + +impl Pointer { + /// Create a new instance of `Self`. + pub fn new(ptr: u32) -> Self { + Self { ptr, _marker: Default::default() } + } + + /// Calculate the offset from this pointer. + /// + /// `offset` is in units of `T`. So, `3` means `3 * mem::size_of::()` as offset to the + /// pointer. + /// + /// Returns an `Option` to respect that the pointer could probably overflow. + pub fn offset(self, offset: u32) -> Option { + offset + .checked_mul(T::SIZE) + .and_then(|o| self.ptr.checked_add(o)) + .map(|ptr| Self { ptr, _marker: Default::default() }) + } + + /// Create a null pointer. + pub fn null() -> Self { + Self::new(0) + } + + /// Cast this pointer of type `T` to a pointer of type `R`. + pub fn cast(self) -> Pointer { + Pointer::new(self.ptr) + } +} + +impl From for Pointer { + fn from(ptr: u32) -> Self { + Pointer::new(ptr) + } +} + +impl From> for u32 { + fn from(ptr: Pointer) -> Self { + ptr.ptr + } +} + +impl From> for u64 { + fn from(ptr: Pointer) -> Self { + u64::from(ptr.ptr) + } +} + +impl From> for usize { + fn from(ptr: Pointer) -> Self { + ptr.ptr as _ + } +} + +// trait implementations for Pointer. +impl IntoValue for Pointer { + const VALUE_TYPE: ValueType = ValueType::I32; + fn into_value(self) -> Value { + Value::I32(self.ptr as _) + } +} + +impl TryFromValue for Pointer { + fn try_from_value(val: Value) -> Option { + match val { + Value::I32(val) => Some(Self::new(val as _)), + _ => None, + } + } +} + +/// The Signature of a function +#[derive(Eq, PartialEq, Debug, Clone)] +pub struct Signature { + /// The arguments of a function. + pub args: Cow<'static, [ValueType]>, + /// The optional return value of a function. + pub return_value: Option, +} + +impl Signature { + /// Create a new instance of `Signature`. + pub fn new>>( + args: T, + return_value: Option, + ) -> Self { + Self { args: args.into(), return_value } + } + + /// Create a new instance of `Signature` with the given `args` and without any return value. + pub fn new_with_args>>(args: T) -> Self { + Self { args: args.into(), return_value: None } + } +} + +/// The word size used in wasm. Normally known as `usize` in Rust. +pub type WordSize = u32; + +/// Sandbox memory identifier. +pub type MemoryId = u32; + +/// Host pointer: suit both for 32-bit and 64-bit archs. +pub type HostPointer = u64; + +/// Typed value that can be returned from a function. +/// +/// Basically a `TypedValue` plus `Unit`, for functions which return nothing. +#[derive(Clone, Copy, PartialEq, codec::Encode, codec::Decode, Debug)] +pub enum ReturnValue { + /// For returning nothing. + Unit, + /// For returning some concrete value. + Value(Value), +} + +impl From for ReturnValue { + fn from(v: Value) -> ReturnValue { + ReturnValue::Value(v) + } +} + +impl ReturnValue { + /// Maximum number of bytes `ReturnValue` might occupy when serialized with `SCALE`. + /// + /// Breakdown: + /// 1 byte for encoding unit/value variant + /// 1 byte for encoding value type + /// 8 bytes for encoding the biggest value types available in wasm: f64, i64. + pub const ENCODED_MAX_SIZE: usize = 10; +} + +#[cfg(test)] +mod tests { + use super::*; + use codec::Encode; + + #[test] + fn pointer_offset_works() { + let ptr = Pointer::::null(); + + assert_eq!(ptr.offset(10).unwrap(), Pointer::new(40)); + assert_eq!(ptr.offset(32).unwrap(), Pointer::new(128)); + + let ptr = Pointer::::null(); + + assert_eq!(ptr.offset(10).unwrap(), Pointer::new(80)); + assert_eq!(ptr.offset(32).unwrap(), Pointer::new(256)); + } + + #[test] + fn return_value_encoded_max_size() { + let encoded = ReturnValue::Value(Value::I64(-1)).encode(); + assert_eq!(encoded.len(), ReturnValue::ENCODED_MAX_SIZE); + } +} diff --git a/substrate/primitives/wasm-interface-common/src/util.rs b/substrate/primitives/wasm-interface-common/src/util.rs new file mode 100644 index 000000000000..2b4ebd6e6651 --- /dev/null +++ b/substrate/primitives/wasm-interface-common/src/util.rs @@ -0,0 +1,26 @@ +// This file is part of Gear. +// +// Copyright (C) 2021-2023 Gear Technologies Inc. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 +// +// This program 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. +// +// This program 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 this program. If not, see . + +use core::ops::Range; + +/// Construct a range from an offset to a data length after the offset. +/// Returns None if the end of the range would exceed some maximum offset. +pub fn checked_range(offset: usize, len: usize, max: usize) -> Option> { + let end = offset.checked_add(len)?; + (end <= max).then(|| offset..end) +} diff --git a/substrate/primitives/wasm-interface-common/src/wasmi_impl.rs b/substrate/primitives/wasm-interface-common/src/wasmi_impl.rs new file mode 100644 index 000000000000..7394e3455130 --- /dev/null +++ b/substrate/primitives/wasm-interface-common/src/wasmi_impl.rs @@ -0,0 +1,80 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Implementation of conversions between Substrate and wasmi types. +use crate::{Signature, Value, ValueType}; +use sp_std::vec::Vec; + +impl From for wasmi::RuntimeValue { + fn from(value: Value) -> Self { + match value { + Value::I32(val) => Self::I32(val), + Value::I64(val) => Self::I64(val), + Value::F32(val) => Self::F32(val.into()), + Value::F64(val) => Self::F64(val.into()), + } + } +} + +impl From for Value { + fn from(value: wasmi::RuntimeValue) -> Self { + match value { + wasmi::RuntimeValue::I32(val) => Self::I32(val), + wasmi::RuntimeValue::I64(val) => Self::I64(val), + wasmi::RuntimeValue::F32(val) => Self::F32(val.into()), + wasmi::RuntimeValue::F64(val) => Self::F64(val.into()), + } + } +} + +impl From for wasmi::ValueType { + fn from(value: ValueType) -> Self { + match value { + ValueType::I32 => Self::I32, + ValueType::I64 => Self::I64, + ValueType::F32 => Self::F32, + ValueType::F64 => Self::F64, + } + } +} + +impl From for ValueType { + fn from(value: wasmi::ValueType) -> Self { + match value { + wasmi::ValueType::I32 => Self::I32, + wasmi::ValueType::I64 => Self::I64, + wasmi::ValueType::F32 => Self::F32, + wasmi::ValueType::F64 => Self::F64, + } + } +} + +impl From for wasmi::Signature { + fn from(sig: Signature) -> Self { + let args = sig.args.iter().map(|a| (*a).into()).collect::>(); + wasmi::Signature::new(args, sig.return_value.map(Into::into)) + } +} + +impl From<&wasmi::Signature> for Signature { + fn from(sig: &wasmi::Signature) -> Self { + Signature::new( + sig.params().iter().copied().map(Into::into).collect::>(), + sig.return_type().map(Into::into), + ) + } +} diff --git a/substrate/primitives/wasm-interface/Cargo.toml b/substrate/primitives/wasm-interface/Cargo.toml index c7413fec43c4..4f305268ac08 100644 --- a/substrate/primitives/wasm-interface/Cargo.toml +++ b/substrate/primitives/wasm-interface/Cargo.toml @@ -20,8 +20,11 @@ log = { version = "0.4.17", optional = true } wasmtime = { version = "8.0.1", default-features = false, optional = true } anyhow = { version = "1.0.68", optional = true } sp-std = { path = "../std", default-features = false} +sp-wasm-interface-common = { version = "7.0.0", path = "../wasm-interface-common", default-features = false } +sp-allocator = { version = "4.1.0-dev", path = "../allocator", default-features = false } [features] default = [ "std" ] -std = [ "codec/std", "log/std", "sp-std/std", "wasmtime" ] +std = ["codec/std", "log/std", "sp-allocator/std", "sp-std/std", "wasmtime"] wasmtime = [ "anyhow", "dep:wasmtime" ] +wasmi = [ "sp-wasm-interface-common/wasmi" ] diff --git a/substrate/primitives/wasm-interface/lib.rs b/substrate/primitives/wasm-interface/lib.rs new file mode 100644 index 000000000000..b6e85b5894da --- /dev/null +++ b/substrate/primitives/wasm-interface/lib.rs @@ -0,0 +1,385 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Types and traits for interfacing between the host and the wasm runtime. + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::{iter::Iterator, marker::PhantomData, result, vec, vec::Vec}; +pub use sp_wasm_interface_common::{ + self as common, HostPointer, IntoValue, MemoryId, Pointer, PointerType, ReturnValue, Signature, + TryFromValue, Value, ValueType, WordSize, +}; + +if_wasmtime_is_enabled! { + mod host_state; + pub use host_state::HostState; + + mod store_data; + pub use store_data::StoreData; + + mod memory_wrapper; + pub use memory_wrapper::MemoryWrapper; + + pub mod util; +} + +#[cfg(not(all(feature = "std", feature = "wasmtime")))] +pub struct StoreData; + +#[cfg(not(all(feature = "std", feature = "wasmtime")))] +#[macro_export] +macro_rules! if_wasmtime_is_enabled { + ($($token:tt)*) => {}; +} + +#[cfg(all(feature = "std", feature = "wasmtime"))] +#[macro_export] +macro_rules! if_wasmtime_is_enabled { + ($($token:tt)*) => { + $($token)* + } +} + +if_wasmtime_is_enabled! { + // Reexport wasmtime so that its types are accessible from the procedural macro. + pub use wasmtime; + + // Wasmtime uses anyhow types but doesn't reexport them. + pub use anyhow; +} + +/// Result type used by traits in this crate. +#[cfg(feature = "std")] +pub type Result = result::Result; +#[cfg(not(feature = "std"))] +pub type Result = result::Result; + +/// Provides `Sealed` trait to prevent implementing trait `PointerType` and `WasmTy` outside of this +/// crate. +mod private { + pub trait Sealed {} + + impl Sealed for u8 {} + impl Sealed for u16 {} + impl Sealed for u32 {} + impl Sealed for u64 {} + + impl Sealed for i32 {} + impl Sealed for i64 {} + + pub(super) struct Token; +} + +/// A trait that requires `RefUnwindSafe` when `feature = std`. +#[cfg(feature = "std")] +pub trait MaybeRefUnwindSafe: std::panic::RefUnwindSafe {} +#[cfg(feature = "std")] +impl MaybeRefUnwindSafe for T {} + +/// A trait that requires `RefUnwindSafe` when `feature = std`. +#[cfg(not(feature = "std"))] +pub trait MaybeRefUnwindSafe {} +#[cfg(not(feature = "std"))] +impl MaybeRefUnwindSafe for T {} + +/// Something that provides a function implementation on the host for a wasm function. +pub trait Function: MaybeRefUnwindSafe + Send + Sync { + /// Returns the name of this function. + fn name(&self) -> &str; + /// Returns the signature of this function. + fn signature(&self) -> Signature; + /// Execute this function with the given arguments. + fn execute( + &self, + context: &mut dyn FunctionContext, + args: &mut dyn Iterator, + ) -> Result>; +} + +impl PartialEq for dyn Function { + fn eq(&self, other: &Self) -> bool { + other.name() == self.name() && other.signature() == self.signature() + } +} + +#[cfg(not(all(feature = "std", feature = "wasmtime")))] +pub struct Caller<'a, T>(PhantomData<&'a T>); + +#[cfg(all(feature = "std", feature = "wasmtime"))] +pub use wasmtime::Caller; + +pub struct FunctionContextToken(private::Token); + +impl FunctionContextToken { + fn new() -> Self { + Self(private::Token) + } +} + +/// Context used by `Function` to interact with the allocator and the memory of the wasm instance. +pub trait FunctionContext { + /// Read memory from `address` into a vector. + fn read_memory(&self, address: Pointer, size: WordSize) -> Result> { + let mut vec = vec![0; size as usize]; + self.read_memory_into(address, &mut vec)?; + Ok(vec) + } + /// Read memory into the given `dest` buffer from `address`. + fn read_memory_into(&self, address: Pointer, dest: &mut [u8]) -> Result<()>; + /// Write the given data at `address` into the memory. + fn write_memory(&mut self, address: Pointer, data: &[u8]) -> Result<()>; + /// Allocate a memory instance of `size` bytes. + fn allocate_memory(&mut self, size: WordSize) -> Result>; + /// Deallocate a given memory instance. + fn deallocate_memory(&mut self, ptr: Pointer) -> Result<()>; + /// Registers a panic error message within the executor. + /// + /// This is meant to be used in situations where the runtime + /// encounters an unrecoverable error and intends to panic. + /// + /// Panicking in WASM is done through the [`unreachable`](https://webassembly.github.io/spec/core/syntax/instructions.html#syntax-instr-control) + /// instruction which causes an unconditional trap and immediately aborts + /// the execution. It does not however allow for any diagnostics to be + /// passed through to the host, so while we do know that *something* went + /// wrong we don't have any direct indication of what *exactly* went wrong. + /// + /// As a workaround we use this method right before the execution is + /// actually aborted to pass an error message to the host so that it + /// can associate it with the next trap, and return that to the caller. + /// + /// A WASM trap should be triggered immediately after calling this method; + /// otherwise the error message might be associated with a completely + /// unrelated trap. + /// + /// It should only be called once, however calling it more than once + /// is harmless and will overwrite the previously set error message. + fn register_panic_error_message(&mut self, message: &str); + + fn with_caller_mut_impl( + &mut self, + _: FunctionContextToken, + context: *mut (), + callback: fn(*mut (), &mut Caller), + ); +} + +pub fn with_caller_mut)>( + context: &mut dyn FunctionContext, + mut callback: T, +) { + let callback: *mut T = &mut callback; + context.with_caller_mut_impl(FunctionContextToken::new(), callback.cast(), |callback, caller| { + let callback: *mut T = callback.cast(); + let callback: &mut T = unsafe { callback.as_mut().expect("we own the value, obtain mutable reference to it and cast to pointer (correct (not null) and aligned properly); qed") }; + + callback(caller); + }) +} + +if_wasmtime_is_enabled! { + /// A trait used to statically register host callbacks with the WASM executor, + /// so that they call be called from within the runtime with minimal overhead. + /// + /// This is used internally to interface the wasmtime-based executor with the + /// host functions' definitions generated through the runtime interface macro, + /// and is not meant to be used directly. + pub trait HostFunctionRegistry { + type State; + type Error; + type FunctionContext: FunctionContext; + + /// Wraps the given `caller` in a type which implements `FunctionContext` + /// and calls the given `callback`. + fn with_function_context( + caller: wasmtime::Caller, + callback: impl FnOnce(&mut dyn FunctionContext) -> R, + ) -> R; + + /// Registers a given host function with the WASM executor. + /// + /// The function has to be statically callable, and all of its arguments + /// and its return value have to be compatible with WASM FFI. + fn register_static( + &mut self, + fn_name: &str, + func: impl wasmtime::IntoFunc + 'static, + ) -> core::result::Result<(), Self::Error>; + } +} + +/// Something that provides implementations for host functions. +pub trait HostFunctions: 'static + Send + Sync { + /// Returns the host functions `Self` provides. + fn host_functions() -> Vec<&'static dyn Function>; + + if_wasmtime_is_enabled! { + /// Statically registers the host functions. + fn register_static(registry: &mut T) -> core::result::Result<(), T::Error> + where + T: HostFunctionRegistry; + } +} + +#[impl_trait_for_tuples::impl_for_tuples(30)] +impl HostFunctions for Tuple { + fn host_functions() -> Vec<&'static dyn Function> { + let mut host_functions = Vec::new(); + + for_tuples!( #( host_functions.extend(Tuple::host_functions()); )* ); + + host_functions + } + + #[cfg(all(feature = "std", feature = "wasmtime"))] + fn register_static(registry: &mut T) -> core::result::Result<(), T::Error> + where + T: HostFunctionRegistry, + { + for_tuples!( + #( Tuple::register_static(registry)?; )* + ); + + Ok(()) + } +} + +/// A wrapper which merges two sets of host functions, and allows the second set to override +/// the host functions from the first set. +pub struct ExtendedHostFunctions { + phantom: PhantomData<(Base, Overlay)>, +} + +impl HostFunctions for ExtendedHostFunctions +where + Base: HostFunctions, + Overlay: HostFunctions, +{ + fn host_functions() -> Vec<&'static dyn Function> { + let mut base = Base::host_functions(); + let overlay = Overlay::host_functions(); + base.retain(|host_fn| { + !overlay.iter().any(|ext_host_fn| host_fn.name() == ext_host_fn.name()) + }); + base.extend(overlay); + base + } + + if_wasmtime_is_enabled! { + fn register_static(registry: &mut T) -> core::result::Result<(), T::Error> + where + T: HostFunctionRegistry, + { + struct Proxy<'a, T> { + registry: &'a mut T, + seen_overlay: std::collections::HashSet, + seen_base: std::collections::HashSet, + overlay_registered: bool, + } + + impl<'a, T> HostFunctionRegistry for Proxy<'a, T> + where + T: HostFunctionRegistry, + { + type State = T::State; + type Error = T::Error; + type FunctionContext = T::FunctionContext; + + fn with_function_context( + caller: wasmtime::Caller, + callback: impl FnOnce(&mut dyn FunctionContext) -> R, + ) -> R { + T::with_function_context(caller, callback) + } + + fn register_static( + &mut self, + fn_name: &str, + func: impl wasmtime::IntoFunc + 'static, + ) -> core::result::Result<(), Self::Error> { + if self.overlay_registered { + if !self.seen_base.insert(fn_name.to_owned()) { + log::warn!( + target: "extended_host_functions", + "Duplicate base host function: '{}'", + fn_name, + ); + + // TODO: Return an error here? + return Ok(()) + } + + if self.seen_overlay.contains(fn_name) { + // Was already registered when we went through the overlay, so just ignore it. + log::debug!( + target: "extended_host_functions", + "Overriding base host function: '{}'", + fn_name, + ); + + return Ok(()) + } + } else if !self.seen_overlay.insert(fn_name.to_owned()) { + log::warn!( + target: "extended_host_functions", + "Duplicate overlay host function: '{}'", + fn_name, + ); + + // TODO: Return an error here? + return Ok(()) + } + + self.registry.register_static(fn_name, func) + } + } + + let mut proxy = Proxy { + registry, + seen_overlay: Default::default(), + seen_base: Default::default(), + overlay_registered: false, + }; + + // The functions from the `Overlay` can override those from the `Base`, + // so `Overlay` is registered first, and then we skip those functions + // in `Base` if they were already registered from the `Overlay`. + Overlay::register_static(&mut proxy)?; + proxy.overlay_registered = true; + Base::register_static(&mut proxy)?; + + Ok(()) + } + } +} + +/// A trait for types directly usable at the WASM FFI boundary without any conversion at all. +/// +/// This trait is sealed and should not be implemented downstream. +#[cfg(all(feature = "std", feature = "wasmtime"))] +pub trait WasmTy: wasmtime::WasmTy + private::Sealed {} + +/// A trait for types directly usable at the WASM FFI boundary without any conversion at all. +/// +/// This trait is sealed and should not be implemented downstream. +#[cfg(not(all(feature = "std", feature = "wasmtime")))] +pub trait WasmTy: private::Sealed {} + +impl WasmTy for i32 {} +impl WasmTy for u32 {} +impl WasmTy for i64 {} +impl WasmTy for u64 {} diff --git a/substrate/primitives/wasm-interface/src/host_state.rs b/substrate/primitives/wasm-interface/src/host_state.rs new file mode 100644 index 000000000000..440c9271dbf1 --- /dev/null +++ b/substrate/primitives/wasm-interface/src/host_state.rs @@ -0,0 +1,52 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! This module defines `HostState` struct which provide logic and state +//! required for execution of host. + +use sp_allocator::{AllocationStats, FreeingBumpHeapAllocator}; + +/// The state required to construct a HostContext context. The context only lasts for one host +/// call, whereas the state is maintained for the duration of a Wasm runtime call, which may make +/// many different host calls that must share state. +pub struct HostState { + /// The allocator instance to keep track of allocated memory. + /// + /// This is stored as an `Option` as we need to temporarly set this to `None` when we are + /// allocating/deallocating memory. The problem being that we can only mutable access `caller` + /// once. + pub allocator: Option, + pub panic_message: Option, +} + +impl HostState { + /// Constructs a new `HostState`. + pub fn new(allocator: FreeingBumpHeapAllocator) -> Self { + HostState { allocator: Some(allocator), panic_message: None } + } + + /// Takes the error message out of the host state, leaving a `None` in its place. + pub fn take_panic_message(&mut self) -> Option { + self.panic_message.take() + } + + pub fn allocation_stats(&self) -> AllocationStats { + self.allocator.as_ref() + .expect("Allocator is always set and only unavailable when doing an allocation/deallocation; qed") + .stats() + } +} diff --git a/substrate/primitives/wasm-interface/src/lib.rs b/substrate/primitives/wasm-interface/src/lib.rs index 9d5d2bb358d5..f70ccc934c0f 100644 --- a/substrate/primitives/wasm-interface/src/lib.rs +++ b/substrate/primitives/wasm-interface/src/lib.rs @@ -19,7 +19,24 @@ #![cfg_attr(not(feature = "std"), no_std)] -use sp_std::{borrow::Cow, iter::Iterator, marker::PhantomData, mem, result, vec, vec::Vec}; +use sp_std::{iter::Iterator, marker::PhantomData, result, vec, vec::Vec}; +pub use sp_wasm_interface_common::{self as common, Value, ValueType, Pointer, PointerType, IntoValue, TryFromValue, ReturnValue, WordSize, MemoryId, HostPointer, Signature}; + +if_wasmtime_is_enabled! { + mod host_state; + pub use host_state::HostState; + + mod store_data; + pub use store_data::StoreData; + + mod memory_wrapper; + pub use memory_wrapper::MemoryWrapper; + + pub mod util; +} + +#[cfg(not(all(feature = "std", feature = "wasmtime")))] +pub struct StoreData; #[cfg(not(all(feature = "std", feature = "wasmtime")))] #[macro_export] @@ -49,81 +66,6 @@ pub type Result = result::Result; #[cfg(not(feature = "std"))] pub type Result = result::Result; -/// Value types supported by Substrate on the boundary between host/Wasm. -#[derive(Copy, Clone, PartialEq, Debug, Eq)] -pub enum ValueType { - /// An `i32` value type. - I32, - /// An `i64` value type. - I64, - /// An `f32` value type. - F32, - /// An `f64` value type. - F64, -} - -impl From for u8 { - fn from(val: ValueType) -> u8 { - match val { - ValueType::I32 => 0, - ValueType::I64 => 1, - ValueType::F32 => 2, - ValueType::F64 => 3, - } - } -} - -impl TryFrom for ValueType { - type Error = (); - - fn try_from(val: u8) -> sp_std::result::Result { - match val { - 0 => Ok(Self::I32), - 1 => Ok(Self::I64), - 2 => Ok(Self::F32), - 3 => Ok(Self::F64), - _ => Err(()), - } - } -} - -/// Values supported by Substrate on the boundary between host/Wasm. -#[derive(PartialEq, Debug, Clone, Copy, codec::Encode, codec::Decode)] -pub enum Value { - /// A 32-bit integer. - I32(i32), - /// A 64-bit integer. - I64(i64), - /// A 32-bit floating-point number stored as raw bit pattern. - /// - /// You can materialize this value using `f32::from_bits`. - F32(u32), - /// A 64-bit floating-point number stored as raw bit pattern. - /// - /// You can materialize this value using `f64::from_bits`. - F64(u64), -} - -impl Value { - /// Returns the type of this value. - pub fn value_type(&self) -> ValueType { - match self { - Value::I32(_) => ValueType::I32, - Value::I64(_) => ValueType::I64, - Value::F32(_) => ValueType::F32, - Value::F64(_) => ValueType::F64, - } - } - - /// Return `Self` as `i32`. - pub fn as_i32(&self) -> Option { - match self { - Self::I32(val) => Some(*val), - _ => None, - } - } -} - /// Provides `Sealed` trait to prevent implementing trait `PointerType` and `WasmTy` outside of this /// crate. mod private { @@ -136,123 +78,8 @@ mod private { impl Sealed for i32 {} impl Sealed for i64 {} -} - -/// Something that can be wrapped in a wasm `Pointer`. -/// -/// This trait is sealed. -pub trait PointerType: Sized + private::Sealed { - /// The size of the type in wasm. - const SIZE: u32 = mem::size_of::() as u32; -} - -impl PointerType for u8 {} -impl PointerType for u16 {} -impl PointerType for u32 {} -impl PointerType for u64 {} - -/// Type to represent a pointer in wasm at the host. -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub struct Pointer { - ptr: u32, - _marker: PhantomData, -} - -impl Pointer { - /// Create a new instance of `Self`. - pub fn new(ptr: u32) -> Self { - Self { ptr, _marker: Default::default() } - } - - /// Calculate the offset from this pointer. - /// - /// `offset` is in units of `T`. So, `3` means `3 * mem::size_of::()` as offset to the - /// pointer. - /// - /// Returns an `Option` to respect that the pointer could probably overflow. - pub fn offset(self, offset: u32) -> Option { - offset - .checked_mul(T::SIZE) - .and_then(|o| self.ptr.checked_add(o)) - .map(|ptr| Self { ptr, _marker: Default::default() }) - } - - /// Create a null pointer. - pub fn null() -> Self { - Self::new(0) - } - /// Cast this pointer of type `T` to a pointer of type `R`. - pub fn cast(self) -> Pointer { - Pointer::new(self.ptr) - } -} - -impl From for Pointer { - fn from(ptr: u32) -> Self { - Pointer::new(ptr) - } -} - -impl From> for u32 { - fn from(ptr: Pointer) -> Self { - ptr.ptr - } -} - -impl From> for u64 { - fn from(ptr: Pointer) -> Self { - u64::from(ptr.ptr) - } -} - -impl From> for usize { - fn from(ptr: Pointer) -> Self { - ptr.ptr as _ - } -} - -impl IntoValue for Pointer { - const VALUE_TYPE: ValueType = ValueType::I32; - fn into_value(self) -> Value { - Value::I32(self.ptr as _) - } -} - -impl TryFromValue for Pointer { - fn try_from_value(val: Value) -> Option { - match val { - Value::I32(val) => Some(Self::new(val as _)), - _ => None, - } - } -} - -/// The word size used in wasm. Normally known as `usize` in Rust. -pub type WordSize = u32; - -/// The Signature of a function -#[derive(Eq, PartialEq, Debug, Clone)] -pub struct Signature { - /// The arguments of a function. - pub args: Cow<'static, [ValueType]>, - /// The optional return value of a function. - pub return_value: Option, -} - -impl Signature { - /// Create a new instance of `Signature`. - pub fn new>>( - args: T, - return_value: Option, - ) -> Self { - Self { args: args.into(), return_value } - } - - /// Create a new instance of `Signature` with the given `args` and without any return value. - pub fn new_with_args>>(args: T) -> Self { - Self { args: args.into(), return_value: None } - } + pub(super) struct Token; } /// A trait that requires `RefUnwindSafe` when `feature = std`. @@ -287,6 +114,20 @@ impl PartialEq for dyn Function { } } +#[cfg(not(all(feature = "std", feature = "wasmtime")))] +pub struct Caller<'a, T>(PhantomData<&'a T>); + +#[cfg(all(feature = "std", feature = "wasmtime"))] +pub use wasmtime::Caller; + +pub struct FunctionContextToken(private::Token); + +impl FunctionContextToken { + fn new() -> Self { + Self(private::Token) + } +} + /// Context used by `Function` to interact with the allocator and the memory of the wasm instance. pub trait FunctionContext { /// Read memory from `address` into a vector. @@ -325,6 +166,19 @@ pub trait FunctionContext { /// It should only be called once, however calling it more than once /// is harmless and will overwrite the previously set error message. fn register_panic_error_message(&mut self, message: &str); + + fn with_caller_mut_impl(&mut self, _: FunctionContextToken, context: *mut (), callback: fn(*mut (), &mut Caller)); + +} + +pub fn with_caller_mut)>(context: &mut dyn FunctionContext, mut callback: T) { + let callback: *mut T = &mut callback; + context.with_caller_mut_impl(FunctionContextToken::new(), callback.cast(), |callback, caller| { + let callback: *mut T = callback.cast(); + let callback: &mut T = unsafe { callback.as_mut().expect("we own the value, obtain mutable reference to it and cast to pointer (correct (not null) and aligned properly); qed") }; + + callback(caller); + }) } if_wasmtime_is_enabled! { @@ -519,105 +373,3 @@ impl WasmTy for i32 {} impl WasmTy for u32 {} impl WasmTy for i64 {} impl WasmTy for u64 {} - -/// Something that can be converted into a wasm compatible `Value`. -pub trait IntoValue { - /// The type of the value in wasm. - const VALUE_TYPE: ValueType; - - /// Convert `self` into a wasm `Value`. - fn into_value(self) -> Value; -} - -/// Something that can may be created from a wasm `Value`. -pub trait TryFromValue: Sized { - /// Try to convert the given `Value` into `Self`. - fn try_from_value(val: Value) -> Option; -} - -macro_rules! impl_into_and_from_value { - ( - $( - $type:ty, $( < $gen:ident >, )? $value_variant:ident, - )* - ) => { - $( - impl $( <$gen> )? IntoValue for $type { - const VALUE_TYPE: ValueType = ValueType::$value_variant; - fn into_value(self) -> Value { Value::$value_variant(self as _) } - } - - impl $( <$gen> )? TryFromValue for $type { - fn try_from_value(val: Value) -> Option { - match val { - Value::$value_variant(val) => Some(val as _), - _ => None, - } - } - } - )* - } -} - -impl_into_and_from_value! { - u8, I32, - u16, I32, - u32, I32, - u64, I64, - i8, I32, - i16, I32, - i32, I32, - i64, I64, -} - -/// Typed value that can be returned from a function. -/// -/// Basically a `TypedValue` plus `Unit`, for functions which return nothing. -#[derive(Clone, Copy, PartialEq, codec::Encode, codec::Decode, Debug)] -pub enum ReturnValue { - /// For returning nothing. - Unit, - /// For returning some concrete value. - Value(Value), -} - -impl From for ReturnValue { - fn from(v: Value) -> ReturnValue { - ReturnValue::Value(v) - } -} - -impl ReturnValue { - /// Maximum number of bytes `ReturnValue` might occupy when serialized with `SCALE`. - /// - /// Breakdown: - /// 1 byte for encoding unit/value variant - /// 1 byte for encoding value type - /// 8 bytes for encoding the biggest value types available in wasm: f64, i64. - pub const ENCODED_MAX_SIZE: usize = 10; -} - -#[cfg(test)] -mod tests { - use super::*; - use codec::Encode; - - #[test] - fn pointer_offset_works() { - let ptr = Pointer::::null(); - - assert_eq!(ptr.offset(10).unwrap(), Pointer::new(40)); - assert_eq!(ptr.offset(32).unwrap(), Pointer::new(128)); - - let ptr = Pointer::::null(); - - assert_eq!(ptr.offset(10).unwrap(), Pointer::new(80)); - assert_eq!(ptr.offset(32).unwrap(), Pointer::new(256)); - } - - #[test] - fn return_value_encoded_max_size() { - let encoded = ReturnValue::Value(Value::I64(-1)).encode(); - assert_eq!(encoded.len(), ReturnValue::ENCODED_MAX_SIZE); - } -} diff --git a/substrate/primitives/wasm-interface/src/memory_wrapper.rs b/substrate/primitives/wasm-interface/src/memory_wrapper.rs new file mode 100644 index 000000000000..5a3960f6ded3 --- /dev/null +++ b/substrate/primitives/wasm-interface/src/memory_wrapper.rs @@ -0,0 +1,56 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/// Wrapper around [`Memory`] that implements [`sp_allocator::Memory`]. +pub struct MemoryWrapper<'a, C>(&'a wasmtime::Memory, &'a mut C); + +impl<'a, C> From<(&'a wasmtime::Memory, &'a mut C)> for MemoryWrapper<'a, C> { + fn from((memory, caller): (&'a wasmtime::Memory, &'a mut C)) -> Self { + Self(memory, caller) + } +} + +impl sp_allocator::Memory for MemoryWrapper<'_, C> { + fn with_access(&self, run: impl FnOnce(&[u8]) -> R) -> R { + run(self.0.data(&self.1)) + } + + fn with_access_mut(&mut self, run: impl FnOnce(&mut [u8]) -> R) -> R { + run(self.0.data_mut(&mut self.1)) + } + + fn grow(&mut self, additional: u32) -> std::result::Result<(), ()> { + self.0 + .grow(&mut self.1, additional as u64) + .map_err(|e| { + log::error!( + "Failed to grow memory by {} pages: {}", + additional, + e, + ) + }) + .map(drop) + } + + fn pages(&self) -> u32 { + self.0.size(&self.1) as u32 + } + + fn max_pages(&self) -> Option { + self.0.ty(&self.1).maximum().map(|p| p as _) + } +} diff --git a/substrate/primitives/wasm-interface/src/store_data.rs b/substrate/primitives/wasm-interface/src/store_data.rs new file mode 100644 index 000000000000..570429f21e75 --- /dev/null +++ b/substrate/primitives/wasm-interface/src/store_data.rs @@ -0,0 +1,24 @@ +use crate::HostState; +use wasmtime::{Memory, Table}; + +#[derive(Default)] +pub struct StoreData { + /// This will only be set when we call into the runtime. + pub host_state: Option, + /// This will be always set once the store is initialized. + pub memory: Option, + /// This will be set only if the runtime actually contains a table. + pub table: Option
, +} + +impl StoreData { + /// Returns a mutable reference to the host state. + pub fn host_state_mut(&mut self) -> Option<&mut HostState> { + self.host_state.as_mut() + } + + /// Returns the host memory. + pub fn memory(&self) -> Memory { + self.memory.expect("memory is always set; qed") + } +} diff --git a/substrate/primitives/wasm-interface/src/util.rs b/substrate/primitives/wasm-interface/src/util.rs new file mode 100644 index 000000000000..72969b0c716c --- /dev/null +++ b/substrate/primitives/wasm-interface/src/util.rs @@ -0,0 +1,100 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use super::*; +use wasmtime::{AsContext, AsContextMut}; +pub use sp_wasm_interface_common::util::checked_range; + +pub fn write_memory_from( + mut ctx: impl AsContextMut, + address: Pointer, + data: &[u8], +) -> Result<()> { + let memory = ctx.as_context().data().memory(); + let memory = memory.data_mut(&mut ctx); + + let range = checked_range(address.into(), data.len(), memory.len()) + .ok_or_else(|| String::from("memory write is out of bounds"))?; + memory[range].copy_from_slice(data); + Ok(()) +} + +pub fn read_memory_into( + ctx: impl AsContext, + address: Pointer, + dest: &mut [u8], +) -> Result<()> { + let memory = ctx.as_context().data().memory().data(&ctx); + + let range = checked_range(address.into(), dest.len(), memory.len()) + .ok_or_else(|| String::from("memory read is out of bounds"))?; + dest.copy_from_slice(&memory[range]); + Ok(()) +} + +pub fn read_memory( + ctx: impl AsContext, + address: Pointer, + size: WordSize, +) -> Result> { + let mut vec = vec![0; size as usize]; + read_memory_into(ctx, address, &mut vec)?; + Ok(vec) +} + +#[track_caller] +fn host_state_mut<'a>(caller: &'a mut Caller<'_, StoreData>) -> &'a mut HostState { + caller + .data_mut() + .host_state_mut() + .expect("host state is not empty when calling a function in wasm; qed") +} + +pub fn allocate_memory(caller: &mut Caller<'_, StoreData>, size: WordSize) -> Result> { + let mut allocator = host_state_mut(caller) + .allocator + .take() + .expect("allocator is not empty when calling a function in wasm; qed"); + + let memory = caller.data().memory(); + // We can not return on error early, as we need to store back allocator. + let res = allocator + .allocate(&mut MemoryWrapper::from((&memory, &mut caller.as_context_mut())), size) + .map_err(|e| e.to_string()); + + host_state_mut(caller).allocator = Some(allocator); + + res +} + +pub fn deallocate_memory(caller: &mut Caller<'_, StoreData>, ptr: Pointer) -> Result<()> { + let mut allocator = host_state_mut(caller) + .allocator + .take() + .expect("allocator is not empty when calling a function in wasm; qed"); + + let memory = caller.data().memory(); + + // We can not return on error early, as we need to store back allocator. + let res = allocator + .deallocate(&mut MemoryWrapper::from((&memory, &mut caller.as_context_mut())), ptr) + .map_err(|e| e.to_string()); + + host_state_mut(caller).allocator = Some(allocator); + + res +}