From 921e35612538b873055d1136ff2bde822f9b4173 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Papierski?= Date: Fri, 12 Jul 2024 18:31:03 +0200 Subject: [PATCH] Split multiple crates --- Cargo.lock | 281 +++++------- Cargo.toml | 9 +- .../wasm-common}/Cargo.toml | 4 +- .../wasm-common}/src/flags.rs | 0 .../wasm-common}/src/keyspace.rs | 0 .../wasm-common}/src/leb128.rs | 0 executor/wasm-common/src/lib.rs | 6 + .../wasm-common}/src/manifest.rs | 0 .../wasm-common}/src/selector.rs | 0 executor/wasm-host/Cargo.toml | 17 + .../host => executor/wasm-host/src}/abi.rs | 0 executor/wasm-host/src/context.rs | 29 ++ {vm => executor/wasm-host}/src/host.rs | 227 ++++------ executor/wasm-host/src/lib.rs | 5 + executor/wasm-host/src/system.rs | 405 ++++++++++++++++++ executor/wasm-interface/Cargo.toml | 13 + .../wasm-interface}/src/executor.rs | 211 ++------- {vm => executor/wasm-interface}/src/lib.rs | 193 +++++---- executor/wasm/Cargo.toml | 24 ++ {vm => executor/wasm}/src/chain_utils.rs | 17 +- executor/wasm/src/install.rs | 167 ++++++++ .../v2.rs => executor/wasm/src/lib.rs | 146 ++++--- .../runtime.rs => executor/wasm/src/system.rs | 29 +- {vm => executor/wasm}/tests/integration.rs | 44 +- executor/wasm/vm2-cep18-caller.wasm | 1 + executor/wasm/vm2-harness.wasm | 1 + executor/wasm/vm2_cep18.wasm | 1 + executor/wasm/vm2_flipper.wasm | 1 + executor/wasm/vm2_trait.wasm | 1 + executor/wasm/vm2_upgradable.wasm | 1 + executor/wasm/vm2_upgradable_v2.wasm | 1 + executor/wasmer-backend/Cargo.toml | 15 + executor/wasmer-backend/src/imports.rs | 82 ++++ .../wasmer-backend/src/lib.rs | 251 ++++------- .../src}/metering_middleware.rs | 0 node/Cargo.toml | 4 +- node/src/components/contract_runtime.rs | 2 +- .../components/contract_runtime/operations.rs | 16 +- node/src/components/contract_runtime/utils.rs | 2 +- .../contracts/vm2/vm2-cep18-caller/Cargo.toml | 1 - .../contracts/vm2/vm2-cep18/Cargo.toml | 1 - .../contracts/vm2/vm2-cep78/Cargo.toml | 1 - .../contracts/vm2/vm2-harness/Cargo.toml | 2 +- .../vm2/vm2-test-contract/Cargo.toml | 2 +- smart_contracts/macros/Cargo.toml | 3 +- smart_contracts/macros/src/lib.rs | 18 +- smart_contracts/sdk-codegen/Cargo.toml | 1 - smart_contracts/sdk-codegen/src/lib.rs | 2 +- .../sdk-sys/src/for_each_host_function.rs | 19 - smart_contracts/sdk/Cargo.toml | 2 +- smart_contracts/sdk/src/collections/map.rs | 2 +- smart_contracts/sdk/src/collections/set.rs | 2 +- smart_contracts/sdk/src/collections/vector.rs | 2 +- smart_contracts/sdk/src/host.rs | 33 +- smart_contracts/sdk/src/host/native.rs | 2 +- smart_contracts/sdk/src/lib.rs | 15 +- smart_contracts/sdk/src/schema.rs | 2 +- storage/src/global_state.rs | 10 + vm-common/src/lib.rs | 5 - vm/Cargo.toml | 45 -- vm/benches/vm_call.rs | 87 ---- vm/src/chain.rs | 3 - vm/src/host/utils.rs | 1 - vm/src/storage.rs | 53 --- vm/src/wasm_backend.rs | 120 ------ vm/vm2-cep18-caller.wasm | 1 - vm/vm2-harness.wasm | 1 - vm/vm2_cep18.wasm | 1 - vm/vm2_flipper.wasm | 1 - vm/vm2_trait.wasm | 1 - vm/vm2_upgradable.wasm | 1 - vm/vm2_upgradable_v2.wasm | 1 - 72 files changed, 1371 insertions(+), 1276 deletions(-) rename {vm-common => executor/wasm-common}/Cargo.toml (81%) rename {vm-common => executor/wasm-common}/src/flags.rs (100%) rename {vm-common => executor/wasm-common}/src/keyspace.rs (100%) rename {vm-common => executor/wasm-common}/src/leb128.rs (100%) create mode 100644 executor/wasm-common/src/lib.rs rename {vm-common => executor/wasm-common}/src/manifest.rs (100%) rename {vm-common => executor/wasm-common}/src/selector.rs (100%) create mode 100644 executor/wasm-host/Cargo.toml rename {vm/src/host => executor/wasm-host/src}/abi.rs (100%) create mode 100644 executor/wasm-host/src/context.rs rename {vm => executor/wasm-host}/src/host.rs (88%) create mode 100644 executor/wasm-host/src/lib.rs create mode 100644 executor/wasm-host/src/system.rs create mode 100644 executor/wasm-interface/Cargo.toml rename {vm => executor/wasm-interface}/src/executor.rs (55%) rename {vm => executor/wasm-interface}/src/lib.rs (62%) create mode 100644 executor/wasm/Cargo.toml rename {vm => executor/wasm}/src/chain_utils.rs (82%) create mode 100644 executor/wasm/src/install.rs rename vm/src/executor/v2.rs => executor/wasm/src/lib.rs (87%) rename vm/src/storage/runtime.rs => executor/wasm/src/system.rs (94%) rename {vm => executor/wasm}/tests/integration.rs (92%) create mode 120000 executor/wasm/vm2-cep18-caller.wasm create mode 120000 executor/wasm/vm2-harness.wasm create mode 120000 executor/wasm/vm2_cep18.wasm create mode 120000 executor/wasm/vm2_flipper.wasm create mode 120000 executor/wasm/vm2_trait.wasm create mode 120000 executor/wasm/vm2_upgradable.wasm create mode 120000 executor/wasm/vm2_upgradable_v2.wasm create mode 100644 executor/wasmer-backend/Cargo.toml create mode 100644 executor/wasmer-backend/src/imports.rs rename vm/src/wasm_backend/wasmer.rs => executor/wasmer-backend/src/lib.rs (76%) rename {vm/src/wasm_backend/wasmer => executor/wasmer-backend/src}/metering_middleware.rs (100%) delete mode 100644 vm-common/src/lib.rs delete mode 100644 vm/Cargo.toml delete mode 100644 vm/benches/vm_call.rs delete mode 100644 vm/src/chain.rs delete mode 100644 vm/src/host/utils.rs delete mode 100644 vm/src/storage.rs delete mode 100644 vm/src/wasm_backend.rs delete mode 120000 vm/vm2-cep18-caller.wasm delete mode 120000 vm/vm2-harness.wasm delete mode 120000 vm/vm2_cep18.wasm delete mode 120000 vm/vm2_flipper.wasm delete mode 120000 vm/vm2_trait.wasm delete mode 120000 vm/vm2_upgradable.wasm delete mode 120000 vm/vm2_upgradable_v2.wasm diff --git a/Cargo.lock b/Cargo.lock index 5de2493061..9df3bf4900 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -104,12 +104,6 @@ dependencies = [ "alloc-no-stdlib", ] -[[package]] -name = "anes" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" - [[package]] name = "ansi_term" version = "0.12.1" @@ -436,9 +430,9 @@ dependencies = [ [[package]] name = "borsh" -version = "1.3.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d4d6dafc1a3bb54687538972158f07b2c948bc57d5890df22c0739098b3028" +checksum = "a6362ed55def622cddc70a4746a68554d7b687713770de539e59a739b249f8ed" dependencies = [ "borsh-derive", "cfg_aliases", @@ -446,9 +440,9 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.3.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4918709cc4dd777ad2b6303ed03cb37f3ca0ccede8c1b0d28ac6db8f4710e0" +checksum = "c3ef8005764f53cd4dca619f5bf64cafd4664dada50ece25e4d81de54c80cc0b" dependencies = [ "once_cell", "proc-macro-crate", @@ -543,9 +537,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.4.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" dependencies = [ "serde", ] @@ -678,7 +672,7 @@ dependencies = [ "casper-types", "casper-wasm", "clap 2.34.0", - "criterion 0.3.6", + "criterion", "dictionary", "dictionary-call", "fs_extra", @@ -713,7 +707,7 @@ dependencies = [ "casper-wasm", "casper-wasm-utils", "casper-wasmi", - "criterion 0.3.6", + "criterion", "datasize", "either", "hex-buffer-serde 0.2.2", @@ -744,11 +738,92 @@ dependencies = [ "walrus", ] +[[package]] +name = "casper-executor-wasm" +version = "0.1.0" +dependencies = [ + "blake2 0.10.6", + "borsh", + "bytes", + "casper-executor-wasm-common", + "casper-executor-wasm-host", + "casper-executor-wasm-interface", + "casper-executor-wasmer-backend", + "casper-storage", + "casper-types", + "digest 0.10.7", + "either", + "once_cell", + "parking_lot 0.12.3", + "tempfile", + "thiserror", + "tracing", +] + +[[package]] +name = "casper-executor-wasm-common" +version = "0.1.0" +dependencies = [ + "bitflags 2.4.1", + "borsh", + "casper-sdk-sys", + "hex", + "num-derive 0.4.2", + "num-traits", + "serde", +] + +[[package]] +name = "casper-executor-wasm-host" +version = "0.1.0" +dependencies = [ + "bytes", + "casper-executor-wasm-common", + "casper-executor-wasm-interface", + "casper-storage", + "casper-types", + "num-derive 0.4.2", + "num-traits", + "parking_lot 0.12.3", + "safe-transmute", + "thiserror", + "tracing", +] + +[[package]] +name = "casper-executor-wasm-interface" +version = "0.1.0" +dependencies = [ + "borsh", + "bytes", + "casper-executor-wasm-common", + "casper-storage", + "casper-types", + "parking_lot 0.12.3", + "thiserror", +] + +[[package]] +name = "casper-executor-wasmer-backend" +version = "0.1.0" +dependencies = [ + "bytes", + "casper-executor-wasm-host", + "casper-executor-wasm-interface", + "casper-sdk-sys", + "casper-storage", + "wasmer", + "wasmer-compiler-singlepass", + "wasmer-middlewares", + "wasmer-types", +] + [[package]] name = "casper-macros" version = "0.1.0" dependencies = [ "blake2-rfc", + "casper-sdk", "casper-sdk-sys", "darling 0.20.9", "paste", @@ -756,7 +831,6 @@ dependencies = [ "quote 1.0.35", "static_assertions", "syn 2.0.52", - "vm-common", ] [[package]] @@ -776,9 +850,10 @@ dependencies = [ "bytes", "casper-binary-port", "casper-execution-engine", + "casper-executor-wasm", + "casper-executor-wasm-interface", "casper-storage", "casper-types", - "casper-vm", "datasize", "derive_more", "either", @@ -862,6 +937,7 @@ dependencies = [ "bitflags 2.4.1", "borsh", "bytes", + "casper-executor-wasm-common", "casper-sdk-sys", "cfg-if 1.0.0", "clap 4.4.11", @@ -873,7 +949,6 @@ dependencies = [ "serde", "serde_json", "thiserror", - "vm-common", ] [[package]] @@ -889,7 +964,6 @@ dependencies = [ "syn 2.0.52", "tempfile", "trybuild", - "vm-common", ] [[package]] @@ -915,7 +989,7 @@ dependencies = [ "num-rational", "num-traits", "once_cell", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "proptest", "rand", "rand_chacha", @@ -936,7 +1010,7 @@ dependencies = [ "bincode", "bitflags 1.3.2", "blake2 0.9.2", - "criterion 0.3.6", + "criterion", "datasize", "derive_more", "derp", @@ -1001,35 +1075,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "casper-vm" -version = "0.1.0" -dependencies = [ - "blake2 0.10.6", - "borsh", - "borsh-derive", - "bytes", - "casper-storage", - "casper-types", - "criterion 0.5.1", - "digest 0.10.7", - "either", - "num-derive 0.4.2", - "num-traits", - "once_cell", - "parking_lot 0.12.1", - "rand", - "safe-transmute", - "tempfile", - "thiserror", - "tracing", - "vm-common", - "wasmer", - "wasmer-compiler-singlepass", - "wasmer-middlewares", - "wasmer-types", -] - [[package]] name = "casper-wasm" version = "0.46.0" @@ -1109,9 +1154,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cfg_aliases" -version = "0.1.1" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "change_bid_public_key" @@ -1121,33 +1166,6 @@ dependencies = [ "casper-types", ] -[[package]] -name = "ciborium" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" -dependencies = [ - "ciborium-io", - "ciborium-ll", - "serde", -] - -[[package]] -name = "ciborium-io" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" - -[[package]] -name = "ciborium-ll" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" -dependencies = [ - "ciborium-io", - "half 2.4.1", -] - [[package]] name = "clap" version = "2.34.0" @@ -1482,7 +1500,7 @@ dependencies = [ "atty", "cast", "clap 2.34.0", - "criterion-plot 0.4.5", + "criterion-plot", "csv", "itertools 0.10.5", "lazy_static", @@ -1499,32 +1517,6 @@ dependencies = [ "walkdir", ] -[[package]] -name = "criterion" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" -dependencies = [ - "anes", - "cast", - "ciborium", - "clap 4.4.11", - "criterion-plot 0.5.0", - "is-terminal", - "itertools 0.10.5", - "num-traits", - "once_cell", - "oorandom", - "plotters", - "rayon", - "regex", - "serde", - "serde_derive", - "serde_json", - "tinytemplate", - "walkdir", -] - [[package]] name = "criterion-plot" version = "0.4.5" @@ -1535,16 +1527,6 @@ dependencies = [ "itertools 0.10.5", ] -[[package]] -name = "criterion-plot" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" -dependencies = [ - "cast", - "itertools 0.10.5", -] - [[package]] name = "crossbeam" version = "0.7.3" @@ -3213,7 +3195,7 @@ checksum = "385f4ce6ecf3692d313ca3aa9bd3b3d8490de53368d6d94bedff3af8b6d9c58d" dependencies = [ "gix-hash", "hashbrown 0.14.3", - "parking_lot 0.12.1", + "parking_lot 0.12.3", ] [[package]] @@ -3323,7 +3305,7 @@ dependencies = [ "gix-pack", "gix-path", "gix-quote", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "tempfile", "thiserror", ] @@ -3345,7 +3327,7 @@ dependencies = [ "gix-tempfile", "gix-traverse", "memmap2 0.7.1", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "smallvec", "thiserror", ] @@ -3371,7 +3353,7 @@ checksum = "2c22decaf4a063ccae2b2108820c8630c01bd6756656df3fe464b32b8958a5ea" dependencies = [ "gix-command", "gix-config-value", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rustix", "thiserror", ] @@ -3473,7 +3455,7 @@ dependencies = [ "gix-fs 0.4.1", "libc", "once_cell", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "signal-hook", "signal-hook-registry", "tempfile", @@ -3629,16 +3611,6 @@ version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" -[[package]] -name = "half" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" -dependencies = [ - "cfg-if 1.0.0", - "crunchy", -] - [[package]] name = "hashbrown" version = "0.12.3" @@ -4765,9 +4737,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core 0.9.8", @@ -5013,11 +4985,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "2.0.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" dependencies = [ - "toml_edit 0.20.7", + "toml_edit 0.21.0", ] [[package]] @@ -5930,7 +5902,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" dependencies = [ - "half 1.8.2", + "half", "serde", ] @@ -6451,18 +6423,18 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.58" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.58" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2 1.0.78", "quote 1.0.35", @@ -6707,17 +6679,6 @@ dependencies = [ "winnow 0.5.40", ] -[[package]] -name = "toml_edit" -version = "0.20.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" -dependencies = [ - "indexmap 2.2.6", - "toml_datetime", - "winnow 0.5.40", -] - [[package]] name = "toml_edit" version = "0.21.0" @@ -7243,19 +7204,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "vm-common" -version = "0.1.0" -dependencies = [ - "bitflags 2.4.1", - "borsh", - "casper-sdk-sys", - "hex", - "num-derive 0.4.2", - "num-traits", - "serde", -] - [[package]] name = "vm2-cep18" version = "0.1.0" @@ -7264,7 +7212,6 @@ dependencies = [ "casper-sdk", "casper-sdk-codegen", "serde_json", - "vm-common", ] [[package]] @@ -7274,7 +7221,6 @@ dependencies = [ "borsh", "casper-macros", "casper-sdk", - "vm-common", "vm2-cep18", ] @@ -7287,7 +7233,6 @@ dependencies = [ "casper-sdk", "casper-sdk-codegen", "serde_json", - "vm-common", ] [[package]] @@ -7307,7 +7252,6 @@ dependencies = [ "impls", "serde_json", "thiserror", - "vm-common", ] [[package]] @@ -7318,7 +7262,6 @@ dependencies = [ "casper-macros", "casper-sdk", "serde_json", - "vm-common", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 23f1eac72c..440ab3cf82 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,8 +16,6 @@ members = [ "utils/global-state-update-gen", "utils/validation", "binary_port", - "vm", - "vm-common", "smart_contracts/sdk", "smart_contracts/sdk-codegen", "smart_contracts/sdk-sys", @@ -25,6 +23,11 @@ members = [ "cargo-casper", # "utils/highway-rewards-analysis", # "utils/highway-state-grapher", + "executor/wasm-common", + "executor/wasm-interface", + "executor/wasm-host", + "executor/wasmer-backend", + "executor/wasm", ] default-members = [ @@ -38,8 +41,6 @@ default-members = [ "utils/global-state-update-gen", "utils/validation", "binary_port", - "vm", - "vm-common", "smart_contracts/sdk", "smart_contracts/sdk-sys", "smart_contracts/sdk-codegen", diff --git a/vm-common/Cargo.toml b/executor/wasm-common/Cargo.toml similarity index 81% rename from vm-common/Cargo.toml rename to executor/wasm-common/Cargo.toml index f39cfe1709..617df16662 100644 --- a/vm-common/Cargo.toml +++ b/executor/wasm-common/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "vm-common" +name = "casper-executor-wasm-common" version = "0.1.0" edition = "2021" @@ -7,7 +7,7 @@ edition = "2021" [dependencies] bitflags = "2.4.1" -casper-sdk-sys = { path = "../smart_contracts/sdk-sys"} +casper-sdk-sys = { path = "../../smart_contracts/sdk-sys"} borsh = { version = "1.2.0", features = ["derive"] } num-traits = "0.2.19" num-derive = "0.4.2" diff --git a/vm-common/src/flags.rs b/executor/wasm-common/src/flags.rs similarity index 100% rename from vm-common/src/flags.rs rename to executor/wasm-common/src/flags.rs diff --git a/vm-common/src/keyspace.rs b/executor/wasm-common/src/keyspace.rs similarity index 100% rename from vm-common/src/keyspace.rs rename to executor/wasm-common/src/keyspace.rs diff --git a/vm-common/src/leb128.rs b/executor/wasm-common/src/leb128.rs similarity index 100% rename from vm-common/src/leb128.rs rename to executor/wasm-common/src/leb128.rs diff --git a/executor/wasm-common/src/lib.rs b/executor/wasm-common/src/lib.rs new file mode 100644 index 0000000000..8b64414141 --- /dev/null +++ b/executor/wasm-common/src/lib.rs @@ -0,0 +1,6 @@ +//! A crate that shares common types and utilities between the Wasm executor and the Wasm interface. +pub mod flags; +pub mod keyspace; +pub mod leb128; +pub mod manifest; +pub mod selector; diff --git a/vm-common/src/manifest.rs b/executor/wasm-common/src/manifest.rs similarity index 100% rename from vm-common/src/manifest.rs rename to executor/wasm-common/src/manifest.rs diff --git a/vm-common/src/selector.rs b/executor/wasm-common/src/selector.rs similarity index 100% rename from vm-common/src/selector.rs rename to executor/wasm-common/src/selector.rs diff --git a/executor/wasm-host/Cargo.toml b/executor/wasm-host/Cargo.toml new file mode 100644 index 0000000000..6f4a61cd9b --- /dev/null +++ b/executor/wasm-host/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "casper-executor-wasm-host" +version = "0.1.0" +edition = "2021" + +[dependencies] +num-traits = "0.2.18" +num-derive = "0.4.2" +casper-storage = { path = "../../storage" } +casper-types = { path = "../../types" } +safe-transmute = "0.11.2" +tracing = "0.1.40" +casper-executor-wasm-common = { path = "../wasm-common" } +casper-executor-wasm-interface = { path = "../wasm-interface" } +bytes = "1.6.0" +parking_lot = "0.12.3" +thiserror = "1.0.61" diff --git a/vm/src/host/abi.rs b/executor/wasm-host/src/abi.rs similarity index 100% rename from vm/src/host/abi.rs rename to executor/wasm-host/src/abi.rs diff --git a/executor/wasm-host/src/context.rs b/executor/wasm-host/src/context.rs new file mode 100644 index 0000000000..ad388fe94d --- /dev/null +++ b/executor/wasm-host/src/context.rs @@ -0,0 +1,29 @@ +use std::sync::Arc; + +use bytes::Bytes; +use casper_executor_wasm_interface::executor::Executor; +use casper_storage::{global_state::GlobalStateReader, AddressGenerator, TrackingCopy}; +use casper_types::{account::AccountHash, Key, TransactionHash}; +use parking_lot::RwLock; + +/// Container that holds all relevant modules necessary to process an execution request. +pub struct Context { + /// The address of the account that initiated the contract or session code. + pub initiator: AccountHash, + /// The address of the addressable entity that is currently executing the contract or session + /// code. + pub caller: Key, + /// The address of the addressable entity that is being called. + pub callee: Key, + /// The state of the global state at the time of the call based on the currently executing + /// contract or session address. + // pub state_address: Address, + /// The amount of tokens that were send to the contract's purse at the time of the call. + pub value: u128, + pub tracking_copy: TrackingCopy, + pub executor: E, // TODO: This could be part of the caller + pub transaction_hash: TransactionHash, + pub address_generator: Arc>, + pub chain_name: Arc, + pub input: Bytes, +} diff --git a/vm/src/host.rs b/executor/wasm-host/src/host.rs similarity index 88% rename from vm/src/host.rs rename to executor/wasm-host/src/host.rs index 85586817b4..e2b62c6971 100644 --- a/vm/src/host.rs +++ b/executor/wasm-host/src/host.rs @@ -1,44 +1,32 @@ -//! Implementation of all host functions. -pub(crate) mod abi; -pub(crate) mod utils; +use std::{cmp, num::NonZeroU32, sync::Arc}; +use crate::system::{self, MintArgs, MintTransferArgs}; + +use crate::{abi::CreateResult, context::Context}; use bytes::Bytes; -use casper_storage::tracking_copy::{self, TrackingCopyExt}; +use casper_executor_wasm_common::{ + flags::ReturnFlags, + keyspace::{Keyspace, KeyspaceTag}, +}; +use casper_executor_wasm_interface::u32_from_host_result; +use casper_storage::{global_state::GlobalStateReader, tracking_copy::TrackingCopyExt}; use casper_types::{ account::AccountHash, - addressable_entity::{ - self, ActionThresholds, AssociatedKeys, EntryPointV2, MessageTopics, NamedKeyAddr, - }, + addressable_entity::{ActionThresholds, AssociatedKeys, MessageTopics, NamedKeyAddr}, AddressableEntity, ByteCode, ByteCodeAddr, ByteCodeHash, ByteCodeKind, Digest, EntityAddr, - EntityKind, EntryPointAddr, EntryPointValue, Groups, HoldsEpoch, Key, Package, PackageHash, - PackageStatus, ProtocolVersion, StoredValue, TransactionRuntime, URef, U512, + EntityKind, Groups, HashAddr, Key, Package, PackageHash, PackageStatus, ProtocolVersion, + StoredValue, TransactionRuntime, URef, U512, }; use num_derive::FromPrimitive; -use num_traits::{FromPrimitive, ToBytes}; -use safe_transmute::SingleManyGuard; -use std::{cmp, collections::BTreeSet, mem, num::NonZeroU32, sync::Arc}; +use num_traits::FromPrimitive; use tracing::{error, info}; -use vm_common::{ - flags::{EntryPointFlags, ReturnFlags}, - keyspace::{Keyspace, KeyspaceTag}, - selector::Selector, -}; -use wasmer_types::compilation::target; - -use crate::{ - chain_utils, - executor::{ExecuteError, ExecuteRequestBuilder, ExecuteResult, ExecutionKind}, - host::abi::{CreateResult, EntryPoint, Manifest}, - storage::{ - self, - runtime::{self, MintArgs, MintTransferArgs}, - Address, GlobalStateReader, - }, - wasm_backend::{Caller, Context, MeteringPoints, WasmInstance}, - ConfigBuilder, Executor, HostError, HostResult, TrapCode, VMError, VMResult, WasmEngine, + +use casper_executor_wasm_interface::{ + executor::{ExecuteError, ExecuteRequestBuilder, ExecuteResult, ExecutionKind, Executor}, + Caller, HostError, HostResult, MeteringPoints, TrapCode, VMError, VMResult, }; -use self::abi::ReadInfo; +use crate::abi::ReadInfo; #[derive(Debug, Copy, Clone, FromPrimitive, PartialEq)] enum EntityKindTag { @@ -47,8 +35,8 @@ enum EntityKindTag { } /// Write value under a key. -pub(crate) fn casper_write( - mut caller: impl Caller, +pub fn casper_write( + mut caller: impl Caller>, key_space: u64, key_ptr: u32, key_size: u32, @@ -99,8 +87,8 @@ pub(crate) fn casper_write( Ok(0) } -pub(crate) fn casper_print( - caller: impl Caller, +pub fn casper_print( + caller: impl Caller>, message_ptr: u32, message_size: u32, ) -> VMResult<()> { @@ -111,8 +99,8 @@ pub(crate) fn casper_print( } /// Write value under a key. -pub(crate) fn casper_read( - mut caller: impl Caller, +pub fn casper_read( + mut caller: impl Caller>, key_tag: u64, key_ptr: u32, key_size: u32, @@ -231,12 +219,12 @@ fn keyspace_to_global_state_key<'a, S: GlobalStateReader, E: Executor>( } } -pub(crate) fn casper_copy_input( - mut caller: impl Caller, +pub fn casper_copy_input( + mut caller: impl Caller>, cb_alloc: u32, alloc_ctx: u32, ) -> VMResult { - let input = caller.config().input.clone(); + let input = caller.context().input.clone(); let out_ptr: u32 = if cb_alloc != 0 { caller.alloc(cb_alloc, input.len(), alloc_ctx)? @@ -254,8 +242,8 @@ pub(crate) fn casper_copy_input( } /// Returns from the execution of a smart contract with an optional flags. -pub(crate) fn casper_return( - caller: impl Caller, +pub fn casper_return( + caller: impl Caller>, flags: u32, data_ptr: u32, data_len: u32, @@ -272,11 +260,11 @@ pub(crate) fn casper_return( Err(VMError::Return { flags, data }) } -pub(crate) fn casper_create( - mut caller: impl Caller, +pub fn casper_create( + mut caller: impl Caller>, code_ptr: u32, code_len: u32, - value: u128, + value_ptr: u32, entry_point_ptr: u32, entry_point_len: u32, input_ptr: u32, @@ -291,6 +279,12 @@ pub(crate) fn casper_create( - mut caller: impl Caller, +pub fn casper_call( + mut caller: impl Caller>, address_ptr: u32, address_len: u32, - value: u128, + value_ptr: u32, entry_point_ptr: u32, entry_point_len: u32, input_ptr: u32, @@ -562,7 +543,7 @@ pub(crate) fn casper_call // let vm = VM::new(); // vm. let address = caller.memory_read(address_ptr, address_len as _)?; - let address: Address = address.try_into().unwrap(); // TODO: Error handling + let address: HashAddr = address.try_into().unwrap(); // TODO: Error handling let input_data: Bytes = caller.memory_read(input_ptr, input_len as _)?.into(); @@ -577,6 +558,12 @@ pub(crate) fn casper_call } }; + let value: u128 = { + let mut value_bytes = [0u8; 16]; + caller.memory_read_into(value_ptr, &mut value_bytes)?; + u128::from_le_bytes(value_bytes) + }; + let tracking_copy = caller.context().tracking_copy.fork2(); // Take the gas spent so far and use it as a limit for the new VM. @@ -650,8 +637,8 @@ pub(crate) fn casper_call }; let gas_spent = gas_usage - .gas_limit - .checked_sub(gas_usage.remaining_points) + .gas_limit() + .checked_sub(gas_usage.remaining_points()) .expect("remaining points always below or equal to the limit"); match caller.consume_gas(gas_spent) { @@ -664,59 +651,8 @@ pub(crate) fn casper_call Ok(host_result) } -const CASPER_ENV_CALLER: u64 = 0; - -pub(crate) fn casper_env_read( - mut caller: impl Caller, - env_path: u32, - env_path_length: u32, - cb_alloc: u32, - alloc_ctx: u32, -) -> VMResult { - // NOTE: Needs versioning to disallow situtation where a path contains values that may be used - // in the future. - - let size: usize = env_path_length.try_into().unwrap(); - let env_path_bytes = caller.memory_read(env_path, size * 8)?; - - let path = match safe_transmute::transmute_many::(&env_path_bytes) { - Ok(env_path) => env_path, - Err(safe_transmute::Error::Unaligned(unaligned_error)) - if unaligned_error.source.is_empty() => - { - &[] - } - Err(error) => todo!("handle error {:?}", error), - }; - - let data: Option
= if path == &[CASPER_ENV_CALLER] { - // Some(caller.context().caller.to_vec()) - todo!("Not really using this one") - } else { - None - }; - - if let Some(data) = data { - let out_ptr: u32 = if cb_alloc != 0 { - caller.alloc(cb_alloc, data.len(), alloc_ctx)? - } else { - // treats alloc_ctx as data - alloc_ctx - }; - - if out_ptr == 0 { - Ok(out_ptr) - } else { - caller.memory_write(out_ptr, &data)?; - Ok(out_ptr + (data.len() as u32)) - } - } else { - Ok(0) - } -} - -pub(crate) fn casper_env_caller( - caller: impl Caller, +pub fn casper_env_caller( + caller: impl Caller>, dest_ptr: u32, dest_len: u32, entity_kind_ptr: u32, @@ -741,8 +677,8 @@ pub(crate) fn casper_env_caller( } } -pub(crate) fn casper_env_value( - caller: impl Caller, +pub fn casper_env_value( + caller: impl Caller>, output: u32, ) -> Result<(), VMError> { let result = caller.context().value; @@ -750,8 +686,8 @@ pub(crate) fn casper_env_value( Ok(()) } -pub(crate) fn casper_env_balance( - mut caller: impl Caller, +pub fn casper_env_balance( + mut caller: impl Caller>, entity_kind: u32, entity_addr_ptr: u32, entity_addr_len: u32, @@ -815,26 +751,32 @@ pub(crate) fn casper_env_balance( Ok(1) } -pub(crate) fn casper_transfer( - mut caller: impl Caller, +pub fn casper_transfer( + mut caller: impl Caller>, entity_kind: u32, entity_addr_ptr: u32, entity_addr_len: u32, - amount: u128, -) -> VMResult { + amount_ptr: u32, +) -> VMResult { if entity_addr_len != 32 { // Invalid entity address; failing to proceed with the transfer - return Ok(Err(HostError::NotCallable)); + return Ok(u32_from_host_result(Err(HostError::NotCallable))); } let entity_kind = match EntityKindTag::from_u32(entity_kind) { Some(entity_kind) => entity_kind, None => { // Unknown target entity kind; failing to proceed with the transfer - return Ok(Err(HostError::NotCallable)); // fail + return Ok(u32_from_host_result(Err(HostError::NotCallable))); // fail } }; + let amount: u128 = { + let mut amount_bytes = [0u8; 16]; + caller.memory_read_into(amount_ptr, &mut amount_bytes)?; + u128::from_le_bytes(amount_bytes) + }; + let target_entity_addr = match entity_kind { EntityKindTag::Account => { let entity_addr = caller.memory_read(entity_addr_ptr, entity_addr_len as usize)?; @@ -854,7 +796,7 @@ pub(crate) fn casper_transfer( .expect("should be entity addr") } Ok(Some(other)) => panic!("should be cl value but got {other:?}"), - Ok(None) => return Ok(Err(HostError::NotCallable)), + Ok(None) => return Ok(u32_from_host_result(Err(HostError::NotCallable))), Err(error) => { error!( ?error, @@ -870,7 +812,7 @@ pub(crate) fn casper_transfer( debug_assert_eq!(entity_addr.len(), 32); // SAFETY: entity_addr is 32 bytes long - let entity_addr: Address = entity_addr.try_into().unwrap(); + let entity_addr: HashAddr = entity_addr.try_into().unwrap(); EntityAddr::SmartContract(entity_addr) } }; @@ -884,7 +826,7 @@ pub(crate) fn casper_transfer( addressable_entity_key } Ok(Some(other)) => panic!("should be cl value but got {other:?}"), - Ok(None) => return Ok(Err(HostError::NotCallable)), + Ok(None) => return Ok(u32_from_host_result(Err(HostError::NotCallable))), Err(error) => { error!( ?error, @@ -902,7 +844,6 @@ pub(crate) fn casper_transfer( let callee_entity_addr = callee_addressable_entity_key .into_entity_addr() .expect("should be entity addr"); - // dbg!(&callee_entity_addr); let callee_stored_value = caller .context_mut() @@ -951,12 +892,14 @@ pub(crate) fn casper_transfer( id: None, }; - Ok(runtime::mint_transfer( + let result = system::mint_transfer( &mut caller.context_mut().tracking_copy, transaction_hash, address_generator, args, - )) + ); + + Ok(u32_from_host_result(result)) } EntityKindTag::Contract => { // let callee_purse = callee_stored_value.main_purse(); @@ -1021,8 +964,8 @@ pub(crate) fn casper_transfer( }; let gas_spent = gas_usage - .gas_limit - .checked_sub(gas_usage.remaining_points) + .gas_limit() + .checked_sub(gas_usage.remaining_points()) .expect("remaining points always below or equal to the limit"); match caller.consume_gas(gas_spent) { @@ -1032,7 +975,7 @@ pub(crate) fn casper_transfer( } } - Ok(host_result) + Ok(u32_from_host_result(host_result)) } Err(ExecuteError::WasmPreparation(preparation_error)) => { // This is a bug in the EE, as it should have been caught during the preparation @@ -1044,8 +987,8 @@ pub(crate) fn casper_transfer( } } -pub(crate) fn casper_upgrade( - mut caller: impl Caller, +pub fn casper_upgrade( + mut caller: impl Caller>, code_ptr: u32, code_size: u32, entry_point_ptr: u32, diff --git a/executor/wasm-host/src/lib.rs b/executor/wasm-host/src/lib.rs new file mode 100644 index 0000000000..5cefdf488e --- /dev/null +++ b/executor/wasm-host/src/lib.rs @@ -0,0 +1,5 @@ +//! Implementation of all host functions. +pub(crate) mod abi; +pub mod context; +pub mod host; +pub(crate) mod system; diff --git a/executor/wasm-host/src/system.rs b/executor/wasm-host/src/system.rs new file mode 100644 index 0000000000..350abab222 --- /dev/null +++ b/executor/wasm-host/src/system.rs @@ -0,0 +1,405 @@ +//! System contract dispatch. +//! +//! System contracts are special contracts that are always available to the system. +//! They are used to implement core system functionality, such as minting and transferring tokens. +//! This module provides a way to dispatch calls to system contracts that are implemented under +//! storage crate. +//! +//! The dispatcher provides the necessary information to properly execute system contract's code +//! within the context of the current execution of the new Wasm host logic. +use std::{cell::RefCell, rc::Rc, sync::Arc}; + +use casper_executor_wasm_interface::{HostError, HostResult, TrapCode}; +use casper_storage::{ + global_state::GlobalStateReader, + system::{ + mint::Mint, + runtime_native::{Config, Id, RuntimeNative}, + }, + tracking_copy::{TrackingCopyError, TrackingCopyExt}, + AddressGenerator, TrackingCopy, +}; +use casper_types::{ + account::AccountHash, CLValueError, ContextAccessRights, EntityAddr, Key, Phase, + ProtocolVersion, PublicKey, StoredValue, StoredValueTag, SystemEntityRegistry, TransactionHash, + URef, U512, +}; +use parking_lot::RwLock; +use thiserror::Error; +use tracing::{debug, error}; + +#[derive(Debug, Error)] +enum DispatchError { + #[error("Tracking copy error: {0}")] + Storage(#[from] TrackingCopyError), + #[error("CLValue error: {0}")] + CLValue(CLValueError), + #[error("Registry not found")] + RegistryNotFound, + #[error("Missing addressable entity")] + MissingAddressableEntity, + #[error("Missing system contract: {0}")] + MissingSystemContract(&'static str), + #[error("Error getting named keys")] + GetNamedKeys(TrackingCopyError), + #[error("Invalid key variant")] + InvalidStoredValueVariant { + expected: StoredValueTag, + actual: StoredValue, + }, +} + +fn dispatch_system_contract( + tracking_copy: &mut TrackingCopy, + transaction_hash: TransactionHash, + address_generator: Arc>, + system_contract: &'static str, + func: impl FnOnce(RuntimeNative) -> Ret, +) -> Result { + let system_entity_registry = { + let stored_value = tracking_copy + .read(&Key::SystemEntityRegistry)? + .ok_or(DispatchError::RegistryNotFound)?; + stored_value + .into_cl_value() + .expect("should convert stored value into CLValue") + .into_t::() + .map_err(DispatchError::CLValue)? + }; + let system_entity_addr = system_entity_registry + .get(system_contract) + .ok_or(DispatchError::MissingSystemContract(system_contract))?; + let entity_addr = EntityAddr::new_system(system_entity_addr.value()); + let addressable_entity_stored_value = tracking_copy + .read(&Key::AddressableEntity(entity_addr))? + .ok_or(DispatchError::MissingAddressableEntity)?; + + let addressable_entity = addressable_entity_stored_value + .clone() + .into_addressable_entity() + .ok_or_else(|| DispatchError::InvalidStoredValueVariant { + expected: StoredValueTag::AddressableEntity, + actual: addressable_entity_stored_value, + })?; + + let config = Config::default(); + let protocol_version = ProtocolVersion::V1_0_0; + + let access_rights = ContextAccessRights::new(*system_entity_addr, []); + let address = PublicKey::System.to_account_hash(); + + let named_keys = tracking_copy + .get_named_keys(entity_addr) + .map_err(DispatchError::GetNamedKeys)?; + + let forked_tracking_copy = Rc::new(RefCell::new(tracking_copy.fork2())); + + let remaining_spending_limit = U512::MAX; // NOTE: Since there's no custom payment, there's no need to track the remaining spending limit. + let phase = Phase::System; // NOTE: Since this is a system contract, the phase is always `System`. + + let ret = { + let runtime = RuntimeNative::new( + config, + protocol_version, + Id::Transaction(transaction_hash), + address_generator, + Rc::clone(&forked_tracking_copy), + address, + Key::AddressableEntity(entity_addr), + addressable_entity, + named_keys, + access_rights, + remaining_spending_limit, + phase, + ); + + func(runtime) + }; + + // SAFETY: `RuntimeNative` is dropped in the block above, we can extract the tracking copy and + // the effects. + let modified_tracking_copy = Rc::try_unwrap(forked_tracking_copy) + .ok() + .expect("No other references"); + + let modified_tracking_copy = modified_tracking_copy.into_inner(); + + tracking_copy.merge_raw_parts(modified_tracking_copy.into_raw_parts()); + + Ok(ret) +} + +#[derive(Debug, Clone, Copy)] +pub(crate) struct MintArgs { + pub(crate) initial_balance: U512, +} + +pub(crate) fn mint_mint( + tracking_copy: &mut TrackingCopy, + transaction_hash: TransactionHash, + address_generator: Arc>, + args: MintArgs, +) -> Result { + let mint_result = match dispatch_system_contract( + tracking_copy, + transaction_hash, + address_generator, + "mint", + |mut runtime| runtime.mint(args.initial_balance), + ) { + Ok(mint_result) => mint_result, + Err(error) => { + error!(%error, ?args, "mint failed"); + panic!("Mint failed; aborting"); + } + }; + + match mint_result { + Ok(uref) => Ok(uref), + Err(casper_types::system::mint::Error::InsufficientFunds) => Err(HostError::CalleeReverted), + Err(casper_types::system::mint::Error::GasLimit) => Err(HostError::CalleeGasDepleted), + Err(mint_error) => { + error!(%mint_error, ?args, "mint transfer failed"); + Err(HostError::CalleeTrapped(TrapCode::UnreachableCodeReached)) + } + } +} + +#[derive(Debug, Copy, Clone)] +pub(crate) struct MintTransferArgs { + pub(crate) maybe_to: Option, + pub(crate) source: URef, + pub(crate) target: URef, + pub(crate) amount: U512, + pub(crate) id: Option, +} + +pub(crate) fn mint_transfer( + tracking_copy: &mut TrackingCopy, + id: TransactionHash, + address_generator: Arc>, + args: MintTransferArgs, +) -> HostResult { + let transfer_result: Result<(), casper_types::system::mint::Error> = + match dispatch_system_contract( + tracking_copy, + id, + address_generator, + "mint", + |mut runtime| { + runtime.transfer( + args.maybe_to, + args.source, + args.target, + args.amount, + args.id, + ) + }, + ) { + Ok(result) => result, + Err(error) => { + error!(%error, "mint transfer failed"); + return Err(HostError::CalleeTrapped(TrapCode::UnreachableCodeReached)); + } + }; + + debug!(?args, ?transfer_result, "transfer"); + + match transfer_result { + Ok(()) => Ok(()), + Err(casper_types::system::mint::Error::InsufficientFunds) => Err(HostError::CalleeReverted), + Err(casper_types::system::mint::Error::GasLimit) => Err(HostError::CalleeGasDepleted), + Err(mint_error) => { + error!(%mint_error, ?args, "mint transfer failed"); + Err(HostError::CalleeTrapped(TrapCode::UnreachableCodeReached)) + } + } +} + +#[cfg(test)] +mod tests { + use casper_storage::{ + data_access_layer::{GenesisRequest, GenesisResult}, + global_state::{ + self, + state::{CommitProvider, StateProvider}, + }, + system::mint::{storage_provider::StorageProvider, Mint}, + }; + use casper_types::{ + AddressableEntityHash, ChainspecRegistry, Digest, GenesisConfigBuilder, HoldsEpoch, + SystemEntityRegistry, TransactionV1Hash, + }; + + use super::*; + + // #[test] + // fn test_system_dispatcher() { + // let (global_state, mut root_hash, _tempdir) = + // global_state::state::lmdb::make_temporary_global_state([]); + + // let genesis_config = GenesisConfigBuilder::default().build(); + + // let genesis_request: GenesisRequest = GenesisRequest::new( + // Digest::hash("foo"), + // ProtocolVersion::V2_0_0, + // genesis_config, + // ChainspecRegistry::new_with_genesis(b"", b""), + // ); + + // match global_state.genesis(genesis_request) { + // GenesisResult::Failure(failure) => panic!("Failed to run genesis: {:?}", failure), + // GenesisResult::Fatal(fatal) => panic!("Fatal error while running genesis: {}", + // fatal), GenesisResult::Success { + // post_state_hash, + // effects: _, + // } => { + // root_hash = post_state_hash; + // } + // } + + // let mut tracking_copy = global_state + // .tracking_copy(root_hash) + // .expect("Obtaining root hash succeed") + // .expect("Root hash exists"); + + // let mut rng = rand::thread_rng(); + // let transaction_hash_bytes: [u8; 32] = rng.gen(); + // let transaction_hash: TransactionHash = + // TransactionHash::V1(TransactionV1Hash::from_raw(transaction_hash_bytes)); + // let id = Id::Transaction(transaction_hash); + // let address_generator = Arc::new(RwLock::new(AddressGenerator::new( + // &id.seed(), + // Phase::Session, + // ))); + + // let ret = dispatch_system_contract( + // &mut tracking_copy, + // transaction_hash, + // Arc::clone(&address_generator), + // "mint", + // |mut runtime| runtime.mint(U512::from(1000u64)), + // ); + + // let uref = ret.expect("Mint"); + + // let ret = dispatch_system_contract( + // &mut tracking_copy, + // transaction_hash, + // Arc::clone(&address_generator), + // "mint", + // |mut runtime| runtime.total_balance(uref), + // ); + + // assert_eq!(ret, Ok(Ok(U512::from(1000u64)))); + + // let post_root_hash = global_state + // .commit(root_hash, tracking_copy.effects()) + // .expect("Should apply effect"); + + // assert_ne!(post_root_hash, root_hash); + // } + + // #[test] + // fn test_mint() { + // let (global_state, mut root_hash, _tempdir) = + // global_state::state::lmdb::make_temporary_global_state([]); + + // let genesis_config = GenesisConfigBuilder::default().build(); + + // let genesis_request: GenesisRequest = GenesisRequest::new( + // Digest::hash("foo"), + // ProtocolVersion::V2_0_0, + // genesis_config, + // ChainspecRegistry::new_with_genesis(b"", b""), + // ); + + // match global_state.genesis(genesis_request) { + // GenesisResult::Failure(failure) => panic!("Failed to run genesis: {:?}", failure), + // GenesisResult::Fatal(fatal) => panic!("Fatal error while running genesis: {}", + // fatal), GenesisResult::Success { + // post_state_hash, + // effects: _, + // } => { + // root_hash = post_state_hash; + // } + // } + + // let mut tracking_copy = global_state + // .tracking_copy(root_hash) + // .expect("Obtaining root hash succeed") + // .expect("Root hash exists"); + + // let system_entity_registry = { + // let stored_value = tracking_copy + // .read(&Key::SystemEntityRegistry) + // .expect("should read system entity registry") + // .expect("should get system entity registry"); + // stored_value + // .into_cl_value() + // .expect("should convert stored value into CLValue") + // .into_t::() + // .expect("should get system entity registry") + // }; + + // let mint = system_entity_registry.get("mint").expect("should get mint"); + // let entity_addr = EntityAddr::new_system(mint.value()); + // let addressable_entity = tracking_copy + // .read(&Key::AddressableEntity(entity_addr)) + // .expect("should read addressable entity") + // .expect("should get addressable entity") + // .into_addressable_entity() + // .expect("should convert stored value into addressable entity"); + + // let mut runtime = RuntimeNative::new( + // entity_addr, + // Config::default(), + // ProtocolVersion::V1_0_0, + // Id::Seed(vec![1, 2, 3]), + // tracking_copy, + // addressable_entity, + // ContextAccessRights::new(AddressableEntityHash::new([5; 32]), []), + // ); + + // let source = runtime.mint(U512::from(1000u64)).expect("Should mint"); + // let source_balance = runtime + // .total_balance(source) + // .expect("Should get total balance"); + // assert_eq!(source_balance, U512::from(1000u64)); + + // let target = runtime.mint(U512::from(1u64)).expect("Should create uref"); + // let target_balance = runtime + // .total_balance(target) + // .expect("Should get total balance"); + // assert_eq!(target_balance, U512::from(1u64)); + + // runtime + // .transfer( + // None, + // source, + // target, + // U512::from(999), + // None, + // HoldsEpoch::NOT_APPLICABLE, + // ) + // .expect("Should transfer"); + + // let source_balance = runtime + // .total_balance(source) + // .expect("Should get total balance"); + // assert_eq!(source_balance, U512::from(1u64)); + // let target_balance = runtime + // .total_balance(target) + // .expect("Should get total balance"); + // assert_eq!(target_balance, U512::from(1000u64)); + + // runtime + // .mint_into_existing_purse(target, U512::from(1000u64)) + // .expect("Should mint"); + + // let target_balance = runtime + // .total_balance(target) + // .expect("Should get total balance"); + // assert_eq!(target_balance, U512::from(2000u64)); + // } +} diff --git a/executor/wasm-interface/Cargo.toml b/executor/wasm-interface/Cargo.toml new file mode 100644 index 0000000000..4a15e6fba7 --- /dev/null +++ b/executor/wasm-interface/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "casper-executor-wasm-interface" +version = "0.1.0" +edition = "2021" + +[dependencies] +bytes = "1.6.0" +thiserror = "1.0.61" +casper-executor-wasm-common = { path = "../wasm-common" } +casper-storage = { path = "../../storage" } +borsh = { version = "1.5.1", features = ["derive"] } +parking_lot = "0.12.3" +casper-types = { path = "../../types" } diff --git a/vm/src/executor.rs b/executor/wasm-interface/src/executor.rs similarity index 55% rename from vm/src/executor.rs rename to executor/wasm-interface/src/executor.rs index 63962ef3d0..4574da6069 100644 --- a/vm/src/executor.rs +++ b/executor/wasm-interface/src/executor.rs @@ -1,205 +1,60 @@ -pub mod v2; - use std::sync::Arc; use borsh::BorshSerialize; use bytes::Bytes; -use casper_storage::{tracking_copy::TrackingCopyParts, AddressGenerator}; +use casper_storage::{ + address_generator::Address, global_state::GlobalStateReader, tracking_copy::TrackingCopyParts, + AddressGenerator, TrackingCopy, +}; use casper_types::{ + account::AccountHash, contracts::{ContractHash, ContractPackageHash}, execution::Effects, EntityAddr, Key, TransactionHash, }; use parking_lot::RwLock; use thiserror::Error; -use vm_common::selector::Selector; - -use crate::{ - storage::{Address, GlobalStateReader, TrackingCopy}, - wasm_backend::{GasUsage, WasmPreparationError}, - HostError, -}; - -/// Store contract request. -pub struct InstantiateContractRequest { - /// Initiator's address. - pub(crate) initiator: Address, - /// Gas limit. - pub(crate) gas_limit: u64, - /// Wasm bytes of the contract to be stored. - pub(crate) wasm_bytes: Bytes, - /// Constructor entry point name. - pub(crate) entry_point: Option, - /// Input data for the constructor. - pub(crate) input: Option, - /// Value of tokens to be transferred into the constructor. - pub(crate) value: u128, - /// Transaction hash. - pub(crate) transaction_hash: TransactionHash, - /// Address generator. - pub(crate) address_generator: Arc>, - /// Chain name. - pub(crate) chain_name: Arc, -} - -#[derive(Default)] -pub struct InstantiateContractRequestBuilder { - initiator: Option
, - gas_limit: Option, - wasm_bytes: Option, - entry_point: Option, - input: Option, - value: Option, - transaction_hash: Option, - address_generator: Option>>, - chain_name: Option>, -} - -impl InstantiateContractRequestBuilder { - pub fn with_initiator(mut self, initiator: Address) -> Self { - self.initiator = Some(initiator); - self - } - - pub fn with_gas_limit(mut self, gas_limit: u64) -> Self { - self.gas_limit = Some(gas_limit); - self - } - - pub fn with_wasm_bytes(mut self, wasm_bytes: Bytes) -> Self { - self.wasm_bytes = Some(wasm_bytes); - self - } - - pub fn with_entry_point(mut self, entry_point: String) -> Self { - self.entry_point = Some(entry_point); - self - } - - pub fn with_input(mut self, input: Bytes) -> Self { - self.input = Some(input); - self - } - - pub fn with_value(mut self, value: u128) -> Self { - self.value = Some(value); - self - } - - pub fn with_address_generator(mut self, address_generator: AddressGenerator) -> Self { - self.address_generator = Some(Arc::new(RwLock::new(address_generator))); - self - } - - pub fn with_shared_address_generator( - mut self, - address_generator: Arc>, - ) -> Self { - self.address_generator = Some(address_generator); - self - } - pub fn with_transaction_hash(mut self, transaction_hash: TransactionHash) -> Self { - self.transaction_hash = Some(transaction_hash); - self - } - - pub fn with_chain_name>>(mut self, chain_name: T) -> Self { - self.chain_name = Some(chain_name.into()); - self - } - - pub fn build(self) -> Result { - let initiator = self.initiator.ok_or("Initiator not set")?; - let gas_limit = self.gas_limit.ok_or("Gas limit not set")?; - let wasm_bytes = self.wasm_bytes.ok_or("Wasm bytes not set")?; - let entry_point = self.entry_point; - let input = self.input; - let value = self.value.ok_or("Value not set")?; - let address_generator = self.address_generator.ok_or("Address generator not set")?; - let transaction_hash = self.transaction_hash.ok_or("Transaction hash not set")?; - let chain_name = self.chain_name.ok_or("Chain name not set")?; - Ok(InstantiateContractRequest { - initiator, - gas_limit, - wasm_bytes, - entry_point, - input, - value, - address_generator, - transaction_hash, - chain_name, - }) - } -} - -/// Result of executing a Wasm contract. -#[derive(Debug)] -pub struct StoreContractResult { - /// Contract package hash. - pub(crate) contract_package_hash: ContractPackageHash, - /// Contract hash. - pub(crate) contract_hash: ContractHash, - /// Version - pub(crate) version: u32, - /// Gas usage. - pub(crate) gas_usage: GasUsage, - /// Effects produced by the execution. - pub(crate) tracking_copy_parts: TrackingCopyParts, -} -impl StoreContractResult { - pub fn effects(&self) -> &Effects { - let (_cache, effects, _x) = &self.tracking_copy_parts; - effects - } - - pub fn contract_hash(&self) -> [u8; 32] { - self.contract_hash.value() - } - - pub fn gas_usage(&self) -> &GasUsage { - &self.gas_usage - } -} +use crate::{GasUsage, HostError, WasmPreparationError}; /// Request to execute a Wasm contract. pub struct ExecuteRequest { /// Initiator's address. - pub(crate) initiator: Address, + pub initiator: AccountHash, /// Caller's address key. /// /// Either a `[`Key::Account`]` or a `[`Key::AddressableEntity`]. - pub(crate) caller_key: Key, + pub caller_key: Key, /// Callee's address key. TODO: Remove this field as the callee is derived from the execution /// kind field. /// /// Either a `[`Key::Account`]` or a `[`Key::AddressableEntity`]. - pub(crate) callee_key: Key, + pub callee_key: Key, /// Gas limit. - pub(crate) gas_limit: u64, + pub gas_limit: u64, /// Target for execution. - pub(crate) execution_kind: ExecutionKind, + pub execution_kind: ExecutionKind, /// Input data. - pub(crate) input: Bytes, + pub input: Bytes, /// Value transferred to the contract. - pub(crate) value: u128, + pub value: u128, /// Transaction hash. - pub(crate) transaction_hash: TransactionHash, + pub transaction_hash: TransactionHash, /// Address generator. /// /// This can be either seeded and created as part of the builder or shared across chain of /// execution requests. - pub(crate) address_generator: Arc>, + pub address_generator: Arc>, /// Chain name. /// /// This is very important ingredient for deriving contract hashes on the network. - pub(crate) chain_name: Arc, + pub chain_name: Arc, } /// Builder for `ExecuteRequest`. #[derive(Default)] pub struct ExecuteRequestBuilder { - initiator: Option
, + initiator: Option, caller_key: Option, callee_key: Option, gas_limit: Option, @@ -213,7 +68,7 @@ pub struct ExecuteRequestBuilder { impl ExecuteRequestBuilder { /// Set the initiator's address. - pub fn with_initiator(mut self, initiator: Address) -> Self { + pub fn with_initiator(mut self, initiator: AccountHash) -> Self { self.initiator = Some(initiator); self } @@ -328,13 +183,13 @@ impl ExecuteRequestBuilder { #[derive(Debug)] pub struct ExecuteResult { /// Error while executing Wasm: traps, memory access errors, etc. - pub(crate) host_error: Option, + pub host_error: Option, /// Output produced by the Wasm contract. - pub(crate) output: Option, + pub output: Option, /// Gas usage. - pub(crate) gas_usage: GasUsage, + pub gas_usage: GasUsage, /// Effects produced by the execution. - pub(crate) tracking_copy_parts: TrackingCopyParts, + pub tracking_copy_parts: TrackingCopyParts, } impl ExecuteResult { @@ -384,18 +239,6 @@ pub enum ExecuteError { WasmPreparation(#[from] WasmPreparationError), } -#[derive(Debug, Error)] -pub enum StoreContractError { - #[error("system contract error: {0}")] - SystemContract(HostError), - - #[error("execute: {0}")] - Execute(ExecuteError), - - #[error("constructor error: {host_error}")] - Constructor { host_error: HostError }, -} - /// Executor trait. /// /// An executor is responsible for executing Wasm contracts. This implies that the executor is able @@ -404,11 +247,11 @@ pub enum StoreContractError { /// Trait bounds also implying that the executor has to support interior mutability, as it may need /// to update its internal state during execution of a single or a chain of multiple contracts. pub trait Executor: Clone + Send { - fn instantiate_contract( - &self, - tracking_copy: TrackingCopy, - store_request: InstantiateContractRequest, - ) -> Result; + // fn instantiate_contract( + // &self, + // tracking_copy: TrackingCopy, + // store_request: InstantiateContractRequest, + // ) -> Result; fn execute( &self, diff --git a/vm/src/lib.rs b/executor/wasm-interface/src/lib.rs similarity index 62% rename from vm/src/lib.rs rename to executor/wasm-interface/src/lib.rs index eea0ff1ab0..2e91e27654 100644 --- a/vm/src/lib.rs +++ b/executor/wasm-interface/src/lib.rs @@ -1,19 +1,12 @@ -pub mod chain; -pub mod chain_utils; pub mod executor; -pub(crate) mod host; -pub mod storage; -pub(crate) mod wasm_backend; use std::fmt::{self, Display, Formatter}; use bytes::Bytes; - -use executor::Executor; -use storage::GlobalStateReader; +use casper_storage::global_state::GlobalStateReader; use thiserror::Error; -use vm_common::flags::ReturnFlags; -use wasm_backend::{wasmer::WasmerInstance, Context, WasmInstance, WasmPreparationError}; + +use casper_executor_wasm_common::flags::ReturnFlags; const CALLEE_SUCCEED: u32 = 0; const CALLEE_REVERTED: u32 = 1; @@ -24,40 +17,27 @@ const CALLEE_NOT_CALLABLE: u32 = 4; /// Represents the result of a host function call. /// /// 0 is used as a success. -#[derive(Debug)] -#[repr(u32)] +#[derive(Debug, Error)] pub enum HostError { /// Callee contract reverted. + #[error("callee reverted")] CalleeReverted, /// Called contract trapped. + #[error("callee trapped: {0}")] CalleeTrapped(TrapCode), /// Called contract reached gas limit. + #[error("callee gas depleted")] CalleeGasDepleted, /// Called contract is not callable. + #[error("not callable")] NotCallable, } -impl Display for HostError { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - HostError::CalleeReverted => write!(f, "callee reverted"), - HostError::CalleeTrapped(trap) => write!(f, "callee trapped: {}", trap), - HostError::CalleeGasDepleted => write!(f, "callee gas depleted"), - HostError::NotCallable => write!(f, "callee not callable"), - } - } -} - -// no revert: output -// revert: output -// trap: no output -// gas depleted: no output - -type HostResult = Result<(), HostError>; +pub type HostResult = Result<(), HostError>; impl HostError { /// Converts the host error into a u32. - pub(crate) fn into_u32(self) -> u32 { + fn into_u32(self) -> u32 { match self { HostError::CalleeReverted => CALLEE_REVERTED, HostError::CalleeTrapped(_) => CALLEE_TRAPPED, @@ -68,30 +48,13 @@ impl HostError { } /// Converts a host result into a u32. -pub(crate) fn u32_from_host_result(result: HostResult) -> u32 { +pub fn u32_from_host_result(result: HostResult) -> u32 { match result { Ok(_) => CALLEE_SUCCEED, Err(host_error) => host_error.into_u32(), } } -/// `WasmEngine` is a struct that represents a WebAssembly engine. -/// -/// This struct is used to encapsulate the operations and state of a WebAssembly engine. -/// Currently, it does not hold any data (`()`), but it can be extended in the future to hold -/// different compiler instances, configuration options, cached artifacts, state information, -/// etc. -/// -/// # Examples -/// -/// Basic usage: -/// -/// ``` -/// let engine = WasmEngine::new(); -/// ``` -#[derive(Clone)] -pub struct WasmEngine(()); - /// Errors that can occur when resolving imports. #[derive(Debug, Error)] pub enum Resolver { @@ -158,11 +121,11 @@ pub enum TrapCode { #[error("unreachable")] UnreachableCodeReached, } + /// The outcome of a call. /// We can fold all errors into this type and return it from the host functions and remove Outcome /// type. #[derive(Debug, Error)] -#[non_exhaustive] pub enum VMError { #[error("Return 0x{flags:?} {data:?}")] Return { @@ -197,9 +160,18 @@ pub type VMResult = Result; /// Configuration for the Wasm engine. #[derive(Clone, Debug)] pub struct Config { - pub(crate) gas_limit: u64, - pub(crate) memory_limit: u32, - pub(crate) input: Bytes, + gas_limit: u64, + memory_limit: u32, +} + +impl Config { + pub fn gas_limit(&self) -> u64 { + self.gas_limit + } + + pub fn memory_limit(&self) -> u32 { + self.memory_limit + } } /// Configuration for the Wasm engine. @@ -208,8 +180,6 @@ pub struct ConfigBuilder { gas_limit: Option, /// Memory limit in pages. memory_limit: Option, - /// Input data. - input: Option, } impl ConfigBuilder { @@ -230,47 +200,110 @@ impl ConfigBuilder { self } - /// Pass input data. - pub fn with_input(mut self, input: Bytes) -> Self { - self.input = Some(input); - self - } - /// Build the configuration. pub fn build(self) -> Config { let gas_limit = self.gas_limit.expect("Required field"); let memory_limit = self.memory_limit.expect("Required field"); - let input = self.input.unwrap_or_default(); Config { gas_limit, memory_limit, - input, } } } -impl WasmEngine { - pub(crate) fn prepare>( - &self, - wasm_bytes: C, - context: Context, - config: Config, - ) -> Result, WasmPreparationError> { - let wasm_bytes: Bytes = wasm_bytes.into(); - // NOTE: We can add more engines here in the future, e.g. Lucet, Wasmtime, wasmi all - // configurable at runtime. For now, it's ok to return `impl WasmInstance`. - let instance = WasmerInstance::from_wasm_bytes(wasm_bytes, context, config)?; - Ok(instance) +#[derive(Debug, Copy, Clone)] +pub enum MeteringPoints { + Remaining(u64), + Exhausted, +} + +impl MeteringPoints { + pub fn try_into_remaining(self) -> Result { + if let Self::Remaining(v) = self { + Ok(v) + } else { + Err(self) + } } +} - #[inline] - pub fn new() -> Self { - WasmEngine(()) +/// An abstraction over the 'caller' object of a host function that works for any Wasm VM. +/// +/// This allows access for important instances such as the context object that was passed to the +/// instance, wasm linear memory access, etc. + +pub trait Caller { + type Context; + + fn config(&self) -> &Config; + fn context(&self) -> &Self::Context; + fn context_mut(&mut self) -> &mut Self::Context; + /// Returns currently running *unmodified* bytecode. + fn bytecode(&self) -> Bytes; + + fn memory_read(&self, offset: u32, size: usize) -> VMResult> { + let mut vec = vec![0; size]; + self.memory_read_into(offset, &mut vec)?; + Ok(vec) } + fn memory_read_into(&self, offset: u32, output: &mut [u8]) -> VMResult<()>; + fn memory_write(&self, offset: u32, data: &[u8]) -> VMResult<()>; + /// Allocates memory inside the Wasm VM by calling an export. + /// + /// Error is a type-erased error coming from the VM itself. + fn alloc(&mut self, idx: u32, size: usize, ctx: u32) -> VMResult; + /// Returns the amount of gas used. + fn gas_consumed(&mut self) -> MeteringPoints; + /// Set the amount of gas used. + fn consume_gas(&mut self, value: u64) -> MeteringPoints; +} + +#[derive(Debug, Error)] +pub enum WasmPreparationError { + #[error("Missing export {0}")] + MissingExport(String), + #[error("Compile error: {0}")] + Compile(String), + #[error("Memory instantiation error: {0}")] + Memory(String), + #[error("Instantiation error: {0}")] + Instantiation(String), +} + +#[derive(Debug)] +pub struct GasUsage { + /// The amount of gas used by the execution. + gas_limit: u64, + /// The amount of gas remaining after the execution. + remaining_points: u64, } -impl Default for WasmEngine { - fn default() -> Self { - Self::new() +impl GasUsage { + pub fn new(gas_limit: u64, remaining_points: u64) -> Self { + GasUsage { + gas_limit, + remaining_points, + } } + + pub fn gas_spent(&self) -> u64 { + debug_assert!(self.remaining_points <= self.gas_limit); + self.gas_limit - self.remaining_points + } + + pub fn gas_limit(&self) -> u64 { + self.gas_limit + } + + pub fn remaining_points(&self) -> u64 { + self.remaining_points + } +} + +/// A trait that represents a Wasm instance. +pub trait WasmInstance { + type Context; + + fn call_export(&mut self, name: &str) -> (Result<(), VMError>, GasUsage); + fn teardown(self) -> Self::Context; } diff --git a/executor/wasm/Cargo.toml b/executor/wasm/Cargo.toml new file mode 100644 index 0000000000..7ca2cd3b8f --- /dev/null +++ b/executor/wasm/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "casper-executor-wasm" +version = "0.1.0" +edition = "2021" + +[dependencies] +blake2 = "0.10.6" +borsh = {version = "1.2.0", features = ["derive"] } +bytes = "1.4.0" +casper-executor-wasm-common = { path = "../wasm-common" } +casper-executor-wasm-host = { path = "../wasm-host" } +casper-executor-wasm-interface = { path = "../wasm-interface" } +casper-executor-wasmer-backend = { path = "../wasmer-backend" } +casper-storage = { path = "../../storage" } +casper-types = { path = "../../types" } +digest = "0.10.7" +either = "1.10" +parking_lot = "0.12.1" +thiserror = "1.0.44" +tracing = "0.1.40" + +[dev-dependencies] +tempfile = "3.10.1" +once_cell = "1.19.0" diff --git a/vm/src/chain_utils.rs b/executor/wasm/src/chain_utils.rs similarity index 82% rename from vm/src/chain_utils.rs rename to executor/wasm/src/chain_utils.rs index e19f247d41..d788034f94 100644 --- a/vm/src/chain_utils.rs +++ b/executor/wasm/src/chain_utils.rs @@ -1,8 +1,7 @@ use blake2::Blake2b; +use casper_types::{account::AccountHash, HashAddr}; use digest::{consts::U32, Digest}; -use crate::storage::Address; - /// Compute a predictable address for a contract. /// /// The address is computed as the hash of the chain name, initiator account, and the hash of the @@ -10,10 +9,10 @@ use crate::storage::Address; /// different chains. pub(crate) fn compute_predictable_address>( chain_name: T, - initiator: Address, - bytecode_hash: Address, -) -> Address { - let contract_hash: Address = { + initiator: AccountHash, + bytecode_hash: HashAddr, +) -> HashAddr { + let contract_hash: HashAddr = { let mut hasher = Blake2b::::new(); hasher.update(chain_name); @@ -26,7 +25,7 @@ pub(crate) fn compute_predictable_address>( contract_hash } -pub(crate) fn compute_wasm_bytecode_hash>(wasm_bytes: T) -> Address { +pub(crate) fn compute_wasm_bytecode_hash>(wasm_bytes: T) -> HashAddr { let mut hasher = Blake2b::::new(); hasher.update(wasm_bytes); let hash = hasher.finalize(); @@ -35,9 +34,11 @@ pub(crate) fn compute_wasm_bytecode_hash>(wasm_bytes: T) -> Addre #[cfg(test)] mod tests { + use casper_types::account::AccountHash; + #[test] fn test_compute_predictable_address() { - let initiator = [1u8; 32]; + let initiator = AccountHash::new([1u8; 32]); let bytecode_hash = [2u8; 32]; let predictable_address_1 = diff --git a/executor/wasm/src/install.rs b/executor/wasm/src/install.rs new file mode 100644 index 0000000000..2ab3520a38 --- /dev/null +++ b/executor/wasm/src/install.rs @@ -0,0 +1,167 @@ +use std::sync::Arc; + +use bytes::Bytes; +use casper_executor_wasm_interface::{executor::ExecuteError, GasUsage, HostError}; +use casper_storage::{tracking_copy::TrackingCopyParts, AddressGenerator}; +use casper_types::{ + account::AccountHash, + contracts::{ContractHash, ContractPackageHash}, + execution::Effects, + TransactionHash, +}; +use parking_lot::RwLock; +use thiserror::Error; + +/// Store contract request. +pub struct InstallContractRequest { + /// Initiator's address. + pub(crate) initiator: AccountHash, + /// Gas limit. + pub(crate) gas_limit: u64, + /// Wasm bytes of the contract to be stored. + pub(crate) wasm_bytes: Bytes, + /// Constructor entry point name. + pub(crate) entry_point: Option, + /// Input data for the constructor. + pub(crate) input: Option, + /// Value of tokens to be transferred into the constructor. + pub(crate) value: u128, + /// Transaction hash. + pub(crate) transaction_hash: TransactionHash, + /// Address generator. + pub(crate) address_generator: Arc>, + /// Chain name. + pub(crate) chain_name: Arc, +} + +#[derive(Default)] +pub struct InstallContractRequestBuilder { + initiator: Option, + gas_limit: Option, + wasm_bytes: Option, + entry_point: Option, + input: Option, + value: Option, + transaction_hash: Option, + address_generator: Option>>, + chain_name: Option>, +} + +impl InstallContractRequestBuilder { + pub fn with_initiator(mut self, initiator: AccountHash) -> Self { + self.initiator = Some(initiator); + self + } + + pub fn with_gas_limit(mut self, gas_limit: u64) -> Self { + self.gas_limit = Some(gas_limit); + self + } + + pub fn with_wasm_bytes(mut self, wasm_bytes: Bytes) -> Self { + self.wasm_bytes = Some(wasm_bytes); + self + } + + pub fn with_entry_point(mut self, entry_point: String) -> Self { + self.entry_point = Some(entry_point); + self + } + + pub fn with_input(mut self, input: Bytes) -> Self { + self.input = Some(input); + self + } + + pub fn with_value(mut self, value: u128) -> Self { + self.value = Some(value); + self + } + + pub fn with_address_generator(mut self, address_generator: AddressGenerator) -> Self { + self.address_generator = Some(Arc::new(RwLock::new(address_generator))); + self + } + + pub fn with_shared_address_generator( + mut self, + address_generator: Arc>, + ) -> Self { + self.address_generator = Some(address_generator); + self + } + + pub fn with_transaction_hash(mut self, transaction_hash: TransactionHash) -> Self { + self.transaction_hash = Some(transaction_hash); + self + } + + pub fn with_chain_name>>(mut self, chain_name: T) -> Self { + self.chain_name = Some(chain_name.into()); + self + } + + pub fn build(self) -> Result { + let initiator = self.initiator.ok_or("Initiator not set")?; + let gas_limit = self.gas_limit.ok_or("Gas limit not set")?; + let wasm_bytes = self.wasm_bytes.ok_or("Wasm bytes not set")?; + let entry_point = self.entry_point; + let input = self.input; + let value = self.value.ok_or("Value not set")?; + let address_generator = self.address_generator.ok_or("Address generator not set")?; + let transaction_hash = self.transaction_hash.ok_or("Transaction hash not set")?; + let chain_name = self.chain_name.ok_or("Chain name not set")?; + Ok(InstallContractRequest { + initiator, + gas_limit, + wasm_bytes, + entry_point, + input, + value, + address_generator, + transaction_hash, + chain_name, + }) + } +} + +/// Result of executing a Wasm contract. +#[derive(Debug)] +pub struct InstallContractResult { + /// Contract package hash. + pub(crate) contract_package_hash: ContractPackageHash, + /// Contract hash. + pub(crate) contract_hash: ContractHash, + /// Version + pub(crate) version: u32, + /// Gas usage. + pub(crate) gas_usage: GasUsage, + /// Effects produced by the execution. + pub(crate) tracking_copy_parts: TrackingCopyParts, +} +impl InstallContractResult { + pub fn effects(&self) -> &Effects { + let (_cache, effects, _x) = &self.tracking_copy_parts; + effects + } + + pub fn contract_hash(&self) -> [u8; 32] { + self.contract_hash.value() + } + + pub fn gas_usage(&self) -> &GasUsage { + &self.gas_usage + } +} + +#[derive(Debug, Error)] +pub enum InstallContractError { + #[error("system contract error: {0}")] + SystemContract(HostError), + + #[error("execute: {0}")] + Execute(ExecuteError), + + #[error("constructor error: {host_error}")] + Constructor { host_error: HostError }, +} diff --git a/vm/src/executor/v2.rs b/executor/wasm/src/lib.rs similarity index 87% rename from vm/src/executor/v2.rs rename to executor/wasm/src/lib.rs index 3385b0ab68..79f10377d4 100644 --- a/vm/src/executor/v2.rs +++ b/executor/wasm/src/lib.rs @@ -1,38 +1,47 @@ +mod chain_utils; +pub mod install; +pub(crate) mod system; + use std::{collections::VecDeque, sync::Arc}; use blake2::{Blake2b, Digest}; use bytes::Bytes; -use casper_storage::{address_generator, tracking_copy::TrackingCopyExt, AddressGenerator}; +use casper_executor_wasm_common::flags::{EntryPointFlags, ReturnFlags}; +use casper_executor_wasm_host::context::Context; +use casper_executor_wasm_interface::{ + executor::{ + ExecuteError, ExecuteRequest, ExecuteRequestBuilder, ExecuteResult, ExecutionKind, Executor, + }, + ConfigBuilder, GasUsage, HostError, TrapCode, VMError, WasmInstance, +}; +use casper_executor_wasmer_backend::WasmerEngine; +use casper_storage::{global_state::GlobalStateReader, TrackingCopy}; use casper_types::{ - account::AccountHash, addressable_entity::{self, ActionThresholds, AssociatedKeys, MessageTopics}, - bytesrepr::ToBytes, contracts::{ContractHash, ContractPackageHash}, - system, AddressableEntity, AddressableEntityHash, ByteCode, ByteCodeAddr, ByteCodeHash, - ByteCodeKind, EntityAddr, EntityKind, EntryPointAddr, EntryPointValue, Groups, HoldsEpoch, Key, - Package, PackageHash, PackageStatus, ProtocolVersion, StoredValue, TransactionRuntime, URef, - U512, + AddressableEntity, ByteCode, ByteCodeAddr, ByteCodeHash, ByteCodeKind, EntityAddr, EntityKind, + Groups, Key, Package, PackageHash, PackageStatus, ProtocolVersion, StoredValue, + TransactionRuntime, URef, U512, }; -use digest::consts::U32; use either::Either; +use install::{InstallContractError, InstallContractRequest, InstallContractResult}; use parking_lot::RwLock; +use system::{MintArgs, MintTransferArgs}; use tracing::{error, warn}; -use vm_common::flags::{EntryPointFlags, ReturnFlags}; -use wasmer_types::compilation::function; -use super::{ - ExecuteError, ExecuteRequest, ExecuteRequestBuilder, ExecuteResult, ExecutionKind, Executor, - InstantiateContractRequest, StoreContractError, StoreContractResult, -}; -use crate::{ - chain_utils, - storage::{ - runtime::{self, MintArgs, MintTransferArgs}, - Address, GlobalStateReader, TrackingCopy, - }, - wasm_backend::{Context, GasUsage, WasmInstance}, - ConfigBuilder, HostError, TrapCode, VMError, WasmEngine, -}; +// use super::{ +// ExecuteError, ExecuteRequest, ExecuteRequestBuilder, ExecuteResult, ExecutionKind, Executor, +// InstantiateContractRequest, InstallContractError, StoreContractResult, +// }; +// use crate::{ +// chain_utils, +// storage::{ +// runtime::{self, MintArgs, MintTransferArgs}, +// Address, GlobalStateReader, TrackingCopy, +// }, +// wasm_backend::{Context, GasUsage, WasmInstance}, +// ConfigBuilder, HostError, TrapCode, VMError, WasmEngine, +// }; const DEFAULT_WASM_ENTRY_POINT: &str = "call"; @@ -92,41 +101,17 @@ impl ExecutorConfigBuilder { #[derive(Clone)] pub struct ExecutorV2 { config: ExecutorConfig, - vm: Arc, + compiled_wasm_engine: Arc, execution_stack: Arc>>, } impl ExecutorV2 { - /// Create a new `ExecutorV2` instance. - pub fn new(config: ExecutorConfig) -> Self { - let vm = WasmEngine::new(); - ExecutorV2 { - config, - vm: Arc::new(vm), - execution_stack: Default::default(), - } - } - - /// Push the execution stack. - pub(crate) fn push_execution_stack(&self, execution_kind: ExecutionKind) { - let mut execution_stack = self.execution_stack.write(); - execution_stack.push_back(execution_kind); - } - - /// Pop the execution stack. - pub(crate) fn pop_execution_stack(&self) -> Option { - let mut execution_stack = self.execution_stack.write(); - execution_stack.pop_back() - } -} - -impl Executor for ExecutorV2 { - fn instantiate_contract( + pub fn install_contract( &self, mut tracking_copy: TrackingCopy, - instantiate_request: InstantiateContractRequest, - ) -> Result { - let InstantiateContractRequest { + instantiate_request: InstallContractRequest, + ) -> Result { + let InstallContractRequest { initiator, gas_limit, wasm_bytes, @@ -138,7 +123,7 @@ impl Executor for ExecutorV2 { chain_name, } = instantiate_request; - let caller_key = Key::Account(AccountHash::new(initiator.into())); + let caller_key = Key::Account(initiator); let source_purse = get_purse_for_entity(&mut tracking_copy, caller_key); // 1. Store package hash @@ -151,7 +136,7 @@ impl Executor for ExecutorV2 { let bytecode_hash = chain_utils::compute_wasm_bytecode_hash(&wasm_bytes); - let package_hash_bytes: Address; + let package_hash_bytes: [u8; 32]; let contract_hash = chain_utils::compute_predictable_address( chain_name.as_bytes(), initiator, @@ -187,7 +172,7 @@ impl Executor for ExecutorV2 { // TODO: abort(str) as an alternative to trap let transaction_hash = transaction_hash; - let main_purse: URef = match runtime::mint_mint( + let main_purse: URef = match system::mint_mint( &mut tracking_copy, transaction_hash, Arc::clone(&address_generator), @@ -198,7 +183,7 @@ impl Executor for ExecutorV2 { Ok(uref) => uref, Err(mint_error) => { error!(?mint_error, "Failed to create a purse"); - return Err(StoreContractError::SystemContract( + return Err(InstallContractError::SystemContract( HostError::CalleeTrapped(TrapCode::UnreachableCodeReached), )); } @@ -250,7 +235,7 @@ impl Executor for ExecutorV2 { tracking_copy_parts, }) => { if let Some(host_error) = host_error { - return Err(StoreContractError::Constructor { host_error }); + return Err(InstallContractError::Constructor { host_error }); } tracking_copy.merge_raw_parts(tracking_copy_parts); @@ -263,7 +248,7 @@ impl Executor for ExecutorV2 { } Err(error) => { error!(%error, "unable to execute constructor"); - return Err(StoreContractError::Execute(error)); + return Err(InstallContractError::Execute(error)); } } } @@ -274,7 +259,7 @@ impl Executor for ExecutorV2 { } }; - Ok(StoreContractResult { + Ok(InstallContractResult { contract_package_hash: ContractPackageHash::new(package_hash_bytes), contract_hash: ContractHash::new(contract_hash), version: 1, @@ -282,7 +267,35 @@ impl Executor for ExecutorV2 { tracking_copy_parts: tracking_copy.into_raw_parts(), }) } +} + +impl ExecutorV2 { + /// Create a new `ExecutorV2` instance. + pub fn new(config: ExecutorConfig) -> Self { + let wasm_engine = match config.executor_kind { + ExecutorKind::Compiled => WasmerEngine::new(), + }; + ExecutorV2 { + config, + compiled_wasm_engine: Arc::new(wasm_engine), + execution_stack: Default::default(), + } + } + /// Push the execution stack. + pub(crate) fn push_execution_stack(&self, execution_kind: ExecutionKind) { + let mut execution_stack = self.execution_stack.write(); + execution_stack.push_back(execution_kind); + } + + /// Pop the execution stack. + pub(crate) fn pop_execution_stack(&self) -> Option { + let mut execution_stack = self.execution_stack.write(); + execution_stack.pop_back() + } +} + +impl Executor for ExecutorV2 { /// Execute a Wasm contract. /// /// # Errors @@ -368,7 +381,7 @@ impl Executor for ExecutorV2 { } }; - match runtime::mint_transfer( + match system::mint_transfer( &mut tracking_copy, transaction_hash, Arc::clone(&address_generator), @@ -381,11 +394,10 @@ impl Executor for ExecutorV2 { return Ok(ExecuteResult { host_error: Some(error), output: None, - gas_usage: GasUsage { + gas_usage: GasUsage::new( gas_limit, - remaining_points: gas_limit - - DEFAULT_MINT_TRANSFER_GAS_COST, - }, + gas_limit - DEFAULT_MINT_TRANSFER_GAS_COST, + ), tracking_copy_parts: tracking_copy.into_raw_parts(), }); } @@ -404,7 +416,7 @@ impl Executor for ExecutorV2 { } }; - let vm = Arc::clone(&self.vm); + let vm = Arc::clone(&self.compiled_wasm_engine); let mut initial_tracking_copy = tracking_copy.fork2(); @@ -413,7 +425,7 @@ impl Executor for ExecutorV2 { address: entity_addr, .. } => Key::AddressableEntity(*entity_addr), - ExecutionKind::SessionBytes(_wasm_bytes) => Key::Account(AccountHash::new(initiator)), + ExecutionKind::SessionBytes(_wasm_bytes) => Key::Account(initiator), }; let context = Context { @@ -426,12 +438,12 @@ impl Executor for ExecutorV2 { address_generator: Arc::clone(&address_generator), transaction_hash, chain_name, + input, }; let wasm_instance_config = ConfigBuilder::new() .with_gas_limit(gas_limit) .with_memory_limit(self.config.memory_limit) - .with_input(input) .build(); let mut instance = vm.prepare(wasm_bytes, context, wasm_instance_config)?; diff --git a/vm/src/storage/runtime.rs b/executor/wasm/src/system.rs similarity index 94% rename from vm/src/storage/runtime.rs rename to executor/wasm/src/system.rs index 02005f8f48..597e0dd475 100644 --- a/vm/src/storage/runtime.rs +++ b/executor/wasm/src/system.rs @@ -1,36 +1,29 @@ +//! System contract wire up for the new engine. +//! +//! This module wraps system contract logic into a dispatcher that can be used by the new engine +//! hiding the complexity of the underlying implementation. use std::{cell::RefCell, rc::Rc, sync::Arc}; +use casper_executor_wasm_interface::{HostError, HostResult, TrapCode}; use casper_storage::{ - address_generator, - data_access_layer::mint, + global_state::GlobalStateReader, system::{ self, mint::Mint, runtime_native::{Config, Id, RuntimeNative}, }, - tracking_copy::{TrackingCopyError, TrackingCopyExt, TrackingCopyParts}, - AddressGenerator, + tracking_copy::{TrackingCopyError, TrackingCopyExt}, + AddressGenerator, TrackingCopy, }; use casper_types::{ - account::AccountHash, - addressable_entity::{self, NamedKeyAddr, NamedKeys}, - execution::Effects, - AddressableEntity, AddressableEntityHash, CLValueError, ContextAccessRights, EntityAddr, - HoldsEpoch, Key, KeyTag, Phase, ProtocolVersion, PublicKey, StoredValue, StoredValueTag, - SystemEntityRegistry, TransactionHash, URef, U512, + account::AccountHash, CLValueError, ContextAccessRights, EntityAddr, Key, Phase, + ProtocolVersion, PublicKey, StoredValue, StoredValueTag, SystemEntityRegistry, TransactionHash, + URef, U512, }; use parking_lot::RwLock; use thiserror::Error; use tracing::{debug, error}; -use crate::{ - executor::{ExecuteError, ExecuteRequest, ExecuteResult, ExecutionKind, Executor}, - wasm_backend::{Caller, WasmPreparationError}, - HostError, HostResult, TrapCode, -}; - -use super::{Address, GlobalStateReader, TrackingCopy}; - #[derive(Debug, Error)] enum DispatchError { #[error("Tracking copy error: {0}")] diff --git a/vm/tests/integration.rs b/executor/wasm/tests/integration.rs similarity index 92% rename from vm/tests/integration.rs rename to executor/wasm/tests/integration.rs index b083ed5a68..1f24e25e4b 100644 --- a/vm/tests/integration.rs +++ b/executor/wasm/tests/integration.rs @@ -1,6 +1,13 @@ use std::sync::Arc; use bytes::Bytes; +use casper_executor_wasm::{ + install::{InstallContractRequest, InstallContractRequestBuilder, InstallContractResult}, + ExecutorConfigBuilder, ExecutorKind, ExecutorV2, +}; +use casper_executor_wasm_interface::executor::{ + ExecuteRequest, ExecuteRequestBuilder, ExecuteResult, ExecutionKind, Executor, +}; use casper_storage::{ address_generator::Address, data_access_layer::{GenesisRequest, GenesisResult}, @@ -12,15 +19,9 @@ use casper_storage::{ AddressGenerator, }; use casper_types::{ - account::AccountHash, - execution::{Effects, ExecutionResult, TransformKindV2}, - ChainspecRegistry, Digest, EntityAddr, GenesisAccount, GenesisConfigBuilder, Key, Motes, Phase, - ProtocolVersion, PublicKey, SecretKey, TransactionHash, TransactionV1Hash, U512, -}; -use casper_vm::executor::{ - v2::{ExecutorConfigBuilder, ExecutorKind, ExecutorV2}, - ExecuteRequest, ExecuteRequestBuilder, ExecuteResult, ExecutionKind, Executor, - InstantiateContractRequest, InstantiateContractRequestBuilder, StoreContractResult, + account::AccountHash, ChainspecRegistry, Digest, EntityAddr, GenesisAccount, + GenesisConfigBuilder, Key, Motes, Phase, ProtocolVersion, PublicKey, SecretKey, + TransactionHash, TransactionV1Hash, U512, }; use once_cell::sync::Lazy; use parking_lot::RwLock; @@ -35,7 +36,8 @@ static DEFAULT_ACCOUNT_HASH: Lazy = const CSPR: u64 = 10u64.pow(9); -// const VM2_TEST_CONTRACT: Bytes = Bytes::from_static(include_bytes!("../vm2-test-contract.wasm")); +// const VM2_TEST_CONTRACT: Bytes = +// Bytes::from_static(include_bytes!("../vqm2-test-contract.wasm")); const VM2_HARNESS: Bytes = Bytes::from_static(include_bytes!("../vm2-harness.wasm")); const VM2_CEP18: Bytes = Bytes::from_static(include_bytes!("../vm2_cep18.wasm")); const VM2_CEP18_CALLER: Bytes = Bytes::from_static(include_bytes!("../vm2-cep18-caller.wasm")); @@ -61,7 +63,7 @@ fn make_address_generator() -> Arc> { fn base_execute_builder() -> ExecuteRequestBuilder { ExecuteRequestBuilder::default() - .with_initiator(DEFAULT_ACCOUNT_HASH.value()) + .with_initiator(*DEFAULT_ACCOUNT_HASH) .with_caller_key(Key::Account(DEFAULT_ACCOUNT_HASH.clone())) .with_callee_key(Key::Account(DEFAULT_ACCOUNT_HASH.clone())) .with_gas_limit(DEFAULT_GAS_LIMIT) @@ -70,9 +72,9 @@ fn base_execute_builder() -> ExecuteRequestBuilder { .with_chain_name(DEFAULT_CHAIN_NAME) } -fn base_store_request_builder() -> InstantiateContractRequestBuilder { - InstantiateContractRequestBuilder::default() - .with_initiator(DEFAULT_ACCOUNT_HASH.value()) +fn base_store_request_builder() -> InstallContractRequestBuilder { + InstallContractRequestBuilder::default() + .with_initiator(*DEFAULT_ACCOUNT_HASH) .with_gas_limit(1_000_000) .with_transaction_hash(TRANSACTION_HASH) .with_chain_name(DEFAULT_CHAIN_NAME) @@ -142,7 +144,7 @@ fn harness() { }; let execute_request = ExecuteRequestBuilder::default() - .with_initiator(DEFAULT_ACCOUNT_HASH.value()) + .with_initiator(*DEFAULT_ACCOUNT_HASH) .with_caller_key(Key::Account(DEFAULT_ACCOUNT_HASH.clone())) .with_callee_key(Key::Account(DEFAULT_ACCOUNT_HASH.clone())) .with_gas_limit(DEFAULT_GAS_LIMIT) @@ -183,8 +185,8 @@ fn cep18() { .map(Bytes::from) .unwrap(); - let create_request = InstantiateContractRequestBuilder::default() - .with_initiator(DEFAULT_ACCOUNT_HASH.value()) + let create_request = InstallContractRequestBuilder::default() + .with_initiator(*DEFAULT_ACCOUNT_HASH) .with_gas_limit(1_000_000) .with_transaction_hash(TRANSACTION_HASH) .with_wasm_bytes(VM2_CEP18.clone()) @@ -208,7 +210,7 @@ fn cep18() { .expect("Should commit"); let execute_request = ExecuteRequestBuilder::default() - .with_initiator(DEFAULT_ACCOUNT_HASH.value()) + .with_initiator(*DEFAULT_ACCOUNT_HASH) .with_caller_key(Key::Account(DEFAULT_ACCOUNT_HASH.clone())) .with_callee_key(Key::Account(DEFAULT_ACCOUNT_HASH.clone())) .with_gas_limit(DEFAULT_GAS_LIMIT) @@ -449,15 +451,15 @@ fn run_create_contract( executor: &mut ExecutorV2, global_state: &mut LmdbGlobalState, pre_state_hash: Digest, - instantiate_contract_request: InstantiateContractRequest, -) -> StoreContractResult { + instantiate_contract_request: InstallContractRequest, +) -> InstallContractResult { let tracking_copy = global_state .tracking_copy(pre_state_hash) .expect("Obtaining root hash succeed") .expect("Root hash exists"); executor - .instantiate_contract(tracking_copy, instantiate_contract_request) + .install_contract(tracking_copy, instantiate_contract_request) .expect("Succeed") } diff --git a/executor/wasm/vm2-cep18-caller.wasm b/executor/wasm/vm2-cep18-caller.wasm new file mode 120000 index 0000000000..c3072153dc --- /dev/null +++ b/executor/wasm/vm2-cep18-caller.wasm @@ -0,0 +1 @@ +../../target/wasm32-unknown-unknown/release/vm2-cep18-caller.wasm \ No newline at end of file diff --git a/executor/wasm/vm2-harness.wasm b/executor/wasm/vm2-harness.wasm new file mode 120000 index 0000000000..c62270cd9c --- /dev/null +++ b/executor/wasm/vm2-harness.wasm @@ -0,0 +1 @@ +../../target/wasm32-unknown-unknown/release/vm2-harness.wasm \ No newline at end of file diff --git a/executor/wasm/vm2_cep18.wasm b/executor/wasm/vm2_cep18.wasm new file mode 120000 index 0000000000..e4cad90a59 --- /dev/null +++ b/executor/wasm/vm2_cep18.wasm @@ -0,0 +1 @@ +../../target/wasm32-unknown-unknown/release/vm2_cep18.wasm \ No newline at end of file diff --git a/executor/wasm/vm2_flipper.wasm b/executor/wasm/vm2_flipper.wasm new file mode 120000 index 0000000000..95232d698f --- /dev/null +++ b/executor/wasm/vm2_flipper.wasm @@ -0,0 +1 @@ +../../target/wasm32-unknown-unknown/release/vm2_flipper.wasm \ No newline at end of file diff --git a/executor/wasm/vm2_trait.wasm b/executor/wasm/vm2_trait.wasm new file mode 120000 index 0000000000..7e7e0c07d5 --- /dev/null +++ b/executor/wasm/vm2_trait.wasm @@ -0,0 +1 @@ +../../target/wasm32-unknown-unknown/release/vm2_trait.wasm \ No newline at end of file diff --git a/executor/wasm/vm2_upgradable.wasm b/executor/wasm/vm2_upgradable.wasm new file mode 120000 index 0000000000..fe0031bc84 --- /dev/null +++ b/executor/wasm/vm2_upgradable.wasm @@ -0,0 +1 @@ +../../target/wasm32-unknown-unknown/release/vm2_upgradable.wasm \ No newline at end of file diff --git a/executor/wasm/vm2_upgradable_v2.wasm b/executor/wasm/vm2_upgradable_v2.wasm new file mode 120000 index 0000000000..17dccc63a8 --- /dev/null +++ b/executor/wasm/vm2_upgradable_v2.wasm @@ -0,0 +1 @@ +../../target/wasm32-unknown-unknown/release/vm2_upgradable_v2.wasm \ No newline at end of file diff --git a/executor/wasmer-backend/Cargo.toml b/executor/wasmer-backend/Cargo.toml new file mode 100644 index 0000000000..fa31efadc0 --- /dev/null +++ b/executor/wasmer-backend/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "casper-executor-wasmer-backend" +version = "0.1.0" +edition = "2021" + +[dependencies] +bytes = "1.6.0" +wasmer = { version = "4.3.1", default-features = false, features = ["singlepass"] } +wasmer-compiler-singlepass = "4.3.1" +wasmer-middlewares = "4.3.1" +wasmer-types = "4.3.1" +casper-executor-wasm-interface = { path = "../wasm-interface" } +casper-executor-wasm-host = { path = "../wasm-host" } +casper-storage = { path = "../../storage" } +casper-sdk-sys = { path = "../../smart_contracts/sdk-sys" } diff --git a/executor/wasmer-backend/src/imports.rs b/executor/wasmer-backend/src/imports.rs new file mode 100644 index 0000000000..4952b7116e --- /dev/null +++ b/executor/wasmer-backend/src/imports.rs @@ -0,0 +1,82 @@ +use casper_executor_wasm_interface::executor::Executor; +use casper_storage::global_state::GlobalStateReader; +use wasmer::{FunctionEnv, FunctionEnvMut, Imports, Store}; + +use casper_sdk_sys::for_each_host_function; + +use crate::WasmerEnv; + +/// A trait for converting a C ABI type declaration to a type that is understandable by wasm32 +/// target (and wasmer, by a consequence). +#[allow(dead_code)] +pub(crate) trait WasmerConvert: Sized { + type Output; +} + +impl WasmerConvert for i32 { + type Output = i32; +} + +impl WasmerConvert for u32 { + type Output = u32; +} +impl WasmerConvert for u64 { + type Output = u64; +} + +impl WasmerConvert for usize { + type Output = u32; +} + +impl WasmerConvert for *const T { + type Output = u32; // Pointers are 32-bit addressable +} + +impl WasmerConvert for *mut T { + type Output = u32; // Pointers are 32-bit addressable +} + +impl WasmerConvert + for extern "C" fn(Arg1, Arg2) -> Ret +{ + type Output = u32; // Function pointers are 32-bit addressable +} + +/// This function will populate imports object with all host functions that are defined. +#[allow(dead_code)] +pub(crate) fn populate_imports( + imports: &mut Imports, + env_name: &str, + store: &mut Store, + function_env: &FunctionEnv>, +) { + macro_rules! visit_host_function { + ( $( $(#[$cfg:meta])? $vis:vis fn $name:ident $(( $($arg:ident: $argty:ty,)* ))? $(-> $ret:ty)?;)+) => { + $( + imports.define(env_name, stringify!($name), wasmer::Function::new_typed_with_env( + store, + &function_env, + | + env: FunctionEnvMut>, + // List all types and statically mapped C types into wasm types + $($($arg: <$argty as $crate::imports::WasmerConvert>::Output,)*)? + | $(-> casper_executor_wasm_interface::VMResult<<$ret as $crate::imports::WasmerConvert>::Output>)? { + let wasmer_caller = $crate::WasmerCaller { env }; + // Dispatch to the actual host function + let _res = casper_executor_wasm_host::host::$name(wasmer_caller, $($($arg,)*)?); + + // TODO: Unify results in the `host` module and create a VMResult out of it + todo!() + } + )); + )* + } + } + for_each_host_function!(visit_host_function); +} + +#[cfg(test)] +mod tests { + #[test] + fn smoke_test() {} +} diff --git a/vm/src/wasm_backend/wasmer.rs b/executor/wasmer-backend/src/lib.rs similarity index 76% rename from vm/src/wasm_backend/wasmer.rs rename to executor/wasmer-backend/src/lib.rs index 314dce3781..ac186b8887 100644 --- a/vm/src/wasm_backend/wasmer.rs +++ b/executor/wasmer-backend/src/lib.rs @@ -1,12 +1,15 @@ +pub(crate) mod imports; mod metering_middleware; -use std::{ - fmt::Debug, - sync::{Arc, Weak}, -}; +use std::sync::{Arc, Weak}; use bytes::Bytes; -use num_traits::ToBytes; +use casper_executor_wasm_host::{context::Context, host}; +use casper_executor_wasm_interface::{ + executor::Executor, u32_from_host_result, Caller, Config, ExportError, GasUsage, + MeteringPoints, TrapCode, VMError, VMResult, WasmInstance, WasmPreparationError, +}; +use casper_storage::global_state::GlobalStateReader; use wasmer::{ AsStoreMut, AsStoreRef, CompilerConfig, Engine, Exports, Function, FunctionEnv, FunctionEnvMut, Imports, Instance, Memory, MemoryView, Module, RuntimeError, Store, StoreMut, Table, @@ -15,70 +18,73 @@ use wasmer::{ use wasmer_compiler_singlepass::Singlepass; use wasmer_middlewares::metering; -use crate::{ - host, storage::GlobalStateReader, u32_from_host_result, Config, Executor, ExportError, - MemoryError, TrapCode, VMResult, WasmEngine, -}; - -use self::metering_middleware::make_wasmer_metering_middleware; +use metering_middleware::make_wasmer_metering_middleware; -use super::{Caller, Context, GasUsage, MeteringPoints, WasmInstance, WasmPreparationError}; -use crate::VMError; - -impl From for TrapCode { - fn from(error: wasmer::MemoryAccessError) -> Self { - match error { - wasmer::MemoryAccessError::HeapOutOfBounds | wasmer::MemoryAccessError::Overflow => { - // As according to Wasm spec section `Memory Instructions` any access to memory that - // is out of bounds of the memory's current size is a trap. Reference: https://webassembly.github.io/spec/core/syntax/instructions.html#memory-instructions - TrapCode::MemoryOutOfBounds - } - wasmer::MemoryAccessError::NonUtf8String => { - // This can happen only when using wasmer's utf8 reading routines which we don't - // need. - unreachable!("NonUtf8String") - } - _ => { - // All errors are handled and converted to a trap code, but we have to add this as - // wasmer's errors are #[non_exhaustive] - unreachable!("Unexpected error: {:?}", error) - } +fn from_wasmer_memory_access_error(error: wasmer::MemoryAccessError) -> VMError { + let trap_code = match error { + wasmer::MemoryAccessError::HeapOutOfBounds | wasmer::MemoryAccessError::Overflow => { + // As according to Wasm spec section `Memory Instructions` any access to memory that + // is out of bounds of the memory's current size is a trap. Reference: https://webassembly.github.io/spec/core/syntax/instructions.html#memory-instructions + TrapCode::MemoryOutOfBounds } - } + wasmer::MemoryAccessError::NonUtf8String => { + // This can happen only when using wasmer's utf8 reading routines which we don't + // need. + unreachable!("NonUtf8String") + } + _ => { + // All errors are handled and converted to a trap code, but we have to add this as + // wasmer's errors are #[non_exhaustive] + unreachable!("Unexpected error: {:?}", error) + } + }; + VMError::Trap(trap_code) } -impl From for TrapCode { - fn from(value: wasmer_types::TrapCode) -> Self { - match value { - wasmer_types::TrapCode::StackOverflow => TrapCode::StackOverflow, - wasmer_types::TrapCode::HeapAccessOutOfBounds => TrapCode::MemoryOutOfBounds, - wasmer_types::TrapCode::HeapMisaligned => { - unreachable!("Atomic operations are not supported") - } - wasmer_types::TrapCode::TableAccessOutOfBounds => TrapCode::TableAccessOutOfBounds, - wasmer_types::TrapCode::IndirectCallToNull => TrapCode::IndirectCallToNull, - wasmer_types::TrapCode::BadSignature => TrapCode::BadSignature, - wasmer_types::TrapCode::IntegerOverflow => TrapCode::IntegerOverflow, - wasmer_types::TrapCode::IntegerDivisionByZero => TrapCode::IntegerDivisionByZero, - wasmer_types::TrapCode::BadConversionToInteger => TrapCode::BadConversionToInteger, - wasmer_types::TrapCode::UnreachableCodeReached => TrapCode::UnreachableCodeReached, - wasmer_types::TrapCode::UnalignedAtomic => { - todo!("Atomic memory extension is not supported") - } +fn from_wasmer_trap_code(value: wasmer_types::TrapCode) -> TrapCode { + match value { + wasmer_types::TrapCode::StackOverflow => TrapCode::StackOverflow, + wasmer_types::TrapCode::HeapAccessOutOfBounds => TrapCode::MemoryOutOfBounds, + wasmer_types::TrapCode::HeapMisaligned => { + unreachable!("Atomic operations are not supported") + } + wasmer_types::TrapCode::TableAccessOutOfBounds => TrapCode::TableAccessOutOfBounds, + wasmer_types::TrapCode::IndirectCallToNull => TrapCode::IndirectCallToNull, + wasmer_types::TrapCode::BadSignature => TrapCode::BadSignature, + wasmer_types::TrapCode::IntegerOverflow => TrapCode::IntegerOverflow, + wasmer_types::TrapCode::IntegerDivisionByZero => TrapCode::IntegerDivisionByZero, + wasmer_types::TrapCode::BadConversionToInteger => TrapCode::BadConversionToInteger, + wasmer_types::TrapCode::UnreachableCodeReached => TrapCode::UnreachableCodeReached, + wasmer_types::TrapCode::UnalignedAtomic => { + todo!("Atomic memory extension is not supported") } } } -impl From for ExportError { - fn from(error: wasmer::ExportError) -> Self { - match error { - wasmer::ExportError::IncompatibleType => ExportError::IncompatibleType, - wasmer::ExportError::Missing(export_name) => ExportError::Missing(export_name), - } - } +fn from_wasmer_export_error(error: wasmer::ExportError) -> VMError { + let export_error = match error { + wasmer::ExportError::IncompatibleType => ExportError::IncompatibleType, + wasmer::ExportError::Missing(export_name) => ExportError::Missing(export_name), + }; + VMError::Export(export_error) } -pub(crate) struct WasmerEngine(()); +pub struct WasmerEngine(()); + +impl WasmerEngine { + pub fn new() -> Self { + Self(()) + } + + pub fn prepare, S: GlobalStateReader + 'static, E: Executor + 'static>( + &self, + wasm_bytes: T, + context: Context, + config: Config, + ) -> Result>, WasmPreparationError> { + WasmerInstance::from_wasm_bytes(wasm_bytes, context, config) + } +} struct WasmerEnv { config: Config, @@ -126,14 +132,13 @@ impl<'a, S: GlobalStateReader + 'static, E: Executor + 'static> WasmerCaller<'a, } } -impl<'a, S: GlobalStateReader + 'static, E: Executor + 'static> Caller - for WasmerCaller<'a, S, E> -{ +impl<'a, S: GlobalStateReader + 'static, E: Executor + 'static> Caller for WasmerCaller<'a, S, E> { + type Context = Context; + fn memory_write(&self, offset: u32, data: &[u8]) -> Result<(), VMError> { Ok(self .with_memory(|mem| mem.write(offset.into(), data)) - .map_err(TrapCode::from) - .map_err(VMError::Trap)?) + .map_err(from_wasmer_memory_access_error)?) } fn context(&self) -> &Context { @@ -146,8 +151,7 @@ impl<'a, S: GlobalStateReader + 'static, E: Executor + 'static> Caller fn memory_read_into(&self, offset: u32, output: &mut [u8]) -> Result<(), VMError> { Ok(self .with_memory(|mem| mem.read(offset.into(), output)) - .map_err(TrapCode::from) - .map_err(VMError::Trap)?) + .map_err(from_wasmer_memory_access_error)?) } fn alloc(&mut self, idx: u32, size: usize, ctx: u32) -> VMResult { @@ -243,7 +247,7 @@ fn handle_wasmer_runtime_error(error: RuntimeError) -> VMError { // NOTE: Can this be other variant than VMError and trap? This may indicate a bug in // our code. let wasmer_trap_code = wasmer_runtime_error.to_trap().expect("Trap code"); - VMError::Trap(wasmer_trap_code.into()) + VMError::Trap(from_wasmer_trap_code(wasmer_trap_code)) } } } @@ -258,8 +262,7 @@ where .instance .exports .get_typed_function(&self.store, name) - .map_err(ExportError::from) - .map_err(VMError::Export)?; + .map_err(from_wasmer_export_error)?; let () = exported_call_func .call(&mut self.store.as_store_mut()) @@ -315,7 +318,7 @@ where // let mut store = Engine let engine = { let mut singlepass_compiler = Singlepass::new(); - let metering = make_wasmer_metering_middleware(config.gas_limit); + let metering = make_wasmer_metering_middleware(config.gas_limit()); singlepass_compiler.push_middleware(metering); // singlepass_compiler.push_middleware(middleware) singlepass_compiler @@ -471,31 +474,20 @@ where input_ptr: u32, input_len: u32, result_ptr: u32| { - let value = { - let mem = &env.data().exported_runtime().memory; - let binding = env.as_store_ref(); - let view = mem.view(&binding); - value - .read(&view) - .map_err(|error| TrapCode::from(error)) - .map_err(|error| VMError::Trap(error))? - }; - let wasmer_caller = WasmerCaller { env }; match host::casper_create( wasmer_caller, code_ptr, code_size, - value, + value.offset(), entry_point_ptr, entry_point_len, input_ptr, input_len, result_ptr, ) { - Ok(Ok(())) => Ok(0), - Ok(Err(call_error)) => Ok(call_error.into_u32()), + Ok(host_result) => Ok(u32_from_host_result(host_result)), Err(error) => Err(error), } }, @@ -518,22 +510,12 @@ where input_len: u32, cb_alloc: u32, cb_ctx: u32| { - let value = { - let mem = &env.data().exported_runtime().memory; - let binding = env.as_store_ref(); - let view = mem.view(&binding); - value - .read(&view) - .map_err(|error| TrapCode::from(error)) - .map_err(|error| VMError::Trap(error))? - }; - let wasmer_caller = WasmerCaller { env }; match host::casper_call( wasmer_caller, address_ptr, address_len, - value, + value.offset(), entry_point_ptr, entry_point_len, input_ptr, @@ -548,29 +530,6 @@ where ), ); - imports.define( - "env", - "casper_env_read", - Function::new_typed_with_env( - &mut store, - &function_env, - |env: FunctionEnvMut>, - env_path, - env_path_size, - cb_alloc: u32, - cb_ctx: u32| { - let wasmer_caller = WasmerCaller { env }; - host::casper_env_read( - wasmer_caller, - env_path, - env_path_size, - cb_alloc, - cb_ctx, - ) - }, - ), - ); - imports.define( "env", "casper_env_caller", @@ -645,25 +604,14 @@ where address_ptr, address_len, amount: WasmPtr| { - let amount = { - let mem = &env.data().exported_runtime().memory; - let binding = env.as_store_ref(); - let view = mem.view(&binding); - amount - .read(&view) - .map_err(|error| TrapCode::from(error)) - .map_err(|error| VMError::Trap(error))? - }; - let wasmer_caller = WasmerCaller { env }; host::casper_transfer( wasmer_caller, entity_kind, address_ptr, address_len, - amount, + amount.offset(), ) - .map(u32_from_host_result) }, ), ); @@ -693,17 +641,9 @@ where input_ptr, input_len, ) { - Ok(Ok(())) => Ok(0), - Ok(Err(call_error)) => Ok(call_error.into_u32()), + Ok(host_result) => Ok(u32_from_host_result(host_result)), Err(error) => Err(error), } - // todo!() - // { - // Ok(Ok(())) => Ok(0), - // Ok(Err(call_error)) => Ok(call_error.into_u32()), - // Err(error) => Err(error), - // } - // todo!() }, ), ); @@ -762,48 +702,22 @@ where } } -impl WasmInstance for WasmerInstance +impl WasmInstance for WasmerInstance where S: GlobalStateReader + 'static, E: Executor + 'static, { + type Context = Context; fn call_export(&mut self, name: &str) -> (Result<(), VMError>, GasUsage) { let vm_result = self.call_export(name); let remaining_points = metering::get_remaining_points(&mut self.store, &self.instance); match remaining_points { metering::MeteringPoints::Remaining(remaining_points) => { - let gas_usage = GasUsage { - gas_limit: self.config.gas_limit, - remaining_points, - }; - (vm_result, gas_usage) - } - metering::MeteringPoints::Exhausted => { - let gas_usage = GasUsage { - gas_limit: self.config.gas_limit, - remaining_points: 0, - }; - (Err(VMError::OutOfGas), gas_usage) - } - } - } - - fn call_function(&mut self, function_index: u32) -> (Result<(), VMError>, GasUsage) { - let vm_result = self.call_function(function_index); - let remaining_points = metering::get_remaining_points(&mut self.store, &self.instance); - match remaining_points { - metering::MeteringPoints::Remaining(remaining_points) => { - let gas_usage = GasUsage { - gas_limit: self.config.gas_limit, - remaining_points, - }; + let gas_usage = GasUsage::new(self.config.gas_limit(), remaining_points); (vm_result, gas_usage) } metering::MeteringPoints::Exhausted => { - let gas_usage = GasUsage { - gas_limit: self.config.gas_limit, - remaining_points: 0, - }; + let gas_usage = GasUsage::new(self.config.gas_limit(), 0); (Err(VMError::OutOfGas), gas_usage) } } @@ -829,6 +743,7 @@ where transaction_hash: data.context.transaction_hash, address_generator: Arc::clone(&data.context.address_generator), chain_name: data.context.chain_name.clone(), + input: data.context.input.clone(), } } } diff --git a/vm/src/wasm_backend/wasmer/metering_middleware.rs b/executor/wasmer-backend/src/metering_middleware.rs similarity index 100% rename from vm/src/wasm_backend/wasmer/metering_middleware.rs rename to executor/wasmer-backend/src/metering_middleware.rs diff --git a/node/Cargo.toml b/node/Cargo.toml index 36633d68b8..a9c27c54fb 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -93,7 +93,9 @@ uuid = { version = "0.8.1", features = ["serde", "v4"] } warp = { version = "0.3.6", features = ["compression"] } wheelbuf = "0.2.0" -casper-vm = { path = "../vm" } +casper-executor-wasm = { path = "../executor/wasm" } +casper-executor-wasm-interface = { path = "../executor/wasm-interface" } + [build-dependencies] vergen = { version = "8.2.1", default-features = false, features = ["git", "gitoxide"] } diff --git a/node/src/components/contract_runtime.rs b/node/src/components/contract_runtime.rs index 54413f7012..83e8486d9c 100644 --- a/node/src/components/contract_runtime.rs +++ b/node/src/components/contract_runtime.rs @@ -21,7 +21,7 @@ use std::{ time::Instant, }; -use casper_vm::executor::v2::{ExecutorConfigBuilder, ExecutorKind, ExecutorV2}; +use casper_executor_wasm::{ExecutorConfigBuilder, ExecutorKind, ExecutorV2}; use datasize::DataSize; use lmdb::DatabaseFlags; use prometheus::Registry; diff --git a/node/src/components/contract_runtime/operations.rs b/node/src/components/contract_runtime/operations.rs index 0f1f5fc430..aca76a7f3d 100644 --- a/node/src/components/contract_runtime/operations.rs +++ b/node/src/components/contract_runtime/operations.rs @@ -1,13 +1,11 @@ use std::{collections::BTreeMap, convert::TryInto, sync::Arc, time::Instant}; -use casper_vm::executor::{ - v2::ExecutorV2, ExecuteRequestBuilder, ExecutionKind, Executor, - InstantiateContractRequestBuilder, -}; +use casper_executor_wasm::{install::InstallContractRequestBuilder, ExecutorV2}; use itertools::Itertools; use tracing::{debug, error, info, trace, warn}; use casper_execution_engine::engine_state::{ExecutionEngineV1, WasmV1Request, WasmV1Result}; +use casper_executor_wasm_interface::executor::{ExecuteRequestBuilder, ExecutionKind, Executor}; use casper_storage::{ block_store::types::ApprovalsHashes, data_access_layer::{ @@ -400,7 +398,7 @@ pub fn execute_finalized_block( match transaction_v1.body().entry_point() { TransactionEntryPoint::Instantiate(_) | TransactionEntryPoint::DefaultInstantiate => { - let mut builder = InstantiateContractRequestBuilder::default(); + let mut builder = InstallContractRequestBuilder::default(); let module_bytes = match transaction_v1.body().target() { TransactionTarget::Session { @@ -436,7 +434,7 @@ pub fn execute_finalized_block( } let request = builder - .with_initiator(initiator_addr.account_hash().value()) + .with_initiator(initiator_addr.account_hash()) .with_gas_limit(gas_limit) .with_transaction_hash(transaction_hash) .with_wasm_bytes(module_bytes.clone().take_inner().into()) @@ -451,7 +449,7 @@ pub fn execute_finalized_block( .expect("should have tracking copy") .expect("should have state root hash"); - match execution_engine_v2.instantiate_contract(tracking_copy, request) { + match execution_engine_v2.install_contract(tracking_copy, request) { Ok(result) => { let effects = result.effects().clone(); let pre_state_root_hash = state_root_hash; @@ -485,14 +483,14 @@ pub fn execute_finalized_block( let mut builder = ExecuteRequestBuilder::default(); let initiator_account_hash = &initiator_addr.account_hash(); - let initiator_addr_bytes = initiator_account_hash.value(); + let initiator_key = Key::Account(*initiator_account_hash); builder = builder .with_address_generator(address_generator) .with_gas_limit(gas_limit) .with_transaction_hash(transaction_hash) - .with_initiator(initiator_addr_bytes) + .with_initiator(*initiator_account_hash) .with_caller_key(initiator_key) // TODO: Callee is unnecessary as it can be derived from the // execution target inside the executor diff --git a/node/src/components/contract_runtime/utils.rs b/node/src/components/contract_runtime/utils.rs index aaf195eebe..0bef29cc2f 100644 --- a/node/src/components/contract_runtime/utils.rs +++ b/node/src/components/contract_runtime/utils.rs @@ -1,4 +1,4 @@ -use casper_vm::executor::v2::ExecutorV2; +use casper_executor_wasm::ExecutorV2; use num_rational::Ratio; use once_cell::sync::Lazy; use std::{ diff --git a/smart_contracts/contracts/vm2/vm2-cep18-caller/Cargo.toml b/smart_contracts/contracts/vm2/vm2-cep18-caller/Cargo.toml index 4ae5d23eb6..6c87d95cde 100644 --- a/smart_contracts/contracts/vm2/vm2-cep18-caller/Cargo.toml +++ b/smart_contracts/contracts/vm2/vm2-cep18-caller/Cargo.toml @@ -10,4 +10,3 @@ casper-macros = { path = "../../../macros" } casper-sdk = { path = "../../../sdk" } vm2-cep18 = { path = "../vm2-cep18" } borsh = { version = "1.2.0", features = ["derive"] } -vm-common = { path = "../../../../vm-common" } diff --git a/smart_contracts/contracts/vm2/vm2-cep18/Cargo.toml b/smart_contracts/contracts/vm2/vm2-cep18/Cargo.toml index ba30611845..14d79b6955 100644 --- a/smart_contracts/contracts/vm2/vm2-cep18/Cargo.toml +++ b/smart_contracts/contracts/vm2/vm2-cep18/Cargo.toml @@ -11,7 +11,6 @@ crate-type = ["cdylib", "rlib"] [dependencies] casper-macros = { path = "../../../macros" } casper-sdk = { path = "../../../sdk" } -vm-common = { path = "../../../../vm-common" } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] serde_json = "1" diff --git a/smart_contracts/contracts/vm2/vm2-cep78/Cargo.toml b/smart_contracts/contracts/vm2/vm2-cep78/Cargo.toml index 8fdbe69f4e..3aeefbe1cf 100644 --- a/smart_contracts/contracts/vm2/vm2-cep78/Cargo.toml +++ b/smart_contracts/contracts/vm2/vm2-cep78/Cargo.toml @@ -11,7 +11,6 @@ crate-type = ["lib", "cdylib"] casper-macros = { path = "../../../macros" } casper-sdk = { path = "../../../sdk" } borsh = { version = "1.2.0", features = ["derive", "unstable__schema"] } -vm-common = { path = "../../../../vm-common" } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] serde_json = "1" diff --git a/smart_contracts/contracts/vm2/vm2-harness/Cargo.toml b/smart_contracts/contracts/vm2/vm2-harness/Cargo.toml index 0e0c81b720..0337d7f6b1 100644 --- a/smart_contracts/contracts/vm2/vm2-harness/Cargo.toml +++ b/smart_contracts/contracts/vm2/vm2-harness/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" [dependencies] casper-macros = { path = "../../../macros" } casper-sdk = { path = "../../../sdk" } -vm-common = {"path" = "../../../../vm-common"} + impls = "1" thiserror = "1" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] diff --git a/smart_contracts/contracts/vm2/vm2-test-contract/Cargo.toml b/smart_contracts/contracts/vm2/vm2-test-contract/Cargo.toml index 8e0a9438bd..0cd08f24fd 100644 --- a/smart_contracts/contracts/vm2/vm2-test-contract/Cargo.toml +++ b/smart_contracts/contracts/vm2/vm2-test-contract/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" [dependencies] casper-macros = { path = "../../../macros" } casper-sdk = { path = "../../../sdk" } -vm-common = { path = "../../../../vm-common" } + borsh = "1.2.0" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] diff --git a/smart_contracts/macros/Cargo.toml b/smart_contracts/macros/Cargo.toml index 4448530f56..72e5561bd6 100644 --- a/smart_contracts/macros/Cargo.toml +++ b/smart_contracts/macros/Cargo.toml @@ -11,9 +11,8 @@ proc-macro = true [dependencies] syn = { version = "2", features = ["full", "extra-traits"] } quote = "1" -# casper-sdk = { path = "../sdk" } +casper-sdk = { path = "../sdk" } casper-sdk-sys = { path = "../sdk-sys" } -vm-common = { path = "../../vm-common" } paste = "1" darling = "0.20.3" proc-macro2 = "1.0" diff --git a/smart_contracts/macros/src/lib.rs b/smart_contracts/macros/src/lib.rs index 13ee0dc36f..28bd98570a 100644 --- a/smart_contracts/macros/src/lib.rs +++ b/smart_contracts/macros/src/lib.rs @@ -10,8 +10,8 @@ use syn::{ parse_macro_input, Data, DeriveInput, Fields, ItemEnum, ItemFn, ItemImpl, ItemStruct, ItemTrait, ItemUnion, LitStr, Type, }; -use vm_common::{flags::EntryPointFlags, selector::Selector}; +use casper_sdk::casper_executor_wasm_common::{flags::EntryPointFlags, selector::Selector}; const CASPER_RESERVED_FALLBACK_EXPORT: &str = "__casper_fallback"; #[derive(Debug, FromAttributes)] @@ -567,7 +567,7 @@ fn generate_impl_for_contract( quote! { let _ret: &Result<_, _> = &_ret; if _ret.is_err() { - flags |= casper_sdk::vm_common::flags::ReturnFlags::REVERT; + flags |= casper_sdk::casper_executor_wasm_common::flags::ReturnFlags::REVERT; } } @@ -627,7 +627,7 @@ fn generate_impl_for_contract( #(#prelude;)* - let mut flags = casper_sdk::vm_common::flags::ReturnFlags::empty(); + let mut flags = casper_sdk::casper_executor_wasm_common::flags::ReturnFlags::empty(); #handle_call; @@ -814,7 +814,7 @@ fn generate_impl_for_contract( selector: Some(#schema_selector), arguments: vec![ #(#args,)* ], result: #result, - flags: casper_sdk::vm_common::flags::EntryPointFlags::from_bits(#bits).unwrap(), + flags: casper_sdk::casper_executor_wasm_common::flags::EntryPointFlags::from_bits(#bits).unwrap(), } } }); @@ -1138,8 +1138,8 @@ fn casper_trait_definition( // arguments: vec![ #(#args,)* ], // result: #result, // flags: - // casper_sdk::vm_common::flags::EntryPointFlags::from_bits(#flags).unwrap(), - // } + // casper_sdk::casper_executor_wasm_common::flags::EntryPointFlags::from_bits(# + // flags).unwrap(), } // }); let handle_dispatch = match func.sig.inputs.first() { @@ -1156,7 +1156,7 @@ fn casper_trait_definition( #(#args_attrs,)* } - let mut flags = casper_sdk::vm_common::flags::ReturnFlags::empty(); + let mut flags = casper_sdk::casper_executor_wasm_common::flags::ReturnFlags::empty(); let mut instance: T = casper_sdk::host::read_state().unwrap(); let input = casper_sdk::host::casper_copy_input(); let args: Arguments = casper_sdk::serializers::borsh::from_slice(&input).unwrap(); @@ -1267,7 +1267,7 @@ fn casper_trait_definition( #vis struct #ref_struct; impl #ref_struct { - pub const SELECTOR: casper_sdk::vm_common::selector::Selector = casper_sdk::vm_common::selector::Selector::new(#combined_selectors); + pub const SELECTOR: casper_sdk::casper_executor_wasm_common::selector::Selector = casper_sdk::casper_executor_wasm_common::selector::Selector::new(#combined_selectors); // #[doc(hidden)] // #vis const fn __casper_new_trait_dispatch_table() -> [casper_sdk::sys::EntryPoint; #manifest_data_len] { @@ -1774,7 +1774,7 @@ pub fn selector(input: TokenStream) -> TokenStream { let selector_value = utils::compute_selector_bytes(bytes); TokenStream::from(quote! { - casper_sdk::vm_common::selector::Selector::new(#selector_value) + casper_sdk::casper_executor_wasm_common::selector::Selector::new(#selector_value) }) .into() } diff --git a/smart_contracts/sdk-codegen/Cargo.toml b/smart_contracts/sdk-codegen/Cargo.toml index 33ff7e921a..43196e5ee5 100644 --- a/smart_contracts/sdk-codegen/Cargo.toml +++ b/smart_contracts/sdk-codegen/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" [dependencies] casper-sdk = {path = "../sdk" } -vm-common = { path = "../../vm-common" } codegen = "0.2.0" serde = { version = "1", features = ["derive"] } serde_json = { version = "1", features = ["preserve_order"] } diff --git a/smart_contracts/sdk-codegen/src/lib.rs b/smart_contracts/sdk-codegen/src/lib.rs index 8252a5333d..ab6acdcaef 100644 --- a/smart_contracts/sdk-codegen/src/lib.rs +++ b/smart_contracts/sdk-codegen/src/lib.rs @@ -2,6 +2,7 @@ pub mod support; use casper_sdk::{ abi::{Declaration, Definition, Primitive}, + casper_executor_wasm_common::flags::EntryPointFlags, schema::{Schema, SchemaType}, }; use codegen::{Field, Scope, Type}; @@ -12,7 +13,6 @@ use std::{ iter, str::FromStr, }; -use vm_common::flags::EntryPointFlags; const DEFAULT_DERIVED_TRAITS: &[&str] = &[ "Clone", diff --git a/smart_contracts/sdk-sys/src/for_each_host_function.rs b/smart_contracts/sdk-sys/src/for_each_host_function.rs index 863ce1f75f..c3aa55e0e7 100644 --- a/smart_contracts/sdk-sys/src/for_each_host_function.rs +++ b/smart_contracts/sdk-sys/src/for_each_host_function.rs @@ -53,25 +53,6 @@ macro_rules! for_each_host_function { input_ptr: *const u8, input_size: usize, ) -> u32; - - #[doc = r"Obtain data from the blockchain environemnt of current wasm invocation. - -Example paths: - -* `env_read([CASPER_CALLER], 1, nullptr, &caller_addr)` -> read caller's address into - `caller_addr` memory. -* `env_read([CASPER_CHAIN, BLOCK_HASH, 0], 3, nullptr, &block_hash)` -> read hash of the - current block into `block_hash` memory. -* `env_read([CASPER_CHAIN, BLOCK_HASH, 5], 3, nullptr, &block_hash)` -> read hash of the 5th - block from the current one into `block_hash` memory. -* `env_read([CASPER_AUTHORIZED_KEYS], 1, nullptr, &authorized_keys)` -> read list of - authorized keys into `authorized_keys` memory."] - pub fn casper_env_read( - env_path: *const u64, - env_path_size: usize, - alloc: Option *mut u8>, // For capturing output data - alloc_ctx: *const core::ffi::c_void, - ) -> *mut u8; pub fn casper_env_caller(dest: *mut u8, dest_len: usize, entity_kind: *mut u32,) -> *const u8; pub fn casper_env_value(dest: *mut core::ffi::c_void,); #[doc = r"Get balance of an entity by its address."] diff --git a/smart_contracts/sdk/Cargo.toml b/smart_contracts/sdk/Cargo.toml index 08e2c14515..915a68c932 100644 --- a/smart_contracts/sdk/Cargo.toml +++ b/smart_contracts/sdk/Cargo.toml @@ -9,11 +9,11 @@ authors = ["MichaƂ Papierski "] [dependencies] borsh = { version = "1.2.0", features = ["derive"] } bytes = "1" -vm-common = {path="../../vm-common"} bitflags = "2.4.1" const-fnv1a-hash = "1.1.0" impl-trait-for-tuples = "0.2.2" casper-sdk-sys = {path = "../sdk-sys" } +casper-executor-wasm-common = { path = "../../executor/wasm-common" } # casper-macros = {path = "../macros" } once_cell = "1" diff --git a/smart_contracts/sdk/src/collections/map.rs b/smart_contracts/sdk/src/collections/map.rs index ae78b2a75f..100485cc6b 100644 --- a/smart_contracts/sdk/src/collections/map.rs +++ b/smart_contracts/sdk/src/collections/map.rs @@ -3,8 +3,8 @@ use crate::{ host::{self, read_vec}, serializers::borsh::{BorshDeserialize, BorshSerialize}, }; +use casper_executor_wasm_common::keyspace::Keyspace; use const_fnv1a_hash::fnv1a_hash_str_64; -use vm_common::keyspace::Keyspace; use crate::prelude::marker::PhantomData; diff --git a/smart_contracts/sdk/src/collections/set.rs b/smart_contracts/sdk/src/collections/set.rs index d42d9c01ea..dba5e3243b 100644 --- a/smart_contracts/sdk/src/collections/set.rs +++ b/smart_contracts/sdk/src/collections/set.rs @@ -1,7 +1,7 @@ use crate::prelude::marker::PhantomData; use crate::{host, serializers::borsh::BorshSerialize}; -use vm_common::keyspace::Keyspace; +use casper_executor_wasm_common::keyspace::Keyspace; use super::lookup_key::{Identity, LookupKey, LookupKeyOwned}; diff --git a/smart_contracts/sdk/src/collections/vector.rs b/smart_contracts/sdk/src/collections/vector.rs index c37e5e1f12..3f5783ab72 100644 --- a/smart_contracts/sdk/src/collections/vector.rs +++ b/smart_contracts/sdk/src/collections/vector.rs @@ -8,8 +8,8 @@ use crate::{ prelude::{cmp::Ordering, marker::PhantomData}, serializers::borsh::{BorshDeserialize, BorshSerialize}, }; +use casper_executor_wasm_common::keyspace::Keyspace; use const_fnv1a_hash::fnv1a_hash_str_64; -use vm_common::keyspace::Keyspace; #[derive(BorshSerialize, BorshDeserialize, Debug, Clone)] #[borsh(crate = "crate::serializers::borsh")] diff --git a/smart_contracts/sdk/src/host.rs b/smart_contracts/sdk/src/host.rs index 4c7edc8a6d..98cb473437 100644 --- a/smart_contracts/sdk/src/host.rs +++ b/smart_contracts/sdk/src/host.rs @@ -10,11 +10,11 @@ use crate::{ serializers::borsh::{BorshDeserialize, BorshSerialize}, }; -use casper_sdk_sys::casper_env_caller; -use vm_common::{ +use casper_executor_wasm_common::{ flags::ReturnFlags, keyspace::{Keyspace, KeyspaceTag}, }; +use casper_sdk_sys::casper_env_caller; use crate::{ abi::{CasperABI, EnumVariant}, @@ -38,35 +38,6 @@ pub enum Alloc Option>> { Static(ptr::NonNull), } -pub fn casper_env_read Option>>( - env_path: &[u64], - func: F, -) -> Option> { - let ret = unsafe { - casper_sdk_sys::casper_env_read( - env_path.as_ptr(), - env_path.len(), - Some(alloc_callback::), - &func as *const _ as *mut c_void, - ) - }; - - NonNull::::new(ret) -} - -pub fn casper_env_read_into(env_path: &[u64], dest: &mut [u8]) -> Option> { - let ret = unsafe { - casper_sdk_sys::casper_env_read( - env_path.as_ptr(), - env_path.len(), - None, - dest.as_mut_ptr() as *mut c_void, - ) - }; - - NonNull::::new(ret) -} - extern "C" fn alloc_callback Option>>( len: usize, ctx: *mut c_void, diff --git a/smart_contracts/sdk/src/host/native.rs b/smart_contracts/sdk/src/host/native.rs index adbdf6b0dc..dead38518b 100644 --- a/smart_contracts/sdk/src/host/native.rs +++ b/smart_contracts/sdk/src/host/native.rs @@ -1,4 +1,5 @@ use bytes::Bytes; +use casper_executor_wasm_common::flags::{EntryPointFlags, ReturnFlags}; use core::slice; use std::{ cell::RefCell, @@ -7,7 +8,6 @@ use std::{ ptr::{self, NonNull}, sync::{Arc, RwLock}, }; -use vm_common::flags::{EntryPointFlags, ReturnFlags}; use crate::{linkme::distributed_slice, types::Address}; diff --git a/smart_contracts/sdk/src/lib.rs b/smart_contracts/sdk/src/lib.rs index 94f334a1e0..357e52029a 100644 --- a/smart_contracts/sdk/src/lib.rs +++ b/smart_contracts/sdk/src/lib.rs @@ -23,10 +23,10 @@ pub mod types; use crate::prelude::{marker::PhantomData, ptr::NonNull}; use crate::serializers::borsh::{BorshDeserialize, BorshSerialize}; +pub use casper_executor_wasm_common; pub use casper_sdk_sys as sys; use host::{CallResult, Entity}; use types::{Address, CallError}; -pub use vm_common; cfg_if::cfg_if! { if #[cfg(feature = "std")] { @@ -113,15 +113,18 @@ macro_rules! log { #[macro_export] macro_rules! revert { () => {{ - casper_sdk::host::casper_return(vm_common::flags::ReturnFlags::REVERT, None); + $crate::host::casper_return( + $crate::casper_executor_wasm_common::flags::ReturnFlags::REVERT, + None, + ); unreachable!() }}; ($arg:expr) => {{ let value = $arg; let data = - casper_sdk::serializers::borsh::to_vec(&value).expect("Revert value should serialize"); - casper_sdk::host::casper_return( - vm_common::flags::ReturnFlags::REVERT, + $crate::serializers::borsh::to_vec(&value).expect("Revert value should serialize"); + $crate::host::casper_return( + $crate::casper_executor_wasm_common::flags::ReturnFlags::REVERT, Some(data.as_slice()), ); #[allow(unreachable_code)] @@ -143,7 +146,7 @@ where self.unwrap_or_else(|error| { let error_data = borsh::to_vec(&error).expect("Revert value should serialize"); host::casper_return( - vm_common::flags::ReturnFlags::REVERT, + casper_executor_wasm_common::flags::ReturnFlags::REVERT, Some(error_data.as_slice()), ); unreachable!("Support for unwrap_or_revert") diff --git a/smart_contracts/sdk/src/schema.rs b/smart_contracts/sdk/src/schema.rs index 2fca378859..adbf4392e4 100644 --- a/smart_contracts/sdk/src/schema.rs +++ b/smart_contracts/sdk/src/schema.rs @@ -5,8 +5,8 @@ pub trait CasperSchema { use std::fmt::LowerHex; use bitflags::Flags; +use casper_executor_wasm_common::flags::EntryPointFlags; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use vm_common::flags::EntryPointFlags; use crate::abi::{self, Declaration, Definitions}; diff --git a/storage/src/global_state.rs b/storage/src/global_state.rs index 7e1bd84c7a..dee8a4f2b1 100644 --- a/storage/src/global_state.rs +++ b/storage/src/global_state.rs @@ -18,3 +18,13 @@ pub(crate) const DEFAULT_MAX_DB_SIZE: usize = 52_428_800; // 50 MiB pub(crate) const DEFAULT_MAX_READERS: u32 = 512; pub(crate) const DEFAULT_MAX_QUERY_DEPTH: u64 = 5; + +pub trait GlobalStateReader: + state::StateReader +{ +} + +impl> + GlobalStateReader for R +{ +} diff --git a/vm-common/src/lib.rs b/vm-common/src/lib.rs deleted file mode 100644 index cfcf04585c..0000000000 --- a/vm-common/src/lib.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod flags; -pub mod keyspace; -pub mod leb128; -pub mod manifest; -pub mod selector; diff --git a/vm/Cargo.toml b/vm/Cargo.toml deleted file mode 100644 index fb3fb99d07..0000000000 --- a/vm/Cargo.toml +++ /dev/null @@ -1,45 +0,0 @@ -[package] -name = "casper-vm" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -bytes = "1.4.0" -casper-types = { path = "../types" } -wasmer = { version = "4.3.1", default-features = false, features = ["singlepass"] } -wasmer-compiler-singlepass = "4.3.1" -wasmer-middlewares = "4.3.1" -wasmer-types = "4.3.1" - -thiserror = "1.0.44" -criterion = "0.5.1" -borsh = {version = "1.2.0", features = ["derive"] } -borsh-derive = "1.2.0" - -blake2 = "0.10.6" - -digest = "0.10.7" -safe-transmute = "0.11.2" - -num-traits = "0.2.18" -num-derive = "0.4.2" - -tracing = "0.1.40" - -vm-common = { path = "../vm-common"} -casper-storage = { path = "../storage" } - -either = "1.10" - -parking_lot = "0.12.1" - -[dev-dependencies] -tempfile = "3.10.1" -once_cell = "1.19.0" -rand = "0.8.4" - -[[bench]] -name = "vm_call" -harness = false diff --git a/vm/benches/vm_call.rs b/vm/benches/vm_call.rs deleted file mode 100644 index 677fb55aa4..0000000000 --- a/vm/benches/vm_call.rs +++ /dev/null @@ -1,87 +0,0 @@ -use bytes::Bytes; -use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use vm::{ - storage::{self, Storage}, - wasm_backend::{Context, WasmInstance}, - ExecuteRequest, WasmEngine, -}; - -// use super::*; -const TEST_CONTRACT_WASM: &[u8] = include_bytes!("../test-contract.wasm"); - -// fn fibonacci(n: u64) -> u64 { -// match n { -// 0 => 1, -// 1 => 1, -// n => fibonacci(n-1) + fibonacci(n-2), -// } -// } - -fn bench_call() { - // let mut vm = VM::new(); - // let execute_request = ExecuteRequest { - // wasm_bytes: Bytes::from_static(TEST_CONTRACT_WASM), - // }; - - // let storage = MockStorage::default(); - - // let mock_context = Context { storage }; - - // let retrieved_context = { - // let mut instance = vm - // .prepare(execute_request, mock_context) - // .expect("should prepare"); - - // let args = &[b"hello".as_slice(), b"world but longer".as_slice()]; - - // let (result, gas_summary) = instance.call_export("call", args); - // dbg!(&result, gas_summary); - - // instance.teardown() - // }; -} - -#[derive(Default, Debug, Clone)] -struct MockStorage; -impl Storage for MockStorage { - fn write( - &self, - key_tag: u64, - key: &[u8], - value_tag: u64, - value: &[u8], - ) -> Result<(), storage::Error> { - todo!() - } - - fn read(&self, key_tag: u64, key: &[u8]) -> Result, storage::Error> { - todo!() - } -} - -fn criterion_benchmark(c: &mut Criterion) { - c.bench_function("call", |b| { - let mut vm = WasmEngine::new(); - let storage = MockStorage::default(); - - let execute_request = ExecuteRequest { - wasm_bytes: Bytes::from_static(TEST_CONTRACT_WASM), - }; - - let mock_context = Context { storage }; - - let mut instance = vm - .prepare(execute_request, mock_context) - .expect("should prepare"); - - b.iter(|| { - let args = &[b"hello".as_slice(), b"world but longer".as_slice()]; - let (result, gas_summary) = instance.execute_call("call", args); - }); - - instance.teardown(); - }); -} - -criterion_group!(benches, criterion_benchmark); -criterion_main!(benches); diff --git a/vm/src/chain.rs b/vm/src/chain.rs deleted file mode 100644 index 9fc7bf3456..0000000000 --- a/vm/src/chain.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub trait Chain { - fn call_instance(&self); -} diff --git a/vm/src/host/utils.rs b/vm/src/host/utils.rs deleted file mode 100644 index 8b13789179..0000000000 --- a/vm/src/host/utils.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/vm/src/storage.rs b/vm/src/storage.rs deleted file mode 100644 index 4b20c4c66d..0000000000 --- a/vm/src/storage.rs +++ /dev/null @@ -1,53 +0,0 @@ -pub(crate) mod runtime; - -use bytes::Bytes; -use casper_storage::{ - global_state::{self, state::StateReader}, - tracking_copy::TrackingCopyError, -}; -use casper_types::{Key, StoredValue}; -use vm_common::flags::EntryPointFlags; - -pub(crate) type TrackingCopy = casper_storage::TrackingCopy; - -pub trait GlobalStateReader: - StateReader -{ -} - -impl> GlobalStateReader for R {} - -pub enum Tag { - Bytes = 0, -} - -pub enum KeySpace { - Default = 0, -} - -#[derive(Debug)] -pub enum Error { - Foo, - Bar, -} - -pub struct Entry { - pub tag: u64, - pub data: Bytes, -} - -#[derive(Default, Debug, Clone)] -pub(crate) struct EntryPoint { - pub(crate) selector: u32, - pub(crate) function_index: u32, - pub(crate) flags: EntryPointFlags, -} - -pub type Address = [u8; 32]; - -pub struct CreateResult { - pub package_address: Address, - pub contract_address: Address, -} - -const STORAGE_READ_ERROR_MSG: &str = "failed to read from storage"; diff --git a/vm/src/wasm_backend.rs b/vm/src/wasm_backend.rs deleted file mode 100644 index 401ddca3a5..0000000000 --- a/vm/src/wasm_backend.rs +++ /dev/null @@ -1,120 +0,0 @@ -pub(crate) mod wasmer; -use std::{collections::VecDeque, sync::Arc}; - -use bytes::Bytes; -use casper_storage::AddressGenerator; -use casper_types::{system, AddressableEntity, Key, TransactionHash, URef}; -use parking_lot::RwLock; -use thiserror::Error; - -use crate::{ - executor::ExecutionKind, - storage::{Address, GlobalStateReader, TrackingCopy}, - Config, Executor, VMError, VMResult, -}; - -#[derive(Debug)] -pub struct GasUsage { - /// The amount of gas used by the execution. - pub(crate) gas_limit: u64, - /// The amount of gas remaining after the execution. - pub(crate) remaining_points: u64, -} - -impl GasUsage { - pub fn new(gas_limit: u64, remaining_points: u64) -> Self { - GasUsage { - gas_limit, - remaining_points, - } - } - - pub fn gas_spent(&self) -> u64 { - debug_assert!(self.remaining_points <= self.gas_limit); - self.gas_limit - self.remaining_points - } -} - -/// Container that holds all relevant modules necessary to process an execution request. -pub(crate) struct Context { - /// The address of the account that initiated the contract or session code. - pub(crate) initiator: Address, - /// The address of the addressable entity that is currently executing the contract or session - /// code. - pub(crate) caller: Key, - /// The address of the addressable entity that is being called. - pub(crate) callee: Key, - /// The state of the global state at the time of the call based on the currently executing - /// contract or session address. - // pub(crate) state_address: Address, - /// The amount of tokens that were send to the contract's purse at the time of the call. - pub(crate) value: u128, - pub(crate) tracking_copy: TrackingCopy, - pub(crate) executor: E, // TODO: This could be part of the caller - pub(crate) transaction_hash: TransactionHash, - pub(crate) address_generator: Arc>, - pub(crate) chain_name: Arc, -} - -#[derive(Debug, Copy, Clone)] -pub enum MeteringPoints { - Remaining(u64), - Exhausted, -} - -impl MeteringPoints { - pub fn try_into_remaining(self) -> Result { - if let Self::Remaining(v) = self { - Ok(v) - } else { - Err(self) - } - } -} - -/// An abstraction over the 'caller' object of a host function that works for any Wasm VM. -/// -/// This allows access for important instances such as the context object that was passed to the -/// instance, wasm linear memory access, etc. - -pub(crate) trait Caller { - fn config(&self) -> &Config; - fn context(&self) -> &Context; - fn context_mut(&mut self) -> &mut Context; - /// Returns currently running *unmodified* bytecode. - fn bytecode(&self) -> Bytes; - - fn memory_read(&self, offset: u32, size: usize) -> VMResult> { - let mut vec = vec![0; size]; - self.memory_read_into(offset, &mut vec)?; - Ok(vec) - } - fn memory_read_into(&self, offset: u32, output: &mut [u8]) -> VMResult<()>; - fn memory_write(&self, offset: u32, data: &[u8]) -> VMResult<()>; - /// Allocates memory inside the Wasm VM by calling an export. - /// - /// Error is a type-erased error coming from the VM itself. - fn alloc(&mut self, idx: u32, size: usize, ctx: u32) -> VMResult; - /// Returns the amount of gas used. - fn gas_consumed(&mut self) -> MeteringPoints; - /// Set the amount of gas used. - fn consume_gas(&mut self, value: u64) -> MeteringPoints; -} - -#[derive(Debug, Error)] -pub enum WasmPreparationError { - #[error("Missing export {0}")] - MissingExport(String), - #[error("Compile error: {0}")] - Compile(String), - #[error("Memory instantiation error: {0}")] - Memory(String), - #[error("Instantiation error: {0}")] - Instantiation(String), -} - -pub(crate) trait WasmInstance { - fn call_export(&mut self, name: &str) -> (Result<(), VMError>, GasUsage); - fn call_function(&mut self, function_index: u32) -> (Result<(), VMError>, GasUsage); - fn teardown(self) -> Context; -} diff --git a/vm/vm2-cep18-caller.wasm b/vm/vm2-cep18-caller.wasm deleted file mode 120000 index c7652ae4c2..0000000000 --- a/vm/vm2-cep18-caller.wasm +++ /dev/null @@ -1 +0,0 @@ -../target/wasm32-unknown-unknown/release/vm2-cep18-caller.wasm \ No newline at end of file diff --git a/vm/vm2-harness.wasm b/vm/vm2-harness.wasm deleted file mode 120000 index 05537db053..0000000000 --- a/vm/vm2-harness.wasm +++ /dev/null @@ -1 +0,0 @@ -../target/wasm32-unknown-unknown/release/vm2-harness.wasm \ No newline at end of file diff --git a/vm/vm2_cep18.wasm b/vm/vm2_cep18.wasm deleted file mode 120000 index 1bf89d7b8a..0000000000 --- a/vm/vm2_cep18.wasm +++ /dev/null @@ -1 +0,0 @@ -../target/wasm32-unknown-unknown/release/vm2_cep18.wasm \ No newline at end of file diff --git a/vm/vm2_flipper.wasm b/vm/vm2_flipper.wasm deleted file mode 120000 index dd0881759e..0000000000 --- a/vm/vm2_flipper.wasm +++ /dev/null @@ -1 +0,0 @@ -../target/wasm32-unknown-unknown/release/vm2_flipper.wasm \ No newline at end of file diff --git a/vm/vm2_trait.wasm b/vm/vm2_trait.wasm deleted file mode 120000 index a7def27fff..0000000000 --- a/vm/vm2_trait.wasm +++ /dev/null @@ -1 +0,0 @@ -../target/wasm32-unknown-unknown/release/vm2_trait.wasm \ No newline at end of file diff --git a/vm/vm2_upgradable.wasm b/vm/vm2_upgradable.wasm deleted file mode 120000 index e810a1a30f..0000000000 --- a/vm/vm2_upgradable.wasm +++ /dev/null @@ -1 +0,0 @@ -../target/wasm32-unknown-unknown/release/vm2_upgradable.wasm \ No newline at end of file diff --git a/vm/vm2_upgradable_v2.wasm b/vm/vm2_upgradable_v2.wasm deleted file mode 120000 index ffab9cfeed..0000000000 --- a/vm/vm2_upgradable_v2.wasm +++ /dev/null @@ -1 +0,0 @@ -../target/wasm32-unknown-unknown/release/vm2_upgradable_v2.wasm \ No newline at end of file