diff --git a/Cargo.lock b/Cargo.lock index b865897548..8bda75ef7b 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -47,19 +47,13 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" dependencies = [ "gimli", ] -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - [[package]] name = "adler2" version = "2.0.0" @@ -166,9 +160,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" [[package]] name = "arbitrary" @@ -193,23 +187,23 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", - "miniz_oxide 0.7.4", + "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -386,15 +380,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "cc" -version = "1.1.15" +version = "1.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0" dependencies = [ "shlex", ] @@ -452,9 +446,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.16" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" +checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3" dependencies = [ "clap_builder", "clap_derive", @@ -462,9 +456,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.15" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" +checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b" dependencies = [ "anstream", "anstyle", @@ -474,9 +468,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.13" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck", "proc-macro2", @@ -572,9 +566,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] @@ -1082,12 +1076,12 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.33" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", - "miniz_oxide 0.8.0", + "miniz_oxide", ] [[package]] @@ -1333,15 +1327,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" [[package]] name = "globset" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" +checksum = "15f1ce686646e7f1e19bf7d5533fe443a45dbfb990e00629110797578b42fb19" dependencies = [ "aho-corasick", "bstr", @@ -1480,9 +1474,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.2" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", "http", @@ -1513,9 +1507,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.7" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ "bytes", "futures-channel", @@ -1526,7 +1520,6 @@ dependencies = [ "pin-project-lite", "socket2", "tokio", - "tower", "tower-service", "tracing", ] @@ -1543,9 +1536,9 @@ dependencies = [ [[package]] name = "ignore" -version = "0.4.22" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" +checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b" dependencies = [ "crossbeam-deque", "globset", @@ -1590,9 +1583,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" [[package]] name = "is_terminal_polyfill" @@ -1720,9 +1713,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "linked-list-repeat" @@ -1864,15 +1857,6 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[package]] -name = "miniz_oxide" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" -dependencies = [ - "adler", -] - [[package]] name = "miniz_oxide" version = "0.8.0" @@ -1947,6 +1931,14 @@ dependencies = [ "multiversx-sc-meta-lib", ] +[[package]] +name = "multiversx-chain-core" +version = "0.10.0" +dependencies = [ + "bitflags", + "multiversx-sc-codec", +] + [[package]] name = "multiversx-chain-scenario-format" version = "0.23.0" @@ -1970,6 +1962,7 @@ dependencies = [ "hex", "hex-literal", "itertools", + "multiversx-chain-core", "multiversx-chain-vm-executor", "num-bigint", "num-traits", @@ -2012,6 +2005,7 @@ version = "0.53.0" dependencies = [ "bitflags", "hex-literal", + "multiversx-chain-core", "multiversx-sc-codec", "multiversx-sc-derive", "num-traits", @@ -2509,26 +2503,6 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" -[[package]] -name = "pin-project" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "pin-project-lite" version = "0.2.14" @@ -2569,9 +2543,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "ppv-lite86" @@ -2757,9 +2731,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.3" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "355ae415ccd3a04315d3f8246e86d67689ea74d88d915576e1589a351062a13b" dependencies = [ "bitflags", ] @@ -2939,9 +2913,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.35" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ "bitflags", "errno", @@ -2952,9 +2926,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.12" +version = "0.23.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" dependencies = [ "once_cell", "rustls-pki-types", @@ -2981,9 +2955,9 @@ checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" [[package]] name = "rustls-webpki" -version = "0.102.7" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84678086bd54edf2b415183ed7a94d0efb049f1b646a33e22a36f3794be6ae56" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring", "rustls-pki-types", @@ -3032,11 +3006,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3089,9 +3063,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" dependencies = [ "core-foundation-sys", "libc", @@ -3138,18 +3112,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", @@ -3158,9 +3132,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.127" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "indexmap", "itoa", @@ -3182,9 +3156,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -3430,18 +3404,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", @@ -3531,9 +3505,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", @@ -3566,9 +3540,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.20" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ "indexmap", "serde", @@ -3577,27 +3551,6 @@ dependencies = [ "winnow", ] -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "pin-project", - "pin-project-lite", - "tokio", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-layer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" - [[package]] name = "tower-service" version = "0.3.3" @@ -3661,9 +3614,9 @@ checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" @@ -3676,9 +3629,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "untrusted" @@ -4097,9 +4050,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.18" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 651456eebd..ed42646cba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ members = [ # "tools/plotter", "tools/interactor-system-func-calls/", + "vm-core", "vm", "contracts/modules", diff --git a/framework/base/Cargo.toml b/framework/base/Cargo.toml index 0402d16f81..324c87d955 100644 --- a/framework/base/Cargo.toml +++ b/framework/base/Cargo.toml @@ -37,3 +37,7 @@ path = "../derive" version = "=0.21.0" path = "../../data/codec" features = ["derive"] + +[dependencies.multiversx-chain-core] +version = "=0.10.0" +path = "../../vm-core" diff --git a/framework/base/src/abi.rs b/framework/base/src/abi.rs index c031a62166..dd128161bc 100644 --- a/framework/base/src/abi.rs +++ b/framework/base/src/abi.rs @@ -7,6 +7,7 @@ mod type_abi; mod type_abi_from; mod type_abi_impl_basic; mod type_abi_impl_codec_multi; +mod type_abi_impl_vm_core; mod type_description; mod type_description_container; diff --git a/framework/base/src/abi/type_abi_impl_vm_core.rs b/framework/base/src/abi/type_abi_impl_vm_core.rs new file mode 100644 index 0000000000..13b8988a59 --- /dev/null +++ b/framework/base/src/abi/type_abi_impl_vm_core.rs @@ -0,0 +1,204 @@ +use super::*; + +use alloc::vec::Vec; +use multiversx_chain_core::types::{ + Address, BoxedBytes, CodeMetadata, EsdtLocalRole, EsdtTokenType, H256, +}; + +impl TypeAbiFrom for H256 {} + +impl TypeAbi for H256 { + type Unmanaged = Self; + + fn type_name() -> TypeName { + "H256".into() + } + + fn type_name_rust() -> TypeName { + "H256".into() + } +} + +impl TypeAbiFrom for Address {} + +impl TypeAbi for Address { + type Unmanaged = Self; + + fn type_name() -> TypeName { + "Address".into() + } + + fn type_name_rust() -> TypeName { + "Address".into() + } +} + +impl TypeAbiFrom for BoxedBytes {} + +impl TypeAbi for BoxedBytes { + type Unmanaged = Self; + + fn type_name() -> TypeName { + "bytes".into() + } + + fn type_name_rust() -> TypeName { + "BoxedBytes".into() + } +} + +impl TypeAbiFrom for CodeMetadata {} +impl TypeAbi for CodeMetadata { + type Unmanaged = Self; + + fn type_name() -> TypeName { + "CodeMetadata".into() + } + + fn type_name_rust() -> TypeName { + "CodeMetadata".into() + } +} + +impl TypeAbiFrom for EsdtTokenType {} +impl TypeAbiFrom<&Self> for EsdtTokenType {} + +// implementation originally geneated via #[type_abi] attribute +impl TypeAbi for EsdtTokenType { + type Unmanaged = Self; + fn type_name() -> TypeName { + "EsdtTokenType".into() + } + + #[allow(clippy::vec_init_then_push)] + fn provide_type_descriptions(accumulator: &mut TDC) { + let type_names = Self::type_names(); + if !accumulator.contains_type(&type_names.abi) { + accumulator.reserve_type_name(type_names.clone()); + let mut variant_descriptions = Vec::new(); + variant_descriptions.push(EnumVariantDescription::new( + &[], + "Fungible", + 0usize, + Vec::new(), + )); + variant_descriptions.push(EnumVariantDescription::new( + &[], + "NonFungible", + 1usize, + Vec::new(), + )); + variant_descriptions.push(EnumVariantDescription::new( + &[], + "SemiFungible", + 2usize, + Vec::new(), + )); + variant_descriptions.push(EnumVariantDescription::new(&[], "Meta", 3usize, Vec::new())); + variant_descriptions.push(EnumVariantDescription::new( + &[], + "Invalid", + 4usize, + Vec::new(), + )); + accumulator.insert( + type_names.clone(), + TypeDescription::new( + &[], + type_names, + TypeContents::Enum(variant_descriptions), + &[ + "TopDecode", + "TopEncode", + "NestedDecode", + "NestedEncode", + "Clone", + "PartialEq", + "Eq", + "Debug", + "ManagedVecItem", + ], + ), + ); + } + } +} + +impl TypeAbiFrom for EsdtLocalRole {} +impl TypeAbiFrom<&Self> for EsdtLocalRole {} + +// implementation originally geneated via #[type_abi] attribute +impl TypeAbi for EsdtLocalRole { + type Unmanaged = Self; + + fn type_name() -> TypeName { + "EsdtLocalRole".into() + } + + #[allow(clippy::vec_init_then_push)] + fn provide_type_descriptions(accumulator: &mut TDC) { + let type_names = Self::type_names(); + if !accumulator.contains_type(&type_names.abi) { + accumulator.reserve_type_name(type_names.clone()); + let mut variant_descriptions = Vec::new(); + variant_descriptions.push(EnumVariantDescription::new(&[], "None", 0usize, Vec::new())); + variant_descriptions.push(EnumVariantDescription::new(&[], "Mint", 1usize, Vec::new())); + variant_descriptions.push(EnumVariantDescription::new(&[], "Burn", 2usize, Vec::new())); + variant_descriptions.push(EnumVariantDescription::new( + &[], + "NftCreate", + 3usize, + Vec::new(), + )); + variant_descriptions.push(EnumVariantDescription::new( + &[], + "NftAddQuantity", + 4usize, + Vec::new(), + )); + variant_descriptions.push(EnumVariantDescription::new( + &[], + "NftBurn", + 5usize, + Vec::new(), + )); + variant_descriptions.push(EnumVariantDescription::new( + &[], + "NftAddUri", + 6usize, + Vec::new(), + )); + variant_descriptions.push(EnumVariantDescription::new( + &[], + "NftUpdateAttributes", + 7usize, + Vec::new(), + )); + variant_descriptions.push(EnumVariantDescription::new( + &[], + "Transfer", + 8usize, + Vec::new(), + )); + accumulator.insert( + type_names.clone(), + TypeDescription::new( + &[], + type_names, + TypeContents::Enum(variant_descriptions), + &[ + "TopDecode", + "TopEncode", + "NestedDecode", + "NestedEncode", + "Clone", + "PartialEq", + "Eq", + "Debug", + "Copy", + ], + ), + ); + } + } +} diff --git a/framework/base/src/api.rs b/framework/base/src/api.rs index 094522d1ac..8123eded28 100644 --- a/framework/base/src/api.rs +++ b/framework/base/src/api.rs @@ -30,4 +30,4 @@ pub use storage_api::*; pub use vm_api::VMApi; // Backwards compatibility. -pub use crate::types::system_proxy::builtin_func_names::*; +pub use crate::chain_core::builtin_func_names::*; diff --git a/framework/base/src/formatter.rs b/framework/base/src/formatter.rs index e850ec2111..117d332382 100644 --- a/framework/base/src/formatter.rs +++ b/framework/base/src/formatter.rs @@ -1,6 +1,7 @@ mod formatter_impl_bool; mod formatter_impl_bytes; mod formatter_impl_num; +mod formatter_impl_vm_core; mod formatter_traits; pub mod hex_util; diff --git a/framework/base/src/formatter/formatter_impl_vm_core.rs b/framework/base/src/formatter/formatter_impl_vm_core.rs new file mode 100644 index 0000000000..609c090e36 --- /dev/null +++ b/framework/base/src/formatter/formatter_impl_vm_core.rs @@ -0,0 +1,25 @@ +use multiversx_chain_core::types::CodeMetadata; + +use super::{hex_util, FormatByteReceiver, SCBinary, SCDisplay, SCLowerHex}; + +impl SCDisplay for CodeMetadata { + fn fmt(&self, f: &mut F) { + self.for_each_string_token(|token| f.append_bytes(token.as_bytes())) + } +} + +impl SCLowerHex for CodeMetadata { + fn fmt(&self, f: &mut F) { + let num = self.bits().to_be_bytes(); + f.append_bytes(&hex_util::byte_to_hex_digits(num[0])[..]); + f.append_bytes(&hex_util::byte_to_hex_digits(num[1])[..]); + } +} + +impl SCBinary for CodeMetadata { + fn fmt(&self, f: &mut F) { + let num = self.bits().to_be_bytes(); + f.append_bytes(&hex_util::byte_to_binary_digits(num[0])[..]); + f.append_bytes(&hex_util::byte_to_binary_digits(num[1])[..]); + } +} diff --git a/framework/base/src/lib.rs b/framework/base/src/lib.rs index 3b8fc6c0f5..9f6680af7c 100644 --- a/framework/base/src/lib.rs +++ b/framework/base/src/lib.rs @@ -9,6 +9,9 @@ extern crate alloc; /// The current version of `multiversx_sc_codec`, re-exported. pub use multiversx_sc_codec as codec; +// Re-exporting the VM-core, for convenience. +pub use multiversx_chain_core as chain_core; + /// Reexported for convenience. pub use crate::codec::arrayvec; diff --git a/framework/base/src/types.rs b/framework/base/src/types.rs index 23d94214ba..41d303e91b 100644 --- a/framework/base/src/types.rs +++ b/framework/base/src/types.rs @@ -1,5 +1,4 @@ mod crypto; -mod flags; pub mod heap; mod interaction; mod io; @@ -8,7 +7,6 @@ pub(crate) mod math_util; mod static_buffer; pub use crypto::*; -pub use flags::*; pub use interaction::*; pub use io::*; pub use managed::*; @@ -17,3 +15,8 @@ pub use static_buffer::*; /// Only import the heap types in contracts when the "alloc" feature is on. #[cfg(feature = "alloc")] pub use heap::*; + +pub use crate::chain_core::types::CodeMetadata; +pub use crate::chain_core::types::EsdtLocalRole; +pub use crate::chain_core::types::EsdtLocalRoleFlags; +pub use crate::chain_core::types::EsdtTokenType; diff --git a/framework/base/src/types/flags/esdt_local_role.rs b/framework/base/src/types/flags/esdt_local_role.rs deleted file mode 100644 index b66ac612f5..0000000000 --- a/framework/base/src/types/flags/esdt_local_role.rs +++ /dev/null @@ -1,159 +0,0 @@ -use super::EsdtLocalRoleFlags; -use crate as multiversx_sc; -use crate::{ - codec::{ - self, - derive::{NestedDecode, NestedEncode, TopDecode, TopEncode}, - }, - derive::type_abi, - types::{ManagedVecItem, ManagedVecItemPayloadBuffer}, -}; - -static ESDT_ROLE_NONE: &[u8] = &[]; -static ESDT_ROLE_LOCAL_MINT: &[u8] = b"ESDTRoleLocalMint"; -static ESDT_ROLE_LOCAL_BURN: &[u8] = b"ESDTRoleLocalBurn"; -static ESDT_ROLE_NFT_CREATE: &[u8] = b"ESDTRoleNFTCreate"; -static ESDT_ROLE_NFT_ADD_QUANTITY: &[u8] = b"ESDTRoleNFTAddQuantity"; -static ESDT_ROLE_NFT_BURN: &[u8] = b"ESDTRoleNFTBurn"; -static ESDT_ROLE_NFT_ADD_URI: &[u8] = b"ESDTRoleNFTAddURI"; -static ESDT_ROLE_NFT_UPDATE_ATTRIBUTES: &[u8] = b"ESDTRoleNFTUpdateAttributes"; -static ESDT_ROLE_TRANSFER: &[u8] = b"ESDTTransferRole"; - -#[type_abi] -#[derive(TopDecode, TopEncode, NestedDecode, NestedEncode, Clone, PartialEq, Eq, Debug, Copy)] -pub enum EsdtLocalRole { - None, - Mint, - Burn, - NftCreate, - NftAddQuantity, - NftBurn, - NftAddUri, - NftUpdateAttributes, - Transfer, -} - -impl EsdtLocalRole { - pub fn as_u16(&self) -> u16 { - match self { - Self::None => 0, - Self::Mint => 1, - Self::Burn => 2, - Self::NftCreate => 3, - Self::NftAddQuantity => 4, - Self::NftBurn => 5, - Self::NftAddUri => 6, - Self::NftUpdateAttributes => 7, - Self::Transfer => 8, - } - } - - pub fn as_role_name(&self) -> &'static [u8] { - match self { - Self::None => ESDT_ROLE_NONE, - Self::Mint => ESDT_ROLE_LOCAL_MINT, - Self::Burn => ESDT_ROLE_LOCAL_BURN, - Self::NftCreate => ESDT_ROLE_NFT_CREATE, - Self::NftAddQuantity => ESDT_ROLE_NFT_ADD_QUANTITY, - Self::NftBurn => ESDT_ROLE_NFT_BURN, - Self::NftAddUri => ESDT_ROLE_NFT_ADD_URI, - Self::NftUpdateAttributes => ESDT_ROLE_NFT_UPDATE_ATTRIBUTES, - Self::Transfer => ESDT_ROLE_TRANSFER, - } - } - - pub fn to_flag(&self) -> EsdtLocalRoleFlags { - match self { - Self::None => EsdtLocalRoleFlags::NONE, - Self::Mint => EsdtLocalRoleFlags::MINT, - Self::Burn => EsdtLocalRoleFlags::BURN, - Self::NftCreate => EsdtLocalRoleFlags::NFT_CREATE, - Self::NftAddQuantity => EsdtLocalRoleFlags::NFT_ADD_QUANTITY, - Self::NftBurn => EsdtLocalRoleFlags::NFT_BURN, - Self::NftAddUri => EsdtLocalRoleFlags::NFT_ADD_URI, - Self::NftUpdateAttributes => EsdtLocalRoleFlags::NFT_UPDATE_ATTRIBUTES, - Self::Transfer => EsdtLocalRoleFlags::TRANSFER, - } - } -} - -// TODO: can be done with macros, but I didn't find a public library that does it and is no_std -// we can implement it, it's easy -const ALL_ROLES: [EsdtLocalRole; 8] = [ - EsdtLocalRole::Mint, - EsdtLocalRole::Burn, - EsdtLocalRole::NftCreate, - EsdtLocalRole::NftAddQuantity, - EsdtLocalRole::NftBurn, - EsdtLocalRole::NftAddUri, - EsdtLocalRole::NftUpdateAttributes, - EsdtLocalRole::Transfer, -]; - -impl EsdtLocalRole { - pub fn iter_all() -> core::slice::Iter<'static, EsdtLocalRole> { - ALL_ROLES.iter() - } -} - -impl From for EsdtLocalRole { - #[inline] - fn from(value: u16) -> Self { - match value { - 1 => Self::Mint, - 2 => Self::Burn, - 3 => Self::NftCreate, - 4 => Self::NftAddQuantity, - 5 => Self::NftBurn, - 6 => Self::NftAddUri, - 7 => Self::NftUpdateAttributes, - 8 => Self::Transfer, - _ => Self::None, - } - } -} - -impl<'a> From<&'a [u8]> for EsdtLocalRole { - #[inline] - fn from(byte_slice: &'a [u8]) -> Self { - if byte_slice == ESDT_ROLE_LOCAL_MINT { - Self::Mint - } else if byte_slice == ESDT_ROLE_LOCAL_BURN { - Self::Burn - } else if byte_slice == ESDT_ROLE_NFT_CREATE { - Self::NftCreate - } else if byte_slice == ESDT_ROLE_NFT_ADD_QUANTITY { - Self::NftAddQuantity - } else if byte_slice == ESDT_ROLE_NFT_BURN { - Self::NftBurn - } else if byte_slice == ESDT_ROLE_NFT_ADD_URI { - Self::NftAddUri - } else if byte_slice == ESDT_ROLE_NFT_UPDATE_ATTRIBUTES { - Self::NftUpdateAttributes - } else if byte_slice == ESDT_ROLE_TRANSFER { - Self::Transfer - } else { - Self::None - } - } -} - -impl ManagedVecItem for EsdtLocalRole { - type PAYLOAD = ManagedVecItemPayloadBuffer<1>; - const SKIPS_RESERIALIZATION: bool = false; // TODO: might be ok to be true, but needs testing - type Ref<'a> = Self; - - fn from_byte_reader(reader: Reader) -> Self { - u16::from_byte_reader(reader).into() - } - - unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>( - reader: Reader, - ) -> Self::Ref<'a> { - Self::from_byte_reader(reader) - } - - fn to_byte_writer R>(&self, writer: Writer) -> R { - ::to_byte_writer(&self.as_u16(), writer) - } -} diff --git a/framework/base/src/types/heap/mod.rs b/framework/base/src/types/heap.rs similarity index 63% rename from framework/base/src/types/heap/mod.rs rename to framework/base/src/types/heap.rs index eea5a01b90..18a7a5f9fc 100644 --- a/framework/base/src/types/heap/mod.rs +++ b/framework/base/src/types/heap.rs @@ -1,15 +1,11 @@ mod arg_buffer; mod async_call_result; -mod boxed_bytes; -mod h256; -mod h256_address; mod queue; pub use arg_buffer::ArgBuffer; pub use async_call_result::{AsyncCallError, AsyncCallResult}; -pub use boxed_bytes::BoxedBytes; -pub use h256::H256; -pub use h256_address::Address; pub use queue::Queue; pub use alloc::{boxed::Box, string::String, vec::Vec}; + +pub use crate::chain_core::types::{Address, BoxedBytes, H256}; diff --git a/framework/base/src/types/interaction/system_proxy.rs b/framework/base/src/types/interaction/system_proxy.rs index 3b1fb836d6..e86c9f32ff 100644 --- a/framework/base/src/types/interaction/system_proxy.rs +++ b/framework/base/src/types/interaction/system_proxy.rs @@ -1,4 +1,3 @@ -pub mod builtin_func_names; mod builtin_func_proxy; mod esdt_system_sc_proxy; mod legacy_system_sc_proxy; diff --git a/framework/base/src/types/interaction/system_proxy/builtin_func_proxy.rs b/framework/base/src/types/interaction/system_proxy/builtin_func_proxy.rs index 6755dbbd03..1bf7c3a1fc 100644 --- a/framework/base/src/types/interaction/system_proxy/builtin_func_proxy.rs +++ b/framework/base/src/types/interaction/system_proxy/builtin_func_proxy.rs @@ -5,7 +5,7 @@ use crate::types::{ TxEnv, TxFrom, TxGas, TxProxyTrait, TxTo, TxTypedCall, }; -use super::builtin_func_names::{ +use crate::chain_core::builtin_func_names::{ CHANGE_OWNER_BUILTIN_FUNC_NAME, CLAIM_DEVELOPER_REWARDS_FUNC_NAME, DELETE_USERNAME_FUNC_NAME, ESDT_LOCAL_BURN_FUNC_NAME, ESDT_LOCAL_MINT_FUNC_NAME, ESDT_NFT_ADD_QUANTITY_FUNC_NAME, ESDT_NFT_ADD_URI_FUNC_NAME, ESDT_NFT_BURN_FUNC_NAME, ESDT_NFT_CREATE_FUNC_NAME, diff --git a/framework/base/src/types/managed/wrapped/managed_vec_item.rs b/framework/base/src/types/managed/wrapped/managed_vec_item.rs index 9f21a13de4..00cb212c18 100644 --- a/framework/base/src/types/managed/wrapped/managed_vec_item.rs +++ b/framework/base/src/types/managed/wrapped/managed_vec_item.rs @@ -1,5 +1,7 @@ use core::borrow::Borrow; +use multiversx_chain_core::types::{EsdtLocalRole, EsdtTokenType}; + use crate::{ api::ManagedTypeApi, types::{ @@ -258,3 +260,45 @@ where ::to_byte_writer(&self.get_handle(), writer) } } + +impl ManagedVecItem for EsdtTokenType { + type PAYLOAD = ManagedVecItemPayloadBuffer<1>; + const SKIPS_RESERIALIZATION: bool = true; + type Ref<'a> = Self; + + fn from_byte_reader(mut reader: Reader) -> Self { + let mut arr: [u8; 1] = [0u8; 1]; + reader(&mut arr[..]); + arr[0].into() + } + + unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>( + reader: Reader, + ) -> Self::Ref<'a> { + Self::from_byte_reader(reader) + } + + fn to_byte_writer R>(&self, mut writer: Writer) -> R { + writer(&[self.as_u8()]) + } +} + +impl ManagedVecItem for EsdtLocalRole { + type PAYLOAD = ManagedVecItemPayloadBuffer<1>; + const SKIPS_RESERIALIZATION: bool = false; // TODO: might be ok to be true, but needs testing + type Ref<'a> = Self; + + fn from_byte_reader(reader: Reader) -> Self { + u16::from_byte_reader(reader).into() + } + + unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>( + reader: Reader, + ) -> Self::Ref<'a> { + Self::from_byte_reader(reader) + } + + fn to_byte_writer R>(&self, writer: Writer) -> R { + ::to_byte_writer(&self.as_u16(), writer) + } +} diff --git a/publish.sh b/publish.sh index 53a5e922af..60b32b298c 100755 --- a/publish.sh +++ b/publish.sh @@ -60,23 +60,27 @@ # 15. Write a release announcement in Confluence. # -cd vm +cd data/codec-derive cargo publish || return 1 -cd .. +cd ../.. -cd sdk/core +cd data/codec cargo publish || return 1 cd ../.. -cd sdk/scenario-format/ +cd vm-core cargo publish || return 1 -cd ../.. +cd .. -cd data/codec-derive +cd vm +cargo publish || return 1 +cd .. + +cd sdk/core cargo publish || return 1 cd ../.. -cd data/codec +cd sdk/scenario-format/ cargo publish || return 1 cd ../.. diff --git a/tools/rust-debugger/pretty-printers/multiversx_sc_lldb_pretty_printers.py b/tools/rust-debugger/pretty-printers/multiversx_sc_lldb_pretty_printers.py index 1232201e28..237511a541 100644 --- a/tools/rust-debugger/pretty-printers/multiversx_sc_lldb_pretty_printers.py +++ b/tools/rust-debugger/pretty-printers/multiversx_sc_lldb_pretty_printers.py @@ -44,10 +44,10 @@ # 4. SC wasm - Managed multi value types -# 5. SC wasm - heap -MOD_PATH = "multiversx_sc::types::heap" +# 5. VM core types +MOD_PATH = "multiversx_chain_core::types" -HEAP_ADDRESS_TYPE = f"{MOD_PATH}::h256_address::Address" +HEAP_ADDRESS_TYPE = f"{MOD_PATH}::address::Address" BOXED_BYTES_TYPE = f"{MOD_PATH}::boxed_bytes::BoxedBytes" # 6. MultiversX codec - Multi-types diff --git a/vm-core/Cargo.toml b/vm-core/Cargo.toml new file mode 100644 index 0000000000..4c170181f7 --- /dev/null +++ b/vm-core/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "multiversx-chain-core" +version = "0.10.0" +edition = "2021" + +authors = [ + "Andrei Marinica ", + "MultiversX ", +] +license = "GPL-3.0-only" +readme = "README.md" +repository = "https://github.com/multiversx/mx-sdk-rs" +homepage = "https://multiversx.com/" +documentation = "https://docs.multiversx.com/" +description = "MultiversX VM interfaces and base types" +keywords = ["multiversx", "blockchain", "vm", "tools"] +categories = ["cryptography::cryptocurrencies", "development-tools::debugging"] + +[dependencies] +bitflags = "=2.6.0" + +[dependencies.multiversx-sc-codec] +version = "=0.21.0" +path = "../data/codec" +features = ["derive"] diff --git a/vm-core/README.md b/vm-core/README.md new file mode 100644 index 0000000000..76827c0b17 --- /dev/null +++ b/vm-core/README.md @@ -0,0 +1,16 @@ +# MultiversX blockchain base types, interfaces and builtin function names + +It provides various types and contants referring to the MultiversX blockchain base implementation. + +This functionality is designed to be minimal and to be used from both smart contract code and VM implementations. + +It can be viewed as a collection of system specs, which hold for any MultiversX-related implementation. For example: +- `Address` - MultiversX adresses are 32 bytes long. This is the old SC address type, it holds the bytes on the heap. It is also used in the MultiversX Rust VM. +- `H256` - same as address, currently used for transaction hashes. +- Flags: + - Code metadata - a bitflag encoding the SC code metadta, as it is stored on the blockchain, and encoded in smart contracts; + - ESDT local roles + - as enum + - as bitflags + - ESDT token types + diff --git a/framework/base/src/types/interaction/system_proxy/builtin_func_names.rs b/vm-core/src/builtin_func_names.rs similarity index 100% rename from framework/base/src/types/interaction/system_proxy/builtin_func_names.rs rename to vm-core/src/builtin_func_names.rs diff --git a/vm-core/src/lib.rs b/vm-core/src/lib.rs new file mode 100644 index 0000000000..503f690d82 --- /dev/null +++ b/vm-core/src/lib.rs @@ -0,0 +1,9 @@ +#![no_std] + +extern crate alloc; + +pub mod builtin_func_names; +pub mod types; + +/// Re-exported for convenience. +pub use multiversx_sc_codec as codec; diff --git a/vm-core/src/types.rs b/vm-core/src/types.rs new file mode 100644 index 0000000000..6aa0159afd --- /dev/null +++ b/vm-core/src/types.rs @@ -0,0 +1,13 @@ +mod address; +mod boxed_bytes; +mod flags; +mod h256; +mod heap_address; +mod heap_h256; + +pub use address::Address; +pub use boxed_bytes::BoxedBytes; +pub use flags::*; +pub use h256::H256; +pub use heap_address::HeapAddress; +pub use heap_h256::HeapH256; diff --git a/framework/base/src/types/heap/h256_address.rs b/vm-core/src/types/address.rs similarity index 85% rename from framework/base/src/types/heap/h256_address.rs rename to vm-core/src/types/address.rs index a9fa69c2e7..0f5099fddb 100644 --- a/framework/base/src/types/heap/h256_address.rs +++ b/vm-core/src/types/address.rs @@ -1,12 +1,11 @@ -use super::h256::H256; -use crate::{ - abi::{TypeAbi, TypeAbiFrom, TypeName}, - types::heap::BoxedBytes, -}; +use super::H256; use alloc::{boxed::Box, vec::Vec}; use core::fmt::Debug; const SC_ADDRESS_NUM_LEADING_ZEROS: u8 = 8; +pub const NUM_INT_CHARACTERS_FOR_ADDRESS: usize = 10; +pub const VM_TYPE_LEN: usize = 2; +pub const DEFAULT_VM_TYPE: &[u8] = &[5, 0]; /// An Address is just a H256 with a different name. /// Has a different ABI name than H256. @@ -16,6 +15,30 @@ const SC_ADDRESS_NUM_LEADING_ZEROS: u8 = 8; #[derive(Hash, PartialEq, Eq, Clone, Debug)] pub struct Address(H256); +impl Address { + pub const fn new(bytes: [u8; 32]) -> Self { + Address(H256::new(bytes)) + } + + pub fn generate_mock_address(creator_address: &[u8], creator_nonce: u64) -> Self { + let mut result = [0x00; 32]; + + result[10] = 0x11; + result[11] = 0x11; + result[12] = 0x11; + result[13] = 0x11; + + result[14..29].copy_from_slice(&creator_address[..15]); + result[29] = creator_nonce as u8; + result[30..].copy_from_slice(&creator_address[30..]); + + let start_index = NUM_INT_CHARACTERS_FOR_ADDRESS - VM_TYPE_LEN; + result[start_index..(start_index + DEFAULT_VM_TYPE.len())].copy_from_slice(DEFAULT_VM_TYPE); + + Address::from(result) + } +} + impl From for Address { #[inline] fn from(hash: H256) -> Self { @@ -145,13 +168,6 @@ impl Address { self.0.is_zero() } - /// Transmutes self to an (in principle) variable length boxed bytes object. - /// Both BoxedBytes and H256 keep the data on the heap, so only the pointer to that data needs to be transmuted. - /// Does not reallocate or copy data, the data on the heap remains untouched. - pub fn into_boxed_bytes(self) -> BoxedBytes { - self.0.into_boxed_bytes() - } - pub fn is_smart_contract_address(&self) -> bool { self.as_bytes() .iter() @@ -202,20 +218,6 @@ impl TopDecode for Address { } } -impl TypeAbiFrom for Address {} - -impl TypeAbi for Address { - type Unmanaged = Self; - - fn type_name() -> TypeName { - "Address".into() - } - - fn type_name_rust() -> TypeName { - "Address".into() - } -} - #[cfg(test)] mod address_tests { use super::*; @@ -251,11 +253,4 @@ mod address_tests { fn test_is_zero() { assert!(Address::zero().is_zero()); } - - #[test] - fn test_size_of() { - use core::mem::size_of; - assert_eq!(size_of::
(), size_of::()); - assert_eq!(size_of::>(), size_of::()); - } } diff --git a/framework/base/src/types/heap/boxed_bytes.rs b/vm-core/src/types/boxed_bytes.rs similarity index 96% rename from framework/base/src/types/heap/boxed_bytes.rs rename to vm-core/src/types/boxed_bytes.rs index 336b0874a8..b6fbb86297 100644 --- a/framework/base/src/types/heap/boxed_bytes.rs +++ b/vm-core/src/types/boxed_bytes.rs @@ -5,14 +5,14 @@ use alloc::{ vec::Vec, }; -use crate::{ - abi::{TypeAbi, TypeAbiFrom, TypeName}, - codec::*, -}; +use crate::codec::*; /// Simple wrapper around a boxed byte slice, /// but with a lot of optimized methods for manipulating it. /// The focus is on reducing code size rather improving speed. +/// +/// Used to be used extensively in smart contracts, before the introduction of ManagedBuffer, +/// but was superseded by it. #[derive(Clone, PartialEq, Eq, Debug)] pub struct BoxedBytes(Box<[u8]>); @@ -224,20 +224,6 @@ impl TopDecode for BoxedBytes { } } -impl TypeAbiFrom for BoxedBytes {} - -impl TypeAbi for BoxedBytes { - type Unmanaged = Self; - - fn type_name() -> TypeName { - "bytes".into() - } - - fn type_name_rust() -> TypeName { - "BoxedBytes".into() - } -} - //////////////////////////////////////////////////////////////////////////////// #[cfg(test)] diff --git a/framework/base/src/types/flags/mod.rs b/vm-core/src/types/flags.rs similarity index 84% rename from framework/base/src/types/flags/mod.rs rename to vm-core/src/types/flags.rs index b24a0d4fba..cfe9fc28ef 100644 --- a/framework/base/src/types/flags/mod.rs +++ b/vm-core/src/types/flags.rs @@ -2,8 +2,10 @@ mod code_metadata; mod esdt_local_role; mod esdt_local_role_flags; mod esdt_token_type; +mod token_type; pub use code_metadata::CodeMetadata; pub use esdt_local_role::EsdtLocalRole; pub use esdt_local_role_flags::EsdtLocalRoleFlags; pub use esdt_token_type::EsdtTokenType; +pub use token_type::TokenType; diff --git a/framework/base/src/types/flags/code_metadata.rs b/vm-core/src/types/flags/code_metadata.rs similarity index 69% rename from framework/base/src/types/flags/code_metadata.rs rename to vm-core/src/types/flags/code_metadata.rs index 9275e976cf..596bf9744c 100644 --- a/framework/base/src/types/flags/code_metadata.rs +++ b/vm-core/src/types/flags/code_metadata.rs @@ -1,17 +1,13 @@ #![allow(clippy::bad_bit_mask)] -use crate::{ - abi::{TypeAbi, TypeAbiFrom, TypeName}, - codec::*, - formatter::{hex_util, FormatByteReceiver, SCBinary, SCDisplay, SCLowerHex}, -}; +use crate::codec::*; use bitflags::bitflags; -const UPGRADEABLE_STRING: &[u8] = b"Upgradeable"; -const READABLE_STRING: &[u8] = b"Readable"; -const PAYABLE_STRING: &[u8] = b"Payable"; -const PAYABLE_BY_SC_STRING: &[u8] = b"PayableBySC"; -const DEFAULT_STRING: &[u8] = b"Default"; +const UPGRADEABLE_STRING: &str = "Upgradeable"; +const READABLE_STRING: &str = "Readable"; +const PAYABLE_STRING: &str = "Payable"; +const PAYABLE_BY_SC_STRING: &str = "PayableBySC"; +const DEFAULT_STRING: &str = "Default"; bitflags! { #[derive(Default, PartialEq, Debug, Clone, Copy)] @@ -45,6 +41,43 @@ impl CodeMetadata { pub fn to_byte_array(&self) -> [u8; 2] { self.bits().to_be_bytes() } + + pub fn to_vec(&self) -> Vec { + self.to_byte_array().to_vec() + } + + pub fn for_each_string_token(&self, mut f: F) { + let mut nothing_printed: bool = true; + if self.is_upgradeable() { + f(UPGRADEABLE_STRING); + nothing_printed = false; + } + if self.is_readable() { + if !nothing_printed { + f("|"); + } + f(READABLE_STRING); + nothing_printed = false; + } + if self.is_payable() { + if !nothing_printed { + f("|"); + } + f(PAYABLE_STRING); + nothing_printed = false; + } + if self.is_payable_by_sc() { + if !nothing_printed { + f("|"); + } + f(PAYABLE_BY_SC_STRING); + nothing_printed = false; + } + + if nothing_printed { + f(DEFAULT_STRING); + } + } } impl From<[u8; 2]> for CodeMetadata { @@ -61,6 +94,19 @@ impl From for CodeMetadata { } } +impl From<&[u8]> for CodeMetadata { + fn from(slice: &[u8]) -> Self { + let arr: [u8; 2] = slice.try_into().unwrap_or_default(); + CodeMetadata::from(arr) + } +} + +impl From<&Vec> for CodeMetadata { + fn from(v: &Vec) -> Self { + CodeMetadata::from(v.as_slice()) + } +} + impl NestedEncode for CodeMetadata { fn dep_encode_or_handle_err(&self, dest: &mut O, h: H) -> Result<(), H::HandledErr> where @@ -103,74 +149,6 @@ impl TopDecode for CodeMetadata { } } -impl TypeAbiFrom for CodeMetadata {} - -impl TypeAbi for CodeMetadata { - type Unmanaged = Self; - - fn type_name() -> TypeName { - "CodeMetadata".into() - } - - fn type_name_rust() -> TypeName { - "CodeMetadata".into() - } -} - -impl SCDisplay for CodeMetadata { - fn fmt(&self, f: &mut F) { - let mut nothing_printed: bool = true; - verify_metadata_and_append( - self.is_upgradeable(), - f, - UPGRADEABLE_STRING, - &mut nothing_printed, - ); - verify_metadata_and_append(self.is_readable(), f, READABLE_STRING, &mut nothing_printed); - verify_metadata_and_append(self.is_payable(), f, PAYABLE_STRING, &mut nothing_printed); - verify_metadata_and_append( - self.is_payable_by_sc(), - f, - PAYABLE_BY_SC_STRING, - &mut nothing_printed, - ); - if nothing_printed { - f.append_bytes(DEFAULT_STRING); - } - } -} - -impl SCLowerHex for CodeMetadata { - fn fmt(&self, f: &mut F) { - let num = self.bits().to_be_bytes(); - f.append_bytes(&hex_util::byte_to_hex_digits(num[0])[..]); - f.append_bytes(&hex_util::byte_to_hex_digits(num[1])[..]); - } -} - -impl SCBinary for CodeMetadata { - fn fmt(&self, f: &mut F) { - let num = self.bits().to_be_bytes(); - f.append_bytes(&hex_util::byte_to_binary_digits(num[0])[..]); - f.append_bytes(&hex_util::byte_to_binary_digits(num[1])[..]); - } -} - -fn verify_metadata_and_append( - constraint: bool, - f: &mut F, - bytes_to_append: &[u8], - nothing_printed: &mut bool, -) { - if constraint { - if !*nothing_printed { - f.append_bytes(b"|"); - } - f.append_bytes(bytes_to_append); - *nothing_printed = false; - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/vm/src/types/vm_esdt_local_role.rs b/vm-core/src/types/flags/esdt_local_role.rs similarity index 92% rename from vm/src/types/vm_esdt_local_role.rs rename to vm-core/src/types/flags/esdt_local_role.rs index 40c383b869..048d3876ce 100644 --- a/vm/src/types/vm_esdt_local_role.rs +++ b/vm-core/src/types/flags/esdt_local_role.rs @@ -1,4 +1,8 @@ use super::EsdtLocalRoleFlags; +use crate::codec::{ + self, + derive::{NestedDecode, NestedEncode, TopDecode, TopEncode}, +}; const ESDT_ROLE_NONE: &str = ""; const ESDT_ROLE_LOCAL_MINT: &str = "ESDTRoleLocalMint"; @@ -10,12 +14,7 @@ const ESDT_ROLE_NFT_ADD_URI: &str = "ESDTRoleNFTAddURI"; const ESDT_ROLE_NFT_UPDATE_ATTRIBUTES: &str = "ESDTRoleNFTUpdateAttributes"; const ESDT_ROLE_TRANSFER: &str = "ESDTTransferRole"; -/// The VM implementation for EsdtLocalRole, used internally in builtin functions. -/// -/// There is another near-identical implementation in the framework, used for communicating with the VM. -/// -/// It might be a good idea to move it to some "common ground" crate, between the framework and the VM. -#[derive(Clone, PartialEq, Eq, Debug, Copy)] +#[derive(TopDecode, TopEncode, NestedDecode, NestedEncode, Clone, PartialEq, Eq, Debug, Copy)] pub enum EsdtLocalRole { None, Mint, @@ -43,6 +42,10 @@ impl EsdtLocalRole { } } + pub fn as_role_name(&self) -> &'static [u8] { + self.name().as_bytes() + } + pub fn name(&self) -> &'static str { match self { Self::None => ESDT_ROLE_NONE, diff --git a/framework/base/src/types/flags/esdt_local_role_flags.rs b/vm-core/src/types/flags/esdt_local_role_flags.rs similarity index 100% rename from framework/base/src/types/flags/esdt_local_role_flags.rs rename to vm-core/src/types/flags/esdt_local_role_flags.rs diff --git a/framework/base/src/types/flags/esdt_token_type.rs b/vm-core/src/types/flags/esdt_token_type.rs similarity index 89% rename from framework/base/src/types/flags/esdt_token_type.rs rename to vm-core/src/types/flags/esdt_token_type.rs index e80b91590d..74db07c9a6 100644 --- a/framework/base/src/types/flags/esdt_token_type.rs +++ b/vm-core/src/types/flags/esdt_token_type.rs @@ -1,4 +1,4 @@ -use multiversx_sc_derive::{type_abi, ManagedVecItem}; +// use multiversx_sc_derive::{type_abi, ManagedVecItem}; use crate::codec::{ self, @@ -11,14 +11,9 @@ const ESDT_TYPE_SEMI_FUNGIBLE: &[u8] = b"SemiFungibleESDT"; const ESDT_TYPE_META: &[u8] = b"MetaESDT"; const ESDT_TYPE_INVALID: &[u8] = &[]; -use crate as multiversx_sc; // needed by the TypeAbi generated code - // Note: In the current implementation, SemiFungible is never returned -#[type_abi] -#[derive( - TopDecode, TopEncode, NestedDecode, NestedEncode, Clone, PartialEq, Eq, Debug, ManagedVecItem, -)] +#[derive(TopDecode, TopEncode, NestedDecode, NestedEncode, Clone, PartialEq, Eq, Debug)] pub enum EsdtTokenType { Fungible, NonFungible, diff --git a/vm/src/types/vm_token_type.rs b/vm-core/src/types/flags/token_type.rs similarity index 51% rename from vm/src/types/vm_token_type.rs rename to vm-core/src/types/flags/token_type.rs index 18670a90dc..77ff975a45 100644 --- a/vm/src/types/vm_token_type.rs +++ b/vm-core/src/types/flags/token_type.rs @@ -1,18 +1,18 @@ #[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum VMTokenType { +pub enum TokenType { Fungible, SemiFungible, Meta, NonFungible, } -impl VMTokenType { +impl TokenType { pub fn from_system_sc_arg(raw: &[u8]) -> Self { match raw { - b"FNG" => VMTokenType::Fungible, - b"SFT" => VMTokenType::SemiFungible, - b"META" => VMTokenType::Meta, - b"NFT" => VMTokenType::NonFungible, + b"FNG" => TokenType::Fungible, + b"SFT" => TokenType::SemiFungible, + b"META" => TokenType::Meta, + b"NFT" => TokenType::NonFungible, _ => panic!("invalid token type"), } } diff --git a/vm-core/src/types/h256.rs b/vm-core/src/types/h256.rs new file mode 100644 index 0000000000..8a7b63d1a1 --- /dev/null +++ b/vm-core/src/types/h256.rs @@ -0,0 +1,223 @@ +use alloc::{boxed::Box, vec::Vec}; +use core::fmt::Debug; + +const ZERO_32: &[u8] = &[0u8; 32]; + +/// Type that holds 32 bytes of data. +/// Data is kept on the heap to keep wasm size low and avoid copies. +#[derive(Hash, PartialEq, Eq, Clone, Debug)] +pub struct H256([u8; 32]); + +impl H256 { + pub const fn new(bytes: [u8; 32]) -> Self { + H256(bytes) + } +} + +impl From<[u8; 32]> for H256 { + /// Constructs a hash type from the given bytes array of fixed length. + /// + /// # Note + /// + /// The given bytes are interpreted in big endian order. + fn from(arr: [u8; 32]) -> Self { + H256::new(arr) + } +} + +impl<'a> From<&'a [u8; 32]> for H256 { + /// Constructs a hash type from the given reference + /// to the bytes array of fixed length. + /// + /// # Note + /// + /// The given bytes are interpreted in big endian order. + #[inline] + fn from(bytes: &'a [u8; 32]) -> Self { + H256::new(*bytes) + } +} + +impl<'a> From<&'a mut [u8; 32]> for H256 { + /// Constructs a hash type from the given reference + /// to the mutable bytes array of fixed length. + /// + /// # Note + /// + /// The given bytes are interpreted in big endian order. + #[inline] + fn from(bytes: &'a mut [u8; 32]) -> Self { + H256::new(*bytes) + } +} + +impl From> for H256 { + #[inline] + fn from(bytes: Box<[u8; 32]>) -> Self { + H256::new(*bytes) + } +} + +impl H256 { + pub fn from_slice(slice: &[u8]) -> Self { + let mut arr = [0u8; 32]; + let len = core::cmp::min(slice.len(), 32); + arr[..len].copy_from_slice(&slice[..len]); + H256::new(arr) + } +} + +impl From for [u8; 32] { + fn from(s: H256) -> Self { + s.0 + } +} + +impl AsRef<[u8]> for H256 { + #[inline] + fn as_ref(&self) -> &[u8] { + self.as_bytes() + } +} + +impl AsMut<[u8]> for H256 { + #[inline] + fn as_mut(&mut self) -> &mut [u8] { + self.0.as_mut() + } +} + +impl H256 { + /// Returns a new zero-initialized fixed hash. + pub fn zero() -> Self { + H256([0u8; 32]) + } + + /// Returns the size of this hash in bytes. + #[inline] + pub fn len_bytes() -> usize { + 32 + } + + /// Extracts a byte slice containing the entire fixed hash. + #[inline] + pub fn as_bytes(&self) -> &[u8] { + self.0.as_ref() + } + + #[inline] + pub fn as_array(&self) -> &[u8; 32] { + &self.0 + } + + #[inline] + pub fn copy_to_array(&self, target: &mut [u8; 32]) { + target.copy_from_slice(&self.0[..]); + } + + #[inline] + pub fn to_vec(&self) -> Vec { + self.0[..].to_vec() + } + + /// Pointer to the data on the heap. + #[inline] + pub fn as_ptr(&self) -> *const u8 { + self.0.as_ptr() + } + + /// Returns an unsafe mutable pointer to the data on the heap. + /// Used by the API to populate data. + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut u8 { + self.0.as_mut_ptr() + } + + /// True if all 32 bytes of the hash are zero. + pub fn is_zero(&self) -> bool { + self.as_bytes() == ZERO_32 + } +} + +use crate::codec::*; + +impl NestedEncode for H256 { + fn dep_encode_or_handle_err(&self, dest: &mut O, _h: H) -> Result<(), H::HandledErr> + where + O: NestedEncodeOutput, + H: EncodeErrorHandler, + { + dest.write(&self.0[..]); + Ok(()) + } +} + +impl TopEncode for H256 { + fn top_encode_or_handle_err(&self, output: O, _h: H) -> Result<(), H::HandledErr> + where + O: TopEncodeOutput, + H: EncodeErrorHandler, + { + output.set_slice_u8(&self.0[..]); + Ok(()) + } +} + +impl NestedDecode for H256 { + fn dep_decode_or_handle_err(input: &mut I, h: H) -> Result + where + I: NestedDecodeInput, + H: DecodeErrorHandler, + { + let mut res = H256::zero(); + input.read_into(res.as_mut(), h)?; + Ok(res) + } +} + +impl TopDecode for H256 { + fn top_decode_or_handle_err(input: I, h: H) -> Result + where + I: TopDecodeInput, + H: DecodeErrorHandler, + { + Ok(Self::new(<[u8; 32]>::top_decode_or_handle_err(input, h)?)) + } +} + +#[cfg(test)] +mod h256_tests { + use super::*; + use crate::codec::test_util::{check_top_encode, check_top_encode_decode}; + use alloc::vec::Vec; + + #[test] + fn test_h256_from_array() { + let addr = H256::from([4u8; 32]); + check_top_encode_decode(addr, &[4u8; 32]); + } + + #[test] + fn test_opt_h256() { + let addr = H256::from([4u8; 32]); + let mut expected: Vec = Vec::new(); + expected.push(1u8); + expected.extend_from_slice(&[4u8; 32]); + check_top_encode_decode(Some(addr), expected.as_slice()); + } + + #[test] + fn test_ser_h256_ref() { + let addr = H256::from([4u8; 32]); + let expected_bytes: &[u8] = &[4u8; 32 * 3]; + + let tuple = (&addr, &&&addr, addr.clone()); + let serialized_bytes = check_top_encode(&tuple); + assert_eq!(serialized_bytes.as_slice(), expected_bytes); + } + + #[test] + fn test_is_zero() { + assert!(H256::zero().is_zero()); + } +} diff --git a/vm-core/src/types/heap_address.rs b/vm-core/src/types/heap_address.rs new file mode 100644 index 0000000000..57e053e815 --- /dev/null +++ b/vm-core/src/types/heap_address.rs @@ -0,0 +1,243 @@ +use super::{heap_h256::HeapH256, BoxedBytes}; + +use alloc::{boxed::Box, vec::Vec}; +use core::fmt::Debug; + +const SC_ADDRESS_NUM_LEADING_ZEROS: u8 = 8; + +/// Old smart contracts were using this Address implementation, +/// which was explicitly relying on the heap, to avoid large data copies on the stack. +/// +/// It is no longer used, kept for reference. +#[derive(Hash, PartialEq, Eq, Clone, Debug)] +pub struct HeapAddress(HeapH256); + +impl From for HeapAddress { + #[inline] + fn from(hash: HeapH256) -> Self { + HeapAddress(hash) + } +} + +impl From for HeapH256 { + #[inline] + fn from(address: HeapAddress) -> Self { + address.0 + } +} + +impl<'a> From<&'a HeapAddress> for &'a HeapH256 { + #[inline] + fn from(address: &'a HeapAddress) -> Self { + &address.0 + } +} + +impl From<[u8; 32]> for HeapAddress { + #[inline] + fn from(arr: [u8; 32]) -> Self { + HeapAddress(HeapH256::from(arr)) + } +} + +impl<'a> From<&'a [u8; 32]> for HeapAddress { + #[inline] + fn from(bytes: &'a [u8; 32]) -> Self { + HeapAddress(HeapH256::from(bytes)) + } +} + +impl<'a> From<&'a mut [u8; 32]> for HeapAddress { + #[inline] + fn from(bytes: &'a mut [u8; 32]) -> Self { + HeapAddress(HeapH256::from(bytes)) + } +} + +impl From> for HeapAddress { + #[inline] + fn from(bytes: Box<[u8; 32]>) -> Self { + HeapAddress(HeapH256::from(bytes)) + } +} + +impl HeapAddress { + pub fn from_slice(slice: &[u8]) -> Self { + HeapAddress(HeapH256::from_slice(slice)) + } +} + +impl From for [u8; 32] { + #[inline] + fn from(addr: HeapAddress) -> Self { + addr.0.into() + } +} + +impl AsRef<[u8]> for HeapAddress { + #[inline] + fn as_ref(&self) -> &[u8] { + self.0.as_ref() + } +} + +impl AsMut<[u8]> for HeapAddress { + #[inline] + fn as_mut(&mut self) -> &mut [u8] { + self.0.as_mut() + } +} + +impl HeapAddress { + /// Returns a new address of 32 zeros. + /// Allocates directly in heap. + /// Minimal resulting wasm code (14 bytes if not inlined). + pub fn zero() -> Self { + HeapAddress(HeapH256::zero()) + } + + /// Returns the size of an address in bytes. + #[inline] + pub fn len_bytes() -> usize { + HeapH256::len_bytes() + } + + /// Extracts a byte slice containing the entire fixed hash. + #[inline] + pub fn as_bytes(&self) -> &[u8] { + self.0.as_bytes() + } + + #[inline] + pub fn as_array(&self) -> &[u8; 32] { + self.0.as_array() + } + + #[inline] + pub fn copy_to_array(&self, target: &mut [u8; 32]) { + self.0.copy_to_array(target) + } + + #[inline] + pub fn to_vec(&self) -> Vec { + self.0.to_vec() + } + + /// Pointer to the data on the heap. + #[inline] + pub fn as_ptr(&self) -> *const u8 { + self.0.as_ptr() + } + + /// Returns an unsafe mutable pointer to the data on the heap. + /// Used by the API to populate data. + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut u8 { + self.0.as_mut_ptr() + } + + /// True if all 32 bytes of the hash are zero. + pub fn is_zero(&self) -> bool { + self.0.is_zero() + } + + /// Transmutes self to an (in principle) variable length boxed bytes object. + /// Both BoxedBytes and H256 keep the data on the heap, so only the pointer to that data needs to be transmuted. + /// Does not reallocate or copy data, the data on the heap remains untouched. + pub fn into_boxed_bytes(self) -> BoxedBytes { + self.0.into_boxed_bytes() + } + + pub fn is_smart_contract_address(&self) -> bool { + self.as_bytes() + .iter() + .take(SC_ADDRESS_NUM_LEADING_ZEROS.into()) + .all(|item| item == &0u8) + } +} + +use crate::codec::*; + +impl NestedEncode for HeapAddress { + fn dep_encode_or_handle_err(&self, dest: &mut O, h: H) -> Result<(), H::HandledErr> + where + O: NestedEncodeOutput, + H: EncodeErrorHandler, + { + self.0.dep_encode_or_handle_err(dest, h) + } +} + +impl TopEncode for HeapAddress { + fn top_encode_or_handle_err(&self, output: O, h: H) -> Result<(), H::HandledErr> + where + O: TopEncodeOutput, + H: EncodeErrorHandler, + { + self.0.top_encode_or_handle_err(output, h) + } +} + +impl NestedDecode for HeapAddress { + fn dep_decode_or_handle_err(input: &mut I, h: H) -> Result + where + I: NestedDecodeInput, + H: DecodeErrorHandler, + { + Ok(HeapAddress(HeapH256::dep_decode_or_handle_err(input, h)?)) + } +} + +impl TopDecode for HeapAddress { + fn top_decode_or_handle_err(input: I, h: H) -> Result + where + I: TopDecodeInput, + H: DecodeErrorHandler, + { + Ok(HeapAddress(HeapH256::top_decode_or_handle_err(input, h)?)) + } +} + +#[cfg(test)] +mod address_tests { + use super::*; + use crate::codec::test_util::{check_top_encode, check_top_encode_decode}; + use alloc::vec::Vec; + + #[test] + fn test_address() { + let addr = HeapAddress::from([4u8; 32]); + check_top_encode_decode(addr, &[4u8; 32]); + } + + #[test] + fn test_opt_address() { + let addr = HeapAddress::from([4u8; 32]); + let mut expected: Vec = Vec::new(); + expected.push(1u8); + expected.extend_from_slice(&[4u8; 32]); + check_top_encode_decode(Some(addr), expected.as_slice()); + } + + #[test] + fn test_ser_address_ref() { + let addr = HeapAddress::from([4u8; 32]); + let expected_bytes: &[u8] = &[4u8; 32 * 3]; + + let tuple = (&addr, &&&addr, addr.clone()); + let serialized_bytes = check_top_encode(&tuple); + assert_eq!(serialized_bytes.as_slice(), expected_bytes); + } + + #[test] + fn test_is_zero() { + assert!(HeapAddress::zero().is_zero()); + } + + #[test] + fn test_size_of() { + use core::mem::size_of; + assert_eq!(size_of::(), size_of::()); + assert_eq!(size_of::>(), size_of::()); + } +} diff --git a/framework/base/src/types/heap/h256.rs b/vm-core/src/types/heap_h256.rs similarity index 80% rename from framework/base/src/types/heap/h256.rs rename to vm-core/src/types/heap_h256.rs index f440765d00..80f5a54f67 100644 --- a/framework/base/src/types/heap/h256.rs +++ b/vm-core/src/types/heap_h256.rs @@ -1,19 +1,17 @@ -use crate::{ - abi::{TypeAbi, TypeAbiFrom, TypeName}, - types::heap::BoxedBytes, -}; use alloc::{boxed::Box, vec::Vec}; use core::fmt::Debug; const ERR_BAD_H256_LENGTH: &str = "bad H256 length"; const ZERO_32: &[u8] = &[0u8; 32]; -/// Type that holds 32 bytes of data. -/// Data is kept on the heap to keep wasm size low and avoid copies. +/// Old smart contracts were using this H256 implementation, +/// which was explicitly relying on the heap, to avoid large data copies on the stack. +/// +/// It is no longer used, kept for reference. #[derive(Hash, PartialEq, Eq, Clone, Debug)] -pub struct H256(Box<[u8; 32]>); +pub struct HeapH256(Box<[u8; 32]>); -impl From<[u8; 32]> for H256 { +impl From<[u8; 32]> for HeapH256 { /// Constructs a hash type from the given bytes array of fixed length. /// /// # Note @@ -21,11 +19,11 @@ impl From<[u8; 32]> for H256 { /// The given bytes are interpreted in big endian order. #[inline] fn from(arr: [u8; 32]) -> Self { - H256(Box::new(arr)) + HeapH256(Box::new(arr)) } } -impl<'a> From<&'a [u8; 32]> for H256 { +impl<'a> From<&'a [u8; 32]> for HeapH256 { /// Constructs a hash type from the given reference /// to the bytes array of fixed length. /// @@ -34,11 +32,11 @@ impl<'a> From<&'a [u8; 32]> for H256 { /// The given bytes are interpreted in big endian order. #[inline] fn from(bytes: &'a [u8; 32]) -> Self { - H256(Box::new(*bytes)) + HeapH256(Box::new(*bytes)) } } -impl<'a> From<&'a mut [u8; 32]> for H256 { +impl<'a> From<&'a mut [u8; 32]> for HeapH256 { /// Constructs a hash type from the given reference /// to the mutable bytes array of fixed length. /// @@ -47,48 +45,48 @@ impl<'a> From<&'a mut [u8; 32]> for H256 { /// The given bytes are interpreted in big endian order. #[inline] fn from(bytes: &'a mut [u8; 32]) -> Self { - H256(Box::new(*bytes)) + HeapH256(Box::new(*bytes)) } } -impl From> for H256 { +impl From> for HeapH256 { #[inline] fn from(bytes: Box<[u8; 32]>) -> Self { - H256(bytes) + HeapH256(bytes) } } -impl H256 { +impl HeapH256 { pub fn from_slice(slice: &[u8]) -> Self { let mut arr = [0u8; 32]; let len = core::cmp::min(slice.len(), 32); arr[..len].copy_from_slice(&slice[..len]); - H256(Box::new(arr)) + HeapH256(Box::new(arr)) } } -impl From for [u8; 32] { +impl From for [u8; 32] { #[inline] - fn from(s: H256) -> Self { + fn from(s: HeapH256) -> Self { *(s.0) } } -impl AsRef<[u8]> for H256 { +impl AsRef<[u8]> for HeapH256 { #[inline] fn as_ref(&self) -> &[u8] { self.as_bytes() } } -impl AsMut<[u8]> for H256 { +impl AsMut<[u8]> for HeapH256 { #[inline] fn as_mut(&mut self) -> &mut [u8] { self.0.as_mut() } } -impl H256 { +impl HeapH256 { /// Returns a new zero-initialized fixed hash. /// Allocates directly in heap. /// Minimal resulting wasm code (14 bytes if not inlined). @@ -96,7 +94,7 @@ impl H256 { use alloc::alloc::{alloc_zeroed, Layout}; unsafe { let ptr = alloc_zeroed(Layout::new::<[u8; 32]>()) as *mut [u8; 32]; - H256(Box::from_raw(ptr)) + HeapH256(Box::from_raw(ptr)) } } @@ -159,7 +157,9 @@ impl H256 { use crate::codec::*; -impl NestedEncode for H256 { +use super::BoxedBytes; + +impl NestedEncode for HeapH256 { fn dep_encode_or_handle_err(&self, dest: &mut O, _h: H) -> Result<(), H::HandledErr> where O: NestedEncodeOutput, @@ -170,7 +170,7 @@ impl NestedEncode for H256 { } } -impl TopEncode for H256 { +impl TopEncode for HeapH256 { fn top_encode_or_handle_err(&self, output: O, _h: H) -> Result<(), H::HandledErr> where O: TopEncodeOutput, @@ -181,19 +181,19 @@ impl TopEncode for H256 { } } -impl NestedDecode for H256 { +impl NestedDecode for HeapH256 { fn dep_decode_or_handle_err(input: &mut I, h: H) -> Result where I: NestedDecodeInput, H: DecodeErrorHandler, { - let mut res = H256::zero(); + let mut res = HeapH256::zero(); input.read_into(res.as_mut(), h)?; Ok(res) } } -impl H256 { +impl HeapH256 { // Transmutes directly from a (variable-sized) boxed byte slice. // Will exit early if the input length is not 32. // Designed to be used especially in deserializer implementations. @@ -207,14 +207,14 @@ impl H256 { if input.len() == 32 { let raw = Box::into_raw(input); let array_box = unsafe { Box::<[u8; 32]>::from_raw(raw as *mut [u8; 32]) }; - Ok(H256(array_box)) + Ok(HeapH256(array_box)) } else { Err(h.handle_error(DecodeError::from(ERR_BAD_H256_LENGTH))) } } } -impl TopDecode for H256 { +impl TopDecode for HeapH256 { fn top_decode_or_handle_err(input: I, h: H) -> Result where I: TopDecodeInput, @@ -224,20 +224,6 @@ impl TopDecode for H256 { } } -impl TypeAbiFrom for H256 {} - -impl TypeAbi for H256 { - type Unmanaged = Self; - - fn type_name() -> TypeName { - "H256".into() - } - - fn type_name_rust() -> TypeName { - "H256".into() - } -} - #[cfg(test)] mod h256_tests { use super::*; @@ -246,13 +232,13 @@ mod h256_tests { #[test] fn test_h256_from_array() { - let addr = H256::from([4u8; 32]); + let addr = HeapH256::from([4u8; 32]); check_top_encode_decode(addr, &[4u8; 32]); } #[test] fn test_opt_h256() { - let addr = H256::from([4u8; 32]); + let addr = HeapH256::from([4u8; 32]); let mut expected: Vec = Vec::new(); expected.push(1u8); expected.extend_from_slice(&[4u8; 32]); @@ -261,7 +247,7 @@ mod h256_tests { #[test] fn test_ser_h256_ref() { - let addr = H256::from([4u8; 32]); + let addr = HeapH256::from([4u8; 32]); let expected_bytes: &[u8] = &[4u8; 32 * 3]; let tuple = (&addr, &&&addr, addr.clone()); @@ -271,20 +257,20 @@ mod h256_tests { #[test] fn test_is_zero() { - assert!(H256::zero().is_zero()); + assert!(HeapH256::zero().is_zero()); } #[test] fn test_size_of() { use core::mem::size_of; - assert_eq!(size_of::(), size_of::()); - assert_eq!(size_of::>(), size_of::()); + assert_eq!(size_of::(), size_of::()); + assert_eq!(size_of::>(), size_of::()); } #[test] fn test_into_boxed_bytes() { let array = b"32_bytes________________________"; - let h256 = H256::from(array); + let h256 = HeapH256::from(array); let bb = h256.into_boxed_bytes(); assert_eq!(bb.as_slice(), &array[..]); } diff --git a/vm/Cargo.toml b/vm/Cargo.toml index 78c36567af..0810f82eba 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -34,5 +34,9 @@ rand = { version= "0.8.5", optional = true } rand_seeder = "0.3.0" ed25519-dalek = "2.1.0" +[dependencies.multiversx-chain-core] +version = "=0.10.0" +path = "../vm-core" + [dependencies.multiversx-chain-vm-executor] version = "0.2.0" diff --git a/vm/src/lib.rs b/vm/src/lib.rs index 48f9c288e1..51e8931642 100644 --- a/vm/src/lib.rs +++ b/vm/src/lib.rs @@ -14,5 +14,8 @@ pub use world_mock::BlockchainMock; // Re-exporting the executor, for convenience. pub use multiversx_chain_vm_executor as executor; +// Re-exporting the VM-core, for convenience. +pub use multiversx_chain_core as chain_core; + #[macro_use] extern crate alloc; diff --git a/vm/src/tx_execution/builtin_function_mocks.rs b/vm/src/tx_execution/builtin_function_mocks.rs index dff42101cc..d50044d0c1 100644 --- a/vm/src/tx_execution/builtin_function_mocks.rs +++ b/vm/src/tx_execution/builtin_function_mocks.rs @@ -3,8 +3,6 @@ mod builtin_func_trait; mod esdt_nft; mod general; mod transfer; -pub mod vm_builtin_function_names; pub use builtin_func_container::BuiltinFunctionContainer; pub use builtin_func_trait::{BuiltinFunction, BuiltinFunctionEsdtTransferInfo}; -pub use vm_builtin_function_names as builtin_function_names; diff --git a/vm/src/tx_execution/builtin_function_mocks/builtin_func_container.rs b/vm/src/tx_execution/builtin_function_mocks/builtin_func_container.rs index 8b5a302377..39220d9722 100644 --- a/vm/src/tx_execution/builtin_function_mocks/builtin_func_container.rs +++ b/vm/src/tx_execution/builtin_function_mocks/builtin_func_container.rs @@ -1,6 +1,5 @@ use super::{ builtin_func_trait::BuiltinFunction, - builtin_function_names::*, esdt_nft::{ ESDTLocalBurn, ESDTLocalMint, ESDTNftAddQuantity, ESDTNftAddUri, ESDTNftBurn, ESDTNftCreate, ESDTNftUpdateAttributes, @@ -9,12 +8,15 @@ use super::{ transfer::{ESDTMultiTransfer, ESDTNftTransfer, ESDTTransfer}, BuiltinFunctionEsdtTransferInfo, }; + use crate::{ tx_execution::BlockchainVMRef, tx_mock::{BlockchainUpdate, TxCache, TxInput, TxResult}, types::EsdtLocalRole, }; +use crate::chain_core::builtin_func_names::*; + /// Container for builtin function logic. /// /// Currently has no data, but could conceivably be configurable in the future. diff --git a/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_local_burn.rs b/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_local_burn.rs index 88d84f5681..b3f42b3844 100644 --- a/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_local_burn.rs +++ b/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_local_burn.rs @@ -1,7 +1,8 @@ use num_bigint::BigUint; use crate::{ - tx_execution::{builtin_function_names::ESDT_LOCAL_BURN_FUNC_NAME, BlockchainVMRef}, + chain_core::builtin_func_names::ESDT_LOCAL_BURN_FUNC_NAME, + tx_execution::BlockchainVMRef, tx_mock::{BlockchainUpdate, TxCache, TxInput, TxLog, TxResult}, }; diff --git a/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_local_mint.rs b/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_local_mint.rs index 73f35aef69..cb59eee3d5 100644 --- a/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_local_mint.rs +++ b/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_local_mint.rs @@ -1,8 +1,8 @@ use num_bigint::BigUint; -use crate::tx_execution::{builtin_function_names::ESDT_LOCAL_MINT_FUNC_NAME, BlockchainVMRef}; - use crate::{ + chain_core::builtin_func_names::ESDT_LOCAL_MINT_FUNC_NAME, + tx_execution::BlockchainVMRef, tx_mock::{BlockchainUpdate, TxCache, TxInput, TxLog, TxResult}, world_mock::EsdtInstanceMetadata, }; diff --git a/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_nft_add_quantity_mock.rs b/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_nft_add_quantity_mock.rs index f462d64ef3..4ef229d686 100644 --- a/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_nft_add_quantity_mock.rs +++ b/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_nft_add_quantity_mock.rs @@ -1,13 +1,10 @@ use num_bigint::BigUint; use crate::{ + chain_core::builtin_func_names::ESDT_NFT_ADD_QUANTITY_FUNC_NAME, tx_execution::BlockchainVMRef, - types::{top_decode_u64, top_encode_u64}, -}; - -use crate::{ - tx_execution::builtin_function_names::ESDT_NFT_ADD_QUANTITY_FUNC_NAME, tx_mock::{BlockchainUpdate, TxCache, TxInput, TxLog, TxResult}, + types::{top_decode_u64, top_encode_u64}, world_mock::EsdtInstanceMetadata, }; diff --git a/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_nft_add_uri_mock.rs b/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_nft_add_uri_mock.rs index 19966902b4..3c4d2b986b 100644 --- a/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_nft_add_uri_mock.rs +++ b/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_nft_add_uri_mock.rs @@ -1,5 +1,6 @@ use crate::{ - tx_execution::{builtin_function_names::ESDT_NFT_ADD_URI_FUNC_NAME, BlockchainVMRef}, + chain_core::builtin_func_names::ESDT_NFT_ADD_URI_FUNC_NAME, + tx_execution::BlockchainVMRef, tx_mock::{BlockchainUpdate, TxCache, TxInput, TxLog, TxResult}, types::{top_decode_u64, top_encode_u64}, }; diff --git a/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_nft_burn_mock.rs b/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_nft_burn_mock.rs index 26ffe468a6..ef6362f073 100644 --- a/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_nft_burn_mock.rs +++ b/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_nft_burn_mock.rs @@ -1,7 +1,8 @@ use num_bigint::BigUint; use crate::{ - tx_execution::{builtin_function_names::ESDT_NFT_BURN_FUNC_NAME, BlockchainVMRef}, + chain_core::builtin_func_names::ESDT_NFT_BURN_FUNC_NAME, + tx_execution::BlockchainVMRef, tx_mock::{BlockchainUpdate, TxCache, TxInput, TxLog, TxResult}, types::{top_decode_u64, top_encode_u64}, }; diff --git a/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_nft_create_mock.rs b/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_nft_create_mock.rs index 2f538c9e67..0007ec3c91 100644 --- a/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_nft_create_mock.rs +++ b/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_nft_create_mock.rs @@ -1,7 +1,8 @@ use num_bigint::BigUint; use crate::{ - tx_execution::{builtin_function_names::ESDT_NFT_CREATE_FUNC_NAME, BlockchainVMRef}, + chain_core::builtin_func_names::ESDT_NFT_CREATE_FUNC_NAME, + tx_execution::BlockchainVMRef, tx_mock::{BlockchainUpdate, TxCache, TxInput, TxLog, TxResult}, types::{top_decode_u64, top_encode_u64}, world_mock::{EsdtInstance, EsdtInstanceMetadata}, diff --git a/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_nft_update_attriutes_mock.rs b/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_nft_update_attriutes_mock.rs index 49c2629cfb..d6f088f4f6 100644 --- a/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_nft_update_attriutes_mock.rs +++ b/vm/src/tx_execution/builtin_function_mocks/esdt_nft/esdt_nft_update_attriutes_mock.rs @@ -1,5 +1,6 @@ use crate::{ - tx_execution::{builtin_function_names::ESDT_NFT_UPDATE_ATTRIBUTES_FUNC_NAME, BlockchainVMRef}, + chain_core::builtin_func_names::ESDT_NFT_UPDATE_ATTRIBUTES_FUNC_NAME, + tx_execution::BlockchainVMRef, tx_mock::{BlockchainUpdate, TxCache, TxInput, TxLog, TxResult}, types::{top_decode_u64, top_encode_u64}, }; diff --git a/vm/src/tx_execution/builtin_function_mocks/general/change_owner_mock.rs b/vm/src/tx_execution/builtin_function_mocks/general/change_owner_mock.rs index 8352b606cd..17d168a4cd 100644 --- a/vm/src/tx_execution/builtin_function_mocks/general/change_owner_mock.rs +++ b/vm/src/tx_execution/builtin_function_mocks/general/change_owner_mock.rs @@ -1,8 +1,6 @@ -use crate::tx_execution::{ - builtin_function_names::CHANGE_OWNER_BUILTIN_FUNC_NAME, BlockchainVMRef, -}; - use crate::{ + chain_core::builtin_func_names::CHANGE_OWNER_BUILTIN_FUNC_NAME, + tx_execution::BlockchainVMRef, tx_mock::{BlockchainUpdate, TxCache, TxInput, TxResult}, types::VMAddress, }; diff --git a/vm/src/tx_execution/builtin_function_mocks/general/claim_developer_rewards_mock.rs b/vm/src/tx_execution/builtin_function_mocks/general/claim_developer_rewards_mock.rs index 0b7e9c694f..3d705959f1 100644 --- a/vm/src/tx_execution/builtin_function_mocks/general/claim_developer_rewards_mock.rs +++ b/vm/src/tx_execution/builtin_function_mocks/general/claim_developer_rewards_mock.rs @@ -1,10 +1,11 @@ -use crate::tx_execution::{ - builtin_function_names::CLAIM_DEVELOPER_REWARDS_FUNC_NAME, BlockchainVMRef, -}; use num_bigint::BigUint; use num_traits::Zero; -use crate::tx_mock::{BlockchainUpdate, TxCache, TxInput, TxResult}; +use crate::{ + chain_core::builtin_func_names::CLAIM_DEVELOPER_REWARDS_FUNC_NAME, + tx_execution::BlockchainVMRef, + tx_mock::{BlockchainUpdate, TxCache, TxInput, TxResult}, +}; use super::super::builtin_func_trait::BuiltinFunction; diff --git a/vm/src/tx_execution/builtin_function_mocks/general/delete_username_mock.rs b/vm/src/tx_execution/builtin_function_mocks/general/delete_username_mock.rs index c697f76859..719454c20a 100644 --- a/vm/src/tx_execution/builtin_function_mocks/general/delete_username_mock.rs +++ b/vm/src/tx_execution/builtin_function_mocks/general/delete_username_mock.rs @@ -1,6 +1,8 @@ -use crate::tx_execution::{builtin_function_names::DELETE_USERNAME_FUNC_NAME, BlockchainVMRef}; - -use crate::tx_mock::{BlockchainUpdate, TxCache, TxInput, TxResult}; +use crate::{ + chain_core::builtin_func_names::DELETE_USERNAME_FUNC_NAME, + tx_execution::BlockchainVMRef, + tx_mock::{BlockchainUpdate, TxCache, TxInput, TxResult}, +}; use super::super::builtin_func_trait::BuiltinFunction; diff --git a/vm/src/tx_execution/builtin_function_mocks/general/migrate_username_mock.rs b/vm/src/tx_execution/builtin_function_mocks/general/migrate_username_mock.rs index ea7c5ec57a..8674aed324 100644 --- a/vm/src/tx_execution/builtin_function_mocks/general/migrate_username_mock.rs +++ b/vm/src/tx_execution/builtin_function_mocks/general/migrate_username_mock.rs @@ -1,5 +1,5 @@ -use crate::tx_execution::{builtin_function_names::MIGRATE_USERNAME_FUNC_NAME, BlockchainVMRef}; - +use crate::chain_core::builtin_func_names::MIGRATE_USERNAME_FUNC_NAME; +use crate::tx_execution::BlockchainVMRef; use crate::tx_mock::{BlockchainUpdate, TxCache, TxInput, TxResult}; use super::super::builtin_func_trait::BuiltinFunction; diff --git a/vm/src/tx_execution/builtin_function_mocks/general/set_username_mock.rs b/vm/src/tx_execution/builtin_function_mocks/general/set_username_mock.rs index 8df9d6316d..65e1c95f1e 100644 --- a/vm/src/tx_execution/builtin_function_mocks/general/set_username_mock.rs +++ b/vm/src/tx_execution/builtin_function_mocks/general/set_username_mock.rs @@ -1,5 +1,5 @@ -use crate::tx_execution::{builtin_function_names::SET_USERNAME_FUNC_NAME, BlockchainVMRef}; - +use crate::chain_core::builtin_func_names::SET_USERNAME_FUNC_NAME; +use crate::tx_execution::BlockchainVMRef; use crate::tx_mock::{BlockchainUpdate, TxCache, TxInput, TxResult}; use super::super::builtin_func_trait::BuiltinFunction; diff --git a/vm/src/tx_execution/builtin_function_mocks/general/upgrade_contract.rs b/vm/src/tx_execution/builtin_function_mocks/general/upgrade_contract.rs index 7de2032273..18ed1783ec 100644 --- a/vm/src/tx_execution/builtin_function_mocks/general/upgrade_contract.rs +++ b/vm/src/tx_execution/builtin_function_mocks/general/upgrade_contract.rs @@ -1,8 +1,6 @@ -use crate::tx_execution::{ - builtin_function_names::UPGRADE_CONTRACT_FUNC_NAME, create_transfer_value_log, BlockchainVMRef, -}; - use crate::{ + chain_core::builtin_func_names::UPGRADE_CONTRACT_FUNC_NAME, + tx_execution::{create_transfer_value_log, BlockchainVMRef}, tx_mock::{BlockchainUpdate, CallType, TxCache, TxFunctionName, TxInput, TxResult}, types::VMCodeMetadata, }; diff --git a/vm/src/tx_execution/builtin_function_mocks/transfer/esdt_multi_transfer_mock.rs b/vm/src/tx_execution/builtin_function_mocks/transfer/esdt_multi_transfer_mock.rs index 183819f372..0235d68f9e 100644 --- a/vm/src/tx_execution/builtin_function_mocks/transfer/esdt_multi_transfer_mock.rs +++ b/vm/src/tx_execution/builtin_function_mocks/transfer/esdt_multi_transfer_mock.rs @@ -1,5 +1,6 @@ use crate::{ - tx_execution::{builtin_function_names::ESDT_MULTI_TRANSFER_FUNC_NAME, BlockchainVMRef}, + chain_core::builtin_func_names::ESDT_MULTI_TRANSFER_FUNC_NAME, + tx_execution::BlockchainVMRef, tx_mock::TxLog, types::{top_decode_u64, top_encode_u64}, }; diff --git a/vm/src/tx_execution/builtin_function_mocks/transfer/esdt_nft_transfer_mock.rs b/vm/src/tx_execution/builtin_function_mocks/transfer/esdt_nft_transfer_mock.rs index 24d5925662..39bbe7f1cb 100644 --- a/vm/src/tx_execution/builtin_function_mocks/transfer/esdt_nft_transfer_mock.rs +++ b/vm/src/tx_execution/builtin_function_mocks/transfer/esdt_nft_transfer_mock.rs @@ -1,8 +1,6 @@ use crate::{ - tx_execution::{ - builtin_function_names::ESDT_NFT_TRANSFER_FUNC_NAME, BlockchainVMRef, - BuiltinFunctionEsdtTransferInfo, - }, + chain_core::builtin_func_names::ESDT_NFT_TRANSFER_FUNC_NAME, + tx_execution::{BlockchainVMRef, BuiltinFunctionEsdtTransferInfo}, tx_mock::{BlockchainUpdate, TxCache, TxInput, TxLog, TxResult}, types::VMAddress, }; diff --git a/vm/src/tx_execution/builtin_function_mocks/transfer/esdt_transfer_mock.rs b/vm/src/tx_execution/builtin_function_mocks/transfer/esdt_transfer_mock.rs index 8f5a912a2a..4d8bd08b2e 100644 --- a/vm/src/tx_execution/builtin_function_mocks/transfer/esdt_transfer_mock.rs +++ b/vm/src/tx_execution/builtin_function_mocks/transfer/esdt_transfer_mock.rs @@ -1,8 +1,6 @@ use crate::{ - tx_execution::{ - builtin_function_names::ESDT_TRANSFER_FUNC_NAME, BlockchainVMRef, - BuiltinFunctionEsdtTransferInfo, - }, + chain_core::builtin_func_names::ESDT_TRANSFER_FUNC_NAME, + tx_execution::{BlockchainVMRef, BuiltinFunctionEsdtTransferInfo}, tx_mock::{BlockchainUpdate, TxCache, TxInput, TxLog, TxResult}, }; diff --git a/vm/src/tx_execution/builtin_function_mocks/vm_builtin_function_names.rs b/vm/src/tx_execution/builtin_function_mocks/vm_builtin_function_names.rs deleted file mode 100644 index 108ed29016..0000000000 --- a/vm/src/tx_execution/builtin_function_mocks/vm_builtin_function_names.rs +++ /dev/null @@ -1,16 +0,0 @@ -pub const ESDT_LOCAL_MINT_FUNC_NAME: &str = "ESDTLocalMint"; -pub const ESDT_LOCAL_BURN_FUNC_NAME: &str = "ESDTLocalBurn"; -pub const ESDT_MULTI_TRANSFER_FUNC_NAME: &str = "MultiESDTNFTTransfer"; -pub const ESDT_NFT_TRANSFER_FUNC_NAME: &str = "ESDTNFTTransfer"; -pub const ESDT_NFT_CREATE_FUNC_NAME: &str = "ESDTNFTCreate"; -pub const ESDT_NFT_ADD_QUANTITY_FUNC_NAME: &str = "ESDTNFTAddQuantity"; -pub const ESDT_NFT_ADD_URI_FUNC_NAME: &str = "ESDTNFTAddURI"; -pub const ESDT_NFT_UPDATE_ATTRIBUTES_FUNC_NAME: &str = "ESDTNFTUpdateAttributes"; -pub const ESDT_NFT_BURN_FUNC_NAME: &str = "ESDTNFTBurn"; -pub const ESDT_TRANSFER_FUNC_NAME: &str = "ESDTTransfer"; -pub const CHANGE_OWNER_BUILTIN_FUNC_NAME: &str = "ChangeOwnerAddress"; -pub const CLAIM_DEVELOPER_REWARDS_FUNC_NAME: &str = "ClaimDeveloperRewards"; -pub const SET_USERNAME_FUNC_NAME: &str = "SetUserName"; -pub const MIGRATE_USERNAME_FUNC_NAME: &str = "migrateUserName"; -pub const DELETE_USERNAME_FUNC_NAME: &str = "DeleteUserName"; -pub const UPGRADE_CONTRACT_FUNC_NAME: &str = "upgradeContract"; diff --git a/vm/src/types.rs b/vm/src/types.rs index d1ada0c0f6..9ab80284a5 100644 --- a/vm/src/types.rs +++ b/vm/src/types.rs @@ -1,20 +1,14 @@ -mod vm_address; -mod vm_code_metadata; -mod vm_esdt_local_role; -mod vm_esdt_local_role_flags; -mod vm_h256; -mod vm_token_type; +pub use crate::chain_core::types::Address as VMAddress; +pub use crate::chain_core::types::CodeMetadata as VMCodeMetadata; +pub use crate::chain_core::types::EsdtLocalRole; +pub use crate::chain_core::types::EsdtLocalRoleFlags; +pub use crate::chain_core::types::TokenType as VMTokenType; +pub use crate::chain_core::types::H256; + +pub type RawHandle = i32; use num_bigint::BigUint; use num_traits::Zero; -pub use vm_address::VMAddress; -pub use vm_code_metadata::VMCodeMetadata; -pub use vm_esdt_local_role::EsdtLocalRole; -pub use vm_esdt_local_role_flags::EsdtLocalRoleFlags; -pub use vm_h256::H256; -pub use vm_token_type::VMTokenType; - -pub type RawHandle = i32; pub(crate) fn top_encode_u64(value: u64) -> Vec { top_encode_big_uint(&BigUint::from(value)) diff --git a/vm/src/types/vm_address.rs b/vm/src/types/vm_address.rs deleted file mode 100644 index 75786787cc..0000000000 --- a/vm/src/types/vm_address.rs +++ /dev/null @@ -1,153 +0,0 @@ -use super::H256; - -use core::fmt::Debug; - -const SC_ADDRESS_NUM_LEADING_ZEROS: u8 = 8; - -pub const NUM_INT_CHARACTERS_FOR_ADDRESS: usize = 10; -pub const VM_TYPE_LEN: usize = 2; -pub const DEFAULT_VM_TYPE: &[u8] = &[5, 0]; - -/// Address type being used in the VM only. -/// -/// Its implementation is similar to that of the heap Address in the framework, -/// but we have a separate implementation for the VM, because it is a separate component. -#[derive(Hash, PartialEq, Eq, Clone, Debug)] -pub struct VMAddress(H256); - -impl VMAddress { - pub const fn new(bytes: [u8; 32]) -> Self { - VMAddress(H256::new(bytes)) - } - - pub fn generate_mock_address(creator_address: &[u8], creator_nonce: u64) -> Self { - let mut result = [0x00; 32]; - - result[10] = 0x11; - result[11] = 0x11; - result[12] = 0x11; - result[13] = 0x11; - - result[14..29].copy_from_slice(&creator_address[..15]); - result[29] = creator_nonce as u8; - result[30..].copy_from_slice(&creator_address[30..]); - - let start_index = NUM_INT_CHARACTERS_FOR_ADDRESS - VM_TYPE_LEN; - result[start_index..(start_index + DEFAULT_VM_TYPE.len())].copy_from_slice(DEFAULT_VM_TYPE); - - VMAddress::from(result) - } -} - -impl From for VMAddress { - fn from(hash: H256) -> Self { - VMAddress(hash) - } -} - -impl From for H256 { - fn from(address: VMAddress) -> Self { - address.0 - } -} - -impl<'a> From<&'a VMAddress> for &'a H256 { - fn from(address: &'a VMAddress) -> Self { - &address.0 - } -} - -impl From<[u8; 32]> for VMAddress { - fn from(arr: [u8; 32]) -> Self { - VMAddress(H256::from(arr)) - } -} - -impl From<&[u8; 32]> for VMAddress { - fn from(bytes: &[u8; 32]) -> Self { - VMAddress(H256::from(bytes)) - } -} - -impl From<&mut [u8; 32]> for VMAddress { - fn from(bytes: &mut [u8; 32]) -> Self { - VMAddress(H256::from(bytes)) - } -} - -impl From> for VMAddress { - fn from(bytes: Box<[u8; 32]>) -> Self { - VMAddress(H256::from(bytes)) - } -} - -impl VMAddress { - pub fn from_slice(slice: &[u8]) -> Self { - VMAddress(H256::from_slice(slice)) - } -} - -impl From for [u8; 32] { - fn from(addr: VMAddress) -> Self { - addr.0.into() - } -} - -impl AsRef<[u8]> for VMAddress { - fn as_ref(&self) -> &[u8] { - self.0.as_ref() - } -} - -impl AsMut<[u8]> for VMAddress { - fn as_mut(&mut self) -> &mut [u8] { - self.0.as_mut() - } -} - -impl VMAddress { - /// Returns a new address of 32 zeros. - /// Allocates directly in heap. - /// Minimal resulting wasm code (14 bytes if not inlined). - pub fn zero() -> Self { - VMAddress(H256::zero()) - } - - /// Extracts a byte slice containing the entire fixed hash. - pub fn as_bytes(&self) -> &[u8] { - self.0.as_bytes() - } - - pub fn as_array(&self) -> &[u8; 32] { - self.0.as_array() - } - - pub fn to_vec(&self) -> Vec { - self.0.to_vec() - } - - pub fn is_smart_contract_address(&self) -> bool { - self.as_bytes() - .iter() - .take(SC_ADDRESS_NUM_LEADING_ZEROS.into()) - .all(|item| item == &0u8) - } -} - -#[cfg(test)] -mod tests { - use crate::{display_util::address_hex, types::VMAddress}; - - #[test] - fn generate_mock_address_test() { - let creator_address = VMAddress::new([ - 111, 119, 110, 101, 114, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, - ]); - let mock_address = VMAddress::generate_mock_address(&creator_address.to_vec(), 1u64); - assert_eq!( - address_hex(&mock_address), - "0x00000000000000000500111111116f776e65725f5f5f5f5f5f5f5f5f5f015f5f" - ); - } -} diff --git a/vm/src/types/vm_code_metadata.rs b/vm/src/types/vm_code_metadata.rs deleted file mode 100644 index 5073d9ffe1..0000000000 --- a/vm/src/types/vm_code_metadata.rs +++ /dev/null @@ -1,130 +0,0 @@ -#![allow(clippy::bad_bit_mask)] - -use bitflags::bitflags; - -bitflags! { - #[derive(Default, PartialEq, Debug, Clone, Copy)] - pub struct VMCodeMetadata: u16 { - const DEFAULT = 0; - const UPGRADEABLE = 0b0000_0001_0000_0000; // LSB of first byte - const READABLE = 0b0000_0100_0000_0000; // 3rd LSB of first byte - const PAYABLE = 0b0000_0000_0000_0010; // 2nd LSB of second byte - const PAYABLE_BY_SC = 0b0000_0000_0000_0100; // 3rd LSB of second byte - } -} - -impl VMCodeMetadata { - pub fn is_upgradeable(&self) -> bool { - *self & VMCodeMetadata::UPGRADEABLE != VMCodeMetadata::DEFAULT - } - - pub fn is_payable(&self) -> bool { - *self & VMCodeMetadata::PAYABLE != VMCodeMetadata::DEFAULT - } - - pub fn is_payable_by_sc(&self) -> bool { - *self & VMCodeMetadata::PAYABLE_BY_SC != VMCodeMetadata::DEFAULT - } - - pub fn is_readable(&self) -> bool { - *self & VMCodeMetadata::READABLE != VMCodeMetadata::DEFAULT - } - - pub fn to_byte_array(&self) -> [u8; 2] { - self.bits().to_be_bytes() - } - - pub fn to_vec(&self) -> Vec { - self.to_byte_array().to_vec() - } -} - -impl From<[u8; 2]> for VMCodeMetadata { - fn from(arr: [u8; 2]) -> Self { - VMCodeMetadata::from(u16::from_be_bytes(arr)) - } -} - -impl From<&[u8]> for VMCodeMetadata { - fn from(slice: &[u8]) -> Self { - let arr: [u8; 2] = slice.try_into().unwrap_or_default(); - VMCodeMetadata::from(arr) - } -} - -impl From<&Vec> for VMCodeMetadata { - fn from(v: &Vec) -> Self { - VMCodeMetadata::from(v.as_slice()) - } -} - -impl From for VMCodeMetadata { - #[inline] - fn from(value: u16) -> Self { - VMCodeMetadata::from_bits_truncate(value) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_default() { - assert!(!VMCodeMetadata::DEFAULT.is_upgradeable()); - assert!(!VMCodeMetadata::DEFAULT.is_payable()); - assert!(!VMCodeMetadata::DEFAULT.is_readable()); - } - - #[test] - fn test_all() { - let all = VMCodeMetadata::UPGRADEABLE - | VMCodeMetadata::PAYABLE - | VMCodeMetadata::PAYABLE_BY_SC - | VMCodeMetadata::READABLE; - assert!(all.is_upgradeable()); - assert!(all.is_payable()); - assert!(all.is_payable_by_sc()); - assert!(all.is_readable()); - - assert_eq!(all.bits(), 0x0506); - - assert_eq!(VMCodeMetadata::from_bits_truncate(0xffff), all); - } - - #[test] - fn test_each() { - assert!(VMCodeMetadata::UPGRADEABLE.is_upgradeable()); - assert!(!VMCodeMetadata::PAYABLE.is_upgradeable()); - assert!(!VMCodeMetadata::PAYABLE_BY_SC.is_upgradeable()); - assert!(!VMCodeMetadata::READABLE.is_upgradeable()); - - assert!(!VMCodeMetadata::UPGRADEABLE.is_payable()); - assert!(VMCodeMetadata::PAYABLE.is_payable()); - assert!(!VMCodeMetadata::PAYABLE_BY_SC.is_payable()); - assert!(!VMCodeMetadata::READABLE.is_payable()); - - assert!(!VMCodeMetadata::UPGRADEABLE.is_payable_by_sc()); - assert!(!VMCodeMetadata::PAYABLE.is_payable_by_sc()); - assert!(VMCodeMetadata::PAYABLE_BY_SC.is_payable_by_sc()); - assert!(!VMCodeMetadata::READABLE.is_payable_by_sc()); - - assert!(!VMCodeMetadata::UPGRADEABLE.is_readable()); - assert!(!VMCodeMetadata::PAYABLE.is_readable()); - assert!(!VMCodeMetadata::PAYABLE_BY_SC.is_readable()); - assert!(VMCodeMetadata::READABLE.is_readable()); - } - - /// Translated from vm-wasm. - #[test] - fn test_from_array() { - assert!(VMCodeMetadata::from([1, 0]).is_upgradeable()); - assert!(!VMCodeMetadata::from([1, 0]).is_readable()); - assert!(VMCodeMetadata::from([0, 2]).is_payable()); - assert!(VMCodeMetadata::from([4, 0]).is_readable()); - assert!(!VMCodeMetadata::from([4, 0]).is_upgradeable()); - assert!(!VMCodeMetadata::from([0, 0]).is_upgradeable()); - assert!(!VMCodeMetadata::from([0, 0]).is_payable()); - assert!(!VMCodeMetadata::from([0, 0]).is_readable()); - } -} diff --git a/vm/src/types/vm_esdt_local_role_flags.rs b/vm/src/types/vm_esdt_local_role_flags.rs deleted file mode 100644 index 2b47879ec8..0000000000 --- a/vm/src/types/vm_esdt_local_role_flags.rs +++ /dev/null @@ -1,73 +0,0 @@ -#![allow(clippy::bad_bit_mask)] - -use super::EsdtLocalRole; -use bitflags::bitflags; - -bitflags! { - /// The VM implementation for EsdtLocalRoleFlags, used internally in builtin functions. - /// - /// There is another near-identical implementation in the framework, used for communicating with the VM. - /// - /// It might be a good idea to move it to some "common ground" crate, between the framework and the VM. - #[derive(PartialEq, Clone, Copy)] - pub struct EsdtLocalRoleFlags: u64 { - const NONE = 0b00000000; - const MINT = 0b00000001; - const BURN = 0b00000010; - const NFT_CREATE = 0b00000100; - const NFT_ADD_QUANTITY = 0b00001000; - const NFT_BURN = 0b00010000; - const NFT_ADD_URI = 0b00100000; - const NFT_UPDATE_ATTRIBUTES = 0b01000000; - const TRANSFER = 0b10000000; - } -} - -impl EsdtLocalRoleFlags { - pub fn has_role(&self, role: &EsdtLocalRole) -> bool { - *self & role.to_flag() != EsdtLocalRoleFlags::NONE - } - - pub fn iter_roles(&self) -> impl Iterator { - EsdtLocalRole::iter_all().filter(move |role| self.has_role(role)) - } -} - -#[cfg(test)] -pub mod tests { - use super::*; - use alloc::vec::Vec; - - #[test] - fn test_flags_has_role() { - let flags = EsdtLocalRoleFlags::MINT; - assert!(flags.has_role(&EsdtLocalRole::Mint)); - let flags = EsdtLocalRoleFlags::MINT | EsdtLocalRoleFlags::BURN; - assert!(flags.has_role(&EsdtLocalRole::Mint)); - let flags = EsdtLocalRoleFlags::NONE; - assert!(!flags.has_role(&EsdtLocalRole::Mint)); - let flags = EsdtLocalRoleFlags::BURN; - assert!(!flags.has_role(&EsdtLocalRole::Mint)); - } - - #[test] - fn test_flags_iter_role() { - let flags = EsdtLocalRoleFlags::MINT; - assert_eq!( - flags.iter_roles().collect::>(), - alloc::vec![&EsdtLocalRole::Mint], - ); - - let flags = EsdtLocalRoleFlags::MINT | EsdtLocalRoleFlags::BURN; - assert_eq!( - flags.iter_roles().collect::>(), - alloc::vec![&EsdtLocalRole::Mint, &EsdtLocalRole::Burn], - ); - - let flags = EsdtLocalRoleFlags::NONE; - assert_eq!( - flags.iter_roles().collect::>(), - Vec::<&EsdtLocalRole>::new(), - ); - } -} diff --git a/vm/src/types/vm_h256.rs b/vm/src/types/vm_h256.rs deleted file mode 100644 index 58e8dd7eda..0000000000 --- a/vm/src/types/vm_h256.rs +++ /dev/null @@ -1,108 +0,0 @@ -use core::fmt::Debug; - -// const ERR_BAD_H256_LENGTH: &str = "bad H256 length"; -const ZERO_32: &[u8] = &[0u8; 32]; - -/// Type that holds 32 bytes of data. -/// Data is kept on the heap to keep wasm size low and avoid copies. -#[derive(Hash, PartialEq, Eq, Clone, Debug)] -pub struct H256([u8; 32]); - -impl H256 { - pub const fn new(bytes: [u8; 32]) -> Self { - H256(bytes) - } -} - -impl From<[u8; 32]> for H256 { - /// Constructs a hash type from the given bytes array of fixed length. - /// - /// # Note - /// - /// The given bytes are interpreted in big endian order. - fn from(arr: [u8; 32]) -> Self { - H256(arr) - } -} - -impl<'a> From<&'a [u8; 32]> for H256 { - /// Constructs a hash type from the given reference - /// to the bytes array of fixed length. - /// - /// # Note - /// - /// The given bytes are interpreted in big endian order. - fn from(bytes: &'a [u8; 32]) -> Self { - H256(*bytes) - } -} - -impl<'a> From<&'a mut [u8; 32]> for H256 { - /// Constructs a hash type from the given reference - /// to the mutable bytes array of fixed length. - /// - /// # Note - /// - /// The given bytes are interpreted in big endian order. - fn from(bytes: &'a mut [u8; 32]) -> Self { - H256(*bytes) - } -} - -impl From> for H256 { - fn from(bytes: Box<[u8; 32]>) -> Self { - H256(*bytes) - } -} - -impl H256 { - pub fn from_slice(slice: &[u8]) -> Self { - let mut arr = [0u8; 32]; - let len = core::cmp::min(slice.len(), 32); - arr[..len].copy_from_slice(&slice[..len]); - H256(arr) - } -} - -impl From for [u8; 32] { - fn from(s: H256) -> Self { - s.0 - } -} - -impl AsRef<[u8]> for H256 { - fn as_ref(&self) -> &[u8] { - self.as_bytes() - } -} - -impl AsMut<[u8]> for H256 { - fn as_mut(&mut self) -> &mut [u8] { - self.0.as_mut() - } -} - -impl H256 { - /// Returns a new zero-initialized fixed hash. - pub fn zero() -> Self { - H256([0u8; 32]) - } - - /// Extracts a byte slice containing the entire fixed hash. - pub fn as_bytes(&self) -> &[u8] { - self.0.as_ref() - } - - pub fn as_array(&self) -> &[u8; 32] { - &self.0 - } - - pub fn to_vec(&self) -> Vec { - self.0[..].to_vec() - } - - /// True if all 32 bytes of the hash are zero. - pub fn is_zero(&self) -> bool { - self.as_bytes() == ZERO_32 - } -} diff --git a/vm/src/vm_hooks/vh_handler/vh_blockchain.rs b/vm/src/vm_hooks/vh_handler/vh_blockchain.rs index 43940d4a57..5dcd5e7c0d 100644 --- a/vm/src/vm_hooks/vh_handler/vh_blockchain.rs +++ b/vm/src/vm_hooks/vh_handler/vh_blockchain.rs @@ -1,5 +1,5 @@ use crate::{ - tx_execution::vm_builtin_function_names::*, + chain_core::builtin_func_names::*, types::{EsdtLocalRole, EsdtLocalRoleFlags, RawHandle, VMAddress}, vm_hooks::VMHooksHandlerSource, world_mock::{EsdtData, EsdtInstance}, diff --git a/vm/src/vm_hooks/vh_handler/vh_send.rs b/vm/src/vm_hooks/vh_handler/vh_send.rs index 4d0584586b..67d590f772 100644 --- a/vm/src/vm_hooks/vh_handler/vh_send.rs +++ b/vm/src/vm_hooks/vh_handler/vh_send.rs @@ -1,5 +1,5 @@ use crate::{ - tx_execution::builtin_function_names::{ + chain_core::builtin_func_names::{ ESDT_MULTI_TRANSFER_FUNC_NAME, ESDT_NFT_TRANSFER_FUNC_NAME, ESDT_TRANSFER_FUNC_NAME, UPGRADE_CONTRACT_FUNC_NAME, },