From 7255fbd61a7966fc51b26919d2c74f01932159a9 Mon Sep 17 00:00:00 2001 From: Hoon <48665813+sh-cha@users.noreply.github.com> Date: Wed, 30 Oct 2024 18:39:51 +0900 Subject: [PATCH] LoaderV2 integration (#139) * wip: apply loader v2, need to fix move to json error * copy type conversion functions from runtime loader & handle json parsing error * bump aptos core loader v2 version * introduce InitiaModuleStorage using LRU module cache * introduce InitiaCodeStorage to connect InitiaModuleStorage * manage module cache as a single unit within the Initia VM * manage script cache as a single unit within the Initia VM * fmt and clippy * compiled module & script interface change * use custom move (#140) * update rust version * clone runtime_environment on every call * introduce lock on cache (#141) * use aptor-core move & flush type_cache every vm call * not cloning environment with flushed ty_cache * fix coderabbit audit * feat: deps code upgrade policy check (#144) * upgrade policy check to dependency modules * fix broken tests * pass policy check if dep is stdlib * add code publish tests * fmt and clippy * feat: implement flashswap (#142) * implement flashswap * fix typo; * fix missing pool_amounts conversion * change the impl to use hot potato pattern * fix typo and add borrow_amounts read function * rename get_borrow_amounts * movefmt * lock the pool at flash swap and disallow provide liquidity and swap operations * add testcases * fmt and rebuild * lock first before calling external functoins * add flash swap event * feat: support multisend cosmos interface (#143) * introduce multisend * remove unused from minitia_stdlib * add comments for the error handlings * change to call move function instead of reading table context data (#147) * change to call move function instead of reading table context data * lint * change to do not receive module_ids --------- Co-authored-by: beer-1 <147697694+beer-1@users.noreply.github.com> Co-authored-by: beer-1 * apply recent aptos update making struct index map to arc * calculate cache size using real heap size * fmt clippy * add storage & code conversion test * fix script access specifier * add code scale test code to be used in e2e test & debug code to identify equal structs * add panic handling when fetching size * apply merged version * Feat/refactor native code (#154) * change upgrade policy u8 to enum * code test cleanup & use loaderv2 as default * code module type * typo * nit error message change * cleanup module cache code * nit error message * delete type conversion funcs from sessionExt & use them from session directly * use 1 as cache weight for all cache items * minor lint fix * feat: use constant cache weight for all modules & scripts (#156) * use 1 as cache weight for all cache items * small refactor --------- Co-authored-by: beer-1 <147697694+beer-1@users.noreply.github.com> Co-authored-by: beer-1 --- .cargo/config.toml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/test.yml | 2 +- Cargo.toml | 105 +-- Makefile | 5 +- README.md | 5 +- builders/Dockerfile.alpine | 2 +- builders/Dockerfile.centos7 | 2 +- builders/Dockerfile.cross | 2 +- crates/compiler/src/unit_test_factory.rs | 11 +- crates/e2e-move-tests/Cargo.toml | 1 + crates/e2e-move-tests/src/harness.rs | 38 +- crates/e2e-move-tests/src/tests/args.rs | 17 +- crates/e2e-move-tests/src/tests/cache.rs | 9 +- crates/e2e-move-tests/src/tests/code.rs | 118 +++ crates/e2e-move-tests/src/tests/cosmos.rs | 5 +- .../e2e-move-tests/src/tests/infinite_loop.rs | 5 +- .../src/tests/max_loop_depth.rs | 9 +- .../e2e-move-tests/src/tests/memory_quota.rs | 9 +- crates/e2e-move-tests/src/tests/mod.rs | 1 + crates/e2e-move-tests/src/tests/output.rs | 3 +- crates/e2e-move-tests/src/tests/std_coin.rs | 3 +- .../tests/string_viewer.data/viewer/Move.toml | 10 + .../viewer/sources/StringViewer.move | 8 + .../string_viewer.data/viewer2/Move.toml | 11 + .../viewer2/sources/StringViewer2.move | 9 + crates/e2e-move-tests/src/tests/table.rs | 5 +- .../e2e-move-tests/src/tests/view_output.rs | 3 +- crates/json/Cargo.toml | 4 +- crates/json/src/json_to_move.rs | 364 ++++++--- crates/natives/src/code.rs | 68 +- crates/natives/src/native_functions.rs | 163 ---- crates/storage/Cargo.toml | 8 + crates/storage/src/code_scale.rs | 34 + crates/storage/src/code_storage.rs | 273 +++++++ crates/storage/src/initia_storage.rs | 47 ++ crates/storage/src/lib.rs | 9 + crates/storage/src/memory_module_storage.rs | 325 ++++++++ crates/storage/src/module_cache.rs | 188 +++++ crates/storage/src/module_storage.rs | 705 ++++++++++++++++++ crates/storage/src/script_cache.rs | 104 +++ crates/storage/src/state_view.rs | 12 + crates/storage/src/state_view_impl.rs | 78 +- crates/types/Cargo.toml | 1 + crates/types/src/access_path.rs | 33 +- crates/types/src/metadata.rs | 3 + crates/types/src/module.rs | 8 + crates/types/src/vm_config.rs | 12 + crates/types/src/write_set.rs | 32 +- crates/vm/Cargo.toml | 3 +- crates/vm/src/initia_vm.rs | 451 ++++------- crates/vm/src/lib.rs | 4 +- crates/vm/src/publish.rs | 345 +++++++++ crates/vm/src/session.rs | 91 ++- crates/vm/src/verifier/config.rs | 1 - crates/vm/src/verifier/event_validation.rs | 20 +- crates/vm/src/verifier/metadata.rs | 11 +- crates/vm/src/verifier/module_metadata.rs | 6 +- .../verifier/transaction_arg_validation.rs | 50 +- crates/vm/src/verifier/view_function.rs | 8 +- lib_test.go | 4 +- libmovevm/Cargo.toml | 1 + libmovevm/src/vm.rs | 36 +- precompile/binaries/minlib/account.mv | Bin 1837 -> 1827 bytes precompile/binaries/minlib/acl.mv | Bin 612 -> 612 bytes precompile/binaries/minlib/any.mv | Bin 516 -> 521 bytes precompile/binaries/minlib/ascii.mv | Bin 977 -> 981 bytes precompile/binaries/minlib/bigdecimal.mv | Bin 2933 -> 3000 bytes precompile/binaries/minlib/biguint.mv | Bin 1493 -> 1536 bytes precompile/binaries/minlib/bit_vector.mv | Bin 1075 -> 1036 bytes precompile/binaries/minlib/block.mv | Bin 304 -> 307 bytes precompile/binaries/minlib/capability.mv | Bin 1145 -> 1162 bytes precompile/binaries/minlib/code.mv | Bin 3154 -> 3597 bytes precompile/binaries/minlib/coin.mv | Bin 3486 -> 3508 bytes precompile/binaries/minlib/collection.mv | Bin 5001 -> 4990 bytes precompile/binaries/minlib/comparator.mv | Bin 563 -> 565 bytes precompile/binaries/minlib/compare.mv | Bin 435 -> 430 bytes precompile/binaries/minlib/copyable_any.mv | Bin 525 -> 530 bytes precompile/binaries/minlib/cosmos.mv | Bin 3352 -> 3378 bytes precompile/binaries/minlib/dex.mv | Bin 14057 -> 14085 bytes .../minlib/dispatchable_fungible_asset.mv | Bin 2328 -> 2344 bytes precompile/binaries/minlib/ed25519.mv | Bin 1130 -> 1127 bytes precompile/binaries/minlib/fixed_point32.mv | Bin 1432 -> 1393 bytes precompile/binaries/minlib/fixed_point64.mv | Bin 2885 -> 2827 bytes precompile/binaries/minlib/from_bcs.mv | Bin 816 -> 823 bytes precompile/binaries/minlib/function_info.mv | Bin 907 -> 912 bytes precompile/binaries/minlib/fungible_asset.mv | Bin 10340 -> 10319 bytes precompile/binaries/minlib/guid.mv | Bin 1034 -> 1042 bytes precompile/binaries/minlib/hex.mv | Bin 1348 -> 1315 bytes precompile/binaries/minlib/initia_nft.mv | Bin 3973 -> 3968 bytes precompile/binaries/minlib/json.mv | Bin 1102 -> 1097 bytes precompile/binaries/minlib/managed_coin.mv | Bin 1359 -> 1356 bytes precompile/binaries/minlib/math128.mv | Bin 1704 -> 1684 bytes precompile/binaries/minlib/math64.mv | Bin 1267 -> 1255 bytes precompile/binaries/minlib/multisig.mv | Bin 5110 -> 5088 bytes precompile/binaries/minlib/multisig_v2.mv | Bin 9973 -> 9714 bytes precompile/binaries/minlib/nft.mv | Bin 3853 -> 3829 bytes precompile/binaries/minlib/object.mv | Bin 4514 -> 4523 bytes .../binaries/minlib/object_code_deployment.mv | Bin 1416 -> 1469 bytes precompile/binaries/minlib/option.mv | Bin 1628 -> 1640 bytes precompile/binaries/minlib/oracle.mv | Bin 252 -> 255 bytes .../binaries/minlib/primary_fungible_store.mv | Bin 3783 -> 3832 bytes precompile/binaries/minlib/property_map.mv | Bin 5184 -> 5148 bytes precompile/binaries/minlib/query.mv | Bin 662 -> 669 bytes precompile/binaries/minlib/royalty.mv | Bin 1147 -> 1162 bytes precompile/binaries/minlib/secp256k1.mv | Bin 1326 -> 1321 bytes precompile/binaries/minlib/simple_map.mv | Bin 2166 -> 2114 bytes precompile/binaries/minlib/simple_nft.mv | Bin 3510 -> 3501 bytes .../binaries/minlib/soul_bound_token.mv | Bin 5018 -> 5018 bytes precompile/binaries/minlib/string.mv | Bin 1081 -> 1083 bytes precompile/binaries/minlib/string_utils.mv | Bin 1585 -> 1533 bytes precompile/binaries/minlib/table.mv | Bin 2032 -> 2057 bytes precompile/binaries/minlib/timestamp.mv | Bin 406 -> 409 bytes precompile/binaries/minlib/vector.mv | Bin 2281 -> 2247 bytes precompile/binaries/minlib/vip_score.mv | Bin 3457 -> 3441 bytes precompile/binaries/stdlib/account.mv | Bin 1847 -> 1837 bytes precompile/binaries/stdlib/acl.mv | Bin 612 -> 612 bytes precompile/binaries/stdlib/any.mv | Bin 516 -> 521 bytes precompile/binaries/stdlib/ascii.mv | Bin 977 -> 981 bytes precompile/binaries/stdlib/bigdecimal.mv | Bin 2933 -> 3000 bytes precompile/binaries/stdlib/biguint.mv | Bin 1493 -> 1536 bytes precompile/binaries/stdlib/bit_vector.mv | Bin 1075 -> 1036 bytes precompile/binaries/stdlib/block.mv | Bin 304 -> 307 bytes precompile/binaries/stdlib/capability.mv | Bin 1145 -> 1162 bytes precompile/binaries/stdlib/code.mv | Bin 3154 -> 3597 bytes precompile/binaries/stdlib/coin.mv | Bin 3582 -> 3606 bytes precompile/binaries/stdlib/collection.mv | Bin 5001 -> 4990 bytes precompile/binaries/stdlib/comparator.mv | Bin 563 -> 565 bytes precompile/binaries/stdlib/compare.mv | Bin 435 -> 430 bytes precompile/binaries/stdlib/copyable_any.mv | Bin 525 -> 530 bytes precompile/binaries/stdlib/cosmos.mv | Bin 3352 -> 3378 bytes precompile/binaries/stdlib/dex.mv | Bin 14057 -> 14085 bytes .../stdlib/dispatchable_fungible_asset.mv | Bin 2328 -> 2344 bytes precompile/binaries/stdlib/ed25519.mv | Bin 1130 -> 1127 bytes precompile/binaries/stdlib/fixed_point32.mv | Bin 1432 -> 1393 bytes precompile/binaries/stdlib/fixed_point64.mv | Bin 2885 -> 2827 bytes precompile/binaries/stdlib/from_bcs.mv | Bin 816 -> 823 bytes precompile/binaries/stdlib/function_info.mv | Bin 907 -> 912 bytes precompile/binaries/stdlib/fungible_asset.mv | Bin 10439 -> 10419 bytes precompile/binaries/stdlib/guid.mv | Bin 1034 -> 1042 bytes precompile/binaries/stdlib/hex.mv | Bin 1348 -> 1315 bytes precompile/binaries/stdlib/initia_nft.mv | Bin 3973 -> 3968 bytes precompile/binaries/stdlib/json.mv | Bin 1102 -> 1097 bytes precompile/binaries/stdlib/managed_coin.mv | Bin 1359 -> 1356 bytes precompile/binaries/stdlib/math128.mv | Bin 1704 -> 1684 bytes precompile/binaries/stdlib/math64.mv | Bin 1267 -> 1255 bytes precompile/binaries/stdlib/minitswap.mv | Bin 20756 -> 20775 bytes precompile/binaries/stdlib/multisig.mv | Bin 5110 -> 5088 bytes precompile/binaries/stdlib/multisig_v2.mv | Bin 9973 -> 9714 bytes precompile/binaries/stdlib/nft.mv | Bin 3853 -> 3829 bytes precompile/binaries/stdlib/object.mv | Bin 4514 -> 4523 bytes .../binaries/stdlib/object_code_deployment.mv | Bin 1415 -> 1468 bytes precompile/binaries/stdlib/option.mv | Bin 1628 -> 1640 bytes precompile/binaries/stdlib/oracle.mv | Bin 252 -> 255 bytes .../binaries/stdlib/primary_fungible_store.mv | Bin 3783 -> 3832 bytes precompile/binaries/stdlib/property_map.mv | Bin 5184 -> 5148 bytes precompile/binaries/stdlib/query.mv | Bin 662 -> 669 bytes precompile/binaries/stdlib/royalty.mv | Bin 1147 -> 1162 bytes precompile/binaries/stdlib/secp256k1.mv | Bin 1326 -> 1321 bytes precompile/binaries/stdlib/simple_map.mv | Bin 2166 -> 2114 bytes precompile/binaries/stdlib/simple_nft.mv | Bin 3510 -> 3501 bytes .../binaries/stdlib/soul_bound_token.mv | Bin 5018 -> 5018 bytes precompile/binaries/stdlib/stableswap.mv | Bin 12111 -> 11877 bytes precompile/binaries/stdlib/staking.mv | Bin 11782 -> 11551 bytes precompile/binaries/stdlib/string.mv | Bin 1081 -> 1083 bytes precompile/binaries/stdlib/string_utils.mv | Bin 1585 -> 1533 bytes precompile/binaries/stdlib/table.mv | Bin 2032 -> 2057 bytes precompile/binaries/stdlib/timestamp.mv | Bin 406 -> 409 bytes precompile/binaries/stdlib/vector.mv | Bin 2281 -> 2247 bytes .../modules/initia_stdlib/sources/code.move | 200 +++-- .../sources/object_code_deployment.move | 15 +- .../modules/minitia_stdlib/sources/code.move | 200 +++-- .../sources/object_code_deployment.move | 15 +- types/bcs.go | 6 + 174 files changed, 3364 insertions(+), 976 deletions(-) create mode 100644 crates/e2e-move-tests/src/tests/code.rs create mode 100644 crates/e2e-move-tests/src/tests/string_viewer.data/viewer/Move.toml create mode 100644 crates/e2e-move-tests/src/tests/string_viewer.data/viewer/sources/StringViewer.move create mode 100644 crates/e2e-move-tests/src/tests/string_viewer.data/viewer2/Move.toml create mode 100644 crates/e2e-move-tests/src/tests/string_viewer.data/viewer2/sources/StringViewer2.move delete mode 100644 crates/natives/src/native_functions.rs create mode 100644 crates/storage/src/code_scale.rs create mode 100644 crates/storage/src/code_storage.rs create mode 100644 crates/storage/src/initia_storage.rs create mode 100644 crates/storage/src/memory_module_storage.rs create mode 100644 crates/storage/src/module_cache.rs create mode 100644 crates/storage/src/module_storage.rs create mode 100644 crates/storage/src/script_cache.rs create mode 100644 crates/vm/src/publish.rs diff --git a/.cargo/config.toml b/.cargo/config.toml index 3a7bfeb7..b341c695 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,4 +1,4 @@ [env] RUST_BIGDECIMAL_FMT_EXPONENTIAL_UPPER_THRESHOLD="100" -RUST_BIGDECIMAL_FMT_EXPONENTIAL_LOWER_THRESHOLD="100" +RUST_BIGDECIMAL_FMT_EXPONENTIAL_LOWER_THRESHOLD="100" \ No newline at end of file diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index f8470eb0..f45d2636 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -30,7 +30,7 @@ jobs: - name: Install latest rust uses: actions-rs/toolchain@v1 with: - toolchain: 1.77.1 + toolchain: 1.80.1 override: true components: rustfmt, clippy - uses: actions/setup-go@v4 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 747db6f8..86f9df8d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -46,7 +46,7 @@ jobs: - name: Install latest rust uses: actions-rs/toolchain@v1 with: - toolchain: 1.77.1 + toolchain: 1.80.1 - name: Build Rust run: make build-rust - uses: actions/setup-go@v4 diff --git a/Cargo.toml b/Cargo.toml index 4a1d6cd1..11b95e5e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,7 +49,7 @@ license = "BUSL-1.1" license-file = "LICENSE" homepage = "https://initia.xyz" repository = "https://github.com/initia-labs/movevm" -rust-version = "1.77.1" +rust-version = "1.80.1" [workspace.dependencies] # Internal crate dependencies. @@ -65,9 +65,11 @@ initia-move-resource-viewer = { path = "crates/resource-viewer" } # External crate dependencies. # Please do not add any test features here: they should be declared by the individual crate. -anyhow = "1.0.41" -bcs = "0.1.5" +ambassador = "0.4.1" +anyhow = "1.0.71" +bcs = { git = "https://github.com/aptos-labs/bcs.git", rev = "d31fab9d81748e2594be5cd5cdf845786a30562d" } better_any = "0.1.1" +claims = "0.7" clru = "^0.6.2" cbindgen = "0.26.0" clap = { version = "4.3.9", features = ["derive", "env", "suggestions"] } @@ -76,7 +78,7 @@ dialoguer = "0.10.2" ed25519-consensus = { version = "2.0.1", features = ["serde"] } errno = "0.3.0" hex = { version = "0.4.3", default-features = false } -itertools = "0.10.3" +itertools = "0.13" libsecp256k1 = { version = "0.7.1" } log = { version = "0.4.17", features = [ "max_level_debug", @@ -95,16 +97,17 @@ serde-generate = { git = "https://github.com/aptos-labs/serde-reflection", rev = serde-reflection = { git = "https://github.com/aptos-labs/serde-reflection", rev = "73b6bbf748334b71ff6d7d09d06a29e3062ca075" } sha2 = "0.10.8" sha3 = "0.10.6" -smallvec = "1.6.1" +smallvec = "1.8.0" smallbitvec = "2.5.1" -tempfile = "3.2.0" +tempfile = "3.3.0" serial_test = "1.0.0" -thiserror = "1.0.34" +thiserror = "1.0.37" tsu = "1.0.1" bytes = "1.4.0" parking_lot = "0.12.1" base64 = "0.21.7" bigdecimal = ">=0.4.5" +primitive-types = { version = "0.10" } bech32 = "0.11" triomphe = "0.1.9" ripemd = "0.1.1" @@ -113,51 +116,51 @@ tiny-keccak = { version = "2.0.2", features = ["keccak", "sha3"] } # Note: the BEGIN and END comments below are required for external tooling. Do not remove. # BEGIN MOVE DEPENDENCIES -move-binary-format = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "85966af7ddcf971f3f04f4f409c3e67c9d9b11cb" } -move-bytecode-verifier = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "85966af7ddcf971f3f04f4f409c3e67c9d9b11cb" } -move-bytecode-utils = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "85966af7ddcf971f3f04f4f409c3e67c9d9b11cb" } -move-cli = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "85966af7ddcf971f3f04f4f409c3e67c9d9b11cb" } -move-command-line-common = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "85966af7ddcf971f3f04f4f409c3e67c9d9b11cb" } -move-compiler = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "85966af7ddcf971f3f04f4f409c3e67c9d9b11cb" } -move-coverage = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "85966af7ddcf971f3f04f4f409c3e67c9d9b11cb" } -move-core-types = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "85966af7ddcf971f3f04f4f409c3e67c9d9b11cb" } -move-docgen = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "85966af7ddcf971f3f04f4f409c3e67c9d9b11cb" } -move-model = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "85966af7ddcf971f3f04f4f409c3e67c9d9b11cb" } -move-package = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "85966af7ddcf971f3f04f4f409c3e67c9d9b11cb" } -move-prover = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "85966af7ddcf971f3f04f4f409c3e67c9d9b11cb" } -move-prover-boogie-backend = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "85966af7ddcf971f3f04f4f409c3e67c9d9b11cb" } -move-prover-bytecode-pipeline = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "85966af7ddcf971f3f04f4f409c3e67c9d9b11cb" } -move-resource-viewer = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "85966af7ddcf971f3f04f4f409c3e67c9d9b11cb" } -move-stackless-bytecode = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "85966af7ddcf971f3f04f4f409c3e67c9d9b11cb" } -move-stdlib = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "85966af7ddcf971f3f04f4f409c3e67c9d9b11cb" } -move-symbol-pool = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "85966af7ddcf971f3f04f4f409c3e67c9d9b11cb" } -move-unit-test = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "85966af7ddcf971f3f04f4f409c3e67c9d9b11cb" } -move-vm-runtime = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "85966af7ddcf971f3f04f4f409c3e67c9d9b11cb" } -move-vm-test-utils = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "85966af7ddcf971f3f04f4f409c3e67c9d9b11cb" } -move-vm-types = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "85966af7ddcf971f3f04f4f409c3e67c9d9b11cb" } +move-binary-format = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "751c9a34969e54dd18452d41f3c996fc2e971eb7" } +move-bytecode-verifier = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "751c9a34969e54dd18452d41f3c996fc2e971eb7" } +move-bytecode-utils = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "751c9a34969e54dd18452d41f3c996fc2e971eb7" } +move-cli = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "751c9a34969e54dd18452d41f3c996fc2e971eb7" } +move-command-line-common = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "751c9a34969e54dd18452d41f3c996fc2e971eb7" } +move-compiler = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "751c9a34969e54dd18452d41f3c996fc2e971eb7" } +move-coverage = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "751c9a34969e54dd18452d41f3c996fc2e971eb7" } +move-core-types = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "751c9a34969e54dd18452d41f3c996fc2e971eb7" } +move-docgen = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "751c9a34969e54dd18452d41f3c996fc2e971eb7" } +move-model = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "751c9a34969e54dd18452d41f3c996fc2e971eb7" } +move-package = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "751c9a34969e54dd18452d41f3c996fc2e971eb7" } +move-prover = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "751c9a34969e54dd18452d41f3c996fc2e971eb7" } +move-prover-boogie-backend = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "751c9a34969e54dd18452d41f3c996fc2e971eb7" } +move-prover-bytecode-pipeline = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "751c9a34969e54dd18452d41f3c996fc2e971eb7" } +move-resource-viewer = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "751c9a34969e54dd18452d41f3c996fc2e971eb7" } +move-stackless-bytecode = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "751c9a34969e54dd18452d41f3c996fc2e971eb7" } +move-stdlib = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "751c9a34969e54dd18452d41f3c996fc2e971eb7" } +move-symbol-pool = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "751c9a34969e54dd18452d41f3c996fc2e971eb7" } +move-unit-test = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "751c9a34969e54dd18452d41f3c996fc2e971eb7" } +move-vm-runtime = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "751c9a34969e54dd18452d41f3c996fc2e971eb7" } +move-vm-test-utils = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "751c9a34969e54dd18452d41f3c996fc2e971eb7" } +move-vm-types = { git = "https://github.com/aptos-labs/aptos-core.git", rev = "751c9a34969e54dd18452d41f3c996fc2e971eb7" } # END MOVE DEPENDENCIES # FOR LOCAL DEVELOPMENNT -# move-binary-format = { path = "../aptos-core/third_party/move/move-binary-format" } -# move-bytecode-verifier = { path = "../aptos-core/third_party/move/move-bytecode-verifier" } -# move-bytecode-utils = { path = "../aptos-core/third_party/move/tools/move-bytecode-utils" } -# move-cli = { path = "../aptos-core/third_party/move/tools/move-cli" } -# move-command-line-common = { path = "../aptos-core/third_party/move/move-command-line-common" } -# move-compiler = { path = "../aptos-core/third_party/move/move-compiler" } -# move-coverage ={ path = "../aptos-core/third_party/move/tools/move-coverage" } -# move-core-types = { path = "../aptos-core/third_party/move/move-core/types" } -# move-docgen = { path = "../aptos-core/third_party/move/move-prover/move-docgen" } -# move-model = { path = "../aptos-core/third_party/move/move-model" } -# move-package = { path = "../aptos-core/third_party/move/tools/move-package" } -# move-prover = { path = "../aptos-core/third_party/move/move-prover" } -# move-prover-boogie-backend = { path = "../aptos-core/third_party/move/move-prover/boogie-backend" } -# move-prover-bytecode-pipeline = { path = "../aptos-core/third_party/move/move-prover/bytecode-pipeline" } -# move-resource-viewer = { path = "../aptos-core/third_party/move/tools/move-resource-viewer" } -# move-stackless-bytecode = { path = "../aptos-core/third_party/move/move-model/bytecode" } -# move-stdlib = { path = "../aptos-core/third_party/move/move-stdlib" } -# move-symbol-pool = { path = "../aptos-core/third_party/move/move-symbol-pool" } -# move-unit-test = { path = "../aptos-core/third_party/move/tools/move-unit-test" } -# move-vm-runtime = { path = "../aptos-core/third_party/move/move-vm/runtime" } -# move-vm-test-utils = { path = "../aptos-core/third_party/move/move-vm/test-utils" } -# move-vm-types = { path = "../aptos-core/third_party/move/move-vm/types" } +# move-binary-format = { path = "../move/move-binary-format" } +# move-bytecode-verifier = { path = "../move/move-bytecode-verifier" } +# move-bytecode-utils = { path = "../move/tools/move-bytecode-utils" } +# move-cli = { path = "../move/tools/move-cli" } +# move-command-line-common = { path = "../move/move-command-line-common" } +# move-compiler = { path = "../move/move-compiler" } +# move-coverage ={ path = "../move/tools/move-coverage" } +# move-core-types = { path = "../move/move-core/types" } +# move-docgen = { path = "../move/move-prover/move-docgen" } +# move-model = { path = "../move/move-model" } +# move-package = { path = "../move/tools/move-package" } +# move-prover = { path = "../move/move-prover" } +# move-prover-boogie-backend = { path = "../move/move-prover/boogie-backend" } +# move-prover-bytecode-pipeline = { path = "../move/move-prover/bytecode-pipeline" } +# move-resource-viewer = { path = "../move/tools/move-resource-viewer" } +# move-stackless-bytecode = { path = "../move/move-model/bytecode" } +# move-stdlib = { path = "../move/move-stdlib" } +# move-symbol-pool = { path = "../move/move-symbol-pool" } +# move-unit-test = { path = "../move/tools/move-unit-test" } +# move-vm-runtime = { path = "../move/move-vm/runtime" } +# move-vm-test-utils = { path = "../move/move-vm/test-utils" } +# move-vm-types = { path = "../move/move-vm/types" } diff --git a/Makefile b/Makefile index adc8200c..a43891bb 100644 --- a/Makefile +++ b/Makefile @@ -53,7 +53,7 @@ test-safety: # Use package list mode to include all subdirectores. The -count=1 turns off caching. GODEBUG=cgocheck=2 go test -race -v -count=1 -parallel=1 ./... -test-rust: test-compiler test-lib test-e2e test-movevm test-json +test-rust: test-compiler test-lib test-e2e test-movevm test-json test-storage test-compiler: cargo test -p initia-move-compiler @@ -67,6 +67,9 @@ test-json: test-lib: cargo test -p initia-move-vm +test-storage: + cargo test -p initia-move-storage + test-e2e: cargo test -p e2e-move-tests --features testing diff --git a/README.md b/README.md index bf90bf4d..ad4a437f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # Initia MoveVM + The Initia MoveVM is forked from [wasmvm](https://github.com/CosmWasm/wasmvm) with some modifications to support ([Aptos](https://github.com/aptos-labs/aptos-core)) MoveVM. This mechanism allows the users to compile, initialize, and execute Move Smart Contracts from Go applications, in particular from [x/move](https://github.com/initia-labs/initia/tree/main/x/move). @@ -8,7 +9,7 @@ This repo contains both Rust and Go codes. The rust code is compiled into a dll/ ## Supported Platform -Requires **Rust 1.77+ and Go 1.22+.** +Requires **Rust 1.80+ and Go 1.22+.** The Rust implementation of the VM is compiled to a library called libmovevm. This is then linked to the Go code when the final binary is built. For that reason not all systems supported by Go are supported by this project. @@ -44,4 +45,4 @@ There are two parts to this code - go and rust. The first step is to ensure that If this is present, then `make test` will run the Go test suite and you can import this code freely. If it is not present you will have to build it for your system, and ideally add it to this repo with a PR (on your fork). We will set up a proper CI system for building these binaries, but we are not there yet. -To build the rust side, try make `build-rust` and wait for it to compile. This depends on `cargo` being installed with rustc version 1.77+. Generally, you can just use rustup to install all this with no problems. +To build the rust side, try make `build-rust` and wait for it to compile. This depends on `cargo` being installed with rustc version 1.80+. Generally, you can just use rustup to install all this with no problems. diff --git a/builders/Dockerfile.alpine b/builders/Dockerfile.alpine index 0a6e2a99..2f8a2f0a 100644 --- a/builders/Dockerfile.alpine +++ b/builders/Dockerfile.alpine @@ -16,7 +16,7 @@ RUN set -eux \ RUN wget "https://static.rust-lang.org/rustup/dist/x86_64-unknown-linux-musl/rustup-init" \ && chmod +x rustup-init \ - && ./rustup-init -y --no-modify-path --profile minimal --default-toolchain 1.77.1 \ + && ./rustup-init -y --no-modify-path --profile minimal --default-toolchain 1.80.1 \ && rm rustup-init \ && chmod -R a+w $RUSTUP_HOME $CARGO_HOME diff --git a/builders/Dockerfile.centos7 b/builders/Dockerfile.centos7 index 99368d07..5b2bb0d7 100644 --- a/builders/Dockerfile.centos7 +++ b/builders/Dockerfile.centos7 @@ -27,7 +27,7 @@ ENV RUSTUP_HOME=/usr/local/rustup \ RUN wget "https://static.rust-lang.org/rustup/dist/x86_64-unknown-linux-gnu/rustup-init" \ && chmod +x rustup-init \ - && ./rustup-init -y --no-modify-path --profile minimal --default-toolchain 1.77.1 \ + && ./rustup-init -y --no-modify-path --profile minimal --default-toolchain 1.80.1 \ && rm rustup-init \ && chmod -R a+w $RUSTUP_HOME $CARGO_HOME \ && rustup --version \ diff --git a/builders/Dockerfile.cross b/builders/Dockerfile.cross index d6fd5a8d..ca323eee 100644 --- a/builders/Dockerfile.cross +++ b/builders/Dockerfile.cross @@ -1,4 +1,4 @@ -FROM rust:1.77.1-bullseye +FROM rust:1.80.1-bullseye # Install build dependencies RUN apt-get update \ diff --git a/crates/compiler/src/unit_test_factory.rs b/crates/compiler/src/unit_test_factory.rs index 172c64aa..c3380ca7 100644 --- a/crates/compiler/src/unit_test_factory.rs +++ b/crates/compiler/src/unit_test_factory.rs @@ -27,11 +27,12 @@ impl InitiaUnitTestFactory { let table_change_set = table_context .into_change_set() .map_err(|e| e.finish(Location::Undefined))?; - let write_set = WriteSet::new(changes.clone(), table_change_set).map_err(|e| { - PartialVMError::new(StatusCode::FAILED_TO_SERIALIZE_WRITE_SET_CHANGES) - .with_message(e.to_string()) - .finish(Location::Undefined) - })?; + let write_set = + WriteSet::new_with_change_set(changes.clone(), table_change_set).map_err(|e| { + PartialVMError::new(StatusCode::FAILED_TO_SERIALIZE_WRITE_SET_CHANGES) + .with_message(e.to_string()) + .finish(Location::Undefined) + })?; gas_meter.charge_write_set_gas(&write_set)?; diff --git a/crates/e2e-move-tests/Cargo.toml b/crates/e2e-move-tests/Cargo.toml index c900b90a..d6b5e665 100644 --- a/crates/e2e-move-tests/Cargo.toml +++ b/crates/e2e-move-tests/Cargo.toml @@ -45,5 +45,6 @@ default = [] testing = [ "initia-move-gas/testing", "initia-move-natives/testing", + "initia-move-storage/testing", "move-vm-runtime/testing", ] diff --git a/crates/e2e-move-tests/src/harness.rs b/crates/e2e-move-tests/src/harness.rs index bd2b00b0..b5d6b2f6 100644 --- a/crates/e2e-move-tests/src/harness.rs +++ b/crates/e2e-move-tests/src/harness.rs @@ -3,6 +3,7 @@ use bytes::Bytes; use initia_move_compiler::built_package::BuiltPackage; +use initia_move_natives::code::UpgradePolicy; use initia_move_types::env::Env; use initia_move_types::view_function::{ViewFunction, ViewOutput}; use move_core_types::account_address::AccountAddress; @@ -13,7 +14,7 @@ use move_package::BuildConfig; use crate::test_utils::mock_chain::{MockAPI, MockChain, MockState, MockTableState}; use crate::test_utils::parser::MemberId; use initia_move_gas::Gas; -use initia_move_storage::{state_view::StateView, state_view_impl::StateViewImpl}; +use initia_move_storage::state_view::StateView; use initia_move_types::access_path::AccessPath; use initia_move_types::message::{Message, MessageOutput}; use initia_move_types::module::ModuleBundle; @@ -69,7 +70,6 @@ impl MoveHarness { pub fn initialize(&mut self) { let state = self.chain.create_state(); - let resolver = StateViewImpl::new(&state); let mut table_resolver = MockTableState::new(&state); let env = Env::new( @@ -85,7 +85,7 @@ impl MoveHarness { .initialize( &self.api, &env, - &resolver, + &state, &mut table_resolver, self.load_precompiled_stdlib() .expect("Failed to load precompiles"), @@ -109,9 +109,10 @@ impl MoveHarness { &mut self, acc: &AccountAddress, path: &str, + upgrade_policy: UpgradePolicy, ) -> Result { - let (module_ids, code) = self.compile_package(path); - let msg = self.create_publish_message(*acc, module_ids, code); + let code = self.compile_package(path); + let msg = self.create_publish_message(*acc, code, upgrade_policy); self.run_message(msg) } @@ -158,7 +159,6 @@ impl MoveHarness { view_fn: ViewFunction, state: &MockState, ) -> Result { - let resolver = StateViewImpl::new(state); let mut table_resolver = MockTableState::new(state); let gas_limit = Gas::new(100_000_000u64); @@ -176,7 +176,7 @@ impl MoveHarness { &mut gas_meter, &self.api, &env, - &resolver, + state, &mut table_resolver, &view_fn, ) @@ -188,7 +188,7 @@ impl MoveHarness { vals } - pub fn compile_package(&mut self, path: &str) -> (Vec, Vec>) { + pub fn compile_package(&mut self, path: &str) -> Vec> { let package_path = path_in_crate(path); let package = BuiltPackage::build( package_path.clone(), @@ -202,29 +202,22 @@ impl MoveHarness { ) .expect("compile failed"); - ( - package - .modules() - .map(|v| v.self_id().short_str_lossless()) - .collect(), - package.extract_code(), - ) + package.extract_code() } pub fn create_publish_message( &mut self, sender: AccountAddress, - module_ids: Vec, modules: Vec>, + upgrade_policy: UpgradePolicy, ) -> Message { let ef = MoveHarness::create_entry_function_with_json( - str::parse("0x1::code::publish").unwrap(), + str::parse("0x1::code::publish_v2").unwrap(), vec![], vec![ - serde_json::to_string(&module_ids).unwrap(), serde_json::to_string(&modules.iter().map(hex::encode).collect::>()) .unwrap(), - serde_json::to_string(&(1_u8)).unwrap(), // compatible upgrade policy + serde_json::to_string(&upgrade_policy.to_u8()).unwrap(), // compatible upgrade policy ], ); Message::execute(vec![sender], ef) @@ -321,8 +314,6 @@ impl MoveHarness { ); let state = self.chain.create_state(); - - let resolver = StateViewImpl::new(&state); let mut table_resolver = MockTableState::new(&state); let gas_limit: initia_move_gas::GasQuantity = @@ -332,7 +323,7 @@ impl MoveHarness { &mut gas_meter, &self.api, &env, - &resolver, + &state, &mut table_resolver, message, ) @@ -351,7 +342,6 @@ impl MoveHarness { Self::generate_random_hash().try_into().unwrap(), ); - let resolver = StateViewImpl::new(state); let mut table_resolver = MockTableState::new(state); let gas_limit = Gas::new(100_000_000u64); @@ -360,7 +350,7 @@ impl MoveHarness { &mut gas_meter, &self.api, &env, - &resolver, + state, &mut table_resolver, message, ) diff --git a/crates/e2e-move-tests/src/tests/args.rs b/crates/e2e-move-tests/src/tests/args.rs index 4ed1def4..3a6eab77 100644 --- a/crates/e2e-move-tests/src/tests/args.rs +++ b/crates/e2e-move-tests/src/tests/args.rs @@ -1,6 +1,7 @@ use crate::MoveHarness; use bigdecimal::num_bigint::BigUint; use bigdecimal::FromPrimitive; +use initia_move_natives::code::UpgradePolicy; use move_core_types::account_address::AccountAddress; use move_core_types::identifier::Identifier; use move_core_types::language_storage::{StructTag, TypeTag}; @@ -26,7 +27,9 @@ fn success_generic(ty_args: Vec, tests: Vec) { h.initialize(); // publish package - let output = h.publish_package(&acc, path).expect("should success"); + let output = h + .publish_package(&acc, path, UpgradePolicy::Compatible) + .expect("should success"); h.commit(output, true); // Check in initial state, resource does not exist. @@ -74,7 +77,9 @@ fn fail_generic(ty_args: Vec, tests: Vec<(&str, Vec>, StatusCod h.initialize(); // publish package - let output = h.publish_package(&acc, path).expect("should success"); + let output = h + .publish_package(&acc, path, UpgradePolicy::Compatible) + .expect("should success"); h.commit(output, true); // Check in initial state, resource does not exist. @@ -749,7 +754,9 @@ fn json_object_args() { h.initialize(); // publish package - let output = h.publish_package(&acc, path).expect("should success"); + let output = h + .publish_package(&acc, path, UpgradePolicy::Compatible) + .expect("should success"); h.commit(output, true); // execute create_object @@ -794,7 +801,9 @@ fn biguint_bigdecimal() { h.initialize(); // publish package - let output = h.publish_package(&acc, path).expect("should success"); + let output = h + .publish_package(&acc, path, UpgradePolicy::Compatible) + .expect("should success"); h.commit(output, true); // execute create_object diff --git a/crates/e2e-move-tests/src/tests/cache.rs b/crates/e2e-move-tests/src/tests/cache.rs index cfeaf23f..7c328b40 100644 --- a/crates/e2e-move-tests/src/tests/cache.rs +++ b/crates/e2e-move-tests/src/tests/cache.rs @@ -1,4 +1,5 @@ use crate::MoveHarness; +use initia_move_natives::code::UpgradePolicy; use move_core_types::account_address::AccountAddress; // revive this at loader v2 @@ -31,11 +32,7 @@ fn test_redeploy_should_update_module_cache() { h.initialize(); let code = hex::decode("a11ceb0b060000000d01000a020a12031c28044404054822076aa001088a022010aa02420aec02140b8003020c8203670de903020eeb030200000001000200030004000509010001000600000007060003110700000800010100000900020100000a03040100000b04010002120700000413040801000114050401060505060901050103010b00010900020c03000109000205070b0001090001060c010803010802094261736963436f696e056576656e74067369676e657206737472696e6709747970655f696e666f04436f696e06496e69746961094d696e744576656e7403676574086765745f636f696e046d696e74066e756d6265720576616c756504746573740b64756d6d795f6669656c6406616d6f756e7409636f696e5f7479706506537472696e670a616464726573735f6f6609747970655f6e616d6504656d6974000000000000000000000000000000000000000000000000000000000000000113696e697469613a3a6d657461646174615f76302d0001094d696e744576656e740104000303676574010100066e756d626572010100086765745f636f696e0101000002020c030d010102010e010202020f031008030005000100010004050b003d0037001402010100010004040b003d0014020201040100061d0e0011040c020a023b0020040d0e000a010839003f0005180b023c000c030a033700140a01160b033600150b0138001202380102030100000402064101000000000000020000000500").expect("ms"); - let msg = h.create_publish_message( - AccountAddress::ONE, - vec!["0x1::BasicCoin".to_string()], - vec![code], - ); + let msg = h.create_publish_message(AccountAddress::ONE, vec![code], UpgradePolicy::Compatible); let output = h.run_message(msg).expect("should success"); // commit to store for republish check, @@ -53,7 +50,7 @@ fn test_redeploy_should_update_module_cache() { // upgrade module let output = h - .publish_package(&AccountAddress::ONE, path) + .publish_package(&AccountAddress::ONE, path, UpgradePolicy::Compatible) .expect("should success"); // have to use new module cache, diff --git a/crates/e2e-move-tests/src/tests/code.rs b/crates/e2e-move-tests/src/tests/code.rs new file mode 100644 index 00000000..dd06c51d --- /dev/null +++ b/crates/e2e-move-tests/src/tests/code.rs @@ -0,0 +1,118 @@ +use crate::MoveHarness; +use initia_move_natives::code::UpgradePolicy; +use move_core_types::account_address::AccountAddress; + +fn setup_harness() -> (MoveHarness, AccountAddress) { + let mut h = MoveHarness::new(); + let acc = AccountAddress::from_hex_literal("0x9999").unwrap(); + h.initialize(); + (h, acc) +} + +fn publish_and_commit( + h: &mut MoveHarness, + acc: &AccountAddress, + path: &str, + policy: UpgradePolicy, +) { + let output = h + .publish_package(acc, path, policy) + .expect("should succeed"); + h.commit(output, true); +} + +fn view_string(h: &mut MoveHarness, path: &str) -> String { + let view_function = h.create_view_function(str::parse(path).unwrap(), vec![], vec![]); + + h.run_view_function(view_function).expect("should succeed") +} + +#[test] +fn test_simple_publish_compatible() { + let (mut h, acc) = setup_harness(); + publish_and_commit( + &mut h, + &acc, + "src/tests/string_viewer.data/viewer", + UpgradePolicy::Compatible, + ); + + let view_output = view_string(&mut h, "0x9999::string_viewer::view_string"); + assert_eq!("\"Hello, World!\"".to_string(), view_output); + + publish_and_commit( + &mut h, + &acc, + "src/tests/string_viewer.data/viewer2", + UpgradePolicy::Compatible, + ); + + let view_output = view_string(&mut h, "0x9999::string_viewer2::view_my_string"); + assert_eq!("\"Hello, World!\"".to_string(), view_output); +} + +#[test] +fn test_simple_publish_immutable() { + let (mut h, acc) = setup_harness(); + publish_and_commit( + &mut h, + &acc, + "src/tests/string_viewer.data/viewer", + UpgradePolicy::Immutable, + ); + + let view_output = view_string(&mut h, "0x9999::string_viewer::view_string"); + assert_eq!("\"Hello, World!\"".to_string(), view_output); + + publish_and_commit( + &mut h, + &acc, + "src/tests/string_viewer.data/viewer2", + UpgradePolicy::Immutable, + ); + + let view_output = view_string(&mut h, "0x9999::string_viewer2::view_my_string"); + assert_eq!("\"Hello, World!\"".to_string(), view_output); +} + +#[test] +fn test_publish_immutable_referring_compatible() { + let (mut h, acc) = setup_harness(); + publish_and_commit( + &mut h, + &acc, + "src/tests/string_viewer.data/viewer", + UpgradePolicy::Compatible, + ); + + let view_output = view_string(&mut h, "0x9999::string_viewer::view_string"); + assert_eq!("\"Hello, World!\"".to_string(), view_output); + + let path = "src/tests/string_viewer.data/viewer2"; + h.publish_package(&acc, path, UpgradePolicy::Immutable) + .expect_err("expected an error during package publishing"); +} + +#[test] +fn test_publish_compatible_referring_immutable() { + let (mut h, acc) = setup_harness(); + publish_and_commit( + &mut h, + &acc, + "src/tests/string_viewer.data/viewer", + UpgradePolicy::Immutable, + ); + + let view_output = view_string(&mut h, "0x9999::string_viewer::view_string"); + assert_eq!("\"Hello, World!\"".to_string(), view_output); + + publish_and_commit( + &mut h, + &acc, + "src/tests/string_viewer.data/viewer2", + UpgradePolicy::Compatible, + ); + + let view_output = view_string(&mut h, "0x9999::string_viewer2::view_my_string"); + assert_eq!("\"Hello, World!\"".to_string(), view_output); +} diff --git a/crates/e2e-move-tests/src/tests/cosmos.rs b/crates/e2e-move-tests/src/tests/cosmos.rs index f0c1d2fb..9877ddc1 100644 --- a/crates/e2e-move-tests/src/tests/cosmos.rs +++ b/crates/e2e-move-tests/src/tests/cosmos.rs @@ -2,6 +2,7 @@ use core::str; use crate::tests::common::ExpectedOutput; use crate::MoveHarness; +use initia_move_natives::code::UpgradePolicy; use initia_move_types::cosmos::{CosmosCallback, CosmosMessage}; use move_core_types::account_address::AccountAddress; use move_core_types::language_storage::TypeTag; @@ -63,7 +64,9 @@ fn run_tests(tests: Vec) { h.initialize(); // publish package - let output = h.publish_package(&acc, path).expect("should success"); + let output = h + .publish_package(&acc, path, UpgradePolicy::Compatible) + .expect("should success"); h.commit(output, true); for (sender, entry, ty_args, args, exp_output) in tests { diff --git a/crates/e2e-move-tests/src/tests/infinite_loop.rs b/crates/e2e-move-tests/src/tests/infinite_loop.rs index 6dd55c52..b703a065 100644 --- a/crates/e2e-move-tests/src/tests/infinite_loop.rs +++ b/crates/e2e-move-tests/src/tests/infinite_loop.rs @@ -1,4 +1,5 @@ use crate::MoveHarness; +use initia_move_natives::code::UpgradePolicy; use move_core_types::account_address::AccountAddress; use move_core_types::vm_status::StatusCode; @@ -12,7 +13,9 @@ fn empty_while_loop() { h.initialize(); - let output = h.publish_package(&acc, path).expect("should success"); + let output = h + .publish_package(&acc, path, UpgradePolicy::Compatible) + .expect("should success"); h.commit(output, true); let err = h diff --git a/crates/e2e-move-tests/src/tests/max_loop_depth.rs b/crates/e2e-move-tests/src/tests/max_loop_depth.rs index da52470b..629093f5 100644 --- a/crates/e2e-move-tests/src/tests/max_loop_depth.rs +++ b/crates/e2e-move-tests/src/tests/max_loop_depth.rs @@ -1,4 +1,5 @@ use crate::MoveHarness; +use initia_move_natives::code::UpgradePolicy; use move_core_types::{account_address::AccountAddress, vm_status::StatusCode}; #[test] @@ -8,7 +9,9 @@ fn module_loop_depth_at_limit() { let mut h = MoveHarness::new(); h.initialize(); - let _ = h.publish_package(&acc, path).expect("should success"); + let _ = h + .publish_package(&acc, path, UpgradePolicy::Compatible) + .expect("should success"); } #[test] @@ -17,6 +20,8 @@ fn module_loop_depth_just_above_limit() { let path = "src/tests/max_loop_depth.data/pack-bad"; let mut h = MoveHarness::new(); h.initialize(); - let status = h.publish_package(&acc, path).expect_err("should error"); + let status = h + .publish_package(&acc, path, UpgradePolicy::Compatible) + .expect_err("should error"); assert!(status.status_code() == StatusCode::LOOP_MAX_DEPTH_REACHED); } diff --git a/crates/e2e-move-tests/src/tests/memory_quota.rs b/crates/e2e-move-tests/src/tests/memory_quota.rs index b4303f9f..b1ac3d95 100644 --- a/crates/e2e-move-tests/src/tests/memory_quota.rs +++ b/crates/e2e-move-tests/src/tests/memory_quota.rs @@ -1,4 +1,5 @@ use crate::MoveHarness; +use initia_move_natives::code::UpgradePolicy; use move_core_types::account_address::AccountAddress; use move_core_types::vm_status::StatusCode; @@ -9,7 +10,9 @@ fn clone_large_vectors() { let mut h = MoveHarness::new(); h.initialize(); - let output = h.publish_package(&acc, path).expect("should success"); + let output = h + .publish_package(&acc, path, UpgradePolicy::Compatible) + .expect("should success"); h.commit(output, true); let _ = h @@ -41,7 +44,9 @@ fn add_vec_to_table() { // Load the code h.initialize(); - let output = h.publish_package(&acc, path).expect("should success"); + let output = h + .publish_package(&acc, path, UpgradePolicy::Compatible) + .expect("should success"); h.commit(output, true); let status = h diff --git a/crates/e2e-move-tests/src/tests/mod.rs b/crates/e2e-move-tests/src/tests/mod.rs index 00e155b9..76711ba2 100644 --- a/crates/e2e-move-tests/src/tests/mod.rs +++ b/crates/e2e-move-tests/src/tests/mod.rs @@ -1,5 +1,6 @@ mod args; mod cache; +mod code; mod common; mod cosmos; mod infinite_loop; diff --git a/crates/e2e-move-tests/src/tests/output.rs b/crates/e2e-move-tests/src/tests/output.rs index 50b364ce..d3605227 100644 --- a/crates/e2e-move-tests/src/tests/output.rs +++ b/crates/e2e-move-tests/src/tests/output.rs @@ -1,5 +1,6 @@ use crate::tests::common::ExpectedOutput; use crate::MoveHarness; +use initia_move_natives::code::UpgradePolicy; use move_core_types::account_address::AccountAddress; use move_core_types::language_storage::TypeTag; use move_core_types::vm_status::VMStatus; @@ -22,7 +23,7 @@ fn run_tests(tests: Vec) { // publish std coin let output = h - .publish_package(&minter_addr, path) + .publish_package(&minter_addr, path, UpgradePolicy::Compatible) .expect("should success"); h.commit(output, true); diff --git a/crates/e2e-move-tests/src/tests/std_coin.rs b/crates/e2e-move-tests/src/tests/std_coin.rs index 11ca7c42..b4921170 100644 --- a/crates/e2e-move-tests/src/tests/std_coin.rs +++ b/crates/e2e-move-tests/src/tests/std_coin.rs @@ -1,5 +1,6 @@ use crate::tests::common::ExpectedOutput; use crate::MoveHarness; +use initia_move_natives::code::UpgradePolicy; use move_core_types::account_address::AccountAddress; use move_core_types::language_storage::TypeTag; use move_core_types::vm_status::VMStatus; @@ -32,7 +33,7 @@ fn run_tests(tests: Vec) { // publish std coin let output = h - .publish_package(&minter_addr, path) + .publish_package(&minter_addr, path, UpgradePolicy::Compatible) .expect("should success"); h.commit(output, true); diff --git a/crates/e2e-move-tests/src/tests/string_viewer.data/viewer/Move.toml b/crates/e2e-move-tests/src/tests/string_viewer.data/viewer/Move.toml new file mode 100644 index 00000000..3ff69c9f --- /dev/null +++ b/crates/e2e-move-tests/src/tests/string_viewer.data/viewer/Move.toml @@ -0,0 +1,10 @@ +[package] +name = "StringViewer" +version = "0.0.0" + +[dependencies] +InitiaStdlib = { local = "../../../../../../precompile/modules/initia_stdlib" } + +[addresses] +std = "0x1" +publisher = "0x9999" diff --git a/crates/e2e-move-tests/src/tests/string_viewer.data/viewer/sources/StringViewer.move b/crates/e2e-move-tests/src/tests/string_viewer.data/viewer/sources/StringViewer.move new file mode 100644 index 00000000..150177ad --- /dev/null +++ b/crates/e2e-move-tests/src/tests/string_viewer.data/viewer/sources/StringViewer.move @@ -0,0 +1,8 @@ +module publisher::string_viewer { + use std::string; + + #[view] + public fun view_string(): string::String { + string::utf8(b"Hello, World!") + } +} diff --git a/crates/e2e-move-tests/src/tests/string_viewer.data/viewer2/Move.toml b/crates/e2e-move-tests/src/tests/string_viewer.data/viewer2/Move.toml new file mode 100644 index 00000000..0a73ab8b --- /dev/null +++ b/crates/e2e-move-tests/src/tests/string_viewer.data/viewer2/Move.toml @@ -0,0 +1,11 @@ +[package] +name = "StringViewer2" +version = "0.0.0" + +[dependencies] +InitiaStdlib = { local = "../../../../../../precompile/modules/initia_stdlib" } +StringViewer = { local = "../viewer" } + +[addresses] +std = "0x1" +publisher = "0x9999" diff --git a/crates/e2e-move-tests/src/tests/string_viewer.data/viewer2/sources/StringViewer2.move b/crates/e2e-move-tests/src/tests/string_viewer.data/viewer2/sources/StringViewer2.move new file mode 100644 index 00000000..623c076e --- /dev/null +++ b/crates/e2e-move-tests/src/tests/string_viewer.data/viewer2/sources/StringViewer2.move @@ -0,0 +1,9 @@ +module publisher::string_viewer2 { + use std::string; + use publisher::string_viewer; + + #[view] + public fun view_my_string(): string::String { + string_viewer::view_string() + } +} diff --git a/crates/e2e-move-tests/src/tests/table.rs b/crates/e2e-move-tests/src/tests/table.rs index 9452e448..e16bdef5 100644 --- a/crates/e2e-move-tests/src/tests/table.rs +++ b/crates/e2e-move-tests/src/tests/table.rs @@ -1,6 +1,7 @@ use crate::test_utils::generate_account; use crate::tests::common::{ExpectedOutput, ExpectedOutputItem}; use crate::MoveHarness; +use initia_move_natives::code::UpgradePolicy; use move_core_types::account_address::AccountAddress; use move_core_types::language_storage::TypeTag; use move_core_types::vm_status::VMStatus; @@ -22,7 +23,9 @@ fn run_tests(tests: Vec) { h.initialize(); // publish table data - let output = h.publish_package(&test_addr, path).expect("should success"); + let output = h + .publish_package(&test_addr, path, UpgradePolicy::Compatible) + .expect("should success"); h.commit(output, true); for (senders, entry, ty_args, args, exp_output) in tests { diff --git a/crates/e2e-move-tests/src/tests/view_output.rs b/crates/e2e-move-tests/src/tests/view_output.rs index 56487865..382d94b6 100644 --- a/crates/e2e-move-tests/src/tests/view_output.rs +++ b/crates/e2e-move-tests/src/tests/view_output.rs @@ -1,6 +1,7 @@ use std::str::FromStr; use crate::MoveHarness; +use initia_move_natives::code::UpgradePolicy; use initia_move_types::json_event::JsonEvents; use initia_move_types::view_function::ViewFunction; use move_core_types::identifier::Identifier; @@ -18,7 +19,7 @@ fn test_view_output() { // publish std coin let output = h - .publish_package(&deployer_addr, path) + .publish_package(&deployer_addr, path, UpgradePolicy::Compatible) .expect("should success"); h.commit(output, true); diff --git a/crates/json/Cargo.toml b/crates/json/Cargo.toml index 91476571..0e9b78e3 100644 --- a/crates/json/Cargo.toml +++ b/crates/json/Cargo.toml @@ -14,11 +14,13 @@ default = [] [dependencies] initia-move-types = { workspace = true } +initia-move-storage = { workspace = true } ## Move Dependencies move-core-types = { workspace = true } move-vm-types = { workspace = true } move-binary-format = { workspace = true } +move-vm-runtime = { workspace = true } bigdecimal = { workspace = true } serde_json = { workspace = true } @@ -31,5 +33,3 @@ smallbitvec = { workspace = true } triomphe = { workspace = true } bytes = { workspace = true } anyhow = { workspace = true } - -initia-move-storage = { workspace = true } diff --git a/crates/json/src/json_to_move.rs b/crates/json/src/json_to_move.rs index dcb3800b..c4609b17 100644 --- a/crates/json/src/json_to_move.rs +++ b/crates/json/src/json_to_move.rs @@ -6,6 +6,7 @@ use bigdecimal::{ BigDecimal, Signed, }; use bytes::Bytes; +use initia_move_storage::{initia_storage::InitiaStorage, state_view::StateView}; use move_binary_format::errors::{PartialVMResult, VMResult}; use move_core_types::{ account_address::AccountAddress, @@ -15,6 +16,7 @@ use move_core_types::{ u256::U256, value::{MoveTypeLayout, MoveValue}, }; +use move_vm_runtime::ModuleStorage; use move_vm_types::{ loaded_data::runtime_types::{ StructNameIndex, StructType, @@ -22,21 +24,25 @@ use move_vm_types::{ }, resolver::ResourceResolver, }; - use serde_json::Value as JSONValue; use crate::errors::{deserialization_error, deserialization_error_with_msg}; pub trait StructResolver { - fn get_struct_type(&self, index: StructNameIndex) -> Option>; - fn get_type_tag(&self, ty: &Type) -> VMResult; + fn get_struct_type( + &self, + index: StructNameIndex, + module_storage: &impl ModuleStorage, + ) -> Option>; + fn type_to_type_tag(&self, ty: &Type, module_storage: &impl ModuleStorage) + -> VMResult; } // deserialize json argument to JSONValue and convert to MoveValue, // and then do bcs serialization. -pub fn deserialize_json_args( - struct_resolver: &S, - resource_resolver: &R, +pub fn deserialize_json_args( + code_storage: &InitiaStorage, + struct_resolver: &impl StructResolver, ty: &Type, arg: &[u8], ) -> VMResult> { @@ -52,14 +58,14 @@ pub fn deserialize_json_args( serde_json::from_slice(arg).map_err(deserialization_error_with_msg)?; let move_val = - convert_json_value_to_move_value(struct_resolver, resource_resolver, ty, json_val, 1)?; + convert_json_value_to_move_value(code_storage, struct_resolver, ty, json_val, 1)?; bcs::to_bytes(&move_val).map_err(deserialization_error_with_msg) } // convert JSONValue to MoveValue. -fn convert_json_value_to_move_value( - struct_resolver: &S, - resource_resolver: &R, +fn convert_json_value_to_move_value( + code_storage: &InitiaStorage, + struct_resolver: &impl StructResolver, ty: &Type, json_val: JSONValue, depth: usize, @@ -122,8 +128,8 @@ fn convert_json_value_to_move_value( let mut vec = Vec::new(); for json_val in json_vals { vec.push(convert_json_value_to_move_value( + code_storage, struct_resolver, - resource_resolver, ty, json_val, depth + 1, @@ -133,7 +139,7 @@ fn convert_json_value_to_move_value( } Struct { idx, .. } => { let st = struct_resolver - .get_struct_type(*idx) + .get_struct_type(*idx, code_storage) .ok_or_else(deserialization_error)?; let full_name = format!("{}::{}", st.module.short_str_lossless(), st.name); match full_name.as_str() { @@ -216,7 +222,7 @@ fn convert_json_value_to_move_value( } let st = struct_resolver - .get_struct_type(*idx) + .get_struct_type(*idx, code_storage) .ok_or_else(deserialization_error)?; let ty = ty_args.first().ok_or_else(deserialization_error)?; let full_name = format!("{}::{}", st.module.short_str_lossless(), st.name); @@ -227,8 +233,8 @@ fn convert_json_value_to_move_value( } return Ok(MoveValue::Vector(vec![convert_json_value_to_move_value( + code_storage, struct_resolver, - resource_resolver, ty, json_val, depth + 1, @@ -243,7 +249,7 @@ fn convert_json_value_to_move_value( // verify a object // 1) address is holding object core resource // 2) object is holding inner type resource - verify_object(struct_resolver, resource_resolver, addr, ty)?; + verify_object(code_storage, struct_resolver, addr, ty)?; MoveValue::Address(addr) } @@ -259,12 +265,13 @@ fn convert_json_value_to_move_value( } // verify object address is holding object core and inner type resources. -fn verify_object( - struct_resolver: &S, - resource_resolver: &R, +fn verify_object( + code_storage: &InitiaStorage, + struct_resolver: &impl StructResolver, addr: AccountAddress, inner_type: &Type, ) -> VMResult<()> { + let resource_resolver = code_storage.state_view_impl(); // verify a object hold object core if resource_resolver .get_resource_bytes_with_metadata_and_layout( @@ -287,8 +294,9 @@ fn verify_object( // verify a object hold inner type let inner_type_tag = struct_resolver - .get_type_tag(inner_type) + .type_to_type_tag(inner_type, code_storage) .map_err(deserialization_error_with_msg)?; + let inner_type_st = if let TypeTag::Struct(inner_type_st) = inner_type_tag { inner_type_st } else { @@ -331,7 +339,9 @@ mod json_arg_testing { use bigdecimal::FromPrimitive; use bytes::Bytes; - use initia_move_storage::{state_view::StateView, state_view_impl::StateViewImpl}; + use initia_move_storage::{ + module_cache::InitiaModuleCache, script_cache::InitiaScriptCache, state_view::StateView, + }; use initia_move_types::access_path::{AccessPath, DataPath}; use move_binary_format::{ errors::{Location, PartialVMError}, @@ -343,11 +353,14 @@ mod json_arg_testing { language_storage::{ModuleId, StructTag}, vm_status::StatusCode, }; + use move_vm_runtime::RuntimeEnvironment; use move_vm_types::loaded_data::runtime_types::AbilityInfo; use smallbitvec::SmallBitVec; use super::*; + const TEST_CACHE_CAPACITY: usize = 100; + struct MockState { pub map: BTreeMap, Vec>, pub structs: BTreeMap>, @@ -363,24 +376,35 @@ mod json_arg_testing { } impl StructResolver for MockState { - fn get_struct_type(&self, index: StructNameIndex) -> Option> { + fn get_struct_type( + &self, + index: StructNameIndex, + _module_storage: &impl ModuleStorage, + ) -> Option> { self.structs.get(&index).cloned() } - fn get_type_tag(&self, ty: &Type) -> VMResult { + fn type_to_type_tag( + &self, + ty: &Type, + module_storage: &impl ModuleStorage, + ) -> VMResult { match ty { Struct { idx, .. } => { - let st = self.structs.get(idx).ok_or_else(|| { - PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR) - .finish(Location::Undefined) - })?; + let struct_ty = + self.get_struct_type(*idx, module_storage).ok_or_else(|| { + PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR) + .finish(Location::Undefined) + })?; Ok(TypeTag::Struct(Box::new(StructTag { - address: st.module.address, - module: st.module.name.clone(), - name: st.name.clone(), + address: struct_ty.module.address, + module: struct_ty.module.name.clone(), + name: struct_ty.name.clone(), type_args: vec![], }))) } - _ => unimplemented!(), + _ => { + Err(PartialVMError::new(StatusCode::TYPE_MISMATCH).finish(Location::Undefined)) + } } } } @@ -395,138 +419,202 @@ mod json_arg_testing { #[test] fn test_deserialize_json_args_u8() { let mock_state = mock_state(); - let state_view = StateViewImpl::new(&mock_state); + let runtime_environment = RuntimeEnvironment::new(vec![]); + let script_cache = InitiaScriptCache::new(TEST_CACHE_CAPACITY); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + let code_storage = InitiaStorage::new( + &mock_state, + &runtime_environment, + script_cache, + module_cache, + ); let ty = Type::U8; let arg = b"123"; - let result = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap(); + let result = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap(); assert_eq!(result, bcs::to_bytes(&123u8).unwrap()); // invalid negative let arg = b"-123"; - _ = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap_err(); + _ = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap_err(); // invalid decimal let arg = b"123.4567"; - _ = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap_err(); + _ = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap_err(); } #[test] fn test_deserialize_json_args_u16() { let mock_state = mock_state(); - let state_view = StateViewImpl::new(&mock_state); + let runtime_environment = RuntimeEnvironment::new(vec![]); + let script_cache = InitiaScriptCache::new(TEST_CACHE_CAPACITY); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + let code_storage = InitiaStorage::new( + &mock_state, + &runtime_environment, + script_cache, + module_cache, + ); let ty = Type::U16; let arg = b"123"; - let result = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap(); + let result = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap(); assert_eq!(result, bcs::to_bytes(&123u16).unwrap()); // invalid negative let arg = b"-123"; - _ = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap_err(); + _ = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap_err(); // invalid decimal let arg = b"123.4567"; - _ = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap_err(); + _ = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap_err(); } #[test] fn test_deserialize_json_args_u32() { let mock_state = mock_state(); - let state_view = StateViewImpl::new(&mock_state); + let runtime_environment = RuntimeEnvironment::new(vec![]); + let script_cache = InitiaScriptCache::new(TEST_CACHE_CAPACITY); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + let code_storage = InitiaStorage::new( + &mock_state, + &runtime_environment, + script_cache, + module_cache, + ); let ty = Type::U32; let arg = b"123"; - let result = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap(); + let result = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap(); assert_eq!(result, bcs::to_bytes(&123u32).unwrap()); // invalid negative let arg = b"-123"; - _ = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap_err(); + _ = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap_err(); // invalid decimal let arg = b"123.4567"; - _ = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap_err(); + _ = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap_err(); } #[test] fn test_deserialize_json_args_u64() { let mock_state = mock_state(); - let state_view = StateViewImpl::new(&mock_state); + let runtime_environment = RuntimeEnvironment::new(vec![]); + let script_cache = InitiaScriptCache::new(TEST_CACHE_CAPACITY); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + let code_storage = InitiaStorage::new( + &mock_state, + &runtime_environment, + script_cache, + module_cache, + ); let ty = Type::U64; let arg = b"\"123\""; - let result = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap(); + let result = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap(); assert_eq!(result, bcs::to_bytes(&123u64).unwrap()); // invalid negative let arg = b"\"-123\""; - _ = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap_err(); + _ = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap_err(); // invalid decimal let arg = b"\"123.4567\""; - _ = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap_err(); + _ = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap_err(); } #[test] fn test_deserialize_json_args_u128() { let mock_state = mock_state(); - let state_view = StateViewImpl::new(&mock_state); + let runtime_environment = RuntimeEnvironment::new(vec![]); + let script_cache = InitiaScriptCache::new(TEST_CACHE_CAPACITY); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + let code_storage = InitiaStorage::new( + &mock_state, + &runtime_environment, + script_cache, + module_cache, + ); let ty = Type::U128; let arg = b"\"123\""; - let result = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap(); + let result = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap(); assert_eq!(result, bcs::to_bytes(&123u128).unwrap()); // invalid negative let arg = b"\"-123\""; - _ = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap_err(); + _ = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap_err(); // invalid decimal let arg = b"\"123.4567\""; - _ = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap_err(); + _ = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap_err(); } #[test] fn test_deserialize_json_args_u256() { let mock_state = mock_state(); - let state_view = StateViewImpl::new(&mock_state); + let runtime_environment = RuntimeEnvironment::new(vec![]); + let script_cache = InitiaScriptCache::new(TEST_CACHE_CAPACITY); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + let code_storage = InitiaStorage::new( + &mock_state, + &runtime_environment, + script_cache, + module_cache, + ); let ty = Type::U256; let arg = b"\"123\""; - let result = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap(); + let result = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap(); assert_eq!(result, bcs::to_bytes(&U256::from(123u128)).unwrap()); // invalid negative let arg = b"\"-123\""; - _ = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap_err(); + _ = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap_err(); // invalid decimal let arg = b"\"123.4567\""; - _ = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap_err(); + _ = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap_err(); } #[test] fn test_deserialize_json_args_bool() { let mock_state = mock_state(); - let state_view = StateViewImpl::new(&mock_state); + let runtime_environment = RuntimeEnvironment::new(vec![]); + let script_cache = InitiaScriptCache::new(TEST_CACHE_CAPACITY); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + let code_storage = InitiaStorage::new( + &mock_state, + &runtime_environment, + script_cache, + module_cache, + ); let ty = Type::Bool; let arg = b"true"; - let result = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap(); + let result = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap(); assert_eq!(result, bcs::to_bytes(&true).unwrap()); } #[test] fn test_deserialize_json_args_address() { let mock_state = mock_state(); - let state_view = StateViewImpl::new(&mock_state); + let runtime_environment = RuntimeEnvironment::new(vec![]); + let script_cache = InitiaScriptCache::new(TEST_CACHE_CAPACITY); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + let code_storage = InitiaStorage::new( + &mock_state, + &runtime_environment, + script_cache, + module_cache, + ); let ty = Type::Address; let arg = b"\"0x1\""; - let result = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap(); + let result = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap(); assert_eq!( result, bcs::to_bytes(&"0x1".parse::().unwrap()).unwrap() @@ -536,27 +624,43 @@ mod json_arg_testing { #[test] fn test_deserialize_json_args_vec_u8() { let mock_state = mock_state(); - let state_view = StateViewImpl::new(&mock_state); + let runtime_environment = RuntimeEnvironment::new(vec![]); + let script_cache = InitiaScriptCache::new(TEST_CACHE_CAPACITY); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + let code_storage = InitiaStorage::new( + &mock_state, + &runtime_environment, + script_cache, + module_cache, + ); let ty = Type::Vector(triomphe::Arc::new(Type::U8)); let arg = b"[0, 1, 2, 3]"; - let result = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap(); + let result = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap(); assert_eq!(result, bcs::to_bytes(&vec![0u8, 1u8, 2u8, 3u8]).unwrap()); // hex string to vector let arg = b"\"00010203\""; - let result = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap(); + let result = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap(); assert_eq!(result, bcs::to_bytes(&vec![0u8, 1u8, 2u8, 3u8]).unwrap()); } #[test] fn test_deserialize_json_args_vec_address() { let mock_state = mock_state(); - let state_view = StateViewImpl::new(&mock_state); + let runtime_environment = RuntimeEnvironment::new(vec![]); + let script_cache = InitiaScriptCache::new(TEST_CACHE_CAPACITY); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + let code_storage = InitiaStorage::new( + &mock_state, + &runtime_environment, + script_cache, + module_cache, + ); let ty = Type::Vector(triomphe::Arc::new(Type::Address)); let arg = b"[\"0x1\", \"0x2\"]"; - let result = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap(); + let result = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap(); assert_eq!( result, bcs::to_bytes(&vec![ @@ -568,7 +672,7 @@ mod json_arg_testing { // invalid inner addresss let arg = b"[\"0xgg\"]"; - _ = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap_err(); + _ = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap_err(); } pub fn for_test(module_name: &str, name: &str) -> StructType { @@ -588,24 +692,34 @@ mod json_arg_testing { #[test] fn test_deserialize_json_args_string() { let mut mock_state = mock_state(); + mock_state .structs .insert(StructNameIndex(0), Arc::new(for_test("string", "String"))); - let state_view = StateViewImpl::new(&mock_state); - let ty = Type::Struct { idx: StructNameIndex(0), ability: AbilityInfo::struct_(AbilitySet::ALL), }; let arg = b"\"hello\""; - let result = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap(); + let runtime_environment = RuntimeEnvironment::new(vec![]); + let script_cache = InitiaScriptCache::new(TEST_CACHE_CAPACITY); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + let code_storage = InitiaStorage::new( + &mock_state, + &runtime_environment, + script_cache, + module_cache, + ); + + let result = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap(); assert_eq!(result, bcs::to_bytes("hello").unwrap()); } #[test] fn test_deserialize_json_args_object() { let mut mock_state = mock_state(); + mock_state .structs .insert(StructNameIndex(0), Arc::new(for_test("object", "Object"))); @@ -663,14 +777,23 @@ mod json_arg_testing { let hex_addr = format!("\"{}\"", obj_addr.to_hex_literal()); let arg = hex_addr.as_bytes(); + let runtime_environment = RuntimeEnvironment::new(vec![]); + let script_cache = InitiaScriptCache::new(TEST_CACHE_CAPACITY); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + let code_storage = InitiaStorage::new( + &mock_state, + &runtime_environment, + script_cache, + module_cache, + ); + // valid object address - let state_view = StateViewImpl::new(&mock_state); - let result = deserialize_json_args(&mock_state, &state_view, &ty, arg); + let result = deserialize_json_args(&code_storage, &mock_state, &ty, arg); assert_eq!(result.unwrap(), bcs::to_bytes(&obj_addr).unwrap()); // invalid object address let wrong_object_addr_arg = b"\"0x1\""; - _ = deserialize_json_args(&mock_state, &state_view, &ty, wrong_object_addr_arg) + _ = deserialize_json_args(&code_storage, &mock_state, &ty, wrong_object_addr_arg) .unwrap_err(); // invalid inner type @@ -682,11 +805,11 @@ mod json_arg_testing { ability: AbilityInfo::struct_(AbilitySet::singleton(Ability::Key)), }]), }; - _ = deserialize_json_args(&mock_state, &state_view, &wrong_inner_ty, arg).unwrap_err(); + _ = deserialize_json_args(&code_storage, &mock_state, &wrong_inner_ty, arg).unwrap_err(); // invalid address let arg = b"\"0xgg\""; - _ = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap_err(); + _ = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap_err(); } #[test] @@ -696,15 +819,24 @@ mod json_arg_testing { .structs .insert(StructNameIndex(0), Arc::new(for_test("option", "Option"))); - let state_view = StateViewImpl::new(&mock_state); - let ty = Type::StructInstantiation { idx: StructNameIndex(0), ty_args: triomphe::Arc::new(vec![Type::Address]), ability: AbilityInfo::struct_(AbilitySet::ALL), }; let arg = b"\"0x1\""; - let result = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap(); + + let runtime_environment = RuntimeEnvironment::new(vec![]); + let script_cache = InitiaScriptCache::new(TEST_CACHE_CAPACITY); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + let code_storage = InitiaStorage::new( + &mock_state, + &runtime_environment, + script_cache, + module_cache, + ); + + let result = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap(); assert_eq!( result, bcs::to_bytes(&vec!["0x1".parse::().unwrap()]).unwrap() @@ -712,7 +844,7 @@ mod json_arg_testing { // invalid inner value let arg = b"\"0xgg\""; - _ = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap_err(); + _ = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap_err(); } #[test] @@ -722,15 +854,24 @@ mod json_arg_testing { .structs .insert(StructNameIndex(0), Arc::new(for_test("option", "Option"))); - let state_view = StateViewImpl::new(&mock_state); - let ty = Type::StructInstantiation { idx: StructNameIndex(0), ty_args: triomphe::Arc::new(vec![Type::Address]), ability: AbilityInfo::struct_(AbilitySet::ALL), }; let arg = b"null"; - let result = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap(); + + let runtime_environment = RuntimeEnvironment::new(vec![]); + let script_cache = InitiaScriptCache::new(TEST_CACHE_CAPACITY); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + let code_storage = InitiaStorage::new( + &mock_state, + &runtime_environment, + script_cache, + module_cache, + ); + + let result = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap(); assert_eq!( result, bcs::to_bytes::>(&vec![]).unwrap() @@ -745,14 +886,22 @@ mod json_arg_testing { Arc::new(for_test("fixed_point32", "FixedPoint32")), ); - let state_view = StateViewImpl::new(&mock_state); - let ty = Type::Struct { idx: StructNameIndex(0), ability: AbilityInfo::struct_(AbilitySet::ALL), }; let arg = b"\"123.4567\""; - let result = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap(); + let runtime_environment = RuntimeEnvironment::new(vec![]); + let script_cache = InitiaScriptCache::new(TEST_CACHE_CAPACITY); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + let code_storage = InitiaStorage::new( + &mock_state, + &runtime_environment, + script_cache, + module_cache, + ); + + let result = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap(); assert_eq!( result, @@ -761,7 +910,7 @@ mod json_arg_testing { // invalid negative let arg = b"\"-123.4567\""; - _ = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap_err(); + _ = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap_err(); } #[test] @@ -772,14 +921,23 @@ mod json_arg_testing { Arc::new(for_test("fixed_point64", "FixedPoint64")), ); - let state_view = StateViewImpl::new(&mock_state); - let ty = Type::Struct { idx: StructNameIndex(0), ability: AbilityInfo::struct_(AbilitySet::ALL), }; let arg = b"\"123.4567\""; - let result = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap(); + + let runtime_environment = RuntimeEnvironment::new(vec![]); + let script_cache = InitiaScriptCache::new(TEST_CACHE_CAPACITY); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + let code_storage = InitiaStorage::new( + &mock_state, + &runtime_environment, + script_cache, + module_cache, + ); + + let result = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap(); assert_eq!( result, @@ -788,7 +946,7 @@ mod json_arg_testing { // invalid negative let arg = b"\"-123.4567\""; - _ = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap_err(); + _ = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap_err(); } #[test] @@ -798,14 +956,22 @@ mod json_arg_testing { .structs .insert(StructNameIndex(0), Arc::new(for_test("biguint", "BigUint"))); - let state_view = StateViewImpl::new(&mock_state); - let ty = Type::Struct { idx: StructNameIndex(0), ability: AbilityInfo::struct_(AbilitySet::ALL), }; let arg = b"\"1234567\""; - let result = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap(); + let runtime_environment = RuntimeEnvironment::new(vec![]); + let script_cache = InitiaScriptCache::new(TEST_CACHE_CAPACITY); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + let code_storage = InitiaStorage::new( + &mock_state, + &runtime_environment, + script_cache, + module_cache, + ); + + let result = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap(); assert_eq!( result, @@ -814,7 +980,7 @@ mod json_arg_testing { // invalid negative let arg = b"\"-1234567\""; - _ = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap_err(); + _ = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap_err(); } #[test] @@ -825,14 +991,22 @@ mod json_arg_testing { Arc::new(for_test("bigdecimal", "BigDecimal")), ); - let state_view = StateViewImpl::new(&mock_state); - let ty = Type::Struct { idx: StructNameIndex(0), ability: AbilityInfo::struct_(AbilitySet::ALL), }; let arg = b"\"123.4567\""; - let result = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap(); + let runtime_environment = RuntimeEnvironment::new(vec![]); + let script_cache = InitiaScriptCache::new(TEST_CACHE_CAPACITY); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + let code_storage = InitiaStorage::new( + &mock_state, + &runtime_environment, + script_cache, + module_cache, + ); + + let result = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap(); assert_eq!( result, @@ -846,6 +1020,6 @@ mod json_arg_testing { // invalid negative let arg = b"\"-123.4567\""; - _ = deserialize_json_args(&mock_state, &state_view, &ty, arg).unwrap_err(); + _ = deserialize_json_args(&code_storage, &mock_state, &ty, arg).unwrap_err(); } } diff --git a/crates/natives/src/code.rs b/crates/natives/src/code.rs index 331a0aab..8c764ccc 100644 --- a/crates/natives/src/code.rs +++ b/crates/natives/src/code.rs @@ -1,5 +1,4 @@ use crate::{ - helpers::get_string, interface::{ RawSafeNative, SafeNativeBuilder, SafeNativeContext, SafeNativeError, SafeNativeResult, }, @@ -9,20 +8,37 @@ use better_any::{Tid, TidAble}; use initia_move_types::module::ModuleBundle; use move_core_types::{account_address::AccountAddress, gas_algebra::NumBytes}; use move_vm_runtime::native_functions::NativeFunction; -use move_vm_types::{ - loaded_data::runtime_types::Type, - values::{Struct, Value}, -}; +use move_vm_types::{loaded_data::runtime_types::Type, values::Value}; use serde::{Deserialize, Serialize}; use smallvec::{smallvec, SmallVec}; use std::collections::VecDeque; -/// Whether a compatibility check should be performed for upgrades. The check only passes if -/// a new module has (a) the same public functions (b) for existing resources, no layout change. -const _UPGRADE_POLICY_COMPATIBLE: u8 = 1; +#[derive(Clone, Copy, Debug, Serialize, Deserialize, Eq, PartialEq)] +pub enum UpgradePolicy { + /// Whether a compatibility check should be performed for upgrades. The check only passes if + /// a new module has (a) the same public functions (b) for existing resources, no layout change. + Compatible = 1, + /// Whether the modules in the package are immutable and cannot be upgraded. + Immutable = 2, +} + +impl TryFrom for UpgradePolicy { + type Error = (); -/// Whether the modules in the package are immutable and cannot be upgraded. -const _UPGRADE_POLICY_IMMUTABLE: u8 = 2; + fn try_from(value: u8) -> Result { + match value { + 1 => Ok(UpgradePolicy::Compatible), + 2 => Ok(UpgradePolicy::Immutable), + _ => Err(()), + } + } +} + +impl UpgradePolicy { + pub fn to_u8(self) -> u8 { + self as u8 + } +} /// A wrapper around the representation of a Move Option, which is a vector with 0 or 1 element. /// TODO: move this elsewhere for reuse? @@ -63,7 +79,7 @@ const ECATEGORY_INVALID_ARGUMENT: u64 = 0x1; // native errors always start from 100 const EALREADY_REQUESTED: u64 = (ECATEGORY_INVALID_ARGUMENT << 16) + 100; -const EUNABLE_TO_PARSE_STRING: u64 = (ECATEGORY_INVALID_ARGUMENT << 16) + 101; +const EINVALID_UPGRADE_POLICY: u64 = (ECATEGORY_INVALID_ARGUMENT << 16) + 101; /// The native code context. #[derive(Tid, Default)] @@ -76,9 +92,9 @@ pub struct NativeCodeContext { /// Represents a request for code publishing made from a native call and to be processed /// by the Initia VM. pub struct PublishRequest { - pub destination: AccountAddress, + pub publisher: AccountAddress, pub module_bundle: ModuleBundle, - pub expected_modules: Option>, + pub upgrade_policy: UpgradePolicy, } /*************************************************************************************************** @@ -112,6 +128,12 @@ fn native_request_publish( context.charge(gas_params.code_request_publish_base_cost)?; + let upgrade_policy = UpgradePolicy::try_from(safely_pop_arg!(arguments, u8)).map_err(|_| { + SafeNativeError::Abort { + abort_code: EINVALID_UPGRADE_POLICY, + } + })?; + let mut code: Vec> = vec![]; for module_code in safely_pop_vec_arg!(arguments, Vec) { context.charge( @@ -120,21 +142,7 @@ fn native_request_publish( code.push(module_code); } - let mut expected_modules: Vec = vec![]; - for name in safely_pop_vec_arg!(arguments, Struct) { - let str_bytes = get_string(name)?; - - context.charge( - gas_params.code_request_publish_per_byte * NumBytes::new(str_bytes.len() as u64), - )?; - expected_modules.push(String::from_utf8(str_bytes).map_err(|_| { - SafeNativeError::Abort { - abort_code: EUNABLE_TO_PARSE_STRING, - } - })?); - } - - let destination = safely_pop_arg!(arguments, AccountAddress); + let publisher = safely_pop_arg!(arguments, AccountAddress); let code_context = context.extensions_mut().get_mut::(); if code_context.requested_module_bundle.is_some() { @@ -144,9 +152,9 @@ fn native_request_publish( } code_context.requested_module_bundle = Some(PublishRequest { - destination, + publisher, module_bundle: ModuleBundle::new(code), - expected_modules: Some(expected_modules), + upgrade_policy, }); Ok(smallvec![]) diff --git a/crates/natives/src/native_functions.rs b/crates/natives/src/native_functions.rs deleted file mode 100644 index 9d00394a..00000000 --- a/crates/natives/src/native_functions.rs +++ /dev/null @@ -1,163 +0,0 @@ -use move_binary_format::errors::{ - ExecutionState, Location, PartialVMError, PartialVMResult, VMResult, -}; -use move_core_types::{ - account_address::AccountAddress, - gas_algebra::{InternalGas, NumBytes}, - identifier::Identifier, - language_storage::TypeTag, - value::MoveTypeLayout, - vm_status::StatusCode, -}; -use move_vm_types::{ - loaded_data::runtime_types::Type, natives::function::NativeResult, values::Value, -}; -use std::{ - collections::{HashMap, VecDeque}, - fmt::Write, - sync::Arc, -}; - -pub type UnboxedNativeFunction = dyn Fn(&mut NativeContext, Vec, VecDeque) -> PartialVMResult - + Send - + Sync - + 'static; - -pub type NativeFunction = Arc; - -pub type NativeFunctionTable = Vec<(AccountAddress, Identifier, Identifier, NativeFunction)>; - -pub fn make_table( - addr: AccountAddress, - elems: &[(&str, &str, NativeFunction)], -) -> NativeFunctionTable { - make_table_from_iter(addr, elems.iter().cloned()) -} - -pub fn make_table_from_iter>>( - addr: AccountAddress, - elems: impl IntoIterator, -) -> NativeFunctionTable { - elems - .into_iter() - .map(|(module_name, func_name, func)| { - ( - addr, - Identifier::new(module_name).unwrap(), - Identifier::new(func_name).unwrap(), - func, - ) - }) - .collect() -} - -pub(crate) struct NativeFunctions( - HashMap>>, -); - -impl NativeFunctions { - pub fn resolve( - &self, - addr: &AccountAddress, - module_name: &str, - func_name: &str, - ) -> Option { - self.0.get(addr)?.get(module_name)?.get(func_name).cloned() - } - - pub fn new(natives: I) -> PartialVMResult - where - I: IntoIterator, - { - let mut map = HashMap::new(); - for (addr, module_name, func_name, func) in natives.into_iter() { - let modules = map.entry(addr).or_insert_with(HashMap::new); - let funcs = modules - .entry(module_name.into_string()) - .or_insert_with(HashMap::new); - - if funcs.insert(func_name.into_string(), func).is_some() { - return Err(PartialVMError::new(StatusCode::DUPLICATE_NATIVE_FUNCTION)); - } - } - Ok(Self(map)) - } -} - -pub struct NativeContext<'a, 'b, 'c> { - interpreter: &'a mut Interpreter, - data_store: &'a mut TransactionDataCache<'c>, - resolver: &'a Resolver<'a>, - extensions: &'a mut NativeContextExtensions<'b>, - gas_balance: InternalGas, -} - -impl<'a, 'b, 'c> NativeContext<'a, 'b, 'c> { - pub(crate) fn new( - interpreter: &'a mut Interpreter, - data_store: &'a mut TransactionDataCache<'c>, - resolver: &'a Resolver<'a>, - extensions: &'a mut NativeContextExtensions<'b>, - gas_balance: InternalGas, - ) -> Self { - Self { - interpreter, - data_store, - resolver, - extensions, - gas_balance, - } - } -} - -impl<'a, 'b, 'c> NativeContext<'a, 'b, 'c> { - pub fn print_stack_trace(&self, buf: &mut B) -> PartialVMResult<()> { - self.interpreter - .debug_print_stack_trace(buf, self.resolver.loader()) - } - - pub fn exists_at( - &mut self, - address: AccountAddress, - type_: &Type, - ) -> VMResult<(bool, Option)> { - let (value, num_bytes) = self - .data_store - .load_resource(self.resolver.loader(), address, type_) - .map_err(|err| err.finish(Location::Undefined))?; - let exists = value - .exists() - .map_err(|err| err.finish(Location::Undefined))?; - Ok((exists, num_bytes)) - } - - pub fn type_to_type_tag(&self, ty: &Type) -> PartialVMResult { - self.resolver.loader().type_to_type_tag(ty) - } - - pub fn type_to_type_layout(&self, ty: &Type) -> PartialVMResult { - self.resolver.type_to_type_layout(ty) - } - - pub fn type_to_fully_annotated_layout(&self, ty: &Type) -> PartialVMResult { - self.resolver.type_to_fully_annotated_layout(ty) - } - - pub fn extensions(&self) -> &NativeContextExtensions<'b> { - self.extensions - } - - pub fn extensions_mut(&mut self) -> &mut NativeContextExtensions<'b> { - self.extensions - } - - /// Get count stack frames, including the one of the called native function. This - /// allows a native function to reflect about its caller. - pub fn stack_frames(&self, count: usize) -> ExecutionState { - self.interpreter.get_stack_frames(count) - } - - pub fn gas_balance(&self) -> InternalGas { - self.gas_balance - } -} diff --git a/crates/storage/Cargo.toml b/crates/storage/Cargo.toml index aa18858d..9408372f 100644 --- a/crates/storage/Cargo.toml +++ b/crates/storage/Cargo.toml @@ -14,9 +14,17 @@ move-vm-runtime = { workspace = true } move-vm-types = { workspace = true } move-bytecode-utils = { workspace = true } +ambassador = { workspace = true } anyhow = { workspace = true } thiserror = { workspace = true } bytes = { workspace = true } clru = { workspace = true } parking_lot = { workspace = true } sha3 = { workspace = true } +claims = { workspace = true } + +[features] +default = [] +testing = [ + "move-vm-runtime/testing", +] diff --git a/crates/storage/src/code_scale.rs b/crates/storage/src/code_scale.rs new file mode 100644 index 00000000..382ac6ea --- /dev/null +++ b/crates/storage/src/code_scale.rs @@ -0,0 +1,34 @@ +use clru::WeightScale; +use std::sync::Arc; + +use move_binary_format::file_format::CompiledScript; +use move_binary_format::CompiledModule; +use move_vm_runtime::Module; +use move_vm_runtime::Script; +use move_vm_types::code::{Code, ModuleCode}; + +use crate::module_cache::BytesWithHash; +use crate::module_cache::NoVersion; +use crate::state_view::Checksum; + +pub struct CodeScale; + +impl WeightScale> for CodeScale { + fn weight(&self, _key: &Checksum, _value: &Code) -> usize { + 1 + } +} + +pub struct ModuleCodeScale; + +impl WeightScale>> + for ModuleCodeScale +{ + fn weight( + &self, + _key: &Checksum, + _value: &Arc>, + ) -> usize { + 1 + } +} diff --git a/crates/storage/src/code_storage.rs b/crates/storage/src/code_storage.rs new file mode 100644 index 00000000..0dfe76d1 --- /dev/null +++ b/crates/storage/src/code_storage.rs @@ -0,0 +1,273 @@ +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use ambassador::Delegate; +use bytes::Bytes; +use move_binary_format::{errors::VMResult, file_format::CompiledScript, CompiledModule}; +use move_core_types::{account_address::AccountAddress, identifier::IdentStr, metadata::Metadata}; +use move_vm_runtime::{ + ambassador_impl_ModuleStorage, ambassador_impl_WithRuntimeEnvironment, + logging::expect_no_verification_errors, CodeStorage, Module, ModuleStorage, RuntimeEnvironment, + Script, WithRuntimeEnvironment, +}; +use move_vm_types::{ + code::{Code, ModuleBytesStorage}, + module_linker_error, sha3_256, +}; +use std::sync::Arc; + +use crate::{ + module_cache::InitiaModuleCache, + module_storage::{AsInitiaModuleStorage, InitiaModuleStorage}, + script_cache::InitiaScriptCache, + state_view::ChecksumStorage, +}; + +/// Code storage that stores both modules and scripts (not thread-safe). +#[allow(clippy::duplicated_attributes)] +#[derive(Delegate)] +#[delegate(WithRuntimeEnvironment, target = "module_storage")] +#[delegate(ModuleStorage, target = "module_storage")] +pub struct InitiaCodeStorage { + script_cache: Arc, + module_storage: M, +} + +pub trait AsInitiaCodeStorage<'a, S> { + fn as_initia_code_storage( + &'a self, + env: &'a RuntimeEnvironment, + script_cache: Arc, + module_cache: Arc, + ) -> InitiaCodeStorage>; + + fn into_initia_code_storage( + self, + env: &'a RuntimeEnvironment, + script_cache: Arc, + module_cache: Arc, + ) -> InitiaCodeStorage>; +} + +impl<'a, S: ModuleBytesStorage + ChecksumStorage> AsInitiaCodeStorage<'a, S> for S { + fn as_initia_code_storage( + &'a self, + env: &'a RuntimeEnvironment, + script_cache: Arc, + module_cache: Arc, + ) -> InitiaCodeStorage> { + InitiaCodeStorage::new( + script_cache, + self.as_initia_module_storage(env, module_cache), + ) + } + + fn into_initia_code_storage( + self, + env: &'a RuntimeEnvironment, + script_cache: Arc, + module_cache: Arc, + ) -> InitiaCodeStorage> { + InitiaCodeStorage::new( + script_cache, + self.into_initia_module_storage(env, module_cache), + ) + } +} + +impl InitiaCodeStorage { + /// Creates a new storage with no scripts. There are no constraints on which modules exist in + /// module storage. + fn new(script_cache: Arc, module_storage: M) -> Self { + Self { + script_cache, + module_storage, + } + } + + /// Returns the underlying module storage used by this code storage. + pub fn module_storage(&self) -> &M { + &self.module_storage + } +} + +impl CodeStorage for InitiaCodeStorage { + fn deserialize_and_cache_script( + &self, + serialized_script: &[u8], + ) -> VMResult> { + let hash = sha3_256(serialized_script); + Ok(match self.script_cache.get_script(&hash) { + Some(script) => script.deserialized().clone(), + None => { + let deserialized_script = self + .runtime_environment() + .deserialize_into_script(serialized_script)?; + self.script_cache + .insert_deserialized_script(hash, deserialized_script)? + } + }) + } + + fn verify_and_cache_script(&self, serialized_script: &[u8]) -> VMResult> { + use Code::*; + + let hash = sha3_256(serialized_script); + let deserialized_script = match self.script_cache.get_script(&hash) { + Some(Verified(script)) => return Ok(script), + Some(Deserialized(deserialized_script)) => deserialized_script, + None => self + .runtime_environment() + .deserialize_into_script(serialized_script) + .map(Arc::new)?, + }; + + // Locally verify the script. + let locally_verified_script = self + .runtime_environment() + .build_locally_verified_script(deserialized_script)?; + + // Verify the script is correct w.r.t. its dependencies. + let immediate_dependencies = locally_verified_script + .immediate_dependencies_iter() + .map(|(addr, name)| { + // Since module is stored on-chain, we should not see any verification errors here. + self.fetch_verified_module(addr, name) + .map_err(expect_no_verification_errors)? + .ok_or_else(|| module_linker_error!(addr, name)) + }) + .collect::>>()?; + let verified_script = self + .runtime_environment() + .build_verified_script(locally_verified_script, &immediate_dependencies)?; + + self.script_cache + .insert_verified_script(hash, verified_script) + } +} + +#[cfg(test)] +use crate::state_view::Checksum; +impl InitiaCodeStorage { + /// Test-only method that checks the state of the script cache. + #[cfg(test)] + pub(crate) fn assert_cached_state<'b>( + &self, + deserialized: Vec<&'b Checksum>, + verified: Vec<&'b Checksum>, + ) { + assert_eq!( + self.script_cache.num_scripts(), + deserialized.len() + verified.len() + ); + for hash in deserialized { + let script = claims::assert_some!(self.script_cache.get_script(hash)); + assert!(!script.is_verified()) + } + for hash in verified { + let script = claims::assert_some!(self.script_cache.get_script(hash)); + assert!(script.is_verified()) + } + } +} + +#[cfg(test)] +pub(crate) mod test { + use claims::assert_ok; + use move_binary_format::{ + file_format::empty_script_with_dependencies, file_format_common::VERSION_DEFAULT, + }; + use move_core_types::{ + account_address::AccountAddress, identifier::Identifier, language_storage::ModuleId, + }; + use move_vm_runtime::{CodeStorage, RuntimeEnvironment}; + use move_vm_types::sha3_256; + + use crate::{ + code_storage::AsInitiaCodeStorage, + memory_module_storage::InMemoryStorage, + module_cache::InitiaModuleCache, + module_storage::test::{add_module_bytes, TEST_CACHE_CAPACITY}, + script_cache::InitiaScriptCache, + }; + + pub fn make_script<'a>(dependencies: impl IntoIterator) -> Vec { + let mut script = empty_script_with_dependencies(dependencies); + script.version = VERSION_DEFAULT; + + let mut serialized_script = vec![]; + assert_ok!(script.serialize(&mut serialized_script)); + serialized_script + } + + #[test] + fn test_deserialized_script_caching() { + let mut module_bytes_storage = InMemoryStorage::new(); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + let script_cache = InitiaScriptCache::new(TEST_CACHE_CAPACITY); + + add_module_bytes(&mut module_bytes_storage, "a", vec!["b", "c"], vec![]); + add_module_bytes(&mut module_bytes_storage, "b", vec![], vec![]); + add_module_bytes(&mut module_bytes_storage, "c", vec![], vec![]); + + let runtime_environment = RuntimeEnvironment::new(vec![]); + let code_storage = module_bytes_storage.into_initia_code_storage( + &runtime_environment, + script_cache, + module_cache, + ); + + let serialized_script = make_script(vec!["a"]); + let hash_1 = sha3_256(&serialized_script); + assert_ok!(code_storage.deserialize_and_cache_script(&serialized_script)); + + let serialized_script = make_script(vec!["b"]); + let hash_2 = sha3_256(&serialized_script); + assert_ok!(code_storage.deserialize_and_cache_script(&serialized_script)); + + code_storage.assert_cached_state(vec![&hash_1, &hash_2], vec![]); + } + + #[test] + fn test_verified_script_caching() { + let mut module_bytes_storage = InMemoryStorage::new(); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + let script_cache = InitiaScriptCache::new(TEST_CACHE_CAPACITY); + + let a_id = ModuleId::new(AccountAddress::ZERO, Identifier::new("a").unwrap()); + let b_id = ModuleId::new(AccountAddress::ZERO, Identifier::new("b").unwrap()); + let c_id = ModuleId::new(AccountAddress::ZERO, Identifier::new("c").unwrap()); + + let checksum_a = add_module_bytes(&mut module_bytes_storage, "a", vec!["b", "c"], vec![]); + let checksum_b = add_module_bytes(&mut module_bytes_storage, "b", vec![], vec![]); + let checksum_c = add_module_bytes(&mut module_bytes_storage, "c", vec![], vec![]); + + let runtime_environment = RuntimeEnvironment::new(vec![]); + let code_storage = module_bytes_storage.into_initia_code_storage( + &runtime_environment, + script_cache, + module_cache, + ); + + let serialized_script = make_script(vec!["a"]); + let hash = sha3_256(&serialized_script); + assert_ok!(code_storage.deserialize_and_cache_script(&serialized_script)); + + // Nothing gets loaded into module cache. + code_storage + .module_storage() + .assert_cached_state(vec![], vec![], vec![], vec![]); + code_storage.assert_cached_state(vec![&hash], vec![]); + + assert_ok!(code_storage.verify_and_cache_script(&serialized_script)); + + // Script is verified, so its dependencies are loaded into cache. + code_storage.module_storage().assert_cached_state( + vec![], + vec![], + vec![&a_id, &b_id, &c_id], + vec![&checksum_a, &checksum_b, &checksum_c], + ); + code_storage.assert_cached_state(vec![], vec![&hash]); + } +} diff --git a/crates/storage/src/initia_storage.rs b/crates/storage/src/initia_storage.rs new file mode 100644 index 00000000..f6d788eb --- /dev/null +++ b/crates/storage/src/initia_storage.rs @@ -0,0 +1,47 @@ +use crate::{ + code_storage::{AsInitiaCodeStorage, InitiaCodeStorage}, + module_cache::InitiaModuleCache, + module_storage::InitiaModuleStorage, + script_cache::InitiaScriptCache, + state_view::StateView, + state_view_impl::StateViewImpl, +}; +use ambassador::Delegate; +use bytes::Bytes; +use move_binary_format::{errors::VMResult, file_format::CompiledScript, CompiledModule}; +use move_core_types::{account_address::AccountAddress, identifier::IdentStr, metadata::Metadata}; +use move_vm_runtime::{ + ambassador_impl_CodeStorage, ambassador_impl_ModuleStorage, + ambassador_impl_WithRuntimeEnvironment, CodeStorage, Module, ModuleStorage, RuntimeEnvironment, + Script, WithRuntimeEnvironment, +}; +use std::sync::Arc; + +#[derive(Delegate)] +#[delegate(WithRuntimeEnvironment)] +#[delegate(ModuleStorage)] +#[delegate(CodeStorage)] +pub struct InitiaStorage<'s, S> { + storage: InitiaCodeStorage>>, +} + +impl<'s, S: StateView> InitiaStorage<'s, S> { + pub fn new( + state_view: &'s S, + runtime_environment: &'s RuntimeEnvironment, + script_cache: Arc, + module_cache: Arc, + ) -> Self { + let state_view_impl = StateViewImpl::new(state_view); + let storage = state_view_impl.into_initia_code_storage( + runtime_environment, + script_cache, + module_cache, + ); + Self { storage } + } + + pub fn state_view_impl(&self) -> &StateViewImpl<'s, S> { + self.storage.module_storage().byte_storage() + } +} diff --git a/crates/storage/src/lib.rs b/crates/storage/src/lib.rs index 9ce956c4..f02a8b72 100644 --- a/crates/storage/src/lib.rs +++ b/crates/storage/src/lib.rs @@ -1,3 +1,12 @@ pub mod state_view; pub mod state_view_impl; pub mod table_resolver; + +pub mod code_storage; +pub mod initia_storage; +pub mod memory_module_storage; +pub mod module_cache; +pub mod module_storage; +pub mod script_cache; + +pub mod code_scale; diff --git a/crates/storage/src/memory_module_storage.rs b/crates/storage/src/memory_module_storage.rs new file mode 100644 index 00000000..4fefb43e --- /dev/null +++ b/crates/storage/src/memory_module_storage.rs @@ -0,0 +1,325 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use bytes::Bytes; +use move_binary_format::{ + deserializer::DeserializerConfig, + errors::{PartialVMError, PartialVMResult, VMResult}, + file_format_common::{IDENTIFIER_SIZE_MAX, VERSION_MAX}, + CompiledModule, +}; +use move_bytecode_utils::compiled_module_viewer::CompiledModuleView; +use move_core_types::{ + account_address::AccountAddress, + effects::{AccountChangeSet, ChangeSet, Op}, + identifier::{IdentStr, Identifier}, + language_storage::{ModuleId, StructTag}, + metadata::Metadata, + value::MoveTypeLayout, + vm_status::StatusCode, +}; +use move_vm_types::{ + code::ModuleBytesStorage, + resolver::{resource_size, ModuleResolver, ResourceResolver}, + sha3_256, +}; +use std::{ + collections::{btree_map, BTreeMap}, + fmt::Debug, +}; + +use crate::state_view::{Checksum, ChecksumStorage}; + +/// A dummy storage containing no modules or resources. +#[derive(Debug, Clone)] +pub struct BlankStorage; + +impl Default for BlankStorage { + fn default() -> Self { + Self::new() + } +} + +impl BlankStorage { + pub fn new() -> Self { + Self + } +} + +impl ModuleBytesStorage for BlankStorage { + fn fetch_module_bytes( + &self, + _address: &AccountAddress, + _module_name: &IdentStr, + ) -> VMResult> { + Ok(None) + } +} + +impl ChecksumStorage for BlankStorage { + fn fetch_checksum( + &self, + _address: &AccountAddress, + _module_name: &IdentStr, + ) -> VMResult> { + Ok(None) + } +} + +impl ModuleResolver for BlankStorage { + fn get_module_metadata(&self, _module_id: &ModuleId) -> Vec { + vec![] + } + + fn get_module(&self, _module_id: &ModuleId) -> PartialVMResult> { + Ok(None) + } +} + +impl ResourceResolver for BlankStorage { + fn get_resource_bytes_with_metadata_and_layout( + &self, + _address: &AccountAddress, + _tag: &StructTag, + _metadata: &[Metadata], + _maybe_layout: Option<&MoveTypeLayout>, + ) -> PartialVMResult<(Option, usize)> { + Ok((None, 0)) + } +} + +/// Simple in-memory storage for modules and resources under an account. +#[derive(Debug, Clone)] +struct InMemoryAccountStorage { + resources: BTreeMap, + modules: BTreeMap, + checksums: BTreeMap, +} + +/// Simple in-memory storage that can be used as a Move VM storage backend for testing purposes. +#[derive(Debug, Clone)] +pub struct InMemoryStorage { + accounts: BTreeMap, +} + +impl CompiledModuleView for InMemoryStorage { + type Item = CompiledModule; + + fn view_compiled_module(&self, id: &ModuleId) -> anyhow::Result> { + Ok(match self.get_module(id)? { + Some(bytes) => { + let config = DeserializerConfig::new(VERSION_MAX, IDENTIFIER_SIZE_MAX); + Some(CompiledModule::deserialize_with_config(&bytes, &config)?) + } + None => None, + }) + } +} + +fn apply_changes( + map: &mut BTreeMap, + changes: impl IntoIterator)>, +) -> PartialVMResult<()> +where + K: Ord + Debug, +{ + use btree_map::Entry::*; + use Op::*; + + for (k, op) in changes.into_iter() { + match (map.entry(k), op) { + (Occupied(entry), New(_)) => { + return Err( + PartialVMError::new(StatusCode::STORAGE_ERROR).with_message(format!( + "Failed to apply changes -- key {:?} already exists", + entry.key() + )), + ) + } + (Occupied(entry), Delete) => { + entry.remove(); + } + (Occupied(entry), Modify(val)) => { + *entry.into_mut() = val; + } + (Vacant(entry), New(val)) => { + entry.insert(val); + } + (Vacant(entry), Delete | Modify(_)) => { + return Err( + PartialVMError::new(StatusCode::STORAGE_ERROR).with_message(format!( + "Failed to apply changes -- key {:?} does not exist", + entry.key() + )), + ) + } + } + } + Ok(()) +} + +fn get_or_insert(map: &mut BTreeMap, key: K, make_val: F) -> &mut V +where + K: Ord, + F: FnOnce() -> V, +{ + use btree_map::Entry::*; + + match map.entry(key) { + Occupied(entry) => entry.into_mut(), + Vacant(entry) => entry.insert(make_val()), + } +} + +impl InMemoryAccountStorage { + fn apply(&mut self, account_changeset: AccountChangeSet) -> PartialVMResult<()> { + let (modules, resources) = account_changeset.into_inner(); + apply_changes(&mut self.modules, modules.clone())?; + apply_changes( + &mut self.checksums, + Self::modules_to_checksum_changes(modules), + )?; + apply_changes(&mut self.resources, resources)?; + Ok(()) + } + + fn modules_to_checksum_changes( + modules: BTreeMap>, + ) -> BTreeMap> { + modules + .into_iter() + .map(|(k, v)| { + ( + k, + match v { + Op::New(bytes) => Op::New(sha3_256(&bytes)), + Op::Modify(bytes) => Op::Modify(sha3_256(&bytes)), + Op::Delete => Op::Delete, + }, + ) + }) + .collect() + } + + fn new() -> Self { + Self { + modules: BTreeMap::new(), + checksums: BTreeMap::new(), + resources: BTreeMap::new(), + } + } +} + +impl Default for InMemoryStorage { + fn default() -> Self { + Self::new() + } +} + +impl InMemoryStorage { + pub fn apply_extended(&mut self, changeset: ChangeSet) -> PartialVMResult<()> { + for (addr, account_changeset) in changeset.into_inner() { + self.accounts + .entry(addr) + .or_insert_with(InMemoryAccountStorage::new) + .apply(account_changeset)?; + } + + Ok(()) + } + + pub fn apply(&mut self, changeset: ChangeSet) -> PartialVMResult<()> { + self.apply_extended(changeset) + } + + pub fn new() -> Self { + Self { + accounts: BTreeMap::new(), + } + } + + /// Adds serialized module bytes to this storage. + pub fn add_module_bytes( + &mut self, + address: &AccountAddress, + module_name: &IdentStr, + bytes: Bytes, + ) -> Checksum { + let checksum = sha3_256(&bytes); + + let account = get_or_insert(&mut self.accounts, *address, || { + InMemoryAccountStorage::new() + }); + account.modules.insert(module_name.to_owned(), bytes); + account.checksums.insert(module_name.to_owned(), checksum); + checksum + } + + pub fn publish_or_overwrite_resource( + &mut self, + addr: AccountAddress, + struct_tag: StructTag, + blob: Vec, + ) { + let account = get_or_insert(&mut self.accounts, addr, InMemoryAccountStorage::new); + account.resources.insert(struct_tag, blob.into()); + } +} + +impl ModuleBytesStorage for InMemoryStorage { + fn fetch_module_bytes( + &self, + address: &AccountAddress, + module_name: &IdentStr, + ) -> VMResult> { + Ok(self + .accounts + .get(address) + .and_then(|account_storage| account_storage.modules.get(module_name).cloned())) + } +} + +impl ChecksumStorage for InMemoryStorage { + fn fetch_checksum( + &self, + address: &AccountAddress, + module_name: &IdentStr, + ) -> VMResult> { + Ok(self + .accounts + .get(address) + .and_then(|account_storage| account_storage.checksums.get(module_name)) + .cloned()) + } +} + +impl ModuleResolver for InMemoryStorage { + fn get_module_metadata(&self, _module_id: &ModuleId) -> Vec { + vec![] + } + + fn get_module(&self, module_id: &ModuleId) -> PartialVMResult> { + Ok(self + .accounts + .get(module_id.address()) + .and_then(|account_storage| account_storage.modules.get(module_id.name()).cloned())) + } +} + +impl ResourceResolver for InMemoryStorage { + fn get_resource_bytes_with_metadata_and_layout( + &self, + address: &AccountAddress, + tag: &StructTag, + _metadata: &[Metadata], + _maybe_layout: Option<&MoveTypeLayout>, + ) -> PartialVMResult<(Option, usize)> { + if let Some(account_storage) = self.accounts.get(address) { + let buf = account_storage.resources.get(tag).cloned(); + let buf_size = resource_size(&buf); + return Ok((buf, buf_size)); + } + Ok((None, 0)) + } +} diff --git a/crates/storage/src/module_cache.rs b/crates/storage/src/module_cache.rs new file mode 100644 index 00000000..1a22fce4 --- /dev/null +++ b/crates/storage/src/module_cache.rs @@ -0,0 +1,188 @@ +use std::{hash::RandomState, num::NonZeroUsize, sync::Arc}; + +use bytes::Bytes; +use clru::{CLruCache, CLruCacheConfig}; +use move_binary_format::{ + errors::{Location, PartialVMError, VMError, VMResult}, + CompiledModule, +}; +use move_core_types::{language_storage::ModuleId, vm_status::StatusCode}; +use move_vm_runtime::Module; +use move_vm_types::code::{ModuleCode, ModuleCodeBuilder, WithBytes, WithHash}; +use parking_lot::Mutex; + +use crate::{code_scale::ModuleCodeScale, state_view::Checksum}; + +fn handle_cache_error(module_id: ModuleId) -> VMError { + PartialVMError::new(StatusCode::MEMORY_LIMIT_EXCEEDED) + .with_message("Module storage cache eviction error".to_string()) + .finish(Location::Module(module_id)) +} + +/// Extension for modules stored in [InitialModuleCache] to also capture information about bytes +/// and hash. +#[derive(PartialEq, Eq, Debug)] +pub struct BytesWithHash { + /// Bytes of the module. + bytes: Bytes, + /// Hash of the module. + hash: [u8; 32], +} + +impl BytesWithHash { + /// Returns new extension containing bytes and hash. + pub fn new(bytes: Bytes, hash: [u8; 32]) -> Self { + Self { bytes, hash } + } +} + +impl WithBytes for BytesWithHash { + fn bytes(&self) -> &Bytes { + &self.bytes + } +} + +impl WithHash for BytesWithHash { + fn hash(&self) -> &[u8; 32] { + &self.hash + } +} + +/// Placeholder for module versioning since we do not allow mutations in [InitiaModuleCache]. +#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)] +pub struct NoVersion; + +pub struct InitiaModuleCache { + #[allow(clippy::type_complexity)] + pub(crate) module_cache: Mutex< + CLruCache< + Checksum, + Arc>, + RandomState, + ModuleCodeScale, + >, + >, +} + +impl InitiaModuleCache { + pub fn new(cache_capacity: usize) -> Arc { + let capacity = NonZeroUsize::new(cache_capacity).unwrap(); + Arc::new(InitiaModuleCache { + module_cache: Mutex::new(CLruCache::with_config( + CLruCacheConfig::new(capacity).with_scale(ModuleCodeScale), + )), + }) + } +} + +// modified ModuleCache trait implementation +impl InitiaModuleCache { + #[allow(unused)] + pub(crate) fn insert_deserialized_module( + &self, + key: Checksum, + deserialized_code: CompiledModule, + extension: Arc, + version: NoVersion, + ) -> VMResult<()> { + let mut module_cache = self.module_cache.lock(); + + match module_cache.get(&key) { + // we don't use version of the module, so we don't need to check it + Some(_) => Ok(()), + None => { + let module_id = deserialized_code.self_id(); + let module = Arc::new(ModuleCode::from_deserialized( + deserialized_code, + extension, + version, + )); + module_cache + .put_with_weight(key, module) + .map_err(|_| handle_cache_error(module_id))?; + Ok(()) + } + } + } + + pub(crate) fn insert_verified_module( + &self, + key: Checksum, + verified_code: Module, + extension: Arc, + version: NoVersion, + ) -> VMResult>> { + let mut module_cache = self.module_cache.lock(); + + match module_cache.get(&key) { + Some(code) => { + if code.code().is_verified() { + Ok(code.clone()) + } else { + let module_id = verified_code.self_id(); + let module = + Arc::new(ModuleCode::from_verified(verified_code, extension, version)); + module_cache + .put_with_weight(key, module.clone()) + .map_err(|_| handle_cache_error(module_id))?; + Ok(module) + } + } + None => { + let module_id = verified_code.self_id(); + let module = Arc::new(ModuleCode::from_verified(verified_code, extension, version)); + module_cache + .put_with_weight(key, module.clone()) + .map_err(|_| handle_cache_error(module_id))?; + Ok(module) + } + } + } + + #[allow(clippy::type_complexity)] + pub(crate) fn get_module_or_build_with( + &self, + id: &ModuleId, + checksum: &Checksum, + builder: &dyn ModuleCodeBuilder< + Key = ModuleId, + Deserialized = CompiledModule, + Verified = Module, + Extension = BytesWithHash, + Version = NoVersion, + >, + ) -> VMResult>>> { + let mut module_cache = self.module_cache.lock(); + Ok(match module_cache.get(checksum) { + Some(code) => Some(code.clone()), + None => match builder.build(id)? { + Some(code) => { + if code.extension().hash() != checksum { + return Err(PartialVMError::new( + StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR, + ) + .with_message("Checksum mismatch".to_string()) + .finish(Location::Module(id.clone()))); + } + + let code = Arc::new(code); + module_cache + .put_with_weight(*checksum, code.clone()) + .map_err(|_| { + PartialVMError::new(StatusCode::MEMORY_LIMIT_EXCEEDED) + .with_message("Module storage cache eviction error".to_string()) + .finish(Location::Module(id.clone())) + })?; + Some(code) + } + None => None, + }, + }) + } + + #[allow(unused)] + pub(crate) fn num_modules(&self) -> usize { + let module_cache = self.module_cache.lock(); + module_cache.len() + } +} diff --git a/crates/storage/src/module_storage.rs b/crates/storage/src/module_storage.rs new file mode 100644 index 00000000..d8d4981d --- /dev/null +++ b/crates/storage/src/module_storage.rs @@ -0,0 +1,705 @@ +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use crate::{ + module_cache::{BytesWithHash, InitiaModuleCache, NoVersion}, + state_view::{Checksum, ChecksumStorage}, +}; +use bytes::Bytes; + +use move_binary_format::{errors::VMResult, CompiledModule}; +use move_core_types::{ + account_address::AccountAddress, identifier::IdentStr, language_storage::ModuleId, + metadata::Metadata, +}; +use move_vm_runtime::{Module, ModuleStorage, RuntimeEnvironment, WithRuntimeEnvironment}; +use move_vm_types::{ + code::{ModuleBytesStorage, ModuleCode, ModuleCodeBuilder, WithBytes, WithHash}, + module_cyclic_dependency_error, module_linker_error, +}; +use std::{borrow::Borrow, collections::HashSet, ops::Deref, sync::Arc}; + +/// Implementation of (not thread-safe) module storage used for Move unit tests, and externally. +pub struct InitiaModuleStorage<'a, S> { + /// Environment where this module storage is defined in. + runtime_environment: &'a RuntimeEnvironment, + /// Storage with deserialized modules, i.e., module cache. + module_cache: Arc, + /// Immutable baseline storage from which one can fetch raw module bytes and checksums. + base_storage: BorrowedOrOwned<'a, S>, +} + +pub trait AsInitiaModuleStorage<'a, S> { + fn as_initia_module_storage( + &'a self, + env: &'a RuntimeEnvironment, + module_cache: Arc, + ) -> InitiaModuleStorage<'a, S>; + + fn into_initia_module_storage( + self, + env: &'a RuntimeEnvironment, + module_cache: Arc, + ) -> InitiaModuleStorage<'a, S>; +} + +impl<'a, S: ModuleBytesStorage + ChecksumStorage> AsInitiaModuleStorage<'a, S> for S { + fn as_initia_module_storage( + &'a self, + env: &'a RuntimeEnvironment, + module_cache: Arc, + ) -> InitiaModuleStorage<'a, S> { + InitiaModuleStorage::from_borrowed(env, self, module_cache) + } + + fn into_initia_module_storage( + self, + env: &'a RuntimeEnvironment, + module_cache: Arc, + ) -> InitiaModuleStorage<'a, S> { + InitiaModuleStorage::from_owned(env, self, module_cache) + } +} + +impl<'s, S: ModuleBytesStorage + ChecksumStorage> WithRuntimeEnvironment + for InitiaModuleStorage<'s, S> +{ + fn runtime_environment(&self) -> &RuntimeEnvironment { + self.runtime_environment + } +} + +impl<'s, S: ModuleBytesStorage + ChecksumStorage> InitiaModuleStorage<'s, S> { + /// Private constructor from borrowed byte storage. Creates empty module storage cache. + fn from_borrowed( + runtime_environment: &'s RuntimeEnvironment, + storage: &'s S, + module_cache: Arc, + ) -> Self { + Self { + runtime_environment, + module_cache, + base_storage: BorrowedOrOwned::Borrowed(storage), + } + } + + /// Private constructor that captures provided byte storage by value. Creates empty module + /// storage cache. + fn from_owned( + runtime_environment: &'s RuntimeEnvironment, + storage: S, + module_cache: Arc, + ) -> Self { + Self { + runtime_environment, + module_cache, + base_storage: BorrowedOrOwned::Owned(storage), + } + } + + /// The reference to the baseline byte storage used by this module storage. + pub fn byte_storage(&self) -> &S { + &self.base_storage + } + + /// Test-only method that checks the state of the module cache. + #[cfg(test)] + pub(crate) fn assert_cached_state( + &self, + deserialized: Vec<&'s ModuleId>, + deserialized_checksum: Vec<&'s Checksum>, + verified: Vec<&'s ModuleId>, + verified_checksum: Vec<&'s Checksum>, + ) { + assert_eq!( + self.module_cache.num_modules(), + deserialized.len() + verified.len() + ); + assert_eq!(deserialized.len(), deserialized_checksum.len()); + for (id, checksum) in deserialized.into_iter().zip(deserialized_checksum) { + let result = self + .module_cache + .get_module_or_build_with(id, checksum, self); + let module = claims::assert_some!(claims::assert_ok!(result)); + assert!(!module.code().is_verified()) + } + assert_eq!(verified.len(), verified_checksum.len()); + for (id, checksum) in verified.into_iter().zip(verified_checksum) { + let result = self + .module_cache + .get_module_or_build_with(id, checksum, self); + let module = claims::assert_some!(claims::assert_ok!(result)); + assert!(module.code().is_verified()) + } + } +} + +impl<'s, S: ModuleBytesStorage + ChecksumStorage> ModuleCodeBuilder for InitiaModuleStorage<'s, S> { + type Deserialized = CompiledModule; + type Extension = BytesWithHash; + type Key = ModuleId; + type Verified = Module; + type Version = NoVersion; + + fn build( + &self, + key: &Self::Key, + ) -> VMResult< + Option>, + > { + let bytes = match self + .base_storage + .fetch_module_bytes(key.address(), key.name())? + { + Some(bytes) => bytes, + None => return Ok(None), + }; + + let checksum = match self + .base_storage + .fetch_checksum(key.address(), key.name())? + { + Some(checksum) => checksum, + None => return Ok(None), + }; + + let (compiled_module, _, hash) = self + .runtime_environment() + .deserialize_into_compiled_module(&bytes)?; + + if checksum != hash { + return Err(module_linker_error!(key.address(), key.name())); + } + + let extension = Arc::new(BytesWithHash::new(bytes, hash)); + let module = ModuleCode::from_deserialized(compiled_module, extension, NoVersion); + Ok(Some(module)) + } +} + +impl<'a, S: ModuleBytesStorage + ChecksumStorage> ModuleStorage for InitiaModuleStorage<'a, S> { + fn check_module_exists( + &self, + address: &AccountAddress, + module_name: &IdentStr, + ) -> VMResult { + let id = ModuleId::new(*address, module_name.to_owned()); + let checksum = match self.base_storage.fetch_checksum(address, module_name)? { + Some(checksum) => checksum, + None => return Ok(false), + }; + Ok(self + .module_cache + .get_module_or_build_with(&id, &checksum, self)? + .is_some()) + } + + fn fetch_module_bytes( + &self, + address: &AccountAddress, + module_name: &IdentStr, + ) -> VMResult> { + let id = ModuleId::new(*address, module_name.to_owned()); + let checksum = match self.base_storage.fetch_checksum(address, module_name)? { + Some(checksum) => checksum, + None => return Ok(None), + }; + Ok(self + .module_cache + .get_module_or_build_with(&id, &checksum, self)? + .map(|module| module.extension().bytes().clone())) + } + + fn fetch_module_size_in_bytes( + &self, + address: &AccountAddress, + module_name: &IdentStr, + ) -> VMResult> { + let id = ModuleId::new(*address, module_name.to_owned()); + let checksum = match self.base_storage.fetch_checksum(address, module_name)? { + Some(checksum) => checksum, + None => return Ok(None), + }; + Ok(self + .module_cache + .get_module_or_build_with(&id, &checksum, self)? + .map(|module| module.extension().bytes().len())) + } + + fn fetch_module_metadata( + &self, + address: &AccountAddress, + module_name: &IdentStr, + ) -> VMResult>> { + let id = ModuleId::new(*address, module_name.to_owned()); + let checksum = match self.base_storage.fetch_checksum(address, module_name)? { + Some(checksum) => checksum, + None => return Ok(None), + }; + Ok(self + .module_cache + .get_module_or_build_with(&id, &checksum, self)? + .map(|module| module.code().deserialized().metadata.clone())) + } + + fn fetch_deserialized_module( + &self, + address: &AccountAddress, + module_name: &IdentStr, + ) -> VMResult>> { + let id = ModuleId::new(*address, module_name.to_owned()); + let checksum = match self.base_storage.fetch_checksum(address, module_name)? { + Some(checksum) => checksum, + None => return Ok(None), + }; + Ok(self + .module_cache + .get_module_or_build_with(&id, &checksum, self)? + .map(|module| module.code().deserialized().clone())) + } + + fn fetch_verified_module( + &self, + address: &AccountAddress, + module_name: &IdentStr, + ) -> VMResult>> { + let id = ModuleId::new(*address, module_name.to_owned()); + let checksum = match self.base_storage.fetch_checksum(address, module_name)? { + Some(checksum) => checksum, + None => return Ok(None), + }; + + // Look up the verified module in cache, if it is not there, or if the module is not yet + // verified, we need to load & verify its transitive dependencies. + let module = match self + .module_cache + .get_module_or_build_with(&id, &checksum, self)? + { + Some(module) => module, + None => return Ok(None), + }; + + if module.code().is_verified() { + return Ok(Some(module.code().verified().clone())); + } + + let mut visited = HashSet::new(); + visited.insert(id.clone()); + Ok(Some(visit_dependencies_and_verify( + id, + checksum, + module, + &mut visited, + self, + )?)) + } +} + +/// Visits the dependencies of the given module. If dependencies form a cycle (which should not be +/// the case as we check this when modules are added to the module cache), an error is returned. +/// +/// Note: +/// This implementation **does not** load transitive friends. While it is possible to view +/// friends as `used-by` relation, it cannot be checked fully. For example, consider the case +/// when we have four modules A, B, C, D and let `X --> Y` be a dependency relation (Y is a +/// dependency of X) and `X ==> Y ` a friend relation (X declares Y a friend). Then consider the +/// case `A --> B <== C --> D <== A`. Here, if we opt for `used-by` semantics, there is a cycle. +/// But it cannot be checked, since, A only sees B and D, and C sees B and D, but both B and D do +/// not see any dependencies or friends. Hence, A cannot discover C and vice-versa, making +/// detection of such corner cases only possible if **all existing modules are checked**, which +/// is clearly infeasible. +fn visit_dependencies_and_verify( + module_id: ModuleId, + checksum: Checksum, + module: Arc>, + visited: &mut HashSet, + module_cache_with_context: &InitiaModuleStorage<'_, S>, +) -> VMResult> { + let runtime_environment = module_cache_with_context.runtime_environment; + + // Step 1: Local verification. + runtime_environment.paranoid_check_module_address_and_name( + module.code().deserialized(), + module_id.address(), + module_id.name(), + )?; + let locally_verified_code = runtime_environment.build_locally_verified_module( + module.code().deserialized().clone(), + module.extension().size_in_bytes(), + module.extension().hash(), + )?; + + // Step 2: Traverse and collect all verified immediate dependencies so that we can verify + // non-local properties of the module. + let mut verified_dependencies = vec![]; + for (addr, name) in locally_verified_code.immediate_dependencies_iter() { + let dependency_id = ModuleId::new(*addr, name.to_owned()); + let dependency_checksum = module_cache_with_context + .base_storage + .fetch_checksum(addr, name)? + .ok_or_else(|| module_linker_error!(dependency_id.address(), dependency_id.name()))?; + + let dependency = module_cache_with_context + .module_cache + .get_module_or_build_with( + &dependency_id, + &dependency_checksum, + module_cache_with_context, + )? + .ok_or_else(|| module_linker_error!(addr, name))?; + + // Dependency is already verified! + if dependency.code().is_verified() { + verified_dependencies.push(dependency.code().verified().clone()); + continue; + } + + if visited.insert(dependency_id.clone()) { + // Dependency is not verified, and we have not visited it yet. + let verified_dependency = visit_dependencies_and_verify( + dependency_id.clone(), + dependency_checksum, + dependency, + visited, + module_cache_with_context, + )?; + verified_dependencies.push(verified_dependency); + } else { + // We must have found a cycle otherwise. + return Err(module_cyclic_dependency_error!( + dependency_id.address(), + dependency_id.name() + )); + } + } + + let verified_code = + runtime_environment.build_verified_module(locally_verified_code, &verified_dependencies)?; + let module = module_cache_with_context + .module_cache + .insert_verified_module( + checksum, + verified_code, + module.extension().clone(), + module.version(), + )?; + Ok(module.code().verified().clone()) +} + +/// Represents owned or borrowed types, similar to [std::borrow::Cow] but without enforcing +/// [ToOwned] trait bound on types it stores. We use it to be able to construct different storages +/// that capture or borrow underlying byte storage. +enum BorrowedOrOwned<'a, T> { + Borrowed(&'a T), + Owned(T), +} + +impl<'a, T> Deref for BorrowedOrOwned<'a, T> { + type Target = T; + + fn deref(&self) -> &Self::Target { + match *self { + Self::Borrowed(x) => x, + Self::Owned(ref x) => x.borrow(), + } + } +} + +#[cfg(test)] +pub(crate) mod test { + use bytes::Bytes; + use claims::{assert_err, assert_none, assert_ok, assert_some}; + use move_binary_format::{ + file_format::empty_module_with_dependencies_and_friends, + file_format_common::VERSION_DEFAULT, CompiledModule, + }; + use move_core_types::{ + account_address::AccountAddress, ident_str, identifier::Identifier, + language_storage::ModuleId, vm_status::StatusCode, + }; + use move_vm_runtime::{ModuleStorage, RuntimeEnvironment}; + + use crate::{ + memory_module_storage::InMemoryStorage, module_cache::InitiaModuleCache, + module_storage::AsInitiaModuleStorage, state_view::Checksum, + }; + + pub const TEST_CACHE_CAPACITY: usize = 100; + + fn make_module<'a>( + module_name: &'a str, + dependencies: impl IntoIterator, + friends: impl IntoIterator, + ) -> (CompiledModule, Bytes) { + let mut module = + empty_module_with_dependencies_and_friends(module_name, dependencies, friends); + module.version = VERSION_DEFAULT; + + let mut module_bytes = vec![]; + assert_ok!(module.serialize(&mut module_bytes)); + + (module, module_bytes.into()) + } + + pub(crate) fn add_module_bytes<'a>( + module_bytes_storage: &mut InMemoryStorage, + module_name: &'a str, + dependencies: impl IntoIterator, + friends: impl IntoIterator, + ) -> Checksum { + let (module, bytes) = make_module(module_name, dependencies, friends); + module_bytes_storage.add_module_bytes(module.self_addr(), module.self_name(), bytes) + } + + #[test] + fn test_module_does_not_exist() { + let runtime_environment = RuntimeEnvironment::new(vec![]); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + let module_storage = + InMemoryStorage::new().into_initia_module_storage(&runtime_environment, module_cache); + + let result = module_storage.check_module_exists(&AccountAddress::ZERO, ident_str!("a")); + assert!(!assert_ok!(result)); + + let result = + module_storage.fetch_module_size_in_bytes(&AccountAddress::ZERO, ident_str!("a")); + assert_none!(assert_ok!(result)); + + let result = module_storage.fetch_module_metadata(&AccountAddress::ZERO, ident_str!("a")); + assert_none!(assert_ok!(result)); + + let result = + module_storage.fetch_deserialized_module(&AccountAddress::ZERO, ident_str!("a")); + assert_none!(assert_ok!(result)); + + let result = module_storage.fetch_verified_module(&AccountAddress::ZERO, ident_str!("a")); + assert_none!(assert_ok!(result)); + } + + #[test] + fn test_module_exists() { + let mut module_bytes_storage = InMemoryStorage::new(); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + let checksum_a = add_module_bytes(&mut module_bytes_storage, "a", vec![], vec![]); + let id = ModuleId::new(AccountAddress::ZERO, Identifier::new("a").unwrap()); + + let runtime_environment = RuntimeEnvironment::new(vec![]); + let module_storage = + module_bytes_storage.into_initia_module_storage(&runtime_environment, module_cache); + + assert!(assert_ok!( + module_storage.check_module_exists(id.address(), id.name()) + )); + module_storage.assert_cached_state(vec![&id], vec![&checksum_a], vec![], vec![]); + } + + #[test] + fn test_deserialized_caching() { + let mut module_bytes_storage = InMemoryStorage::new(); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + + let a_id = ModuleId::new(AccountAddress::ZERO, Identifier::new("a").unwrap()); + let c_id = ModuleId::new(AccountAddress::ZERO, Identifier::new("c").unwrap()); + + let checksum_a = add_module_bytes(&mut module_bytes_storage, "a", vec!["b", "c"], vec![]); + add_module_bytes(&mut module_bytes_storage, "b", vec![], vec![]); + let checksum_c = add_module_bytes(&mut module_bytes_storage, "c", vec!["d", "e"], vec![]); + add_module_bytes(&mut module_bytes_storage, "d", vec![], vec![]); + add_module_bytes(&mut module_bytes_storage, "e", vec![], vec![]); + + let runtime_environment = RuntimeEnvironment::new(vec![]); + let module_storage = + module_bytes_storage.into_initia_module_storage(&runtime_environment, module_cache); + + let result = module_storage.fetch_module_metadata(a_id.address(), a_id.name()); + let expected = make_module("a", vec!["b", "c"], vec![]).0.metadata; + assert_eq!(assert_some!(assert_ok!(result)), expected); + module_storage.assert_cached_state(vec![&a_id], vec![&checksum_a], vec![], vec![]); + + let result = module_storage.fetch_deserialized_module(c_id.address(), c_id.name()); + let expected = make_module("c", vec!["d", "e"], vec![]).0; + assert_eq!(assert_some!(assert_ok!(result)).as_ref(), &expected); + module_storage.assert_cached_state( + vec![&a_id, &c_id], + vec![&checksum_a, &checksum_c], + vec![], + vec![], + ); + } + + #[test] + fn test_dependency_tree_traversal() { + let mut module_bytes_storage = InMemoryStorage::new(); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + + let a_id = ModuleId::new(AccountAddress::ZERO, Identifier::new("a").unwrap()); + let b_id = ModuleId::new(AccountAddress::ZERO, Identifier::new("b").unwrap()); + let c_id = ModuleId::new(AccountAddress::ZERO, Identifier::new("c").unwrap()); + let d_id = ModuleId::new(AccountAddress::ZERO, Identifier::new("d").unwrap()); + let e_id = ModuleId::new(AccountAddress::ZERO, Identifier::new("e").unwrap()); + + let checksum_a = add_module_bytes(&mut module_bytes_storage, "a", vec!["b", "c"], vec![]); + let checksum_b = add_module_bytes(&mut module_bytes_storage, "b", vec![], vec![]); + let checksum_c = add_module_bytes(&mut module_bytes_storage, "c", vec!["d", "e"], vec![]); + let checksum_d = add_module_bytes(&mut module_bytes_storage, "d", vec![], vec![]); + let checksum_e = add_module_bytes(&mut module_bytes_storage, "e", vec![], vec![]); + + let runtime_environment = RuntimeEnvironment::new(vec![]); + let module_storage = + module_bytes_storage.into_initia_module_storage(&runtime_environment, module_cache); + + assert_ok!(module_storage.fetch_verified_module(c_id.address(), c_id.name())); + module_storage.assert_cached_state( + vec![], + vec![], + vec![&c_id, &d_id, &e_id], + vec![&checksum_c, &checksum_d, &checksum_e], + ); + + assert_ok!(module_storage.fetch_verified_module(a_id.address(), a_id.name())); + module_storage.assert_cached_state( + vec![], + vec![], + vec![&a_id, &b_id, &c_id, &d_id, &e_id], + vec![ + &checksum_a, + &checksum_b, + &checksum_c, + &checksum_d, + &checksum_e, + ], + ); + + assert_ok!(module_storage.fetch_verified_module(a_id.address(), a_id.name())); + } + + #[test] + fn test_dependency_dag_traversal() { + let mut module_bytes_storage = InMemoryStorage::new(); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + + let a_id = ModuleId::new(AccountAddress::ZERO, Identifier::new("a").unwrap()); + let b_id = ModuleId::new(AccountAddress::ZERO, Identifier::new("b").unwrap()); + let c_id = ModuleId::new(AccountAddress::ZERO, Identifier::new("c").unwrap()); + let d_id = ModuleId::new(AccountAddress::ZERO, Identifier::new("d").unwrap()); + let e_id = ModuleId::new(AccountAddress::ZERO, Identifier::new("e").unwrap()); + let f_id = ModuleId::new(AccountAddress::ZERO, Identifier::new("f").unwrap()); + let g_id = ModuleId::new(AccountAddress::ZERO, Identifier::new("g").unwrap()); + + let checksum_a = add_module_bytes(&mut module_bytes_storage, "a", vec!["b", "c"], vec![]); + let checksum_b = add_module_bytes(&mut module_bytes_storage, "b", vec!["d"], vec![]); + let checksum_c = add_module_bytes(&mut module_bytes_storage, "c", vec!["d"], vec![]); + let checksum_d = add_module_bytes(&mut module_bytes_storage, "d", vec!["e", "f"], vec![]); + let checksum_e = add_module_bytes(&mut module_bytes_storage, "e", vec!["g"], vec![]); + let checksum_f = add_module_bytes(&mut module_bytes_storage, "f", vec!["g"], vec![]); + let checksum_g = add_module_bytes(&mut module_bytes_storage, "g", vec![], vec![]); + + let runtime_environment = RuntimeEnvironment::new(vec![]); + let module_storage = + module_bytes_storage.into_initia_module_storage(&runtime_environment, module_cache); + + assert_ok!(module_storage.fetch_deserialized_module(a_id.address(), a_id.name())); + assert_ok!(module_storage.fetch_deserialized_module(c_id.address(), c_id.name())); + module_storage.assert_cached_state( + vec![&a_id, &c_id], + vec![&checksum_a, &checksum_c], + vec![], + vec![], + ); + + assert_ok!(module_storage.fetch_verified_module(d_id.address(), d_id.name())); + module_storage.assert_cached_state( + vec![&a_id, &c_id], + vec![&checksum_a, &checksum_c], + vec![&d_id, &e_id, &f_id, &g_id], + vec![&checksum_d, &checksum_e, &checksum_f, &checksum_g], + ); + + assert_ok!(module_storage.fetch_verified_module(a_id.address(), a_id.name())); + module_storage.assert_cached_state( + vec![], + vec![], + vec![&a_id, &b_id, &c_id, &d_id, &e_id, &f_id, &g_id], + vec![ + &checksum_a, + &checksum_b, + &checksum_c, + &checksum_d, + &checksum_e, + &checksum_f, + &checksum_g, + ], + ); + } + + #[test] + fn test_cyclic_dependencies_traversal_fails() { + let mut module_bytes_storage = InMemoryStorage::new(); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + + let c_id = ModuleId::new(AccountAddress::ZERO, Identifier::new("c").unwrap()); + + add_module_bytes(&mut module_bytes_storage, "a", vec!["b"], vec![]); + add_module_bytes(&mut module_bytes_storage, "b", vec!["c"], vec![]); + add_module_bytes(&mut module_bytes_storage, "c", vec!["a"], vec![]); + + let runtime_environment = RuntimeEnvironment::new(vec![]); + let module_storage = + module_bytes_storage.into_initia_module_storage(&runtime_environment, module_cache); + + let result = module_storage.fetch_verified_module(c_id.address(), c_id.name()); + assert_eq!( + assert_err!(result).major_status(), + StatusCode::CYCLIC_MODULE_DEPENDENCY + ); + } + + #[test] + fn test_cyclic_friends_are_allowed() { + let mut module_bytes_storage = InMemoryStorage::new(); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + + let c_id = ModuleId::new(AccountAddress::ZERO, Identifier::new("c").unwrap()); + + add_module_bytes(&mut module_bytes_storage, "a", vec![], vec!["b"]); + add_module_bytes(&mut module_bytes_storage, "b", vec![], vec!["c"]); + let checksum_c = add_module_bytes(&mut module_bytes_storage, "c", vec![], vec!["a"]); + + let runtime_environment = RuntimeEnvironment::new(vec![]); + let module_storage = + module_bytes_storage.into_initia_module_storage(&runtime_environment, module_cache); + + let result = module_storage.fetch_verified_module(c_id.address(), c_id.name()); + assert_ok!(result); + + // Since `c` has no dependencies, only it gets deserialized and verified. + module_storage.assert_cached_state(vec![], vec![], vec![&c_id], vec![&checksum_c]); + } + + #[test] + fn test_transitive_friends_are_allowed_to_be_transitive_dependencies() { + let mut module_bytes_storage = InMemoryStorage::new(); + let module_cache = InitiaModuleCache::new(TEST_CACHE_CAPACITY); + + let a_id = ModuleId::new(AccountAddress::ZERO, Identifier::new("a").unwrap()); + let b_id = ModuleId::new(AccountAddress::ZERO, Identifier::new("b").unwrap()); + let c_id = ModuleId::new(AccountAddress::ZERO, Identifier::new("c").unwrap()); + + let checksum_a = add_module_bytes(&mut module_bytes_storage, "a", vec!["b"], vec!["d"]); + let checksum_b = add_module_bytes(&mut module_bytes_storage, "b", vec!["c"], vec![]); + let checksum_c = add_module_bytes(&mut module_bytes_storage, "c", vec![], vec![]); + add_module_bytes(&mut module_bytes_storage, "d", vec![], vec!["c"]); + + let runtime_environment = RuntimeEnvironment::new(vec![]); + let module_storage = + module_bytes_storage.into_initia_module_storage(&runtime_environment, module_cache); + + assert_ok!(module_storage.fetch_verified_module(a_id.address(), a_id.name())); + module_storage.assert_cached_state( + vec![], + vec![], + vec![&a_id, &b_id, &c_id], + vec![&checksum_a, &checksum_b, &checksum_c], + ); + } +} diff --git a/crates/storage/src/script_cache.rs b/crates/storage/src/script_cache.rs new file mode 100644 index 00000000..ec4a2587 --- /dev/null +++ b/crates/storage/src/script_cache.rs @@ -0,0 +1,104 @@ +use std::{hash::RandomState, num::NonZeroUsize, sync::Arc}; + +use clru::{CLruCache, CLruCacheConfig}; +use move_binary_format::{ + errors::{Location, PartialVMError, VMResult}, + file_format::CompiledScript, +}; +use move_core_types::vm_status::StatusCode; +use move_vm_runtime::Script; +use move_vm_types::code::Code; +use parking_lot::Mutex; + +use crate::{code_scale::CodeScale, state_view::Checksum}; + +pub struct InitiaScriptCache { + pub(crate) script_cache: + Mutex, RandomState, CodeScale>>, +} + +impl InitiaScriptCache { + pub fn new(cache_capacity: usize) -> Arc { + Arc::new(InitiaScriptCache { + script_cache: Mutex::new(CLruCache::with_config( + CLruCacheConfig::new(NonZeroUsize::new(cache_capacity).unwrap()) + .with_scale(CodeScale), + )), + }) + } +} + +// modified ScriptCache trait implementation +// we need error handling for the script cache +impl InitiaScriptCache { + pub(crate) fn insert_deserialized_script( + &self, + key: Checksum, + deserialized_script: CompiledScript, + ) -> VMResult> { + let mut script_cache = self.script_cache.lock(); + match script_cache.get(&key) { + Some(code) => Ok(code.deserialized().clone()), + None => { + let new_script = Code::from_deserialized(deserialized_script); + let deserialized_script = new_script.deserialized().clone(); + + // error occurs when the new script has a weight greater than the cache capacity + script_cache.put_with_weight(key, new_script).map_err(|_| { + PartialVMError::new(StatusCode::MEMORY_LIMIT_EXCEEDED) + .with_message("Script storage cache eviction error".to_string()) + .finish(Location::Script) + })?; + + Ok(deserialized_script) + } + } + } + + pub(crate) fn insert_verified_script( + &self, + key: Checksum, + verified_script: Script, + ) -> VMResult> { + let mut script_cache = self.script_cache.lock(); + + let (new_script, verified_script) = match script_cache.get(&key) { + Some(code) => { + if !code.is_verified() { + let new_script = Code::from_verified(verified_script); + let verified_script = new_script.verified().clone(); + (Some(new_script), verified_script) + } else { + (None, code.verified().clone()) + } + } + None => { + let new_script = Code::from_verified(verified_script); + let verified_script = new_script.verified().clone(); + (Some(new_script), verified_script) + } + }; + + if new_script.is_some() { + script_cache + .put_with_weight(key, new_script.unwrap()) + .map_err(|_| { + PartialVMError::new(StatusCode::MEMORY_LIMIT_EXCEEDED) + .with_message("Script storage cache eviction error".to_string()) + .finish(Location::Script) + })?; + } + Ok(verified_script) + } + + pub(crate) fn get_script(&self, key: &Checksum) -> Option> { + let mut script_cache = self.script_cache.lock(); + script_cache.get(key).cloned() + } + + #[allow(unused)] + pub(crate) fn num_scripts(&self) -> usize { + let script_cache = self.script_cache.lock(); + script_cache.len() + } +} diff --git a/crates/storage/src/state_view.rs b/crates/storage/src/state_view.rs index c70a4bd6..23de3939 100644 --- a/crates/storage/src/state_view.rs +++ b/crates/storage/src/state_view.rs @@ -8,6 +8,10 @@ use anyhow::Result; use bytes::Bytes; use initia_move_types::access_path::AccessPath; +use move_binary_format::errors::VMResult; +use move_core_types::{account_address::AccountAddress, identifier::IdentStr}; + +pub type Checksum = [u8; 32]; /// `StateView` is a trait that defines a read-only snapshot of the global state. It is passed to /// the VM for transaction execution, during which the VM is guaranteed to read anything at the @@ -16,3 +20,11 @@ pub trait StateView { /// Gets the state for a single access path. fn get(&self, access_path: &AccessPath) -> Result>; } + +pub trait ChecksumStorage { + fn fetch_checksum( + &self, + address: &AccountAddress, + module_name: &IdentStr, + ) -> VMResult>; +} diff --git a/crates/storage/src/state_view_impl.rs b/crates/storage/src/state_view_impl.rs index 9d88e95c..3aac756f 100644 --- a/crates/storage/src/state_view_impl.rs +++ b/crates/storage/src/state_view_impl.rs @@ -1,29 +1,31 @@ #![forbid(unsafe_code)] -use super::state_view::StateView; +use crate::state_view::{Checksum, ChecksumStorage, StateView}; use bytes::Bytes; use move_binary_format::deserializer::DeserializerConfig; -use move_binary_format::errors::{PartialVMError, PartialVMResult}; +use move_binary_format::errors::{Location, PartialVMError, PartialVMResult, VMResult}; use move_binary_format::CompiledModule; use move_bytecode_utils::compiled_module_viewer::CompiledModuleView; use move_core_types::account_address::AccountAddress; +use move_core_types::identifier::IdentStr; use move_core_types::language_storage::ModuleId; use move_core_types::language_storage::StructTag; use move_core_types::metadata::Metadata; use move_core_types::value::MoveTypeLayout; use move_core_types::vm_status::StatusCode; +use move_vm_types::code::ModuleBytesStorage; use move_vm_types::resolver::{resource_size, ModuleResolver, ResourceResolver}; use initia_move_types::access_path::AccessPath; -pub struct StateViewImpl<'block, S> { - state_view: &'block S, +pub struct StateViewImpl<'s, S> { + state_view: &'s S, deserialize_config: DeserializerConfig, } -impl<'block, S: StateView> StateViewImpl<'block, S> { - pub fn new(state_view: &'block S) -> Self { +impl<'s, S: StateView> StateViewImpl<'s, S> { + pub fn new(state_view: &'s S) -> Self { Self { state_view, deserialize_config: DeserializerConfig::default(), @@ -31,7 +33,7 @@ impl<'block, S: StateView> StateViewImpl<'block, S> { } pub fn new_with_deserialize_config( - state_view: &'block S, + state_view: &'s S, deserialize_config: DeserializerConfig, ) -> Self { Self { @@ -41,7 +43,7 @@ impl<'block, S: StateView> StateViewImpl<'block, S> { } } -impl<'block, S: StateView> StateViewImpl<'block, S> { +impl<'s, S: StateView> StateViewImpl<'s, S> { pub(crate) fn get(&self, access_path: &AccessPath) -> PartialVMResult> { self.state_view.get(access_path).map_err(|err| { PartialVMError::new(StatusCode::STORAGE_ERROR).with_message(err.to_string()) @@ -49,7 +51,58 @@ impl<'block, S: StateView> StateViewImpl<'block, S> { } } -impl<'block, S: StateView> ModuleResolver for StateViewImpl<'block, S> { +impl<'s, S: StateView> ChecksumStorage for StateViewImpl<'s, S> { + fn fetch_checksum( + &self, + address: &AccountAddress, + module_name: &IdentStr, + ) -> VMResult> { + let ap = AccessPath::checksum_access_path(*address, module_name.to_owned()); + match self.get(&ap).map_err(|e| { + e.finish(Location::Module(ModuleId::new( + *address, + module_name.to_owned(), + ))) + })? { + Some(b) => { + if b.len() != 32 { + return Err(PartialVMError::new(StatusCode::STORAGE_ERROR) + .with_message(format!("Checksum has an invalid length: {}", b.len())) + .finish(Location::Module(ModuleId::new( + *address, + module_name.to_owned(), + )))); + } + let mut checksum: Checksum = [0u8; 32]; + checksum.copy_from_slice(&b); + Ok(Some(checksum)) + } + None => Ok(None), + } + } +} + +impl<'s, S: StateView> ModuleBytesStorage for StateViewImpl<'s, S> { + fn fetch_module_bytes( + &self, + address: &AccountAddress, + module_name: &IdentStr, + ) -> VMResult> { + let module_id = ModuleId::new(*address, module_name.to_owned()); + let module_bytes = match self.get_module(&module_id).map_err(|e| { + e.finish(Location::Module(ModuleId::new( + *address, + module_name.to_owned(), + ))) + })? { + Some(bytes) => bytes, + _ => return Ok(None), + }; + Ok(Some(module_bytes)) + } +} + +impl<'s, S: StateView> ModuleResolver for StateViewImpl<'s, S> { fn get_module_metadata(&self, module_id: &ModuleId) -> Vec { let module_bytes = match self.get_module(module_id) { Ok(Some(bytes)) => bytes, @@ -66,13 +119,12 @@ impl<'block, S: StateView> ModuleResolver for StateViewImpl<'block, S> { } fn get_module(&self, module_id: &ModuleId) -> PartialVMResult> { - let ap = AccessPath::from(module_id); - + let ap = AccessPath::code_access_path(module_id.address, module_id.name.to_owned()); self.get(&ap) } } -impl<'block, S: StateView> ResourceResolver for StateViewImpl<'block, S> { +impl<'s, S: StateView> ResourceResolver for StateViewImpl<'s, S> { fn get_resource_bytes_with_metadata_and_layout( &self, address: &AccountAddress, @@ -87,7 +139,7 @@ impl<'block, S: StateView> ResourceResolver for StateViewImpl<'block, S> { } } -impl<'block, S: StateView> CompiledModuleView for StateViewImpl<'block, S> { +impl<'s, S: StateView> CompiledModuleView for StateViewImpl<'s, S> { type Item = CompiledModule; fn view_compiled_module(&self, id: &ModuleId) -> anyhow::Result> { diff --git a/crates/types/Cargo.toml b/crates/types/Cargo.toml index a9e512bf..7a3f8bb6 100644 --- a/crates/types/Cargo.toml +++ b/crates/types/Cargo.toml @@ -16,6 +16,7 @@ move-model = { workspace = true } move-coverage = { workspace = true } anyhow = { workspace = true } +bytes = {workspace = true} bcs = { workspace = true } serde = { workspace = true } serde_bytes = { workspace = true } diff --git a/crates/types/src/access_path.rs b/crates/types/src/access_path.rs index 2321525b..4579b640 100644 --- a/crates/types/src/access_path.rs +++ b/crates/types/src/access_path.rs @@ -67,6 +67,10 @@ impl AccessPath { AccessPath::new(address, Self::code_data_path(module_name)) } + pub fn checksum_access_path(address: AccountAddress, module_name: Identifier) -> AccessPath { + AccessPath::new(address, Self::checksum_data_path(module_name)) + } + pub fn table_item_access_path( handle /* Table Address */: AccountAddress, key: Vec, @@ -87,6 +91,10 @@ impl AccessPath { DataPath::Code(module_name) } + pub fn checksum_data_path(module_name: ModuleName) -> DataPath { + DataPath::Checksum(module_name) + } + pub fn table_item_data_path(key: Vec) -> DataPath { DataPath::TableItem(key) } @@ -133,12 +141,6 @@ impl fmt::Display for AccessPath { } } -impl From<&ModuleId> for AccessPath { - fn from(id: &ModuleId) -> AccessPath { - AccessPath::code_access_path(*id.address(), id.name().to_owned()) - } -} - impl From<&ResourceKey> for AccessPath { fn from(key: &ResourceKey) -> AccessPath { AccessPath::resource_access_path(key.address(), key.type_().clone()) @@ -148,6 +150,7 @@ impl From<&ResourceKey> for AccessPath { #[repr(u8)] pub enum DataType { Code, + Checksum, Resource, TableItem, TableInfo, @@ -159,6 +162,11 @@ impl DataType { pub fn is_code(self) -> bool { matches!(self, DataType::Code) } + + pub fn is_checksum(self) -> bool { + matches!(self, DataType::Checksum) + } + pub fn is_resource(self) -> bool { matches!(self, DataType::Resource) } @@ -177,6 +185,7 @@ impl DataType { pub fn from_index(idx: u8) -> Result { match idx { 0 => Ok(DataType::Code), + 1 => Ok(DataType::Checksum), 2 => Ok(DataType::Resource), 3 => Ok(DataType::TableItem), 4 => Ok(DataType::TableInfo), @@ -190,6 +199,7 @@ pub type ModuleName = Identifier; #[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Debug, Serialize, Deserialize)] pub enum DataPath { Code(ModuleName), + Checksum(ModuleName), Resource(StructTag), TableItem(Vec), TableInfo, @@ -200,6 +210,10 @@ impl DataPath { matches!(self, DataPath::Code(_)) } + pub fn is_checksum(&self) -> bool { + matches!(self, DataPath::Checksum(_)) + } + pub fn is_resource(&self) -> bool { matches!(self, DataPath::Resource(_)) } @@ -222,6 +236,7 @@ impl DataPath { pub fn data_type(&self) -> DataType { match self { DataPath::Code(_) => DataType::Code, + DataPath::Checksum(_) => DataType::Checksum, DataPath::Resource(_) => DataType::Resource, DataPath::TableItem(_) => DataType::TableItem, DataPath::TableInfo => DataType::TableInfo, @@ -235,6 +250,7 @@ impl DataPath { let prefix = self.data_type().storage_index(); let raw_key = match self { DataPath::Code(module_name) => bcs::to_bytes(module_name)?, + DataPath::Checksum(module_name) => bcs::to_bytes(module_name)?, DataPath::Resource(struct_tag) => bcs::to_bytes(struct_tag)?, DataPath::TableItem(key) => key.to_vec(), DataPath::TableInfo => vec![], @@ -255,6 +271,7 @@ impl DataPath { let data_type = DataType::from_index(data_type).map_err(|e| anyhow!(e))?; match data_type { DataType::Code => Ok(DataPath::Code(bcs::from_bytes(&val[1..])?)), + DataType::Checksum => Ok(DataPath::Checksum(bcs::from_bytes(&val[1..])?)), DataType::Resource => Ok(DataPath::Resource(bcs::from_bytes(&val[1..])?)), DataType::TableItem => Ok(DataPath::TableItem(val[1..].to_vec())), DataType::TableInfo => Ok(DataPath::TableInfo), @@ -273,6 +290,9 @@ impl fmt::Display for DataPath { DataPath::Code(module_name) => { write!(f, "{}/{}", storage_index, module_name) } + DataPath::Checksum(module_name) => { + write!(f, "{}/{}", storage_index, module_name) + } DataPath::Resource(struct_tag) => { write!(f, "{}/{}", storage_index, struct_tag) } @@ -300,6 +320,7 @@ impl FromStr for AccessPath { let data_path = match data_type { DataType::Code => AccessPath::code_data_path(Identifier::new(parts[2])?), + DataType::Checksum => AccessPath::checksum_data_path(Identifier::new(parts[2])?), DataType::Resource => AccessPath::resource_data_path(parse_struct_tag(parts[2])?), DataType::TableItem => AccessPath::table_item_data_path(decode_hex(parts[2])?), DataType::TableInfo => AccessPath::table_info_data_path(), diff --git a/crates/types/src/metadata.rs b/crates/types/src/metadata.rs index e3c3a558..2eb3daae 100644 --- a/crates/types/src/metadata.rs +++ b/crates/types/src/metadata.rs @@ -8,7 +8,10 @@ use serde::{Deserialize, Serialize}; pub const ERROR_PREFIX: &str = "E"; pub const VIEW_FUN_ATTRIBUTE: &str = "view"; pub const EVENT_STRUCT_ATTRIBUTE: &str = "event"; +pub const CODE_MODULE_NAME: &str = "code"; pub const INIT_MODULE_FUNCTION_NAME: &str = "init_module"; +pub const INIT_GENESIS_FUNCTION_NAME: &str = "init_genesis"; +pub const VERIFY_PUBLISH_REQUEST: &str = "verify_publish_request"; pub const METADATA_V0_MIN_FILE_FORMAT_VERSION: u32 = 6; /// The keys used to identify the metadata in the metadata section of the module bytecode. diff --git a/crates/types/src/module.rs b/crates/types/src/module.rs index c55a6f2a..e2b02201 100644 --- a/crates/types/src/module.rs +++ b/crates/types/src/module.rs @@ -6,6 +6,7 @@ use move_binary_format::errors::{PartialVMError, PartialVMResult}; use move_binary_format::CompiledModule; use move_core_types::language_storage::ModuleId; +use bytes::Bytes; use move_core_types::vm_status::StatusCode; use serde::{Deserialize, Serialize}; use std::collections::{BTreeMap, BTreeSet}; @@ -65,6 +66,13 @@ impl ModuleBundle { self.codes.into_iter().map(Module::into_inner).collect() } + pub fn into_bytes(self) -> Vec { + self.codes + .into_iter() + .map(|m| m.into_inner().into()) + .collect() + } + pub fn res(&mut self) -> Vec> { self.codes.iter().map(|m| m.code.clone()).collect() } diff --git a/crates/types/src/vm_config.rs b/crates/types/src/vm_config.rs index 42b29098..7108aafc 100644 --- a/crates/types/src/vm_config.rs +++ b/crates/types/src/vm_config.rs @@ -4,4 +4,16 @@ use serde::{Deserialize, Serialize}; #[allow(clippy::upper_case_acronyms)] pub struct InitiaVMConfig { pub allow_unstable: bool, + pub script_cache_capacity: usize, + pub module_cache_capacity: usize, +} + +impl Default for InitiaVMConfig { + fn default() -> Self { + Self { + allow_unstable: true, + script_cache_capacity: 100, + module_cache_capacity: 500, + } + } } diff --git a/crates/types/src/write_set.rs b/crates/types/src/write_set.rs index a4b883ad..608783f1 100644 --- a/crates/types/src/write_set.rs +++ b/crates/types/src/write_set.rs @@ -1,8 +1,6 @@ use crate::{access_path::AccessPath, table::TableChangeSet}; -use move_core_types::{ - effects::{ChangeSet, Op}, - language_storage::ModuleId, -}; +use anyhow::ensure; +use move_core_types::effects::{ChangeSet, Op}; use std::collections::{btree_map, BTreeMap}; pub type WriteOp = Op>; @@ -11,7 +9,14 @@ pub type WriteOp = Op>; pub struct WriteSet(BTreeMap); impl WriteSet { - pub fn new(change_set: ChangeSet, table_change_set: TableChangeSet) -> anyhow::Result { + pub fn new_with_write_set(write_set: BTreeMap) -> Self { + Self(write_set) + } + + pub fn new_with_change_set( + change_set: ChangeSet, + table_change_set: TableChangeSet, + ) -> anyhow::Result { let mut write_set: BTreeMap = BTreeMap::new(); for (addr, account_changeset) in change_set.into_inner() { let (modules, resources) = account_changeset.into_inner(); @@ -20,12 +25,11 @@ impl WriteSet { write_set.insert(ap, blob_opt.map(|v| v.into())); } - for (name, blob_opt) in modules.into_iter() { - // write module bytes changes - let module_id = ModuleId::new(addr, name); - let ap = AccessPath::from(&module_id); - write_set.insert(ap, blob_opt.map(|v| v.into())); - } + // unused in loader v2 + ensure!( + modules.is_empty(), + "Modules should not be present in the account change set in Loader v2" + ); } for (handle, changes) in table_change_set.changes.into_iter() { @@ -49,6 +53,12 @@ impl WriteSet { } } +impl Extend<(AccessPath, WriteOp)> for WriteSet { + fn extend>(&mut self, iter: I) { + self.0.extend(iter) + } +} + impl ::std::iter::FromIterator<(AccessPath, WriteOp)> for WriteSet { fn from_iter>(iter: I) -> Self { let mut ws = WriteSet::default(); diff --git a/crates/vm/Cargo.toml b/crates/vm/Cargo.toml index 89b226f3..3f03b009 100644 --- a/crates/vm/Cargo.toml +++ b/crates/vm/Cargo.toml @@ -38,7 +38,8 @@ thiserror = { workspace = true } bcs = { workspace = true } tempfile = { workspace = true } bigdecimal = { workspace = true } +bytes = { workspace = true } [dev-dependencies] triomphe = { workspace = true } -bytes = { workspace = true } + diff --git a/crates/vm/src/initia_vm.rs b/crates/vm/src/initia_vm.rs index 7bfcc28a..b738200d 100644 --- a/crates/vm/src/initia_vm.rs +++ b/crates/vm/src/initia_vm.rs @@ -1,16 +1,10 @@ use move_binary_format::{ - access::ModuleAccess, - compatibility::Compatibility, deserializer::DeserializerConfig, errors::{Location, PartialVMError, VMResult}, file_format::CompiledScript, - CompiledModule, }; use move_core_types::{ account_address::AccountAddress, - ident_str, - identifier::Identifier, - language_storage::ModuleId, value::{MoveTypeLayout, MoveValue}, vm_status::{StatusCode, VMStatus}, }; @@ -20,20 +14,21 @@ use move_vm_runtime::{ move_vm::MoveVM, native_extensions::NativeContextExtensions, session::SerializedReturnValues, + RuntimeEnvironment, }; -use move_vm_types::{gas::GasMeter, resolver::MoveResolver}; +use move_vm_types::resolver::MoveResolver; -use std::{collections::BTreeSet, sync::Arc}; +use std::sync::Arc; +use initia_move_gas::MiscGasParameters; use initia_move_gas::{ Gas, InitiaGasMeter, InitiaGasParameters, InitialGasSchedule, NativeGasParameters, }; -use initia_move_gas::{MiscGasParameters, NumBytes}; use initia_move_json::serialize_move_value_to_json_value; use initia_move_natives::{ account::{AccountAPI, NativeAccountContext}, all_natives, - code::{NativeCodeContext, PublishRequest}, + code::{NativeCodeContext, PublishRequest, UpgradePolicy}, cosmos::NativeCosmosContext, event::NativeEventContext, oracle::{NativeOracleContext, OracleAPI}, @@ -44,7 +39,10 @@ use initia_move_natives::{ use initia_move_natives::{ block::NativeBlockContext, staking::StakingAPI, table::NativeTableContext, }; -use initia_move_storage::table_resolver::TableResolver; +use initia_move_storage::{ + initia_storage::InitiaStorage, module_cache::InitiaModuleCache, + script_cache::InitiaScriptCache, state_view::StateView, table_resolver::TableResolver, +}; use initia_move_types::{ account::Accounts, cosmos::CosmosMessages, @@ -52,7 +50,6 @@ use initia_move_types::{ gas_usage::GasUsageSet, json_event::JsonEvents, message::{Message, MessageOutput, MessagePayload}, - metadata::INIT_MODULE_FUNCTION_NAME, module::ModuleBundle, staking_change_set::StakingChangeSet, view_function::{ViewFunction, ViewOutput}, @@ -63,28 +60,26 @@ use initia_move_types::{ use crate::{ session::{SessionExt, SessionOutput}, verifier::{ - config::verifier_config, errors::metadata_validation_error, - event_validation::verify_no_event_emission_in_script, metadata::get_vm_metadata, - module_init::verify_module_init_function, module_metadata::validate_publish_request, - script::reject_unstable_bytecode_for_script, + config::verifier_config, event_validation::verify_no_event_emission_in_script, + metadata::get_vm_metadata, script::reject_unstable_bytecode_for_script, transaction_arg_validation::validate_combine_signer_and_txn_args, - view_function::validate_view_function, + view_function::validate_view_function_and_construct, }, }; -#[derive(Clone)] #[allow(clippy::upper_case_acronyms)] pub struct InitiaVM { move_vm: Arc, gas_params: InitiaGasParameters, initia_vm_config: InitiaVMConfig, + runtime_environment: Arc, + script_cache: Arc, + module_cache: Arc, } impl Default for InitiaVM { fn default() -> Self { - Self::new(InitiaVMConfig { - allow_unstable: true, - }) + Self::new(InitiaVMConfig::default()) } } @@ -94,14 +89,24 @@ impl InitiaVM { let misc_params = MiscGasParameters::initial(); let vm_config = VMConfig { verifier_config: verifier_config(), + use_loader_v2: true, ..Default::default() }; - let move_vm = MoveVM::new_with_config(all_natives(gas_params, misc_params), vm_config); + let runtime_environment = Arc::new(RuntimeEnvironment::new_with_config( + all_natives(gas_params, misc_params), + vm_config, + )); + let move_vm = MoveVM::new_with_runtime_environment(&runtime_environment); + let script_cache = InitiaScriptCache::new(initia_vm_config.script_cache_capacity); + let module_cache = InitiaModuleCache::new(initia_vm_config.module_cache_capacity); Self { move_vm: Arc::new(move_vm), gas_params: InitiaGasParameters::initial(), initia_vm_config, + runtime_environment, + script_cache, + module_cache, } } @@ -110,15 +115,20 @@ impl InitiaVM { } #[inline(always)] - fn allow_unstable(&self) -> bool { + pub(crate) fn allow_unstable(&self) -> bool { self.initia_vm_config.allow_unstable } #[inline(always)] - pub fn deserialize_config(&self) -> &DeserializerConfig { + pub fn deserializer_config(&self) -> &DeserializerConfig { &self.move_vm.vm_config().deserializer_config } + #[inline(always)] + pub fn runtime_environment(&self) -> Arc { + self.runtime_environment.clone() + } + fn create_session< 'r, A: AccountAPI + StakingAPI + QueryAPI + OracleAPI, @@ -163,79 +173,57 @@ impl InitiaVM { #[allow(clippy::too_many_arguments)] pub fn initialize< - M: MoveResolver, + S: StateView, T: TableResolver, A: AccountAPI + StakingAPI + QueryAPI + OracleAPI, >( &mut self, api: &A, env: &Env, - state_view_impl: &M, - table_view_impl: &mut T, + storage: &S, + table_resolver: &mut T, module_bundle: ModuleBundle, allowed_publishers: Vec, ) -> Result { + let runtime_environment = self.runtime_environment(); + let code_storage = InitiaStorage::new( + storage, + &runtime_environment, + self.script_cache.clone(), + self.module_cache.clone(), + ); + let move_resolver = code_storage.state_view_impl(); + let gas_limit = Gas::new(u64::MAX); let gas_params = self.gas_params.clone(); let mut gas_meter = InitiaGasMeter::new(gas_params, gas_limit); - let mut session = self.create_session(api, env, state_view_impl, table_view_impl); + let session = self.create_session(api, env, move_resolver, table_resolver); let traversal_storage = TraversalStorage::new(); let mut traversal_context = TraversalContext::new(&traversal_storage); - let publish_request = PublishRequest { - destination: AccountAddress::ONE, - expected_modules: None, - module_bundle, - }; - - let published_module_ids = self.resolve_pending_code_publish( - state_view_impl, - &mut session, + let session_output = session.finish_with_module_publish( + self.deserializer_config(), + self.allow_unstable(), + &code_storage, &mut gas_meter, - publish_request, + PublishRequest { + publisher: AccountAddress::ONE, + module_bundle, + upgrade_policy: UpgradePolicy::Compatible, + }, &mut traversal_context, + Some(allowed_publishers), )?; - // execute code::init_genesis to properly store module metadata. - { - const CODE_MODULE_NAME: &str = "code"; - const INIT_GENESIS_FUNCTION_NAME: &str = "init_genesis"; - let args: Vec> = vec![ - MoveValue::Signer(AccountAddress::ONE) - .simple_serialize() - .unwrap(), - bcs::to_bytes(&published_module_ids).unwrap(), - bcs::to_bytes(&allowed_publishers).unwrap(), - ]; - - let function = session.load_function( - &ModuleId::new( - AccountAddress::ONE, - Identifier::new(CODE_MODULE_NAME).unwrap(), - ), - &Identifier::new(INIT_GENESIS_FUNCTION_NAME).unwrap(), - &[], - )?; - - // ignore the output - session.execute_entry_function( - function, - args, - &mut gas_meter, - &mut traversal_context, - )?; - } - // session cleanup - let session_output = session.finish()?; let output: MessageOutput = self.success_message_cleanup(session_output, &mut gas_meter)?; Ok(output) } pub fn execute_message< - M: MoveResolver, + S: StateView, T: TableResolver, A: AccountAPI + StakingAPI + QueryAPI + OracleAPI, >( @@ -243,22 +231,31 @@ impl InitiaVM { gas_meter: &mut InitiaGasMeter, api: &A, env: &Env, - state_view_impl: &M, - table_view_impl: &mut T, + storage: &S, + table_resolver: &mut T, msg: Message, ) -> Result { + let runtime_environment = self.runtime_environment(); + let senders = msg.senders().to_vec(); let traversal_storage = TraversalStorage::new(); let mut traversal_context = TraversalContext::new(&traversal_storage); + let code_storage = InitiaStorage::new( + storage, + &runtime_environment, + self.script_cache.clone(), + self.module_cache.clone(), + ); + // Charge for msg byte size gas_meter.charge_intrinsic_gas_for_transaction((msg.size() as u64).into())?; let res = self.execute_script_or_entry_function( api, env, - state_view_impl, - table_view_impl, + &code_storage, + table_resolver, senders, msg.payload(), gas_meter, @@ -269,7 +266,7 @@ impl InitiaVM { } pub fn execute_view_function< - M: MoveResolver, + S: StateView, T: TableResolver, A: AccountAPI + StakingAPI + QueryAPI + OracleAPI, >( @@ -277,23 +274,33 @@ impl InitiaVM { gas_meter: &mut InitiaGasMeter, api: &A, env: &Env, - state_view_impl: &M, - table_view_impl: &mut T, + storage: &S, + table_resolver: &mut T, view_fn: &ViewFunction, ) -> Result { - // flush loader cache if invalidated - self.move_vm.flush_loader_cache_if_invalidated(); - - let mut session = self.create_session(api, env, state_view_impl, table_view_impl); + let runtime_environment = self.runtime_environment(); + let code_storage = InitiaStorage::new( + storage, + &runtime_environment, + self.script_cache.clone(), + self.module_cache.clone(), + ); + let move_resolver = code_storage.state_view_impl(); + let mut session = self.create_session(api, env, move_resolver, table_resolver); let traversal_storage = TraversalStorage::new(); let mut traversal_context = TraversalContext::new(&traversal_storage); - let function = - session.load_function(view_fn.module(), view_fn.function(), view_fn.ty_args())?; - let metadata = get_vm_metadata(&session, view_fn.module()); - let args = validate_view_function( + let function = session.load_function( + &code_storage, + view_fn.module(), + view_fn.function(), + view_fn.ty_args(), + )?; + let metadata = get_vm_metadata(&code_storage, view_fn.module()); + + let args = validate_view_function_and_construct( &mut session, - state_view_impl, + &code_storage, view_fn.args().to_vec(), view_fn.function(), &function, @@ -311,6 +318,7 @@ impl InitiaVM { args, gas_meter, &mut traversal_context, + &code_storage, )?; // load fully annotated type layouts for return value serialization @@ -319,12 +327,13 @@ impl InitiaVM { .return_tys() .iter() .map(|ty| { - let ty_tag = session.get_type_tag(ty)?; - session.get_fully_annotated_type_layout(&ty_tag) + session + .inner + .get_fully_annotated_type_layout_from_ty(ty, &code_storage) }) .collect::>>()?; - let session_output = session.finish()?; + let session_output = session.finish(&code_storage)?; let (events, _, _, _, _) = session_output; let json_events = JsonEvents::new(events.into_iter().map(|e| e.into_inner()).collect()); let ret = serialize_response_to_json(&ret_ty_layouts, res)? @@ -335,28 +344,27 @@ impl InitiaVM { #[allow(clippy::too_many_arguments)] fn execute_script_or_entry_function< - M: MoveResolver, + S: StateView, T: TableResolver, A: AccountAPI + StakingAPI + QueryAPI + OracleAPI, >( &self, api: &A, env: &Env, - state_view_impl: &M, - table_view_impl: &mut T, + code_storage: &InitiaStorage, + table_resolver: &mut T, senders: Vec, payload: &MessagePayload, gas_meter: &mut InitiaGasMeter, traversal_context: &mut TraversalContext, ) -> Result { - // flush loader cache if invalidated - self.move_vm.flush_loader_cache_if_invalidated(); - - let mut session = self.create_session(api, env, state_view_impl, table_view_impl); + let move_resolver = code_storage.state_view_impl(); + let mut session = self.create_session(api, env, move_resolver, table_resolver); match payload { MessagePayload::Script(script) => { session.check_script_dependencies_and_check_gas( + code_storage, gas_meter, traversal_context, script.code(), @@ -364,11 +372,12 @@ impl InitiaVM { // we only use the ok path, let move vm handle the wrong path. // let Ok(s) = CompiledScript::deserialize(script.code()); - let function = session.load_script(script.code(), script.ty_args())?; + let function = + session.load_script(code_storage, script.code(), script.ty_args())?; let compiled_script = match CompiledScript::deserialize_with_config( script.code(), - self.deserialize_config(), + self.deserializer_config(), ) { Ok(script) => script, Err(err) => { @@ -389,7 +398,7 @@ impl InitiaVM { let args = validate_combine_signer_and_txn_args( &mut session, - state_view_impl, + code_storage, senders, script.args().to_vec(), &function, @@ -402,6 +411,7 @@ impl InitiaVM { args, gas_meter, traversal_context, + code_storage, ) } MessagePayload::Execute(entry_fn) => { @@ -409,12 +419,14 @@ impl InitiaVM { .referenced_module_ids .alloc(entry_fn.module().clone()); session.check_dependencies_and_charge_gas( + code_storage, gas_meter, traversal_context, [(module_id.address(), module_id.name())], )?; let function = session.load_function( + code_storage, entry_fn.module(), entry_fn.function(), entry_fn.ty_args(), @@ -433,9 +445,11 @@ impl InitiaVM { ); } + // need check function.is_friend_or_private() ?? + let args = validate_combine_signer_and_txn_args( &mut session, - state_view_impl, + code_storage, senders, entry_fn.args().to_vec(), &function, @@ -445,24 +459,29 @@ impl InitiaVM { // first execution does not execute `charge_call`, so need to record call here gas_meter.record_call(entry_fn.module()); - session.execute_entry_function(function, args, gas_meter, traversal_context) + session.execute_entry_function( + function, + args, + gas_meter, + traversal_context, + code_storage, + ) } }?; - if let Some(publish_request) = session.extract_publish_request() { - // mark loader cache as invalid until loader v2 is implemented - self.move_vm.mark_loader_cache_as_invalid(); - - self.resolve_pending_code_publish( - state_view_impl, - &mut session, + let session_output = if let Some(publish_request) = session.extract_publish_request() { + session.finish_with_module_publish( + self.deserializer_config(), + self.allow_unstable(), + code_storage, gas_meter, publish_request, traversal_context, - )?; - } - - let session_output = session.finish()?; + None, + )? + } else { + session.finish(code_storage)? + }; // Charge for gas cost for write set ops gas_meter.charge_write_set_gas(&session_output.1)?; @@ -471,194 +490,6 @@ impl InitiaVM { Ok(output) } - /// Resolve a pending code publish request registered via the NativeCodeContext. - fn resolve_pending_code_publish( - &self, - resolver: &M, - session: &mut SessionExt, - gas_meter: &mut InitiaGasMeter, - publish_request: PublishRequest, - traversal_context: &mut TraversalContext, - ) -> VMResult> { - let PublishRequest { - destination, - module_bundle, - expected_modules, - } = publish_request; - - let modules = self.deserialize_module_bundle(&module_bundle)?; - let modules: &Vec = - traversal_context.referenced_module_bundles.alloc(modules); - - // Note: Feature gating is needed here because the traversal of the dependencies could - // result in shallow-loading of the modules and therefore subtle changes in - // the error semantics. - { - // Charge old versions of existing modules, in case of upgrades. - for module in modules.iter() { - let id = module.self_id(); - let addr = module.self_addr(); - let name = module.self_name(); - - // TODO: Allow the check of special addresses to be customized. - if addr.is_special() || traversal_context.visited.insert((addr, name), ()).is_some() - { - continue; - } - - let size_if_module_exists = resolver - .get_module(&id) - .map_err(|e| e.finish(Location::Undefined))? - .map(|m| m.len() as u64); - - if let Some(size) = size_if_module_exists { - gas_meter - .charge_dependency(false, addr, name, NumBytes::new(size)) - .map_err(|err| { - err.finish(Location::Module(ModuleId::new(*addr, name.to_owned()))) - })?; - } - } - - // Charge all modules in the bundle that is about to be published. - for (module, blob) in modules.iter().zip(module_bundle.iter()) { - let module_id = &module.self_id(); - gas_meter - .charge_dependency( - true, - module_id.address(), - module_id.name(), - NumBytes::new(blob.code().len() as u64), - ) - .map_err(|err| err.finish(Location::Undefined))?; - } - - // Charge all dependencies. - // - // Must exclude the ones that are in the current bundle because they have not - // been published yet. - let module_ids_in_bundle = modules - .iter() - .map(|module| (module.self_addr(), module.self_name())) - .collect::>(); - - session.check_dependencies_and_charge_gas( - gas_meter, - traversal_context, - modules - .iter() - .flat_map(|module| { - module - .immediate_dependencies_iter() - .chain(module.immediate_friends_iter()) - }) - .filter(|addr_and_name| !module_ids_in_bundle.contains(addr_and_name)), - )?; - } - - // validate modules are properly compiled with metadata - validate_publish_request(session, modules, &module_bundle, self.allow_unstable())?; - - if let Some(expected_modules) = expected_modules { - for (m, expected_id) in modules.iter().zip(expected_modules.iter()) { - if m.self_id().short_str_lossless().as_str() != expected_id { - return Err(metadata_validation_error(&format!( - "unexpected module: '{}', expected: '{}'", - m.self_id().name(), - expected_id - ))); - } - } - } - - // Check what modules exist before publishing. - let mut exists = BTreeSet::new(); - for m in modules.iter() { - let id = m.self_id(); - - if session.exists_module(&id)? { - exists.insert(id); - } - } - - // sort the modules by dependencies - let (sorted_module_bundle, published_module_ids, sorted_compiled_modules) = module_bundle - .sorted_code_and_modules(modules) - .map_err(|e| e.finish(Location::Undefined))?; - - // publish and cache the modules on loader cache. - session.publish_module_bundle_with_compat_config( - sorted_module_bundle.into_inner(), - destination, - gas_meter, - // treat friends as private - Compatibility::new(true, false), - )?; - - // call init function of the each module - self.execute_module_initialization( - session, - gas_meter, - sorted_compiled_modules, - exists, - &[destination], - traversal_context, - )?; - - Ok(published_module_ids) - } - - /// Execute all module initializers. - fn execute_module_initialization( - &self, - session: &mut SessionExt, - gas_meter: &mut InitiaGasMeter, - modules: Vec<&CompiledModule>, - exists: BTreeSet, - senders: &[AccountAddress], - traversal_context: &mut TraversalContext, - ) -> VMResult<()> { - let init_func_name = ident_str!(INIT_MODULE_FUNCTION_NAME); - for module in modules { - if exists.contains(&module.self_id()) { - // Call initializer only on first publish. - continue; - } - - let init_function = session.load_function(&module.self_id(), init_func_name, &[]); - // it is ok to not have init_module function - // init_module function should be (1) private and (2) has no return value - // Note that for historic reasons, verification here is treated - // as StatusCode::CONSTRAINT_NOT_SATISFIED, there this cannot be unified - // with the general verify_module above. - if init_function.is_ok() { - if verify_module_init_function(module).is_ok() { - let args: Vec> = senders - .iter() - .map(|s| MoveValue::Signer(*s).simple_serialize().unwrap()) - .collect(); - - // first execution does not execute `charge_call`, so need to record call here - gas_meter.record_call(&module.self_id()); - - session.execute_function_bypass_visibility( - &module.self_id(), - init_func_name, - vec![], - args, - gas_meter, - traversal_context, - )?; - } else { - return Err(PartialVMError::new(StatusCode::CONSTRAINT_NOT_SATISFIED) - .finish(Location::Module(module.self_id()))); - } - } - } - - Ok(()) - } - fn success_message_cleanup( &self, session_output: SessionOutput, @@ -677,26 +508,6 @@ impl InitiaVM { gas_usage_set, )) } - - /// Deserialize a module bundle. - fn deserialize_module_bundle( - &self, - module_bundle: &ModuleBundle, - ) -> VMResult> { - let mut result = vec![]; - for module_blob in module_bundle.iter() { - match CompiledModule::deserialize_with_config( - module_blob.code(), - self.deserialize_config(), - ) { - Ok(module) => { - result.push(module); - } - Err(err) => return Err(err.finish(Location::Undefined)), - } - } - Ok(result) - } } fn serialize_response_to_json( diff --git a/crates/vm/src/lib.rs b/crates/vm/src/lib.rs index e1dd646d..b6060da1 100644 --- a/crates/vm/src/lib.rs +++ b/crates/vm/src/lib.rs @@ -1,6 +1,6 @@ -mod session; - pub use crate::initia_vm::InitiaVM; mod initia_vm; +mod publish; +mod session; mod verifier; diff --git a/crates/vm/src/publish.rs b/crates/vm/src/publish.rs new file mode 100644 index 00000000..08ffbc5a --- /dev/null +++ b/crates/vm/src/publish.rs @@ -0,0 +1,345 @@ +use std::collections::BTreeSet; + +use initia_move_gas::{InitiaGasMeter, NumBytes}; +use initia_move_natives::code::{PublishRequest, UpgradePolicy}; +use initia_move_storage::{initia_storage::InitiaStorage, state_view::StateView}; +use initia_move_types::{ + metadata::{ + CODE_MODULE_NAME, INIT_GENESIS_FUNCTION_NAME, INIT_MODULE_FUNCTION_NAME, + VERIFY_PUBLISH_REQUEST, + }, + module::ModuleBundle, +}; + +use move_binary_format::{ + access::ModuleAccess, + compatibility::Compatibility, + deserializer::DeserializerConfig, + errors::{Location, VMResult}, + CompiledModule, +}; +use move_core_types::{ + account_address::AccountAddress, ident_str, identifier::Identifier, language_storage::ModuleId, + value::MoveValue, +}; +use move_vm_runtime::{module_traversal::TraversalContext, ModuleStorage, StagingModuleStorage}; +use move_vm_types::gas::GasMeter; + +use crate::verifier::module_init::verify_module_init_function; +use crate::{ + session::{SessionExt, SessionOutput}, + verifier::module_metadata::validate_publish_request, +}; + +impl<'r, 'l> SessionExt<'r, 'l> { + #[allow(clippy::too_many_arguments)] + pub(crate) fn finish_with_module_publish( + mut self, + deserializer_config: &DeserializerConfig, + allow_unstable: bool, + code_storage: &InitiaStorage, + gas_meter: &mut InitiaGasMeter, + publish_request: PublishRequest, + traversal_context: &mut TraversalContext, + init_genesis_opts: Option>, + ) -> VMResult> { + let PublishRequest { + publisher, + module_bundle, + upgrade_policy, + } = publish_request; + + let modules = deserialize_module_bundle(&module_bundle, deserializer_config)?; + let modules: &Vec = + traversal_context.referenced_module_bundles.alloc(modules); + + self.check_publish_request( + code_storage, + gas_meter, + publisher, + &module_bundle, + modules, + upgrade_policy, + traversal_context, + allow_unstable, + init_genesis_opts.is_some(), + )?; + + let staging_module_storage = StagingModuleStorage::create_with_compat_config( + &publisher, + Compatibility::new(true, false), + code_storage, + module_bundle.into_bytes(), + )?; + + self.initialize_module( + code_storage, + gas_meter, + traversal_context, + &staging_module_storage, + publisher, + modules, + )?; + + if let Some(allowed_publishers) = init_genesis_opts { + self.initialize_genesis( + gas_meter, + traversal_context, + &staging_module_storage, + modules, + allowed_publishers, + )?; + } + + let mut output = self.finish(&staging_module_storage)?; + let module_write_set = Self::convert_modules_into_write_set( + code_storage, + staging_module_storage + .release_verified_module_bundle() + .into_iter(), + ) + .map_err(|e| e.finish(Location::Undefined))?; + output.1.extend(module_write_set); + Ok(output) + } + + pub(crate) fn initialize_module( + &mut self, + code_storage: &InitiaStorage, + gas_meter: &mut InitiaGasMeter, + traversal_context: &mut TraversalContext, + staging_module_storage: &StagingModuleStorage, + destination: AccountAddress, + modules: &[CompiledModule], + ) -> VMResult<()> { + let init_func_name = ident_str!(INIT_MODULE_FUNCTION_NAME); + for module in modules { + // Check if module existed previously. If not, we do not run initialization. + if code_storage.check_module_exists(module.self_addr(), module.self_name())? { + continue; + } + + let module_id = module.self_id(); + let init_function_exists = self + .inner + .load_function(staging_module_storage, &module_id, init_func_name, &[]) + .is_ok(); + + if init_function_exists { + // We need to check that init_module function we found is well-formed. + verify_module_init_function(module).map_err(|e| e.finish(Location::Undefined))?; + + self.inner.execute_function_bypass_visibility( + &module_id, + init_func_name, + vec![], + vec![MoveValue::Signer(destination).simple_serialize().unwrap()], + gas_meter, + traversal_context, + staging_module_storage, + )?; + } + } + Ok(()) + } + + /// Special function to initialize the genesis block. This function is only called once per + /// blockchain genesis. It is used to initialize the blockchain by setting genesis modules with + /// allowed publishers. + pub(crate) fn initialize_genesis( + &mut self, + gas_meter: &mut InitiaGasMeter, + traversal_context: &mut TraversalContext, + staging_module_storage: &StagingModuleStorage, + modules: &[CompiledModule], + allowed_publishers: Vec, + ) -> VMResult<()> { + let published_module_ids: Vec = modules + .iter() + .map(|m| m.self_id().short_str_lossless()) + .collect(); + + // ignore the output + self.inner.execute_function_bypass_visibility( + &ModuleId::new( + AccountAddress::ONE, + Identifier::new(CODE_MODULE_NAME).unwrap(), + ), + ident_str!(INIT_GENESIS_FUNCTION_NAME), + vec![], + vec![ + MoveValue::Signer(AccountAddress::ONE) + .simple_serialize() + .unwrap(), + bcs::to_bytes(&published_module_ids).unwrap(), + bcs::to_bytes(&allowed_publishers).unwrap(), + ], + gas_meter, + traversal_context, + staging_module_storage, + )?; + Ok(()) + } + + #[allow(clippy::too_many_arguments)] + pub(crate) fn check_publish_request<'a, S: StateView>( + &mut self, + code_storage: &InitiaStorage, + gas_meter: &mut InitiaGasMeter, + publisher: AccountAddress, + module_bundle: &ModuleBundle, + modules: &'a [CompiledModule], + upgrade_policy: UpgradePolicy, + traversal_context: &mut TraversalContext<'a>, + allow_unsafe: bool, + skip_dependencies_upgrade_policy_verification: bool, + ) -> VMResult<()> { + // Note: Feature gating is needed here because the traversal of the dependencies could + // result in shallow-loading of the modules and therefore subtle changes in + // the error semantics. + { + // Charge old versions of existing modules, in case of upgrades. + for module in modules.iter() { + let addr = module.self_addr(); + let name = module.self_name(); + + // TODO: Allow the check of special addresses to be customized. + if addr.is_special() || traversal_context.visited.insert((addr, name), ()).is_some() + { + continue; + } + + if let Some(size) = code_storage + .fetch_module_size_in_bytes(addr, name)? + .map(|v| v as u64) + { + gas_meter + .charge_dependency(false, addr, name, NumBytes::new(size)) + .map_err(|err| { + err.finish(Location::Module(ModuleId::new(*addr, name.to_owned()))) + })?; + } + } + + // Charge all modules in the bundle that is about to be published. + for (module, blob) in modules.iter().zip(module_bundle.iter()) { + let module_id = &module.self_id(); + gas_meter + .charge_dependency( + true, + module_id.address(), + module_id.name(), + NumBytes::new(blob.code().len() as u64), + ) + .map_err(|err| err.finish(Location::Undefined))?; + } + + // Charge all dependencies. + // + // Must exclude the ones that are in the current bundle because they have not + // been published yet. + let module_ids_in_bundle = modules + .iter() + .map(|module| (module.self_addr(), module.self_name())) + .collect::>(); + + self.check_dependencies_and_charge_gas( + code_storage, + gas_meter, + traversal_context, + modules + .iter() + .flat_map(|module| { + module + .immediate_dependencies_iter() + .chain(module.immediate_friends_iter()) + }) + .filter(|addr_and_name| !module_ids_in_bundle.contains(addr_and_name)), + )?; + } + + // validate modules are properly compiled with metadata + validate_publish_request(code_storage, modules, module_bundle, allow_unsafe)?; + + // validate dependencies upgrade policy + if !skip_dependencies_upgrade_policy_verification { + self.verify_dependencies_upgrade_policy( + gas_meter, + code_storage, + traversal_context, + publisher, + modules, + upgrade_policy, + )?; + } + + Ok(()) + } + + fn verify_dependencies_upgrade_policy( + &mut self, + gas_meter: &mut InitiaGasMeter, + module_storage: &impl ModuleStorage, + traversal_context: &mut TraversalContext<'_>, + publisher: AccountAddress, + modules: &[CompiledModule], + upgrade_policy: UpgradePolicy, + ) -> VMResult<()> { + let mut module_ids = vec![]; + let mut dependency_addresses = vec![]; + let mut dependency_module_ids = vec![]; + for module in modules { + let mut deps_addresses = vec![]; + let mut deps_module_ids = vec![]; + for dep in module.immediate_dependencies() { + // allow a special addresses to be used as dependencies, + // even they are having a weaker upgrade policy. + if AccountAddress::is_special(dep.address()) { + continue; + } + + deps_addresses.push(dep.address().to_owned()); + deps_module_ids.push(dep.short_str_lossless()); + } + + module_ids.push(module.self_id().short_str_lossless()); + dependency_addresses.push(deps_addresses); + dependency_module_ids.push(deps_module_ids); + } + + let _ = self.inner.execute_function_bypass_visibility( + &ModuleId::new(AccountAddress::ONE, ident_str!(CODE_MODULE_NAME).into()), + ident_str!(VERIFY_PUBLISH_REQUEST), + vec![], + vec![ + MoveValue::Signer(publisher).simple_serialize().unwrap(), + bcs::to_bytes(&module_ids).unwrap(), + bcs::to_bytes(&dependency_addresses).unwrap(), + bcs::to_bytes(&dependency_module_ids).unwrap(), + bcs::to_bytes(&upgrade_policy.to_u8()).unwrap(), + ], + gas_meter, + traversal_context, + module_storage, + )?; + + Ok(()) + } +} + +fn deserialize_module_bundle( + module_bundle: &ModuleBundle, + deserializer_config: &DeserializerConfig, +) -> VMResult> { + let mut result = vec![]; + for module_blob in module_bundle.iter() { + match CompiledModule::deserialize_with_config(module_blob.code(), deserializer_config) { + Ok(module) => { + result.push(module); + } + Err(err) => return Err(err.finish(Location::Undefined)), + } + } + + Ok(result) +} diff --git a/crates/vm/src/session.rs b/crates/vm/src/session.rs index 2587bb67..9ddf25ba 100644 --- a/crates/vm/src/session.rs +++ b/crates/vm/src/session.rs @@ -1,8 +1,10 @@ use std::{ + collections::BTreeMap, ops::{Deref, DerefMut}, sync::Arc, }; +use bytes::Bytes; use initia_move_json::StructResolver; use initia_move_natives::{ account::NativeAccountContext, @@ -13,14 +15,25 @@ use initia_move_natives::{ table::NativeTableContext, }; use initia_move_types::{ - account::Accounts, cosmos::CosmosMessages, event::ContractEvent, - staking_change_set::StakingChangeSet, write_set::WriteSet, + access_path::AccessPath, + account::Accounts, + cosmos::CosmosMessages, + event::ContractEvent, + staking_change_set::StakingChangeSet, + write_set::{WriteOp, WriteSet}, }; -use move_binary_format::errors::{Location, PartialVMError, VMResult}; -use move_core_types::{language_storage::TypeTag, vm_status::StatusCode}; -use move_vm_runtime::session::Session; -use move_vm_types::loaded_data::runtime_types::{StructNameIndex, StructType, Type}; +use move_binary_format::errors::{Location, PartialVMError, PartialVMResult, VMResult}; +use move_core_types::{ + effects::Op, + language_storage::{ModuleId, TypeTag}, + vm_status::StatusCode, +}; +use move_vm_runtime::{session::Session, ModuleStorage}; +use move_vm_types::{ + loaded_data::runtime_types::{StructNameIndex, StructType, Type}, + sha3_256, +}; pub type SessionOutput<'r> = ( Vec, @@ -31,7 +44,7 @@ pub type SessionOutput<'r> = ( ); pub struct SessionExt<'r, 'l> { - inner: Session<'r, 'l>, + pub(crate) inner: Session<'r, 'l>, } impl<'r, 'l> SessionExt<'r, 'l> { @@ -39,8 +52,10 @@ impl<'r, 'l> SessionExt<'r, 'l> { Self { inner } } - pub fn finish(self) -> VMResult> { - let (change_set, mut extensions) = self.inner.finish_with_extensions()?; + pub fn finish(self, module_storage: &impl ModuleStorage) -> VMResult { + let Self { inner } = self; + + let (change_set, mut extensions) = inner.finish_with_extensions(module_storage)?; let event_context: NativeEventContext = extensions.remove::(); let events = event_context.into_events(); @@ -59,11 +74,12 @@ impl<'r, 'l> SessionExt<'r, 'l> { let new_accounts = account_context.into_accounts(); // build output change set from the changes - let write_set = WriteSet::new(change_set, table_change_set).map_err(|e| { - PartialVMError::new(StatusCode::FAILED_TO_SERIALIZE_WRITE_SET_CHANGES) - .with_message(e.to_string()) - .finish(Location::Undefined) - })?; + let write_set = + WriteSet::new_with_change_set(change_set, table_change_set).map_err(|e| { + PartialVMError::new(StatusCode::FAILED_TO_SERIALIZE_WRITE_SET_CHANGES) + .with_message(e.to_string()) + .finish(Location::Undefined) + })?; Ok(( events, @@ -78,15 +94,54 @@ impl<'r, 'l> SessionExt<'r, 'l> { let ctx = self.get_native_extensions().get_mut::(); ctx.requested_module_bundle.take() } + + /// Converts module bytes and their compiled representation extracted from publish request into + /// write ops. Only used by V2 loader implementation. + pub fn convert_modules_into_write_set( + module_storage: &impl ModuleStorage, + staged_modules: impl Iterator, + ) -> PartialVMResult { + let mut module_write_set: BTreeMap = BTreeMap::new(); + for (module_id, bytes) in staged_modules { + let module_exists = module_storage + .check_module_exists(&module_id.address, &module_id.name) + .map_err(|e| e.to_partial())?; + let op = if module_exists { + Op::Modify(bytes) + } else { + Op::New(bytes) + }; + let ap = AccessPath::code_access_path(module_id.address, module_id.name.to_owned()); + module_write_set.insert(ap, op.clone().map(|v| v.into())); + + let ap = AccessPath::checksum_access_path(module_id.address, module_id.name.to_owned()); + module_write_set.insert( + ap, + op.map(|v| { + let checksum = sha3_256(&v); + checksum.into() + }), + ); + } + Ok(WriteSet::new_with_write_set(module_write_set)) + } } impl StructResolver for SessionExt<'_, '_> { - fn get_struct_type(&self, index: StructNameIndex) -> Option> { - self.inner.get_struct_type(index) + fn get_struct_type( + &self, + index: StructNameIndex, + module_storage: &impl ModuleStorage, + ) -> Option> { + self.inner.fetch_struct_ty_by_idx(index, module_storage) } - fn get_type_tag(&self, ty: &Type) -> VMResult { - self.inner.get_type_tag(ty) + fn type_to_type_tag( + &self, + ty: &Type, + module_storage: &impl ModuleStorage, + ) -> VMResult { + self.inner.get_type_tag(ty, module_storage) } } diff --git a/crates/vm/src/verifier/config.rs b/crates/vm/src/verifier/config.rs index 17f91ac7..11df20c6 100644 --- a/crates/vm/src/verifier/config.rs +++ b/crates/vm/src/verifier/config.rs @@ -10,7 +10,6 @@ pub fn verifier_config() -> VerifierConfig { max_value_stack_size: 1024, max_type_nodes: Some(256), max_push_size: Some(10000), - max_dependency_depth: Some(100), max_struct_definitions: Some(200), max_fields_in_struct: Some(30), max_struct_variants: Some(90), diff --git a/crates/vm/src/verifier/event_validation.rs b/crates/vm/src/verifier/event_validation.rs index c9aeb466..bd7dfbca 100644 --- a/crates/vm/src/verifier/event_validation.rs +++ b/crates/vm/src/verifier/event_validation.rs @@ -14,7 +14,7 @@ use move_binary_format::{ use move_core_types::{ account_address::AccountAddress, language_storage::ModuleId, vm_status::StatusCode, }; -use move_vm_runtime::session::Session; +use move_vm_runtime::ModuleStorage; use std::collections::HashSet; use super::metadata::get_metadata_from_compiled_module; @@ -36,7 +36,7 @@ fn metadata_validation_error(msg: &str) -> VMError { /// * Extract the event metadata /// * Verify all changes are compatible upgrades (existing event attributes cannot be removed) pub(crate) fn validate_module_events( - session: &Session, + module_storage: &impl ModuleStorage, modules: &[CompiledModule], ) -> VMResult<()> { for module in modules { @@ -51,7 +51,7 @@ pub(crate) fn validate_module_events( validate_emit_calls(&new_event_structs, module)?; let original_event_structs = - extract_event_metadata_from_module(session, &module.self_id())?; + extract_event_metadata_from_module(module_storage, &module.self_id())?; for member in original_event_structs { // Fail if we see a removal of an event attribute. @@ -119,18 +119,14 @@ pub(crate) fn validate_emit_calls( /// Given a module id extract all event metadata pub(crate) fn extract_event_metadata_from_module( - session: &Session, + module_storage: &impl ModuleStorage, module_id: &ModuleId, ) -> VMResult> { - let metadata = session.load_module(module_id).map(|module| { - CompiledModule::deserialize_with_config( - &module, - &session.get_vm_config().deserializer_config, - ) - .map(|module| get_metadata_from_compiled_module(&module)) - }); + let metadata = module_storage + .fetch_deserialized_module(module_id.address(), module_id.name())? + .map(|module| get_metadata_from_compiled_module(module.as_ref())); - if let Ok(Ok(Some(metadata))) = metadata { + if let Some(Some(metadata)) = metadata { extract_event_metadata(&metadata) } else { Ok(HashSet::new()) diff --git a/crates/vm/src/verifier/metadata.rs b/crates/vm/src/verifier/metadata.rs index 41cba72e..99f8017f 100644 --- a/crates/vm/src/verifier/metadata.rs +++ b/crates/vm/src/verifier/metadata.rs @@ -1,9 +1,9 @@ /// Extract metadata from the VM, upgrading V0 to V1 representation as needed -use crate::session::SessionExt; use initia_move_types::metadata::{RuntimeModuleMetadataV0, INITIA_METADATA_KEY_V0}; use move_binary_format::{file_format::CompiledScript, CompiledModule}; use move_core_types::{language_storage::ModuleId, metadata::Metadata}; use move_model::metadata::{CompilationMetadata, COMPILATION_METADATA_KEY}; +use move_vm_runtime::ModuleStorage; /// Extract metadata from the VM, upgrading V0 to V1 representation as needed pub fn get_metadata(md: &[Metadata]) -> Option { @@ -15,12 +15,13 @@ pub fn get_metadata(md: &[Metadata]) -> Option { } pub(crate) fn get_vm_metadata( - session: &SessionExt, + module_storage: &impl ModuleStorage, module_id: &ModuleId, ) -> Option { - session - .get_move_vm() - .with_module_metadata(module_id, get_metadata) + let metadata = module_storage + .fetch_module_metadata(module_id.address(), module_id.name()) + .ok()??; + get_metadata(&metadata) } /// Extract metadata from a compiled module, upgrading V0 to V1 representation as needed. diff --git a/crates/vm/src/verifier/module_metadata.rs b/crates/vm/src/verifier/module_metadata.rs index 4b65bacf..14a7ba73 100644 --- a/crates/vm/src/verifier/module_metadata.rs +++ b/crates/vm/src/verifier/module_metadata.rs @@ -17,7 +17,7 @@ use move_core_types::{ vm_status::StatusCode, }; use move_model::metadata::{CompilationMetadata, COMPILATION_METADATA_KEY}; -use move_vm_runtime::session::Session; +use move_vm_runtime::ModuleStorage; use super::{ errors::{ @@ -30,7 +30,7 @@ use super::{ }; pub(crate) fn validate_publish_request( - session: &Session, + module_storage: &impl ModuleStorage, modules: &[CompiledModule], module_bundle: &ModuleBundle, allow_unstable: bool, @@ -47,7 +47,7 @@ pub(crate) fn validate_publish_request( validate_module_metadata(module).map_err(|e| metadata_validation_error(&e.to_string()))?; } - validate_module_events(session, modules) + validate_module_events(module_storage, modules) .map_err(|e| metadata_validation_error(&e.to_string()))?; Ok(()) diff --git a/crates/vm/src/verifier/transaction_arg_validation.rs b/crates/vm/src/verifier/transaction_arg_validation.rs index e5f3e2bb..b3bea33b 100644 --- a/crates/vm/src/verifier/transaction_arg_validation.rs +++ b/crates/vm/src/verifier/transaction_arg_validation.rs @@ -1,3 +1,5 @@ +use initia_move_storage::initia_storage::InitiaStorage; +use initia_move_storage::state_view::StateView; use move_binary_format::errors::{Location, PartialVMError}; use move_binary_format::file_format::FunctionDefinitionIndex; use move_binary_format::file_format_common::read_uleb128_as_u64; @@ -8,11 +10,10 @@ use move_core_types::vm_status::VMStatus; use move_core_types::{account_address::AccountAddress, value::MoveValue, vm_status::StatusCode}; use move_vm_runtime::module_traversal::{TraversalContext, TraversalStorage}; use move_vm_runtime::session::Session; -use move_vm_runtime::LoadedFunction; +use move_vm_runtime::{LoadedFunction, ModuleStorage}; use move_vm_types::gas::{GasMeter, UnmeteredGasMeter}; use move_vm_types::loaded_data::runtime_types::Type; -use move_vm_types::resolver::MoveResolver; use once_cell::sync::Lazy; use std::io::Read; use std::{collections::BTreeMap, io::Cursor}; @@ -112,9 +113,9 @@ pub(crate) static ALLOWED_STRUCTS: ConstructorMap = Lazy::new(|| { /// 3. check arg types are allowed after signers /// /// after validation, add senders and non-signer arguments to generate the final args -pub fn validate_combine_signer_and_txn_args( +pub fn validate_combine_signer_and_txn_args( session: &mut SessionExt, - state_view: &M, + code_storage: &InitiaStorage, senders: Vec, args: Vec>, func: &LoadedFunction, @@ -148,7 +149,7 @@ pub fn validate_combine_signer_and_txn_args( for ty in func.param_tys()[signer_param_cnt..].iter() { let subst_res = ty_builder.create_ty_with_subst(ty, func.ty_args()); let ty = subst_res.map_err(|e| e.finish(Location::Undefined).into_vm_status())?; - let valid = is_valid_txn_arg(session, &ty, allowed_structs); + let valid = is_valid_txn_arg(session, code_storage, &ty, allowed_structs); if !valid { return Err(VMStatus::error( StatusCode::INVALID_MAIN_FUNCTION_SIGNATURE, @@ -180,7 +181,7 @@ pub fn validate_combine_signer_and_txn_args( // FAILED_TO_DESERIALIZE_ARGUMENT error. let args = construct_args( session, - state_view, + code_storage, &func.param_tys()[signer_param_cnt..], args, func.ty_args(), @@ -205,20 +206,21 @@ pub fn validate_combine_signer_and_txn_args( // Return whether the argument is valid/allowed and whether it needs construction. pub(crate) fn is_valid_txn_arg( session: &Session, - typ: &Type, + module_storage: &impl ModuleStorage, + ty: &Type, allowed_structs: &ConstructorMap, ) -> bool { use move_vm_types::loaded_data::runtime_types::Type::*; - match typ { + match ty { Bool | U8 | U16 | U32 | U64 | U128 | U256 | Address => true, - Vector(inner) => is_valid_txn_arg(session, inner, allowed_structs), - Struct { idx, .. } | StructInstantiation { idx, .. } => { - session.get_struct_type(*idx).is_some_and(|st| { + Vector(inner) => is_valid_txn_arg(session, module_storage, inner, allowed_structs), + Struct { idx, .. } | StructInstantiation { idx, .. } => session + .fetch_struct_ty_by_idx(*idx, module_storage) + .is_some_and(|st| { let full_name = format!("{}::{}", st.module.short_str_lossless(), st.name); allowed_structs.contains_key(&full_name) - }) - } + }), Signer | Reference(_) | MutableReference(_) | TyParam(_) => false, } } @@ -227,9 +229,9 @@ pub(crate) fn is_valid_txn_arg( // Construct arguments. Walk through the arguments and according to the signature // construct arguments that require so. // TODO: This needs a more solid story and a tighter integration with the VM. -pub(crate) fn construct_args( +pub(crate) fn construct_args( session: &mut SessionExt, - state_view: &M, + code_storage: &InitiaStorage, types: &[Type], args: Vec>, ty_args: &[Type], @@ -250,7 +252,7 @@ pub(crate) fn construct_args( let ty = subst_res.map_err(|e| e.finish(Location::Undefined).into_vm_status())?; let arg = construct_arg( session, - state_view, + code_storage, &ty, allowed_structs, arg, @@ -268,9 +270,9 @@ fn invalid_signature() -> VMStatus { } #[allow(clippy::too_many_arguments)] -fn construct_arg( +fn construct_arg( session: &mut SessionExt, - state_view: &M, + code_storage: &InitiaStorage, ty: &Type, allowed_structs: &ConstructorMap, arg: Vec, @@ -279,7 +281,7 @@ fn construct_arg( is_json: bool, ) -> Result, VMStatus> { if is_json { - return deserialize_json_args(session, state_view, ty, &arg) + return deserialize_json_args(code_storage, session, ty, &arg) .map_err(|e| e.into_vm_status()); } @@ -294,6 +296,7 @@ fn construct_arg( let max_depth = 10; recursively_construct_arg( session, + code_storage, ty, allowed_structs, &mut cursor, @@ -332,6 +335,7 @@ fn construct_arg( // constructed types into the output parameter arg. pub(crate) fn recursively_construct_arg( session: &mut Session, + module_storage: &impl ModuleStorage, ty: &Type, allowed_structs: &ConstructorMap, cursor: &mut Cursor<&[u8]>, @@ -358,6 +362,7 @@ pub(crate) fn recursively_construct_arg( while len > 0 { recursively_construct_arg( session, + module_storage, inner, allowed_structs, cursor, @@ -372,7 +377,7 @@ pub(crate) fn recursively_construct_arg( } Struct { idx, .. } | StructInstantiation { idx, .. } => { let st = session - .get_struct_type(*idx) + .fetch_struct_ty_by_idx(*idx, module_storage) .ok_or_else(invalid_signature)?; let full_name = format!("{}::{}", st.module.short_str_lossless(), st.name); @@ -383,6 +388,7 @@ pub(crate) fn recursively_construct_arg( // of the argument. arg.append(&mut validate_and_construct( session, + module_storage, ty, constructor, allowed_structs, @@ -411,6 +417,7 @@ pub(crate) fn recursively_construct_arg( // value and returning the BCS serialized representation. fn validate_and_construct( session: &mut Session, + module_storage: &impl ModuleStorage, expected_type: &Type, constructor: &FunctionId, allowed_structs: &ConstructorMap, @@ -471,6 +478,7 @@ fn validate_and_construct( } let function = session.load_function_with_type_arg_inference( + module_storage, &constructor.module_id, constructor.func_name, expected_type, @@ -485,6 +493,7 @@ fn validate_and_construct( recursively_construct_arg( session, + module_storage, &arg_ty, allowed_structs, cursor, @@ -502,6 +511,7 @@ fn validate_and_construct( args, gas_meter, &mut TraversalContext::new(&storage), + module_storage, )?; let mut ret_vals = serialized_result.return_values; // We know ret_vals.len() == 1 diff --git a/crates/vm/src/verifier/view_function.rs b/crates/vm/src/verifier/view_function.rs index 04589011..af21b1c3 100644 --- a/crates/vm/src/verifier/view_function.rs +++ b/crates/vm/src/verifier/view_function.rs @@ -1,11 +1,11 @@ use crate::{session::SessionExt, verifier::transaction_arg_validation}; +use initia_move_storage::{initia_storage::InitiaStorage, state_view::StateView}; use initia_move_types::metadata::RuntimeModuleMetadataV0; use move_core_types::{ identifier::IdentStr, vm_status::{StatusCode, VMStatus}, }; use move_vm_runtime::LoadedFunction; -use move_vm_types::resolver::MoveResolver; use super::transaction_arg_validation::ALLOWED_STRUCTS; @@ -27,9 +27,9 @@ pub fn determine_is_view( /// Validate view function call. This checks whether the function is marked as a view /// function, and validates the arguments. -pub(crate) fn validate_view_function( +pub(crate) fn validate_view_function_and_construct( session: &mut SessionExt, - move_resolver: &M, + code_storage: &InitiaStorage, args: Vec>, fun_name: &IdentStr, func: &LoadedFunction, @@ -56,7 +56,7 @@ pub(crate) fn validate_view_function( let allowed_structs = &ALLOWED_STRUCTS; let args = transaction_arg_validation::construct_args( session, - move_resolver, + code_storage, func.param_tys(), args, func.ty_args(), diff --git a/lib_test.go b/lib_test.go index 9fac0299..7462fe8b 100644 --- a/lib_test.go +++ b/lib_test.go @@ -56,7 +56,9 @@ func initializeVM(t *testing.T, isMinitia bool) (vm.VM, *api.Lookup) { blockTime := uint64(time.Now().Unix()) vm, err := vm.NewVM(types.InitiaVMConfig{ - AllowUnstable: true, + AllowUnstable: true, + ScriptCacheCapacity: 100, + ModuleCacheCapacity: 500, }) require.NoError(t, err) _, err = vm.Initialize( diff --git a/libmovevm/Cargo.toml b/libmovevm/Cargo.toml index 89d49c10..2cd16b72 100644 --- a/libmovevm/Cargo.toml +++ b/libmovevm/Cargo.toml @@ -50,6 +50,7 @@ move-core-types = { workspace = true } move-vm-types = { workspace = true } move-resource-viewer = { workspace = true } move-binary-format = { workspace = true } +move-vm-runtime = { workspace = true } [build-dependencies] cbindgen = { workspace = true } diff --git a/libmovevm/src/vm.rs b/libmovevm/src/vm.rs index f6658181..5e132700 100644 --- a/libmovevm/src/vm.rs +++ b/libmovevm/src/vm.rs @@ -8,7 +8,6 @@ use crate::Db; use crate::GoStorage; use initia_move_gas::InitiaGasMeter; -use initia_move_storage::state_view_impl::StateViewImpl; use initia_move_types::access_path::AccessPath; use initia_move_types::env::Env; use initia_move_types::errors::BackendError; @@ -31,12 +30,10 @@ pub(crate) fn initialize_vm( let mut storage = GoStorage::new(&db_handle); let mut table_storage = GoTableStorage::new(&db_handle); - let state_view_impl = - StateViewImpl::new_with_deserialize_config(&storage, vm.deserialize_config().clone()); let output = vm.initialize( &api, &env, - &state_view_impl, + &storage, &mut table_storage, module_bundle, allowed_publishers, @@ -60,17 +57,8 @@ pub(crate) fn execute_contract( let mut storage = GoStorage::new(&db_handle); let mut table_storage = GoTableStorage::new(&db_handle); - let state_view_impl = - StateViewImpl::new_with_deserialize_config(&storage, vm.deserialize_config().clone()); - - let output = vm.execute_message( - gas_meter, - &api, - &env, - &state_view_impl, - &mut table_storage, - message, - )?; + let output = + vm.execute_message(gas_meter, &api, &env, &storage, &mut table_storage, message)?; // push write set to storage push_write_set(&mut storage, output.write_set())?; @@ -91,17 +79,8 @@ pub(crate) fn execute_script( let mut table_storage = GoTableStorage::new(&db_handle); // NOTE - storage passed as mut for iterator implementation - let state_view_impl = - StateViewImpl::new_with_deserialize_config(&storage, vm.deserialize_config().clone()); - - let output = vm.execute_message( - gas_meter, - &api, - &env, - &state_view_impl, - &mut table_storage, - message, - )?; + let output = + vm.execute_message(gas_meter, &api, &env, &storage, &mut table_storage, message)?; // push write set to storage push_write_set(&mut storage, output.write_set())?; @@ -122,14 +101,11 @@ pub(crate) fn execute_view_function( let storage = GoStorage::new(&db_handle); let mut table_storage = GoTableStorage::new(&db_handle); - let state_view_impl = - StateViewImpl::new_with_deserialize_config(&storage, vm.deserialize_config().clone()); - let output = vm.execute_view_function( gas_meter, &api, &env, - &state_view_impl, + &storage, &mut table_storage, &view_fn, )?; diff --git a/precompile/binaries/minlib/account.mv b/precompile/binaries/minlib/account.mv index ce61feb2371b39ad7bb4f92ed154827a3a6fb836..ac74d88f4c826827bd2ab8f7d16bd7d77d2a8d75 100644 GIT binary patch delta 806 zcmZuvyKdA_5S^E=ANSg8C!0+c42cz?MHG?T@&|ka1q~}jqT*F=K}m&HqC!Y0v{ZBy z`G5!t_yWpEDfk8EPIi$u?6ovL_MFFzIUoZ#K)q5Rt(j=Wf+F_7T7v_vrFARF6pswoQ4I|g z@C;!mzQSFTjYAag8EIm8->3&63KGLp!?z6IHryJ%WB9J&!-z3SkeN{Do&`SaKFm#>~IAK~%WH~5ejqe6#5JsiBQwmLmDMDFS8so|NR0E>qPk<=KR zeu(tGX#)ld%xxCLi|lyt++#z*c}E_5>}2XWxTGHX71%>3_xvgS%j|+Ac^*ru0a*+< z90u%O2hJiv5Zk@PF=T z&BZa*ip$D;m5SnRk`3!7(w$l_AG-&O8(i)-xO;0ZjeBiPwz%V_Vt=5}*1;A94HU;s Tm`w)~?UDX_dQfi+N6^7vTdXn~ delta 823 zcmah{v2GMG5PdUad%bJ#-7VR>BwQd_3L-?4ZK>cBkZ34Tpd}5|D^aAN-I59+rK6%l z;t!zUH-HLy#LOz7lL*0Dd7nLR-psT8X7+YAyx#ko0)Rwt?3~0G1m z5TP_K9vvT_Jb(Hu-LwC=qKD%tEyokue)o#*$k0~WBI%ImQ+TW{Y&3jmhNjUYbC!f8 zi5p=@4&o9TEu{@0sQcpfq>{;)QpN22vZ5ZH+e-XLsI%=dyX4${PuZK~kbEPV{jEej zb?#=G7Mpz}=0eLvD|6%TGMe}AGCO{~Db;hP$p@*AQg5;>#t(iy)au60Ad|C0cyeyM z$%l!!R-XA?pyiq3bk5eJzJNXd&8C(YitG8Lt>g>X+Br9b@qRdZa4AnZUYc;wHn{C| hx%#g*bv%9!?cGa-x#QgpVO@$nP3SXcebxu)@C%>kH8ubM diff --git a/precompile/binaries/minlib/acl.mv b/precompile/binaries/minlib/acl.mv index 6b82acccaf9fa42a8fff981f0b98b0b1b7d08fac..85385977b1bd68ff6f08a44a92f5a7c3cd0f63b1 100644 GIT binary patch delta 263 zcmYj~AyR`;41{-+yuA0nw9uj|DsZ6CMT0@(dj$rA;1NU@^tadclHdP= z6f4=?El*YJsCXN4$k2N#eN+%>CdH(Pctd%5ScTL+KskW=@p{Xjfv#7OyDmzfo%j^Ah?7T`TrxSADFKbB>(^b delta 272 zcmYk1Elxy15QMAxZ|2Rs{dvJ6a0n8D+@KKL0M7+hqp@p2tp$gJV{nf(giFwmunDa? zRbN-94tB7|m(%Ya06Gy8rtQkE!*4Fi_P&1dZ2iSIwr7oTuX`@uO_DWKumB2zswCj% zK!l~Pg^-~p5<^R?rHYM8($M1L%>JP`vb+_kGdlFFI>FrQ|G>G{4;FJ1NdN!< diff --git a/precompile/binaries/minlib/any.mv b/precompile/binaries/minlib/any.mv index b5f562b1a97ff11d39b446b6f0fa3d2d504e86ed..a5bbd540df0ba90fd16151c0a255170f7216b67f 100644 GIT binary patch delta 194 zcmXBGy$XV06oBD#zVrR1CI)VX6a)={u1zgXU4>X$2>sA!1??>j4HC3>CtXC)MRWnJ z8NJK%p7@zZ_x9UX0G5s5Fh`Rg^RX0@KxL(VVaNO64Xq0`oEwdr&ngOH1W6nvGR6b~ zQbVd5usGFlNBt14)_{zNM77NZdTutWWI8LY{~ULDDRN^r#w*r`bXjCcY8LxdzTRCC c!)u6-o;w5=Jn*~Ru0?;ym_+#3lKpxRzQ3~}b^rhX delta 177 zcmeBVX<^Y@DD#?|je&uIn~{NsiHCz(M1#eKjnzq-J+_$R0;7V!2gYfPTy4ypJpIfL zyyqwCNoz2$F|#nTF)=Z*GBPl8vavHVFmSOjGcvI7aBwiN^05P%Ow7#8Y!fR|CVmhX z;YcgW&y7z?F6M$TDoav}Ckrx)PF7%K17eoRYK;5U_$?Ut7z7wZ6j|6=x!8avf`K5b QI#85R#Da+l$Y*2#054!0Pyhe` diff --git a/precompile/binaries/minlib/ascii.mv b/precompile/binaries/minlib/ascii.mv index 40493e1666791f514c6b51de32a5fd300a2a8156..bd763871a82bceef1a4cf038d5205b3ee5ca160b 100644 GIT binary patch delta 318 zcmYk0JxT;Y5QSe=S5NnJ^~}zX27=&%_>+#&f`NDhPhjF14A(@#R3e<=-0W delta 298 zcmYk0txf|`5QWdoo!R@l+ubdMkXE!LrBx)0+62)@z+iX*B#*!ofFK(L5*z{n29Lrb z2oFJm!*h#b#L3K=$@%8PzT56@`V|WRksvIUX;0+L>G|3|(i^!Sp4B(zp2Ca7^eUfR z-d=aR$0%R`3k95H@zw#sdQcgZKvhfxa4En@N}%2xHO>OKu>`EY5D+KEn8R}n4shW|LfpHdw> diff --git a/precompile/binaries/minlib/bigdecimal.mv b/precompile/binaries/minlib/bigdecimal.mv index 875416e71dc268580aa34420a3604b712e566f4e..f6f182b88bb77853640505664ab2d37e7f01e61d 100644 GIT binary patch delta 1257 zcmah{IcyVA5S{t^_x!u-{cFeTTqMMV1ag=J5{?`YNC+U&gpPtLbWqabhKdSl8(Jy~ z1WhCa5)CDCO%DYXR7mv9%;E?+MIz;CJp1OoIsTvKhobvx?5FVoq6ooLUf`t9wfj z$QVbAo?=WK-KByQ4PlMTFkw_yDf*nV1m-cz)mZ}T3C9hVz(&gPki)e@E@S9Z22IHM zrsSKPheF~);+E!2DmYB}F5<9!7!lHl#5JA+M#X+q?8n4@Ozg+Seq8KN&@K=rWbO%> zds5~;DHBi0tZn9Cn|KJPG~=|yr!}pxi!;1QnAIVX&LAP2)igcMA@5+`WrKwp<6_3x zv5e=CaVaOn<(x&&i}VGZQ)UGTVU_+7E_$qgN$@gT!j*ts)&%davoUN$Y_=(QmF?l0 z!^K;I*G2kcmlLgkGf#Fr^Q< zjR9`?!<%f!l%$sf;2E$jZjci6h^ho~qMY@gx-msb`NqH9%_4}<4(mkvtj3vV>HUA6 zG|mDE=sL~d#){~Q=+y>N#cLR(FZSvF@$_Yq@AUcM@qD6}Z-a46%3iS9aV_<3oYX+9 zEX0mc#<4LqI(U#ZvhXb*1k>_&3_!C3gI|0hd43#vcbNm)d_CBDiY38A5`F+yU-)sy1B?$H+rs^8nzkyF*pD$RVy%>4xu C98}Z* delta 1221 zcmaJ=%T7~K6y5ur`#!z5_gvcYXpssiD({E*02CF)#|#r=oEQ>_ApuMp(V3l_IJ)rz z`~{gfW$ehgiN>Kib>hIdb{hzhKnE+kyKAj|*4d{YJAYT2?`uDeM??{mr@TNXyV~8; z3;tjI%ME^n_4G}&5`Brh!uRN_iT5fBT!)IpKC$+RTw-ERF_EtwbX`<|=MaTHAPN8` z1Qa5GrvS0=5;mk#rJBSR5{^ZeLC0AERR?t35u++W$E5^SSsUWA3kZEEOo(1ZdKL7j zQ>sp>x*R|v&@H`g>Gep}BbCK;s>-0M3~JV7QcWiH%A{VIbP5TnPmb9q$Er)5(~_iL zLJZ(n9zbjwbO2|hI_uy%hHxiz&IyUnb4YZ-QN+WH3mb7E8!ZCHQoy(cOfXv#e3v4x?8q)j$%|DI%|iWue>^JZ8cbluU%R_B_j%Am?&S(7kK#T&<1aHoe?UFO1Ay1~&U}@y9{MT-bD#`!& z_nJ1spTKsv&au`WbC9u}Zv+;juy9I<;T9AG3WC5j-VuS4n-Rg-zQ8|O@c2M6zOM*R zRvZW>B$l?5m^LM4(B8|m)va(@cx{wZWHZ`v{lhDGudA8zjfsA z!jV`g^Pq(G(CU_sEMx!1VcONQU4TYqC+#mEi)xP8=TD+fRoT@FG;DA}ju=L9J5!P` PnldN(BQpzpYli;;z6f1K diff --git a/precompile/binaries/minlib/biguint.mv b/precompile/binaries/minlib/biguint.mv index 6bd9837bd5c530d9898cb7ee149019c04c430cc1..5df3f7a4f4da00360c794fda5cbabdf2bf49e774 100644 GIT binary patch delta 331 zcmW+xNm2qq5Ui?RW|(edcLQWm78f4j7yJ+&IQanYUi^S}Be?MaIC=C2kDw}}qq8zH zvpS>q={>K%2FFwoRf$PNyo($0ACkkTEQ??HcIAHea&;>p){Nr;Gb$r0=E z&MO8EiqS`t3U!%EE){DvQ>tK?D#KhD*0qsoeNozI=w)i+r4|<2h;|U_QdYO;Epr($ zt{`1IGj70d!TW5=KrA{0zXKm3Ge%|tJ_Uch*C5janrCR9qj`bmCEQ22PjH{%zQA3v K{`{xQTYm-wi4@@g delta 288 zcmWlSJyrri5QM8|dS;iMSwvA(TmgST5Ilo-@Ivbyj15dohQQF4}gcTEBRja z`>J2P=AYDlG=~%cB!P2Iee6VkC5MA7i#PY_%dapSbm67i#+Y~UPwV&OtS<%NA%J=X zf&?IHw7Z}wr389CJF8$wl_3{~+IG+{4M%()wERA1@r0cr^(iuNrj|yLJm-Dk4VO$~ zrYkWt&g?bQglS4UqrG9eWxC_aJxAsoS#acmBTI^vADMZiS<`H2oMm-ja7g^yP6OPi70E_)>4{`#_f0o zE_npRyC7bH7vP4M;Mi@|c1YkT_L0y3cl>qtw+sjof)d6U2mhhheGt4G*S^!Z{)>L2 z;xp8uFYtqJ{R}uEgrYSg6hF@G>2WLj)WOZ+ zCPpUz$CdE7;jqO1$ObTMH~Hce5v!)=(0%0%A{Fp(vZNT!>;{z zbfJw-kB*kAWY#U2rDB)gdwF)+d)qo6srYhI&UB`-*cBb?DlVrcE(h^NIW4jZu{f8Y z_quoX{QO1dxIoKUn(Hi{x9)7UnS+V1(kdS6nJUl=hh;e;ZUS7AIyq(xITNoTXvBoO zh(Iz4Enc^JNl#dVNrHn~q&;BPzJs>3fi6_C7H==S@dku*-V;QyZ3?^Sis5LJN#>)Y zTX!Pn2~>D@Hv$9dgAOK|uZRjv-{$*1u`dYM{07slY}nH|46B8Xz!qBk-WG(Xt89@g zz~-!XB$03npVgA#!AimhNy6se7^Et?2R@NFLtoaufc4uD}C>=D+r-4gHap` cZSnVRDE>9)S9TJ6wwC|2Z;Re+-@YUA2Q>P4n*aa+ literal 1075 zcmb7@TWi!n6oAj%a+yi(#cc~B5=q-#sg&YlL9mxat5Oh(_!iP;b~~_5>SlK9qYpm% zC&XXkPx0ATe}HEu)~*#q56R?Y&L!u3XY%RpHx&SYBtR+UEXc%z&G7g<`a;r$ujDh4 zA6S%pWZ(JR`-r0>2>~b&0M03Z;HU)zGlUTXh};t6LV^egBbXEwMj0dcU`!GkqQdb# zB*L#uo*0`?^{K7L@t(1-y%vmgHMD23vkiT0MP>vX)|PIPsu z^TrlqYpP*hSXSvvhDO<(nSsqmdSJz*!VPTTZ$dh!_4$Pv71q>Mey(j%7Pg3iJ=)rK z_ia-dYl@wnD^ot*t`P%XC_(@5=%D{5J3iCt#kiiDQkSVOIyFsNPi$Hb(vx~pl?{UN zAz}Yz|LE!Qv)*onp3`Dv%Cv3W`x@JVNiT~g9h#}GFbe17NV*v?u3!OnDMivCmL*B3 z^cx9NRI!XJF|TkKR~2@hyCQqEgCQ8PiQc4xK}6Av$71d`=b!1&fk~e&lOX9LVfWBY zbQKLShnJOviVeSs-=m7GQii7Rp*vY#5+d=tYdjP&2DQC+18@flrL|^!K`hN$TO%a& zNgLoiSx;h%8DF1c@xgTg2{xdJFGF<2N>71eOF-S}jPLvlmU%31pGFB!ghFb|RA8ta z%<$RZ8!g-GrWle#G#S4yVICygr}3`@ip|hrV$IQ67q^7|gX*D#Er*pq#@5Ix!p7nk wxj2}84Q|kWE?$V9uMTPZspFUkj)`Qv@MF3eQMwAWc;%t}50vYk{C^KW0DY}{#sB~S diff --git a/precompile/binaries/minlib/block.mv b/precompile/binaries/minlib/block.mv index 022294be891c993d476ab1fbbf05763369e020b3..9c84f44b4d2e942eb67f4a556b626c64a456cab2 100644 GIT binary patch delta 82 zcmdnMw3*3dq0DP;b_ND6c18v!W+ow45jJ)yFOC!iffmLho^OmY3=9m6V93P41f-ck d}*vf1~xWE5Hn+U zegz8)BZvj(2?QQu=W^$q{pqgjqq~*2P$TjUCI{D-wR1D$+}`nJ?G`t14`!|PVov?N z?S^OT;@p0q@$6hapN=-JR3wIpsZLo+zGfNB(bdzfK~@u*Vu+>iUZHkO5OwlORW>Vn z*R>SnUV-$s(5@)`PNK+SlF3p!83tkkBD^sMSF?{NqMX-LH@lQO@Mx+Om0Jt~uE|zAW9~9`4a>R^QB-f3U6a zY+Zb{-^ibxORv*W|D2o{CMr{=(U&ZPqbqBklVw6h3`xy}24VuJ!G_Cv!{Eep(JNXbTp z3uE(FEA@`evN%B0BLPQ%Qwhk|J?48+W;Zfgt0zypfrk=d^mxF~u+0mW*@v{R5)G(1 z!9FJp)ksoinb0H^ql+k-n;kC$D2+&Ep6%R2Q6)Bp&;;(#5ll&5Ks_Ih%siIb{=IynJF`E z2@5j`D-(l}yqFlH3)~t1f{7bLB1<^App)Y#t{%KeF#}bB%T+N5K&NykO9vjPz>ls4uN4ppd8M~ z-ae8Ax5J^lB%aZbc+}wmjy`%(krOgGC<*bWVThFAk>L?WRGb@;tm_U(M-DlHn0Kbc zf`hQANDCYrCx}aMm~nwPG69YcmLqp}yy)PGX$Mzk96Wi%!3>3oaB7auI501Jrrwxe z=t-VF=BQ_umK_$vC*U$NgmWi}N*1`%p7ymVWC~fEE9FaJX{b~xO_ZY2RB8G+pq5N& zDN&-*0VzUGcmOJZ^b`E^ZLX}=lu79zdRlU=>Fg8YfHKGe2#_RIfRe6!CVi%SaDv2; zcG=+RP|?xzB}1t!U3nzsGoN#=XrmkMG46A^B)&cU=?nH#B$IZ#)y_AXJGG5Qy;^Ip zZ{JUvTmD+Bxm9a4JL&iQi&52StT&UkuGQ=9q|>Rk?)VLY4~dp;it}UPX41aj=yV#b zX0@I)8%aHAwzjHwTHDQf`h$3Xb#r@lqtUrr-8q?SCl9uh&Q`Tgn%YU)jXRG>Y%^(+ z>{=t~RJS+R+qHU9-E3_%)*h+V7Ww#ayw7>RRo~wDA5;3b7%C0*S@z8JZKdzYV*0U^ zz3+m&&A(GR{YJh@e^fV7raA8_s`Nwe9D3=OUK#!LrC07!)Am-ea-)3lYWZ@ddZ}`w z`p%VGx30W<`OQmv?mmjvTH71-h~kY_lZevO+Sp0z(N-&}H6KNNPl&KtTf0|VPnLCG zZ=vG!-L90cR&G{rT)%eZ;s-0`=ye*7km6d?X}w$9NupZxFsa>3+EG6>(QazelE2d} zYKTE(44`ir4Vh+2_Kk#mE{m2MFg!-fq~|Vjb1}0>qq4g!(@?gSYo__Mn9-ow1#3kX zwTL+%&!7=SKNf~58v5QEa+=7T5lCbA)-I7u5s3wkNsvK2!nB+I(d8`0l8mr<5c8(z zO-T9;HzHPIHhmBbo)|Y0nU=B6G3&1|;}4=NDf(;mR#P2r`F?Oxa|(_IP^)P%r@59FY(`kGxPk?=fz`${+61vR@<4o2<_)L# z3Sg}UW0!y;V&QNW%Qh@B=Z)AaBzc!!({tpGbWDbaqihrffHLHoL6RF|W58e-1@hSe zM|BS8v*uE2KTE!W$Z0KZEoXxYMX0u{Z8udCbs;EbQ zojs2R<_@0OBv4FzZw+m)h8b;jW?DQ(Dx#$h&1$o(vqcJ`L!0g9v@y9jXY)Ew z!K|=pakqEUEDXd)CQq#uYG%Sglci7#EY2HypyXB_GgJerdKOI{6+LIY<@)*{eQyYe zPG(6F+5tsDE35VEAZPezD4(FwyL}`l`h&#x?NJulq*c<;14Su@ Wz>Sj@;iT&>BSL!Eh#7%i-+uvxiu#rS delta 1575 zcmY*ZO^j4U5U%R(>VB`g=goVwZ)SGcWp{>U8Fm+t0S`|JCQBp+MTm+doF?E7G6_2a zyE~|-IhdGe;tzQjPbPX$6HL5#@&HG##G@C_#G@u&tzMR0spNHaS65YkRsHq*eD3$@ z%iqrZy!b1sPehBp7f*!wlKxQ9lencnwTIFN_HVM^q%Hq2eQYXUOh+80 zKtmO3P=|xig2Qm?{^ixl5rY7DR0xTH;Q50@0LWAkg3L6JYRVXZJO-c!IH43xS172N z1X#g=lmKQk06jk?F;WZcZrZs7eW*^nUgUMO1Pwl*Gd&|D;PMOwwK8*H!WvdNJsdm8 zIF7@-kP2rOAlOf|*#1J!!^uV7%$9bdx<@*^8J}JT6!78-?^eLDzm(b<8(CLNYN^kf zwdPc_(QGznn{&;BM*%GfZHbUj+ZYge6$5FW%JLEZa}BK!+M$Rc#u$Xzo1%%4%V47< z8wqPgO|v!;2~I_%eFVWf5)p%tnl*1q6P9Q!m1pInR`lLzxP5&v+@k*G=4dk=4DVgP zJy`Eu-+X_((I0M?bLuM_4@cX*o1^h?z5Ged*0MYO&5gm<)?hU3t@nq6{(AYFI#bTm zm8Baa&hkNTW4ulMdmOI%8-wlYX8-QEzqQ@FGrnNSH@z8JWB0NFmTjm<-@_~5+P5G~R38S(b ztzlel@rdPpSuaO%Z&J5VfQlSo0IU?Zj|%0ao-lKFq~RqUWmj4zBjR9H zj02a14Gf<>onS#;Sg{PskY`7xz*EV5$L*lbDxOn1RcO_q866%^kgVEqVg;&Ln8I|i zh&)*;V%c%bs>Ugv+ph4sDtzR$i|R;iQ9ibF6I3YMuUN<`2HHxK3#Wz-1mUa+W>mOP zs+ariklYUP+A_x$)p72MKIbdSo4kuP^s%?jIP2oVJFWMN*L2cJq%Jj_s)6?wTzS={ z<=Ay50_5s1n25E*39k9}v-;IjAfcfFiGdZ#mB}u))pXUh@(2;Np{D$~_ z?g$5k!W^aGBOklS#u?gp8RQuU-WHBQIL7IY!-UR;!gm9~#-W$qbJc3!sJQBiPkhxT zwz8JSNF0ueAVqZh@$F}|Ctl|VfO&~ z5$SbX-K*`!Vf8b*YL*kL*r5~IyqE_8(}5tza<@m2_<431$S~YW75FW2SY0eImnHC3 Pt;$s9;b+O*=3n@KnoXiS diff --git a/precompile/binaries/minlib/coin.mv b/precompile/binaries/minlib/coin.mv index a9097628eddb6300131f410fb2e8f42739d1524a..d7483d09220b4216995a368f831951942b68aa16 100644 GIT binary patch delta 1081 zcmah{Id2m|6n^vO*!9kO?a3zC@f9D5Z*SsUI0@m%VZ^O)6%-K-1;4_g1yMxqL3Dsb z1vR3iqokxjqM?F<7T(wiN+cxK(&u^C_r7mupJm@=H(%twYX`uKGe~2)&-dSO@kA8l zEAb1R=gtS${gNoE--%Z8b@D5EPs6VNK78rKzh(Ty&x6ee1BR2FF_%F~3Sc6ogbk25 z8B9AaFqUz-O=T&;FgtF}L5zYNkJ(Dz(=?g)wG9e!qG83rr2q>F3ZP^x^9Z5rP0+dQ zPuSiHgae|f@X$up$ten|rwE~zvLn^B9j}kZM+l8+n`vfjwK103f{?~qV~%!~rbRn9 zMTESQFOZaIhD^YGu|$Ots&0ld&XOk8Fj!{fl&|C|;Hzb_==SmzV6pXz9ov|*o6c12 z*3Ei@@NB(Fq~}|0%5QZjkK55a;ZC$bxEpn;+K(0qFGj@RU0N0l8M_?Wm&mR}E5vct zrI!HL9Kv0=PDjRXR0#FnY5V8iEZEeop51zT-QpdqgCR$SE_&!=fFVv{0gG71wWZ+< zepJdsSF_;{Tpup-Jx@wk+nz?h#e|2-}P95t`lT?um$L&1eL@qo*7chEE zz1E=fY%>7URPr!8D{8}iJvY!?lx@Km0sJj$VOqWnq-mRuue9nReYiv|eI;jNK9?r4 z@@iI|IO)cWyi59K&HOQS3#35M_iSZru7#FbnJz=wrNZja_>VT%asiM_MtdBe_IYTe z$4Vm5w4IrAq>%N3k*o_o#s&G`(gL@cfQ`lBXTNMB8G4R7GzivVDn9ox)QoA_caQQ~ f_4UyisYW+6zN6aCe@(?sm?BF|f&dNz;V%3EusT!X delta 1029 zcmb7DJChql5dOO7sh!bEs|UI}orF%hlTNpHTAzJqV!33 zyR9Dm#`-%oG{34(mHXX(>-|@ak^P~OH~(tGv!HU_q(E7N%a4=% zQN`yM@s;p^uulsgeRZ(f=u+rGNwk&epm7J9)p5$B@k&wzM@hE3;p%YLxnjxS+D@!SD^zxN=nf8OOu6=>;OWif5NGOI-DHuGY5B%V~Yb eFN9zU(<>j;*RS3DUrp4c2|$y9hJt3ihkpQ`*;f7l diff --git a/precompile/binaries/minlib/collection.mv b/precompile/binaries/minlib/collection.mv index 55ab3410a0a571d191febbbe61cf2b11fe362377..07ce7f53021c040efda656ea5ee2dc61c12fcbc9 100644 GIT binary patch delta 2151 zcmaJ?J#1V>5Z?c{Z)e}Ww|CFyzw`Ou=bzXnA&Fl?ED{I-LP$h@2tmRjKL(P*7LGws z9W4b#cnuN~5=azO6mAhhN`(*w4ILE?5=c}CD#YxIliVpNSM0u-ot^pS+nKo!+yBn2 ze%|~YB0@|;NrN>`@vC>3_>vd$7yhY;{)v8w^qq7}{hFT0zRG@+=5}Mv{@K_`lP_k5 z(r<3B-t17`;(}@_#*`wI7!m|BPBdVeu3-3H0z+pm4P6j+u%2;Hd>@P>JAMK z;rWr_u&%-gq4AR~v}H%-7(>+Z*!TqcluyMBH*=gx%BXy1I!OA&3$QRY_c^qJ~i2tbFI12xykZpx;`g4SAkMosEP?yhOsCpVgMQw zDU}vdQ^U&Z>_XJwhH+)fZ`sILFapW&HMCGxDqATm)ec>0 zWJ-sk_4l^7u3Xy|H#Tl;+w1GMwzoFlzr3-zvA)w6T@{@Sh^3Ae#4^L?xJZC4@Qmb4 zQF8a^5hK0>kN)43_L>SxnAB$65p+onMVBpHrSL%KWybP?S`M6{PK#ma(0QHlN-5KV zSuWG=z!8FQ5s-pcAVrO_7*W+m4DlwoS0C)6oE8I^36F>eE1a+rI7n}Sj*C8~u+6HU zPuf_kir*7mr=5n}8VjbEhS@-a6-HznffNw5N=!x!<0vN!X(JbTZ*`(T`x>Yo z;_8TBN=JbD-1o7@Lp*jKa4vd@?0?AifvM~@#pWc^1xmW;h=KS4MBI~Zdk{_A+lHxK z1_YT9o8@Q8LVdYS|{>lh^dnIAG94r(IsO3_maiepThj--*U|7 zRvLm8GPHYGe(etXYcB3dX{~IgtFK)$X-K5VtU~x|QA3KzkeCV?AhL7vqSFaf$TWkL zqP3T20{7j>Q0ziBjUX4Um7k;s{2G=}Hp;HwiKcNJtKK$dQl)!#dDa*cii} zmS>$x;wr3SkWjQvp98|abYa9(0K`5>Hpbhxg<;`m1= JNx4<;{|_EQsfhpp delta 2117 zcmb7ENpBoQ6t3-6SJ$iFW_rf<*q-s&9#3Yx1SfXf4zaQj!j=RjY(Xp`2__4YEya!m z2Q-|JI3Z~91GvD2TnHD$i4#Ix`4LFK0f`%8c|Dm#wm~A)p}P9LSKs&QZGX?hQWv4FFxsGgRWKN9LUk-_Kk1Lb|~eeap~q6z(JbSnNi`Vs68l~>&t)!(Dw_Dn7M z_QSOsJz1BE8#SQ`#WFgwCNtc?wD38D7SPUS&@s6W87VsvFy4(cQ?qn~&&8ba`GkHK z3V{8LbE6l_B=ruaq*|%~W6MK|u|rYJeN*P-nsWEwEl(sb-Xa3Q; zV&WJ~2&v$BbCTRR;S0{}Nda8Iqdt)2REs3$u^EDYd|!>RCyMRKxdvlT%>xss7xoLu z*qP#d_5c*;aA}zv@${h;`Vr?=CX3JcmBrOU_sqkD^DJ$IueCM-4`KylV-AZ1Xt3AgA(o+3pd_)VoU5S;&l+EY@#!P9A$o2Mxk?A{ zj57SrlKPGZZu8dm#mzS^-n_JNbv^$B8h1K6;x+gB`quW%&9^UZY;LT3>u+t}ymVz- zUEjFAedoM)S@jZRj)y#BPFT^A$_J+@@%@#EHi}spvs6e*sq`Min5RNK@W>lSICYA$HCY(em@^fyu*RU+H`rUzRju-wSZz&5A z)s?1P_E&;!k0s8@P&$PSRT7|Rs!^zG@19B67E$q@>Vo~x$2(kYgMJ!P9 z{>#7^a|2@i~Xm1*lwz;3D)h?cy*<{4k>UGjSKA zr8=-sU{G847sWkvg@L(eumr1x0rl5?158F;5+<%hu8p~}ExQyQRY>3fBlk)r^IR3F zED*4Q)sl2WwuD3TGK@2$uG*4g7-v3(n4v!pSW3pQj6q3d7T&}XCnbhq=G0b*L6`-} z6l@`iX$nC1M*dBB=3pJB_B!qFa(eKp9Zu(sXzl3BHX`mIi=8HJJ#R1~?ig*K`!$R> zDU%S1`&wuM>~mj3BU<$K+4cOZX!+m>)c10GySQo2>Ym(!0yVU8Z*j z#2upPbH9WECnbhHabF2_;P<(&6!n+KX9JWJPElf6%HeSSOT2GxmxOAWx}Hf1X7NR; zYUQMrU1}XGsY93Z6UpI)7Ieu>4>Hdv)2Je2Y0PDn0T|D!aDlEE^?d$W@<{JOfje8& z^x>m4V5k{s5>O}o%Yad{G$VC=P$kpOa|S&%d|%=O45NunHiUdpWW&xK%Lc~G1=eLF zsv8E!Gb^T?2Xnsj(CevHQq+RLg=xuiF-0prnZXg7y08XK48;Dzx3!g!@5;cShjwJ2 z1_aHS*rnuo8ETXt6ny6-!$R4W$mrwAV(>WSdSD?|DHV&N0BOrhIvYiZ6gkJytB8ko g(%)~X0sW4a`hWClKo1R~hkw%3n7T`!Un-CP4QT_Yv;Y7A diff --git a/precompile/binaries/minlib/comparator.mv b/precompile/binaries/minlib/comparator.mv index d3ef5487cdf3ddee6c478c62e5d060b3c2aef963..8ef60db20439ab5b124ecd7c3c4ca953ad780e1c 100644 GIT binary patch delta 253 zcmXAiK}thG5JbCss%QT6jGsg#Zd?dIxDe6&O>k)>#4BVWuDyle6+D4kHzMK@vt&TuKZxJdVp-8Y|3etBbWqV-*V_~02rL?Ctv z#O$j9E)-*9%I55L%#9!0V}82pX_cz<>dA1Mj%w_AZ<0kz z1BQ_gNlGkfj`LBPhd^^%@0ox_I#h-MeRd=dGrD)RS*|A zVkTAxCi1>mh>57F7K?puC;a@_(kisP3Uy(Si8(`(gbs%Vt~1r+Xqpu_EhV`Nk@; CXca;L diff --git a/precompile/binaries/minlib/compare.mv b/precompile/binaries/minlib/compare.mv index dab3964005ebcdb8c61d775bc3d1e7b71a913b92..1256b1901a11f1aeb54aa7a04f80e546ae741789 100644 GIT binary patch delta 272 zcmah@ISK+n5bR@iM!N@emjw+BJR?m81i?%LbMYmL;%31h_kXYKBwzxEwI5zg2pT)Tw-)W z-trBmZYBJ6(W`e!$>)U`y-3PGjs=9aSPKf9loW%61Y@2TqJWC1fj*6+_96PBYM!fX b5J#?+z&4Ua6eq5e?6<-v%1m|+|Ht4B-T)C0 delta 277 zcmah@J5B>p47A7Zv#~AM1tL;VgkM3qQj!LQ6bec%z#X^(XW$6wQl%m1$pvx=yxTy> zSh77Dd+eQjOTW1~S|Os!1i@+UX7%B|d7HN%ufFF4hr|&fMv}zzwb*_>E3H|1%?=k8 zMaQ002A>gk>0I&4yyWS`iClr`Z?v&`la@wo%+?@3 n+WXk&r>vGRes~tUe4T2nAh$-wx9Oyh_j23AVF2PH|35}QSy>Ul diff --git a/precompile/binaries/minlib/copyable_any.mv b/precompile/binaries/minlib/copyable_any.mv index 4912d5e7777e9de064af4231b489895bdf53be40..56ccac92fc07d58ebba619bf8d8c5edefb82fd56 100644 GIT binary patch delta 174 zcmeBWnZ%;EQ06r^I|Bn3HzNZN6AuToh(3!m8>^=@drA$*14adb2Bv9@T+^62dFC_Q z@!p-NC#}!Oz{bqN$j->b#Kg+Tz{t$W#tx(yxLBBh6blbKh+^gA;9y{6VrFJ$omiMF z!jV>#pBtZ)T+9VwRF5k(emAk8RZ!NkPI00n|< J>OdAF0{~Oh8Q}l` delta 189 zcmbQl(#xW^Q06r^8v_FaHzNZN6AuTohz5%d8>^Evdu$EIO-2QQpN!KOx%!zod1f#> z@ZOlHC#}K2#>~RV&cwvT%E-XX$;Qsez`(`A%*epP!@V*R3UV`ZJ-z`y_jK^}EBMhFwco_w6k Q0H%$Tcx{_Cx!*Ga0IJwH=>Px# delta 367 zcma)zIZFdk6ot=yTVCc(oJ=wr2nvCK3W5Yh5OsohfWAY{kkK8?o~gAKY{9cbmRQhnJo2MgcH{fCVAnJ0;Pi4*5w<7I_g5 zTA#-<>Mr)h;y3Y%bLF2f_d0psQUr!Ef-y{B3Nu(Z3k$VT#v#Uqgq)NdYFcqb@=-<% zvkn1su0@tSVBYtj7ZVB4QZfLA$#!75HLTbHt10`pmbO^$ve?L2Y-TMA-Gpedmy^a; zpS`#HEp~DiyMqK-AEKJ!q%_$mhczCFMEzN&JbhT+FC86Ms`8*(DU};<@<|Lxsg+fK m;yXQU{;K--|EtlzU3l^09bXywcM~zDEwM2^_9g}I(tn2H9d(aiZU$4K?RNq~k z2!FJ=KYe4(j}!gs_HS|f&W`UdR$jQUn=vL>##(Hgt!G=J8?U{*)^+-H~hS=G*f1m5%l<>Ts#K!T(=>~!L;i_Nq zh+iTeotXmFrMY>$A6w-azO0pJ^2(|)Og~=i{!_*KiDKK2`96EnbETgi5{%R{o+s0j zIEXz*y%1yJ^Hd1@aasT!Ke~ux*(YcX8h+ne48<>yT!%0DBCTJ-;7hb&BS=0;g-kD# z=PmdYZ33zN3~la$qu{e7wCC(|bR$;M=`E56Sn~>P2NnBi+OZSO=XX&bm(42J@!>vLL2-N>BC%s-(RLfM?m~5wB(yN>Ck;> zew7X#Me{W}2DaF*(V^pLzD`TN`39Zvhx|J2^36Btq&L^MXu==)8+6Jyze%Tk^IIj! zx9LGo`Ii6c5&LcOuEoAnj{Xka<0pTY4#LvnyX7`-)9JGq{JpaIeHuN7x$hNf7k^L~ zq4Ewz=P~$4blxBT$K>rE{t4;G+u&U~^e{%hPov(6KdG~%ym)U)_E^elXiy+^(0Jk8(I^8_OLJNh_%f(o1b zJ-tMq#GLpCdYNz}f1f_(Y1lu~XA4?RcgB*(na<2W(j4N=sqt*>)W&!dUmJCsX6v@d z+`K)a#tzXGJIz|NtGT;*b91}dvD94J6yN^g^ONZN z%pj>DskkJ>sP%tAAcLUn6z@7ROLe4_`M-$$x5c0_lO%*FNCk*IMOo1wsB^cz`PTNHp64QJ}b1 zfdIRze)Yvks~V|VnxBd`5#?WuwyTsQBY3T}qfS(=q&!lcdZ9_^wXaO>`ONpL@t(R? zyQJD&S*U(G_CgdUfJOttvQW7o;9iCNs%WMl16`nfFCb`c1U#r924&N09!q6uu(&Xi zH%Cw{XU*g&iE?tt>sxg&=Qj$A1DpAOsKK~z%%LE!#1jSoLB1H@JDU1EyhXj?v9(uV zsYP&}e<>bG!sU~T&ENV#e7DHgB!?RE^rcG=UrNtjeEh^m&z?Gd;?kKb7fxS%>-prL z)802IVO?gq=8h-i0vq5htVl$ctkkT_ZJ2~9tJ_FR6Sc)xy_Sp;U#9-B@xwMYOgV^V zt*zL^R&^|1S*8FX)op63)|td+rebTLs~cwrdM2|CQ?rAnZikBVn`Xc?%%B-EO=DbS z8+JhR)m7WVJ4m@xb~qWfBPJF--AaSHp>AMWsi@mgGh#;dKv&o?6WMW-+6lvL+ca#` zjGGD5HUai-X0@&~V;qY`-5e}e2iL8Z7fOz!Qo}uh*{BkAVN0#n zFYmD2w#BICI+zkIC{P>CO<=VgGTel&WexNw(fS$dhQ(TAjdCL!3KCOxeSefO9;nq{ z$lq_z^j_|}&GUpUp*~oy8{5c)rSo`xbVY+7qs@Qgrz4)!GL7AY_pQDZRhz=cE@*F? z#8g}c`#6)iHoj9^(={E;h=-ih&UJLqbCYm5nd-W!yE?jot`F)OT+g+Pb5q*55n~27 znAi@Ox*6a`QfT`6fRS|t+n2{A2EF2#s;$Yr1~3J*e3`a7+aI~cMKsTYPPSV%ra>hU zDsCoXZ4q+7xbktcvt#IuCvMKLRHddqgS=!&7#>!aX{xjNk;&oSjc(2+T9{@Sw z1|4ZJ1v9|ehSBLzzqBo0JGQpGY^~5nm%%NZBmO zkU=6hgAii67BRO$*K8eht4fV`P4O+Se)~N@fn97PtJ*;wnZd=Xj_eSEv1uxaZNVfh zL^QXdrPk2CfF006`v#g05f5Jb zk%?Vz!Dq)6^;Zx#2I@yFL;V$~e+x0xgX-Q>MNSr4I52^&x!dZaHVL|^IHnLak+@F_ zBt?aHnH1wBwpyz)tc)gO+Tw1bd|tGg+ltQ;J}V$Ez>Q6kDdcEvs*B1yhz^l8Q)CHB zQa7&!EXm;(A&iBXf=*->b$wjb;b1Ev;!m@7CI3J)ZWFl}2E{o@j@4PPoYi$WZ6le= z{5vz7cRrwlbz@V3l+n5|6dTs9@W(Y4Y@aWrD98AQgsI8fJH751s0A zCtdD1RL(T3XL`?Fa=USa7xI9CJgMAwjXYZ30C{XFQ7KUV{@lC0^Vf+}@GQOJ#VHMq zYeHdwo>AnHn~f?|6YspWuNVf^%e10nYr2CL4s2{8T9W9#8BXW~qE(TY?nkd>Q|l7v z0R*zX2|MDhdyx%HCicS=CM8st#3iwp{9r|!)LUs5<8l_O02{y%R@qGM^rqVv+p4@l zBPjYti)AZ+V%0&C`43mMdbem6yO3;PMN#HFe2HKrvMPx@53xpaY>S(e<%Wx`{Xw5G z+hRTZ9l}8-0l|X8ZpIx(v}kwOwNVl<4Tys&pJXa>)pal+0=LTtST2W-l)XID@6 zB#Md8x^64+kMt)r;(jlx_+A@y$B~Y?JIarhb7%G!$O~8utcxV@tV^VP*%mv17ELI& z^#^^rX_webS)>4uz{C<>6<8)gfv%#YrTcuyn<~;XM?SirI40qiAb>tWlzu>#z-zud z5ZE+5zAVbQh2h>AC>d(~pLl~>J#Sn8H{RBNkhkkti~di}de^h|0Pv0kvO&e?AxHzyHEzn7XEPfJaMzHfqD`cbCuFr;te10sC z*G%+2`XT24?BL_>K>>UL7wK3;ci_%gffOrCj0XX27{2jR0r;4E$er~N9VK>H?9|~3 z&B#iAZj0?Ym;h3bMc1HOVOKa0*g98my}V=_V-0W!FtM^n15SX#h9w!eoR4iRClLiP zoDa7nf**rHT!*C1{}lpUn1gJvbLj zL&VVeJ{_&lkF50C;%4nLiV-(eln(cd8XyiR{3>n3^-exkn1rEc%LC zss3sj{xbS#|HQ{HBB?P1kOY1SH4Kg`NdzR5Z|k&rZTK!qj1K!i1~Q^R0JmB{Y(no% z&`2>HV7LPBLv_WyX0uI_1QJvWG?lnDaH14WRA5q5#RXR@Tv{?6K)4nz2$`Nv}~9TTkPDK6Qt zDSmn_A8%0Z;au$D+%z`F1seBfIeLXe{`sZ3UI!K4JK=(lA{f>KIDs=;<(UJ8X~Ov~pEex9`skdbc zTjE~pA&$+cI|C2$KbHV~!Rs@GOxzW4THMgPqKH&ks;9u|g<%n?Re6)Y&K6VtzTk~c zeWNFGGyWr>$Q!RvTk{pq?uZej(-|n2!9diVg+Txvq16RnTHVtgnIP0PqB4ZEtl~rkwHCTfN@xxlc^Y3k1{4cYTB;f!6 delta 6484 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 diff --git a/precompile/binaries/minlib/dispatchable_fungible_asset.mv b/precompile/binaries/minlib/dispatchable_fungible_asset.mv index d61093ddc76a5ccbbba5f8372334ab57c1c5b161..8ddf36a461fe1cce8f9769ad69c61f96acc540e8 100644 GIT binary patch delta 837 zcmZ`%%}x|S5bmn}ovxnQo!w=3VS!y>7X&1FATo(DF(G>J9SlLih%qbyJa6Ken3z52 z)td)Ta_|{^2jdG!j1SQ)aPoTRI&tG@o~tLc8*c;DE4H~)>S5S~B;3`2SI3#bcR z)gSQ#+OO)BaaVp&zn~xJf958^zVF1oLGHzpvQRNz2(4eWqSa=|*@ z$uiP|Z1})VHFLJmvIUp0T`%LYP9x&=Y_rLwxfTONuN`5@iiJ*$lf}jEEXV!s9NR%J zwON{^KCo%QEC^+lA}PT%0o`^ zbio3O4m+e`q$s2-vL=7_tP5BdmfcX(w`N)IV1}nF0&rfblC2Kt zv9u%zt6GpGkpy>=x;D@7%G+9N(kIuNMb~!NR!EI<|!NF;bR;$ zP-!O2B$D-Ly%}EOo@34*n9fwV0ZuExPN*$xcI4Fs%kSpR#SjlMOCO;>-FKGTiEEDInlS0e00jN!r8h! zZVYVLa$sG1vr#~uF_w{rpWW8kqbw?hfUN2eu;!=>ErR!@kJ6cFf+=0VXahz0);4BE zR=XHNScRw}v(k%ZmCe7#VPqV|)^TK0=PZKJF|%vQ3^6asaDFD!+vc84|3W%tYsEY) zP&TBp9dpj9BXMRYBx?~-F0^h)HIV|9j)AEji^_~Mh`M4$U7^n>dgDLz@(;Zl(UFJW k{lwi)pgM|LdIpflBpah>i)OT}*tS?N>j~5Td(pJ>ZS>JeO6O+rkn=}+_PKf3D6e%kT#=C_Lhm=zF`)qd9;9mL~TWnZw<{J>x2cjNt! zdBgg|5&%S?1kiE`lpGUO#gX`6QH$1UD9RZ6j>Fr#kgR)A&5Ue;t&-x$(OGxxJR4rz z^hbGBTs`!Qa+p_THZXZr-Brz^9A$&zvY%Dg_qTaDoG8`C@o586^tz!^?Wut&dBZwV zGF_;II!w+awB;z8T4L(9*|6xqDTghEk)Cy0xXrY{_E-mY$LR&O8`wEA4vc0>=){GO zeC%R6UINl3K=L&on|%ccTE;X^7O+ugHbO$y!3yBqkUWJLIcUNvnt$XlAnS6cjO>BI KkrL)S+#Q#3Kf*@(kh=_zZ%L zwNGGSVQC@gD_A&pVjzV-EX=a={WJf5m`~HcU;1(y0IUK+GJ$XN_Fg!CR^|ztwKx1m z`^w(G^9xoU4M``13IPH+1PYYaf`?Lp!2lqNP|Q#oot4Tvd8l{=w^xHUr+I#v*RtU_ z8DyuuBtO5tNQa~O<79Nw?~T(uJG<#+!%>k3phEdLI{aM zt#(07E0!I_)Zj%e3zVv>mg6E;shE}xa@X?IAf^pr1#0oy3{-^qgVqgBgwmE{+Hu7U zAM$SGLl@FMAO6dA4LWejVI2_xA&|A%OAw=*Q*+JH^j2&ObAVJdl7kvFkV|N_qz+~% O`PEXtl)}3$+WY~N4=!*3 diff --git a/precompile/binaries/minlib/fixed_point32.mv b/precompile/binaries/minlib/fixed_point32.mv index c197aa67e95eecb333ee15de05adc4c40dcd70bb..46998389bb49c97b0b7b58092f17a9a51761edb7 100644 GIT binary patch delta 668 zcmZuvyG}zf47D96y^Yfs1q$UMXbVUnR9dw&NGwcz3_nnQfCYrair@zr*pQg{7N#z& z#mOy2Rhui>xjA;uv7ILw`_c3Ew-f-pM<60L?#fa0o0F^wXA30Fxo=0nL31GLOo>ar5MqWY$>7Th+?)2Xn+inF_v{9F_Y00q)ap4 z?(b;3;h~1Ty>7rVRAJTQK37B!&Ped#-0X}_Jq&vn-Jt)&7-zictI)aC;u9e;&A^_Q zfQMOd;<%&WWV-&+54a^fSOIbtV*LO||2qK(qiN)RaCSrcpgo8|Mm-q;&1BuWim1w1 zg~ufvCBb^@0kn8Cza$+Gn}Iy_C&vqd8$tteG?N<#l{7uP^5rN9XsbxO z70CKxges}C>DD&S17$`S delta 732 zcmaJX6BrkJ!gOCuhxD)zP1Da8G(p|(`$XZ=)M1e%}1IY{G?0HSE}V&Z)9+l z$vd$Jz<>Y}LB&(aFVKt7MC?Z)Ljz!a&y@&+C=9)T4Il$E6EVwJ1cgM1J&n{jNPd0$ zOzqe)^NPE}{t0R`i5GMck0W190KUfrls@5E8vqvbZAk z8F&H?aN^7raqb&%fthifrU+px*1C&!6h5>+hqdnm0s!O;1IV{Uc}7OoF-9C)B}>WK?noI6l+p!*hx9AgWyLR#~LRZry4i-8^Wf>EzR22 zteJ|~QO;fAd_ak4O}Hn^SDGS{wPcCkTS`-Y7$cAbqEtSUO@R0f8uMv{mFf3AWau%& zKyy#?B3Ngu$8MIFw&(3hMifUNLj$-~{jv}DGf4=fDaMgA`!@CD%}}5*ORk|WqOIxB zL6#hy-V4})F7zGF7>Y-yhn!t~j9%>p56ndTH&Em}=eBd9pL?8hUJ=OALQLlAFEKCU zyHr-9n}P(v!G^UV%y9;V+IrIR`0rcZ^yDTOGHl)Ew0Ry z2Txf>xm2A<)!wMq_*cnir5$ofivLlt&&hGe!wDNA7mdfi7gsZx(gsiWSCXqI?RN(^ zw|>Gbwy5PcR$OPJG;Ta7ZGYiL(=j8s`0&w7Xo)P5@zIVM=rg;;anD(vXN)Ra9BGfo)Y4CF%-rS2Ji;m9@ z6G)-q1<7GdW1BfTK06{oeN-fg!Tf?+`8R$zat=Ik#c4E2f@t1U%!R{+lv?p51$Q*F zDc81mnu6!E;M&vO0y9AYZY3mk<_(XF@4~aWbcPZE@h358{TNTyoYwynZ@hIzq)DWy z>v!V9i%^a`kA!+R|3rMpv$wHaP3#~Nw26a%YK^^-N;5tvNyk>CpWe8|x63YB!c4(HM_aFk_KSNx&kcdpMf->*SHU^1x7Tk%lYQo3&Ze)oo2U{cBrwXGW5+-NT`7{vUicY3cv~ diff --git a/precompile/binaries/minlib/from_bcs.mv b/precompile/binaries/minlib/from_bcs.mv index 69c253e6a98c8c42ace6920a1644027eb52f45fd..2c030eb8767e73eac874b5f82d79acec2b120547 100644 GIT binary patch delta 277 zcmX|)F-`+P3`PI9J+r%>A;~6E1X7Sd6uANoMK}Tt1!azrB7z(t1)}5zP(jC4sNn## zctOh8@*Ds8_Ppe`ynSALmj-YrOw6>sv-NS>Ts80fVEZFylSh4EeX=i(ci8|m%rQVP z5)wfuEb8z`qzJMN57{+??&zYHAW?(FQIHq~XT&%z#3V@cLB8%jxhMsfS~+5$`fOdH zWXAsCEcf?vb9)|!G8n4le;ugmvP#ul-7f6Z#q~P8BKhEDQ5Tu Duk{pg delta 256 zcmYj}Jx)VG41{OA_P!VIlH?HuffPmjNnC-30y-orlw;%$NK_F;isS^8bfKc;D$pU( zQBz=2AUwrq&DisjH~H>y@>wzfCsb5Zd!w^`n_o0fd}aF~hr>m>XMNBw4!%v}vSDrj zf&?Ulgs^`TScq-J>@{IHdO!)F2Cx%AKY&31!vM4kKCj+5tp(?)vd_-CtgU&D{_UI< x%6cicJYB!b=-TDdYO3n$=|rb4u2;5w8rwk;{`=FveXpt=MQF$7QHNcO@B{5_754xD diff --git a/precompile/binaries/minlib/function_info.mv b/precompile/binaries/minlib/function_info.mv index 2313d43ef89e3d47b8d2776385928cd8b048710d..5111c7d15058d4b240de152280ec5973e9d5fc60 100644 GIT binary patch delta 188 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 aTUV|?Xi9?E{?jB@HvJT(pPd`u<>Cjaa~P%o delta 342 zcmaKnF;2uV5Jmrd+lk3Ii8o}S*@6xMV%rshf&y`fy$lkfqFd6?as))j9Vn>rN9v6rRhOz06E&S4bN!iDCszFxVwAK}-xKfS0Hwzz-9DY*t!e6KF|UP@ll( z@Q3j=d_`Swe{&i*z&V>;l>6CO#upQ-1RpV*&{ZsT_CCr4YCgDeOLZjEjJL+(Q>-TD#r&7JjR+vr5(NRfbHCmr@BX zIOkr#xGpYQXe~S~q|`#7x{t#xha`Bw0vEy+e(Cafk&9Gv&#ADaJnnuno$f)u(@hSJ z(}C&^2K_-T>s_WNStm&cM;E8vUS1idoackAcjWDrM`=~E^8{6r(o!Ej=iT#aw^x+R z`$g61zs=-hmLDhmvpnnfYFDAM0A1vVtFt$~*Poanpz9ap{crKfgZ}ARc9J@%$}Jd9n3wZ-4jY+vlZ|$!D6y=>k2) zaX4><5p>(Y(};E5a>E7u?FCxJu|03e5H%5Qmtj?dyR|@%aXgu~$|zbvwAHX&)w~gK z#1})W)KX|kO@~&fKp+(CY8FX)vp#HuF~G5itk9y(tklw}u2^$4VMNi3^u*9NH7-9# zub`Zvn{BYkh*__~jkn3hIhHhO*`#gAjEWRZ<6zxFRK_n~1{H2~Opi=Zx1Q0iilH%T z9V6T?dl@4ZF2={@Fs?#3VFXfilXToNtfVqdL5^;~P=R}HrVXb?+{Va7YPC$2Mv5X4 zbPGduE0v8?@J2p(t2|sE%?ide16NnmJKD5p(xPTsVjwqnT$?u7rZAXqDN^`MzEPVD z6v4uHa@@Lu@(lykQ6NHq-Fk2h3|+bpb8YaF)F!|jsa92lR)Ety0&NvxU`&+;I2_5r zaae!|fZ&gU)nbef6)od{ikt-R1r{t&Jt!16iDn!{km(%|1DTSlIW;-?L7YoCAWqN} jmK!7{Q8+?21jRM~CrLA!7bHbm)(z*OxWPmKXCT-g7X^`6 literal 1348 zcmaJ>%T5$Q6uot;svlJ~FcS#~qXHqK1eIxBs3bueUqc>!rJg*--a}!@;nb z_fNBT`Cgh04^EDH{h~2~92dj9e-P|cQ}x!!k5jOu)ti3%spuU~^!g=bF(_H*{(enA z0W->SkC9{Kw1Wk0G@?qBi$P~>yk?=&h}Oz+ zE7M?pg$DI&ouEm492B>pk6BW2(y`=~olG()WM;4i#J6GRtWY}XLc=i0aPo3Pv)Ul_ z`4aBPvL}!h{)du{&V#dqLNY^ju^4BNMDfXv2q4v@W;&QnLLS4LLNF(*OVf diff --git a/precompile/binaries/minlib/initia_nft.mv b/precompile/binaries/minlib/initia_nft.mv index 74e59982a4cf2a8a7b862c50935de8723be62bf9..b7c9afc7e8c4729fa4e706be9f9989c7eb376132 100644 GIT binary patch literal 3968 zcmb7H+j85u83sTAgb0Wtb+F|#eYWG+ahz<+O}B^GRyOV=_KxG7-8+qJQC{xIqKA@` z>_fEg&_`&m+UZ^U0)2&EcY52I-t`Aa*|IlrHynvL{2%`R`wt+&KTQ8i+6XxkqbjL> zVSV*aLjP#JWdF7PV%dMP|0=}4OM&-0@9&oLkIIVrPvvh;@z1j!LWm-c9HdYM)zBmg z&_jd;!j_E@B8(#zi#|7c(X*`iMb>&p)|=BDv-y;c`9uOIuayYNSX%`Tz2AKJcwJ(UT07^ zFx|t>K%8Esy=EG9_|fGcPI^2sjlB!g$5F=uu)Me$v<6A4QO@hE52DJoj=iMYjn4FH z=j^&$Ns}L1-N6sdk=1rSSJ88)-Kg1)`e$iuEE+3%?kbJPhjOq!iYblG1CDC){OI(1 zu+9_HxLMO|wcBab@AH0q-iuNvA2yQ?P2TnTcHD3FlZ(iX-Vf5&*?>i9nxw_J_qNrI z+s!`s8~K+}dJ*^g;1+P`#ZkM^O9stOa@A|oi?}!7Zw6`HJLi4Vl=PI2Z8Kv~XuKap zy*30&fQeqe6Q!kobjzJFU@`P)Bog*n8tHiR(*#((v-K)))*V5^&^M^4c@uGGH$LBw z&f<$!*Ex;P+gZ2%BV109X9D{;%M;b{7|+3-_$Pfu#K2v#iI%#qN>aTTb8SN##XeuXg)$7I=@!%GT`H=wJcs*Jl z%O6JEsiK*Wqadyyk>-^<@!_>5AJ?Uy2iUpU7e!MXP#{s-Yjr1noRYjg{b8LBl3a-m zQF*B+4sNWG~P(eaALUZ%<0xE-~FtfqrFGc?cyvJFY|wdKZ(gT||U!}9glC(n0ZHH?N%9Ch2l zX#@|2;Ox6r?;MonTJmkqat)5Le)P>@<9O-+*oMbdl)^#ET*b!T^Fw2I_v_=sS-liI z9~yz&CGWuIAPIDlAaduCfie2XBL^gi5Mtgh`kgH-O1SATsfWCXU0lK*93v=3YR$zV zT1Rxz!SLEgK2eq=(h4yRwB#XD)TJH@37wI&g0Nym7Fs?heCUX8ukv9qe6b40H$F_J zUs!d(3NBAMa9q%OB^*+GiIwg0kkYzD3SO0}P~;&~juf&Wosa_$I4>44B?#9+Luk_l zSYrX2x>kr3a~M#b0h;hu^vOJ(lxzceI4nrw`-BfGL(`$R=xBDs+=H}yW5f9r8`V#+ zQNwT!EXk1oNH}U`zWQTumV+ZKTK(41v6s@3(jQmKC84CR!Qmn}?iNX?q@_wyg+=8l zUlye+eOZzoxIdxFZrPty6^GH^3RRU=`Xx+Eg|4bePWPcd?azcIHKu!NT-M|moD>a% zGFElBBI}#jEr*^QC!w##*iKkhHMZf{s>+r#n})t+>;oo#a1YeF4PCqkN^e7#?t!wfa*M(8Jy?EQt*fD!N)%SZ8mWwo#>gt1 zlkwJ9@R`J2s9?!`IEDIa;kXix2$ni7 z*V5gCpy&ABIzqUq*MKzZp)evMfu#j8w%{va*S!B;gDs;PY@+ z`Rs`-d9tCy{pWQq7DUKi?E{t{ScU^ zfuukYHX5XpPD$q3;XG`vZ6e_VVPps0+H0`6MiT#6^Z02tAY;Y|3m3r1&L=SIma~!rW7}8%#7I^+Yx$>jq literal 3973 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 SS>DwAD_nMN0$#aWr?pS-9U%<> delta 544 zcmZvYxlRKy5QaUM*XtRQfR+f+aI8RxLqG%D0U_`T@HP=G6^ND>pr)jur9t9Vs419D zI3j^%+2i@`ncv?_dQCSAi&s!w<2$4eTJGKRQhwsTz40^6+}`d#T$C|m%qb8N#1wqC zJ3vkZiE=A>NL2Vb(f!nlu?$oszvF@ZDe|}jmoPf&z$_T%&`7M(I?w=3K=p1Ky#|h|1{y^1 zC$`q64UYBOgyF9Za2sTtIaBR~AoD9G=wQ& zD8G+)Bhu0Nm;sF$@P7>0n~w=ta@WpMtut&aN zF=AX!Lc!`pm&t0xnm4dSW+h;j6c^ zqv`7}&-jdvClQ6RiImJ9WTU0MJ~NLX>&ZOUWh6>mBuj@RMQ5uFT}VB}?e;1EPjy!W zGfK;x!zIqOp0n#216P`ZzE^pcNg5JDXmm6uQ+yVcASLQ(fV5o5V_VeozrlHTK!Vl9 qg*<(kHq}w83PgKEU5#5-R}w{CjgnLarUcy(C0ok1k{g7m7vKuytSg%U delta 597 zcmZuty=s(E5Ir+@=Kg=X-`)Hf6Equxi$wbbZ1V7w4Z(!#WINw@?h_{+M=gc{C=3BnXCm(iy6%U{idhQ>($Is*)iN2>rc*`GMywE-W zUHALn`i1hRQ0wRLgS+!AHX|tLFhV;&xqG$&_}xH2xD&ur(@Y@9m>sxRPf;hqfVJo- z()s|VZ0yaU+N=rK>IigeWW8-B=xt+TXKcN_aSz^a6X4!JIWP)~i1W3G$vTj)bgWjg zH4>DF9QjpE(X)>nz0>G@gnh_~uljeCt-GAj&t6|H7V||qoxgtmYX0W*#nSQp%VYjZ zX9pRLs>@W|5hQ9?%#SVo@S2;A=xBi51IW5=51=JjJp+q7v>O#F+_XxMBF(cMiQsn1 zP2KW;(Wf%ejejNkK`?S6A*5smTwDuP%t%`1V)m2={eY=>P1n+O#vKXPmRIuV$!KcX n%4!d>DY1N6yKAzAV+$u)R^hg8tRaW6HC&5!ODftLTPolWhR`do diff --git a/precompile/binaries/minlib/math128.mv b/precompile/binaries/minlib/math128.mv index d2f98227337fcff6343ce222b64fd3fbdfa64c6f..99ccb71bf2e14ae0397ec0151f5f424715d55a22 100644 GIT binary patch literal 1684 zcmbtU-EPxJ6h8B3yED@^S(XF>NN%W7i3?I^OF`VUMHCdNC8)bXf*Z>;Zfhxyv&K!i z?B4EMAn^uV^C-LkyaZ>QO!;xe4HIR?KEL1hok`x^{Gwa{=@Ia#=ds#9V%Ty2Cm)FS zk@~ey^gYr4@y{Lrc%Y$1F`6x71}Q(Z+*!Hvau?<9P~&$A+Q@=1Hc4C{bWz|AOJo5E zTQob=%g8?n##7D-XPjdaC5%%}De=I;lQBj-BJhcGH;syup!a~K(OWjj&RCj^-Dn!; z(Q)h@#>prgCR1@ZiqeTZ8f94?jHQ~#Ut|)PG)ac5A!%G;_xWX(lC$CLQFr6U6U1VZhV)xx$%AC=7yV|mO%KMfAa#x z`_&?U9%ktz8AU~sjl(o9qG41-3&47J*Uk4zGERyldic<~!s+@1Wt*+$ZvWYfoxT3! zaOdD@_+)P|I0*L!PkX`6>ntz)60m=E5|908?9ci8mcO68@h5pUO@{ICE}d7b?>_Fo z=>OdxJPRMa3}5XY42%Q&5hZbs9quX6R8gvkrozF|0bP@%H&4GfR=C%*D6O%~t6CYR z{~Wr?+i10*Y=P^QxD|F)TvtrOHO*8tp{0ogg-#GsG4p_!je0XSw|`>8jOT{od7IZ1 zrZy`OT1WyEZOk;l$jd@N5d|0`mbf9-lyHeYONiGJvuB&@immMASSi*NR77Yh(yACu zdnvFz^9-6g{(u!iuT$!v(OCbC>(Sgio|{*VTrTWw z-YusZ_!vFsVD&M<9o80i6qll*xdHRqqV^Wfvs-@jMK_8BS0lL*KAIJ8v@)AxEE}9 z@dnlv4YqzHps@gx3icJ*zozJZ>mFT16YXCz=oRi%aM9|#acTi+VDED7lD1GUs+h5u Pi}3pfyhB*j-c9%lhD@OJ delta 838 zcmZvay>1gh5Xa~9K6ciLogiaAWL@mYjtP=;5vB-84ibVl;7#Zv8JZNdM~#F;L5BcQ zQStx?UW1;RStmv|VNRNxo1OX3Z+Gu?>wRnS_VzE!0H8o9s3^GoM4wIa#b+!&QPuuQ z?=b%6S7oYz2yL<)csmC`e}IzX07haW$j<2*Nrq@`gb^CDNENx)+V+ps;!k9}>!yl>n*rvuz; z-q6UTXB?mxS$oZQ>faye&~@27m826KT5$5AY!2nLa_eGcyXkX9dZT&7Rq0)lhV~ki z-R6vYgHkP{ONj9mNC)aRU-+={M)gK63=KMdz()Qi$~>9ft-(eMfYS@>9D;o|njTpdiBtwHBM=s1ky1wP1NsUKQbfR~3%b5J)p?DmilLc6Uu4be` zBcJ^=4c`e|SJ$H$SW?rQbrtyXdm17AK}$=)ixfqt4f;1fkdx-C^cONSPj_QxkT5`J zrYTT;pbxcge6OyimUTNN1qTW1U@Pe)pTJgJ^9`=~I@iA^-@Dl2x{`xp(B>uY;z@I+ a{X<9eL^t}4{2y^vpH2h;r diff --git a/precompile/binaries/minlib/math64.mv b/precompile/binaries/minlib/math64.mv index c102411e45883d24a18578e3019b471aac33850f..ec22cfbf0a122c57ed88690b43dff0ec08994450 100644 GIT binary patch delta 664 zcmY+By>1gh5P;`z_s%#32!qU%eDWE&6V+((oWhBVK)sOZ_>8a q%}>K~4Jmdxs5p{n^ecu=@kQw`G<35GmELw&o7+rG;b3?tU+w_jhbE!` delta 702 zcmY*WJB|}U5UuZwr>oh;1mnRA(%4?vEJ9ij0%-$SG9W?X1_%*w408h{W=Y6a+6$17 za}**1GPnR$#vY(Xs;;hj^WN+3@71qrb9w8B6#y_oD5wxlkM!y7^38i3{lxbA2fD)i zg+Fc)kjY8_^baT!N0LYysUS}!dZR+G5*9$$Ji$Q>4!uXr$Ps{~j6_u72+FAB^Tlg? zUYd(&W$02w!9pj&vx}LOh4;4MxYgecJ8C~UmRWyJwMk=~pvkOF|BC9Db6q$!o40~J zOra(Bxsd;LIVMMcCWnRzCI#(Or~WG#)vkWC|4L2eL=wVH|Ba3|mD&JZ4YnOz8w~y? zhSOo=OirOr!6QS1F=XfWl_)TJuY&{w(>zmVBdIhG4C8XuwONvMusN1HLqExBcJGEu zSr{Z)J25Az{XP~Z9j>$JiQd%%WAfLB@>zm$u@j3UEq7u!5_jz+iyz!cP^Vp+c(->6 z!-so+Z?{h0#a(60koBLpo6F;*rcKwby|4EJw7=D;mvZJVv38dl=2XuNqd+~^Cpt5J P(6y%q^|+$`g?#!A@zy8^ diff --git a/precompile/binaries/minlib/multisig.mv b/precompile/binaries/minlib/multisig.mv index df6af4e04f9170d37a6c6b6ec605217b20aa0f95..175115dc35b926757cddec49cc951ebb451d35ba 100644 GIT binary patch delta 2349 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 delta 1699 zcmb7EOK%)S5U#3z%xrhh?Dp*V6?-@K+UxcDfnSL;7y?NMC}1Ief@LL35`k>VS)VsI zP8_0@kT`PU$RYd%&N(1)jF33OfeYfof$FghYoUOtL(Oz|RoB;Fecit`K5y=QHS@F8 z0N@aE%CCugUyyuBP4x$TPtgnYqmI9Ev-*XbtNrRe)8_Z=ru(-3%p~769A`-|kirB^ z!8Ejo3Sy~BAiF+8 zkjwQPL9L7tK)DsJPK4C8kowvb0j^(>fE&{UYEx#QHY9=A;`{+@CsTmel4*b`-N0B~ z4<2>`6mg@;S%uU*@p>`~xSNDuU&5@HJ}dnj^NjAzN(Av+IU&K@Jce6~66ki!knaQ- z@8~7Yz1!s--(BXF_uL9p?#-+b0=&x`9n0YoeLb#q zOtDl^tYR6(lIKAR@%$(H5_eVa`1t6!dUAMh(tp%D>_5JL(C_2ixC;k1SkN1xc4j=Z0L%H+(7rCqO{;*?q1`XA+F>1rj3g)9uYJ8kl zd__ZiI@gxVYCQx+r(^J@le!SV#}3w(*VS$a2tohSVyd`&U691jf#=V@~t`9z7CFIW1f| zSme|W!R;FG&ssU!= zY2ZJY!*FVgZD~|BFd|RqgPbD@RZ>1CYgPJXOLKBsHFf1YWTiumvKNlQAd zXd1pu#s||TwC?Fy&9>xcBlHF@K(*l4b4Lk9qDT`y4-X5zd9)b_;GT5_ZH3w!jWb2M zS6?P4Ot?_&FgF8H6S);N$}>sZVT`E{A;LQf@F&QAe+>Wt diff --git a/precompile/binaries/minlib/object.mv b/precompile/binaries/minlib/object.mv index f9942a005ccf885cf272a37624af86d25ea04773..dcdaa21c7419b046f133fe10b2c66a2dfaaef022 100644 GIT binary patch delta 1507 zcmZuxyKkID5TDuCx8Lsidz{zzaEyI-wsZEKpO;`eU`U*VVBUdHKxIX6LY9&gv3WI^ z0?|-K-#-9|0u-Q0heSb-(xyRjL5T!4U1mQAe1@!a^Udu3W@mmgv-kD%-RZ5bCjPJy zfJqRltlH<>zcKL*ugahJpBQ~BKR5cvw3*#c?<({6*fslWmAU)XzwF4*?RIk57U}PI zwraR`=k1LH1jPU~VpU2&s3{;>r@IjvI>>QgbPT5yk}<(zrpbE3IzTox5&+F4$W}@_ z(9TKcGkFD2bVfb7$a(JpRnG^|LU4n{T98W(lF`A6pab0>7le(^0_6}t38w(fIv2P|L4RXalvTOb z57wKMHNm(tX(ff~SYraY;$7ZYUg0Pa(JG9ICUN0dJixc4baYVk*+nK~@jmMtsdOY6 zBYE!!_8prWdFS@v`u<>NZ}+`hgWGcO!Qj@u7~I_5Pp;pflXpMf8GN+6x4(Dq6L~0G zX#(ru=Of`tr59!B8Fl$+<*ZYDYUjJDfdDbE0V1|=4w#~@mx~}L;16umI}5pSEMXRN z>x5-i=puF9-eV5p+_6zkRjtPfT2|sA;BUCin@a}s8XBCBc#qV&vt# z&11-giheAlMM;X>Kqh@Cd&azl%=rpqmL7;a4p%HC3s5$o6qxe2))I&rOHbcZAg2iESIn|a%!O>+bb|_WRPuqij z0vp;f!wj}WtVyAnS+=a4DaTjA34?~W#iA9fNIf%RRZokq;nd!lm|6Y^DMuCkvm6z4 zxuZ{x<1guFGt1P9#CIcV1!So=tZY)3zUXNuqmIoMUt|*pmZ75mjH9b2JHZ@cvKH8i z|Gxlx@&%ls#}}PFAEr=jTBI@)waj|4ZbQIF%pfpZJHhPCPM{`M0x=p%6?}SDl|C|~ Ym#z45Zo_#F(`O;+VchWB{4no51V~$b^8f$< delta 1541 zcmZ`(&2L*p5TBXdeQ)3H`hD1ICviezJ89h{PNouq@k2=ii9{-6<82adPpJ! zrywD5M6G<`3W5XbfkU~`|A89^E*z1lkb36CtkZlI*u!|<&Tl?`Gqb)o{q6MHHxmzS z1OO>QjcQBc>h~o7qMG_b{DJYG@=K#1rH%Yfb}uqNSFhWzYUJ+JzH_CYTCMcgmdt*; zyEcO7?!MdGgNOh%)|3Jm2_Z*g7Gs)49SAjyM+h)M326;aSqC&#Vp}6+(aan`s{jx) zMHytf;t|xW_Ylo{Hg^~e3nMHR#~j3GC4gS4ON3+v6yP(QGTB>&aWFk0k>LC!L!X^u z&*vHv@Iol*`4)R!4B}GM0C*vq0a%Mp0bFjK23U{A0X8&?E72^#CUB`Q&LLNQb)H$l zOAz#HQQ+}%9ONs(im!&yuPsQ_EAaXv2Y(}oH>X&<)s=zi^(EHdrr<6jla({5RqGQd zA~7fGgTL{X5arQ+kiTcKbJW zwm!Js-&Xxk`nPvw|KqLQ`w!IbYC2Eh9QfH-Mk?W1?4N?#!|VAtM^A$Xc6PBaz#ysO z;~)b)kXEHp7+N^&XyH82Aajk;)Iwn#rDU%r>&v@}f9YN#Zy)mzTBnR#WI{M}`bG zWujT({VJ*a_{C diff --git a/precompile/binaries/minlib/object_code_deployment.mv b/precompile/binaries/minlib/object_code_deployment.mv index bb6260f9b672e701f9c33917cea36d9ac665ebc4..e1fdf2b75d9dd9ab7142a6c36d53d0fa0cf0913a 100644 GIT binary patch delta 569 zcmXX@yN(k<5bW-G?as`uJ?qE4?0Z^R2qAO?Xhn2ia532m(knYNYD|Io}7@u zeE<;wNQe|ZgMbk63qUVN2i2vj>6+HeYxl*SUX6Y_17JNupZYh%{g?71cGWk0gXTNE z6VV^Fuixrv_pAOy_IEV!>-ZNYuN(n@1P=)W=)nLsU<(c}PmeA}?8Jb8^bb)Bi4lra zBN9T#umf4dsQR%4)I(_j&1S+IV6>egH{9uT8OI^xl&se(yJ5g{dmAm^-`wIvJlJmS z&JIiQk>!wh!WfW9sL01IvZCK1F}nOQ5v2WE;#3Ik$9T_5?QLYNC0ft%v$JRCkDgY` zC&lx->qELa8PChQY#y%4Vp+|Z6^|E9QNCD}^{lGrs%)A?6W5Cs>*w_>oR!V9YPqZy zbulaJs+@fg;yqrVbl@l`QYc|~hj-J#Xyk`$Yv}33T~h!r5@Ep0ROXa3PbrtVaKbB& zP{DegYHzFw&PQqF!GgnM48G0GC|AyeBm-~xw7m_KqC|Kwo;bF>w8F_;%Y#(pe1(-a nLGC(v3%U@xUZv_f&JhQOb|MqGAuayz7P6^sKfA5an=<|d>Jdd> delta 507 zcmX|-J8M)?5XWcEW6opFy?f8iKJqfgM6yb-&_XU&`UQemX|>I+u!Xx}qjg%rM!h7E zGNrW^g4ip520wrZ_IA!C;J_K?@Spkr&Y7?LnvX8Ge=`98JmL#gC|D$UuSuGStwAA*{phyQBTnEl~m>s4gLCgI;Z098C0*9>$R#6urrkE`e+?}xDf(`JxRE~Aw5c4 z$3D8C*Gi=~6(zRl3FKf~;;22un`9_O@7gDLzkQEi+NbJr&(2n>lxIn|I@X7~=M0u92}EfzIB yGg0gsGTt(E`|cw5#sU&}G`GRjc0l?{fLx8)96|*-caIVv{RdJOfB<#lI-`GdpEkGv diff --git a/precompile/binaries/minlib/option.mv b/precompile/binaries/minlib/option.mv index a50f65dc5634907f8f96be6bbf4b978571a0eb30..2e75c7b85974627a5d1978458257dd311a0260a8 100644 GIT binary patch delta 713 zcmZ`#y-pl45S|&2*Sj9u_rn2A3Yv&il(3{r0w^i+1QE}2B5#1Mra(ez5J(X%ZC)W& zq%;VSc!|vTF1pi6SSyXk^X+^;f6{ZBUcPye01z_*6E`l-kT0D2S)pN@jaa zb7;;LQwD^38HCymy9yZ#TJlb|8RvU+_0g zQ-mJ56*z!KHP`czNarevYrCsdz&XO6B0GWoCGyi6(kn8K=E!WwM3Ih3NbqP4s_P+b zd^2JL^~6aC1(Oq}a1>h6lbnwl7;smhcN_%X!--{Gk0BRQqk>9S5VFj&-<~dAh>nH> z`!i9dJtdR{TULq6&?RHgK+LBmvJb~=nl(v?x?=8YzG7jGa4ABQ295 thd>SempahVc>Ie0Rr3>bKYQ|D-<95LJe5&HvSj9BhHNWv6 zT>g}joF|me>D<@11?^pd-t)wX_3Mb4*f~WCAu7gTbxMQcFhX%8?Q<6EOZAH7w3BMJ zaht%PDOo*_HeNNAMe7yV(Sf&m14X`uruFsFIyb7;uP$CVr2O$If5EP1TG;zA2(d2o zs*dQ6&@q|OejWh!zHgZhl^eqN5BF%#eFy~Q=JnOwf{ZN$!jFKRnJ)*n&-x3z2w1qd zuu|)SODc*J2MfsOMvGI?QKx?tpU|mg+z+zST2q>NiJq diff --git a/precompile/binaries/minlib/oracle.mv b/precompile/binaries/minlib/oracle.mv index 5f332c26f0ffc0ec628da090d170bc7ae43293c5..e2da6cda645ed1c5b05c8a22eb2b7d7b5056b052 100644 GIT binary patch delta 69 zcmeyv_@B{sq0DP;b_ND64n_tRCKeWE4k1=4VRl^$j#LGKRz??|lZ-+P3=GVSOh849 SAjrtV%mSoYS%K_{R)+w8!wA*@ delta 66 zcmey*_=nMIq0DP;HU~Kb!nci4dj$VgyGn zL^nT2@|E0H_tjgOeAI7r`m0=zpAI)m?}k5sxi{Lh&qp7mg%`EB`1;}cogIjVFcKij zDuxtPmI9l2EYbqv@yKvy!h!%-d;h-kI|SYI$E^t?Zv?K!0J;k0e=z zB|ZlZ9q4)q>s=k};cm}cJQ7tr;%FENZmdMCaPy$!)K-6$*W-tLn81zrs)NK+F*tb&)A$lEx|d-8f5T$MkP?F2*GzI-oDtYuk^ z5)LWIznFtsPN>O&s?cR zBMi7i{)H3*gi&1ljavHO_Pk=({zKicPr>Cs?b7Y#EZr~$d(&2vmitWXc3I=9mdK2_ z$wET3l@(HJxxb7oWm`sN6ayu;NU1GRkxHnoR%44GP{77U2Cin&psRwxIVgdZMv&C` zlfw8dn^HWqVs#?gB5J7BM0A8T#*~B+Zc27k*O(&vmYlNO16fz65OEEIM!P0YOB0sS zO;d{gS%~8e<^v%`BuO!U4f3gM*J?Db>YiW3EO9fGxRz@ozYOj&E)M1vnK1m>Ftx#d L;L)Y|-R%5ttnpmU delta 1014 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 F_&-(mdS(Cs literal 5184 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 HJAwTVYrmxF diff --git a/precompile/binaries/minlib/query.mv b/precompile/binaries/minlib/query.mv index 5daa782a026b45e3505789a3b05adf15e38880fd..380e0006eff240e892b7f33a469d0a57b8a7a43e 100644 GIT binary patch delta 136 zcmWlQJq`h36h-fQ_kBNRzF~|;AwsWKDl9~257SL-LZ`3bvzz{Q*Vd4yynF delta 136 zcmWlQu@wP96h+_r|IeRUJIh)Dfq*~@1bUGvU@MR*K_*awPzM@t4mC)`BIDfbo_o*X z6b_g9yLJGXaPh3&$~G3Z>)79!ZnE%~EZeW_22Y*kkM5g?<&sAj^Nzq6(P4b7SoYnO>l^<8f4)g#3 diff --git a/precompile/binaries/minlib/royalty.mv b/precompile/binaries/minlib/royalty.mv index 426a02309b1cd6959b8944ca8676af5720c1cfdf..ebc233755d5c5e94e036ef7b76617568c55985b1 100644 GIT binary patch delta 310 zcmXv|yG{c^4D@*S_V(<(+#?sDI3Qg_po)Z&p5Nd*Xc3fjC_exVeSQE@Qqdp^I;bi5 z0GjwfxR|kK#@77An__w2e`!u62_!62H^1?LB2UHu# delta 280 zcmXAjElvbM6oji@_w@Ai>-p(n77zohBmAgM$Sx<~5}-HklDAb6on+qnQnjy8_LPuEks5G7Ym3tH fKY*k;kzq2O+LJLVk2tItrD#?XMJ1E+eqs-QhX)%n diff --git a/precompile/binaries/minlib/secp256k1.mv b/precompile/binaries/minlib/secp256k1.mv index e94c009ea467a3b141469c032e1fbc3dce5414d9..d290f1381c69ba0193a2349daa043aeb381f8d2a 100644 GIT binary patch delta 616 zcmaJ-Jxc>Y5S^L*yq!&QcV1$|6tU62kWwrEgeVpf1WgfwAP6a~C6$GRl?ZC1VCCQN z9|($ty_Itbq8G$n_U+By+c)p+UAPY8%g#GHfWQcrY_8f{dgRT?p?kvzFSWN(FiO&bxEwmS?^+W9ci&lBq?d z+pII&gJ{@L52G=yIj<3648{L)z9Of3G?P<*$kl#gSMyLMPyIU&7L){eE|4W>U!7eo AVE_OC delta 623 zcma)2L26V%5PenE-M@cV|C#wee-a6SWDw&OW@!$PGl+{30?sUg1hNQo13_jbuCfw0 zfuKv*<_vlT7j8U&)jxi+$R#yuaFiRM z9gV@=e9{tlODv<$TfnrM0^8daQqq*7MoAnZLS!OhkQgrK_2+k+3)*SNXN%L5=jTsP zRxcN)t7k6`H=k(l!!>=UN4p~&aX2tzC1x)8Mv0Uu6tg8-dc3)o>6)3r5GzX_NVD7j zfmGjZS9D-k8lBn>dM<;CC|cXzZ~l}2@QKT^20r&3?Y-_E{$*AF@TokZzRr@Jl0uzI zdyB;Ft82p?+56d?vRBX9MEiSc#w?3}h{~J?Q5i&=`;Esu`ZXT)T-#n@*GfMDP*g03 diff --git a/precompile/binaries/minlib/simple_map.mv b/precompile/binaries/minlib/simple_map.mv index 7bbd4ca877fe9256f62ca1d7792f58822751de2d..69147e6587a65b5b2901af7a53819759621ffe6a 100644 GIT binary patch literal 2114 zcma)7OOM-B6uvLtx1D5?NjiN@Gef0HfJy~Y$DIZ0Kr#pc9f>ItU0LqLEf$F#*`8_V z7qDW>iUs@%{s3DREZ|SDVgnl%oNLE35d~2vx##-4&v)**`TqKEMj)hpj3kjmy8Q!Y zzu;Z(Py7=RKeDfh{F#rtzw>Xf{z`6|ZzZ$e$zO&4M~4T0bvQyuA&UkG3j%wDSVOTC z7~VL-gfWZ+qK;ziaf~oFLINQ^V+fd1H=qBQ|c)Z=1?F8HI9YZL} z1e44tpLK|kVkD&;^<{r#$p+~w!VM-0Da;juU$e)CUS(z@D^CVitOEH}% zizKV)m&v(z7SB%;bzBQSiI;2^S22H*7e)S@Jx#M2KU!94p7FdUA}ymbUnC-VQ5Eq? zJjD$vTe@7#62eww9K z8t?D7qUh}I6Bv!==}$kJK8_AP{&adUc^pkY|M2+H@erULLpI}h4h784$H|MdtjcDZ z5ejOPhewa1!=uk0P6n-ZT8^{48b8fXvl%!i1P(Zy6-=<#o;6GmOc_FEQzL^zWJy3m z%(^}aiG_2xhYWpB?O|eIhT3>NcH46{LyhjN8TDGDdtmgwy7!V1+$%^kgZ9y(YT>Kv z?%vW6=|EZHF01;nR8vh}W7|%mT@FO!9kvB|7#KzxQevocSU*EcJvix36f&Y#ahyxA z`kzcgZ~vuCEf~=OlovQmXh1{GItD>uaDm*%6IJ8UMh83s*l+GSyexhoS6Km?>-AtL zkU>?nic)sUFO>y8U> z8PU_8i}e-=wC4Z}0KnI4lw1*(YijsJ!Ri_IfiiTe_OTVAG$Moo-L2iC>vhmD{o1&YA+T=BP*~za8ZZ(a=-UXG<2Tk01AefUh?@dS0je&*!~zDbgMO{y tvFo#@A6EL<$cY5kVlrB5%gB0OVA$m>K?4*tKpSPWn=AMt0)LbQ{SBj^)_4E_ literal 2166 zcmbVN&2QX96rb<$e0X=0-6WefNjGh1B@SuSqQ=dsf!!bkG!iKiJy~wnEf%}>%68J` zAK-$xas?z#ocIU0^AB+5j5u@WjlJHkDv(f}?2KpL$M3!0n>YS(>n|e^LOw-VtK; zj6I2AB@iZzA&DqVSaX39v9N)CPl3E;eJ5_Wr4x5l2P3>9VMME|%t^YIz(m)&PJ6vq zsckqfsK2^KVA_;zr+2NMuJ<uX?OU=+x|#@si9!ksh2U4eV?!{7KLImrL(H;%gM~qrI&~^SH!C8S z+(?Bhv0RApTYDCS_G4l7c*as!5c`5KEhY86uB z7c4YrIxtng*CT|YT#g`IhQtsNY%L%$Kw?sxka^_IGKr#;3LF*!!&L(j< zjb?H*iKlT|(y!txei=uHmgRZ&l08q-u{fQTNtTMNnq*RhMK+Cj z3<`NCNx?iBhf)6G!g-YOt1^$yOI$}dG8 zPqWKdT*l{RmYd>bGz;r38jZ&e&M7m9w4iDHQk>^;RL0_BR>XNJK_!eP6Pd@CabAEI zmrP;Lv$Twov1FP_Po=r`eg@6*yq9m^x>AwfuJI|)GWD>c|!)aVbjuoi;z5N6C z>n3SZCehJRBML7Mp1EeJp6=-5(bMqwlg~!S!>8fsi;vEpoUH@31Bhl2O(22s)gXSA z6lGC&G_+}D^7!;gcyjvr<6*DSPKrUAm4oNmMLGuGguvN{^MVQHO`S18uKSSbYh-YM zENPJdGmrZQ8ma+Up?7=|5Q7eprIs0L*!%hr6AqTGO^x=KOcihatLcM<=?D4&Chm@q z%%CH5qUV{Tii4Hg8eopKySl2!5=%AF^cLH35={V_XuQid0mooy%78*UIfvD=ZVA6t zi})TF0VD2ma#+qSSiVin0YAdTf+<~tbX$%o+Ml4clNzY2djT|b&mXc$97n0^Tp@f9A!M&u977RW_ z#NE!41d^=4%O;2%@tW>0Gs-LnJbsJa1%U%Rgg|%MyA^9Law{}7VyIzchJUCH9qA)% zW#AbZDDp-?_YB4SK36VtOY7XNfKvh<0v#B#3ZZO0G#G^NdGTpreHQqJT5gyXEq<)5 z)Y5t_aoo4cct$~W`F4Gd>O*)(%LQk9?7-(E<%?0@YHQ%+8l!`jkqeqOtmOB>oWBQN z_{oBJBTo8F5l9cB+G%RD*#2L&!A))YZ&0yRn>BC`ABLs2BI~d<@B(Rx56uKk(}o&u zz~=7VrNedJ&5T4n0ci(+?)*G)KV#hXMClDv(gCq^`(w0^rTj^^PK>1j&awRS3t* zJyxoOK>h>p12{$EkMvln+_-S+rRt%F&U%fgDk>2l_VH++ndh0AeP6d=obAn-8re0Oam zdj`aU26@QW*2u0@aupi{$93>o9)*?P?G)@QkR_skq;EjF5bUXZPLeX$kAWdc}A zQ3B|vC;=>|C;_abXbO$aS#E6g+<89NyEtOlP~5t>+*%NZWj2$=1h92sVmJZpT#Qk1 zWvS0buO?ywxV9Xx?DbY07koa^#4lE2M_;a@Faq($I-)@PRcj+sZcZp0@Xe$Q?rufu ztw|NUy&Z!))4aQ%#XJ<5P~$haTh&fbh6N~$l9-LR#kVNOKZyr2Gsc~~758v_Q#RJ^ zU^qA)Jlq>TI#vfqM~6q@hl8W<2ag{Q4u^aD2gAX^ela{e-g|WTWVnCwME)g5y6dro z6_9Odv8eVb)cssG;+|LVg{6 zC5Y0Df3!C?J0B8F=(1qJWIHv`bL3-{1#iP*4V?3K{HOhHw9FkVuS#&*YM#I%sj^Ny zfu8J=UImwP)3dToc@>hWuqh}qM}%dAcPLg+dJ?Nx#aW^8y}`V{6Un;Ddx+E# zOu3bhajzuzOYA=L8M~KOvilytjOmQdk!15~Vt$@f6}$*n1*uQ9KDw49PO}C-d03%5 a#Tu^v-x}^u_wbQ5M47UAiZuX#z3>l>e{AXi delta 1465 zcmcIjO>bL86utM($D21Ze)e;m#<7#eanrhvlQs!$`bt|6O{Q0P_r^8Q2gNc3K?@tEP>GAkPj=va9^Uns87sKgvI36AM2czMjZ-=Ad>G1jS z=;ZX}kMd7BOWGM0&;_ZKb%2_9GQ!HKW6_g^TzKKwxjRX*dp8II2VQSWpw5FclN>kHWwzCpZS@*<r9JcB%q*)Nb6noe zY<{H*@r!pbFT0OtJ3oz4})sba}-AvWc*s%x>xKBVt-4}8Lj*W`xU zatUhn#$i%{#iQ~)+DA!%+uQ6VGs#}cs)g6=-)8b6GsR~5wV6I|rWa<#GTr2P$Gxh9 z;*v*h&D3en@u~M*nAXvN)lWyr8=mcIQ89PB1I#{C9B+{s9*5b#VXy diff --git a/precompile/binaries/minlib/soul_bound_token.mv b/precompile/binaries/minlib/soul_bound_token.mv index d0e96619d21d9f9c4fbb57a348681ce93f3001af..5fd762061918a2caa285e87a785deed786d2398a 100644 GIT binary patch literal 5018 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 diff --git a/precompile/binaries/minlib/string.mv b/precompile/binaries/minlib/string.mv index 302f00c0899259f182fe5ad148a0b52fb198ada7..f2f46ef11ff5213e817e488d31277b74e56cc512 100644 GIT binary patch delta 503 zcmYLDF-}7<47Hs&$&b_jf7)LpDh7m9DiCU6K* z3?^0vgaei8;l+N>@p~`fHJq$=KE(q>L2%@vX|L@q2ENA||AQYG-py|NWgao!u}cs9 zP0QK#6@oPg2y6)u*-;t1*8xJP6suU6C`nPGGAMObD2k0@YRhUb7rAcAho+wu+uQ-t zV7R5L)KPhstBXVDA{m1L0-!6`bS57l5~}bgazVuB0lwklG(ro>L`*iCb51N)cx;bF zsm#fVvqur8*{Kdw2kTPNC$Eg4SZzbk3uRIanZyeWNz|Lx>k~0pCC6<*0J5TssJL}iVy+vt h>{1Q6XDfj|%qgKD%}qk~NyQO`Kh+hrg!-?EKELnTAW#4R delta 445 zcmYL_KWsyV(*fJ}VY&;?hu`5A z^$*ALm%oJl>n9(80|E#WphWVpX$T;t43O1Rwc`CW16r3oC+z{s;GVX6rR&|;FDk%L zmq3rk#|X3}|M%ao+7y*SzyvWtbBk*UlkjbWclh>=!T=>G7S?bnMT||hT+O8_CCX?4 zbBPvtC2IqW&OE+Tg;zBmY8X#SDs0KnxHfHLRH#dZvZsr24_lExrIY3}tvEYNFWiLlyL@OnpDqcRAp#*JDMK+w zlr>Mpgt`;;8hP}Zbz)Yt)gco}dq7r+TAlx@8=*X`?92s-cv*n;ESwDpRDcZuRx>Xm TyCS&`e?1?2`g@F2dY$15s@fJa delta 269 zcmZ`!J4ysW5Pel$)6+H8POpyO3X8~sM;K636QfP{4xYqRJi%aSG||GcxOkOGJ%eEP z#$!^Cdi6fkuZ^)ERzKze7(rN;Zncq@o9dNzu0F~{Veq$$Z$EMKp;xw7jt4#RTfcrr zAvVrHCoO#>2*yTt`L3Kv^eph`xCJq1OUE_cUX2ssi6P!MH9h4Kiz01ASLC$@j|?^Xkt1i_FQh_!bl zztM(zE>1|lQ9niPb)45f#!t$_<%$m$D&S+5ZeT@r?b zMCgkaaWOP#%?*bsS3n5TwJM`gH=C;%_YhfDmO3nQwZF^)7Y124W$j#Et)7hY04`?D z3an=<0c_;wLvZ6#zFMU&XQA}XY|)J?`69TQhs?Ek?SwobMVe~mF&>)8BE=9Rit-2U za7L6{w3W)=oNtB*%V+epydx&f>GaVwIe7SF@4>;{+mDa-j_$pEA-Xj29=5SPzm)15 zOY5N!779tx{sK1QNqMSf*PR8l$YbH;a)L$Tq?d(v$`g}bLQEnbG0|+K zthS;^>E>`zEjX>3f6bJ-74t3quVejRj&XTk9}X$}2RDSQ>?q5xhaU$-+$0OX08u4C AeE+e^GV_mY_NqDC9Zrjz^)_7X5cNK`n3q&w1Sr);BT z5FwDlLhwJa6a-5fE5Xh;bBS2kxbS%U&HLUrZ@!tA*^hMRbnx9o0N@yC)C0c$3dJYf zkYDi()eHHHw@%_JJB^R^TirJ2TG$Wzr*QAnC^=7kWBPh$I)@k-=Y%u}q-;P2XjRKY zr{Vw;%?Yy1T7cZ~u-4X#+;PlPrL#U2D)OnTl0fREz7fi7!R_Z^mnE)|3s~m!4g%ny zL$bq^c0>@a;~Pf3k`f>H83Vqu)MX&nmai~?Yr`@KuV1Y^Z!)d|yk53FoR%vAZd9uw z->BC7^35`gc&l8Tb+cOJ+f@A`navRb z%QBgd%^Un&$i3O@>CEjvdA@tN|M0=Hquryu<}sgqJmUpU(*(9y;e8L^SSYEZM;9np zlLTsRpcdGClk>STzzkX;bA!x)VRg$2BQPfi3RB0H?kn#Y_@lSYED;e?K;RUTq9AfN z)3B*ot+>_9at($XthKa3l*EbGqKGNTWZ=TU7B*iZH`k8U&Wc3TiIvjc8(a(vRwh_m z(Q`=kD2b@9WdEktETH{1vv delta 60 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 b-SVbyM8_XU7P+zfA-{&{djm*{P#)MnJjP(B diff --git a/precompile/binaries/stdlib/account.mv b/precompile/binaries/stdlib/account.mv index 377eac117ea27a11dfe871c178a4caf233a5f36d..e2238c5bc70313165d6dfc3a76bfa4834b4dc773 100644 GIT binary patch delta 811 zcmZuvJ8l#~5Utgk%Yk5fN|$ z0we+u7jR~Y0FL15VvTke_eeFbr(V5RHQk?^kImwE`b%?wN)d!axOj`%dpyd2;7=(& zgoE}=_(s*T)cCIaD)nhyjQ-RC07^gx2!QtFKo$$Jh!rKQz!sws5o*siP#7LLZc{aM zP{C7#o%9KJy{wO^c+W{=$CsRXIi`Zl@x<{J$5$Os9ba>N-SK|Hm}SUJXnk_VL~p*2 zbH-4B!QW5H@$>n!SMwJyA1&|W%}=lK9xq0fHHEe~s*Sc<19U{;@oLxcp`ZYZLWf8u z48eXxe%os!MvBbSB8rOaC@2ruQ4AVLaln~Olw-)+b-fA)n8__&&_B;vl&maM$jzWg z2K(ytM)%_r}J-{9UKr6zy<-(0tDeA0(gpU8pz-?r%eXf zAS!fN>VgZ<0}o)6J^Jhs_;lN1>o!X}OxgA6X0f!#(k+(uSvp|pHcMZybcZBiSwcz_ zbQoz#l!87U+9+$u7XpO?gbCXLqG2nF<9wV|`sn)iNp_ZRG+3C8FHcR;Db0^#lf|ad z{fW7Hdu6<|3{Nle__ax-M zu#AiJs+tB&lERebgp{BDVB%_$rro%f>3L>~pwX)6^kRAv_d0hNRo!zlbqx8;oAbbR z?QWJ=;Tbh3IaoD@Kc&^H+OyBbr8eDOgUviT+_$Kl9&2w&pD}}3hi71qz{@-t&+6J= zK^EDIjbip9GGlkiw$QR$%fO6l)kOO`RI99_*J*Z6lm35~2;%(mD!quRG|$3IQ$zsnFG?srAY>9HpnQ~8#6c?XE7&zV47H)(^$`*pM>8~)W-nsY(#{BxdA6_ z`LPkSGDeIocZ{&rN7jIg&w;=-b4cjA86y}_(Vtr?v;+v+B7|6hM{7mUB^^uKlg9P% z9xtK#8i9|#)S#utoFw*tD@)_v*rF^BXSutYh5Y_I%dWLQA8LfYsB;P`!=>Wg z7L`#Kj~=OYRlHwmp@VKWHeV?2%w!CD{yiexhH z!=`$$#}2lJE(WY_lIptb!!AP50s51WGQi-*kaCDyb0JCHzR^bvac9nl)ZH6>aEN;1NU@^tadclHdP= z6f4=?El*YJsCXN4$k2N#eN+%>CdH(Pctd%5ScTL+KskW=@p{Xjfv#7OyDmzfo%j^Ah?7T`TrxSADFKbB>(^b delta 272 zcmYk1Elxy15QMAxZ|2Rs{dvJ6a0n8D+@KKL0M7+hqp@p2tp$gJV{nf(giFwmunDa? zRbN-94tB7|m(%Ya06Gy8rtQkE!*4Fi_P&1dZ2iSIwr7oTuX`@uO_DWKumB2zswCj% zK!l~Pg^-~p5<^R?rHYM8($M1L%>JP`vb+_kGdlFFI>FrQ|G>G{4;FJ1NdN!< diff --git a/precompile/binaries/stdlib/any.mv b/precompile/binaries/stdlib/any.mv index b5f562b1a97ff11d39b446b6f0fa3d2d504e86ed..a5bbd540df0ba90fd16151c0a255170f7216b67f 100644 GIT binary patch delta 194 zcmXBGy$XV06oBD#zVrR1CI)VX6a)={u1zgXU4>X$2>sA!1??>j4HC3>CtXC)MRWnJ z8NJK%p7@zZ_x9UX0G5s5Fh`Rg^RX0@KxL(VVaNO64Xq0`oEwdr&ngOH1W6nvGR6b~ zQbVd5usGFlNBt14)_{zNM77NZdTutWWI8LY{~ULDDRN^r#w*r`bXjCcY8LxdzTRCC c!)u6-o;w5=Jn*~Ru0?;ym_+#3lKpxRzQ3~}b^rhX delta 177 zcmeBVX<^Y@DD#?|je&uIn~{NsiHCz(M1#eKjnzq-J+_$R0;7V!2gYfPTy4ypJpIfL zyyqwCNoz2$F|#nTF)=Z*GBPl8vavHVFmSOjGcvI7aBwiN^05P%Ow7#8Y!fR|CVmhX z;YcgW&y7z?F6M$TDoav}Ckrx)PF7%K17eoRYK;5U_$?Ut7z7wZ6j|6=x!8avf`K5b QI#85R#Da+l$Y*2#054!0Pyhe` diff --git a/precompile/binaries/stdlib/ascii.mv b/precompile/binaries/stdlib/ascii.mv index 40493e1666791f514c6b51de32a5fd300a2a8156..bd763871a82bceef1a4cf038d5205b3ee5ca160b 100644 GIT binary patch delta 318 zcmYk0JxT;Y5QSe=S5NnJ^~}zX27=&%_>+#&f`NDhPhjF14A(@#R3e<=-0W delta 298 zcmYk0txf|`5QWdoo!R@l+ubdMkXE!LrBx)0+62)@z+iX*B#*!ofFK(L5*z{n29Lrb z2oFJm!*h#b#L3K=$@%8PzT56@`V|WRksvIUX;0+L>G|3|(i^!Sp4B(zp2Ca7^eUfR z-d=aR$0%R`3k95H@zw#sdQcgZKvhfxa4En@N}%2xHO>OKu>`EY5D+KEn8R}n4shW|LfpHdw> diff --git a/precompile/binaries/stdlib/bigdecimal.mv b/precompile/binaries/stdlib/bigdecimal.mv index 875416e71dc268580aa34420a3604b712e566f4e..f6f182b88bb77853640505664ab2d37e7f01e61d 100644 GIT binary patch delta 1257 zcmah{IcyVA5S{t^_x!u-{cFeTTqMMV1ag=J5{?`YNC+U&gpPtLbWqabhKdSl8(Jy~ z1WhCa5)CDCO%DYXR7mv9%;E?+MIz;CJp1OoIsTvKhobvx?5FVoq6ooLUf`t9wfj z$QVbAo?=WK-KByQ4PlMTFkw_yDf*nV1m-cz)mZ}T3C9hVz(&gPki)e@E@S9Z22IHM zrsSKPheF~);+E!2DmYB}F5<9!7!lHl#5JA+M#X+q?8n4@Ozg+Seq8KN&@K=rWbO%> zds5~;DHBi0tZn9Cn|KJPG~=|yr!}pxi!;1QnAIVX&LAP2)igcMA@5+`WrKwp<6_3x zv5e=CaVaOn<(x&&i}VGZQ)UGTVU_+7E_$qgN$@gT!j*ts)&%davoUN$Y_=(QmF?l0 z!^K;I*G2kcmlLgkGf#Fr^Q< zjR9`?!<%f!l%$sf;2E$jZjci6h^ho~qMY@gx-msb`NqH9%_4}<4(mkvtj3vV>HUA6 zG|mDE=sL~d#){~Q=+y>N#cLR(FZSvF@$_Yq@AUcM@qD6}Z-a46%3iS9aV_<3oYX+9 zEX0mc#<4LqI(U#ZvhXb*1k>_&3_!C3gI|0hd43#vcbNm)d_CBDiY38A5`F+yU-)sy1B?$H+rs^8nzkyF*pD$RVy%>4xu C98}Z* delta 1221 zcmaJ=%T7~K6y5ur`#!z5_gvcYXpssiD({E*02CF)#|#r=oEQ>_ApuMp(V3l_IJ)rz z`~{gfW$ehgiN>Kib>hIdb{hzhKnE+kyKAj|*4d{YJAYT2?`uDeM??{mr@TNXyV~8; z3;tjI%ME^n_4G}&5`Brh!uRN_iT5fBT!)IpKC$+RTw-ERF_EtwbX`<|=MaTHAPN8` z1Qa5GrvS0=5;mk#rJBSR5{^ZeLC0AERR?t35u++W$E5^SSsUWA3kZEEOo(1ZdKL7j zQ>sp>x*R|v&@H`g>Gep}BbCK;s>-0M3~JV7QcWiH%A{VIbP5TnPmb9q$Er)5(~_iL zLJZ(n9zbjwbO2|hI_uy%hHxiz&IyUnb4YZ-QN+WH3mb7E8!ZCHQoy(cOfXv#e3v4x?8q)j$%|DI%|iWue>^JZ8cbluU%R_B_j%Am?&S(7kK#T&<1aHoe?UFO1Ay1~&U}@y9{MT-bD#`!& z_nJ1spTKsv&au`WbC9u}Zv+;juy9I<;T9AG3WC5j-VuS4n-Rg-zQ8|O@c2M6zOM*R zRvZW>B$l?5m^LM4(B8|m)va(@cx{wZWHZ`v{lhDGudA8zjfsA z!jV`g^Pq(G(CU_sEMx!1VcONQU4TYqC+#mEi)xP8=TD+fRoT@FG;DA}ju=L9J5!P` PnldN(BQpzpYli;;z6f1K diff --git a/precompile/binaries/stdlib/biguint.mv b/precompile/binaries/stdlib/biguint.mv index 6bd9837bd5c530d9898cb7ee149019c04c430cc1..5df3f7a4f4da00360c794fda5cbabdf2bf49e774 100644 GIT binary patch delta 331 zcmW+xNm2qq5Ui?RW|(edcLQWm78f4j7yJ+&IQanYUi^S}Be?MaIC=C2kDw}}qq8zH zvpS>q={>K%2FFwoRf$PNyo($0ACkkTEQ??HcIAHea&;>p){Nr;Gb$r0=E z&MO8EiqS`t3U!%EE){DvQ>tK?D#KhD*0qsoeNozI=w)i+r4|<2h;|U_QdYO;Epr($ zt{`1IGj70d!TW5=KrA{0zXKm3Ge%|tJ_Uch*C5janrCR9qj`bmCEQ22PjH{%zQA3v K{`{xQTYm-wi4@@g delta 288 zcmWlSJyrri5QM8|dS;iMSwvA(TmgST5Ilo-@Ivbyj15dohQQF4}gcTEBRja z`>J2P=AYDlG=~%cB!P2Iee6VkC5MA7i#PY_%dapSbm67i#+Y~UPwV&OtS<%NA%J=X zf&?IHw7Z}wr389CJF8$wl_3{~+IG+{4M%()wERA1@r0cr^(iuNrj|yLJm-Dk4VO$~ zrYkWt&g?bQglS4UqrG9eWxC_aJxAsoS#acmBTI^vADMZiS<`H2oMm-ja7g^yP6OPi70E_)>4{`#_f0o zE_npRyC7bH7vP4M;Mi@|c1YkT_L0y3cl>qtw+sjof)d6U2mhhheGt4G*S^!Z{)>L2 z;xp8uFYtqJ{R}uEgrYSg6hF@G>2WLj)WOZ+ zCPpUz$CdE7;jqO1$ObTMH~Hce5v!)=(0%0%A{Fp(vZNT!>;{z zbfJw-kB*kAWY#U2rDB)gdwF)+d)qo6srYhI&UB`-*cBb?DlVrcE(h^NIW4jZu{f8Y z_quoX{QO1dxIoKUn(Hi{x9)7UnS+V1(kdS6nJUl=hh;e;ZUS7AIyq(xITNoTXvBoO zh(Iz4Enc^JNl#dVNrHn~q&;BPzJs>3fi6_C7H==S@dku*-V;QyZ3?^Sis5LJN#>)Y zTX!Pn2~>D@Hv$9dgAOK|uZRjv-{$*1u`dYM{07slY}nH|46B8Xz!qBk-WG(Xt89@g zz~-!XB$03npVgA#!AimhNy6se7^Et?2R@NFLtoaufc4uD}C>=D+r-4gHap` cZSnVRDE>9)S9TJ6wwC|2Z;Re+-@YUA2Q>P4n*aa+ literal 1075 zcmb7@TWi!n6oAj%a+yi(#cc~B5=q-#sg&YlL9mxat5Oh(_!iP;b~~_5>SlK9qYpm% zC&XXkPx0ATe}HEu)~*#q56R?Y&L!u3XY%RpHx&SYBtR+UEXc%z&G7g<`a;r$ujDh4 zA6S%pWZ(JR`-r0>2>~b&0M03Z;HU)zGlUTXh};t6LV^egBbXEwMj0dcU`!GkqQdb# zB*L#uo*0`?^{K7L@t(1-y%vmgHMD23vkiT0MP>vX)|PIPsu z^TrlqYpP*hSXSvvhDO<(nSsqmdSJz*!VPTTZ$dh!_4$Pv71q>Mey(j%7Pg3iJ=)rK z_ia-dYl@wnD^ot*t`P%XC_(@5=%D{5J3iCt#kiiDQkSVOIyFsNPi$Hb(vx~pl?{UN zAz}Yz|LE!Qv)*onp3`Dv%Cv3W`x@JVNiT~g9h#}GFbe17NV*v?u3!OnDMivCmL*B3 z^cx9NRI!XJF|TkKR~2@hyCQqEgCQ8PiQc4xK}6Av$71d`=b!1&fk~e&lOX9LVfWBY zbQKLShnJOviVeSs-=m7GQii7Rp*vY#5+d=tYdjP&2DQC+18@flrL|^!K`hN$TO%a& zNgLoiSx;h%8DF1c@xgTg2{xdJFGF<2N>71eOF-S}jPLvlmU%31pGFB!ghFb|RA8ta z%<$RZ8!g-GrWle#G#S4yVICygr}3`@ip|hrV$IQ67q^7|gX*D#Er*pq#@5Ix!p7nk wxj2}84Q|kWE?$V9uMTPZspFUkj)`Qv@MF3eQMwAWc;%t}50vYk{C^KW0DY}{#sB~S diff --git a/precompile/binaries/stdlib/block.mv b/precompile/binaries/stdlib/block.mv index 022294be891c993d476ab1fbbf05763369e020b3..9c84f44b4d2e942eb67f4a556b626c64a456cab2 100644 GIT binary patch delta 82 zcmdnMw3*3dq0DP;b_ND6c18v!W+ow45jJ)yFOC!iffmLho^OmY3=9m6V93P41f-ck d}*vf1~xWE5Hn+U zegz8)BZvj(2?QQu=W^$q{pqgjqq~*2P$TjUCI{D-wR1D$+}`nJ?G`t14`!|PVov?N z?S^OT;@p0q@$6hapN=-JR3wIpsZLo+zGfNB(bdzfK~@u*Vu+>iUZHkO5OwlORW>Vn z*R>SnUV-$s(5@)`PNK+SlF3p!83tkkBD^sMSF?{NqMX-LH@lQO@Mx+Om0Jt~uE|zAW9~9`4a>R^QB-f3U6a zY+Zb{-^ibxORv*W|D2o{CMr{=(U&ZPqbqBklVw6h3`xy}24VuJ!G_Cv!{Eep(JNXbTp z3uE(FEA@`evN%B0BLPQ%Qwhk|J?48+W;Zfgt0zypfrk=d^mxF~u+0mW*@v{R5)G(1 z!9FJp)ksoinb0H^ql+k-n;kC$D2+&Ep6%R2Q6)Bp&;;(#5ll&5Ks_Ih%siIb{=IynJF`E z2@5j`D-(l}yqFlH3)~t1f{7bLB1<^App)Y#t{%KeF#}bB%T+N5K&NykO9vjPz>ls4uN4ppd8M~ z-ae8Ax5J^lB%aZbc+}wmjy`%(krOgGC<*bWVThFAk>L?WRGb@;tm_U(M-DlHn0Kbc zf`hQANDCYrCx}aMm~nwPG69YcmLqp}yy)PGX$Mzk96Wi%!3>3oaB7auI501Jrrwxe z=t-VF=BQ_umK_$vC*U$NgmWi}N*1`%p7ymVWC~fEE9FaJX{b~xO_ZY2RB8G+pq5N& zDN&-*0VzUGcmOJZ^b`E^ZLX}=lu79zdRlU=>Fg8YfHKGe2#_RIfRe6!CVi%SaDv2; zcG=+RP|?xzB}1t!U3nzsGoN#=XrmkMG46A^B)&cU=?nH#B$IZ#)y_AXJGG5Qy;^Ip zZ{JUvTmD+Bxm9a4JL&iQi&52StT&UkuGQ=9q|>Rk?)VLY4~dp;it}UPX41aj=yV#b zX0@I)8%aHAwzjHwTHDQf`h$3Xb#r@lqtUrr-8q?SCl9uh&Q`Tgn%YU)jXRG>Y%^(+ z>{=t~RJS+R+qHU9-E3_%)*h+V7Ww#ayw7>RRo~wDA5;3b7%C0*S@z8JZKdzYV*0U^ zz3+m&&A(GR{YJh@e^fV7raA8_s`Nwe9D3=OUK#!LrC07!)Am-ea-)3lYWZ@ddZ}`w z`p%VGx30W<`OQmv?mmjvTH71-h~kY_lZevO+Sp0z(N-&}H6KNNPl&KtTf0|VPnLCG zZ=vG!-L90cR&G{rT)%eZ;s-0`=ye*7km6d?X}w$9NupZxFsa>3+EG6>(QazelE2d} zYKTE(44`ir4Vh+2_Kk#mE{m2MFg!-fq~|Vjb1}0>qq4g!(@?gSYo__Mn9-ow1#3kX zwTL+%&!7=SKNf~58v5QEa+=7T5lCbA)-I7u5s3wkNsvK2!nB+I(d8`0l8mr<5c8(z zO-T9;HzHPIHhmBbo)|Y0nU=B6G3&1|;}4=NDf(;mR#P2r`F?Oxa|(_IP^)P%r@59FY(`kGxPk?=fz`${+61vR@<4o2<_)L# z3Sg}UW0!y;V&QNW%Qh@B=Z)AaBzc!!({tpGbWDbaqihrffHLHoL6RF|W58e-1@hSe zM|BS8v*uE2KTE!W$Z0KZEoXxYMX0u{Z8udCbs;EbQ zojs2R<_@0OBv4FzZw+m)h8b;jW?DQ(Dx#$h&1$o(vqcJ`L!0g9v@y9jXY)Ew z!K|=pakqEUEDXd)CQq#uYG%Sglci7#EY2HypyXB_GgJerdKOI{6+LIY<@)*{eQyYe zPG(6F+5tsDE35VEAZPezD4(FwyL}`l`h&#x?NJulq*c<;14Su@ Wz>Sj@;iT&>BSL!Eh#7%i-+uvxiu#rS delta 1575 zcmY*ZO^j4U5U%R(>VB`g=goVwZ)SGcWp{>U8Fm+t0S`|JCQBp+MTm+doF?E7G6_2a zyE~|-IhdGe;tzQjPbPX$6HL5#@&HG##G@C_#G@u&tzMR0spNHaS65YkRsHq*eD3$@ z%iqrZy!b1sPehBp7f*!wlKxQ9lencnwTIFN_HVM^q%Hq2eQYXUOh+80 zKtmO3P=|xig2Qm?{^ixl5rY7DR0xTH;Q50@0LWAkg3L6JYRVXZJO-c!IH43xS172N z1X#g=lmKQk06jk?F;WZcZrZs7eW*^nUgUMO1Pwl*Gd&|D;PMOwwK8*H!WvdNJsdm8 zIF7@-kP2rOAlOf|*#1J!!^uV7%$9bdx<@*^8J}JT6!78-?^eLDzm(b<8(CLNYN^kf zwdPc_(QGznn{&;BM*%GfZHbUj+ZYge6$5FW%JLEZa}BK!+M$Rc#u$Xzo1%%4%V47< z8wqPgO|v!;2~I_%eFVWf5)p%tnl*1q6P9Q!m1pInR`lLzxP5&v+@k*G=4dk=4DVgP zJy`Eu-+X_((I0M?bLuM_4@cX*o1^h?z5Ged*0MYO&5gm<)?hU3t@nq6{(AYFI#bTm zm8Baa&hkNTW4ulMdmOI%8-wlYX8-QEzqQ@FGrnNSH@z8JWB0NFmTjm<-@_~5+P5G~R38S(b ztzlel@rdPpSuaO%Z&J5VfQlSo0IU?Zj|%0ao-lKFq~RqUWmj4zBjR9H zj02a14Gf<>onS#;Sg{PskY`7xz*EV5$L*lbDxOn1RcO_q866%^kgVEqVg;&Ln8I|i zh&)*;V%c%bs>Ugv+ph4sDtzR$i|R;iQ9ibF6I3YMuUN<`2HHxK3#Wz-1mUa+W>mOP zs+ariklYUP+A_x$)p72MKIbdSo4kuP^s%?jIP2oVJFWMN*L2cJq%Jj_s)6?wTzS={ z<=Ay50_5s1n25E*39k9}v-;IjAfcfFiGdZ#mB}u))pXUh@(2;Np{D$~_ z?g$5k!W^aGBOklS#u?gp8RQuU-WHBQIL7IY!-UR;!gm9~#-W$qbJc3!sJQBiPkhxT zwz8JSNF0ueAVqZh@$F}|Ctl|VfO&~ z5$SbX-K*`!Vf8b*YL*kL*r5~IyqE_8(}5tza<@m2_<431$S~YW75FW2SY0eImnHC3 Pt;$s9;b+O*=3n@KnoXiS diff --git a/precompile/binaries/stdlib/coin.mv b/precompile/binaries/stdlib/coin.mv index a955dacb50b1ff64c8d48e0e5350bc3781587892..5164c4371f57eed8e5ce12b3ec16939718d995c1 100644 GIT binary patch delta 1140 zcmah{O>a|I5S_W-zH|NJn-@qN+esXgIF6GSl0a(mfkGfb{h+N1ZBZ9hH(hnzO*a-& z|3G+YKAUTpLg#A@O7#-#IgL?wNV-W#iZ8!Eep~$O8B( z!i<CC))nm1w|4@&lJ+*&3_j7H*Jgx25{;B;d{9pNI_&-0h)n|<`arVo>_d^s@ z644<{YXzvLjY@%FO@z92fH>=9q8dz~XpD=SP~o5{D=E|R#GS1`DVVFW3@&7j12H$j z0kmUM9w99HNj@)z$yD2ce8@5#nWt!Z>JkUbml>fuom!S>Qv1rNeT2}fCuVgvWqV_* zeaN}3Kh{`laJO1(USdJH-kM`8#XJuI8w+htjL>Y(GGn)iUBmDi@}%;5ivzi{$RoNz zs{>fs?WDH7rF7H&a=P_krN?-4WtBw_`)kY}turrf7aNRsimQyr#U^J@iY>;w1uOUu zuPGFW9~Ehd_;GQaH9m2?1h{7zx8PGgB7XKk+KBwT!vTFUNPq7B9HV@2BVGRGUc#@E zosvWyx638*+!!w$VfjMrmb>y{=CmXJG3CgM(cv>?u_v*;h3r zj1$5L7(dt;!3y2=PRoj#8snTvsYBNd`wG2l4>y}g391+l2q&mo$0t1*MlK55d6Ke zv<^nkSAx{BNcOtPp1L?q9L=tILviDryQ}O#@n@WDlO#o&Ox#3K9tMRw<#Bj4+}+B6 zr$i6Y20>t9kf{wXg0dnW2A!JP$&I|M>sB(wro4#SV_UU}Eh2L^!@)#wnTtn3S1svy zo2;m?@%#=d*x%wYS|pQPFqyvPg7uc`O?j{CW1(|z&Fd9G+R=~Ir5|!aBz@xE@MKQt g%~^1c-|_e@caPt@mdb^-@KR8N0trgM*YFTt0rLr2761SM delta 1088 zcmb7DJB%Ym5Pe-;J>8yek3F{cY_C78*Sq$5XV-J)b{DfBbllz@;*S6Kq7xD#+L(An zLPCJhNaSP$2$0AS5h1#Sn2?YY0Vxuq#*0V@PV`8n>greZURC#e-v6t2_C^0U9|5Q; zbf|MzKm48ek=`(m^{3kY8U5_squNIFxOQ6qvi>W@pEMWYhvpx)`gJeVzW?m(gG*{@ zr5xIZ!R?5}B`fv1)F{V2D7f1-F4Z{R(i5BGh1cu_13_9 z{WazE{$L0-f64**#t2-RXtC~KZ+H(JC_o<$JoM3~f?E#8s2q<4e6lTdPbb1~wlf2s zyV%)O*JC9t8z`f&bY3;N^4Yn8)pwo zJUt1o1>dHQ=;wOtDnTb&2sq~d5U>zPf~T}g#i4&Mmlu#uEk+!fN+bhct#oHfGudp- z6QsM5`6s-^jp9eYeQ8>ipuOg4d79wg^T5G`$Q#c-O0!@So9?Ci!I{iLXiSiSEQ#i& z)M+V|pVXU?rVx-o?VwnUTSVUfn zMU|!W=1N&K3fgq89%5= z9Y{L^uY%Dzw^Ha RQISCatPB_$On4U$@Hf70Tqytm diff --git a/precompile/binaries/stdlib/collection.mv b/precompile/binaries/stdlib/collection.mv index 55ab3410a0a571d191febbbe61cf2b11fe362377..07ce7f53021c040efda656ea5ee2dc61c12fcbc9 100644 GIT binary patch delta 2151 zcmaJ?J#1V>5Z?c{Z)e}Ww|CFyzw`Ou=bzXnA&Fl?ED{I-LP$h@2tmRjKL(P*7LGws z9W4b#cnuN~5=azO6mAhhN`(*w4ILE?5=c}CD#YxIliVpNSM0u-ot^pS+nKo!+yBn2 ze%|~YB0@|;NrN>`@vC>3_>vd$7yhY;{)v8w^qq7}{hFT0zRG@+=5}Mv{@K_`lP_k5 z(r<3B-t17`;(}@_#*`wI7!m|BPBdVeu3-3H0z+pm4P6j+u%2;Hd>@P>JAMK z;rWr_u&%-gq4AR~v}H%-7(>+Z*!TqcluyMBH*=gx%BXy1I!OA&3$QRY_c^qJ~i2tbFI12xykZpx;`g4SAkMosEP?yhOsCpVgMQw zDU}vdQ^U&Z>_XJwhH+)fZ`sILFapW&HMCGxDqATm)ec>0 zWJ-sk_4l^7u3Xy|H#Tl;+w1GMwzoFlzr3-zvA)w6T@{@Sh^3Ae#4^L?xJZC4@Qmb4 zQF8a^5hK0>kN)43_L>SxnAB$65p+onMVBpHrSL%KWybP?S`M6{PK#ma(0QHlN-5KV zSuWG=z!8FQ5s-pcAVrO_7*W+m4DlwoS0C)6oE8I^36F>eE1a+rI7n}Sj*C8~u+6HU zPuf_kir*7mr=5n}8VjbEhS@-a6-HznffNw5N=!x!<0vN!X(JbTZ*`(T`x>Yo z;_8TBN=JbD-1o7@Lp*jKa4vd@?0?AifvM~@#pWc^1xmW;h=KS4MBI~Zdk{_A+lHxK z1_YT9o8@Q8LVdYS|{>lh^dnIAG94r(IsO3_maiepThj--*U|7 zRvLm8GPHYGe(etXYcB3dX{~IgtFK)$X-K5VtU~x|QA3KzkeCV?AhL7vqSFaf$TWkL zqP3T20{7j>Q0ziBjUX4Um7k;s{2G=}Hp;HwiKcNJtKK$dQl)!#dDa*cii} zmS>$x;wr3SkWjQvp98|abYa9(0K`5>Hpbhxg<;`m1= JNx4<;{|_EQsfhpp delta 2117 zcmb7ENpBoQ6t3-6SJ$iFW_rf<*q-s&9#3Yx1SfXf4zaQj!j=RjY(Xp`2__4YEya!m z2Q-|JI3Z~91GvD2TnHD$i4#Ix`4LFK0f`%8c|Dm#wm~A)p}P9LSKs&QZGX?hQWv4FFxsGgRWKN9LUk-_Kk1Lb|~eeap~q6z(JbSnNi`Vs68l~>&t)!(Dw_Dn7M z_QSOsJz1BE8#SQ`#WFgwCNtc?wD38D7SPUS&@s6W87VsvFy4(cQ?qn~&&8ba`GkHK z3V{8LbE6l_B=ruaq*|%~W6MK|u|rYJeN*P-nsWEwEl(sb-Xa3Q; zV&WJ~2&v$BbCTRR;S0{}Nda8Iqdt)2REs3$u^EDYd|!>RCyMRKxdvlT%>xss7xoLu z*qP#d_5c*;aA}zv@${h;`Vr?=CX3JcmBrOU_sqkD^DJ$IueCM-4`KylV-AZ1Xt3AgA(o+3pd_)VoU5S;&l+EY@#!P9A$o2Mxk?A{ zj57SrlKPGZZu8dm#mzS^-n_JNbv^$B8h1K6;x+gB`quW%&9^UZY;LT3>u+t}ymVz- zUEjFAedoM)S@jZRj)y#BPFT^A$_J+@@%@#EHi}spvs6e*sq`Min5RNK@W>lSICYA$HCY(em@^fyu*RU+H`rUzRju-wSZz&5A z)s?1P_E&;!k0s8@P&$PSRT7|Rs!^zG@19B67E$q@>Vo~x$2(kYgMJ!P9 z{>#7^a|2@i~Xm1*lwz;3D)h?cy*<{4k>UGjSKA zr8=-sU{G847sWkvg@L(eumr1x0rl5?158F;5+<%hu8p~}ExQyQRY>3fBlk)r^IR3F zED*4Q)sl2WwuD3TGK@2$uG*4g7-v3(n4v!pSW3pQj6q3d7T&}XCnbhq=G0b*L6`-} z6l@`iX$nC1M*dBB=3pJB_B!qFa(eKp9Zu(sXzl3BHX`mIi=8HJJ#R1~?ig*K`!$R> zDU%S1`&wuM>~mj3BU<$K+4cOZX!+m>)c10GySQo2>Ym(!0yVU8Z*j z#2upPbH9WECnbhHabF2_;P<(&6!n+KX9JWJPElf6%HeSSOT2GxmxOAWx}Hf1X7NR; zYUQMrU1}XGsY93Z6UpI)7Ieu>4>Hdv)2Je2Y0PDn0T|D!aDlEE^?d$W@<{JOfje8& z^x>m4V5k{s5>O}o%Yad{G$VC=P$kpOa|S&%d|%=O45NunHiUdpWW&xK%Lc~G1=eLF zsv8E!Gb^T?2Xnsj(CevHQq+RLg=xuiF-0prnZXg7y08XK48;Dzx3!g!@5;cShjwJ2 z1_aHS*rnuo8ETXt6ny6-!$R4W$mrwAV(>WSdSD?|DHV&N0BOrhIvYiZ6gkJytB8ko g(%)~X0sW4a`hWClKo1R~hkw%3n7T`!Un-CP4QT_Yv;Y7A diff --git a/precompile/binaries/stdlib/comparator.mv b/precompile/binaries/stdlib/comparator.mv index d3ef5487cdf3ddee6c478c62e5d060b3c2aef963..8ef60db20439ab5b124ecd7c3c4ca953ad780e1c 100644 GIT binary patch delta 253 zcmXAiK}thG5JbCss%QT6jGsg#Zd?dIxDe6&O>k)>#4BVWuDyle6+D4kHzMK@vt&TuKZxJdVp-8Y|3etBbWqV-*V_~02rL?Ctv z#O$j9E)-*9%I55L%#9!0V}82pX_cz<>dA1Mj%w_AZ<0kz z1BQ_gNlGkfj`LBPhd^^%@0ox_I#h-MeRd=dGrD)RS*|A zVkTAxCi1>mh>57F7K?puC;a@_(kisP3Uy(Si8(`(gbs%Vt~1r+Xqpu_EhV`Nk@; CXca;L diff --git a/precompile/binaries/stdlib/compare.mv b/precompile/binaries/stdlib/compare.mv index dab3964005ebcdb8c61d775bc3d1e7b71a913b92..1256b1901a11f1aeb54aa7a04f80e546ae741789 100644 GIT binary patch delta 272 zcmah@ISK+n5bR@iM!N@emjw+BJR?m81i?%LbMYmL;%31h_kXYKBwzxEwI5zg2pT)Tw-)W z-trBmZYBJ6(W`e!$>)U`y-3PGjs=9aSPKf9loW%61Y@2TqJWC1fj*6+_96PBYM!fX b5J#?+z&4Ua6eq5e?6<-v%1m|+|Ht4B-T)C0 delta 277 zcmah@J5B>p47A7Zv#~AM1tL;VgkM3qQj!LQ6bec%z#X^(XW$6wQl%m1$pvx=yxTy> zSh77Dd+eQjOTW1~S|Os!1i@+UX7%B|d7HN%ufFF4hr|&fMv}zzwb*_>E3H|1%?=k8 zMaQ002A>gk>0I&4yyWS`iClr`Z?v&`la@wo%+?@3 n+WXk&r>vGRes~tUe4T2nAh$-wx9Oyh_j23AVF2PH|35}QSy>Ul diff --git a/precompile/binaries/stdlib/copyable_any.mv b/precompile/binaries/stdlib/copyable_any.mv index 4912d5e7777e9de064af4231b489895bdf53be40..56ccac92fc07d58ebba619bf8d8c5edefb82fd56 100644 GIT binary patch delta 174 zcmeBWnZ%;EQ06r^I|Bn3HzNZN6AuToh(3!m8>^=@drA$*14adb2Bv9@T+^62dFC_Q z@!p-NC#}!Oz{bqN$j->b#Kg+Tz{t$W#tx(yxLBBh6blbKh+^gA;9y{6VrFJ$omiMF z!jV>#pBtZ)T+9VwRF5k(emAk8RZ!NkPI00n|< J>OdAF0{~Oh8Q}l` delta 189 zcmbQl(#xW^Q06r^8v_FaHzNZN6AuTohz5%d8>^Evdu$EIO-2QQpN!KOx%!zod1f#> z@ZOlHC#}K2#>~RV&cwvT%E-XX$;Qsez`(`A%*epP!@V*R3UV`ZJ-z`y_jK^}EBMhFwco_w6k Q0H%$Tcx{_Cx!*Ga0IJwH=>Px# delta 367 zcma)zIZFdk6ot=yTVCc(oJ=wr2nvCK3W5Yh5OsohfWAY{kkK8?o~gAKY{9cbmRQhnJo2MgcH{fCVAnJ0;Pi4*5w<7I_g5 zTA#-<>Mr)h;y3Y%bLF2f_d0psQUr!Ef-y{B3Nu(Z3k$VT#v#Uqgq)NdYFcqb@=-<% zvkn1su0@tSVBYtj7ZVB4QZfLA$#!75HLTbHt10`pmbO^$ve?L2Y-TMA-Gpedmy^a; zpS`#HEp~DiyMqK-AEKJ!q%_$mhczCFMEzN&JbhT+FC86Ms`8*(DU};<@<|Lxsg+fK m;yXQU{;K--|EtlzU3l^09bXywcM~zDEwM2^_9g}I(tn2H9d(aiZU$4K?RNq~k z2!FJ=KYe4(j}!gs_HS|f&W`UdR$jQUn=vL>##(Hgt!G=J8?U{*)^+-H~hS=G*f1m5%l<>Ts#K!T(=>~!L;i_Nq zh+iTeotXmFrMY>$A6w-azO0pJ^2(|)Og~=i{!_*KiDKK2`96EnbETgi5{%R{o+s0j zIEXz*y%1yJ^Hd1@aasT!Ke~ux*(YcX8h+ne48<>yT!%0DBCTJ-;7hb&BS=0;g-kD# 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 delta 6484 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 diff --git a/precompile/binaries/stdlib/dispatchable_fungible_asset.mv b/precompile/binaries/stdlib/dispatchable_fungible_asset.mv index d61093ddc76a5ccbbba5f8372334ab57c1c5b161..8ddf36a461fe1cce8f9769ad69c61f96acc540e8 100644 GIT binary patch delta 837 zcmZ`%%}x|S5bmn}ovxnQo!w=3VS!y>7X&1FATo(DF(G>J9SlLih%qbyJa6Ken3z52 z)td)Ta_|{^2jdG!j1SQ)aPoTRI&tG@o~tLc8*c;DE4H~)>S5S~B;3`2SI3#bcR z)gSQ#+OO)BaaVp&zn~xJf958^zVF1oLGHzpvQRNz2(4eWqSa=|*@ z$uiP|Z1})VHFLJmvIUp0T`%LYP9x&=Y_rLwxfTONuN`5@iiJ*$lf}jEEXV!s9NR%J zwON{^KCo%QEC^+lA}PT%0o`^ zbio3O4m+e`q$s2-vL=7_tP5BdmfcX(w`N)IV1}nF0&rfblC2Kt zv9u%zt6GpGkpy>=x;D@7%G+9N(kIuNMb~!NR!EI<|!NF;bR;$ zP-!O2B$D-Ly%}EOo@34*n9fwV0ZuExPN*$xcI4Fs%kSpR#SjlMOCO;>-FKGTiEEDInlS0e00jN!r8h! zZVYVLa$sG1vr#~uF_w{rpWW8kqbw?hfUN2eu;!=>ErR!@kJ6cFf+=0VXahz0);4BE zR=XHNScRw}v(k%ZmCe7#VPqV|)^TK0=PZKJF|%vQ3^6asaDFD!+vc84|3W%tYsEY) zP&TBp9dpj9BXMRYBx?~-F0^h)HIV|9j)AEji^_~Mh`M4$U7^n>dgDLz@(;Zl(UFJW k{lwi)pgM|LdIpflBpah>i)OT}*tS?N>j~5Td(pJ>ZS>JeO6O+rkn=}+_PKf3D6e%kT#=C_Lhm=zF`)qd9;9mL~TWnZw<{J>x2cjNt! zdBgg|5&%S?1kiE`lpGUO#gX`6QH$1UD9RZ6j>Fr#kgR)A&5Ue;t&-x$(OGxxJR4rz z^hbGBTs`!Qa+p_THZXZr-Brz^9A$&zvY%Dg_qTaDoG8`C@o586^tz!^?Wut&dBZwV zGF_;II!w+awB;z8T4L(9*|6xqDTghEk)Cy0xXrY{_E-mY$LR&O8`wEA4vc0>=){GO zeC%R6UINl3K=L&on|%ccTE;X^7O+ugHbO$y!3yBqkUWJLIcUNvnt$XlAnS6cjO>BI KkrL)S+#Q#3Kf*@(kh=_zZ%L zwNGGSVQC@gD_A&pVjzV-EX=a={WJf5m`~HcU;1(y0IUK+GJ$XN_Fg!CR^|ztwKx1m z`^w(G^9xoU4M``13IPH+1PYYaf`?Lp!2lqNP|Q#oot4Tvd8l{=w^xHUr+I#v*RtU_ z8DyuuBtO5tNQa~O<79Nw?~T(uJG<#+!%>k3phEdLI{aM zt#(07E0!I_)Zj%e3zVv>mg6E;shE}xa@X?IAf^pr1#0oy3{-^qgVqgBgwmE{+Hu7U zAM$SGLl@FMAO6dA4LWejVI2_xA&|A%OAw=*Q*+JH^j2&ObAVJdl7kvFkV|N_qz+~% O`PEXtl)}3$+WY~N4=!*3 diff --git a/precompile/binaries/stdlib/fixed_point32.mv b/precompile/binaries/stdlib/fixed_point32.mv index c197aa67e95eecb333ee15de05adc4c40dcd70bb..46998389bb49c97b0b7b58092f17a9a51761edb7 100644 GIT binary patch delta 668 zcmZuvyG}zf47D96y^Yfs1q$UMXbVUnR9dw&NGwcz3_nnQfCYrair@zr*pQg{7N#z& z#mOy2Rhui>xjA;uv7ILw`_c3Ew-f-pM<60L?#fa0o0F^wXA30Fxo=0nL31GLOo>ar5MqWY$>7Th+?)2Xn+inF_v{9F_Y00q)ap4 z?(b;3;h~1Ty>7rVRAJTQK37B!&Ped#-0X}_Jq&vn-Jt)&7-zictI)aC;u9e;&A^_Q zfQMOd;<%&WWV-&+54a^fSOIbtV*LO||2qK(qiN)RaCSrcpgo8|Mm-q;&1BuWim1w1 zg~ufvCBb^@0kn8Cza$+Gn}Iy_C&vqd8$tteG?N<#l{7uP^5rN9XsbxO z70CKxges}C>DD&S17$`S delta 732 zcmaJX6BrkJ!gOCuhxD)zP1Da8G(p|(`$XZ=)M1e%}1IY{G?0HSE}V&Z)9+l z$vd$Jz<>Y}LB&(aFVKt7MC?Z)Ljz!a&y@&+C=9)T4Il$E6EVwJ1cgM1J&n{jNPd0$ zOzqe)^NPE}{t0R`i5GMck0W190KUfrls@5E8vqvbZAk z8F&H?aN^7raqb&%fthifrU+px*1C&!6h5>+hqdnm0s!O;1IV{Uc}7OoF-9C)B}>WK?noI6l+p!*hx9AgWyLR#~LRZry4i-8^Wf>EzR22 zteJ|~QO;fAd_ak4O}Hn^SDGS{wPcCkTS`-Y7$cAbqEtSUO@R0f8uMv{mFf3AWau%& zKyy#?B3Ngu$8MIFw&(3hMifUNLj$-~{jv}DGf4=fDaMgA`!@CD%}}5*ORk|WqOIxB zL6#hy-V4})F7zGF7>Y-yhn!t~j9%>p56ndTH&Em}=eBd9pL?8hUJ=OALQLlAFEKCU zyHr-9n}P(v!G^UV%y9;V+IrIR`0rcZ^yDTOGHl)Ew0Ry z2Txf>xm2A<)!wMq_*cnir5$ofivLlt&&hGe!wDNA7mdfi7gsZx(gsiWSCXqI?RN(^ zw|>Gbwy5PcR$OPJG;Ta7ZGYiL(=j8s`0&w7Xo)P5@zIVM=rg;;anD(vXN)Ra9BGfo)Y4CF%-rS2Ji;m9@ z6G)-q1<7GdW1BfTK06{oeN-fg!Tf?+`8R$zat=Ik#c4E2f@t1U%!R{+lv?p51$Q*F zDc81mnu6!E;M&vO0y9AYZY3mk<_(XF@4~aWbcPZE@h358{TNTyoYwynZ@hIzq)DWy z>v!V9i%^a`kA!+R|3rMpv$wHaP3#~Nw26a%YK^^-N;5tvNyk>CpWe8|x63YB!c4(HM_aFk_KSNx&kcdpMf->*SHU^1x7Tk%lYQo3&Ze)oo2U{cBrwXGW5+-NT`7{vUicY3cv~ diff --git a/precompile/binaries/stdlib/from_bcs.mv b/precompile/binaries/stdlib/from_bcs.mv index 69c253e6a98c8c42ace6920a1644027eb52f45fd..2c030eb8767e73eac874b5f82d79acec2b120547 100644 GIT binary patch delta 277 zcmX|)F-`+P3`PI9J+r%>A;~6E1X7Sd6uANoMK}Tt1!azrB7z(t1)}5zP(jC4sNn## zctOh8@*Ds8_Ppe`ynSALmj-YrOw6>sv-NS>Ts80fVEZFylSh4EeX=i(ci8|m%rQVP z5)wfuEb8z`qzJMN57{+??&zYHAW?(FQIHq~XT&%z#3V@cLB8%jxhMsfS~+5$`fOdH zWXAsCEcf?vb9)|!G8n4le;ugmvP#ul-7f6Z#q~P8BKhEDQ5Tu Duk{pg delta 256 zcmYj}Jx)VG41{OA_P!VIlH?HuffPmjNnC-30y-orlw;%$NK_F;isS^8bfKc;D$pU( zQBz=2AUwrq&DisjH~H>y@>wzfCsb5Zd!w^`n_o0fd}aF~hr>m>XMNBw4!%v}vSDrj zf&?Ulgs^`TScq-J>@{IHdO!)F2Cx%AKY&31!vM4kKCj+5tp(?)vd_-CtgU&D{_UI< x%6cicJYB!b=-TDdYO3n$=|rb4u2;5w8rwk;{`=FveXpt=MQF$7QHNcO@B{5_754xD diff --git a/precompile/binaries/stdlib/function_info.mv b/precompile/binaries/stdlib/function_info.mv index 2313d43ef89e3d47b8d2776385928cd8b048710d..5111c7d15058d4b240de152280ec5973e9d5fc60 100644 GIT binary patch delta 188 zcmYL?u?+$-3`M`4#K|Rh$>nMaItof8CSV*SI$8!mNUXpJl&ru86j0Jou>rnour2?u zr*HY_&;D?keUb-aBnV3|dF?h!zq@m|nR)*(CysBI+OOM|r&s_E9ms>MUa4pY!@8Tv zM>~=y$wP!41~{4?BpdO?}wIxjsj6run#pG&>|ruR$v2IgNg=;h8~F}NM3_w`8%IZ zcXmg&zs$Z-0R)1wdXrbOS-S0={ngC7hdFV0OH3cxwJ)_LD42j8$U2|^@P>h=s$k2B z^-ZGS>^#sm3hIJIDMwi%P=y9In*8nXN z5K@G3!W*inqGpp7RVi4I1#J8a2vx9wU%)C=R8grE8#WZHaJpwkGsd_;i`#uppFZdG zcV44EUVeIc>7%~SwTF-jFv^nb8+7jr#{R)q_$T6T%==h>7|GuiO5)SPCph|L|4)0= zZ;$>0n?D`<=Yin&E2Ejuf4=l?4fAnI5k>{ZvBY@7ldzykhAlP46p=tmZAGR{fH0ml z%u38+9Xn+;1@=}8;Hf5 za-GatbvLYPe$$EF>b35??#|Jd8_O!Tch<~N_^z8{@V#wPgvrM7JY27#H{6{&&Utco z@dPmOo6JVR+ma^{_P)Agm41y`_|Ues=6&6HQh89w>R5GB%*>Py&Ckp)oLD$nompVvVpuve&oA)#;)UX+nHyDF zE!{XRZi&@}dLR9iQ!XT{e?jLM;ZoOU*-6GY$MuJ7y#6s;Ra|HfODUwR$Gm6W-zS0R zPC8bZHCV_z(U8mrQy~%TeDGZ=%ImjzSu@7~lLkNiF{kW6u)Xv4o%`FH8+(uLJlgVi zb{}ngW%u#UX8l+GnbF+#-p1YgyKmmxvgf-Gw>IurCL(C7En`GvFkA-U zK^&*1%=$u{B109857KUp4AWGTc*t-)#59kK#71Sct-_M3P1b*1ybbRDrQEwXr0G~- zm|~F+x{r*o0k_roNVjGgKSwmfB57S6uZUc0KT)aQ8R%P|%QhdZQf08hRn8)f$9bd^ zLo^|2WC#zZpl!*+bFG&vRF!O6p)u)9tHf|cH7~O<)kdt$dg}ig7_3G3(JJG6~JwlX#Y9iCAl00~NHjpQ~tsMPG}=6-6SI#D_`{ zE*V0&B&h+wQILcr!bzDW7I{z@+Z8aMdRB2W7ZFs#VQPJQAv|FxJVyW?HWyiE9fphr zfFX-AAT-+oQ6Gg`$s3Kb-hNh<4YsfKi7@Rq)ECN?+93qpa=r&ty0Ca?kmYT3Y(cVY zBSL8xWDbKuWIVRjs22YBrRcd!i*PBJm{Yjz731~K%BD8GpImX8g)UH1EEA_m;!>>J zrQ4WgLheDr<=Y9zTaU>Kp!nVQ`| zDVjzp`nCj@0Yd_nSM|xk|EBGwwl+JjB=MR`Aib-coUs+W+zwRW0u@BixLmU5!3}*D zY*483sx5P@4Tu9Ph+QqvA;utgs z&7qGLcqyQ1KS;1#$UtIkhWn$&+i~ z_mv-Ea2)y+IR1UC8F)Z6t3I+z19WgGGG9_v@{{JFbA7bsB8$h z$}&WRj1$Pc1<4t{gM_~{a9nf&L_ zX^vvs59_}f8SK*vrGr%3n$p-d&;3pe0)HPV)|O*?=9*x@LTFO~G>3GkU0r6amC->$ zlx5Z!V*KIg^uGa?_#+ko delta 3449 zcmb7HNpu`X8LqXvr>eTATeB#VMxz;RqtRkno6{c2i|jZ~h+|vwns`xcOAujO3YHU+ zJd!a^9`N9jq%UyEdz^W2@ts31aN*2>3pw#19Jz3UuUa#nG2jFJ^lG~6U+VwAe=9v% z``y~HUzWbn4k5&+B*$`Z@x3pF_*|ZsU(3G;_xI}Oq4($hit}jTD;j=P`dOd)!_t@3 zd~@jUef}TMPh|h~`LPe1a*A_8285&@opwFykr_epen2SZdBoG8&KjT4IU_)v&oZnF zAy~*_WZ##1?0P6?cV5ifcP0WThzmvPiNn2;kVaoWq06R7=!zL2;z)@TdDI?T7EPQ> zhC~@_#o9os>3U4}6Vfj@HjaBmLRNxn<2`x0hEap?3t3bho@C#Qn}u z(B2jRgKR^i`(68eH~p@O<4tVeI|04-t;ahrLD}wUyuI^^HSc?`GQ#T14t5{BhTXk0 z_ba>@4B$odc%dHy)AiTZ=zfgQ5>FFhYND!3OK2OIFFpX_%U6;2u$N97g_- zI@Z_6^y(nAenQ`{e4kS5rS~Ix9dP}a+VCX{yjq{F%r|BmjU$bt^@9x&tOS))4S7a3 z%4f>wW-r%yy>fZgx$0bNBp>mw8I#E!F`xWGAiz>4e-cxMYvcyoUlT`O^BqUKILY%I z{3Ul~-=f#OV=0!FGt}{l!b%&?DR(@A_YA?eLY5@Il~rZ6W{7k=^W<-mix)CGyALfq&g)B-@diCkxZ+;iRhiJ2lu!4_O^F-Ha53*wzoD5 z+j|?g@9o~XyJaPIA8c*h+T48bIl@FeIi;*21~uk$=Xj8)jPug@yPcHX#w zYrKF(1?N$VGA8nJ0Ib@hPPWZmtOdNq)3keIqADj^OksyfiMh&{n30PuQq&;@67mFT zW1lh6kgF}8-2N7caE9{?&uMw~zj<_Wd2lKD$KdUz4oFOi;}4LJRSrGI&CEo;Hdi|<&Xtg4_OI+tf> zQ2^&J25C;jJ))#pTy}}eqsSFe)Qrv>9&jU!)G#<&6UDS8JJtQL*zPUMC@w{eqnv2n zCBtG|&e(40P-m#kHD3cU$LD0+qI7kC4Y7Jg9FZq19Obr%?F&(Jy)O7^dB#!(+ms76 z-5MC0_J|q5F2aZPFDRTq6HA>CPo0oa1RrEz%fi)|xg8(++6q%21PxeAzMlw*1=(tWN)5RBR6*prseC5Lbjh#FD^`A>Oa4vB14O0NK8UyF zHdvY(71WKQ0*d$LLy#<`8%4+g#Si4iR`atcuGc01gvy^#OZrb3b)YrXO!FQ&BiSXJ z3VI=h8$`&Ev6F?;d40Q`&QT zci7##NA0Y;c2JSzac#24&M-`!?u*l}YopB@=`gr4qo_SC+Q59~NSB&WxH@=ks4$HH z(v*j~W4!3W@RE{tq%Bu$QxQXQRLf^anzSRWE~h)FASn1Z30>=jbaA TgX=>mbKMbm>VNX-#O%KTd1xhf diff --git a/precompile/binaries/stdlib/guid.mv b/precompile/binaries/stdlib/guid.mv index d061b091c6c7aa2af4c5ade11c97f1b963a711d7..1b532b8d58b48a10c07cdadee32877022c0ec319 100644 GIT binary patch delta 321 zcmZvXElvbM5QVE=O;2~adVaQ<1+yWb2#{S%2uKnff^Z1Vfn3MV0mvQ!i$fvNcpOK- zP#q>HN_^?$y?(E19X4ULU3{r0ijk>8)yr__?$7)aKOk)7pnsJYj^EW@+PF6~ACIfW z4J!#TC1GRZYGd%h*jfft=Zo5FGFHB*Gir=kif5-S9NOZU6NsPJm)P%WnkFMbNwI|T z4EAJ~#!nnx=SU|=9J$Ak5K;5=V^_JuT+Ny#Go0-J#7M`Mz*SJPn7{a=@m9{S{;$jQ aTUV|?Xi9?E{?jB@HvJT(pPd`u<>Cjaa~P%o delta 342 zcmaKnF;2uV5Jmrd+lk3Ii8o}S*@6xMV%rshf&y`fy$lkfqFd6?as))j9Vn>rN9v6rRhOz06E&S4bN!iDCszFxVwAK}-xKfS0Hwzz-9DY*t!e6KF|UP@ll( z@Q3j=d_`Swe{&i*z&V>;l>6CO#upQ-1RpV*&{ZsT_CCr4YCgDeOLZjEjJL+(Q>-TD#r&7JjR+vr5(NRfbHCmr@BX zIOkr#xGpYQXe~S~q|`#7x{t#xha`Bw0vEy+e(Cafk&9Gv&#ADaJnnuno$f)u(@hSJ z(}C&^2K_-T>s_WNStm&cM;E8vUS1idoackAcjWDrM`=~E^8{6r(o!Ej=iT#aw^x+R z`$g61zs=-hmLDhmvpnnfYFDAM0A1vVtFt$~*Poanpz9ap{crKfgZ}ARc9J@%$}Jd9n3wZ-4jY+vlZ|$!D6y=>k2) zaX4><5p>(Y(};E5a>E7u?FCxJu|03e5H%5Qmtj?dyR|@%aXgu~$|zbvwAHX&)w~gK z#1})W)KX|kO@~&fKp+(CY8FX)vp#HuF~G5itk9y(tklw}u2^$4VMNi3^u*9NH7-9# zub`Zvn{BYkh*__~jkn3hIhHhO*`#gAjEWRZ<6zxFRK_n~1{H2~Opi=Zx1Q0iilH%T z9V6T?dl@4ZF2={@Fs?#3VFXfilXToNtfVqdL5^;~P=R}HrVXb?+{Va7YPC$2Mv5X4 zbPGduE0v8?@J2p(t2|sE%?ide16NnmJKD5p(xPTsVjwqnT$?u7rZAXqDN^`MzEPVD z6v4uHa@@Lu@(lykQ6NHq-Fk2h3|+bpb8YaF)F!|jsa92lR)Ety0&NvxU`&+;I2_5r zaae!|fZ&gU)nbef6)od{ikt-R1r{t&Jt!16iDn!{km(%|1DTSlIW;-?L7YoCAWqN} jmK!7{Q8+?21jRM~CrLA!7bHbm)(z*OxWPmKXCT-g7X^`6 literal 1348 zcmaJ>%T5$Q6uot;svlJ~FcS#~qXHqK1eIxBs3bueUqc>!rJg*--a}!@;nb z_fNBT`Cgh04^EDH{h~2~92dj9e-P|cQ}x!!k5jOu)ti3%spuU~^!g=bF(_H*{(enA z0W->SkC9{Kw1Wk0G@?qBi$P~>yk?=&h}Oz+ zE7M?pg$DI&ouEm492B>pk6BW2(y`=~olG()WM;4i#J6GRtWY}XLc=i0aPo3Pv)Ul_ z`4aBPvL}!h{)du{&V#dqLNY^ju^4BNMDfXv2q4v@W;&QnLLS4LLNF(*OVf diff --git a/precompile/binaries/stdlib/initia_nft.mv b/precompile/binaries/stdlib/initia_nft.mv index 74e59982a4cf2a8a7b862c50935de8723be62bf9..b7c9afc7e8c4729fa4e706be9f9989c7eb376132 100644 GIT binary patch literal 3968 zcmb7H+j85u83sTAgb0Wtb+F|#eYWG+ahz<+O}B^GRyOV=_KxG7-8+qJQC{xIqKA@` z>_fEg&_`&m+UZ^U0)2&EcY52I-t`Aa*|IlrHynvL{2%`R`wt+&KTQ8i+6XxkqbjL> zVSV*aLjP#JWdF7PV%dMP|0=}4OM&-0@9&oLkIIVrPvvh;@z1j!LWm-c9HdYM)zBmg z&_jd;!j_E@B8(#zi#|7c(X*`iMb>&p)|=BDv-y;c`9uOIuayYNSX%`Tz2AKJcwJ(UT07^ zFx|t>K%8Esy=EG9_|fGcPI^2sjlB!g$5F=uu)Me$v<6A4QO@hE52DJoj=iMYjn4FH z=j^&$Ns}L1-N6sdk=1rSSJ88)-Kg1)`e$iuEE+3%?kbJPhjOq!iYblG1CDC){OI(1 zu+9_HxLMO|wcBab@AH0q-iuNvA2yQ?P2TnTcHD3FlZ(iX-Vf5&*?>i9nxw_J_qNrI z+s!`s8~K+}dJ*^g;1+P`#ZkM^O9stOa@A|oi?}!7Zw6`HJLi4Vl=PI2Z8Kv~XuKap zy*30&fQeqe6Q!kobjzJFU@`P)Bog*n8tHiR(*#((v-K)))*V5^&^M^4c@uGGH$LBw z&f<$!*Ex;P+gZ2%BV109X9D{;%M;b{7|+3-_$Pfu#K2v#iI%#qN>aTTb8SN##XeuXg)$7I=@!%GT`H=wJcs*Jl z%O6JEsiK*Wqadyyk>-^<@!_>5AJ?Uy2iUpU7e!MXP#{s-Yjr1noRYjg{b8LBl3a-m zQF*B+4sNWG~P(eaALUZ%<0xE-~FtfqrFGc?cyvJFY|wdKZ(gT||U!}9glC(n0ZHH?N%9Ch2l zX#@|2;Ox6r?;MonTJmkqat)5Le)P>@<9O-+*oMbdl)^#ET*b!T^Fw2I_v_=sS-liI z9~yz&CGWuIAPIDlAaduCfie2XBL^gi5Mtgh`kgH-O1SATsfWCXU0lK*93v=3YR$zV zT1Rxz!SLEgK2eq=(h4yRwB#XD)TJH@37wI&g0Nym7Fs?heCUX8ukv9qe6b40H$F_J zUs!d(3NBAMa9q%OB^*+GiIwg0kkYzD3SO0}P~;&~juf&Wosa_$I4>44B?#9+Luk_l zSYrX2x>kr3a~M#b0h;hu^vOJ(lxzceI4nrw`-BfGL(`$R=xBDs+=H}yW5f9r8`V#+ zQNwT!EXk1oNH}U`zWQTumV+ZKTK(41v6s@3(jQmKC84CR!Qmn}?iNX?q@_wyg+=8l zUlye+eOZzoxIdxFZrPty6^GH^3RRU=`Xx+Eg|4bePWPcd?azcIHKu!NT-M|moD>a% zGFElBBI}#jEr*^QC!w##*iKkhHMZf{s>+r#n})t+>;oo#a1YeF4PCqkN^e7#?t!wfa*M(8Jy?EQt*fD!N)%SZ8mWwo#>gt1 zlkwJ9@R`J2s9?!`IEDIa;kXix2$ni7 z*V5gCpy&ABIzqUq*MKzZp)evMfu#j8w%{va*S!B;gDs;PY@+ z`Rs`-d9tCy{pWQq7DUKi?E{t{ScU^ zfuukYHX5XpPD$q3;XG`vZ6e_VVPps0+H0`6MiT#6^Z02tAY;Y|3m3r1&L=SIma~!rW7}8%#7I^+Yx$>jq literal 3973 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 SS>DwAD_nMN0$#aWr?pS-9U%<> delta 544 zcmZvYxlRKy5QaUM*XtRQfR+f+aI8RxLqG%D0U_`T@HP=G6^ND>pr)jur9t9Vs419D zI3j^%+2i@`ncv?_dQCSAi&s!w<2$4eTJGKRQhwsTz40^6+}`d#T$C|m%qb8N#1wqC zJ3vkZiE=A>NL2Vb(f!nlu?$oszvF@ZDe|}jmoPf&z$_T%&`7M(I?w=3K=p1Ky#|h|1{y^1 zC$`q64UYBOgyF9Za2sTtIaBR~AoD9G=wQ& zD8G+)Bhu0Nm;sF$@P7>0n~w=ta@WpMtut&aN zF=AX!Lc!`pm&t0xnm4dSW+h;j6c^ zqv`7}&-jdvClQ6RiImJ9WTU0MJ~NLX>&ZOUWh6>mBuj@RMQ5uFT}VB}?e;1EPjy!W zGfK;x!zIqOp0n#216P`ZzE^pcNg5JDXmm6uQ+yVcASLQ(fV5o5V_VeozrlHTK!Vl9 qg*<(kHq}w83PgKEU5#5-R}w{CjgnLarUcy(C0ok1k{g7m7vKuytSg%U delta 597 zcmZuty=s(E5Ir+@=Kg=X-`)Hf6Equxi$wbbZ1V7w4Z(!#WINw@?h_{+M=gc{C=3BnXCm(iy6%U{idhQ>($Is*)iN2>rc*`GMywE-W zUHALn`i1hRQ0wRLgS+!AHX|tLFhV;&xqG$&_}xH2xD&ur(@Y@9m>sxRPf;hqfVJo- z()s|VZ0yaU+N=rK>IigeWW8-B=xt+TXKcN_aSz^a6X4!JIWP)~i1W3G$vTj)bgWjg zH4>DF9QjpE(X)>nz0>G@gnh_~uljeCt-GAj&t6|H7V||qoxgtmYX0W*#nSQp%VYjZ zX9pRLs>@W|5hQ9?%#SVo@S2;A=xBi51IW5=51=JjJp+q7v>O#F+_XxMBF(cMiQsn1 zP2KW;(Wf%ejejNkK`?S6A*5smTwDuP%t%`1V)m2={eY=>P1n+O#vKXPmRIuV$!KcX n%4!d>DY1N6yKAzAV+$u)R^hg8tRaW6HC&5!ODftLTPolWhR`do diff --git a/precompile/binaries/stdlib/math128.mv b/precompile/binaries/stdlib/math128.mv index d2f98227337fcff6343ce222b64fd3fbdfa64c6f..99ccb71bf2e14ae0397ec0151f5f424715d55a22 100644 GIT binary patch literal 1684 zcmbtU-EPxJ6h8B3yED@^S(XF>NN%W7i3?I^OF`VUMHCdNC8)bXf*Z>;Zfhxyv&K!i z?B4EMAn^uV^C-LkyaZ>QO!;xe4HIR?KEL1hok`x^{Gwa{=@Ia#=ds#9V%Ty2Cm)FS zk@~ey^gYr4@y{Lrc%Y$1F`6x71}Q(Z+*!Hvau?<9P~&$A+Q@=1Hc4C{bWz|AOJo5E zTQob=%g8?n##7D-XPjdaC5%%}De=I;lQBj-BJhcGH;syup!a~K(OWjj&RCj^-Dn!; z(Q)h@#>prgCR1@ZiqeTZ8f94?jHQ~#Ut|)PG)ac5A!%G;_xWX(lC$CLQFr6U6U1VZhV)xx$%AC=7yV|mO%KMfAa#x z`_&?U9%ktz8AU~sjl(o9qG41-3&47J*Uk4zGERyldic<~!s+@1Wt*+$ZvWYfoxT3! zaOdD@_+)P|I0*L!PkX`6>ntz)60m=E5|908?9ci8mcO68@h5pUO@{ICE}d7b?>_Fo z=>OdxJPRMa3}5XY42%Q&5hZbs9quX6R8gvkrozF|0bP@%H&4GfR=C%*D6O%~t6CYR z{~Wr?+i10*Y=P^QxD|F)TvtrOHO*8tp{0ogg-#GsG4p_!je0XSw|`>8jOT{od7IZ1 zrZy`OT1WyEZOk;l$jd@N5d|0`mbf9-lyHeYONiGJvuB&@immMASSi*NR77Yh(yACu zdnvFz^9-6g{(u!iuT$!v(OCbC>(Sgio|{*VTrTWw z-YusZ_!vFsVD&M<9o80i6qll*xdHRqqV^Wfvs-@jMK_8BS0lL*KAIJ8v@)AxEE}9 z@dnlv4YqzHps@gx3icJ*zozJZ>mFT16YXCz=oRi%aM9|#acTi+VDED7lD1GUs+h5u Pi}3pfyhB*j-c9%lhD@OJ delta 838 zcmZvay>1gh5Xa~9K6ciLogiaAWL@mYjtP=;5vB-84ibVl;7#Zv8JZNdM~#F;L5BcQ zQStx?UW1;RStmv|VNRNxo1OX3Z+Gu?>wRnS_VzE!0H8o9s3^GoM4wIa#b+!&QPuuQ z?=b%6S7oYz2yL<)csmC`e}IzX07haW$j<2*Nrq@`gb^CDNENx)+V+ps;!k9}>!yl>n*rvuz; z-q6UTXB?mxS$oZQ>faye&~@27m826KT5$5AY!2nLa_eGcyXkX9dZT&7Rq0)lhV~ki z-R6vYgHkP{ONj9mNC)aRU-+={M)gK63=KMdz()Qi$~>9ft-(eMfYS@>9D;o|njTpdiBtwHBM=s1ky1wP1NsUKQbfR~3%b5J)p?DmilLc6Uu4be` zBcJ^=4c`e|SJ$H$SW?rQbrtyXdm17AK}$=)ixfqt4f;1fkdx-C^cONSPj_QxkT5`J zrYTT;pbxcge6OyimUTNN1qTW1U@Pe)pTJgJ^9`=~I@iA^-@Dl2x{`xp(B>uY;z@I+ a{X<9eL^t}4{2y^vpH2h;r diff --git a/precompile/binaries/stdlib/math64.mv b/precompile/binaries/stdlib/math64.mv index c102411e45883d24a18578e3019b471aac33850f..ec22cfbf0a122c57ed88690b43dff0ec08994450 100644 GIT binary patch delta 664 zcmY+By>1gh5P;`z_s%#32!qU%eDWE&6V+((oWhBVK)sOZ_>8a q%}>K~4Jmdxs5p{n^ecu=@kQw`G<35GmELw&o7+rG;b3?tU+w_jhbE!` delta 702 zcmY*WJB|}U5UuZwr>oh;1mnRA(%4?vEJ9ij0%-$SG9W?X1_%*w408h{W=Y6a+6$17 za}**1GPnR$#vY(Xs;;hj^WN+3@71qrb9w8B6#y_oD5wxlkM!y7^38i3{lxbA2fD)i zg+Fc)kjY8_^baT!N0LYysUS}!dZR+G5*9$$Ji$Q>4!uXr$Ps{~j6_u72+FAB^Tlg? zUYd(&W$02w!9pj&vx}LOh4;4MxYgecJ8C~UmRWyJwMk=~pvkOF|BC9Db6q$!o40~J zOra(Bxsd;LIVMMcCWnRzCI#(Or~WG#)vkWC|4L2eL=wVH|Ba3|mD&JZ4YnOz8w~y? zhSOo=OirOr!6QS1F=XfWl_)TJuY&{w(>zmVBdIhG4C8XuwONvMusN1HLqExBcJGEu zSr{Z)J25Az{XP~Z9j>$JiQd%%WAfLB@>zm$u@j3UEq7u!5_jz+iyz!cP^Vp+c(->6 z!-so+Z?{h0#a(60koBLpo6F;*rcKwby|4EJw7=D;mvZJVv38dl=2XuNqd+~^Cpt5J P(6y%q^|+$`g?#!A@zy8^ diff --git a/precompile/binaries/stdlib/minitswap.mv b/precompile/binaries/stdlib/minitswap.mv index 8ec3b4d6301397384a1be9809bd478e8cdb303fe..d39d07c46d61908c349726174ed8efb6468b913a 100644 GIT binary patch delta 10612 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 G?*9P3ulU*k delta 10508 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 delta 1699 zcmb7EOK%)S5U#3z%xrhh?Dp*V6?-@K+UxcDfnSL;7y?NMC}1Ief@LL35`k>VS)VsI zP8_0@kT`PU$RYd%&N(1)jF33OfeYfof$FghYoUOtL(Oz|RoB;Fecit`K5y=QHS@F8 z0N@aE%CCugUyyuBP4x$TPtgnYqmI9Ev-*XbtNrRe)8_Z=ru(-3%p~769A`-|kirB^ z!8Ejo3Sy~BAiF+8 zkjwQPL9L7tK)DsJPK4C8kowvb0j^(>fE&{UYEx#QHY9=A;`{+@CsTmel4*b`-N0B~ z4<2>`6mg@;S%uU*@p>`~xSNDuU&5@HJ}dnj^NjAzN(Av+IU&K@Jce6~66ki!knaQ- z@8~7Yz1!s--(BXF_uL9p?#-+b0=&x`9n0YoeLb#q zOtDl^tYR6(lIKAR@%$(H5_eVa`1t6!dUAMh(tp%D>_5JL(C_2ixC;k1SkN1xc4j=Z0L%H+(7rCqO{;*?q1`XA+F>1rj3g)9uYJ8kl zd__ZiI@gxVYCQx+r(^J@le!SV#}3w(*VS$a2tohSVyd`&U691jf#=V@~t`9z7CFIW1f| zSme|W!R;FG&ssU!= zY2ZJY!*FVgZD~|BFd|RqgPbD@RZ>1CYgPJXOLKBsHFf1YWTiumvKNlQAd zXd1pu#s||TwC?Fy&9>xcBlHF@K(*l4b4Lk9qDT`y4-X5zd9)b_;GT5_ZH3w!jWb2M zS6?P4Ot?_&FgF8H6S);N$}>sZVT`E{A;LQf@F&QAe+>Wt diff --git a/precompile/binaries/stdlib/object.mv b/precompile/binaries/stdlib/object.mv index f9942a005ccf885cf272a37624af86d25ea04773..dcdaa21c7419b046f133fe10b2c66a2dfaaef022 100644 GIT binary patch delta 1507 zcmZuxyKkID5TDuCx8Lsidz{zzaEyI-wsZEKpO;`eU`U*VVBUdHKxIX6LY9&gv3WI^ z0?|-K-#-9|0u-Q0heSb-(xyRjL5T!4U1mQAe1@!a^Udu3W@mmgv-kD%-RZ5bCjPJy zfJqRltlH<>zcKL*ugahJpBQ~BKR5cvw3*#c?<({6*fslWmAU)XzwF4*?RIk57U}PI zwraR`=k1LH1jPU~VpU2&s3{;>r@IjvI>>QgbPT5yk}<(zrpbE3IzTox5&+F4$W}@_ z(9TKcGkFD2bVfb7$a(JpRnG^|LU4n{T98W(lF`A6pab0>7le(^0_6}t38w(fIv2P|L4RXalvTOb z57wKMHNm(tX(ff~SYraY;$7ZYUg0Pa(JG9ICUN0dJixc4baYVk*+nK~@jmMtsdOY6 zBYE!!_8prWdFS@v`u<>NZ}+`hgWGcO!Qj@u7~I_5Pp;pflXpMf8GN+6x4(Dq6L~0G zX#(ru=Of`tr59!B8Fl$+<*ZYDYUjJDfdDbE0V1|=4w#~@mx~}L;16umI}5pSEMXRN z>x5-i=puF9-eV5p+_6zkRjtPfT2|sA;BUCin@a}s8XBCBc#qV&vt# z&11-giheAlMM;X>Kqh@Cd&azl%=rpqmL7;a4p%HC3s5$o6qxe2))I&rOHbcZAg2iESIn|a%!O>+bb|_WRPuqij z0vp;f!wj}WtVyAnS+=a4DaTjA34?~W#iA9fNIf%RRZokq;nd!lm|6Y^DMuCkvm6z4 zxuZ{x<1guFGt1P9#CIcV1!So=tZY)3zUXNuqmIoMUt|*pmZ75mjH9b2JHZ@cvKH8i z|Gxlx@&%ls#}}PFAEr=jTBI@)waj|4ZbQIF%pfpZJHhPCPM{`M0x=p%6?}SDl|C|~ Ym#z45Zo_#F(`O;+VchWB{4no51V~$b^8f$< delta 1541 zcmZ`(&2L*p5TBXdeQ)3H`hD1ICviezJ89h{PNouq@k2=ii9{-6<82adPpJ! zrywD5M6G<`3W5XbfkU~`|A89^E*z1lkb36CtkZlI*u!|<&Tl?`Gqb)o{q6MHHxmzS z1OO>QjcQBc>h~o7qMG_b{DJYG@=K#1rH%Yfb}uqNSFhWzYUJ+JzH_CYTCMcgmdt*; zyEcO7?!MdGgNOh%)|3Jm2_Z*g7Gs)49SAjyM+h)M326;aSqC&#Vp}6+(aan`s{jx) zMHytf;t|xW_Ylo{Hg^~e3nMHR#~j3GC4gS4ON3+v6yP(QGTB>&aWFk0k>LC!L!X^u z&*vHv@Iol*`4)R!4B}GM0C*vq0a%Mp0bFjK23U{A0X8&?E72^#CUB`Q&LLNQb)H$l zOAz#HQQ+}%9ONs(im!&yuPsQ_EAaXv2Y(}oH>X&<)s=zi^(EHdrr<6jla({5RqGQd zA~7fGgTL{X5arQ+kiTcKbJW zwm!Js-&Xxk`nPvw|KqLQ`w!IbYC2Eh9QfH-Mk?W1?4N?#!|VAtM^A$Xc6PBaz#ysO z;~)b)kXEHp7+N^&XyH82Aajk;)Iwn#rDU%r>&v@}f9YN#Zy)mzTBnR#WI{M}`bG zWujT({VJ*a_{C diff --git a/precompile/binaries/stdlib/object_code_deployment.mv b/precompile/binaries/stdlib/object_code_deployment.mv index ce8f6fdc0c0cfcf7cb0fe8728ed1fadc70f14046..08fb72af6f702ae6c169886d90246f0b6f842079 100644 GIT binary patch delta 569 zcmXX@J#Q015S^L*y4zi!z2}d7+4;0$A%svU(1|L)AT`|yAt#?>)|hF0IWyoQSVSZI+vfYqrT%?G(YIQ zh;G!bey0yR-}Gm)f1_8eZs$MJs^*~xcv)j{&%5bhH1fkWHSl!oZYh8lEn&dRL}rvRPbia_aKbB& zP{DegXm6|u&PPe)!Ggmh48F-sDO1jbRtnzoX?qVSL5c8qGO%YPcAI|L{py^)sQAqf(og>fiyu+RkbwjRWT>GJLs*6F_s6@Z8=?e2P+daO2E8r` zQ9;ik*cESp1}1Mdt@j@@7ibhu>F8v+vn<~PG*bw zcru;OrjsyVycxe-yq!I*y_Jcy8OCPMja7sI3<$D2}CW(wmV+0r(u z(S<2>V;apS5d%{W$(1ho=yOb=4EHg`1Q8fnam?H~*Q&AXbE+Y+%1sa5nyDVyY zVWQYIWV~hS_T5G99SBI^(Hw%Q?SS-+0J%C~a|9LS+&xNw^dCrB00PvF>x}*ZX6QDs diff --git a/precompile/binaries/stdlib/option.mv b/precompile/binaries/stdlib/option.mv index a50f65dc5634907f8f96be6bbf4b978571a0eb30..2e75c7b85974627a5d1978458257dd311a0260a8 100644 GIT binary patch delta 713 zcmZ`#y-pl45S|&2*Sj9u_rn2A3Yv&il(3{r0w^i+1QE}2B5#1Mra(ez5J(X%ZC)W& zq%;VSc!|vTF1pi6SSyXk^X+^;f6{ZBUcPye01z_*6E`l-kT0D2S)pN@jaa zb7;;LQwD^38HCymy9yZ#TJlb|8RvU+_0g zQ-mJ56*z!KHP`czNarevYrCsdz&XO6B0GWoCGyi6(kn8K=E!WwM3Ih3NbqP4s_P+b zd^2JL^~6aC1(Oq}a1>h6lbnwl7;smhcN_%X!--{Gk0BRQqk>9S5VFj&-<~dAh>nH> z`!i9dJtdR{TULq6&?RHgK+LBmvJb~=nl(v?x?=8YzG7jGa4ABQ295 thd>SempahVc>Ie0Rr3>bKYQ|D-<95LJe5&HvSj9BhHNWv6 zT>g}joF|me>D<@11?^pd-t)wX_3Mb4*f~WCAu7gTbxMQcFhX%8?Q<6EOZAH7w3BMJ zaht%PDOo*_HeNNAMe7yV(Sf&m14X`uruFsFIyb7;uP$CVr2O$If5EP1TG;zA2(d2o zs*dQ6&@q|OejWh!zHgZhl^eqN5BF%#eFy~Q=JnOwf{ZN$!jFKRnJ)*n&-x3z2w1qd zuu|)SODc*J2MfsOMvGI?QKx?tpU|mg+z+zST2q>NiJq diff --git a/precompile/binaries/stdlib/oracle.mv b/precompile/binaries/stdlib/oracle.mv index 5f332c26f0ffc0ec628da090d170bc7ae43293c5..e2da6cda645ed1c5b05c8a22eb2b7d7b5056b052 100644 GIT binary patch delta 69 zcmeyv_@B{sq0DP;b_ND64n_tRCKeWE4k1=4VRl^$j#LGKRz??|lZ-+P3=GVSOh849 SAjrtV%mSoYS%K_{R)+w8!wA*@ delta 66 zcmey*_=nMIq0DP;HU~Kb!nci4dj$VgyGn zL^nT2@|E0H_tjgOeAI7r`m0=zpAI)m?}k5sxi{Lh&qp7mg%`EB`1;}cogIjVFcKij zDuxtPmI9l2EYbqv@yKvy!h!%-d;h-kI|SYI$E^t?Zv?K!0J;k0e=z zB|ZlZ9q4)q>s=k};cm}cJQ7tr;%FENZmdMCaPy$!)K-6$*W-tLn81zrs)NK+F*tb&)A$lEx|d-8f5T$MkP?F2*GzI-oDtYuk^ z5)LWIznFtsPN>O&s?cR zBMi7i{)H3*gi&1ljavHO_Pk=({zKicPr>Cs?b7Y#EZr~$d(&2vmitWXc3I=9mdK2_ z$wET3l@(HJxxb7oWm`sN6ayu;NU1GRkxHnoR%44GP{77U2Cin&psRwxIVgdZMv&C` zlfw8dn^HWqVs#?gB5J7BM0A8T#*~B+Zc27k*O(&vmYlNO16fz65OEEIM!P0YOB0sS zO;d{gS%~8e<^v%`BuO!U4f3gM*J?Db>YiW3EO9fGxRz@ozYOj&E)M1vnK1m>Ftx#d L;L)Y|-R%5ttnpmU delta 1014 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 F_&-(mdS(Cs literal 5184 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 HJAwTVYrmxF diff --git a/precompile/binaries/stdlib/query.mv b/precompile/binaries/stdlib/query.mv index 5daa782a026b45e3505789a3b05adf15e38880fd..380e0006eff240e892b7f33a469d0a57b8a7a43e 100644 GIT binary patch delta 136 zcmWlQJq`h36h-fQ_kBNRzF~|;AwsWKDl9~257SL-LZ`3bvzz{Q*Vd4yynF delta 136 zcmWlQu@wP96h+_r|IeRUJIh)Dfq*~@1bUGvU@MR*K_*awPzM@t4mC)`BIDfbo_o*X z6b_g9yLJGXaPh3&$~G3Z>)79!ZnE%~EZeW_22Y*kkM5g?<&sAj^Nzq6(P4b7SoYnO>l^<8f4)g#3 diff --git a/precompile/binaries/stdlib/royalty.mv b/precompile/binaries/stdlib/royalty.mv index 426a02309b1cd6959b8944ca8676af5720c1cfdf..ebc233755d5c5e94e036ef7b76617568c55985b1 100644 GIT binary patch delta 310 zcmXv|yG{c^4D@*S_V(<(+#?sDI3Qg_po)Z&p5Nd*Xc3fjC_exVeSQE@Qqdp^I;bi5 z0GjwfxR|kK#@77An__w2e`!u62_!62H^1?LB2UHu# delta 280 zcmXAjElvbM6oji@_w@Ai>-p(n77zohBmAgM$Sx<~5}-HklDAb6on+qnQnjy8_LPuEks5G7Ym3tH fKY*k;kzq2O+LJLVk2tItrD#?XMJ1E+eqs-QhX)%n diff --git a/precompile/binaries/stdlib/secp256k1.mv b/precompile/binaries/stdlib/secp256k1.mv index e94c009ea467a3b141469c032e1fbc3dce5414d9..d290f1381c69ba0193a2349daa043aeb381f8d2a 100644 GIT binary patch delta 616 zcmaJ-Jxc>Y5S^L*yq!&QcV1$|6tU62kWwrEgeVpf1WgfwAP6a~C6$GRl?ZC1VCCQN z9|($ty_Itbq8G$n_U+By+c)p+UAPY8%g#GHfWQcrY_8f{dgRT?p?kvzFSWN(FiO&bxEwmS?^+W9ci&lBq?d z+pII&gJ{@L52G=yIj<3648{L)z9Of3G?P<*$kl#gSMyLMPyIU&7L){eE|4W>U!7eo AVE_OC delta 623 zcma)2L26V%5PenE-M@cV|C#wee-a6SWDw&OW@!$PGl+{30?sUg1hNQo13_jbuCfw0 zfuKv*<_vlT7j8U&)jxi+$R#yuaFiRM z9gV@=e9{tlODv<$TfnrM0^8daQqq*7MoAnZLS!OhkQgrK_2+k+3)*SNXN%L5=jTsP zRxcN)t7k6`H=k(l!!>=UN4p~&aX2tzC1x)8Mv0Uu6tg8-dc3)o>6)3r5GzX_NVD7j zfmGjZS9D-k8lBn>dM<;CC|cXzZ~l}2@QKT^20r&3?Y-_E{$*AF@TokZzRr@Jl0uzI zdyB;Ft82p?+56d?vRBX9MEiSc#w?3}h{~J?Q5i&=`;Esu`ZXT)T-#n@*GfMDP*g03 diff --git a/precompile/binaries/stdlib/simple_map.mv b/precompile/binaries/stdlib/simple_map.mv index 7bbd4ca877fe9256f62ca1d7792f58822751de2d..69147e6587a65b5b2901af7a53819759621ffe6a 100644 GIT binary patch literal 2114 zcma)7OOM-B6uvLtx1D5?NjiN@Gef0HfJy~Y$DIZ0Kr#pc9f>ItU0LqLEf$F#*`8_V z7qDW>iUs@%{s3DREZ|SDVgnl%oNLE35d~2vx##-4&v)**`TqKEMj)hpj3kjmy8Q!Y zzu;Z(Py7=RKeDfh{F#rtzw>Xf{z`6|ZzZ$e$zO&4M~4T0bvQyuA&UkG3j%wDSVOTC z7~VL-gfWZ+qK;ziaf~oFLINQ^V+fd1H=qBQ|c)Z=1?F8HI9YZL} z1e44tpLK|kVkD&;^<{r#$p+~w!VM-0Da;juU$e)CUS(z@D^CVitOEH}% zizKV)m&v(z7SB%;bzBQSiI;2^S22H*7e)S@Jx#M2KU!94p7FdUA}ymbUnC-VQ5Eq? zJjD$vTe@7#62eww9K z8t?D7qUh}I6Bv!==}$kJK8_AP{&adUc^pkY|M2+H@erULLpI}h4h784$H|MdtjcDZ z5ejOPhewa1!=uk0P6n-ZT8^{48b8fXvl%!i1P(Zy6-=<#o;6GmOc_FEQzL^zWJy3m z%(^}aiG_2xhYWpB?O|eIhT3>NcH46{LyhjN8TDGDdtmgwy7!V1+$%^kgZ9y(YT>Kv z?%vW6=|EZHF01;nR8vh}W7|%mT@FO!9kvB|7#KzxQevocSU*EcJvix36f&Y#ahyxA z`kzcgZ~vuCEf~=OlovQmXh1{GItD>uaDm*%6IJ8UMh83s*l+GSyexhoS6Km?>-AtL zkU>?nic)sUFO>y8U> z8PU_8i}e-=wC4Z}0KnI4lw1*(YijsJ!Ri_IfiiTe_OTVAG$Moo-L2iC>vhmD{o1&YA+T=BP*~za8ZZ(a=-UXG<2Tk01AefUh?@dS0je&*!~zDbgMO{y tvFo#@A6EL<$cY5kVlrB5%gB0OVA$m>K?4*tKpSPWn=AMt0)LbQ{SBj^)_4E_ literal 2166 zcmbVN&2QX96rb<$e0X=0-6WefNjGh1B@SuSqQ=dsf!!bkG!iKiJy~wnEf%}>%68J` zAK-$xas?z#ocIU0^AB+5j5u@WjlJHkDv(f}?2KpL$M3!0n>YS(>n|e^LOw-VtK; zj6I2AB@iZzA&DqVSaX39v9N)CPl3E;eJ5_Wr4x5l2P3>9VMME|%t^YIz(m)&PJ6vq zsckqfsK2^KVA_;zr+2NMuJ<uX?OU=+x|#@si9!ksh2U4eV?!{7KLImrL(H;%gM~qrI&~^SH!C8S z+(?Bhv0RApTYDCS_G4l7c*as!5c`5KEhY86uB z7c4YrIxtng*CT|YT#g`IhQtsNY%L%$Kw?sxka^_IGKr#;3LF*!!&L(j< zjb?H*iKlT|(y!txei=uHmgRZ&l08q-u{fQTNtTMNnq*RhMK+Cj z3<`NCNx?iBhf)6G!g-YOt1^$yOI$}dG8 zPqWKdT*l{RmYd>bGz;r38jZ&e&M7m9w4iDHQk>^;RL0_BR>XNJK_!eP6Pd@CabAEI zmrP;Lv$Twov1FP_Po=r`eg@6*yq9m^x>AwfuJI|)GWD>c|!)aVbjuoi;z5N6C z>n3SZCehJRBML7Mp1EeJp6=-5(bMqwlg~!S!>8fsi;vEpoUH@31Bhl2O(22s)gXSA z6lGC&G_+}D^7!;gcyjvr<6*DSPKrUAm4oNmMLGuGguvN{^MVQHO`S18uKSSbYh-YM zENPJdGmrZQ8ma+Up?7=|5Q7eprIs0L*!%hr6AqTGO^x=KOcihatLcM<=?D4&Chm@q z%%CH5qUV{Tii4Hg8eopKySl2!5=%AF^cLH35={V_XuQid0mooy%78*UIfvD=ZVA6t zi})TF0VD2ma#+qSSiVin0YAdTf+<~tbX$%o+Ml4clNzY2djT|b&mXc$97n0^Tp@f9A!M&u977RW_ z#NE!41d^=4%O;2%@tW>0Gs-LnJbsJa1%U%Rgg|%MyA^9Law{}7VyIzchJUCH9qA)% zW#AbZDDp-?_YB4SK36VtOY7XNfKvh<0v#B#3ZZO0G#G^NdGTpreHQqJT5gyXEq<)5 z)Y5t_aoo4cct$~W`F4Gd>O*)(%LQk9?7-(E<%?0@YHQ%+8l!`jkqeqOtmOB>oWBQN z_{oBJBTo8F5l9cB+G%RD*#2L&!A))YZ&0yRn>BC`ABLs2BI~d<@B(Rx56uKk(}o&u zz~=7VrNedJ&5T4n0ci(+?)*G)KV#hXMClDv(gCq^`(w0^rTj^^PK>1j&awRS3t* zJyxoOK>h>p12{$EkMvln+_-S+rRt%F&U%fgDk>2l_VH++ndh0AeP6d=obAn-8re0Oam zdj`aU26@QW*2u0@aupi{$93>o9)*?P?G)@QkR_skq;EjF5bUXZPLeX$kAWdc}A zQ3B|vC;=>|C;_abXbO$aS#E6g+<89NyEtOlP~5t>+*%NZWj2$=1h92sVmJZpT#Qk1 zWvS0buO?ywxV9Xx?DbY07koa^#4lE2M_;a@Faq($I-)@PRcj+sZcZp0@Xe$Q?rufu ztw|NUy&Z!))4aQ%#XJ<5P~$haTh&fbh6N~$l9-LR#kVNOKZyr2Gsc~~758v_Q#RJ^ zU^qA)Jlq>TI#vfqM~6q@hl8W<2ag{Q4u^aD2gAX^ela{e-g|WTWVnCwME)g5y6dro z6_9Odv8eVb)cssG;+|LVg{6 zC5Y0Df3!C?J0B8F=(1qJWIHv`bL3-{1#iP*4V?3K{HOhHw9FkVuS#&*YM#I%sj^Ny zfu8J=UImwP)3dToc@>hWuqh}qM}%dAcPLg+dJ?Nx#aW^8y}`V{6Un;Ddx+E# zOu3bhajzuzOYA=L8M~KOvilytjOmQdk!15~Vt$@f6}$*n1*uQ9KDw49PO}C-d03%5 a#Tu^v-x}^u_wbQ5M47UAiZuX#z3>l>e{AXi delta 1465 zcmcIjO>bL86utM($D21Ze)e;m#<7#eanrhvlQs!$`bt|6O{Q0P_r^8Q2gNc3K?@tEP>GAkPj=va9^Uns87sKgvI36AM2czMjZ-=Ad>G1jS z=;ZX}kMd7BOWGM0&;_ZKb%2_9GQ!HKW6_g^TzKKwxjRX*dp8II2VQSWpw5FclN>kHWwzCpZS@*<r9JcB%q*)Nb6noe zY<{H*@r!pbFT0OtJ3oz4})sba}-AvWc*s%x>xKBVt-4}8Lj*W`xU zatUhn#$i%{#iQ~)+DA!%+uQ6VGs#}cs)g6=-)8b6GsR~5wV6I|rWa<#GTr2P$Gxh9 z;*v*h&D3en@u~M*nAXvN)lWyr8=mcIQ89PB1I#{C9B+{s9*5b#VXy diff --git a/precompile/binaries/stdlib/soul_bound_token.mv b/precompile/binaries/stdlib/soul_bound_token.mv index d0e96619d21d9f9c4fbb57a348681ce93f3001af..5fd762061918a2caa285e87a785deed786d2398a 100644 GIT binary patch literal 5018 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 diff --git a/precompile/binaries/stdlib/stableswap.mv b/precompile/binaries/stdlib/stableswap.mv index f48bbf64aa853b49c54d8c92bed1931f4d8c4976..1ffa7ed210e44c5652d2b4f0405db043c316b2f4 100644 GIT binary patch literal 11877 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 YD-1poj5 diff --git a/precompile/binaries/stdlib/staking.mv b/precompile/binaries/stdlib/staking.mv index 6aa9606341bd359b54416641d2590979c9e5bc58..bc2694580f9291442956f99de1b4fc28971a2187 100644 GIT binary patch delta 5431 zcmai2S#ur7b?$YR?w+}KF6I&>R)SbA0T2rbkQkBzL{Jb#0whIACMn9aAcCa0n2Q7g zlBGzxUL`wD9LwVsju!tF!vBPZs<8ybLhXhOB4LM`H zDTL&Vvjh0Y<)l=M^Qj;d676&pQ!5Tyhv!U^LS|M#A~;gbc*OObsNqAAbU^rM4o!@! zWA$B7)F(S3e0(>)v#0iSF|Lnx<2_vH5sXL86P@&Vu@4=7QuGU{ID3YA@w0tcB|7E5 zKj){P9)PSqL(}!Lf3DOp5}oxj=k^Uk)A^xcEIKzb2&=^Njs56c7^4n*;Q+L<7t;{W zmnQZxZZ1xVCKo)sM5eII2QlAX5r^>p$_(lKqSt%%Fn#^fkvTkHEe_(j>PKE9E5i%N zXw_@S>ACha;dgzJ-fujEukL0F1N7_9lEt@bc*;ws1Q~PtG%3Ba(jgG(+AS z=_EYw6Q26PAw1bbP72@P_^jWok@@QfX~LrmSWa(r)5zwFr0A_LT*UM3OPBHd%4K?g z=anx4*!O~~bRx<7;!BvqKX`T3pXyinYO{5|U*oH<(GdGOzl>95-{5Q1e3Q>m^DTaz znh!al!am~Hsrfd)OvZhOuTk@>{KgEL@AB8_+po1mex1+Eq4zyLLn6PyZ{L9p-{*JX zZajJK?w8RtlaKin8O46U*Jx_VFE63_Az!2BH~9=TpYZF{{1$(JeMi5|{ki-O-+T*z z{fK`BgX+ipS0EB5?4Dm=4`v85kX&6!RSmW?s&V1+y@G zq8JrtI+o2Dc}6Uo<>9k(d46<7ugsraI=66s;rWFX^Xk&8ohxTnmsUGpyLa~9x#jNj z%g--&7^7DfEj!BPXQfLF6LYmJA^Y!AJVGc|2mu|I*XbIto?b z{Gf@H!DJ<(PzsF1EXw0BVy&+dODX8M5sarvTZxQp7@6`fgG0L<33?g7Rv6J=UhWT< zYXRAbW!jU_D?bUJuB0NcTtKI`yRd5cSy)fGiDDQYwDwk-=x~TtX<~UQ8md%UQ*7jD ziY@O)y#usQGR!bD&PyP{l_Bk{;uK*mZJ<&Kc_Mhkp( z2JbD61Tciqhg8^Z9|N86n1>n|gi+8MgkZpzw z#_H=2Hy_+6yOMh&^3mp+yuW$RZLDuTxPEQp=IZ8=+3KAKZ(X~0=f>)_^;?_wZ$8*4 z|04MtK3G<2gK4t$?a>CLfA-__qonyx$i|oxDbKi*MpT)R1ydVFROpR6Wz?i$g^+KC zEY6hEsdho@HB3VnnIO|yP)HY>DASlCow3SU!<;kHC1}$uqCXpCv5m6WRb16&uI4&y zVw_ck|WxdcXownQssmh!St+s&;YeCVBfS1ZfL?E_| z&KeCediI%YzvDb*RhwHrtWMxKMjfY}V9a3)Xp-DXIEt_mr=kqsVgIZZWWQ0>G>2q` zfKrvTZdpgf@uTgi>TI>WA63n;jNi|`z--wv))@DDJ34@KuM9Ckr^CPrj44uHHAWP%%5|?H@PyNa z!4Uwg!nQ^V2bYgG^3jBuP!!yECg|u^Hvm9m4bLVihc`6o{Qn}bUpq72ms*q=g9iq<#k8yXQK~R#U zL$KL+P(7C-51m}fVWu=;^JHg^@7e?i*J*^Q!trryaD1?geA*$h5T-}6IYgJMh`M#; zYPP7_FhKR^f1qq#LwJdxvUOBFjiYcIb^Zkp@OkXk`v~_wf}YLE37baMfPe=)FhR8g zfM=>l51XKZcNZ2l&}?X?In(|X<**sNhIVgb%@%q5;Jl42K@sN@c) z6Ph-)sumZWKv@^Nf$Z_NgZIE(u)tG<>ho()qPklC-9V#x6?g@NR}8!Yf-7u;6aysK z0!J4{XEhqP=vGbX@nJ=m_n2og?ysTDj<~<^!-}-^xp4pN?c(-JHY(F7$2r}JCX%*7po7+A%{~FoD8VC84nPJE$l$EXsgZi~RtBZWC{KI>O9;{rEmv{0LXmh* zmk}J={WYVuK?0fpX*CtaKq`xU1M2FQdBq^|9EQ~uJcm$16vKJV6eGxcfs2ZU4PES- z2K;Dj3~cv1dt&Y}sxEblb4CHxOU4$XV3|Vxc2e3-O3X&pOSNW~ z=Jd3M`3^WH`e@MrP3{ZQZFk*)EN_(88;i|{C?B%i^SSWl7cZF1sn$WZmc_VJl%R_P zR8$AmElsx?gM6x0RX zctRXP^Cm)V(ktooN*pPf^jfH@62;^%)6!PbhjzVX2x}YC)iy-54cY5eY}aE=Z^?GQ zL0~;<8^Tn}5UNbQAwsnbnfjcT&ntNuN;djDBAEifKx7a=VwO)n%4ZX}tkun8n##n$ z(H8JSZXjrObZ=wy?Y%8zGS%&sA(d?_Yvrb0q^;Qf|0tWGXn1GJ^8gZ-%$oyh481T% zFGOKE45#jO0z&}}fqE+_{sPpS*$F2T>>#^i1r?e>*d|l&&~f9I7c_ zV)F^*HNhzV%WgF&*9jf6P?Y~Pmaa9Ywqn2+Bf{5`R1hN1f>Er_9)M-^<9s`$4uEs0 za>Nw`#FOPXP?SBm2Si!bS4D9eBMx=;&|d<^%f<1oD^#Js0TaH;2eD_boj*~s_5epD zayXk)Xf+*a_NLl{cV)2&3~P8KC1#GqEOoL@iMX@;`FOAC5|8L`zs{d7KO5iOY~Nfq z9Ii~*-3huhjWN1ZA=RW*rqKZ?eYyi|z(eeT} z|KjW{)~D^D&Vc7GIitsRP+()i)B3mhqF)wEfzTHqqi}Da>JQ5z(cJcERmyiK_Rb>< zhLr2$0W}9Ws7AzE;7bba;z(;b*bv${JB8&A?_93@mx}F%C2k}Df&{?JkQ5-01StU!MOhb$q)3qz?;;6G zARt+`q_t&RvZFY$J+>3Yj&0@c*C^*C56;PB@(=Rj9G|@9Bu{zJYfiqJ#TuYYYbDOk zPS;ddeO2{UHGY2ngA1oV+4es+WQ;k^wu|j|gOB*nl>BA*y81Z!wT(Wj{%b@3YG;4= z>z${vU+(%RXZ~~l|8e)5gP#s0KX~~7-jgh3ni=NVUUu;Nr(SFA6D;{k#2Mo)Ap*`g z8^^z3B9M&l2_q4(a8hf=r(%P9G3^p2_NNub4hYGj+*i3)heVBu!)cxIBMm5F^6@QO zSe8q;&z1Y<}01mnlVc7Z)w$MGXR(N|&NNo>QOB>AVBnuQDa zsTT2)TB6I-HLRZ6F~Ha}gF`GhG(5nyI6bnH1<#J+mVId)nxCsgj6J`52Qx435nSjq zwB1XS1I(TiQ!G4BJG?xN%Z2?|xOm_oYq3}INyaYG@5?YnKYJKkTseZvt4{!xt4DEn z?YLm>dSxe5H%`Emo3$DX&YTq3_105(@AeWjymktAcOV$t9oE3)9xzeMQ}E_Khl|Lf~dTA z=`w!sukp(i68?35`3k<-`~0kA>>KI;gd>YGt%x}NOlJD_5NQmT}J9lyYKHr1=*$?Ypu^J}>N3BNB`_@|uk{g}V`77PB2zb%;j34dpv>EvC>*iZR;Sp0Kj z8B;&wCp1fc!4C`U{|O%gQh&h#2K!6C1S|fE^Y^jkU-S2-82cMeq4`_h0tkP{;}1C8 z7D_5%b!Kf%ZO@v!h9<;JZPw1n88K^ThvxEKVxhKZ7vzFiw2MPe%f*>pOKNH6>G@N$ z&&-~lU9zvtzoM5GF3n%sp)cQi`rfI5) zui!!PRk>9Bn>?mElS=1w-4!#@;-G@JIts$y zFRP>CJ$@Z7tn3I_AI!ZbQ9}BK!_?To}DS>L77a4+g2=#oM}f z8;~SVjjjf|imM1+8yYxQ{G-0wTSBDadbv>vfr#K!J<#>27>|ds2L;Kg;#}PG1nxQ3 z$bA=Le?V4OrADq39`jHE)d+}CjIkVYU5nb!U`X`oKg92fOkH1DxxW%G-(S6SAFloILu~Ftk$~||15g9W<&ZJWw7KNy?^5cUMBPz7SoiuX7 zuv`Q$MlANqsZ_OZ!ZdV|(?b~2uEUfz;zfJT~Cmfq5xZ4_7 z7S&ygJ78`F%_$s2?<@B=bZCIs)5ABtx%Dl5jcxD|fT_adxF*;M)jiLETRVKvM( z5R-mbjF9R37X8kYWw!2MG6cks3%Ctrsu1Un-d!UI&nWo_QG|(QNu7K`?!Yf!+3<=Z zSA-E)EpN)*R+WzBCd$%v$D*uKw}KqQ!;Ca}f-|aQ4a;hp;{!j(Nw;6Wg0SDW2Wl-8zpa15&DJ^D8MwjB$w&$5Ba!X2u0& zbONLDI2b@Z7^7U68;9T^1Xis-%N-Ivo-i^`f>|3Q^QE&J3jLHrAyA^{shYE`n0MB~ z_Kwb?CPE}-2%)4Z@(QxtASlugB2A{nJ}xe3iCb|$aR6D$njg(a_ zBkuR3l%oyUDVdN%^qxZz+PF0!Pp86!$L3K~_|o-MIfis%1}y0J8d*W{!X_APxOJ$s z#3Yp93Cay+e83+>u_YDJun8rj%`+Q@=(go&3s~;*Hm51VJc_O?n5;py@`M*Pcm>I;f_K0Qr@qU^n*ftaTT21HG-2kbi;X{TIlWYu$!bd;^k>C_Vw>mf1>#Sk>Z5&cM6p z1|CXr+7uaX*_g~wL&(CXA~put%lkg?N(=dI1K(vO45lyUfRyN7|U5d5TcO|iLWW7Ve zSw}8{MBo7RYL4WtSYHiX6>Yyde}?vQMqRK91h2Wes0M5-iq8gbv~KkOUR-O082a4V zvI~qNH!(Iy>OKM+Q9~mDf~pmxgr~qLvMGW{y>sF`azIGnR;`PdN$3{B>_;~QTUcwi zKWYUfrqXh#ywG{m*TuyW-{oZ^JNTltJPO`apCUTZ5qJe5hVE`7p+SJ^2XOZ)8#+$}tFx=v?JHoteYwYdun+ilYaOM4V0-lkWl< zKN%w(LU{{6N5PEFk0yv9Vc{s7K_K;VB;zHSa45*oguwf@;;o-Q$kiQdxVo#3VDvBk zW%y|8^)BMavf)slL{{f4z%)VwWY%%(<_L{y`Bd7#aJqZ z5sZgP=S8X;VA0cV2YDiEs>|ZU^IL%yB#_?uZZU{=R%nVU6@|(^N|7T)6GlK&Lv=r- zX= zB}ma8fm1wNL-NBh-!aJH8GQm!OL1lA*49?F4eT6to)hDsr1QPv7NovB*v7?o%-AeO zW?)Q1i3I4ka-w7)jEi|g_Ne~fRf_f~rl~@{GF=i5`e;yZ(F~FjBizu?3 z9uh1+YBQuZUbgjNIiyC(lz6i#pnj}^3CIW!Biciz*uy3JY89q7{6Mgtov^0u!_AR= zGM}nS93mp1xLb;-_}^VyTVLbToua_#3-ZAPKr;+Y0AM4OhhN^91VX1knBkzrv{eqk zQ5u1~Ds_ySQN$fi_cW?`U(RzTHJ~%)@2e?oD`{ zdMu`Fn%B(oy0>-oY>|K*~GmB3sXR(SfTxN@gJkT ztse1!vfvy1SlQ$q&SnTV4wKZY9M068liDi4m?MUuGbH+78w_6dT1qxLH(Dh})Ho$u z2N=I=1bAS`YxEfei$By{*ZVRZpjb%ewe*+ta$kNBylW2)Nlx(hCYY^2`3r=r=cPu zGpj0}HX*Xw1a!g)5i(5iJjdS?@_jB=(+kw$(3(9>;<4CWHjeM``EpaJe#DtgVN*Q+6#q5e a+a2OhGl9k*i6jpgGAIb}Hzl0yIQxH;M9%sE diff --git a/precompile/binaries/stdlib/string.mv b/precompile/binaries/stdlib/string.mv index 302f00c0899259f182fe5ad148a0b52fb198ada7..f2f46ef11ff5213e817e488d31277b74e56cc512 100644 GIT binary patch delta 503 zcmYLDF-}7<47Hs&$&b_jf7)LpDh7m9DiCU6K* z3?^0vgaei8;l+N>@p~`fHJq$=KE(q>L2%@vX|L@q2ENA||AQYG-py|NWgao!u}cs9 zP0QK#6@oPg2y6)u*-;t1*8xJP6suU6C`nPGGAMObD2k0@YRhUb7rAcAho+wu+uQ-t zV7R5L)KPhstBXVDA{m1L0-!6`bS57l5~}bgazVuB0lwklG(ro>L`*iCb51N)cx;bF zsm#fVvqur8*{Kdw2kTPNC$Eg4SZzbk3uRIanZyeWNz|Lx>k~0pCC6<*0J5TssJL}iVy+vt h>{1Q6XDfj|%qgKD%}qk~NyQO`Kh+hrg!-?EKELnTAW#4R delta 445 zcmYL_KWsyV(*fJ}VY&;?hu`5A z^$*ALm%oJl>n9(80|E#WphWVpX$T;t43O1Rwc`CW16r3oC+z{s;GVX6rR&|;FDk%L zmq3rk#|X3}|M%ao+7y*SzyvWtbBk*UlkjbWclh>=!T=>G7S?bnMT||hT+O8_CCX?4 zbBPvtC2IqW&OE+Tg;zBmY8X#SDs0KnxHfHLRH#dZvZsr24_lExrIY3}tvEYNFWiLlyL@OnpDqcRAp#*JDMK+w zlr>Mpgt`;;8hP}Zbz)Yt)gco}dq7r+TAlx@8=*X`?92s-cv*n;ESwDpRDcZuRx>Xm TyCS&`e?1?2`g@F2dY$15s@fJa delta 269 zcmZ`!J4ysW5Pel$)6+H8POpyO3X8~sM;K636QfP{4xYqRJi%aSG||GcxOkOGJ%eEP z#$!^Cdi6fkuZ^)ERzKze7(rN;Zncq@o9dNzu0F~{Veq$$Z$EMKp;xw7jt4#RTfcrr zAvVrHCoO#>2*yTt`L3Kv^eph`xCJq1OUE_cUX2ssi6P!MH9h4Kiz01ASLC$@j|?^Xkt1i_FQh_!bl zztM(zE>1|lQ9niPb)45f#!t$_<%$m$D&S+5ZeT@r?b zMCgkaaWOP#%?*bsS3n5TwJM`gH=C;%_YhfDmO3nQwZF^)7Y124W$j#Et)7hY04`?D z3an=<0c_;wLvZ6#zFMU&XQA}XY|)J?`69TQhs?Ek?SwobMVe~mF&>)8BE=9Rit-2U za7L6{w3W)=oNtB*%V+epydx&f>GaVwIe7SF@4>;{+mDa-j_$pEA-Xj29=5SPzm)15 zOY5N!779tx{sK1QNqMSf*PR8l$YbH;a)L$Tq?d(v$`g}bLQEnbG0|+K zthS;^>E>`zEjX>3f6bJ-74t3quVejRj&XTk9}X$}2RDSQ>?q5xhaU$-+$0OX08u4C AeE+e^GV_mY_NqDC9Zrjz^)_7X5cNK`n3q&w1Sr);BT z5FwDlLhwJa6a-5fE5Xh;bBS2kxbS%U&HLUrZ@!tA*^hMRbnx9o0N@yC)C0c$3dJYf zkYDi()eHHHw@%_JJB^R^TirJ2TG$Wzr*QAnC^=7kWBPh$I)@k-=Y%u}q-;P2XjRKY zr{Vw;%?Yy1T7cZ~u-4X#+;PlPrL#U2D)OnTl0fREz7fi7!R_Z^mnE)|3s~m!4g%ny zL$bq^c0>@a;~Pf3k`f>H83Vqu)MX&nmai~?Yr`@KuV1Y^Z!)d|yk53FoR%vAZd9uw z->BC7^35`gc&l8Tb+cOJ+f@A`navRb z%QBgd%^Un&$i3O@>CEjvdA@tN|M0=Hquryu<}sgqJmUpU(*(9y;e8L^SSYEZM;9np zlLTsRpcdGClk>STzzkX;bA!x)VRg$2BQPfi3RB0H?kn#Y_@lSYED;e?K;RUTq9AfN z)3B*ot+>_9at($XthKa3l*EbGqKGNTWZ=TU7B*iZH`k8U&Wc3TiIvjc8(a(vRwh_m z(Q`=kD2b@9WdEktETH{1vv delta 60 zcmbQqJdN3Sq0DP;HU8v}>`RER;9)^w!K2I*h(3Uz zH}SkDz4#R36L=7;>PfPLU^6o{T~+;kUsd(b&Q0g)-N7%P0Js!^6n#Pc6$|qXKVtHS zt|@(OX2pB+L4}+2M+yK4$PW-`G0GKRu=Z6kXqfB&ap&8xNhGmN85mWKc6Kb3(0~*h~ z#4m$W)W59Wn3GNEXis;n`|E658w4#tbKTAPXOnsEL>a(XugR(%1osmLC)ICrSv|Am z)0~ykO07k9TtRsyr0bfJeL)#-IBc`J1oW`y_qbwk4vxpwXZvuWVyhnS&r+9T*^OxVD^YHwtYuG_T+PHf8cd$5>*V64^Hpyi-KZh>4WFY}`4Nb~`av(q)LeTRBG`zq`6i8I)v@ZaN z79`*yco3?HhMtBQCs_gr7o*wn`umxgudQ|K{O#d)XM_;36rkXZ)bC`5pXDbReS?<} zuk|Q6wuOhVI0ROF z`4-Hn0Jqq~8*TB%gjWLrn@ysc*n<;JI;bW%zkh7S35ix#T2<-<8-zeFA%I@7!oi9h zST)g?NC72xz{wga_Y#>C$CyENftT;~E!4zQjTjlV16%TB!||H2Cc4|8WR*B!A@>4v zEHH68w7)y6e&S;_#j<)}iZf4=VWF06Web5B5id7FspK`iM7lOESgKWcxih@bz{>l> z>Z7^ws9@baR8HQmL7>g8x=KEwB=Mw-z3!Sp)v;z)Z~-U?DLnUw#$8rNQ8}M6>KqTC z!&3ZTQmD~vgu1V)=h4~fWW$tNo&Yb8cFO6}BW8(5hq{9-)99UsJ-=o{JF9*~gS*$5 z_B!^RfkJ}lv5lO_7e;Mu?9G%0UQdwahi#y_ic^5, // unused + code: vector>, + upgrade_policy: u8 + ) { + publish_v2(owner, code, upgrade_policy); + } + + public entry fun publish_v2( + owner: &signer, code: vector>, upgrade_policy: u8 + ) { + request_publish(signer::address_of(owner), code, upgrade_policy) + } + + /// This function can be called by the chain to set the allowed publishers. + public entry fun set_allowed_publishers( + chain: &signer, allowed_publishers: vector
+ ) acquires ModuleStore { + assert!( + signer::address_of(chain) == @initia_std, + error::permission_denied(EINVALID_CHAIN_OPERATOR) + ); + assert_allowed(&allowed_publishers, @initia_std); + + let module_store = borrow_global_mut(@initia_std); + module_store.allowed_publishers = allowed_publishers; + } + + // public functions + + public fun freeze_code_object( + publisher: &signer, code_object: Object + ) acquires MetadataStore { + let code_object_addr = object::object_address(&code_object); + assert!( + exists(code_object_addr), + error::not_found(ECODE_OBJECT_DOES_NOT_EXIST) + ); + assert!( + object::is_owner(code_object, signer::address_of(publisher)), + error::permission_denied(ENOT_PACKAGE_OWNER) + ); + + let registry = borrow_global_mut(code_object_addr); + let iter = table::iter_mut( + &mut registry.metadata, + option::none(), + option::none(), + 1 + ); + loop { + if (!table::prepare_mut(iter)) { break }; + + let (_, metadata) = table::next_mut(iter); + metadata.upgrade_policy = UPGRADE_POLICY_IMMUTABLE; + } + } + // private functions fun increase_total_modules(num_modules: u64) acquires ModuleStore { @@ -129,7 +194,9 @@ module initia_std::code { ); } - public entry fun init_genesis( + /// This function is called by the genesis session to initialize the metadata store of + /// stdlib modules. + fun init_genesis( chain: &signer, module_ids: vector, allowed_publishers: vector
) acquires ModuleStore { assert!( @@ -159,60 +226,29 @@ module initia_std::code { increase_total_modules(vector::length(&module_ids)); } - public entry fun set_allowed_publishers( - chain: &signer, allowed_publishers: vector
- ) acquires ModuleStore { - assert!( - signer::address_of(chain) == @initia_std, - error::permission_denied(EINVALID_CHAIN_OPERATOR) - ); - assert_allowed(&allowed_publishers, @initia_std); - - let module_store = borrow_global_mut(@initia_std); - module_store.allowed_publishers = allowed_publishers; - } - - public fun freeze_code_object( - publisher: &signer, code_object: Object - ) acquires MetadataStore { - let code_object_addr = object::object_address(&code_object); - assert!( - exists(code_object_addr), - error::not_found(ECODE_OBJECT_DOES_NOT_EXIST) - ); - assert!( - object::is_owner(code_object, signer::address_of(publisher)), - error::permission_denied(ENOT_PACKAGE_OWNER) - ); - - let registry = borrow_global_mut(code_object_addr); - let iter = table::iter_mut( - &mut registry.metadata, - option::none(), - option::none(), - 1 + /// This function is called by the publish session to verify the publish request + /// and to update the upgrade policy of the modules. + fun verify_publish_request( + publisher: &signer, + module_ids: vector, + vec_dependency_addresses: vector>, + vec_dependency_ids: vector>, + upgrade_policy: u8 + ) acquires ModuleStore, MetadataStore { + verify_modules_upgrade_policy(publisher, module_ids, upgrade_policy); + verify_dependencies_upgrade_policy( + vec_dependency_addresses, + vec_dependency_ids, + upgrade_policy ); - loop { - if (!table::prepare_mut(iter)) { break }; - - let (_, metadata) = table::next_mut(iter); - metadata.upgrade_policy = UPGRADE_POLICY_IMMUTABLE; - } } - /// Publishes a package at the given signer's address. The caller must provide package metadata describing the - /// package. - public entry fun publish( - owner: &signer, - module_ids: vector, // 0x1::coin - code: vector>, + /// Verify the upgrade policy of the modules and record the upgrade policy in the metadata store + /// and update the total_modules count. + fun verify_modules_upgrade_policy( + publisher: &signer, module_ids: vector, // 0x1::coin upgrade_policy: u8 ) acquires ModuleStore, MetadataStore { - // Disallow incompatible upgrade mode. Governance can decide later if this should be reconsidered. - assert!( - vector::length(&code) == vector::length(&module_ids), - error::invalid_argument(EINVALID_ARGUMENTS) - ); assert_no_duplication(&module_ids); // Check whether arbitrary publish is allowed or not. @@ -223,11 +259,11 @@ module initia_std::code { error::invalid_argument(EUPGRADE_POLICY_UNSPECIFIED) ); - let addr = signer::address_of(owner); + let addr = signer::address_of(publisher); assert_allowed(&module_store.allowed_publishers, addr); if (!exists(addr)) { - move_to(owner, MetadataStore { metadata: table::new() }); + move_to(publisher, MetadataStore { metadata: table::new() }); }; // Check upgradability @@ -271,13 +307,51 @@ module initia_std::code { if (new_modules > 0) { increase_total_modules(new_modules) }; + } + + /// Verify the dependencies upgrade policy have higher policy than the module itself. + /// The function will be called at module publish verification step by session. + fun verify_dependencies_upgrade_policy( + vec_dependency_addresses: vector>, + vec_dependency_ids: vector>, + upgrade_policy: u8 + ) acquires MetadataStore { + while (vector::length(&vec_dependency_addresses) > 0) { + let dependency_addresses = vector::pop_back(&mut vec_dependency_addresses); + let dependency_ids = vector::pop_back(&mut vec_dependency_ids); + + while (vector::length(&dependency_addresses) > 0) { + let dependency_addr = vector::pop_back(&mut dependency_addresses); + let dependency_id = vector::pop_back(&mut dependency_ids); + + assert!( + exists(dependency_addr), + error::not_found(EPACKAGE_DEP_MISSING) + ); + let dependency_metadata_store = + borrow_global(dependency_addr); + + assert!( + table::contains( + &dependency_metadata_store.metadata, dependency_id + ), + error::not_found(EPACKAGE_DEP_MISSING) + ); + let dependency_upgrade_policy = + table::borrow( + &dependency_metadata_store.metadata, dependency_id + ).upgrade_policy; - // Request publish - request_publish(addr, module_ids, code) + assert!( + dependency_upgrade_policy >= upgrade_policy, + error::invalid_argument(EDEP_WEAKER_POLICY) + ); + }; + } } /// Native function to initiate module loading native fun request_publish( - owner: address, expected_modules: vector, code: vector> + owner: address, code: vector>, upgrade_policy: u8 ); } diff --git a/precompile/modules/initia_stdlib/sources/object_code_deployment.move b/precompile/modules/initia_stdlib/sources/object_code_deployment.move index bf11f594..9a6c79b1 100644 --- a/precompile/modules/initia_stdlib/sources/object_code_deployment.move +++ b/precompile/modules/initia_stdlib/sources/object_code_deployment.move @@ -73,18 +73,29 @@ module initia_std::object_code_deployment { object_address: address } + #[deprecated] /// Creates a new object with a unique address derived from the publisher address and the object seed. /// Publishes the code passed in the function to the newly created object. /// The caller must provide package metadata describing the package via `metadata_serialized` and /// the code to be published via `code`. This contains a vector of modules to be deployed on-chain. public entry fun publish( - publisher: &signer, module_ids: vector, code: vector> + publisher: &signer, _module_ids: vector, code: vector> + ) { + publish_v2(publisher, code); + } + + /// Creates a new object with a unique address derived from the publisher address and the object seed. + /// Publishes the code passed in the function to the newly created object. + /// The caller must provide package metadata describing the package via `metadata_serialized` and + /// the code to be published via `code`. This contains a vector of modules to be deployed on-chain. + public entry fun publish_v2( + publisher: &signer, code: vector> ) { let publisher_address = signer::address_of(publisher); let object_seed = object_seed(publisher_address); let constructor_ref = &object::create_named_object(publisher, object_seed); let code_signer = &object::generate_signer(constructor_ref); - code::publish(code_signer, module_ids, code, 1); + code::publish_v2(code_signer, code, 1); event::emit(Publish { object_address: signer::address_of(code_signer) }); diff --git a/precompile/modules/minitia_stdlib/sources/code.move b/precompile/modules/minitia_stdlib/sources/code.move index 351cd859..69d5630b 100644 --- a/precompile/modules/minitia_stdlib/sources/code.move +++ b/precompile/modules/minitia_stdlib/sources/code.move @@ -46,23 +46,26 @@ module minitia_std::code { /// Upgrade policy is not specified. const EUPGRADE_POLICY_UNSPECIFIED: u64 = 0x3; - /// The publish request args are invalid. - const EINVALID_ARGUMENTS: u64 = 0x4; - /// The operation is expected to be executed by chain signer. - const EINVALID_CHAIN_OPERATOR: u64 = 0x5; + const EINVALID_CHAIN_OPERATOR: u64 = 0x4; /// allowed_publishers argument is invalid. - const EINVALID_ALLOWED_PUBLISHERS: u64 = 0x6; + const EINVALID_ALLOWED_PUBLISHERS: u64 = 0x5; /// The module ID is duplicated. - const EDUPLICATE_MODULE_ID: u64 = 0x7; + const EDUPLICATE_MODULE_ID: u64 = 0x6; /// Not the owner of the package registry. - const ENOT_PACKAGE_OWNER: u64 = 0x8; + const ENOT_PACKAGE_OWNER: u64 = 0x7; /// `code_object` does not exist. - const ECODE_OBJECT_DOES_NOT_EXIST: u64 = 0x9; + const ECODE_OBJECT_DOES_NOT_EXIST: u64 = 0x8; + + /// Dependency could not be resolved to any published package. + const EPACKAGE_DEP_MISSING: u64 = 0x9; + + /// A dependency cannot have a weaker upgrade policy. + const EDEP_WEAKER_POLICY: u64 = 0xA; /// Whether a compatibility check should be performed for upgrades. The check only passes if /// a new module has (a) the same public functions (b) for existing resources, no layout change. @@ -98,6 +101,68 @@ module minitia_std::code { module_store.total_modules } + // entry public functions + + #[deprecated] + public entry fun publish( + owner: &signer, + _module_ids: vector, // unused + code: vector>, + upgrade_policy: u8 + ) { + publish_v2(owner, code, upgrade_policy); + } + + public entry fun publish_v2( + owner: &signer, code: vector>, upgrade_policy: u8 + ) { + request_publish(signer::address_of(owner), code, upgrade_policy) + } + + /// This function can be called by the chain to set the allowed publishers. + public entry fun set_allowed_publishers( + chain: &signer, allowed_publishers: vector
+ ) acquires ModuleStore { + assert!( + signer::address_of(chain) == @minitia_std, + error::permission_denied(EINVALID_CHAIN_OPERATOR) + ); + assert_allowed(&allowed_publishers, @minitia_std); + + let module_store = borrow_global_mut(@minitia_std); + module_store.allowed_publishers = allowed_publishers; + } + + // public functions + + public fun freeze_code_object( + publisher: &signer, code_object: Object + ) acquires MetadataStore { + let code_object_addr = object::object_address(&code_object); + assert!( + exists(code_object_addr), + error::not_found(ECODE_OBJECT_DOES_NOT_EXIST) + ); + assert!( + object::is_owner(code_object, signer::address_of(publisher)), + error::permission_denied(ENOT_PACKAGE_OWNER) + ); + + let registry = borrow_global_mut(code_object_addr); + let iter = table::iter_mut( + &mut registry.metadata, + option::none(), + option::none(), + 1 + ); + loop { + if (!table::prepare_mut(iter)) { break }; + + let (_, metadata) = table::next_mut(iter); + metadata.upgrade_policy = UPGRADE_POLICY_IMMUTABLE; + } + } + // private functions fun increase_total_modules(num_modules: u64) acquires ModuleStore { @@ -129,7 +194,9 @@ module minitia_std::code { ); } - public entry fun init_genesis( + /// This function is called by the genesis session to initialize the metadata store of + /// stdlib modules. + fun init_genesis( chain: &signer, module_ids: vector, allowed_publishers: vector
) acquires ModuleStore { assert!( @@ -159,60 +226,29 @@ module minitia_std::code { increase_total_modules(vector::length(&module_ids)); } - public entry fun set_allowed_publishers( - chain: &signer, allowed_publishers: vector
- ) acquires ModuleStore { - assert!( - signer::address_of(chain) == @minitia_std, - error::permission_denied(EINVALID_CHAIN_OPERATOR) - ); - assert_allowed(&allowed_publishers, @minitia_std); - - let module_store = borrow_global_mut(@minitia_std); - module_store.allowed_publishers = allowed_publishers; - } - - public fun freeze_code_object( - publisher: &signer, code_object: Object - ) acquires MetadataStore { - let code_object_addr = object::object_address(&code_object); - assert!( - exists(code_object_addr), - error::not_found(ECODE_OBJECT_DOES_NOT_EXIST) - ); - assert!( - object::is_owner(code_object, signer::address_of(publisher)), - error::permission_denied(ENOT_PACKAGE_OWNER) - ); - - let registry = borrow_global_mut(code_object_addr); - let iter = table::iter_mut( - &mut registry.metadata, - option::none(), - option::none(), - 1 + /// This function is called by the publish session to verify the publish request + /// and to update the upgrade policy of the modules. + fun verify_publish_request( + publisher: &signer, + module_ids: vector, + vec_dependency_addresses: vector>, + vec_dependency_ids: vector>, + upgrade_policy: u8 + ) acquires ModuleStore, MetadataStore { + verify_modules_upgrade_policy(publisher, module_ids, upgrade_policy); + verify_dependencies_upgrade_policy( + vec_dependency_addresses, + vec_dependency_ids, + upgrade_policy ); - loop { - if (!table::prepare_mut(iter)) { break }; - - let (_, metadata) = table::next_mut(iter); - metadata.upgrade_policy = UPGRADE_POLICY_IMMUTABLE; - } } - /// Publishes a package at the given signer's address. The caller must provide package metadata describing the - /// package. - public entry fun publish( - owner: &signer, - module_ids: vector, // 0x1::coin - code: vector>, + /// Verify the upgrade policy of the modules and record the upgrade policy in the metadata store + /// and update the total_modules count. + fun verify_modules_upgrade_policy( + publisher: &signer, module_ids: vector, // 0x1::coin upgrade_policy: u8 ) acquires ModuleStore, MetadataStore { - // Disallow incompatible upgrade mode. Governance can decide later if this should be reconsidered. - assert!( - vector::length(&code) == vector::length(&module_ids), - error::invalid_argument(EINVALID_ARGUMENTS) - ); assert_no_duplication(&module_ids); // Check whether arbitrary publish is allowed or not. @@ -223,11 +259,11 @@ module minitia_std::code { error::invalid_argument(EUPGRADE_POLICY_UNSPECIFIED) ); - let addr = signer::address_of(owner); + let addr = signer::address_of(publisher); assert_allowed(&module_store.allowed_publishers, addr); if (!exists(addr)) { - move_to(owner, MetadataStore { metadata: table::new() }); + move_to(publisher, MetadataStore { metadata: table::new() }); }; // Check upgradability @@ -271,13 +307,51 @@ module minitia_std::code { if (new_modules > 0) { increase_total_modules(new_modules) }; + } + + /// Verify the dependencies upgrade policy have higher policy than the module itself. + /// The function will be called at module publish verification step by session. + fun verify_dependencies_upgrade_policy( + vec_dependency_addresses: vector>, + vec_dependency_ids: vector>, + upgrade_policy: u8 + ) acquires MetadataStore { + while (vector::length(&vec_dependency_addresses) > 0) { + let dependency_addresses = vector::pop_back(&mut vec_dependency_addresses); + let dependency_ids = vector::pop_back(&mut vec_dependency_ids); + + while (vector::length(&dependency_addresses) > 0) { + let dependency_addr = vector::pop_back(&mut dependency_addresses); + let dependency_id = vector::pop_back(&mut dependency_ids); + + assert!( + exists(dependency_addr), + error::not_found(EPACKAGE_DEP_MISSING) + ); + let dependency_metadata_store = + borrow_global(dependency_addr); + + assert!( + table::contains( + &dependency_metadata_store.metadata, dependency_id + ), + error::not_found(EPACKAGE_DEP_MISSING) + ); + let dependency_upgrade_policy = + table::borrow( + &dependency_metadata_store.metadata, dependency_id + ).upgrade_policy; - // Request publish - request_publish(addr, module_ids, code) + assert!( + dependency_upgrade_policy >= upgrade_policy, + error::invalid_argument(EDEP_WEAKER_POLICY) + ); + }; + } } /// Native function to initiate module loading native fun request_publish( - owner: address, expected_modules: vector, code: vector> + owner: address, code: vector>, upgrade_policy: u8 ); } diff --git a/precompile/modules/minitia_stdlib/sources/object_code_deployment.move b/precompile/modules/minitia_stdlib/sources/object_code_deployment.move index d34b2e57..a457cd4f 100644 --- a/precompile/modules/minitia_stdlib/sources/object_code_deployment.move +++ b/precompile/modules/minitia_stdlib/sources/object_code_deployment.move @@ -73,18 +73,29 @@ module minitia_std::object_code_deployment { object_address: address } + #[deprecated] /// Creates a new object with a unique address derived from the publisher address and the object seed. /// Publishes the code passed in the function to the newly created object. /// The caller must provide package metadata describing the package via `metadata_serialized` and /// the code to be published via `code`. This contains a vector of modules to be deployed on-chain. public entry fun publish( - publisher: &signer, module_ids: vector, code: vector> + publisher: &signer, _module_ids: vector, code: vector> + ) { + publish_v2(publisher, code); + } + + /// Creates a new object with a unique address derived from the publisher address and the object seed. + /// Publishes the code passed in the function to the newly created object. + /// The caller must provide package metadata describing the package via `metadata_serialized` and + /// the code to be published via `code`. This contains a vector of modules to be deployed on-chain. + public entry fun publish_v2( + publisher: &signer, code: vector> ) { let publisher_address = signer::address_of(publisher); let object_seed = object_seed(publisher_address); let constructor_ref = &object::create_named_object(publisher, object_seed); let code_signer = &object::generate_signer(constructor_ref); - code::publish(code_signer, module_ids, code, 1); + code::publish_v2(code_signer, code, 1); event::emit(Publish { object_address: signer::address_of(code_signer) }); diff --git a/types/bcs.go b/types/bcs.go index adbecfdf..d54f681e 100644 --- a/types/bcs.go +++ b/types/bcs.go @@ -802,11 +802,15 @@ func BcsDeserializeIdentifier(input []byte) (Identifier, error) { type InitiaVMConfig struct { AllowUnstable bool + ScriptCacheCapacity uint64 + ModuleCacheCapacity uint64 } func (obj *InitiaVMConfig) Serialize(serializer serde.Serializer) error { if err := serializer.IncreaseContainerDepth(); err != nil { return err } if err := serializer.SerializeBool(obj.AllowUnstable); err != nil { return err } + if err := serializer.SerializeU64(obj.ScriptCacheCapacity); err != nil { return err } + if err := serializer.SerializeU64(obj.ModuleCacheCapacity); err != nil { return err } serializer.DecreaseContainerDepth() return nil } @@ -824,6 +828,8 @@ func DeserializeInitiaVMConfig(deserializer serde.Deserializer) (InitiaVMConfig, var obj InitiaVMConfig if err := deserializer.IncreaseContainerDepth(); err != nil { return obj, err } if val, err := deserializer.DeserializeBool(); err == nil { obj.AllowUnstable = val } else { return obj, err } + if val, err := deserializer.DeserializeU64(); err == nil { obj.ScriptCacheCapacity = val } else { return obj, err } + if val, err := deserializer.DeserializeU64(); err == nil { obj.ModuleCacheCapacity = val } else { return obj, err } deserializer.DecreaseContainerDepth() return obj, nil }