diff --git a/Cargo.lock b/Cargo.lock index ec245b66b9..c0df51b5a8 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -66,7 +66,7 @@ version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "once_cell", "version_check", "zerocopy", @@ -98,6 +98,21 @@ dependencies = [ "multiversx-sc-meta-lib", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anstream" version = "0.6.14" @@ -130,9 +145,9 @@ dependencies = [ [[package]] name = "anstyle-query" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" dependencies = [ "windows-sys 0.52.0", ] @@ -182,13 +197,13 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.72" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17c6a35df3749d2e8bb1b7b21a976d82b15548788d2735b9d82f329268f71a11" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ "addr2line", "cc", - "cfg-if", + "cfg-if 1.0.0", "libc", "miniz_oxide", "object", @@ -370,6 +385,12 @@ version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +[[package]] +name = "bytemuck" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78834c15cb5d5efe3452d58b1e8ba890dd62d21907f867f383358198e56ebca5" + [[package]] name = "byteorder" version = "1.5.0" @@ -384,9 +405,15 @@ checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "cc" -version = "1.0.98" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" + +[[package]] +name = "cfg-if" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "cfg-if" @@ -429,11 +456,25 @@ dependencies = [ "multiversx-sc-meta-lib", ] +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets 0.52.5", +] + [[package]] name = "clap" -version = "4.5.4" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" dependencies = [ "clap_builder", "clap_derive", @@ -441,9 +482,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.2" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" dependencies = [ "anstream", "anstyle", @@ -453,9 +494,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.4" +version = "4.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" dependencies = [ "heck", "proc-macro2", @@ -465,9 +506,15 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" + +[[package]] +name = "color_quant" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "colorchoice" @@ -543,6 +590,42 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +[[package]] +name = "core-graphics" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-graphics-types", + "foreign-types 0.5.0", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "libc", +] + +[[package]] +name = "core-text" +version = "20.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9d2790b5c08465d49f8dc05c8bcae9fea467855947db39b0f8145c091aaced5" +dependencies = [ + "core-foundation", + "core-graphics", + "foreign-types 0.5.0", + "libc", +] + [[package]] name = "cpufeatures" version = "0.2.12" @@ -558,7 +641,7 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -664,6 +747,16 @@ dependencies = [ "multiversx-sc-meta-lib", ] +[[package]] +name = "cstr" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68523903c8ae5aacfa32a0d9ae60cadeb764e1da14ee0d26b1f3089f13a54636" +dependencies = [ + "proc-macro2", + "quote", +] + [[package]] name = "curve25519-dalek" version = "3.2.0" @@ -724,6 +817,27 @@ dependencies = [ "multiversx-sc-meta-lib", ] +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if 1.0.0", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "displaydoc" version = "0.2.4" @@ -735,6 +849,27 @@ dependencies = [ "syn", ] +[[package]] +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +dependencies = [ + "libloading", +] + +[[package]] +name = "dwrote" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439a1c2ba5611ad3ed731280541d36d2e9c4ac5e7fb818a27b604bdc5a6aa65b" +dependencies = [ + "lazy_static", + "libc", + "winapi", + "wio", +] + [[package]] name = "ed25519" version = "1.5.3" @@ -787,7 +922,7 @@ version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -1005,6 +1140,15 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +[[package]] +name = "fdeflate" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +dependencies = [ + "simd-adler32", +] + [[package]] name = "first-contract" version = "0.0.0" @@ -1032,19 +1176,71 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "float-ord" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce81f49ae8a0482e4c55ea62ebbd7e5a686af544c00b9d090bba3ff9be97b3d" + [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "font-kit" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2845a73bbd781e691ab7c2a028c579727cd254942e8ced57ff73e0eafd60de87" +dependencies = [ + "bitflags 2.5.0", + "byteorder", + "core-foundation", + "core-graphics", + "core-text", + "dirs-next", + "dwrote", + "float-ord", + "freetype-sys", + "lazy_static", + "libc", + "log", + "pathfinder_geometry", + "pathfinder_simd", + "walkdir", + "winapi", + "yeslogic-fontconfig-sys", +] + [[package]] name = "foreign-types" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" dependencies = [ - "foreign-types-shared", + "foreign-types-shared 0.1.1", +] + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared 0.3.1", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -1053,6 +1249,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -1161,6 +1363,17 @@ dependencies = [ "multiversx-sc-meta-lib", ] +[[package]] +name = "freetype-sys" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7edc5b9669349acfda99533e9e0bcf26a51862ab43b08ee7745c55d28eb134" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + [[package]] name = "futures" version = "0.3.30" @@ -1266,7 +1479,7 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "wasi 0.9.0+wasi-snapshot-preview1", ] @@ -1277,13 +1490,23 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", "wasm-bindgen", ] +[[package]] +name = "gif" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045" +dependencies = [ + "color_quant", + "weezl", +] + [[package]] name = "gimli" version = "0.29.0" @@ -1388,12 +1611,12 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", - "futures-core", + "futures-util", "http", "http-body", "pin-project-lite", @@ -1401,9 +1624,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "humantime" @@ -1431,6 +1654,23 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + [[package]] name = "hyper-tls" version = "0.6.0" @@ -1467,14 +1707,157 @@ dependencies = [ "tracing", ] +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "idna" -version = "0.5.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "icu_normalizer", + "icu_properties", + "smallvec", + "utf8_iter", ] [[package]] @@ -1493,6 +1876,20 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "image" +version = "0.24.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "jpeg-decoder", + "num-traits", + "png", +] + [[package]] name = "indexmap" version = "2.2.6" @@ -1542,6 +1939,12 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "jpeg-decoder" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" + [[package]] name = "js-sys" version = "0.3.69" @@ -1651,6 +2054,26 @@ version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +[[package]] +name = "libloading" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +dependencies = [ + "cfg-if 1.0.0", + "windows-targets 0.52.5", +] + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.5.0", + "libc", +] + [[package]] name = "linked-list-repeat" version = "0.0.0" @@ -1674,6 +2097,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" + [[package]] name = "local-esdt-and-nft" version = "0.0.0" @@ -1781,9 +2210,15 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memory_units" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" [[package]] name = "mime" @@ -1793,11 +2228,12 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", + "simd-adler32", ] [[package]] @@ -2021,7 +2457,6 @@ version = "0.50.3" dependencies = [ "base64", "bech32", - "clap", "colored", "hex", "itertools", @@ -2031,14 +2466,12 @@ dependencies = [ "multiversx-chain-vm-executor", "multiversx-sc", "multiversx-sc-meta-lib", - "multiversx-sdk", "num-bigint", "num-traits", "pathdiff", "serde", "serde_json", "sha2 0.10.8", - "tokio", "unwrap-infallible", ] @@ -2234,9 +2667,9 @@ dependencies = [ [[package]] name = "object" -version = "0.35.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e" +checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" dependencies = [ "memchr", ] @@ -2260,8 +2693,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ "bitflags 2.5.0", - "cfg-if", - "foreign-types", + "cfg-if 1.0.0", + "foreign-types 0.3.2", "libc", "once_cell", "openssl-macros", @@ -2370,7 +2803,7 @@ version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "redox_syscall", "smallvec", @@ -2383,6 +2816,25 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" +[[package]] +name = "pathfinder_geometry" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b7e7b4ea703700ce73ebf128e1450eb69c3a8329199ffbfb9b2a0418e5ad3" +dependencies = [ + "log", + "pathfinder_simd", +] + +[[package]] +name = "pathfinder_simd" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebf45976c56919841273f2a0fc684c28437e2f304e264557d9c72be5d5a718be" +dependencies = [ + "rustc_version", +] + [[package]] name = "payable-features" version = "0.0.0" @@ -2482,6 +2934,77 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +[[package]] +name = "plotters" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3" +dependencies = [ + "chrono", + "font-kit", + "image", + "lazy_static", + "num-traits", + "pathfinder_geometry", + "plotters-backend", + "plotters-bitmap", + "plotters-svg", + "ttf-parser", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7" + +[[package]] +name = "plotters-bitmap" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7e7f6fb8302456d7c264a94dada86f76d76e1a03e2294ee86ca7da92983b0a6" +dependencies = [ + "gif", + "image", + "plotters-backend", +] + +[[package]] +name = "plotters-canvas" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "498a82bf654581fa4df6c1bd73e56f8556bdeec5eca5a0989d170ca0728ccace" +dependencies = [ + "js-sys", + "plotters-backend", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-svg" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81b30686a7d9c3e010b84284bdd26a29f2138574f52f5eb6f794fc0ad924e705" +dependencies = [ + "plotters-backend", +] + +[[package]] +name = "png" +version = "0.17.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -2704,18 +3227,29 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" dependencies = [ "bitflags 2.5.0", ] +[[package]] +name = "redox_users" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +dependencies = [ + "getrandom 0.2.15", + "libredox", + "thiserror", +] + [[package]] name = "regex" -version = "1.10.4" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", @@ -2725,9 +3259,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -2736,15 +3270,15 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "reqwest" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" +checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" dependencies = [ "base64", "bytes", @@ -2757,6 +3291,7 @@ dependencies = [ "http-body", "http-body-util", "hyper", + "hyper-rustls", "hyper-tls", "hyper-util", "ipnet", @@ -2800,6 +3335,21 @@ dependencies = [ "rewards-distribution", ] +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if 1.0.0", + "getrandom 0.2.15", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + [[package]] name = "ruplacer" version = "0.8.2" @@ -2881,6 +3431,19 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.23.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + [[package]] name = "rustls-pemfile" version = "2.1.2" @@ -2897,6 +3460,17 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +[[package]] +name = "rustls-webpki" +version = "0.102.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "ryu" version = "1.0.18" @@ -2912,6 +3486,19 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "sc-plotter-wasm" +version = "0.1.0" +dependencies = [ + "multiversx-sc", + "multiversx-sc-scenario", + "plotters", + "plotters-canvas", + "wasm-bindgen", + "web-sys", + "wee_alloc", +] + [[package]] name = "scenario-tester" version = "0.0.0" @@ -3110,7 +3697,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ "block-buffer 0.9.0", - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "digest 0.9.0", "opaque-debug", @@ -3122,7 +3709,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "digest 0.10.7", ] @@ -3200,6 +3787,18 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "str-repeat" version = "0.0.0" @@ -3241,9 +3840,20 @@ dependencies = [ [[package]] name = "sync_wrapper" -version = "0.1.2" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" + +[[package]] +name = "synstructure" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "system-configuration" @@ -3272,7 +3882,7 @@ version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "fastrand", "rustix", "windows-sys 0.52.0", @@ -3298,6 +3908,16 @@ dependencies = [ "syn", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -3331,9 +3951,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.37.0" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ "backtrace", "bytes", @@ -3350,9 +3970,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", @@ -3369,6 +3989,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + [[package]] name = "tokio-util" version = "0.7.11" @@ -3384,9 +4015,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.13" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e43f8cc456c9704c851ae29c67e17ef65d2c30017c17a9765b89c382dc8bba" +checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" dependencies = [ "indexmap", "serde", @@ -3406,9 +4037,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.13" +version = "0.22.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c127785850e8c20836d49732ae6abfa47616e60bf9d9f57c43c250361a9db96c" +checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38" dependencies = [ "indexmap", "serde", @@ -3488,16 +4119,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] -name = "typenum" -version = "1.17.0" +name = "ttf-parser" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4" [[package]] -name = "unicode-bidi" -version = "0.3.15" +name = "typenum" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-ident" @@ -3520,6 +4151,12 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "unwrap-infallible" version = "0.1.5" @@ -3528,9 +4165,9 @@ checksum = "151ac09978d3c2862c4e39b557f4eceee2cc72150bc4cb4f16abf061b6e381fb" [[package]] name = "url" -version = "2.5.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56" dependencies = [ "form_urlencoded", "idna", @@ -3555,11 +4192,23 @@ dependencies = [ "use-module", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "vault" @@ -3643,7 +4292,7 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "wasm-bindgen-macro", ] @@ -3668,7 +4317,7 @@ version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "wasm-bindgen", "web-sys", @@ -3737,6 +4386,40 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "wee_alloc" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "memory_units", + "winapi", +] + +[[package]] +name = "weezl" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + [[package]] name = "winapi-util" version = "0.1.8" @@ -3746,6 +4429,21 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.5", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -3887,9 +4585,9 @@ checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" -version = "0.6.9" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86c949fede1d13936a99f14fafd3e76fd642b556dd2ce96287fbe2e0151bfac6" +checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" dependencies = [ "memchr", ] @@ -3900,10 +4598,67 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "windows-sys 0.48.0", ] +[[package]] +name = "wio" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5" +dependencies = [ + "winapi", +] + +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "yeslogic-fontconfig-sys" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb6b23999a8b1a997bf47c7bb4d19ad4029c3327bb3386ebe0a5ff584b33c7a" +dependencies = [ + "cstr", + "dlib", + "once_cell", + "pkg-config", +] + +[[package]] +name = "yoke" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "zerocopy" version = "0.7.34" @@ -3924,6 +4679,27 @@ dependencies = [ "syn", ] +[[package]] +name = "zerofrom" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "zeroize" version = "1.8.1" @@ -3944,11 +4720,33 @@ dependencies = [ "syn", ] +[[package]] +name = "zerovec" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb2cc8827d6c0994478a15c53f374f46fbd41bea663d809b14744bc42e6b109c" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "zip" -version = "2.1.1" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd56a4d5921bc2f99947ac5b3abe5f510b1be7376fdc5e9fce4a23c6a93e87c" +checksum = "775a2b471036342aa69bc5a602bc889cb0a06cda00477d0c69566757d5553d39" dependencies = [ "arbitrary", "crc32fast", diff --git a/Cargo.toml b/Cargo.toml index 345b8670a5..5f94cec44e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ members = [ "tools/mxpy-snippet-generator", "tools/payload-macro-generator", + "tools/plotter", "vm", diff --git a/contracts/examples/multisig/sc-config.toml b/contracts/examples/multisig/sc-config.toml index 79c3aeaa20..22ff09f5dd 100644 --- a/contracts/examples/multisig/sc-config.toml +++ b/contracts/examples/multisig/sc-config.toml @@ -17,3 +17,8 @@ add-labels = ["multisig-external-view"] [[proxy]] path = "src/multisig_proxy.rs" + +[[proxy]] +path = "src/multisig_view_proxy.rs" +add-unlabelled = false +add-labels = ["multisig-external-view"] diff --git a/contracts/examples/multisig/src/multisig.rs b/contracts/examples/multisig/src/multisig.rs index 96d3d5cdfa..d1e177df02 100644 --- a/contracts/examples/multisig/src/multisig.rs +++ b/contracts/examples/multisig/src/multisig.rs @@ -6,6 +6,7 @@ pub mod multisig_perform; pub mod multisig_propose; pub mod multisig_proxy; pub mod multisig_state; +pub mod multisig_view_proxy; pub mod user_role; use action::ActionFullInfo; diff --git a/contracts/examples/multisig/src/multisig_proxy.rs b/contracts/examples/multisig/src/multisig_proxy.rs index d3a3e32e0e..6e4b78df16 100644 --- a/contracts/examples/multisig/src/multisig_proxy.rs +++ b/contracts/examples/multisig/src/multisig_proxy.rs @@ -104,20 +104,6 @@ where .original_result() } - /// Iterates through all actions and retrieves those that are still pending. - /// Serialized full action data: - /// - the action id - /// - the serialized action data - /// - (number of signers followed by) list of signer addresses. - pub fn get_pending_action_full_info( - self, - ) -> TxTypedCall>> { - self.wrapped_tx - .payment(NotPayable) - .raw_call("getPendingActionFullInfo") - .original_result() - } - /// Returns `true` (`1`) if the user has signed the action. /// Does not check whether or not the user is still a board member and the signature valid. pub fn signed< @@ -136,43 +122,6 @@ where .original_result() } - /// Indicates user rights. - /// `0` = no rights, - /// `1` = can propose, but not sign, - /// `2` = can propose and sign. - pub fn user_role< - Arg0: ProxyArg>, - >( - self, - user: Arg0, - ) -> TxTypedCall { - self.wrapped_tx - .payment(NotPayable) - .raw_call("userRole") - .argument(&user) - .original_result() - } - - /// Lists all users that can sign actions. - pub fn get_all_board_members( - self, - ) -> TxTypedCall>> { - self.wrapped_tx - .payment(NotPayable) - .raw_call("getAllBoardMembers") - .original_result() - } - - /// Lists all proposers that are not board members. - pub fn get_all_proposers( - self, - ) -> TxTypedCall>> { - self.wrapped_tx - .payment(NotPayable) - .raw_call("getAllProposers") - .original_result() - } - /// Used by board members to sign actions. pub fn sign< Arg0: ProxyArg, @@ -261,69 +210,6 @@ where .original_result() } - /// Serialized action data of an action with index. - pub fn get_action_data< - Arg0: ProxyArg, - >( - self, - action_id: Arg0, - ) -> TxTypedCall> { - self.wrapped_tx - .payment(NotPayable) - .raw_call("getActionData") - .argument(&action_id) - .original_result() - } - - /// Gets addresses of all users who signed an action. - /// Does not check if those users are still board members or not, - /// so the result may contain invalid signers. - pub fn get_action_signers< - Arg0: ProxyArg, - >( - self, - action_id: Arg0, - ) -> TxTypedCall>> { - self.wrapped_tx - .payment(NotPayable) - .raw_call("getActionSigners") - .argument(&action_id) - .original_result() - } - - /// Gets addresses of all users who signed an action and are still board members. - /// All these signatures are currently valid. - pub fn get_action_signer_count< - Arg0: ProxyArg, - >( - self, - action_id: Arg0, - ) -> TxTypedCall { - self.wrapped_tx - .payment(NotPayable) - .raw_call("getActionSignerCount") - .argument(&action_id) - .original_result() - } - - /// It is possible for board members to lose their role. - /// They are not automatically removed from all actions when doing so, - /// therefore the contract needs to re-check every time when actions are performed. - /// This function is used to validate the signers before performing an action. - /// It also makes it easy to check before performing an action. - pub fn get_action_valid_signer_count< - Arg0: ProxyArg, - >( - self, - action_id: Arg0, - ) -> TxTypedCall { - self.wrapped_tx - .payment(NotPayable) - .raw_call("getActionValidSignerCount") - .argument(&action_id) - .original_result() - } - /// Initiates board member addition process. /// Can also be used to promote a proposer to board member. pub fn propose_add_board_member< diff --git a/contracts/examples/multisig/src/multisig_view_proxy.rs b/contracts/examples/multisig/src/multisig_view_proxy.rs new file mode 100644 index 0000000000..f17bdc4212 --- /dev/null +++ b/contracts/examples/multisig/src/multisig_view_proxy.rs @@ -0,0 +1,220 @@ +// Code generated by the multiversx-sc proxy generator. DO NOT EDIT. + +//////////////////////////////////////////////////// +////////////////// AUTO-GENERATED ////////////////// +//////////////////////////////////////////////////// + +#![allow(dead_code)] +#![allow(clippy::all)] + +use multiversx_sc::proxy_imports::*; + +pub struct MultisigProxy; + +impl TxProxyTrait for MultisigProxy +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + type TxProxyMethods = MultisigProxyMethods; + + fn proxy_methods(self, tx: Tx) -> Self::TxProxyMethods { + MultisigProxyMethods { wrapped_tx: tx } + } +} + +pub struct MultisigProxyMethods +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + wrapped_tx: Tx, +} + +#[rustfmt::skip] +impl MultisigProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + /// Iterates through all actions and retrieves those that are still pending. + /// Serialized full action data: + /// - the action id + /// - the serialized action data + /// - (number of signers followed by) list of signer addresses. + pub fn get_pending_action_full_info( + self, + ) -> TxTypedCall>> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getPendingActionFullInfo") + .original_result() + } + + /// Indicates user rights. + /// `0` = no rights, + /// `1` = can propose, but not sign, + /// `2` = can propose and sign. + pub fn user_role< + Arg0: ProxyArg>, + >( + self, + user: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("userRole") + .argument(&user) + .original_result() + } + + /// Lists all users that can sign actions. + pub fn get_all_board_members( + self, + ) -> TxTypedCall>> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getAllBoardMembers") + .original_result() + } + + /// Lists all proposers that are not board members. + pub fn get_all_proposers( + self, + ) -> TxTypedCall>> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getAllProposers") + .original_result() + } + + /// Serialized action data of an action with index. + pub fn get_action_data< + Arg0: ProxyArg, + >( + self, + action_id: Arg0, + ) -> TxTypedCall> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getActionData") + .argument(&action_id) + .original_result() + } + + /// Gets addresses of all users who signed an action. + /// Does not check if those users are still board members or not, + /// so the result may contain invalid signers. + pub fn get_action_signers< + Arg0: ProxyArg, + >( + self, + action_id: Arg0, + ) -> TxTypedCall>> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getActionSigners") + .argument(&action_id) + .original_result() + } + + /// Gets addresses of all users who signed an action and are still board members. + /// All these signatures are currently valid. + pub fn get_action_signer_count< + Arg0: ProxyArg, + >( + self, + action_id: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getActionSignerCount") + .argument(&action_id) + .original_result() + } + + /// It is possible for board members to lose their role. + /// They are not automatically removed from all actions when doing so, + /// therefore the contract needs to re-check every time when actions are performed. + /// This function is used to validate the signers before performing an action. + /// It also makes it easy to check before performing an action. + pub fn get_action_valid_signer_count< + Arg0: ProxyArg, + >( + self, + action_id: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getActionValidSignerCount") + .argument(&action_id) + .original_result() + } +} + +#[type_abi] +#[derive(TopEncode)] +pub struct ActionFullInfo +where + Api: ManagedTypeApi, +{ + pub action_id: usize, + pub action_data: Action, + pub signers: ManagedVec>, +} + +#[rustfmt::skip] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, Clone)] +pub enum Action +where + Api: ManagedTypeApi, +{ + Nothing, + AddBoardMember(ManagedAddress), + AddProposer(ManagedAddress), + RemoveUser(ManagedAddress), + ChangeQuorum(usize), + SendTransferExecute(CallActionData), + SendAsyncCall(CallActionData), + SCDeployFromSource { + amount: BigUint, + source: ManagedAddress, + code_metadata: CodeMetadata, + arguments: ManagedVec>, + }, + SCUpgradeFromSource { + sc_address: ManagedAddress, + amount: BigUint, + source: ManagedAddress, + code_metadata: CodeMetadata, + arguments: ManagedVec>, + }, +} + +#[type_abi] +#[derive(NestedEncode, NestedDecode, Clone)] +pub struct CallActionData +where + Api: ManagedTypeApi, +{ + pub to: ManagedAddress, + pub egld_amount: BigUint, + pub endpoint_name: ManagedBuffer, + pub arguments: ManagedVec>, +} + +#[type_abi] +#[derive(TopEncode, TopDecode)] +pub enum UserRole { + None, + Proposer, + BoardMember, +} diff --git a/contracts/examples/multisig/tests/multisig_blackbox_test.rs b/contracts/examples/multisig/tests/multisig_blackbox_test.rs index 083a6c6be6..e8067bb73a 100644 --- a/contracts/examples/multisig/tests/multisig_blackbox_test.rs +++ b/contracts/examples/multisig/tests/multisig_blackbox_test.rs @@ -2,7 +2,7 @@ use multiversx_sc::codec::top_encode_to_vec_u8_or_panic; use multiversx_sc_scenario::imports::*; use adder::adder_proxy; -use multisig::multisig_proxy; +use multisig::{multisig_proxy, multisig_view_proxy}; use num_bigint::BigUint; const ADDER_ADDRESS: TestSCAddress = TestSCAddress::new("adder"); @@ -71,7 +71,7 @@ impl MultisigTestState { self.sign(action_id); self.perform(action_id); - self.expect_user_role(PROPOSER_ADDRESS, multisig_proxy::UserRole::Proposer); + self.expect_user_role(PROPOSER_ADDRESS, multisig_view_proxy::UserRole::Proposer); self } @@ -232,12 +232,12 @@ impl MultisigTestState { fn expect_user_role( &mut self, user: TestAddress, - expected_user_role: multisig_proxy::UserRole, + expected_user_role: multisig_view_proxy::UserRole, ) { self.world .query() .to(MULTISIG_ADDRESS) - .typed(multisig_proxy::MultisigProxy) + .typed(multisig_view_proxy::MultisigProxy) .user_role(user) .returns(ExpectValue(expected_user_role)) .run(); @@ -253,7 +253,7 @@ fn test_add_board_member() { state.world.account(new_board_member_expr).nonce(1); - state.expect_user_role(new_board_member_expr, multisig_proxy::UserRole::None); + state.expect_user_role(new_board_member_expr, multisig_view_proxy::UserRole::None); let action_id = state.propose_add_board_member(new_board_member_expr); state.sign(action_id); @@ -261,12 +261,15 @@ fn test_add_board_member() { let expected_value = MultiValueVec::from(vec![BOARD_MEMBER_ADDRESS, new_board_member_expr]); - state.expect_user_role(new_board_member_expr, multisig_proxy::UserRole::BoardMember); + state.expect_user_role( + new_board_member_expr, + multisig_view_proxy::UserRole::BoardMember, + ); state .world .query() .to(MULTISIG_ADDRESS) - .typed(multisig_proxy::MultisigProxy) + .typed(multisig_view_proxy::MultisigProxy) .get_all_board_members() .returns(ExpectValue(expected_value)) .run() @@ -281,7 +284,10 @@ fn test_add_proposer() { state.world.account(new_proposer_address_expr).nonce(1); - state.expect_user_role(new_proposer_address_expr, multisig_proxy::UserRole::None); + state.expect_user_role( + new_proposer_address_expr, + multisig_view_proxy::UserRole::None, + ); let action_id = state.propose_add_proposer(new_proposer_address_expr); state.sign(action_id); @@ -289,7 +295,7 @@ fn test_add_proposer() { state.expect_user_role( new_proposer_address_expr, - multisig_proxy::UserRole::Proposer, + multisig_view_proxy::UserRole::Proposer, ); let expected_value = MultiValueVec::from(vec![PROPOSER_ADDRESS, new_proposer_address_expr]); @@ -297,7 +303,7 @@ fn test_add_proposer() { .world .query() .to(MULTISIG_ADDRESS) - .typed(multisig_proxy::MultisigProxy) + .typed(multisig_view_proxy::MultisigProxy) .get_all_proposers() .returns(ExpectValue(expected_value)) .run(); @@ -308,18 +314,18 @@ fn test_remove_proposer() { let mut state = MultisigTestState::new(); state.deploy_multisig_contract(); - state.expect_user_role(PROPOSER_ADDRESS, multisig_proxy::UserRole::Proposer); + state.expect_user_role(PROPOSER_ADDRESS, multisig_view_proxy::UserRole::Proposer); let action_id = state.propose_remove_user(PROPOSER_ADDRESS); state.sign(action_id); state.perform(action_id); - state.expect_user_role(PROPOSER_ADDRESS, multisig_proxy::UserRole::None); + state.expect_user_role(PROPOSER_ADDRESS, multisig_view_proxy::UserRole::None); state .world .query() .to(MULTISIG_ADDRESS) - .typed(multisig_proxy::MultisigProxy) + .typed(multisig_view_proxy::MultisigProxy) .get_all_proposers() .returns(ExpectValue(MultiValueVec::
::new())) .run(); diff --git a/contracts/feature-tests/abi-tester/src/abi_proxy.rs b/contracts/feature-tests/abi-tester/src/abi_proxy.rs index 2011970429..77604821e3 100644 --- a/contracts/feature-tests/abi-tester/src/abi_proxy.rs +++ b/contracts/feature-tests/abi-tester/src/abi_proxy.rs @@ -397,33 +397,6 @@ where .raw_call("payable_any_token") .original_result() } - - pub fn external_view( - self, - ) -> TxTypedCall { - self.wrapped_tx - .payment(NotPayable) - .raw_call("external_view") - .original_result() - } - - pub fn label_a( - self, - ) -> TxTypedCall { - self.wrapped_tx - .payment(NotPayable) - .raw_call("label_a") - .original_result() - } - - pub fn label_b( - self, - ) -> TxTypedCall { - self.wrapped_tx - .payment(NotPayable) - .raw_call("label_b") - .original_result() - } } #[type_abi] diff --git a/contracts/feature-tests/alloc-features/src/echo_alloc.rs b/contracts/feature-tests/alloc-features/src/echo_alloc.rs index 22e334c229..39f7b185c0 100644 --- a/contracts/feature-tests/alloc-features/src/echo_alloc.rs +++ b/contracts/feature-tests/alloc-features/src/echo_alloc.rs @@ -2,9 +2,6 @@ multiversx_sc::imports!(); use crate::types::*; -// String is not part of the standard imports because we want to discourage its use -use multiversx_sc::types::String; - /// Test serialization for heap-allocated types. #[multiversx_sc::module] pub trait EchoAllocTypes { diff --git a/contracts/feature-tests/alloc-features/src/macro_features_legacy.rs b/contracts/feature-tests/alloc-features/src/macro_features_legacy.rs index 0a33d06c05..d5e5f5ef77 100644 --- a/contracts/feature-tests/alloc-features/src/macro_features_legacy.rs +++ b/contracts/feature-tests/alloc-features/src/macro_features_legacy.rs @@ -2,8 +2,6 @@ multiversx_sc::imports!(); -use multiversx_sc::types::String; - /// Legacy, deprecated macros. Will b removed once they get removed. /// /// Error conversions should be moved to corresponding new formatter-based error tests. diff --git a/contracts/feature-tests/basic-features/sc-config.toml b/contracts/feature-tests/basic-features/sc-config.toml index c870fda7cb..82698d1dab 100644 --- a/contracts/feature-tests/basic-features/sc-config.toml +++ b/contracts/feature-tests/basic-features/sc-config.toml @@ -8,3 +8,8 @@ overflow-checks = true # needed for overflow tests add-unlabelled = false add-endpoints = ["init", "load_bytes", "store_bytes"] kill_legacy_callback = true + +[[proxy]] +path = "src/basic_features_proxy.rs" +add-unlabelled = false +add-endpoints = ["init", "store_bytes", "load_bytes", "returns_egld_decimal"] diff --git a/contracts/feature-tests/basic-features/scenarios/big_uint_log2.json b/contracts/feature-tests/basic-features/scenarios/big_uint_log2.json index 18fea6a2c4..e4e6d5c974 100644 --- a/contracts/feature-tests/basic-features/scenarios/big_uint_log2.json +++ b/contracts/feature-tests/basic-features/scenarios/big_uint_log2.json @@ -42,6 +42,54 @@ "gas": "*", "refund": "*" } + }, + { + "step": "scCall", + "id": "log2 from 1", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "value": "0", + "function": "log2_big_uint", + "arguments": [ + "1" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0" + ], + "status": "0", + "logs": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scCall", + "id": "log2 from 0", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "value": "0", + "function": "log2_big_uint", + "arguments": [ + "0" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0" + ], + "status": "0", + "logs": "*", + "gas": "*", + "refund": "*" + } } ] -} +} \ No newline at end of file diff --git a/contracts/feature-tests/basic-features/src/basic_features_proxy.rs b/contracts/feature-tests/basic-features/src/basic_features_proxy.rs index 7131607d8c..469b2d3323 100644 --- a/contracts/feature-tests/basic-features/src/basic_features_proxy.rs +++ b/contracts/feature-tests/basic-features/src/basic_features_proxy.rs @@ -1,3 +1,12 @@ +// Code generated by the multiversx-sc proxy generator. DO NOT EDIT. + +//////////////////////////////////////////////////// +////////////////// AUTO-GENERATED ////////////////// +//////////////////////////////////////////////////// + +#![allow(dead_code)] +#![allow(clippy::all)] + use multiversx_sc::proxy_imports::*; pub struct BasicFeaturesProxy; diff --git a/contracts/feature-tests/basic-features/src/big_num_methods.rs b/contracts/feature-tests/basic-features/src/big_num_methods.rs index 086f89761b..c30b8cb56e 100644 --- a/contracts/feature-tests/basic-features/src/big_num_methods.rs +++ b/contracts/feature-tests/basic-features/src/big_num_methods.rs @@ -48,7 +48,7 @@ pub trait BigIntMethods { } #[endpoint] - fn biguint_overwrite_u64(&self, bu: BigUint, small: u64) -> BigUint { + fn biguint_overwrite_u64(&self, mut bu: BigUint, small: u64) -> BigUint { bu.overwrite_u64(small); bu } diff --git a/contracts/feature-tests/big-float-features/scenarios/big_float_operators.scen.json b/contracts/feature-tests/big-float-features/scenarios/big_float_operators.scen.json index 30c020132b..3021715617 100644 --- a/contracts/feature-tests/big-float-features/scenarios/big_float_operators.scen.json +++ b/contracts/feature-tests/big-float-features/scenarios/big_float_operators.scen.json @@ -820,6 +820,26 @@ "-1" ] } + }, + { + "step": "scCall", + "id": "LnBigFloatRef - 1", + "tx": { + "from": "address:an_account", + "to": "sc:basic-features", + "function": "ln_big_float_ref_wrapped", + "arguments": [ + "23", + "9" + ], + "gasLimit": "50,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "0x00000004bae4281800000009" + ] + } } ] -} +} \ No newline at end of file diff --git a/contracts/feature-tests/big-float-features/src/big_float_operators.rs b/contracts/feature-tests/big-float-features/src/big_float_operators.rs index abf239b52a..a5fae8a720 100644 --- a/contracts/feature-tests/big-float-features/src/big_float_operators.rs +++ b/contracts/feature-tests/big-float-features/src/big_float_operators.rs @@ -85,4 +85,9 @@ pub trait BigFloatOperators { r /= b; r } + #[endpoint] + fn ln_big_float_ref(&self, a: &BigFloat) -> BigFloat { + a.ln() + .unwrap_or_else(|| sc_panic!("log argument must pe strictly positive")) + } } diff --git a/contracts/feature-tests/big-float-features/src/big_float_operators_wrapped.rs b/contracts/feature-tests/big-float-features/src/big_float_operators_wrapped.rs index 74b6045d1c..14cf56510d 100644 --- a/contracts/feature-tests/big-float-features/src/big_float_operators_wrapped.rs +++ b/contracts/feature-tests/big-float-features/src/big_float_operators_wrapped.rs @@ -158,4 +158,14 @@ pub trait BigFloatWrappedOperators: big_float_operators::BigFloatOperators { let number = self.div_assign_big_float_ref(&BigFloat::from(a), &BigFloat::from(b)); number.to_fixed_point(&BigFloat::from(fixed_point_denominator)) } + + #[endpoint] + fn ln_big_float_ref_wrapped( + &self, + a: BigInt, + precision: usize, + ) -> ManagedDecimal { + let number = self.ln_big_float_ref(&BigFloat::from(a)); + number.to_managed_decimal(precision) + } } diff --git a/contracts/feature-tests/big-float-features/tests/big_float_scenario_rs_test.rs b/contracts/feature-tests/big-float-features/tests/big_float_scenario_rs_test.rs index 66ca09ab86..60a9d0ed35 100644 --- a/contracts/feature-tests/big-float-features/tests/big_float_scenario_rs_test.rs +++ b/contracts/feature-tests/big-float-features/tests/big_float_scenario_rs_test.rs @@ -1,5 +1,4 @@ -use multiversx_sc::types::{BigFloat, BigUint}; -use multiversx_sc_scenario::{api::StaticApi, *}; +use multiversx_sc_scenario::*; fn world() -> ScenarioWorld { let mut blockchain = ScenarioWorld::new(); @@ -12,50 +11,6 @@ fn world() -> ScenarioWorld { blockchain } -#[test] -fn big_float_overflow_test_rs() { - let exp = 1_080i32; - - let first = BigFloat::::from_sci(1_005, -3) - .pow(exp) - .to_fixed_point(&(100_000_000_000_000_000i64.into())) - .into_big_uint(); - - let second = BigFloat::::from_sci(1_005, -3) - .pow(exp) - .to_fixed_point(&(10_000_000_000_000_000i64.into())) - .into_big_uint(); - - let third_float = BigFloat::::from_sci(1_005, -3) - .pow(exp) - .to_managed_decimal(17usize); - let third = third_float.into_raw_units(); - - let forth_float = BigFloat::::from_sci(1_005, -3) - .pow(exp) - .to_managed_decimal(16usize); - let forth = forth_float.into_raw_units(); - - assert_eq!( - first.unwrap_or_sc_panic("unwrap failed"), - /* overflow */ - BigUint::from(9223372036854775807u64) - ); - - assert_eq!( - second.unwrap_or_sc_panic("unwrap failed"), - BigUint::from(2184473079534488064u64) - ); - - assert_eq!( - third, - /* overflow */ - &BigUint::from(9223372036854775807u64) - ); - - assert_eq!(forth, &BigUint::from(2184473079534488064u64)); -} - #[test] fn big_float_new_from_big_int_rs() { world().run("scenarios/big_float_new_from_big_int.scen.json"); diff --git a/contracts/feature-tests/big-float-features/wasm/src/lib.rs b/contracts/feature-tests/big-float-features/wasm/src/lib.rs index 6ec41ff9e9..0993fe17ed 100644 --- a/contracts/feature-tests/big-float-features/wasm/src/lib.rs +++ b/contracts/feature-tests/big-float-features/wasm/src/lib.rs @@ -5,9 +5,9 @@ //////////////////////////////////////////////////// // Init: 1 -// Endpoints: 70 +// Endpoints: 72 // Async Callback (empty): 1 -// Total number of exported functions: 72 +// Total number of exported functions: 74 #![no_std] @@ -54,6 +54,7 @@ multiversx_sc_wasm_adapter::endpoints! { mul_assign_big_float_ref => mul_assign_big_float_ref div_assign_big_float => div_assign_big_float div_assign_big_float_ref => div_assign_big_float_ref + ln_big_float_ref => ln_big_float_ref new_from_parts_big_float_wrapped => new_from_parts_big_float_wrapped new_from_frac_big_float_wrapped => new_from_frac_big_float_wrapped new_from_sci_big_float_wrapped => new_from_sci_big_float_wrapped @@ -88,6 +89,7 @@ multiversx_sc_wasm_adapter::endpoints! { mul_assign_big_float_ref_wrapped => mul_assign_big_float_ref_wrapped div_assign_big_float_wrapped => div_assign_big_float_wrapped div_assign_big_float_ref_wrapped => div_assign_big_float_ref_wrapped + ln_big_float_ref_wrapped => ln_big_float_ref_wrapped ) } diff --git a/contracts/feature-tests/composability/forwarder/src/forwarder_main.rs b/contracts/feature-tests/composability/forwarder/src/forwarder_main.rs index cd2254587c..c6e9dcb443 100644 --- a/contracts/feature-tests/composability/forwarder/src/forwarder_main.rs +++ b/contracts/feature-tests/composability/forwarder/src/forwarder_main.rs @@ -14,6 +14,7 @@ pub mod fwd_sft; pub mod fwd_storage; pub mod fwd_upgrade; pub mod vault_proxy; +pub mod vault_upgrade_proxy; multiversx_sc::imports!(); diff --git a/contracts/feature-tests/composability/forwarder/src/fwd_upgrade.rs b/contracts/feature-tests/composability/forwarder/src/fwd_upgrade.rs index f4782821e0..11ef0b1a39 100644 --- a/contracts/feature-tests/composability/forwarder/src/fwd_upgrade.rs +++ b/contracts/feature-tests/composability/forwarder/src/fwd_upgrade.rs @@ -1,4 +1,4 @@ -use crate::vault_proxy; +use crate::vault_upgrade_proxy; multiversx_sc::imports!(); @@ -13,7 +13,7 @@ pub trait UpgradeContractModule { ) { self.tx() .to(child_sc_address) - .typed(vault_proxy::VaultProxy) + .typed(vault_upgrade_proxy::VaultProxy) .upgrade(opt_arg) .code(new_code) .code_metadata(CodeMetadata::UPGRADEABLE) @@ -29,7 +29,7 @@ pub trait UpgradeContractModule { ) { self.tx() .to(child_sc_address) - .typed(vault_proxy::VaultProxy) + .typed(vault_upgrade_proxy::VaultProxy) .upgrade(opt_arg) .code_metadata(CodeMetadata::UPGRADEABLE) .from_source(source_address) diff --git a/contracts/feature-tests/composability/forwarder/src/vault_proxy.rs b/contracts/feature-tests/composability/forwarder/src/vault_proxy.rs index 24e6f12e69..7f653bfa45 100644 --- a/contracts/feature-tests/composability/forwarder/src/vault_proxy.rs +++ b/contracts/feature-tests/composability/forwarder/src/vault_proxy.rs @@ -57,29 +57,6 @@ where } } -#[rustfmt::skip] -impl VaultProxyMethods -where - Env: TxEnv, - Env::Api: VMApi, - From: TxFrom, - To: TxTo, - Gas: TxGas, -{ - pub fn upgrade< - Arg0: ProxyArg>>, - >( - self, - opt_arg_to_echo: Arg0, - ) -> TxTypedUpgrade>>> { - self.wrapped_tx - .payment(NotPayable) - .raw_upgrade() - .argument(&opt_arg_to_echo) - .original_result() - } -} - #[rustfmt::skip] impl VaultProxyMethods where @@ -174,21 +151,6 @@ where .original_result() } - pub fn retrieve_funds_promises< - Arg0: ProxyArg>, - Arg1: ProxyArg>>, - >( - self, - back_transfers: Arg0, - back_transfer_value: Arg1, - ) -> TxTypedCall { - self.wrapped_tx - .raw_call("retrieve_funds_promises") - .argument(&back_transfers) - .argument(&back_transfer_value) - .original_result() - } - pub fn retrieve_funds< Arg0: ProxyArg>, Arg1: ProxyArg, diff --git a/contracts/feature-tests/composability/forwarder/src/vault_upgrade_proxy.rs b/contracts/feature-tests/composability/forwarder/src/vault_upgrade_proxy.rs new file mode 100644 index 0000000000..ee2a10a78f --- /dev/null +++ b/contracts/feature-tests/composability/forwarder/src/vault_upgrade_proxy.rs @@ -0,0 +1,59 @@ +// Code generated by the multiversx-sc proxy generator. DO NOT EDIT. + +//////////////////////////////////////////////////// +////////////////// AUTO-GENERATED ////////////////// +//////////////////////////////////////////////////// + +#![allow(dead_code)] +#![allow(clippy::all)] + +use multiversx_sc::proxy_imports::*; + +pub struct VaultProxy; + +impl TxProxyTrait for VaultProxy +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + type TxProxyMethods = VaultProxyMethods; + + fn proxy_methods(self, tx: Tx) -> Self::TxProxyMethods { + VaultProxyMethods { wrapped_tx: tx } + } +} + +pub struct VaultProxyMethods +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + wrapped_tx: Tx, +} + +#[rustfmt::skip] +impl VaultProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + pub fn upgrade< + Arg0: ProxyArg>>, + >( + self, + opt_arg_to_echo: Arg0, + ) -> TxTypedUpgrade>>> { + self.wrapped_tx + .payment(NotPayable) + .raw_upgrade() + .argument(&opt_arg_to_echo) + .original_result() + } +} diff --git a/contracts/feature-tests/composability/interact/src/vault_proxy.rs b/contracts/feature-tests/composability/interact/src/vault_proxy.rs index 24e6f12e69..7f653bfa45 100644 --- a/contracts/feature-tests/composability/interact/src/vault_proxy.rs +++ b/contracts/feature-tests/composability/interact/src/vault_proxy.rs @@ -57,29 +57,6 @@ where } } -#[rustfmt::skip] -impl VaultProxyMethods -where - Env: TxEnv, - Env::Api: VMApi, - From: TxFrom, - To: TxTo, - Gas: TxGas, -{ - pub fn upgrade< - Arg0: ProxyArg>>, - >( - self, - opt_arg_to_echo: Arg0, - ) -> TxTypedUpgrade>>> { - self.wrapped_tx - .payment(NotPayable) - .raw_upgrade() - .argument(&opt_arg_to_echo) - .original_result() - } -} - #[rustfmt::skip] impl VaultProxyMethods where @@ -174,21 +151,6 @@ where .original_result() } - pub fn retrieve_funds_promises< - Arg0: ProxyArg>, - Arg1: ProxyArg>>, - >( - self, - back_transfers: Arg0, - back_transfer_value: Arg1, - ) -> TxTypedCall { - self.wrapped_tx - .raw_call("retrieve_funds_promises") - .argument(&back_transfers) - .argument(&back_transfer_value) - .original_result() - } - pub fn retrieve_funds< Arg0: ProxyArg>, Arg1: ProxyArg, diff --git a/contracts/feature-tests/composability/promises-features/src/vault_proxy.rs b/contracts/feature-tests/composability/promises-features/src/vault_proxy.rs index 24e6f12e69..7f653bfa45 100644 --- a/contracts/feature-tests/composability/promises-features/src/vault_proxy.rs +++ b/contracts/feature-tests/composability/promises-features/src/vault_proxy.rs @@ -57,29 +57,6 @@ where } } -#[rustfmt::skip] -impl VaultProxyMethods -where - Env: TxEnv, - Env::Api: VMApi, - From: TxFrom, - To: TxTo, - Gas: TxGas, -{ - pub fn upgrade< - Arg0: ProxyArg>>, - >( - self, - opt_arg_to_echo: Arg0, - ) -> TxTypedUpgrade>>> { - self.wrapped_tx - .payment(NotPayable) - .raw_upgrade() - .argument(&opt_arg_to_echo) - .original_result() - } -} - #[rustfmt::skip] impl VaultProxyMethods where @@ -174,21 +151,6 @@ where .original_result() } - pub fn retrieve_funds_promises< - Arg0: ProxyArg>, - Arg1: ProxyArg>>, - >( - self, - back_transfers: Arg0, - back_transfer_value: Arg1, - ) -> TxTypedCall { - self.wrapped_tx - .raw_call("retrieve_funds_promises") - .argument(&back_transfers) - .argument(&back_transfer_value) - .original_result() - } - pub fn retrieve_funds< Arg0: ProxyArg>, Arg1: ProxyArg, diff --git a/contracts/feature-tests/composability/recursive-caller/src/vault_proxy.rs b/contracts/feature-tests/composability/recursive-caller/src/vault_proxy.rs index 24e6f12e69..7f653bfa45 100644 --- a/contracts/feature-tests/composability/recursive-caller/src/vault_proxy.rs +++ b/contracts/feature-tests/composability/recursive-caller/src/vault_proxy.rs @@ -57,29 +57,6 @@ where } } -#[rustfmt::skip] -impl VaultProxyMethods -where - Env: TxEnv, - Env::Api: VMApi, - From: TxFrom, - To: TxTo, - Gas: TxGas, -{ - pub fn upgrade< - Arg0: ProxyArg>>, - >( - self, - opt_arg_to_echo: Arg0, - ) -> TxTypedUpgrade>>> { - self.wrapped_tx - .payment(NotPayable) - .raw_upgrade() - .argument(&opt_arg_to_echo) - .original_result() - } -} - #[rustfmt::skip] impl VaultProxyMethods where @@ -174,21 +151,6 @@ where .original_result() } - pub fn retrieve_funds_promises< - Arg0: ProxyArg>, - Arg1: ProxyArg>>, - >( - self, - back_transfers: Arg0, - back_transfer_value: Arg1, - ) -> TxTypedCall { - self.wrapped_tx - .raw_call("retrieve_funds_promises") - .argument(&back_transfers) - .argument(&back_transfer_value) - .original_result() - } - pub fn retrieve_funds< Arg0: ProxyArg>, Arg1: ProxyArg, diff --git a/contracts/feature-tests/composability/vault/sc-config.toml b/contracts/feature-tests/composability/vault/sc-config.toml index 5a76bc3096..51d609dbbd 100644 --- a/contracts/feature-tests/composability/vault/sc-config.toml +++ b/contracts/feature-tests/composability/vault/sc-config.toml @@ -19,6 +19,11 @@ add-labels = ["upgrade"] [[proxy]] path = "../forwarder/src/vault_proxy.rs" +[[proxy]] +path = "../forwarder/src/vault_upgrade_proxy.rs" +add-unlabelled = false +add-labels = ["upgrade"] + [[proxy]] path = "../promises-features/src/vault_proxy.rs" diff --git a/contracts/feature-tests/multi-contract-features/multicontract.toml b/contracts/feature-tests/multi-contract-features/multicontract.toml index dd9eaa5add..92d196560c 100644 --- a/contracts/feature-tests/multi-contract-features/multicontract.toml +++ b/contracts/feature-tests/multi-contract-features/multicontract.toml @@ -39,10 +39,12 @@ add-unlabelled = false add-labels = ["alt-impl"] [[proxy]] -variant = "multi_contract_example_feature" +variant = "multi-contract-example-feature" path = "src/multi_contract_example_feature_proxy.rs" [[proxy]] -variant = "multi_contract_alt_impl" +variant = "multi-contract-alt-impl" path = "src/multi_contract_alt_impl_proxy.rs" +add-unlabelled = false +add-labels = ["alt-impl"] diff --git a/contracts/feature-tests/rust-snippets-generator-test/src/lib.rs b/contracts/feature-tests/rust-snippets-generator-test/src/lib.rs index bc52826ecd..0ea3aaea2b 100644 --- a/contracts/feature-tests/rust-snippets-generator-test/src/lib.rs +++ b/contracts/feature-tests/rust-snippets-generator-test/src/lib.rs @@ -11,7 +11,7 @@ multiversx_sc::derive_imports!(); // cargo run snippets // Add --overwrite if you want to overwrite existing snippets -// Additionally, we also have to update the interact-rs snippets manually to add relative paths: +// Additionally, we also have to update the interactor snippets manually to add relative paths: // [dependencies.multiversx-sc-snippets] // version = "0.50.3" // path = "../../../../framework/snippets" diff --git a/data/codec/Cargo.toml b/data/codec/Cargo.toml index d1acc107bf..7255a54012 100644 --- a/data/codec/Cargo.toml +++ b/data/codec/Cargo.toml @@ -15,7 +15,6 @@ categories = ["no-std", "wasm", "cryptography::cryptocurrencies", "development-t [features] derive = ["multiversx-sc-codec-derive"] -alloc = [] [dependencies.multiversx-sc-codec-derive] path = "../codec-derive" diff --git a/data/codec/src/multi_types/mod.rs b/data/codec/src/multi_types/mod.rs index 2bb9948b41..bf6a01ec61 100644 --- a/data/codec/src/multi_types/mod.rs +++ b/data/codec/src/multi_types/mod.rs @@ -3,14 +3,10 @@ mod multi_value_optional; mod multi_value_placeholder; mod multi_value_tuple; mod multi_value_unit; - -#[cfg(feature = "alloc")] mod multi_value_vec; pub use multi_value_ignore::IgnoreValue; pub use multi_value_optional::OptionalValue; pub use multi_value_placeholder::*; pub use multi_value_tuple::*; - -#[cfg(feature = "alloc")] pub use multi_value_vec::MultiValueVec; diff --git a/framework/base/Cargo.toml b/framework/base/Cargo.toml index 3e348fd6d0..f088a20640 100644 --- a/framework/base/Cargo.toml +++ b/framework/base/Cargo.toml @@ -18,7 +18,7 @@ all-features = true [features] num-bigint = ["multiversx-sc-codec/num-bigint"] -alloc = ["multiversx-sc-codec/alloc"] +alloc = [] managed-buffer-builder-cached = [] esdt-token-payment-legacy-decode = [] diff --git a/framework/base/src/abi/type_abi_impl_codec_multi.rs b/framework/base/src/abi/type_abi_impl_codec_multi.rs index 7fcfa89ae5..a10755d3e8 100644 --- a/framework/base/src/abi/type_abi_impl_codec_multi.rs +++ b/framework/base/src/abi/type_abi_impl_codec_multi.rs @@ -5,7 +5,6 @@ use crate::{ codec::multi_types::{IgnoreValue, OptionalValue}, }; -#[cfg(feature = "alloc")] impl TypeAbiFrom> for crate::codec::multi_types::MultiValueVec where @@ -13,7 +12,6 @@ where { } -#[cfg(feature = "alloc")] impl TypeAbi for crate::codec::multi_types::MultiValueVec { type Unmanaged = crate::codec::multi_types::MultiValueVec; diff --git a/framework/base/src/storage/mappers/vec_mapper.rs b/framework/base/src/storage/mappers/vec_mapper.rs index de2eb55d82..9869130864 100644 --- a/framework/base/src/storage/mappers/vec_mapper.rs +++ b/framework/base/src/storage/mappers/vec_mapper.rs @@ -12,7 +12,7 @@ use crate::{ storage::{storage_clear, storage_set, StorageKey}, types::{ManagedAddress, ManagedType, MultiValueEncoded}, }; -use core::{marker::PhantomData, usize}; +use core::marker::PhantomData; const ITEM_SUFFIX: &[u8] = b".item"; const LEN_SUFFIX: &[u8] = b".len"; diff --git a/framework/base/src/types/managed/basic/big_float.rs b/framework/base/src/types/managed/basic/big_float.rs index 934bd2c636..e7989eaaa4 100644 --- a/framework/base/src/types/managed/basic/big_float.rs +++ b/framework/base/src/types/managed/basic/big_float.rs @@ -14,6 +14,9 @@ use crate::codec::{ NestedEncodeOutput, TopDecode, TopDecodeInput, TopEncode, TopEncodeOutput, TryStaticCast, }; +/// Denomiator used for initializing BigFloats from constants. +const DENOMINATOR: i64 = 1_000_000_000; + #[derive(Debug)] #[repr(transparent)] pub struct BigFloat { @@ -93,7 +96,6 @@ big_float_conv_num! {i16} big_float_conv_num! {i8} impl BigFloat { - #[inline] pub fn neg(&self) -> Self { let new_bf_handle: M::BigFloatHandle = use_raw_handle(M::static_var_api_impl().next_handle()); @@ -101,7 +103,13 @@ impl BigFloat { BigFloat::from_handle(new_bf_handle) } - #[inline] + pub fn abs(&self) -> Self { + let new_bf_handle: M::BigFloatHandle = + use_raw_handle(M::static_var_api_impl().next_handle()); + M::managed_type_impl().bf_abs(new_bf_handle.clone(), self.handle.clone()); + BigFloat::from_handle(new_bf_handle) + } + pub fn from_big_uint(big_uint: &BigUint) -> Self { let new_bf_handle: M::BigFloatHandle = use_raw_handle(M::static_var_api_impl().next_handle()); @@ -109,7 +117,6 @@ impl BigFloat { BigFloat::from_handle(new_bf_handle) } - #[inline] pub fn from_big_int(big_int: &BigInt) -> Self { let new_bf_handle: M::BigFloatHandle = use_raw_handle(M::static_var_api_impl().next_handle()); @@ -168,9 +175,73 @@ impl BigFloat { (self * denominator).trunc() } - pub fn to_managed_decimal(self, decimals: T) -> ManagedDecimal { + pub fn to_managed_decimal(&self, decimals: T) -> ManagedDecimal { ManagedDecimal::::from_big_float(self, decimals) } + + /// Computes the natural logarithm of the current number. + /// + /// The error is around +/- 0.00006, for all inputs. + /// + /// Will return `None` for zero or negative numbers. + pub fn ln(&self) -> Option { + if self <= &0i64 { + return None; + } + + let one = BigFloat::from(1i64); + match self.cmp(&one) { + core::cmp::Ordering::Less => { + let inv = &one / self; + debug_assert!(inv > one); + Some(inv.ln_gt_one().neg()) + }, + core::cmp::Ordering::Equal => Some(BigFloat::from(0i64)), + core::cmp::Ordering::Greater => Some(self.ln_gt_one()), + } + } + + /// Computes the natural logarithm for values between 1 and 2. Performs very poorly outside of this interval. + fn ln_between_one_and_two(&self) -> Self { + let mut result = BigFloat::from_frac(-56570851, DENOMINATOR); // -0.056570851 + result *= self; + result += BigFloat::from_frac(447179550, DENOMINATOR); // 0.44717955 + result *= self; + result += BigFloat::from_frac(-1469956800, DENOMINATOR); // -1.4699568 + result *= self; + result += BigFloat::from_frac(2821202600, DENOMINATOR); // 2.8212026 + result *= self; + result += BigFloat::from_frac(-1741793900, DENOMINATOR); // -1.7417939 + + result + } + + /// Computes the natural logarithm for values > 1. + fn ln_gt_one(&self) -> Self { + // find the highest power of 2 less than or equal to self + let trunc_val = self.trunc(); + let trunc_val_unsigned = trunc_val + .into_big_uint() + .unwrap_or_sc_panic("log argument must be positive"); + let bit_log2 = trunc_val_unsigned.log2(); // approximate, based on position of the most significant bit + if bit_log2 == u32::MAX { + // means the input was zero, TODO: change log2 return type + return BigFloat::from(0i64); + // return None; + } + let divisor = BigFloat::from(1 << bit_log2); + let x = self / &divisor; // normalize to [1.0, 2.0] + + debug_assert!(x >= 1); + debug_assert!(x <= 2); + + let mut result = x.ln_between_one_and_two(); + + let ln_of_2 = BigFloat::from_frac(693147180, DENOMINATOR); // 0.69314718 + result += BigFloat::from(bit_log2 as i32) * ln_of_2; + + result + } } impl BigFloat { diff --git a/framework/base/src/types/managed/basic/big_float_cmp.rs b/framework/base/src/types/managed/basic/big_float_cmp.rs index d3958667e6..2b342bdb76 100644 --- a/framework/base/src/types/managed/basic/big_float_cmp.rs +++ b/framework/base/src/types/managed/basic/big_float_cmp.rs @@ -4,6 +4,13 @@ use crate::api::{use_raw_handle, BigFloatApiImpl, ManagedTypeApi, StaticVarApiIm use super::{BigFloat, BigInt}; +impl BigFloat { + pub fn is_close(&self, other: &Self, abs_tolerance: &Self) -> bool { + // TODO: temp handles + &(self - other).abs() <= abs_tolerance + } +} + impl PartialEq for BigFloat { #[inline] fn eq(&self, other: &Self) -> bool { diff --git a/framework/base/src/types/managed/basic/big_uint.rs b/framework/base/src/types/managed/basic/big_uint.rs index 7f9f6bb17b..658697c2ec 100644 --- a/framework/base/src/types/managed/basic/big_uint.rs +++ b/framework/base/src/types/managed/basic/big_uint.rs @@ -10,9 +10,12 @@ use crate::{ DecodeErrorHandler, EncodeErrorHandler, NestedDecode, NestedDecodeInput, NestedEncode, NestedEncodeOutput, TopDecode, TopDecodeInput, TopEncode, TopEncodeOutput, TryStaticCast, }, + contract_base::ErrorHelper, formatter::{hex_util::encode_bytes_as_hex, FormatBuffer, FormatByteReceiver, SCDisplay}, - proxy_imports::ManagedRef, - types::{heap::BoxedBytes, ManagedBuffer, ManagedBufferCachedBuilder, ManagedType}, + types::{ + heap::BoxedBytes, ConstDecimals, Decimals, ManagedBuffer, ManagedBufferCachedBuilder, + ManagedDecimal, ManagedRef, ManagedType, + }, }; use super::cast_to_i64::cast_to_i64; @@ -176,7 +179,7 @@ impl BigUint { } #[inline] - pub fn overwrite_u64(&self, value: u64) { + pub fn overwrite_u64(&mut self, value: u64) { Self::set_value(self.handle.clone(), value); } @@ -236,6 +239,56 @@ impl BigUint { let api = M::managed_type_impl(); api.bi_log2(self.handle.clone()) } + + /// Natural logarithm of a number. + /// + /// Returns `None` for 0. + pub fn ln(&self) -> Option>> { + let bit_log2 = self.log2(); // aproximate, based on position of the most significant bit + if bit_log2 == u32::MAX { + // means the input was zero, TODO: change log2 return type + return None; + } + + let scaling_factor_9 = ConstDecimals::<9>.scaling_factor(); + let divisor = BigUint::from(1u64) << bit_log2 as usize; + let normalized = self * &*scaling_factor_9 / divisor; + + let x = normalized + .to_u64() + .unwrap_or_else(|| ErrorHelper::::signal_error_with_message("ln internal error")) + as i64; + + const DENOMINATOR: i64 = 1_000_000_000; + + // x normalized to [1.0, 2.0] + debug_assert!(x >= DENOMINATOR); + debug_assert!(x <= 2 * DENOMINATOR); + + let mut result: i64 = -56570851; // -0.056570851 + result *= x; + result /= DENOMINATOR; + result += 447179550; // 0.44717955 + result *= x; + result /= DENOMINATOR; + result += -1469956800; // -1.4699568 + result *= x; + result /= DENOMINATOR; + result += 2821202600; // 2.8212026 + result *= x; + result /= DENOMINATOR; + result += -1741793900; // -1.7417939 + + const LN_OF_2_SCALE_9: i64 = 693147180; // 0.69314718 + result += bit_log2 as i64 * LN_OF_2_SCALE_9; + + debug_assert!(result > 0); + + let mut result_bi = normalized; // reuse handle + result_bi.overwrite_u64(result as u64); + + Some(ManagedDecimal::const_decimals_from_raw(result_bi)) + } } impl Clone for BigUint { diff --git a/framework/base/src/types/managed/basic/managed_buffer.rs b/framework/base/src/types/managed/basic/managed_buffer.rs index d232776b2e..de2dc63bb8 100644 --- a/framework/base/src/types/managed/basic/managed_buffer.rs +++ b/framework/base/src/types/managed/basic/managed_buffer.rs @@ -514,7 +514,6 @@ impl core::fmt::Debug for ManagedBuffer { } } -#[cfg(feature = "alloc")] impl core::fmt::Display for ManagedBuffer { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { use crate::contract_base::ErrorHelper; diff --git a/framework/base/src/types/managed/multi_value/multi_value_encoded.rs b/framework/base/src/types/managed/multi_value/multi_value_encoded.rs index f06a6fcbdc..04dbde9357 100644 --- a/framework/base/src/types/managed/multi_value/multi_value_encoded.rs +++ b/framework/base/src/types/managed/multi_value/multi_value_encoded.rs @@ -1,5 +1,6 @@ use unwrap_infallible::UnwrapInfallible; +use crate::codec::multi_types::MultiValueVec; use crate::{ abi::{TypeAbi, TypeAbiFrom, TypeDescriptionContainer, TypeName}, api::{ErrorApi, ManagedTypeApi}, @@ -244,12 +245,8 @@ where M: ManagedTypeApi, T: TypeAbi, { - #[cfg(feature = "alloc")] type Unmanaged = MultiValueVec; - #[cfg(not(feature = "alloc"))] - type Unmanaged = Self; - fn type_name() -> TypeName { crate::abi::type_name_variadic::() } @@ -267,10 +264,6 @@ where } } -#[cfg(feature = "alloc")] -use crate::codec::multi_types::MultiValueVec; - -#[cfg(feature = "alloc")] impl TypeAbiFrom> for MultiValueEncoded where M: ManagedTypeApi + ErrorApi, @@ -279,7 +272,6 @@ where { } -#[cfg(feature = "alloc")] impl TypeAbiFrom> for MultiValueVec where M: ManagedTypeApi + ErrorApi, diff --git a/framework/base/src/types/managed/multi_value/multi_value_managed_vec.rs b/framework/base/src/types/managed/multi_value/multi_value_managed_vec.rs index 0c1f094cb6..a168711af1 100644 --- a/framework/base/src/types/managed/multi_value/multi_value_managed_vec.rs +++ b/framework/base/src/types/managed/multi_value/multi_value_managed_vec.rs @@ -1,3 +1,5 @@ +use multiversx_sc_codec::multi_types::MultiValueVec; + use crate::{ abi::{TypeAbi, TypeAbiFrom, TypeDescriptionContainer, TypeName}, api::ManagedTypeApi, @@ -222,11 +224,7 @@ where M: ManagedTypeApi, T: ManagedVecItem, { - #[cfg(feature = "alloc")] - type Unmanaged = multiversx_sc_codec::multi_types::MultiValueVec; - - #[cfg(not(feature = "alloc"))] - type Unmanaged = Self; + type Unmanaged = MultiValueVec; fn type_name() -> TypeName { crate::abi::type_name_variadic::() diff --git a/framework/base/src/types/managed/wrapped/managed_address.rs b/framework/base/src/types/managed/wrapped/managed_address.rs index ca871a718b..a90482fb04 100644 --- a/framework/base/src/types/managed/wrapped/managed_address.rs +++ b/framework/base/src/types/managed/wrapped/managed_address.rs @@ -235,12 +235,8 @@ impl TypeAbi for ManagedAddress where M: ManagedTypeApi, { - #[cfg(feature = "alloc")] type Unmanaged = crate::types::heap::Address; - #[cfg(not(feature = "alloc"))] - type Unmanaged = Self; - /// `"Address"` instead of `"array32"`. fn type_name() -> TypeName { Address::type_name() @@ -274,14 +270,7 @@ impl core::fmt::Debug for ManagedAddress { impl TypeAbiFrom<[u8; 32]> for ManagedAddress where M: ManagedTypeApi {} -#[cfg(feature = "alloc")] impl TypeAbiFrom
for ManagedAddress where M: ManagedTypeApi {} - -#[cfg(feature = "alloc")] impl TypeAbiFrom<&Address> for ManagedAddress where M: ManagedTypeApi {} - -#[cfg(feature = "alloc")] impl TypeAbiFrom> for Address where M: ManagedTypeApi {} - -#[cfg(feature = "alloc")] impl TypeAbiFrom<&ManagedAddress> for Address where M: ManagedTypeApi {} diff --git a/framework/base/src/types/managed/wrapped/managed_decimal.rs b/framework/base/src/types/managed/wrapped/managed_decimal.rs index 0dd9b53d0c..40fbb6ba5d 100644 --- a/framework/base/src/types/managed/wrapped/managed_decimal.rs +++ b/framework/base/src/types/managed/wrapped/managed_decimal.rs @@ -1,12 +1,15 @@ use crate::{ abi::{TypeAbi, TypeAbiFrom, TypeName}, api::{ - const_handles, use_raw_handle, BigFloatApiImpl, BigIntApiImpl, ManagedTypeApi, - StaticVarApiImpl, + const_handles, use_raw_handle, BigFloatApiImpl, BigIntApiImpl, HandleConstraints, + ManagedBufferApiImpl, ManagedTypeApi, StaticVarApiImpl, }, + formatter::{FormatBuffer, FormatByteReceiver, SCDisplay}, + proxy_imports::{ManagedBuffer, ManagedType}, types::{BigFloat, BigUint}, }; +use alloc::string::ToString; use multiversx_sc_codec::{ DecodeError, DecodeErrorHandler, EncodeErrorHandler, NestedDecode, NestedDecodeInput, NestedEncode, NestedEncodeOutput, TopDecode, TopDecodeInput, TopEncode, TopEncodeOutput, @@ -14,7 +17,7 @@ use multiversx_sc_codec::{ use core::{cmp::Ordering, ops::Deref}; -use super::{ManagedRef, MulToPrecision}; +use super::{ManagedBufferCachedBuilder, ManagedRef, MulToPrecision}; fn scaling_factor( num_decimals: NumDecimals, @@ -68,7 +71,7 @@ impl Decimals for ConstDecimals { } } -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct ManagedDecimal { pub(crate) data: BigUint, pub(crate) decimals: D, @@ -91,6 +94,10 @@ impl ManagedDecimal { self.decimals.num_decimals() } + pub fn scaling_factor(&self) -> ManagedRef<'static, M, BigUint> { + self.decimals.scaling_factor() + } + pub fn rescale(&self, scale_to: T) -> ManagedDecimal where M: ManagedTypeApi, @@ -123,7 +130,7 @@ impl ManagedDecimal { } pub fn from_big_float( - big_float: BigFloat, + big_float: &BigFloat, num_decimals: T, ) -> ManagedDecimal { let scaling_factor: &BigUint = &num_decimals.scaling_factor(); @@ -395,3 +402,61 @@ impl TypeAbi false } } +impl SCDisplay for ManagedDecimal { + fn fmt(&self, f: &mut F) { + let full_str_handle: M::ManagedBufferHandle = + use_raw_handle(const_handles::MBUF_TEMPORARY_1); + M::managed_type_impl().bi_to_string(self.data.handle.clone(), full_str_handle.clone()); + let len = M::managed_type_impl().mb_len(full_str_handle.clone()); + let nr_dec = self.decimals.num_decimals(); + + if len > nr_dec { + let temp_str_handle: M::ManagedBufferHandle = + use_raw_handle(const_handles::MBUF_TEMPORARY_2); + let _ = M::managed_type_impl().mb_copy_slice( + full_str_handle.clone(), + 0, + len - nr_dec, + temp_str_handle.clone(), + ); + f.append_managed_buffer(&ManagedBuffer::from_raw_handle( + temp_str_handle.get_raw_handle(), + )); + f.append_bytes(b"."); + let _ = M::managed_type_impl().mb_copy_slice( + full_str_handle.clone(), + len - nr_dec, + nr_dec, + temp_str_handle.clone(), + ); + f.append_managed_buffer(&ManagedBuffer::from_raw_handle( + temp_str_handle.get_raw_handle(), + )); + } else { + f.append_bytes(b"0."); + for _ in len..nr_dec { + f.append_bytes(b"0"); + } + f.append_managed_buffer(&ManagedBuffer::from_raw_handle( + full_str_handle.get_raw_handle(), + )); + } + } +} + +impl core::fmt::Display for ManagedDecimal { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut result = ManagedBufferCachedBuilder::::new_from_slice(&[]); + result.append_display(self); + core::fmt::Display::fmt(&result.into_managed_buffer(), f) + } +} + +impl core::fmt::Debug for ManagedDecimal { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("ManagedDecimal") + .field("handle", &self.data.handle.clone()) + .field("number", &self.to_string()) + .finish() + } +} diff --git a/framework/meta-lib/src/code_report_json.rs b/framework/meta-lib/src/code_report_json.rs new file mode 100644 index 0000000000..a0b997bb6e --- /dev/null +++ b/framework/meta-lib/src/code_report_json.rs @@ -0,0 +1,30 @@ +use serde::{Deserialize, Serialize}; + +use crate::tools::report_creator::ReportCreator; + +#[derive(Serialize, Deserialize, Default)] +#[serde(rename_all = "camelCase")] +pub struct CodeReportJson { + #[serde(default)] + pub path: String, + + #[serde(default)] + pub size: usize, + + #[serde(default)] + pub has_allocator: bool, + + #[serde(default)] + pub has_panic: String, +} + +impl CodeReportJson { + pub fn new(report: &ReportCreator, size: usize) -> CodeReportJson { + CodeReportJson { + path: report.path.clone(), + size, + has_allocator: report.has_allocator, + has_panic: report.has_panic.clone(), + } + } +} diff --git a/framework/meta-lib/src/contract/generate_proxy/proxy_gen_main.rs b/framework/meta-lib/src/contract/generate_proxy/proxy_gen_main.rs index d6c913a0e4..bcd425ae84 100644 --- a/framework/meta-lib/src/contract/generate_proxy/proxy_gen_main.rs +++ b/framework/meta-lib/src/contract/generate_proxy/proxy_gen_main.rs @@ -1,9 +1,7 @@ use colored::Colorize; use std::fs; -use multiversx_sc::abi::ContractAbi; - -use crate::contract::sc_config::ProxyConfigSerde; +use crate::contract::sc_config::proxy_config::ProxyConfig; use super::{ super::meta_config::MetaConfig, proxy_crate_gen::create_file, proxy_generator::ProxyGenerator, @@ -13,58 +11,37 @@ const PROXY_COMPARE_ERR_MSG: &str = "Contract has been modified and proxies have impl MetaConfig { pub fn generate_proxy(&mut self) { - let default_proxy = ProxyConfigSerde::new(); - write_proxy_with_explicit_path(&default_proxy, self); - for proxy_config in self.sc_config.proxy_configs.clone() { - write_proxy_with_explicit_path(&proxy_config, self); + for proxy_config in &self.sc_config.proxy_configs { + write_proxy_with_explicit_path(proxy_config, self); } } pub fn compare_proxy(&mut self) { - for proxy_config in self.sc_config.proxy_configs.clone() { - compare_proxy_explicit_path(&proxy_config, self); + for proxy_config in &self.sc_config.proxy_configs { + compare_proxy_explicit_path(proxy_config, self); } } } -fn compare_proxy_explicit_path(proxy_config: &ProxyConfigSerde, meta_config: &MetaConfig) { - let contract_abi = extract_contract_abi(proxy_config, meta_config); +fn compare_proxy_explicit_path(proxy_config: &ProxyConfig, meta_config: &MetaConfig) { let mut temp = Vec::::new(); - let mut proxy_generator = - ProxyGenerator::new(meta_config, &mut temp, proxy_config, contract_abi); + let mut proxy_generator = ProxyGenerator::new(meta_config, &mut temp, proxy_config); proxy_generator.write_proxy_to_file(); let existent_proxy_path = format!("../{}", proxy_config.path); - let existent_proxy = fs::read_to_string(existent_proxy_path).unwrap(); - let newly_gen_proxy = String::from_utf8(temp).unwrap(); + let existent_proxy = fs::read_to_string(existent_proxy_path); + + if let Ok(existent_proxy) = existent_proxy { + let newly_gen_proxy = String::from_utf8(temp).unwrap(); - if existent_proxy != newly_gen_proxy { - panic!("{}", PROXY_COMPARE_ERR_MSG.to_string().red()); + if existent_proxy != newly_gen_proxy { + panic!("{}", PROXY_COMPARE_ERR_MSG.to_string().red()); + } } } -fn write_proxy_with_explicit_path(proxy_config: &ProxyConfigSerde, meta_config: &MetaConfig) { - let contract_abi = extract_contract_abi(proxy_config, meta_config); +fn write_proxy_with_explicit_path(proxy_config: &ProxyConfig, meta_config: &MetaConfig) { let mut file = create_file(&proxy_config.path); - let mut proxy_generator = - ProxyGenerator::new(meta_config, &mut file, proxy_config, contract_abi); + let mut proxy_generator = ProxyGenerator::new(meta_config, &mut file, proxy_config); proxy_generator.write_proxy_to_file(); } - -fn extract_contract_abi<'a>( - proxy_config: &'a ProxyConfigSerde, - meta_config: &'a MetaConfig, -) -> &'a ContractAbi { - if proxy_config.variant.is_some() { - let variant = proxy_config.variant.as_ref().unwrap(); - for contract_variant in &meta_config.sc_config.contracts { - if variant == &contract_variant.public_name_snake_case() { - return &contract_variant.abi; - } - } - - panic!("No variant with name \"{}\" in multicontract", variant); - } - - &meta_config.original_contract_abi -} diff --git a/framework/meta-lib/src/contract/generate_proxy/proxy_generator.rs b/framework/meta-lib/src/contract/generate_proxy/proxy_generator.rs index d2e0b22036..dbbc3f7bb0 100644 --- a/framework/meta-lib/src/contract/generate_proxy/proxy_generator.rs +++ b/framework/meta-lib/src/contract/generate_proxy/proxy_generator.rs @@ -1,11 +1,11 @@ use std::fmt::Display; use multiversx_sc::abi::{ - ContractAbi, EndpointAbi, EnumVariantDescription, InputAbi, OutputAbi, StructFieldDescription, - TypeContents, TypeDescription, + EndpointAbi, EnumVariantDescription, InputAbi, OutputAbi, StructFieldDescription, TypeContents, + TypeDescription, }; -use crate::contract::{meta_config::MetaConfig, sc_config::ProxyConfigSerde}; +use crate::contract::{meta_config::MetaConfig, sc_config::proxy_config::ProxyConfig}; use super::proxy_process_type_name::{ extract_paths, extract_struct_crate, process_rust_type, proxy_methods_type_name, @@ -43,22 +43,19 @@ pub struct ProxyGenerator<'a> { #[allow(dead_code)] pub meta_config: &'a MetaConfig, pub file: Option<&'a mut dyn std::io::Write>, - pub proxy_config: &'a ProxyConfigSerde, - pub contract_abi: &'a ContractAbi, + pub proxy_config: &'a ProxyConfig, } impl<'a> ProxyGenerator<'a> { pub fn new( meta_config: &'a MetaConfig, file: &'a mut dyn std::io::Write, - proxy_config: &'a ProxyConfigSerde, - contract_abi: &'a ContractAbi, + proxy_config: &'a ProxyConfig, ) -> Self { Self { meta_config, file: Some(file), proxy_config, - contract_abi, } } @@ -83,14 +80,17 @@ impl<'a> ProxyGenerator<'a> { fn write_header(&mut self) { self.writeln(PRELUDE); - match &self.proxy_config.override_import { - Some(override_import) => self.writeln(override_import), - None => self.writeln(IMPORTS), + + if self.proxy_config.override_import.is_empty() { + self.writeln(IMPORTS); + return; } + + self.writeln(self.proxy_config.override_import.to_owned()); } fn write_tx_proxy_type_def(&mut self) { - let proxy_type_name = proxy_type_name(&self.contract_abi.name); + let proxy_type_name = proxy_type_name(&self.proxy_config.abi.name); self.writeln(format!( r#" pub struct {proxy_type_name};"# @@ -98,8 +98,8 @@ pub struct {proxy_type_name};"# } fn write_impl_for_tx_proxy(&mut self) { - let proxy_type_name = proxy_type_name(&self.contract_abi.name); - let proxy_methods_type_name = proxy_methods_type_name(&self.contract_abi.name); + let proxy_type_name = proxy_type_name(&self.proxy_config.abi.name); + let proxy_methods_type_name = proxy_methods_type_name(&self.proxy_config.abi.name); self.writeln(format!( r#" impl TxProxyTrait for {proxy_type_name} @@ -119,7 +119,7 @@ where } fn write_struct_tx_proxy_methods(&mut self) { - let proxy_methods_type_name = proxy_methods_type_name(&self.contract_abi.name); + let proxy_methods_type_name = proxy_methods_type_name(&self.proxy_config.abi.name); self.writeln(format!( r#" pub struct {proxy_methods_type_name} @@ -135,22 +135,22 @@ where } fn write_content(&mut self) { - if !self.contract_abi.constructors.is_empty() { + if !self.proxy_config.abi.constructors.is_empty() { self.write_constructors(); } - if !self.contract_abi.upgrade_constructors.is_empty() { + if !self.proxy_config.abi.upgrade_constructors.is_empty() { self.write_upgrades(); } - if !self.contract_abi.endpoints.is_empty() { + if !self.proxy_config.abi.endpoints.is_empty() { self.write_endpoints(); } } fn write_types(&mut self) { - for (_, type_description) in &self.contract_abi.type_descriptions.0 { - if self.contract_abi.get_crate_name_for_code() + for (_, type_description) in &self.proxy_config.abi.type_descriptions.0 { + if self.proxy_config.abi.get_crate_name_for_code() != extract_struct_crate(type_description.names.rust.as_str()) { continue; @@ -175,7 +175,7 @@ where } fn write_constructors(&mut self) { - let constructors: Vec = self.contract_abi.constructors.clone(); + let constructors: Vec = self.proxy_config.abi.constructors.clone(); self.write_header_impl_constructor(); for (i, constructor_abi) in constructors.into_iter().enumerate() { @@ -193,7 +193,8 @@ where fn write_upgrades(&mut self) { self.write_header_impl_upgrade(); for (i, upgrade) in self - .contract_abi + .proxy_config + .abi .upgrade_constructors .clone() .into_iter() @@ -211,7 +212,7 @@ where } fn write_endpoints(&mut self) { - let endpoints: Vec = self.contract_abi.endpoints.clone(); + let endpoints: Vec = self.proxy_config.abi.endpoints.clone(); self.write_header_impl_endpoints(); for (i, endpoint_abi) in endpoints.into_iter().enumerate() { @@ -227,7 +228,7 @@ where } fn write_header_impl_constructor(&mut self) { - let proxy_methods_type_name = proxy_methods_type_name(&self.contract_abi.name); + let proxy_methods_type_name = proxy_methods_type_name(&self.proxy_config.abi.name); self.writeln(format!( r#" #[rustfmt::skip] @@ -242,7 +243,7 @@ where } fn write_header_impl_upgrade(&mut self) { - let proxy_methods_type_name = proxy_methods_type_name(&self.contract_abi.name); + let proxy_methods_type_name = proxy_methods_type_name(&self.proxy_config.abi.name); self.writeln(format!( r#" #[rustfmt::skip] @@ -258,7 +259,7 @@ where } fn write_header_impl_endpoints(&mut self) { - let proxy_methods_type_name = proxy_methods_type_name(&self.contract_abi.name); + let proxy_methods_type_name = proxy_methods_type_name(&self.proxy_config.abi.name); self.writeln(format!( r#" #[rustfmt::skip] @@ -576,12 +577,10 @@ where fn rename_path_with_custome_config(&self, processed_type: &str) -> String { let mut renamed_processed_type = processed_type.to_owned(); - if let Some(paths_rename) = &self.proxy_config.path_rename { - for path_rename in paths_rename { - if processed_type.contains(&path_rename.from) { - renamed_processed_type = - renamed_processed_type.replace(&path_rename.from, &path_rename.to); - } + for path_rename in &self.proxy_config.path_rename { + if processed_type.contains(&path_rename.from) { + renamed_processed_type = + renamed_processed_type.replace(&path_rename.from, &path_rename.to); } } @@ -590,7 +589,7 @@ where fn process_paths(&self, paths: &Vec) -> Vec { let mut processed_paths: Vec = Vec::new(); - let crate_name = self.contract_abi.get_crate_name_for_code(); + let crate_name = self.proxy_config.abi.get_crate_name_for_code(); for path in paths { let type_rust_name = path.split("::").last().unwrap(); @@ -625,7 +624,7 @@ where pub mod tests { use multiversx_sc::abi::{BuildInfoAbi, ContractAbi, ContractCrateBuildAbi, FrameworkBuildAbi}; - use crate::contract::{meta_config::MetaConfig, sc_config::ProxyConfigSerde}; + use crate::contract::{meta_config::MetaConfig, sc_config::proxy_config::ProxyConfig}; use super::ProxyGenerator; @@ -641,12 +640,11 @@ pub mod tests { }; let original_contract_abi = ContractAbi::new(build_info, &[""], "contract-crate", false); - let meta_config = MetaConfig::create(original_contract_abi, false); + let meta_config = MetaConfig::create(original_contract_abi.clone(), false); let mut proxy_generator = ProxyGenerator { meta_config: &meta_config, file: None, - proxy_config: &ProxyConfigSerde::new(), - contract_abi: &meta_config.original_contract_abi, + proxy_config: &ProxyConfig::new_with_default_path(original_contract_abi), }; let cleaned_path_unsanitized = proxy_generator.clean_paths( @@ -673,12 +671,11 @@ pub mod tests { }; let original_contract_abi = ContractAbi::new(build_info, &[""], "contract-crate", false); - let meta_config = MetaConfig::create(original_contract_abi, false); + let meta_config = MetaConfig::create(original_contract_abi.clone(), false); let mut proxy_generator = ProxyGenerator { meta_config: &meta_config, file: None, - proxy_config: &ProxyConfigSerde::new(), - contract_abi: &meta_config.original_contract_abi, + proxy_config: &ProxyConfig::new_with_default_path(original_contract_abi), }; let cleaned_path_sanitized = proxy_generator.clean_paths( diff --git a/framework/meta-lib/src/contract/generate_snippets/snippet_crate_gen.rs b/framework/meta-lib/src/contract/generate_snippets/snippet_crate_gen.rs index fc02e3f648..0b9d9485e1 100644 --- a/framework/meta-lib/src/contract/generate_snippets/snippet_crate_gen.rs +++ b/framework/meta-lib/src/contract/generate_snippets/snippet_crate_gen.rs @@ -9,9 +9,9 @@ use crate::version_history; static SNIPPETS_SOURCE_FILE_NAME: &str = "interactor_main.rs"; static SC_CONFIG_PATH: &str = "../sc-config.toml"; static FULL_PROXY_ENTRY: &str = r#"[[proxy]] -path = "interact-rs/src/proxy.rs" +path = "interactor/src/proxy.rs" "#; -static PROXY_PATH: &str = "interact-rs/src/proxy.rs"; +static PROXY_PATH: &str = "interactor/src/proxy.rs"; pub(crate) fn create_snippets_folder(snippets_folder_path: &str) { // returns error if folder already exists, so we ignore the result diff --git a/framework/meta-lib/src/contract/meta_config.rs b/framework/meta-lib/src/contract/meta_config.rs index e26a4f4e16..b69a11a16a 100644 --- a/framework/meta-lib/src/contract/meta_config.rs +++ b/framework/meta-lib/src/contract/meta_config.rs @@ -13,7 +13,7 @@ use super::{ }; const OUTPUT_RELATIVE_PATH: &str = "../output"; -const SNIPPETS_RELATIVE_PATH: &str = "../interact-rs"; +const SNIPPETS_RELATIVE_PATH: &str = "../interactor"; const WASM_LIB_PATH: &str = "../wasm/src/lib.rs"; const WASM_NO_MANAGED_EI: &str = "wasm-no-managed-ei"; const WASM_NO_MANAGED_EI_LIB_PATH: &str = "../wasm-no-managed-ei/src/lib.rs"; diff --git a/framework/meta-lib/src/contract/sc_config.rs b/framework/meta-lib/src/contract/sc_config.rs index 2fac2e38eb..ff41a7655d 100644 --- a/framework/meta-lib/src/contract/sc_config.rs +++ b/framework/meta-lib/src/contract/sc_config.rs @@ -2,6 +2,7 @@ mod contract_variant; mod contract_variant_builder; mod contract_variant_settings; mod contract_variant_validate; +pub mod proxy_config; mod sc_config_model; mod sc_config_proxy; mod sc_config_serde; diff --git a/framework/meta-lib/src/contract/sc_config/contract_variant_builder.rs b/framework/meta-lib/src/contract/sc_config/contract_variant_builder.rs index bb6a439245..8bf9793f39 100644 --- a/framework/meta-lib/src/contract/sc_config/contract_variant_builder.rs +++ b/framework/meta-lib/src/contract/sc_config/contract_variant_builder.rs @@ -1,3 +1,4 @@ +use core::panic; use multiversx_sc::abi::{ContractAbi, EndpointAbi}; use std::{ collections::{BTreeSet, HashMap, HashSet}, @@ -9,9 +10,10 @@ use crate::ei::parse_check_ei; use super::{ contract_variant_settings::{parse_allocator, parse_stack_size}, + proxy_config::ProxyConfig, sc_config_model::SC_CONFIG_FILE_NAMES, ContractVariant, ContractVariantProfile, ContractVariantSerde, ContractVariantSettings, - ScConfig, ScConfigSerde, + ProxyConfigSerde, ScConfig, ScConfigSerde, }; /// Temporary structure, to help create instances of `ContractVariant`. Not publicly exposed. @@ -253,40 +255,114 @@ fn validate_contract_variants(contracts: &[ContractVariant]) { } } -impl ScConfig { - /// Assembles an `ContractVariantConfig` from a raw config object that was loaded via Serde. - /// - /// In most cases the config will be loaded from a .toml file, use `load_from_file` for that. - pub fn load_from_config(config: &ScConfigSerde, original_abi: &ContractAbi) -> Self { - let mut contract_builders: HashMap = config - .contracts - .iter() - .map(ContractVariantBuilder::map_from_config) - .collect(); +fn process_contracts(config: &ScConfigSerde, original_abi: &ContractAbi) -> Vec { + let mut contract_builders: HashMap = config + .contracts + .iter() + .map(ContractVariantBuilder::map_from_config) + .collect(); + + collect_and_process_endpoints( + &mut contract_builders, + original_abi, + &config.labels_for_contracts, + ); + + let mut contracts: Vec = contract_builders + .into_values() + .map(|builder| build_contract(builder, original_abi)) + .collect(); + + if contracts.is_empty() { + contracts.push(ContractVariant::default_from_abi(original_abi)); + } + set_main_contract_flag(&mut contracts, &config.settings.main); + validate_contract_variants(&contracts); + + contracts +} + +fn process_proxy_contracts(config: &ScConfigSerde, original_abi: &ContractAbi) -> Vec { + let mut proxy_contracts = Vec::new(); + + let main_contract = process_contracts(config, original_abi) + .into_iter() + .find(|contract| contract.main) + .unwrap(); + + proxy_contracts.push(ProxyConfig::new_with_default_path(main_contract.abi)); + + for proxy_config in &config.proxy { + let mut contract_builders = HashMap::new(); + + match &proxy_config.variant { + Some(variant) => { + let setting_contract = config + .contracts + .iter() + .find(|setting| setting.0.eq(variant)) + .unwrap_or_else(|| panic!("No contact with this name")); + let (contract_id, mut contract_builder) = + ContractVariantBuilder::map_from_config(setting_contract); + alter_builder_with_proxy_config(proxy_config, &mut contract_builder); + + contract_builders = HashMap::from([(contract_id, contract_builder)]); + }, + None => { + let mut contract_builder = ContractVariantBuilder::default(); + alter_builder_with_proxy_config(proxy_config, &mut contract_builder); + + contract_builders.insert(proxy_config.path.clone(), contract_builder); + }, + } + collect_and_process_endpoints( &mut contract_builders, original_abi, &config.labels_for_contracts, ); + if let Some((_, builder)) = contract_builders.into_iter().next() { + let contract = build_contract(builder, original_abi); - let mut contracts: Vec = contract_builders - .into_values() - .map(|builder| build_contract(builder, original_abi)) - .collect(); - if contracts.is_empty() { - contracts.push(ContractVariant::default_from_abi(original_abi)); + proxy_contracts.push(ProxyConfig::new( + proxy_config.path.to_owned(), + proxy_config.override_import.to_owned(), + proxy_config.path_rename.to_owned(), + contract.abi, + )); } - set_main_contract_flag(&mut contracts, &config.settings.main); - validate_contract_variants(&contracts); + } + + proxy_contracts +} + +impl ScConfig { + /// Assembles an `ContractVariantConfig` from a raw config object that was loaded via Serde. + /// + /// In most cases the config will be loaded from a .toml file, use `load_from_file` for that. + pub fn load_from_config(config: &ScConfigSerde, original_abi: &ContractAbi) -> Self { let default_contract_config_name = config.settings.main.clone().unwrap_or_default(); ScConfig { default_contract_config_name, - contracts, - proxy_configs: config.proxy.clone(), + contracts: process_contracts(config, original_abi), + proxy_configs: process_proxy_contracts(config, original_abi), } } } +fn alter_builder_with_proxy_config( + proxy_config: &ProxyConfigSerde, + contract_builder: &mut ContractVariantBuilder, +) { + let default = ContractVariantBuilder::default(); + + contract_builder.add_unlabelled = proxy_config + .add_unlabelled + .unwrap_or(default.add_unlabelled); + contract_builder.add_endpoints = proxy_config.add_endpoints.iter().cloned().collect(); + contract_builder.add_labels = proxy_config.add_labels.iter().cloned().collect(); +} + fn collect_and_process_endpoints( contract_builders: &mut HashMap, original_abi: &ContractAbi, diff --git a/framework/meta-lib/src/contract/sc_config/proxy_config.rs b/framework/meta-lib/src/contract/sc_config/proxy_config.rs new file mode 100644 index 0000000000..2097f50559 --- /dev/null +++ b/framework/meta-lib/src/contract/sc_config/proxy_config.rs @@ -0,0 +1,37 @@ +use multiversx_sc::abi::ContractAbi; + +use super::sc_config_proxy::PathRename; +const DEFAULT_PATH: &str = "/output/proxy.rs"; + +#[derive(Debug)] +pub struct ProxyConfig { + pub path: String, + pub override_import: String, + pub path_rename: Vec, + pub abi: ContractAbi, +} + +impl ProxyConfig { + pub fn new( + path: String, + override_imports: Option, + path_rename: Option>, + abi: ContractAbi, + ) -> Self { + ProxyConfig { + path, + override_import: override_imports.unwrap_or_default(), + path_rename: path_rename.unwrap_or_default(), + abi, + } + } + + pub fn new_with_default_path(abi: ContractAbi) -> Self { + ProxyConfig { + path: DEFAULT_PATH.to_string(), + override_import: String::new(), + path_rename: Vec::new(), + abi, + } + } +} diff --git a/framework/meta-lib/src/contract/sc_config/sc_config_model.rs b/framework/meta-lib/src/contract/sc_config/sc_config_model.rs index 076e91a2f7..8286abd5b9 100644 --- a/framework/meta-lib/src/contract/sc_config/sc_config_model.rs +++ b/framework/meta-lib/src/contract/sc_config/sc_config_model.rs @@ -1,5 +1,5 @@ use super::{ - contract_variant_validate::validate_contract_variant, sc_config_proxy::ProxyConfigSerde, + contract_variant_validate::validate_contract_variant, proxy_config::ProxyConfig, ContractVariant, }; @@ -18,7 +18,7 @@ pub const SC_CONFIG_FILE_NAMES: &[&str] = &["sc-config.toml", "multicontract.tom pub struct ScConfig { pub default_contract_config_name: String, pub contracts: Vec, - pub proxy_configs: Vec, + pub proxy_configs: Vec, } impl ScConfig { diff --git a/framework/meta-lib/src/contract/sc_config/sc_config_proxy.rs b/framework/meta-lib/src/contract/sc_config/sc_config_proxy.rs index 88721fe6e7..ada8b230cc 100644 --- a/framework/meta-lib/src/contract/sc_config/sc_config_proxy.rs +++ b/framework/meta-lib/src/contract/sc_config/sc_config_proxy.rs @@ -2,7 +2,7 @@ use serde::Deserialize; const DEFAULT_PATH: &str = "/output/proxy.rs"; -#[derive(Deserialize, Default, Debug, Clone, PartialEq, Eq)] +#[derive(Deserialize, Default, Debug, Clone, PartialEq, Eq, Hash)] #[serde(deny_unknown_fields)] pub struct ProxyConfigSerde { #[serde(default)] @@ -18,6 +18,17 @@ pub struct ProxyConfigSerde { #[serde(default)] pub variant: Option, + + #[serde(rename = "add-unlabelled")] + pub add_unlabelled: Option, + + #[serde(default)] + #[serde(rename = "add-labels")] + pub add_labels: Vec, + + #[serde(default)] + #[serde(rename = "add-endpoints")] + pub add_endpoints: Vec, } impl ProxyConfigSerde { @@ -27,11 +38,14 @@ impl ProxyConfigSerde { override_import: None, path_rename: None, variant: None, + add_unlabelled: None, + add_labels: Vec::new(), + add_endpoints: Vec::new(), } } } -#[derive(Deserialize, Default, Debug, Clone, PartialEq, Eq)] +#[derive(Deserialize, Default, Debug, Clone, PartialEq, Eq, Hash)] pub struct PathRename { #[serde(default)] pub from: String, diff --git a/framework/meta-lib/src/contract/sc_config/wasm_build.rs b/framework/meta-lib/src/contract/sc_config/wasm_build.rs index d4b5f9d1de..5b318da9a0 100644 --- a/framework/meta-lib/src/contract/sc_config/wasm_build.rs +++ b/framework/meta-lib/src/contract/sc_config/wasm_build.rs @@ -95,11 +95,10 @@ impl ContractVariant { let mut abi = ContractAbiJson::from(&self.abi); let build_info = core::mem::take(&mut abi.build_info).unwrap(); let ei_check_json = EiCheckJson::new(&self.settings.check_ei, wasm_info.ei_check); - let report = ReportInfoJson::new(&wasm_info, ei_check_json); + let report = ReportInfoJson::new(&wasm_info, ei_check_json, compiled_bytes.len()); let mxsc_file_json = MxscFileJson { build_info, abi, - size: compiled_bytes.len(), code: hex::encode(compiled_bytes), report, }; diff --git a/framework/meta-lib/src/lib.rs b/framework/meta-lib/src/lib.rs index ab24acae54..e33c2cfb7b 100644 --- a/framework/meta-lib/src/lib.rs +++ b/framework/meta-lib/src/lib.rs @@ -1,6 +1,7 @@ pub mod abi_json; pub mod cargo_toml_contents; pub mod cli; +mod code_report_json; pub mod contract; pub mod ei; pub mod ei_check_json; diff --git a/framework/meta-lib/src/mxsc_file_json.rs b/framework/meta-lib/src/mxsc_file_json.rs index 47cf44ca28..84a60d0afa 100644 --- a/framework/meta-lib/src/mxsc_file_json.rs +++ b/framework/meta-lib/src/mxsc_file_json.rs @@ -11,7 +11,6 @@ use crate::{ pub struct MxscFileJson { pub build_info: BuildInfoAbiJson, pub abi: ContractAbiJson, - pub size: usize, pub code: String, pub report: ReportInfoJson, } diff --git a/framework/meta-lib/src/report_info_json.rs b/framework/meta-lib/src/report_info_json.rs index 3f0f5d7da5..3ebbda0690 100644 --- a/framework/meta-lib/src/report_info_json.rs +++ b/framework/meta-lib/src/report_info_json.rs @@ -1,6 +1,6 @@ use serde::{Deserialize, Serialize}; -use crate::{ei_check_json::EiCheckJson, tools::WasmInfo}; +use crate::{code_report_json::CodeReportJson, ei_check_json::EiCheckJson, tools::WasmInfo}; #[derive(Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -9,19 +9,19 @@ pub struct ReportInfoJson { #[serde(skip_serializing_if = "Vec::is_empty")] pub imports: Vec, - #[serde(default)] - pub memory_allocation_error: bool, - #[serde(default)] pub is_mem_grow: bool, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] pub ei_check: Option, + + #[serde(default)] + pub code_report: CodeReportJson, } impl ReportInfoJson { - pub fn new(wasm_info: &WasmInfo, ei_check_info: Option) -> Self { + pub fn new(wasm_info: &WasmInfo, ei_check_info: Option, size: usize) -> Self { let ei_check = if wasm_info.imports.is_empty() { None } else { @@ -30,9 +30,9 @@ impl ReportInfoJson { ReportInfoJson { imports: wasm_info.imports.iter().map(|i| i.to_string()).collect(), - memory_allocation_error: wasm_info.allocator_trigger, is_mem_grow: wasm_info.memory_grow_flag, ei_check, + code_report: CodeReportJson::new(&wasm_info.report, size), } } } diff --git a/framework/meta-lib/src/tools.rs b/framework/meta-lib/src/tools.rs index 5be426c21e..e0a8962d9b 100644 --- a/framework/meta-lib/src/tools.rs +++ b/framework/meta-lib/src/tools.rs @@ -1,5 +1,6 @@ mod find_workspace; mod git_describe; +pub(crate) mod report_creator; pub mod twiggy; mod wasm_extractor; mod wasm_opt; diff --git a/framework/meta-lib/src/tools/report_creator.rs b/framework/meta-lib/src/tools/report_creator.rs new file mode 100644 index 0000000000..37af10fa4e --- /dev/null +++ b/framework/meta-lib/src/tools/report_creator.rs @@ -0,0 +1,10 @@ +pub const WITH_MESSAGE: &str = "with message"; +pub const WITHOUT_MESSAGE: &str = "without message"; + +pub struct ReportCreator { + pub path: String, + pub has_allocator: bool, + pub has_panic: String, +} + +impl ReportCreator {} diff --git a/framework/meta-lib/src/tools/wasm_extractor.rs b/framework/meta-lib/src/tools/wasm_extractor.rs index c8b9943190..50d5b78aff 100644 --- a/framework/meta-lib/src/tools/wasm_extractor.rs +++ b/framework/meta-lib/src/tools/wasm_extractor.rs @@ -6,14 +6,19 @@ use wasmparser::{ use crate::ei::EIVersion; +use super::report_creator::{ReportCreator, WITHOUT_MESSAGE, WITH_MESSAGE}; + +const PANIC_WITH_MESSAGE: &[u8; 16] = b"panic occurred: "; +const PANIC_WITHOUT_MESSAGE: &[u8; 14] = b"panic occurred"; const ERROR_FAIL_ALLOCATOR: &[u8; 27] = b"memory allocation forbidden"; const MEMORY_GROW_OPCODE: u8 = 0x40; pub struct WasmInfo { pub imports: Vec, - pub allocator_trigger: bool, pub ei_check: bool, pub memory_grow_flag: bool, + pub has_format: bool, + pub report: ReportCreator, } impl WasmInfo { @@ -25,11 +30,17 @@ impl WasmInfo { let wasm_data = fs::read(output_wasm_path) .expect("error occured while extracting information from .wasm: file not found"); - populate_wasm_info(wasm_data, extract_imports_enabled, check_ei) + populate_wasm_info( + output_wasm_path.to_string(), + wasm_data, + extract_imports_enabled, + check_ei, + ) } } fn populate_wasm_info( + path: String, wasm_data: Vec, extract_imports_enabled: bool, check_ei: &Option, @@ -38,6 +49,7 @@ fn populate_wasm_info( let mut allocator_trigger = false; let mut ei_check = false; let mut memory_grow_flag = false; + let mut has_panic = "none"; let parser = Parser::new(0); for payload in parser.parse_all(&wasm_data) { @@ -47,7 +59,12 @@ fn populate_wasm_info( ei_check = is_ei_valid(imports.clone(), check_ei); }, Payload::DataSection(data_section) => { - allocator_trigger = is_fail_allocator_triggered(data_section); + allocator_trigger = is_fail_allocator_triggered(data_section.clone()); + if is_panic_with_message_triggered(data_section.clone()) { + has_panic = WITH_MESSAGE; + } else if is_panic_without_message_triggered(data_section) { + has_panic = WITHOUT_MESSAGE; + } }, Payload::CodeSectionEntry(code_section) => { memory_grow_flag = is_mem_grow(code_section); @@ -56,11 +73,18 @@ fn populate_wasm_info( } } + let report = ReportCreator { + path, + has_allocator: allocator_trigger, + has_panic: has_panic.to_string(), + }; + Ok(WasmInfo { imports, - allocator_trigger, ei_check, memory_grow_flag, + has_format: true, + report, }) } @@ -85,6 +109,34 @@ fn is_fail_allocator_triggered(data_section: DataSectionReader) -> bool { false } +fn is_panic_with_message_triggered(data_section: DataSectionReader) -> bool { + for data_fragment in data_section.into_iter().flatten() { + if data_fragment + .data + .windows(PANIC_WITH_MESSAGE.len()) + .any(|data| data == PANIC_WITH_MESSAGE) + { + return true; + } + } + + false +} + +fn is_panic_without_message_triggered(data_section: DataSectionReader) -> bool { + for data_fragment in data_section.into_iter().flatten() { + if data_fragment + .data + .windows(PANIC_WITHOUT_MESSAGE.len()) + .any(|data| data == PANIC_WITHOUT_MESSAGE) + { + return true; + } + } + + false +} + pub fn extract_imports( import_section: ImportSectionReader, import_extraction_enabled: bool, diff --git a/framework/scenario/Cargo.toml b/framework/scenario/Cargo.toml index b41d274621..00d7d6c2ad 100644 --- a/framework/scenario/Cargo.toml +++ b/framework/scenario/Cargo.toml @@ -29,11 +29,11 @@ serde_json = "1.0" pathdiff = "0.2.1" itertools = "0.12.0" colored = "2.0" -clap = { version = "4.4.7", features = ["derive"] } -tokio = { version = "1.24", features = ["full"] } unwrap-infallible = "0.1.5" [features] +default = ["wasm-incopatible"] +wasm-incopatible = ["multiversx-chain-vm/wasm-incopatible"] run-go-tests = [] [dependencies.multiversx-sc] @@ -55,7 +55,3 @@ version = "0.2.0" [dependencies.multiversx-chain-vm] version = "=0.8.4" path = "../../vm" - -[dependencies.multiversx-sdk] -version = "=0.4.1" -path = "../../sdk/core" diff --git a/framework/scenario/src/scenario/model/transaction/tx_response.rs b/framework/scenario/src/scenario/model/transaction/tx_response.rs index 46806b1183..fd9721721f 100644 --- a/framework/scenario/src/scenario/model/transaction/tx_response.rs +++ b/framework/scenario/src/scenario/model/transaction/tx_response.rs @@ -1,6 +1,5 @@ use multiversx_chain_vm::tx_mock::TxResult; use multiversx_sc::types::Address; -use multiversx_sdk::data::transaction::{ApiLogs, ApiSmartContractResult}; use super::{Log, TxExpect, TxResponseStatus}; @@ -21,10 +20,6 @@ pub struct TxResponse { pub gas: u64, /// The refund of the transaction. pub refund: u64, - /// The smart contract results of the transaction. - pub api_scrs: Vec, - /// The api logs of the transaction. - pub api_logs: Option, } impl TxResponse { diff --git a/framework/scenario/tests/big_float_test.rs b/framework/scenario/tests/big_float_test.rs new file mode 100644 index 0000000000..2b98cbae41 --- /dev/null +++ b/framework/scenario/tests/big_float_test.rs @@ -0,0 +1,109 @@ +use multiversx_sc::types::{BigFloat, BigUint}; +use multiversx_sc_scenario::api::StaticApi; + +#[test] +fn big_float_overflow_test_rs() { + let exp = 1_080i32; + + let first = BigFloat::::from_sci(1_005, -3) + .pow(exp) + .to_fixed_point(&(100_000_000_000_000_000i64.into())) + .into_big_uint(); + + let second = BigFloat::::from_sci(1_005, -3) + .pow(exp) + .to_fixed_point(&(10_000_000_000_000_000i64.into())) + .into_big_uint(); + + let third_float = BigFloat::::from_sci(1_005, -3) + .pow(exp) + .to_managed_decimal(17usize); + let third = third_float.into_raw_units(); + + let forth_float = BigFloat::::from_sci(1_005, -3) + .pow(exp) + .to_managed_decimal(16usize); + let forth = forth_float.into_raw_units(); + + assert_eq!( + first.unwrap_or_sc_panic("unwrap failed"), + /* overflow */ + BigUint::from(9223372036854775807u64) + ); + + assert_eq!( + second.unwrap_or_sc_panic("unwrap failed"), + BigUint::from(2184473079534488064u64) + ); + + assert_eq!( + third, + /* overflow */ + &BigUint::from(9223372036854775807u64) + ); + + assert_eq!(forth, &BigUint::from(2184473079534488064u64)); +} + +#[test] +fn big_float_ln_test_rs() { + let x = BigFloat::::from(23i64); + let ln_x = x.ln().unwrap(); + assert_eq!(ln_x.to_managed_decimal(9usize).to_string(), "3.135514648"); + assert!(ln_x.is_close( + &BigFloat::from_frac(3135514648, 1_000_000_000), // 3.135514648 + &BigFloat::from_frac(1, 1_000_000_000) + )); + + let big = BigFloat::::from(382747812i64); + let ln_big = big.ln().unwrap(); + assert_eq!( + ln_big.to_managed_decimal(9usize).to_string(), + "19.762913880" + ); + assert!(ln_big.is_close( + &BigFloat::from_frac(19762913880, 1_000_000_000), // 19.762913880 + &BigFloat::from_frac(1, 1_000_000_000) + )); + + let biggest = BigFloat::::from(999999999i64); + let ln_biggest = biggest.ln().unwrap(); + assert_eq!( + ln_biggest.to_managed_decimal(9usize).to_string(), + "20.723319778" + ); + assert!(ln_biggest.is_close( + &BigFloat::from_frac(20723319778, 1_000_000_000), // 20.723319778 + &BigFloat::from_frac(1, 1_000_000_000) + )); + + let small = BigFloat::::from_frac(3i64, 2i64); + let ln_small = small.ln().unwrap(); + assert_eq!( + ln_small.to_managed_decimal(9usize).to_string(), + "0.405448248" + ); + assert!(ln_small.is_close( + &BigFloat::from_frac(405448248, 1_000_000_000), // 0.405448248 + &BigFloat::from_frac(1, 1_000_000_000) + )); + + let smallest = BigFloat::::from(1i64); + let ln_smallest = smallest.ln().unwrap(); + assert_eq!( + ln_smallest.to_managed_decimal(9usize).to_string(), + "0.000000000" + ); + assert!(ln_smallest.is_close( + &BigFloat::from(0i64), // 0.0 + &BigFloat::from_frac(1, 100_000_000) + )); + + let y = BigFloat::::from_frac(11i64, 10i64); + let ln_y = y.ln().unwrap(); + assert_eq!(ln_y.to_managed_decimal(9usize).to_string(), "0.095251830"); + assert!(ln_y.is_close( + &BigFloat::from_frac(95251830, 1_000_000_000), // 0.095310179 + &BigFloat::from_frac(1, 1_000_000_000) + )); +} diff --git a/framework/scenario/tests/big_uint_test.rs b/framework/scenario/tests/big_uint_test.rs new file mode 100644 index 0000000000..60ad0ab78f --- /dev/null +++ b/framework/scenario/tests/big_uint_test.rs @@ -0,0 +1,22 @@ +use multiversx_sc::types::BigUint; +use multiversx_sc_scenario::api::StaticApi; + +fn assert_big_uint_ln(x: u32, ln_str: &str) { + let x = BigUint::::from(x); + let ln_x = x.ln(); + assert_eq!(ln_x.unwrap().to_string(), ln_str); +} + +#[test] +fn test_big_uint_ln() { + assert_big_uint_ln(23, "3.135514649"); // vs. 3.1354942159291497 first 6 decimals are ok + + assert_big_uint_ln(1, "0.000060599"); + assert_big_uint_ln(2, "0.693207779"); // vs. 0.6931471805599453 + assert_big_uint_ln(3, "1.098595430"); // vs. 1.0986122886681096 + assert_big_uint_ln(4, "1.386354959"); // vs. 1.3862943611198906 + assert_big_uint_ln(5, "1.609481340"); // vs. 1.6094379124341003 + assert_big_uint_ln(6, "1.791742610"); // vs. 1.791759469228055 + + assert_big_uint_ln(1000, "6.907784913"); // vs. 6.907755278982137 +} diff --git a/framework/scenario/tests/managed_decimal_test.rs b/framework/scenario/tests/managed_decimal_test.rs index 04aa909b33..ce02758e34 100644 --- a/framework/scenario/tests/managed_decimal_test.rs +++ b/framework/scenario/tests/managed_decimal_test.rs @@ -64,11 +64,9 @@ pub fn test_managed_decimal() { ); let float_1 = BigFloat::::from_frac(3i64, 2i64); - let fixed_float_1 = ManagedDecimal::>::from_big_float( - float_1.clone(), - ConstDecimals::<1>, - ); - let fixed_float_2 = ManagedDecimal::::from_big_float(float_1, 1usize); + let fixed_float_1 = + ManagedDecimal::>::from_big_float(&float_1, ConstDecimals::<1>); + let fixed_float_2 = ManagedDecimal::::from_big_float(&float_1, 1usize); assert_eq!( fixed_float_1, diff --git a/framework/snippets/src/network_response.rs b/framework/snippets/src/network_response.rs index f7f0b962df..d505e7a525 100644 --- a/framework/snippets/src/network_response.rs +++ b/framework/snippets/src/network_response.rs @@ -13,29 +13,19 @@ const LOG_IDENTIFIER_SIGNAL_ERROR: &str = "signalError"; /// Creates a [`TxResponse`] from a [`TransactionOnNetwork`]. pub fn parse_tx_response(tx: TransactionOnNetwork) -> TxResponse { - let mut response = TxResponse { - api_scrs: tx.smart_contract_results.unwrap_or_default(), - api_logs: tx.logs, - ..Default::default() - }; - - response.tx_error = process_signal_error(&response); - if !response.tx_error.is_success() { - return response; + let tx_error = process_signal_error(&tx); + if !tx_error.is_success() { + return TxResponse { + tx_error, + ..Default::default() + }; } - process( - &mut response, - tx.sender.to_bytes(), - tx.nonce, - tx.processing_type_on_destination, - ); - - response + process_success(&tx) } -fn process_signal_error(tx_response: &TxResponse) -> TxResponseStatus { - if let Some(event) = find_log(tx_response, LOG_IDENTIFIER_SIGNAL_ERROR) { +fn process_signal_error(tx: &TransactionOnNetwork) -> TxResponseStatus { + if let Some(event) = find_log(tx, LOG_IDENTIFIER_SIGNAL_ERROR) { let topics = event.topics.as_ref(); if let Some(error) = process_topics_error(topics) { return TxResponseStatus::signal_error(&error); @@ -49,34 +39,27 @@ fn process_signal_error(tx_response: &TxResponse) -> TxResponseStatus { TxResponseStatus::default() } -fn process( - tx_response: &mut TxResponse, - sender_address: [u8; 32], - nonce: u64, - processing_type_on_destination: String, -) { - process_out(tx_response); - process_new_deployed_address( - tx_response, - sender_address, - nonce, - processing_type_on_destination, - ); - process_new_issued_token_identifier(tx_response); +fn process_success(tx: &TransactionOnNetwork) -> TxResponse { + TxResponse { + out: process_out(tx), + new_deployed_address: process_new_deployed_address(tx), + new_issued_token_identifier: process_new_issued_token_identifier(tx), + ..Default::default() + } } -fn process_out(tx_response: &mut TxResponse) { - let out_scr = tx_response.api_scrs.iter().find(is_out_scr); +fn process_out(tx: &TransactionOnNetwork) -> Vec> { + let out_scr = tx.smart_contract_results.iter().find(is_out_scr); if let Some(out_scr) = out_scr { - tx_response.out = decode_scr_data_or_panic(&out_scr.data); - } else if let Some(data) = process_out_from_log(tx_response) { - tx_response.out = data + decode_scr_data_or_panic(&out_scr.data) + } else { + process_out_from_log(tx).unwrap_or_default() } } -fn process_out_from_log(tx_response: &TxResponse) -> Option>> { - if let Some(logs) = &tx_response.api_logs { +fn process_out_from_log(tx: &TransactionOnNetwork) -> Option>> { + if let Some(logs) = &tx.logs { logs.events.iter().rev().find_map(|event| { if event.identifier == "writeLog" { if let Some(data) = &event.data { @@ -96,17 +79,13 @@ fn process_out_from_log(tx_response: &TxResponse) -> Option>> { } } -fn process_new_deployed_address( - tx_response: &mut TxResponse, - sender_address_bytes: [u8; 32], - nonce: u64, - processing_type_on_destination: String, -) { - if processing_type_on_destination != SC_DEPLOY_PROCESSING_TYPE { - return; +fn process_new_deployed_address(tx: &TransactionOnNetwork) -> Option
{ + if tx.processing_type_on_destination != SC_DEPLOY_PROCESSING_TYPE { + return None; } - let sender_nonce_bytes = nonce.to_le_bytes(); + let sender_address_bytes = tx.sender.to_bytes(); + let sender_nonce_bytes = tx.nonce.to_le_bytes(); let mut bytes_to_hash: Vec = Vec::new(); bytes_to_hash.extend_from_slice(&sender_address_bytes); bytes_to_hash.extend_from_slice(&sender_nonce_bytes); @@ -120,17 +99,17 @@ fn process_new_deployed_address( address[10..30].copy_from_slice(&address_keccak[10..30]); address[30..32].copy_from_slice(&sender_address_bytes[30..32]); - tx_response.new_deployed_address = Some(Address::from(address)); + Some(Address::from(address)) } -fn process_new_issued_token_identifier(tx_response: &mut TxResponse) { - for scr in tx_response.api_scrs.iter() { +fn process_new_issued_token_identifier(tx: &TransactionOnNetwork) -> Option { + for scr in tx.smart_contract_results.iter() { if scr.sender.to_bech32_string().unwrap() != ESDTSystemSCAddress.to_bech32_string() { continue; } - let Some(prev_tx) = tx_response - .api_scrs + let Some(prev_tx) = tx + .smart_contract_results .iter() .find(|e| e.hash == scr.prev_tx_hash) else { @@ -155,30 +134,18 @@ fn process_new_issued_token_identifier(tx_response: &mut TxResponse) { if scr.data.starts_with("ESDTTransfer@") { let encoded_tid = scr.data.split('@').nth(1); - if encoded_tid.is_none() { - return; - } - - tx_response.new_issued_token_identifier = - Some(String::from_utf8(hex::decode(encoded_tid.unwrap()).unwrap()).unwrap()); - - break; + return Some(String::from_utf8(hex::decode(encoded_tid?).unwrap()).unwrap()); } else if scr.data.starts_with("@00@") { let encoded_tid = scr.data.split('@').nth(2); - if encoded_tid.is_none() { - return; - } - - tx_response.new_issued_token_identifier = - Some(String::from_utf8(hex::decode(encoded_tid.unwrap()).unwrap()).unwrap()); - - break; + return Some(String::from_utf8(hex::decode(encoded_tid?).unwrap()).unwrap()); } } + + None } -fn find_log<'a>(tx_response: &'a TxResponse, log_identifier: &str) -> Option<&'a Events> { - if let Some(logs) = &tx_response.api_logs { +fn find_log<'a>(tx: &'a TransactionOnNetwork, log_identifier: &str) -> Option<&'a Events> { + if let Some(logs) = &tx.logs { logs.events .iter() .find(|event| event.identifier == log_identifier) diff --git a/framework/snippets/tests/test_tx_multiple_sc_results.rs b/framework/snippets/tests/test_tx_multiple_sc_results.rs index 25e6fc477a..4fee781b7f 100644 --- a/framework/snippets/tests/test_tx_multiple_sc_results.rs +++ b/framework/snippets/tests/test_tx_multiple_sc_results.rs @@ -281,7 +281,9 @@ fn test_transaction_multiple_sc_results() { .data .unwrap() .transaction; - let tx_response = network_response::parse_tx_response(tx_on_network); - assert_eq!(tx_response.api_scrs.len(), 4usize); - assert!(is_out_scr(&tx_response.api_scrs.get(2).unwrap())); + assert_eq!(tx_on_network.smart_contract_results.len(), 4usize); + assert!(is_out_scr( + &tx_on_network.smart_contract_results.get(2).unwrap() + )); + let _ = network_response::parse_tx_response(tx_on_network); } diff --git a/sdk/core/src/data/transaction.rs b/sdk/core/src/data/transaction.rs index ed0a51b8df..3ee2f25684 100644 --- a/sdk/core/src/data/transaction.rs +++ b/sdk/core/src/data/transaction.rs @@ -80,7 +80,8 @@ pub struct TransactionOnNetwork { pub status: String, pub hyperblock_nonce: Option, pub hyperblock_hash: Option, - pub smart_contract_results: Option>, + #[serde(default)] + pub smart_contract_results: Vec, pub logs: Option, } diff --git a/tools/plotter/.gitignore b/tools/plotter/.gitignore new file mode 100644 index 0000000000..769dfbb4ba --- /dev/null +++ b/tools/plotter/.gitignore @@ -0,0 +1,3 @@ +/target +.*.sw* +.vscode/* diff --git a/tools/plotter/Cargo.toml b/tools/plotter/Cargo.toml new file mode 100644 index 0000000000..9f116ae4a5 --- /dev/null +++ b/tools/plotter/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "sc-plotter-wasm" +version = "0.1.0" +authors = ["Hao Hou "] +edition = "2018" +publish = false + +[lib] +crate-type=["cdylib"] + +[dependencies] +plotters = "^0.3.2" +wasm-bindgen = "0.2.78" +wee_alloc = "0.4.5" +web-sys = { version = "0.3.39", features = ["HtmlCanvasElement"] } +plotters-canvas = "^0.3.0" + +[profile.release] +lto = true + +[dependencies.multiversx-sc] +version = "=0.50.3" +path = "../../framework/base" + +[dependencies.multiversx-sc-scenario] +version = "=0.50.3" +path = "../../framework/scenario" +default-features = false diff --git a/tools/plotter/README.md b/tools/plotter/README.md new file mode 100644 index 0000000000..cfe2983da2 --- /dev/null +++ b/tools/plotter/README.md @@ -0,0 +1,54 @@ +# Example Project of Plotters + WASM + +This is a minimal project that uses Plotters in WASM application. + +- For more information about Plotters project, check our [core repository](https://github.com/plotters-rs/plotters). + +- This demo has been deployed at this [link](https://plotters-rs.github.io/wasm-demo/www/index.html). + +## Try this example locally + +To build the demo you need [wasm-pack](https://rustwasm.github.io/docs/book/game-of-life/setup.html). + +Then you can run it locally either using `npm` and `webpack-dev-server` or +just with static web server. + +The following script will install needed software and run the server via `npm`. +``` +./start-server.sh +``` + +For Windows users without Bash, `start-server.bat` can be used to +launch the server. + +``` +start-server.bat +``` + +## Developing with NPM +Please use [rust-wasm guide](https://rustwasm.github.io/docs/book/game-of-life/setup.html) for initial setup . +Then you can run the demo locally using `npm`: +```bash +wasm-pack build +cd www +npm install +npm start +``` + +This will start a dev server which will automatically reload your page +whenever you change anything in `www` directory. To update `rust` code +call `wasm-pack build` manually. + +## Developing without dependenices +If you don't want to use `npm` here's how you can run the example +using any web server. We are using rust [basic-http-server](https://github.com/brson/basic-http-server), but +any web server will do. + +```bash +# Install web server (instead you can use your local nginx for example) +cargo install basic-http-server +wasm-pack build --target web # Note `--target web` +basic-http-server +``` + +Then open http://127.0.0.1:4000/www diff --git a/tools/plotter/build-wasm.sh b/tools/plotter/build-wasm.sh new file mode 100755 index 0000000000..fc7fe6fb1b --- /dev/null +++ b/tools/plotter/build-wasm.sh @@ -0,0 +1,18 @@ +#!/bin/bash +set -e + +CONFIG=release + +rustup target add wasm32-unknown-unknown + +if [ -z "$(cargo install --list | grep wasm-pack)" ] +then + cargo install wasm-pack +fi + +if [ "${CONFIG}" = "release" ] +then + wasm-pack build +else + wasm-pack build --release +fi diff --git a/tools/plotter/src/lib.rs b/tools/plotter/src/lib.rs new file mode 100644 index 0000000000..8b68884dfd --- /dev/null +++ b/tools/plotter/src/lib.rs @@ -0,0 +1,68 @@ +#![allow(clippy::type_complexity)] + +use wasm_bindgen::prelude::*; +use web_sys::HtmlCanvasElement; + +pub mod logarithm_bf; +pub mod logarithm_bu; + +#[global_allocator] +static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; + +/// Type alias for the result of a drawing function. +pub type DrawResult = Result>; + +/// Type used on the JS side to convert screen coordinates to chart +/// coordinates. +#[wasm_bindgen] +pub struct Chart { + convert: Box Option<(f64, f64)>>, +} + +/// Result of screen to chart coordinates conversion. +#[wasm_bindgen] +pub struct Point { + pub x: f64, + pub y: f64, +} + +#[wasm_bindgen] +impl Chart { + /// Draw provided functions on the canvas. + /// Return `Chart` struct suitable for coordinate conversion. + pub fn ln_big_uint(canvas: HtmlCanvasElement, max_x: f32) -> Result { + let map_coord = logarithm_bu::draw_bu_logs(canvas, max_x).map_err(|err| err.to_string())?; + Ok(Chart { + convert: Box::new(move |coord| map_coord(coord).map(|(x, y)| (x.into(), y.into()))), + }) + } + + pub fn ln_big_uint_error(canvas: HtmlCanvasElement, max_x: f32) -> Result { + let map_coord = + logarithm_bu::draw_bu_error(canvas, max_x).map_err(|err| err.to_string())?; + Ok(Chart { + convert: Box::new(move |coord| map_coord(coord).map(|(x, y)| (x.into(), y.into()))), + }) + } + + pub fn ln_big_float(canvas: HtmlCanvasElement, max_x: f32) -> Result { + let map_coord = logarithm_bf::draw_bf_logs(canvas, max_x).map_err(|err| err.to_string())?; + Ok(Chart { + convert: Box::new(move |coord| map_coord(coord).map(|(x, y)| (x.into(), y.into()))), + }) + } + + pub fn ln_big_float_error(canvas: HtmlCanvasElement, max_x: f32) -> Result { + let map_coord = + logarithm_bf::draw_bf_error(canvas, max_x).map_err(|err| err.to_string())?; + Ok(Chart { + convert: Box::new(move |coord| map_coord(coord).map(|(x, y)| (x.into(), y.into()))), + }) + } + + /// This function can be used to convert screen coordinates to + /// chart coordinates. + pub fn coord(&self, x: i32, y: i32) -> Option { + (self.convert)((x, y)).map(|(x, y)| Point { x, y }) + } +} diff --git a/tools/plotter/src/logarithm_bf.rs b/tools/plotter/src/logarithm_bf.rs new file mode 100644 index 0000000000..e3e70f57ec --- /dev/null +++ b/tools/plotter/src/logarithm_bf.rs @@ -0,0 +1,107 @@ +use crate::DrawResult; +use multiversx_sc::types::BigFloat; +use multiversx_sc_scenario::api::StaticApi; +use plotters::prelude::*; +use plotters_canvas::CanvasBackend; +use web_sys::HtmlCanvasElement; + +pub fn draw_bf_logs( + canvas: HtmlCanvasElement, + max_x: f32, +) -> DrawResult Option<(f32, f32)>> { + let root = CanvasBackend::with_canvas_object(canvas) + .unwrap() + .into_drawing_area(); + + let font: FontDesc = ("sans-serif", 20.0).into(); + + root.fill(&WHITE)?; + + let mut chart = ChartBuilder::on(&root) + .margin(20u32) + .caption(format!("y=ln(x), x=1..{max_x}"), font) + .x_label_area_size(30u32) + .y_label_area_size(30u32) + .build_cartesian_2d(0f32..max_x, -5f32..5f32)?; + + chart.configure_mesh().x_labels(3).y_labels(3).draw()?; + + const RANGE_MAX: i32 = 1000; + chart.draw_series(LineSeries::new( + (0..=RANGE_MAX) + .map(|x| x as f32 * max_x / RANGE_MAX as f32) + .map(|x| (x, ln_baseline(x))), + &RED, + ))?; + + chart.draw_series(LineSeries::new( + (0..=RANGE_MAX) + .map(|x| x as f32 * max_x / RANGE_MAX as f32) + .map(|x| (x, big_float_ln(x))), + &GREEN, + ))?; + + root.present()?; + return Ok(chart.into_coord_trans()); +} + +pub fn draw_bf_error( + canvas: HtmlCanvasElement, + max_x: f32, +) -> DrawResult Option<(f32, f32)>> { + let root = CanvasBackend::with_canvas_object(canvas) + .unwrap() + .into_drawing_area(); + + let font: FontDesc = ("sans-serif", 20.0).into(); + + root.fill(&WHITE)?; + + let mut chart = ChartBuilder::on(&root) + .margin(20u32) + .caption(format!("y=logarithm error, x=1..{max_x}"), font) + .x_label_area_size(30u32) + .y_label_area_size(50u32) + .build_cartesian_2d(0f32..max_x, -0.0001f32..0.0001f32)?; + + chart.configure_mesh().x_labels(3).y_labels(3).draw()?; + + const RANGE_MAX: i32 = 1000; + chart.draw_series(LineSeries::new( + (0..=RANGE_MAX) + .map(|x| x as f32 * max_x / RANGE_MAX as f32) + .map(|x| (x, big_float_ln(x) - ln_baseline(x))), + &RED, + ))?; + + root.present()?; + return Ok(chart.into_coord_trans()); +} + +fn big_float_ln(x: f32) -> f32 { + const PREC: i64 = 1_000_000; + let bf = BigFloat::::from_frac((x * PREC as f32) as i64, PREC); + if let Some(ln_dec) = bf.ln() { + let ln_units = (ln_dec * PREC.into()).trunc().to_i64().unwrap(); + (ln_units as f64 / PREC as f64) as f32 + } else { + 0.0 + } +} + +fn ln_baseline(x: f32) -> f32 { + x.ln() +} + +#[cfg(test)] +mod test { + #[test] + fn sc_ln_test() { + assert_eq!(super::big_float_ln(0.0), 0.0); + assert_eq!(super::big_float_ln(1.0), 0.0); + assert!(super::big_float_ln(0.5) < -0.693); + assert!(super::big_float_ln(0.5) > -0.694); + assert!(super::big_float_ln(1.0) < 0.01); + assert!(super::big_float_ln(2.0) > 0.6); + } +} diff --git a/tools/plotter/src/logarithm_bu.rs b/tools/plotter/src/logarithm_bu.rs new file mode 100644 index 0000000000..bd10efed86 --- /dev/null +++ b/tools/plotter/src/logarithm_bu.rs @@ -0,0 +1,110 @@ +use crate::DrawResult; +use multiversx_sc::types::BigUint; +use multiversx_sc_scenario::api::StaticApi; +use plotters::prelude::*; +use plotters_canvas::CanvasBackend; +use web_sys::HtmlCanvasElement; + +pub fn draw_bu_logs( + canvas: HtmlCanvasElement, + max_x: f32, +) -> DrawResult Option<(f32, f32)>> { + let root = CanvasBackend::with_canvas_object(canvas) + .unwrap() + .into_drawing_area(); + + let font: FontDesc = ("sans-serif", 20.0).into(); + + root.fill(&WHITE)?; + + let mut chart = ChartBuilder::on(&root) + .margin(20u32) + .caption(format!("y=ln(x), x=1..{max_x}"), font) + .x_label_area_size(30u32) + .y_label_area_size(30u32) + .build_cartesian_2d(0f32..max_x, -1f32..5f32)?; + + chart.configure_mesh().x_labels(3).y_labels(3).draw()?; + + const RANGE_MAX: i32 = 1000; + chart.draw_series(LineSeries::new( + (0..=RANGE_MAX) + .map(|x| x as f32 * max_x / RANGE_MAX as f32) + .map(|x| (x, int_ln_baseline(x))), + &RED, + ))?; + + chart.draw_series(LineSeries::new( + (0..=RANGE_MAX) + .map(|x| x as f32 * max_x / RANGE_MAX as f32) + .map(|x| (x, big_uint_ln(x))), + &GREEN, + ))?; + + root.present()?; + return Ok(chart.into_coord_trans()); +} + +pub fn draw_bu_error( + canvas: HtmlCanvasElement, + max_x: f32, +) -> DrawResult Option<(f32, f32)>> { + let root = CanvasBackend::with_canvas_object(canvas) + .unwrap() + .into_drawing_area(); + + let font: FontDesc = ("sans-serif", 20.0).into(); + + root.fill(&WHITE)?; + + let mut chart = ChartBuilder::on(&root) + .margin(20u32) + .caption(format!("y=logarithm error, x=1..{max_x}"), font) + .x_label_area_size(30u32) + .y_label_area_size(50u32) + .build_cartesian_2d(0f32..max_x, -0.0001f32..0.0001f32)?; + + chart.configure_mesh().x_labels(3).y_labels(3).draw()?; + + const RANGE_MAX: i32 = 1000; + chart.draw_series(LineSeries::new( + (0..=RANGE_MAX) + .map(|x| x as f32 * max_x / RANGE_MAX as f32) + .map(|x| (x, big_uint_ln(x) - int_ln_baseline(x))), + &RED, + ))?; + + root.present()?; + return Ok(chart.into_coord_trans()); +} + +fn big_uint_ln(x: f32) -> f32 { + let bu = BigUint::::from(x as u32); + if let Some(ln_dec) = bu.ln() { + let ln_units = ln_dec.into_raw_units().to_u64().unwrap(); + let ln_sf = ln_dec.scaling_factor().to_u64().unwrap(); + (ln_units as f64 / ln_sf as f64) as f32 + } else { + 0.0 + } +} + +fn int_ln_baseline(x: f32) -> f32 { + let floor = x.trunc(); + if floor == 0.0 { + 0.0 + } else { + floor.ln() + } +} + +#[cfg(test)] +mod test { + #[test] + fn sc_ln_test() { + assert_eq!(super::big_uint_ln(0.0), 0.0); + assert!(super::big_uint_ln(1.0) >= 0.0); + assert!(super::big_uint_ln(1.0) < 0.01); + assert!(super::big_uint_ln(2.0) > 0.6); + } +} diff --git a/tools/plotter/start-server.bat b/tools/plotter/start-server.bat new file mode 100644 index 0000000000..aee88705f2 --- /dev/null +++ b/tools/plotter/start-server.bat @@ -0,0 +1,8 @@ +if not exist "www\pkg" mkdir www\pkg +rustup target add wasm32-unknown-unknown +wasm-pack build --release +if errorlevel 1 cargo install wasm-pack +wasm-pack build --release +cd www +call npm install +npm start diff --git a/tools/plotter/start-server.sh b/tools/plotter/start-server.sh new file mode 100755 index 0000000000..09641b1a03 --- /dev/null +++ b/tools/plotter/start-server.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -e + +mkdir -p www/pkg + +./build-wasm.sh + +cd www +npm install +npm start diff --git a/tools/plotter/www/.gitignore b/tools/plotter/www/.gitignore new file mode 100644 index 0000000000..16acd49d7f --- /dev/null +++ b/tools/plotter/www/.gitignore @@ -0,0 +1,3 @@ +node_modules +dist +package-lock.json diff --git a/tools/plotter/www/bootstrap.js b/tools/plotter/www/bootstrap.js new file mode 100644 index 0000000000..bea8b6b67a --- /dev/null +++ b/tools/plotter/www/bootstrap.js @@ -0,0 +1,21 @@ +init(); + +async function init() { + if (typeof process == "object") { + // We run in the npm/webpack environment. + const [{Chart}, {main, setup}] = await Promise.all([ + import("wasm-demo"), + import("./index.js"), + ]); + setup(Chart); + main(); + } else { + const [{Chart, default: init}, {main, setup}] = await Promise.all([ + import("../pkg/wasm_demo.js"), + import("./index.js"), + ]); + await init(); + setup(Chart); + main(); + } +} diff --git a/tools/plotter/www/index.html b/tools/plotter/www/index.html new file mode 100644 index 0000000000..37e874280e --- /dev/null +++ b/tools/plotter/www/index.html @@ -0,0 +1,37 @@ + + + + + + MultiversX SC function plots + + + + + +
+

MultiversX SC function plots

+
+ +
Loading WebAssembly...
+
+ + +
+ +
+
+
+ + + diff --git a/tools/plotter/www/index.js b/tools/plotter/www/index.js new file mode 100644 index 0000000000..f9dbafe4b1 --- /dev/null +++ b/tools/plotter/www/index.js @@ -0,0 +1,99 @@ +// If you only use `npm` you can simply +// import { Chart } from "wasm-demo" and remove `setup` call from `bootstrap.js`. +class Chart { } + +const canvas = document.getElementById("canvas"); +const coord = document.getElementById("coord"); +const plotType = document.getElementById("plot-type"); +const logMax = document.getElementById("logMax"); +const logControl = document.getElementById("logControl"); +const status = document.getElementById("status"); + +let chart = null; + +/** Main entry point */ +export function main() { + let hash = location.hash.substr(1); + for (var i = 0; i < plotType.options.length; i++) { + if (hash == plotType.options[i].value) { + plotType.value = hash; + } + } + setupUI(); + setupCanvas(); +} + +/** This function is used in `bootstrap.js` to setup imports. */ +export function setup(WasmChart) { + Chart = WasmChart; +} + +/** Add event listeners. */ +function setupUI() { + status.innerText = "WebAssembly loaded!"; + plotType.addEventListener("change", updatePlot); + logMax.addEventListener("input", updatePlot); + window.addEventListener("resize", setupCanvas); + window.addEventListener("mousemove", onMouseMove); +} + +/** Setup canvas to properly handle high DPI and redraw current plot. */ +function setupCanvas() { + const dpr = window.devicePixelRatio || 1.0; + const aspectRatio = canvas.width / canvas.height; + const size = canvas.parentNode.offsetWidth * 0.8; + canvas.style.width = size + "px"; + canvas.style.height = size / aspectRatio + "px"; + canvas.width = size; + canvas.height = size / aspectRatio; + updatePlot(); +} + +/** Update displayed coordinates. */ +function onMouseMove(event) { + if (chart) { + var text = "Mouse pointer is out of range"; + + if (event.target == canvas) { + let actualRect = canvas.getBoundingClientRect(); + let logicX = event.offsetX * canvas.width / actualRect.width; + let logicY = event.offsetY * canvas.height / actualRect.height; + const point = chart.coord(logicX, logicY); + text = (point) + ? `(${point.x.toFixed(3)}, ${point.y.toFixed(3)})` + : text; + } + coord.innerText = text; + } +} + +/** Redraw currently selected plot. */ +function updatePlot() { + const selected = plotType.selectedOptions[0]; + status.innerText = `Rendering ${selected.innerText}...`; + chart = null; + const start = performance.now(); + switch (selected.value) { + case "ln-bu": + logControl.classList.remove("hide"); + chart = Chart.ln_big_uint(canvas, Number(logMax.value)); + break; + case "ln-bu-error": + logControl.classList.remove("hide"); + chart = Chart.ln_big_uint_error(canvas, Number(logMax.value)); + break; + case "ln-bf": + logControl.classList.remove("hide"); + chart = Chart.ln_big_float(canvas, Number(logMax.value)); + break; + case "ln-bf-error": + logControl.classList.remove("hide"); + chart = Chart.ln_big_float_error(canvas, Number(logMax.value)); + break; + default: + logControl.classList.add("hide"); + } + + const end = performance.now(); + status.innerText = `Rendered ${selected.innerText} in ${Math.ceil(end - start)}ms`; +} diff --git a/tools/plotter/www/package.json b/tools/plotter/www/package.json new file mode 100644 index 0000000000..32a99f8aff --- /dev/null +++ b/tools/plotter/www/package.json @@ -0,0 +1,36 @@ +{ + "name": "plotters-wasm-demo", + "version": "0.1.0", + "description": "Plotters WASM Demo", + "main": "index.js", + "scripts": { + "build": "webpack --config webpack.config.js", + "start": "webpack-dev-server" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/38/plotters.git" + }, + "keywords": [ + "webassembly", + "wasm", + "rust", + "webpack", + "visualization" + ], + "author": "Plotters Developers", + "license": "MIT", + "bugs": { + "url": "https://github.com/38/plotters/issues" + }, + "homepage": "https://github.com/38/plotters", + "dependencies": { + "wasm-demo": "file:../pkg" + }, + "devDependencies": { + "webpack": "^4.43.0", + "webpack-cli": "^3.3.11", + "webpack-dev-server": "^3.10.3", + "copy-webpack-plugin": "^5.0.0" + } +} diff --git a/tools/plotter/www/style.css b/tools/plotter/www/style.css new file mode 100644 index 0000000000..404d385be6 --- /dev/null +++ b/tools/plotter/www/style.css @@ -0,0 +1,55 @@ +html, body, main { + width: 100%; + margin: 0; + padding: 0; +} + +body { + margin: auto; + max-width: 800px; + display: flex; + flex-direction: column; +} + +@media (max-width: 800px) { + body { + padding: 10px; + box-sizing: border-box; + } +} + +main { + display: flex; + flex-direction: column; + align-items: center; +} + +#coord, #status { + color: grey; + font-size: 10px; + height: 15px +} + +#control { + margin-top: 1em; +} + +#control label { + font-weight: bold; + margin-right: 1em; +} + +#control select { + padding: 0.25em 0.5em; +} + +footer { + margin-top: 2em; + font-size: 12px; + text-align: center; +} + +.hide { + visibility: hidden; + height: 0px; +} diff --git a/tools/plotter/www/webpack.config.js b/tools/plotter/www/webpack.config.js new file mode 100644 index 0000000000..80ad8142d2 --- /dev/null +++ b/tools/plotter/www/webpack.config.js @@ -0,0 +1,14 @@ +const CopyWebpackPlugin = require("copy-webpack-plugin"); +const path = require('path'); + +module.exports = { + entry: "./bootstrap.js", + output: { + path: path.resolve(__dirname, "dist"), + filename: "bootstrap.js", + }, + mode: "development", + plugins: [ + new CopyWebpackPlugin(['index.html']) + ], +}; diff --git a/vm/Cargo.toml b/vm/Cargo.toml index 907308f94f..0158bd09fa 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -16,19 +16,23 @@ description = "MultiversX VM implementation and tooling" keywords = ["multiversx", "blockchain", "vm", "tools"] categories = ["cryptography::cryptocurrencies", "development-tools::debugging"] +[features] +# not supported when compiling to wasm +wasm-incopatible = ["rand", "rand_seeder", "ed25519-dalek"] + [dependencies] num-bigint = "0.4" num-traits = "0.2" hex = "0.4" sha2 = "0.10.6" sha3 = "0.10.6" -rand = "0.8.5" -rand_seeder = "0.2.2" -ed25519-dalek = "1.0.1" itertools = "0.12.0" hex-literal = "=0.4.1" bitflags = "=2.5.0" colored = "2.1.0" +rand = { version= "0.8.5", optional = true } +rand_seeder = { version= "0.2.2", optional = true } +ed25519-dalek = { version = "1.0.1" , optional = true } [dependencies.multiversx-chain-vm-executor] version = "0.2.0" diff --git a/vm/src/crypto_functions.rs b/vm/src/crypto_functions.rs index 647f657e10..9d61e9ccc9 100644 --- a/vm/src/crypto_functions.rs +++ b/vm/src/crypto_functions.rs @@ -1,4 +1,3 @@ -use ed25519_dalek::*; use sha2::Sha256; use sha3::{Digest, Keccak256}; @@ -17,7 +16,10 @@ pub fn keccak256(data: &[u8]) -> [u8; KECCAK256_RESULT_LEN] { hasher.finalize().into() } +#[cfg(feature = "wasm-incopatible")] pub fn verify_ed25519(key: &[u8], message: &[u8], signature: &[u8]) -> bool { + use ed25519_dalek::*; + let public = PublicKey::from_bytes(key); if public.is_err() { return false; @@ -30,3 +32,8 @@ pub fn verify_ed25519(key: &[u8], message: &[u8], signature: &[u8]) -> bool { public.unwrap().verify(message, &sig.unwrap()).is_ok() } + +#[cfg(not(feature = "wasm-incopatible"))] +pub fn verify_ed25519(_key: &[u8], _message: &[u8], _signature: &[u8]) -> bool { + panic!("verify_ed25519 not supported for wasm builds, feature `wasm-incopatible` needs to be enabled") +} diff --git a/vm/src/tx_mock.rs b/vm/src/tx_mock.rs index d1da905113..bd508d569e 100644 --- a/vm/src/tx_mock.rs +++ b/vm/src/tx_mock.rs @@ -1,6 +1,5 @@ #![allow(clippy::type_complexity)] -mod blockchain_rng; mod blockchain_update; mod tx_async_call_data; mod tx_async_promise; @@ -20,7 +19,6 @@ mod tx_panic; mod tx_result; mod tx_result_calls; -pub use blockchain_rng::*; pub use blockchain_update::BlockchainUpdate; pub use tx_async_call_data::*; pub use tx_async_promise::*; @@ -38,3 +36,13 @@ pub use tx_managed_types::*; pub use tx_panic::*; pub use tx_result::*; pub use tx_result_calls::*; + +#[cfg(feature = "wasm-incopatible")] +mod blockchain_rng; +#[cfg(feature = "wasm-incopatible")] +pub use blockchain_rng::BlockchainRng; + +#[cfg(not(feature = "wasm-incopatible"))] +mod blockchain_rng_unsupported; +#[cfg(not(feature = "wasm-incopatible"))] +pub use blockchain_rng_unsupported::BlockchainRng; diff --git a/vm/src/tx_mock/blockchain_rng.rs b/vm/src/tx_mock/blockchain_rng.rs index bbcfafee8d..b16e9e2062 100644 --- a/vm/src/tx_mock/blockchain_rng.rs +++ b/vm/src/tx_mock/blockchain_rng.rs @@ -31,7 +31,7 @@ impl BlockchainRng { } } - pub fn fill(&mut self, dest: &mut T) { + fn fill(&mut self, dest: &mut T) { self.rng.fill(dest); } diff --git a/vm/src/tx_mock/blockchain_rng_unsupported.rs b/vm/src/tx_mock/blockchain_rng_unsupported.rs new file mode 100644 index 0000000000..698be4ac11 --- /dev/null +++ b/vm/src/tx_mock/blockchain_rng_unsupported.rs @@ -0,0 +1,14 @@ +use super::{TxCache, TxInput}; + +#[derive(Debug)] +pub struct BlockchainRng; + +impl BlockchainRng { + pub fn new(_tx_input: &TxInput, _tx_cache: &TxCache) -> Self { + BlockchainRng + } + + pub fn next_bytes(&mut self, _length: usize) -> Vec { + panic!("BlockchainRng not supported for wasm builds, feature `wasm-incopatible` needs to be enabled") + } +} diff --git a/vm/src/vm_hooks/vh_handler/vh_managed_types/vh_big_float.rs b/vm/src/vm_hooks/vh_handler/vh_managed_types/vh_big_float.rs index 1e2410fc9c..4c2c06b49a 100644 --- a/vm/src/vm_hooks/vh_handler/vh_managed_types/vh_big_float.rs +++ b/vm/src/vm_hooks/vh_handler/vh_managed_types/vh_big_float.rs @@ -8,7 +8,7 @@ use core::{ ops::{Add, Div, Mul, Neg, Sub}, }; use num_bigint::BigInt; -use num_traits::ToPrimitive; +use num_traits::{ToPrimitive, Zero}; use std::convert::TryInto; macro_rules! binary_op_method { @@ -115,16 +115,18 @@ pub trait VMHooksBigFloat: VMHooksHandlerSource + VMHooksError { fn bf_sign(&self, x: RawHandle) -> i32 { let bf = self.m_types_lock().bf_get_f64(x); + if bf.is_zero() { + return 0; + } + if !bf.is_normal() { self.vm_error(vm_err_msg::NUMBER_IS_NOT_NORMAL) } if bf.is_sign_positive() { 1 - } else if bf.is_sign_negative() { - -1 } else { - 0 + -1 } }