diff --git a/.github/crates-filters.yml b/.github/crates-filters.yml index 55ca74cc759..57a47dd7a25 100644 --- a/.github/crates-filters.yml +++ b/.github/crates-filters.yml @@ -180,9 +180,3 @@ iota-move-natives-latest: - "iota-execution/latest/iota-move-natives/**" iota-verifier-latest: - "iota-execution/latest/iota-verifier/**" -iota-adapter-v0: - - "iota-execution/v0/iota-adapter/**" -iota-move-natives-v0: - - "iota-execution/v0/iota-move-natives/**" -iota-verifier-v0: - - "iota-execution/v0/iota-verifier/**" diff --git a/Cargo.lock b/Cargo.lock index c00578c507c..e598cc0b441 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5794,33 +5794,6 @@ dependencies = [ "iota-transactional-test-runner", ] -[[package]] -name = "iota-adapter-v0" -version = "0.1.0" -dependencies = [ - "anyhow", - "bcs", - "iota-macros", - "iota-metrics", - "iota-move-natives-v0", - "iota-protocol-config", - "iota-types", - "iota-verifier-v0", - "leb128", - "move-binary-format", - "move-bytecode-utils", - "move-bytecode-verifier-meter", - "move-bytecode-verifier-v0", - "move-core-types", - "move-vm-config", - "move-vm-profiler", - "move-vm-runtime-v0", - "move-vm-types", - "parking_lot 0.12.3", - "serde", - "tracing", -] - [[package]] name = "iota-analytics-indexer" version = "0.7.0-alpha" @@ -6479,20 +6452,15 @@ version = "0.1.0" dependencies = [ "cargo_metadata 0.15.4", "iota-adapter-latest", - "iota-adapter-v0", "iota-move-natives-latest", - "iota-move-natives-v0", "iota-protocol-config", "iota-types", "iota-verifier-latest", - "iota-verifier-v0", "move-binary-format", "move-bytecode-verifier", "move-bytecode-verifier-meter", - "move-bytecode-verifier-v0", "move-vm-config", "move-vm-runtime", - "move-vm-runtime-v0", "petgraph 0.6.5", ] @@ -6615,14 +6583,14 @@ dependencies = [ "fastcrypto", "flate2", "fs_extra", - "iota-adapter-v0", + "iota-adapter-latest", "iota-config", "iota-execution", "iota-framework", "iota-framework-snapshot", "iota-genesis-common", "iota-move-build", - "iota-move-natives-v0", + "iota-move-natives-latest", "iota-protocol-config", "iota-sdk 1.1.5", "iota-simulator", @@ -6633,7 +6601,7 @@ dependencies = [ "move-compiler", "move-core-types", "move-package", - "move-vm-runtime-v0", + "move-vm-runtime", "packable", "prefix-hex", "prometheus", @@ -7210,28 +7178,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "iota-move-natives-v0" -version = "0.1.0" -dependencies = [ - "bcs", - "better_any", - "fastcrypto", - "fastcrypto-vdf", - "fastcrypto-zkp", - "indexmap 2.5.0", - "iota-protocol-config", - "iota-types", - "move-binary-format", - "move-core-types", - "move-stdlib-natives-v0", - "move-vm-runtime-v0", - "move-vm-types", - "rand 0.8.5", - "smallvec", - "tracing", -] - [[package]] name = "iota-network" version = "0.7.0-alpha" @@ -8305,21 +8251,6 @@ dependencies = [ "iota-transactional-test-runner", ] -[[package]] -name = "iota-verifier-v0" -version = "0.1.0" -dependencies = [ - "iota-protocol-config", - "iota-types", - "move-abstract-interpreter-v0", - "move-abstract-stack", - "move-binary-format", - "move-bytecode-utils", - "move-bytecode-verifier-meter", - "move-core-types", - "move-vm-config", -] - [[package]] name = "iota_stronghold" version = "2.1.0" @@ -9377,14 +9308,6 @@ dependencies = [ "move-bytecode-verifier-meter", ] -[[package]] -name = "move-abstract-interpreter-v0" -version = "0.1.0" -dependencies = [ - "move-binary-format", - "move-bytecode-verifier-meter", -] - [[package]] name = "move-abstract-stack" version = "0.0.1" @@ -9486,20 +9409,6 @@ dependencies = [ "move-vm-config", ] -[[package]] -name = "move-bytecode-verifier-v0" -version = "0.1.0" -dependencies = [ - "move-abstract-interpreter", - "move-abstract-stack", - "move-binary-format", - "move-borrow-graph", - "move-bytecode-verifier-meter", - "move-core-types", - "move-vm-config", - "petgraph 0.5.1", -] - [[package]] name = "move-bytecode-viewer" version = "0.1.0" @@ -9870,20 +9779,6 @@ dependencies = [ "smallvec", ] -[[package]] -name = "move-stdlib-natives-v0" -version = "0.1.1" -dependencies = [ - "hex", - "move-binary-format", - "move-core-types", - "move-vm-runtime-v0", - "move-vm-types", - "sha2 0.9.9", - "sha3 0.9.1", - "smallvec", -] - [[package]] name = "move-symbol-pool" version = "0.1.0" @@ -9988,24 +9883,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "move-vm-runtime-v0" -version = "0.1.0" -dependencies = [ - "better_any", - "fail", - "move-binary-format", - "move-bytecode-verifier-v0", - "move-core-types", - "move-vm-config", - "move-vm-profiler", - "move-vm-types", - "once_cell", - "parking_lot 0.11.2", - "smallvec", - "tracing", -] - [[package]] name = "move-vm-test-utils" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 0a0ff6300d9..f531d7a4b54 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,11 +53,6 @@ exclude = [ "external-crates/move/crates/move-vm-types", "external-crates/move/crates/serializer-tests", "external-crates/move/crates/test-generation", - "external-crates/move/move-execution/v0/crates/bytecode-verifier-tests", - "external-crates/move/move-execution/v0/crates/move-abstract-interpreter", - "external-crates/move/move-execution/v0/crates/move-bytecode-verifier", - "external-crates/move/move-execution/v0/crates/move-stdlib-natives", - "external-crates/move/move-execution/v0/crates/move-vm-runtime", "sdk/move-bytecode-template", ] members = [ @@ -162,9 +157,6 @@ members = [ "iota-execution/latest/iota-adapter", "iota-execution/latest/iota-move-natives", "iota-execution/latest/iota-verifier", - "iota-execution/v0/iota-adapter", - "iota-execution/v0/iota-move-natives", - "iota-execution/v0/iota-verifier", ] [workspace.package] diff --git a/crates/iota-genesis-builder/Cargo.toml b/crates/iota-genesis-builder/Cargo.toml index a70eac62788..81d3c77ffe1 100644 --- a/crates/iota-genesis-builder/Cargo.toml +++ b/crates/iota-genesis-builder/Cargo.toml @@ -40,14 +40,14 @@ tracing.workspace = true tracing-subscriber = "0.3" # internal dependencies -iota-adapter-v0 = { path = "../../iota-execution/v0/iota-adapter/" } +iota-adapter-latest = { path = "../../iota-execution/latest/iota-adapter/" } iota-config.workspace = true iota-execution.workspace = true iota-framework.workspace = true iota-framework-snapshot.workspace = true iota-genesis-common.workspace = true iota-move-build.workspace = true -iota-move-natives-v0 = { path = "../../iota-execution/v0/iota-move-natives" } +iota-move-natives-latest = { path = "../../iota-execution/latest/iota-move-natives" } iota-protocol-config.workspace = true iota-sdk = { version = "1.1", default-features = false, features = ["irc_27", "irc_30", "std"] } iota-types.workspace = true @@ -55,7 +55,7 @@ move-binary-format.workspace = true move-compiler.workspace = true move-core-types.workspace = true move-package.workspace = true -move-vm-runtime-v0 = { path = "../../external-crates/move/move-execution/v0/crates/move-vm-runtime" } +move-vm-runtime-latest = { path = "../../external-crates/move/crates/move-vm-runtime", package = "move-vm-runtime" } shared-crypto.workspace = true [target.'cfg(msim)'.dependencies] diff --git a/crates/iota-genesis-builder/src/stardust/migration/executor.rs b/crates/iota-genesis-builder/src/stardust/migration/executor.rs index 8c7b6fb96f6..816123dba63 100644 --- a/crates/iota-genesis-builder/src/stardust/migration/executor.rs +++ b/crates/iota-genesis-builder/src/stardust/migration/executor.rs @@ -7,13 +7,13 @@ use std::{ }; use anyhow::Result; -use iota_adapter_v0::{ +use iota_adapter_latest::{ adapter::new_move_vm, execution_mode, gas_charger::GasCharger, programmable_transactions, temporary_store::TemporaryStore, }; use iota_framework::BuiltInFramework; use iota_move_build::CompiledPackage; -use iota_move_natives_v0::all_natives; +use iota_move_natives_latest::all_natives; use iota_protocol_config::{Chain, ProtocolConfig, ProtocolVersion}; use iota_sdk::types::block::output::{ AliasOutput, BasicOutput, FoundryOutput, NativeTokens, NftOutput, OutputId, TokenId, @@ -44,7 +44,7 @@ use iota_types::{ }, }; use move_core_types::{ident_str, language_storage::StructTag}; -use move_vm_runtime_v0::move_vm::MoveVM; +use move_vm_runtime_latest::move_vm::MoveVM; use crate::{ process_package, diff --git a/dprint.json b/dprint.json index 17a5a9f5404..efec70de71e 100644 --- a/dprint.json +++ b/dprint.json @@ -20,7 +20,6 @@ "crates/iota-light-client/example_config/20873329.yaml", "**/pnpm-lock.yaml", "external-crates/move/crates/move-stdlib/**/docs/**/*.md", - "external-crates/move/move-execution/v0/crates/move-stdlib/**/docs/**/*.md", "nre/helm/graphql/templates/**/*.yaml", "nre/helm/indexer/templates/**/*.yaml" ], diff --git a/external-crates/move/Cargo.lock b/external-crates/move/Cargo.lock index 5446c9a86a3..812fbf776bc 100644 --- a/external-crates/move/Cargo.lock +++ b/external-crates/move/Cargo.lock @@ -361,20 +361,6 @@ dependencies = [ "petgraph", ] -[[package]] -name = "bytecode-verifier-tests-v0" -version = "0.1.0" -dependencies = [ - "hex", - "move-abstract-interpreter", - "move-binary-format", - "move-bytecode-verifier-meter", - "move-bytecode-verifier-v0", - "move-core-types", - "move-vm-config", - "petgraph", -] - [[package]] name = "bytecode-verifier-transactional-tests" version = "0.1.0" @@ -1468,15 +1454,6 @@ dependencies = [ "move-bytecode-verifier-meter", ] -[[package]] -name = "move-abstract-interpreter-v0" -version = "0.1.0" -dependencies = [ - "itertools", - "move-binary-format", - "move-bytecode-verifier-meter", -] - [[package]] name = "move-abstract-stack" version = "0.0.1" @@ -1581,20 +1558,6 @@ dependencies = [ "move-vm-config", ] -[[package]] -name = "move-bytecode-verifier-v0" -version = "0.1.0" -dependencies = [ - "move-abstract-interpreter", - "move-abstract-stack", - "move-binary-format", - "move-borrow-graph", - "move-bytecode-verifier-meter", - "move-core-types", - "move-vm-config", - "petgraph", -] - [[package]] name = "move-bytecode-viewer" version = "0.1.0" @@ -2011,20 +1974,6 @@ dependencies = [ "smallvec", ] -[[package]] -name = "move-stdlib-natives-v0" -version = "0.1.1" -dependencies = [ - "hex", - "move-binary-format", - "move-core-types", - "move-vm-runtime-v0", - "move-vm-types", - "sha2", - "sha3", - "smallvec", -] - [[package]] name = "move-symbol-pool" version = "0.1.0" @@ -2158,27 +2107,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "move-vm-runtime-v0" -version = "0.1.0" -dependencies = [ - "anyhow", - "better_any", - "fail", - "hex", - "move-binary-format", - "move-bytecode-verifier-v0", - "move-core-types", - "move-vm-config", - "move-vm-profiler", - "move-vm-types", - "once_cell", - "parking_lot 0.11.2", - "proptest", - "smallvec", - "tracing", -] - [[package]] name = "move-vm-test-utils" version = "0.1.0" diff --git a/external-crates/move/Cargo.toml b/external-crates/move/Cargo.toml index 2e927598fc5..553f221bceb 100644 --- a/external-crates/move/Cargo.toml +++ b/external-crates/move/Cargo.toml @@ -3,11 +3,6 @@ resolver = "2" members = [ "crates/*", - "move-execution/v0/crates/bytecode-verifier-tests", - "move-execution/v0/crates/move-abstract-interpreter", - "move-execution/v0/crates/move-bytecode-verifier", - "move-execution/v0/crates/move-stdlib-natives", - "move-execution/v0/crates/move-vm-runtime", # "move-execution/$CUT/crates/bytecode-verifier-tests", # "move-execution/$CUT/crates/move-abstract-interpreter", # "move-execution/$CUT/crates/move-bytecode-verifier", diff --git a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/Cargo.toml b/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/Cargo.toml deleted file mode 100644 index e6484d36ef7..00000000000 --- a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "bytecode-verifier-tests-v0" -version = "0.1.0" -authors = ["IOTA Foundation "] -edition = "2021" -license = "Apache-2.0" -publish = false -description = "Move bytecode verifier tests" - -[dev-dependencies] -hex.workspace = true -petgraph.workspace = true - -move-abstract-interpreter.workspace = true -move-binary-format = { workspace = true, features = ["fuzzing"] } -# referred to via path for execution versioning -move-bytecode-verifier = { path = "../move-bytecode-verifier", package = "move-bytecode-verifier-v0" } -move-bytecode-verifier-meter.workspace = true -move-core-types.workspace = true -move-vm-config.workspace = true - -[features] -fuzzing = ["move-binary-format/fuzzing"] diff --git a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/METER_TESTING.md b/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/METER_TESTING.md deleted file mode 100644 index 2f1865f6ed6..00000000000 --- a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/METER_TESTING.md +++ /dev/null @@ -1,5 +0,0 @@ -This testsuite can be run in a specific way to print the time until a 'complex' program is detected or accepted. Call as in: - -``` -cargo test --release -- --nocapture 1>/dev/null -``` diff --git a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/lib.rs b/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/lib.rs deleted file mode 100644 index 0dc645aec48..00000000000 --- a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/lib.rs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -#![forbid(unsafe_code)] - -#[cfg(test)] -pub mod support; - -#[cfg(test)] -pub mod unit_tests; diff --git a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/support/mod.rs b/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/support/mod.rs deleted file mode 100644 index 266dddf48a2..00000000000 --- a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/support/mod.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use move_binary_format::{ - file_format::{ - empty_module, Bytecode, CodeUnit, FunctionDefinition, FunctionHandle, IdentifierIndex, - ModuleHandleIndex, SignatureIndex, - }, - CompiledModule, -}; - -/// Create a dummy module to wrap the bytecode program in local@code -pub fn dummy_procedure_module(code: Vec) -> CompiledModule { - let mut module = empty_module(); - let code_unit = CodeUnit { - code, - ..Default::default() - }; - let fun_def = FunctionDefinition { - code: Some(code_unit), - ..Default::default() - }; - - let fun_handle = FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(0), - parameters: SignatureIndex(0), - return_: SignatureIndex(0), - type_parameters: vec![], - }; - - module.function_handles.push(fun_handle); - module.function_defs.push(fun_def); - module -} diff --git a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/binary_samples.rs b/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/binary_samples.rs deleted file mode 100644 index 624004452a2..00000000000 --- a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/binary_samples.rs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -//! Tests in here are based on binary representation of modules taken from -//! production. Those tests may fail over time if the representation becomes out -//! of date, then they can be removed. Right now the serve to calibrate the -//! metering working as expected. Those tests represent cases which we want to -//! continue to succeed. - -use move_binary_format::{errors::VMResult, CompiledModule}; -use move_bytecode_verifier::verifier; -use move_bytecode_verifier_meter::bound::BoundMeter; - -use crate::unit_tests::production_config; - -#[allow(unused)] -fn run_binary_test(name: &str, bytes: &str) -> VMResult<()> { - let bytes = hex::decode(bytes).expect("invalid hex string"); - let m = CompiledModule::deserialize_with_defaults(&bytes).expect("invalid module"); - let (verifier_config, meter_config) = production_config(); - let mut meter = BoundMeter::new(meter_config); - verifier::verify_module_with_config_for_test(name, &verifier_config, &m, &mut meter) -} - -#[test] -fn sample_price_oracle() { - let code = "a11ceb0b050000000c01001602162003368a0104c0011405d401a80607fc07f90308f50b6006d50c9b3210f03e770ae73f170cfe3f951e0d935e060000010101020103010401050006020702080209020a000b0800000c0800080d070004170402030100010318070009190700071c0700000e000100000f0201010000100201010000110302000012030200001304020000140506000015050600080f080900071d0a0100081e080900071f0a0b0007200a010006210c01000122020f01000123020c01000424110b020300042511120203000a261314000527020f0100022803180004290219020304092a1a1b00032b1a0f00042c1c02020302020e0e0e0f0e10101110130e1016111615101810020608020201030001060c02060c0304030103010203010908060303080603010301030106080201080601060806010101020502060800080508040802010900010804020804080502060b0302090009010900010609010208050301080202080406080102080403ae010a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a02080508000708000a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050105010b030209000901010a0201080503070b0302090009010900090193010508000708000a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a02080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805010708000b03030101010301030103010b01030101010301030103010c70726963655f6f7261636c6504636f696e067369676e657206737472696e67057461626c6509747970655f696e666f046d617468036936340570726963651070726963655f6964656e74696669657204707974681250726963654964656e7469666965724d61700e54657374507269636553746f72650550726963650c666f726d61745f7072696365096765745f7072696365126765745f70726963655f666f725f746573740a696e697469616c697a6512696e697469616c697a655f746573746e6574127365745f7468726573686f6c645f73656373107369676e65645f7536345f6d696e75730f7369676e65645f7536345f706c757304696e666f055461626c6506537472696e670f50726963654964656e7469666965720e7468726573686f6c645f736563730b70726963655f7461626c6503493634196765745f6d61676e69747564655f69665f706f736974697665086765745f6578706f0f6765745f69735f6e65676174697665196765745f6d61676e69747564655f69665f6e6567617469766506706f775f31300673796d626f6c08646563696d616c7308636f6e7461696e7306626f72726f77176765745f70726963655f6e6f5f6f6c6465725f7468616e09747970655f6e616d650a616464726573735f6f66036e65770d66726f6d5f627974655f76656304757466380675707365727414812adfd8ba2f589c0fe48c5170fa287cd36050dd487d17e2f4a765101f70ed00000000000000000000000000000000000000000000000000000000000000017e783b349d3e89cf5931af376ebeadbfab855b3fa239b7ada8f5a92fbea6b3870308700000000000000003086d0000000000000003086e0000000000000003081000000000000000052014812adfd8ba2f589c0fe48c5170fa287cd36050dd487d17e2f4a765101f70ed0a0221202b9ab1e972a281585084148ba1389800799bd4be63b957507db1349314e474450a020504414156450a022120bd640cddb72063e2ede34c6a0baf6699759b9837fcb06aa0e2fbcecb9b65fde70a02040341434d0a0221202a01deaec9e51a579277b34b122399984d0bbf57e2458a7e42fecd2829867a0d0a0204034144410a022120fa17ceaf30d19ba51112fdcc750cc83454776f47fb0112e4af07f15f4bb1ebc00a020504414c474f0a0221206d0af467543fc7daedf7abed96423877560c8d03725f3e5c87516774982a679c0a020403414e430a02212015add95022ae13563a11992e727c91bdb6b55bc183d9d747436c80a483d8c8640a0204034150450a02212003ae4db29ed4ae33d323568895aa00337e658e348b37509f5372ae51f0af00d50a0204034150540a022120b881c6dad5dd3dc9a83222f8032fb439859288119afc742d43adc305cef151cc0a0204034153520a022120681e0eb7acf9a2a3384927684d932560fb6f67c6beb21baa0f110e993b2653860a02060541544c41530a0221208ff1200345393bb25be4f4eeb2d97234e91f7e6213f3745a694b1436e700f2710a02040341544d0a022120b00b60f88b03a6a625a8d1c048c3f66653edf217439983d037e7222c4e6128190a02050441544f4d0a0221204cbd623d7aa47003fff1cd75c3f96cb24a660014b697d91cfb7adcd204b952020a020504415553540a02212093da3352f9f1d105fdfe4971cfa80e9dd777bfc5d0f683ebb6e1294b92137bb70a020504415641580a022120b7e3904c08ddd9c0c10c6d207d390fd19e87eb6aab96304f571ed94caebdefa00a0204034158530a0221209d23a47f843f5c9284832ae6e76e4aa067dc6072a58f151d39a65a4cc792ef9f0a0204034241520a0221203dd2b63686a450ec7290df3a1e0b583c0481f651351edfa7636f39aed55cf8a30a0204034243480a0221207f981f906d7cfe93f618804f1de89e0199ead306edc022d3230b3e8305f391b00a020504424554480a0221202f95862b045670cd22bee3114c39763a4a08beeb663b145d283c31d7d1101c4f0a020403424e420a0221201ce9069708fb49e2f1b062fa4f1be0bb151475ca506939d6d8c14386d49f43dc0a02040342525a0a022120e62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b430a0204034254430a022120097d687437374051c75160d648800f021086bc8edf469f11284491fda81923150a0204034254540a0221205bc91f13e412c07599167bae86f07543f076a638962b8d6017ec19dab4a828140a020504425553440a0221202dd14c7c38aa7066c7a508aac299ebcde5165b07d5d9f2d94dfbfe41f0bc5f2e0a0204034339380a0221202356af9529a1064d41e32d617e2ce1dca5733afa901daba9e2b68dee5d53ecf90a02050443414b450a02212015ecddd26d49e1a8f1de9376ebebc03916ede873447c1255d2d5891b92ce57170a02060543424554480a022120bd4dbcbfd90e6bc6c583e07ffcb5cb6d09a0c7b1221805211ace08c8378596270a0204034348520a022120e799f456b358a2534aa1b45141d454ac04b444ed23b1440b778549bb758f2b5c0a02040343485a0a0221209c479b12a2b2c1051715d4d462dd7a6abbb6dccabf3af31a53f6130a1cd88efc0a020504434954590a0221208517b35589b5f1f6ad626da2379ff592d5101b63aa661d75b7a883fdbda023f00a020504434f50450a0221204e53c6ef1f2f9952facdcf64551edb6d2a550985484ccce6a0477cae4c1bca3e0a020403434f570a0221208f218655050a1476b780185e89f19d2b1e1f49e9bd629efad6ac547a946bf6ab0a020504435553440a022120b0948a5e5313200c632b51bb5ca32f6de0d36e9950a942d19751e833f70dabfd0a0204034441490a022120dcef50dd0a4cd2dcc17e45df1676dcb336a11a61c69df7a0299b0150c672d25c0a020504444f47450a022120ca3eed9b267293f6595901c734c7525ce8ef49adafe8284606ceb307afa2ca5b0a020403444f540a022120ff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace0a0204034554480a022120c80657b7f6f3eac27218d09d5a4e54e47b25768d9f5e10ac15fe2cf9008814000a020504464944410a0221202fb245b9a84554a0f15aa123cbb5f64cd263b59e9a87d80148cbffab50c69f300a020504464c4f570a0221205c6c0d2386e3352356c3ab84434fafb5ea067ac2678a38a338c4a69ddc4bdb0c0a02040346544d0a0221206c75e52531ec5fd3ef253f6062956a8508a2f03fa0a209fb7fbc51efd9d35f880a0204034654540a022120301377b122716cee1a498e7930a1836c0b1db84667cc78bbbcbad6c330ea6afb0a02040347414c0a0221200781209c28fda797616212b7f94d77af3a01f3e94a5d421760aef020cf2bcb510a02050447414c410a022120baa284eaf23edf975b371ba2818772f93dbae72836bbdea28b07d40f3cf8b4850a020403474d540a0221206034b1f68b9363dff2cf9d53b1a88fb4d0929c65f34d532db53738853efc00ad0a020504474f46580a02212095609d32c98a467a72ac419f2e64bb2b8dbd5b00b74f3a0fd72f42343af1743d0a0205044858524f0a0221207a5bc1d2b56ad029048cd63964b3ad2776eadf812edc1a43a31406cb54bff5920a020403494e4a0a022120a4702f0f5818258783a1e47f453cb20b0fbec32ca67260e1d19dfcdd6a4d0ebb0a020605494e5445520a02212081a21b01c15b8d01f6cdfed65e00987cc4c901858c821b2089344987de3102e90a0204034a45540a022120ee42016c303126bd9263724e00f83a8114e84518c6e8ffc9738c001cc301daff0a0204034a53540a022120abe4f2b264560a397f38eec024369356e5c1ea4f7aab94729369f144b3d977790a0204034a55560a022120d1d95644ffc11ca502f21e067a7814144c56b37018515ced4335a886a827a3050a0206054c415a494f0a0221206e3f3fa8253588df9326580180233eb791e03b443a3ba7a1d892e73874e19a540a0204034c54430a022120e6ccd3f878cf338e6732bf59f60943e8ca2c28402fc4d9c258503b2edbe74a310a0205044c554e410a0221204456d442a152fd1f972b18459263ef467d3c29fb9d667e30c463b086691fbc790a0205044c554e430a0221205de33a9112c2b700b8d30b8a3402c103578ccfa2765696471cc672bd5cf6ac520a0206054d415449430a0221201888f463c27997174f97d2a36af29bf4648b61a5f69e67c45505a80f826bb7850a0205044d424f580a02212027d108eb764c912f49d3453a21dd95516619b1c45d0b607ee58a137ac8a6f32d0a0205044d45414e0a022120dfaeafde7f8ad3cb9ddbcc85ed7ae7e53910e7ab377fd75921920f97c80a8edc0a0204034d45520a0221200b46c1c04e9c914037cc4e0561a7e6787f6db0b89b7b65281f0f6fea1ce45a740a0204034d49520a0221205b70af49d639eefe11f20df47a0c0760123291bb5bc55053faf797d1ff9059830a0205044d4e474f0a022120c2289a6a43d2ce91c6f55caec370f4acc38a2ed477f58813334c6d03749ff2a40a0205044d534f4c0a022120c415de8d2eba7db216527dff4b60e8f3a5311c740dadb233e13e12547e2267500a0205044e4541520a02212005934526b94a9fbe4c4ce0c3792213032f086ee4bf58f2168a7085361af9bdc10a0203024f470a022120c572690504b42b57a3f7aed6bd4aae08cbeeebdadcf130646a692fe73ec1e0090a0204034f4e450a02212037505261e557e251290b8c8899453064e8d760ed5c65a779726f2490980da74c0a0205044f5243410a0221200afa3199e0899270a74ddcf5cc960d3c6c4414b4ca71024af1a62786dd24f52a0a020504504f52540a02212088e2d5cbd2474766abffb2a67a58755a2cc19beb3b309e1ded1e357253aa36230a020605504f52544f0a0221203d253019d38099c0fe918291bd08c9b887f4306a44d7d472c8031529141f275a0a0204035053470a022120fd0690232b0fae5efdc402c1b9aac74176383ff7daf87d021554bda24a38e0ec0a020504524143410a02212091568baa8beb53db23eb3fb7f22c6e8bd303d103919e19733f2bb642d3e7987a0a0204035241590a0221206ed3c7c4427ae2f91707495fc5a891b30795d93dbb3931782ddd77a5d8cb6db70a0204035342520a0221201021a42d623ab4fe0bf8c47fd21cc10636e39e07f91e9b2478551e137d512aaa0a02070653434e534f4c0a022120f8d030e4ef460b91ad23eabbbb27aec463e3c30ecc8d5c4b71e92f54a36ccdbd0a020504534c4e440a0221209fb0bd29fe51481b61df41e650346cc374b13c2bab2e3610364cd834a592025a0a020403534e590a022120ef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d0a020403534f4c0a02212023245bb74254e65a98cc3ff4a37443d79f527e44e449750ad304538b006f21bc0a02040353524d0a022120a1a6465f4c2ebf244c31d80bc95c27345a3424e428c2def33eced9e90d3f701b0a0206055354534f4c0a0221204457960559b812558bb0f8cb7912f8bcb843eb801a3133ef45be998630ff8c050a020403544c4d0a022120433faaa801ecdb6618e3897177a118b273a8e18cc3ff545aadfc207d58d028f70a020504545553440a022120eaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a0a020504555344430a0221202b89b9dc8fdf9f34709a5b106b472f0f39bb6ca9ce04b0fd7f2e971688e2e53b0a020504555344540a022120ef94acc2fb09eb976c6eb3000bab898cab891d5b800702cd1dc88e61d7c3c5e60a020504555354430a0221207507a4629ad0143550666bce2e7cae0b961a0f624f821feaab642fe1be632f5c0a0204035641490a022120b216f7ca372b318985903866e0b6dc44a14564828c49f36d0d363805aa76335c0a02040357494e0a022120b82449fd728133488d2d41131cffe763f9c1693b73c544d9ef6aaa371060dd250a020403574f4f0a022120831624f51c7bd4499fe5e0f16dfa2fd22584ae4bdc496bbbbe9ba831b2d9bce90a0204035856530a02212026852e2d0696e25e6adaad2d7ca3a1f2f15aab68d317ace14d41b4128a7e780f0a0204035a42430a022120d6b3bc030a8bbb7dd9de46fb564c34bb7f860dead8985eb16a49cdc62f8ab3a50a02212073dc009953c83c944690037ea477df627657f45c14f16ad3a61089c5a3f9f4f20a02212008f781a893bc9340140c5f89c8a96f438bcfae4d1474cc0f688e3a52892c73180a0221204204a764d9e0ca8db0fd43b62728265bf82671ce8a8b4bfedba13672be12de620a022120cb1743d0e3e3eace7e84b8230dc082829813e3ab04e91b503c08e9a441c0ea8b0a02212044a93dddd8effa54ea51076c4e851b6cbbfd938e82eb90197de38fe8876bb66e0a022120c11efd88a9b2c96bc84bccd6ce4aa05bebad7aa760dbe5f2f00ef90c4abd50cc0a02212061226d39beea19d334f17c2febce27e12646d84675924ebb02b9cdaea68727e30a022120d7566a3ba7f7286ed54f4ae7e983f4420ae0b1e0f3892e11f9c4ab107bbad7b90a02212030029479598797290e3638a1712c29bde2367d0eca794f778b25b5a472f192de0a022120fc309467defa4b198c6b5bd59c08db4b9dfb27ddbcc32f31560f217b4ff8fc2b0a022120ecf553770d9b10965f8fb64771e93f5690a182edc32be4a3236e0caaa6e0581a0a022120457064c555edae5b6b89267e992be4c58be5375f0e9ca9749391c7094f7d90330a022120f9c0172ba10dfa4d19088d94f5bf61d3b54d5bd7483a322a982e1373ee8ea31b0a022120eb3b5720301b36fa074260e6e27e2cfff3a7c6bbb47564eb218a9a7f2a8c01930a02212006c532524fabd49cc142815502d785e4f34ec3bd035480efb770568d423f46c60a022120c098773aa18ebb7e84d5ee7ea7d97105ab2015a329f670012398cd2c8f5cc6ca0a0221200d10b9ccdc9af1d65cd4bafabf4e34db01c0ce83abba190230eaf26d7592cd210a022120970541e943e11d1bf1d4d763bc8e70995f613dc682f727045a866312312a63760a02212013ac8c71e4e1c61dece57bea76163d393bf75cd0db8e52981e1564fa592698cb0a022120b59d65c2e10af17c0d6f7d10be8d64c0c13dd15d957c4c39763b4cc55e5919370a02212087a67534df591d2dd5ec577ab3c75668a8e3d35e92e27bf29d9e2e52df8de4120a02212031775e1d6897129e8a84eeba975778fb50015b88039e9bc140bbd839694ac0ae0a02212036032e522b810babd8e3148e9f0d588af9e95e93b97ffb58566b837fdbd31f7f0a022120ca80ba6dc32e08d06f1aa886011eed1d77c77be9eb761cc10d72b7d0a2fd57a60a0221206660d7629213995af8aa169ad6a1cf1a725765d3741b7e7a27825f884a701b960a022120aa67a6594d0e1578faa3bba80bec5b31e461b945e4fbab59eeab38ece09335fb0a0221209b7bfd7654cbb80099d5edc0a29159afc9e9b4636c811cf8c3b95bd11dd8e3dd0a0221200184a60a47ab7c23fcb828d727b05748ef52433fb5ae96f775cc98c9049d8c2c0a0221206354d685c247f1efc36f967617beffa2ebd5a95d8ffe17de4498505c923067b80a02212021adabf73ad61903c1872fa220f84d3b1b9990cec2047f8317e2a67efcd1764e0a022120c999fe8a75bf9528931deb832e2934dd1ac138757d7f2c1398675b6f521d556f0a02212087fd5a8d0bf026239f98b53311d2cec2ee171e853f545e1ad742e092a97ef8600a02212051ae9b785e6aeb288955720faef15f63ee3ae21af38114ade8b3fc3d3831b5ad0a0221202d9315a88f3019f8efa88dfe9c0f0843712da0bac814461e27733f6b83eb51b30a0221202245aec1db780b8dc9f710173256996164f0a65f25a975453e4202a54371d2ea0a022120077e345652cb98edba89815a63a0ede724eba12d7a10c8498e0e762d581aca6b0a022120997e0bf451cb36b4aea096e6b5c254d700922211dd933d9d17c467f0d6f343210a022120677dbbf4f68b5cb996a40dfae338b87d5efb2e12a9b2686d1ca16d69b3d7f2040a0221206de025a4cf28124f8ea6cb8085f860096dbc36d9c40002e221fc449337e065b20a022120d2c2c1f2bba8e0964f9589e060c2ee97f5e19057267ac3284caef3bd50bd2cb50a02212070bf2974182b6ebf4eac64977170074315e7a07d7b58a963758060924ee9a1920a0221209f2acb902ee5c3a8e41c643164a498ed3089c99df3477189babd3682801340750a02212052800482aa2666c0d2621f8f0a8c19ee6e5e5039a65524e268315501b3355fbb0a0221202f317bea04ce89adb8acc85a1a68d20d6e89976d5e86306570a0bb3107e4916a0a022120b5366e5ded52c3db5d81635a624a39d81eb8c639427fc79c539e5c91e17c84940a0221207f57ca775216655022daa88e41c380529211cde01a1517735dbcf30e4a02bdaa0a02212027e867f0f4f61076456d1a73b14c7edc1cf5cef4f4d6193a33424288f11bd0f40a0221209b245faf19d2f3306b58821ef60b194d7b67eb5250635059d8eaae4a36337b280a02212085dafbfa99c733fdd33649551666958ca8f82fd0d849746e093b770caab249d20a0221206b86b78584e182c61729267d73593f48b6a929f3218234769281513cbe5e87ee0a0204035041490a0221201e761bb4e6b1e4d7899b618d389516ddbdfbdb858018b71c45cb6ade57c96f620a0221207730809b4a4656325b7fbc8157fd803c3da170727c541afc4db37773246258b10a022120cb9372930932694b8a74dd5599c0f9e236575f434faf05141d95803a91f044ed0a022120341d9502b1e6bc445036fd76f57bc824c09254a754289878b52a40eb067d2a0b0a022120f9917668f24038a383e51c0b019f5d9645d6785c6bf9a0d48483edf82ba5caec0a022120dd51a67a1b4d0702abf5b5385631b7d3e586993eadacf2e0d900c0a81edcffdd0a022120b5d2cee0b86bb0571db898ae7b9f288c5e272fa486d41a5bf375b52a0249d94c0a022120fe650f0367d4a7ef9815a593ea15d36593f0643aaaf0149bb04be67ab851decd0a02212078ec25615d53d2486db101e829f77615c4408cbbd543088714b9f267da44591a0a022120b718e659619a031b41c6ea9122f146859a82d4a7edc17c55b1e5188e8b4c1d1c0a020504535445500a02212013f7925c9186b8cca50dde4bbf2d4fa9705052cceb6f2fc79df827e2b37d6f3b0a0221200adbf6463e27f60f171bcc498703a4282d1954ec3a85e1f6698b48ecde18c00e0a0221201bd1c59cd425aebf8a931c1b2a902b9a11e7d18dc68021e4a35a5cf24220a6c70a02212041f3625971ca2ed2263e78573fe5ce23e13d2558ed3f2e47ab0f84fb9e7ae7220a0221201fc18861232290221461220bd4e2acd1dcdfbc89c84092c93c18bdc7756c15880a022120026d1f1cf9f1c0ee92eb55696d3bd2393075b611c4f468ae5b967175edc4c25c0a022120eca4f9c5ce7cbef8a349fa9f6c12b23ac45b9ad91c4d1808c6a2dda841f95a020a022120834d3f05278b6f5c963670f437a2267c160914707328f888418902106bcd13d70a022120bf517e0f7ccfc307f0b2fa93b99a737641933989af6af769c928725989c21e660a0221206ff709bf1f0fdb46d991ae6839163df1e050d143429d737fc650b6b2143478080a02212064abe8a459058c60d55427f62be3dc4942c0ba93d1eb5cb85117b70b8e4651ad126170746f733a3a6d657461646174615f763063036d000000000000001a4552525f4e4f545f454e4f5547485f5045524d495353494f4e53006e00000000000000134552525f544f4b454e5f4e4f545f464f554e44007000000000000000174552525f414c52454144595f494e495449414c495a454400000202160b0302080408051a030102011b0b03020804030000000007440a0011080c020e0211090c080b00110a0c050600000000000000000c0a090c090b0a0b0907030911070c090c0a0e05110b0c070a07031a051e0e05110c0c0305210e0511090c030b030c060b0a0b090b060b0711070c090c0a0b0a0b090b01340911060c090c0a0b090335053c0b080b0a33110d1a0c0405420b080b0a33110d180c040b04020101000200010d26070429010304050638000238010c0338020c0007042b000c010a0110000a03380303160b01010702270a0110000b033804140c020b020b0110011411120c040e040b001100020200000101151438050c0007042b010c010a0110020a003806030e0b01010702270b0110020b0038071402030104010017a4060a00111407042103090b00010701270a00111429002003120b00010700273808063c0000000000000012000c6b0a000b6b2d000b0011142a000c6c070511160c020a6c0f00070611170b023809070711160c040a6c0f00070811170b043809070911160c060a6c0f00070a11170b063809070b11160c080a6c0f00070c11170b083809070d11160c0a0a6c0f00070e11170b0a3809070f11160c0c0a6c0f00071011170b0c3809071111160c0e0a6c0f00071211170b0e3809071311160c100a6c0f00071411170b103809071511160c120a6c0f00071611170b123809071711160c140a6c0f00071811170b143809071911160c160a6c0f00071a11170b163809071b11160c180a6c0f00071c11170b183809071d11160c1a0a6c0f00071e11170b1a3809071f11160c1c0a6c0f00072011170b1c3809072111160c1e0a6c0f00072211170b1e3809072311160c200a6c0f00072411170b203809072511160c220a6c0f00072611170b223809072711160c240a6c0f00072811170b243809072911160c260a6c0f00072a11170b263809072b11160c280a6c0f00072c11170b283809072d11160c2a0a6c0f00072e11170b2a3809072f11160c2c0a6c0f00073011170b2c3809073111160c2e0a6c0f00073211170b2e3809073311160c300a6c0f00073411170b303809073511160c320a6c0f00073611170b323809073711160c340a6c0f00073811170b343809073911160c360a6c0f00073a11170b363809073b11160c380a6c0f00073c11170b383809073d11160c3a0a6c0f00073e11170b3a3809073f11160c3c0a6c0f00074011170b3c3809074111160c3e0a6c0f00074211170b3e3809074311160c400a6c0f00074411170b403809074511160c420a6c0f00074611170b423809074711160c440a6c0f00074811170b443809074911160c460a6c0f00074a11170b463809074b11160c480a6c0f00074c11170b483809074d11160c4a0a6c0f00074e11170b4a3809074f11160c4c0a6c0f00075011170b4c3809075111160c4e0a6c0f00075211170b4e3809075311160c500a6c0f00075411170b503809075511160c520a6c0f00075611170b523809075711160c540a6c0f00075811170b543809075911160c560a6c0f00075a11170b563809075b11160c580a6c0f00075c11170b583809075d11160c5a0a6c0f00075e11170b5a3809075f11160c5c0a6c0f00076011170b5c3809076111160c5e0a6c0f00076211170b5e3809076311160c600a6c0f00076411170b603809076511160c620a6c0f00076611170b623809076711160c640a6c0f00076811170b643809076911160c660a6c0f00076a11170b663809076b11160c680a6c0f00076c11170b683809076d11160c6a0a6c0f00076e11170b6a3809076f11160c6e0a6c0f00077011170b6e3809077111160c700a6c0f00077211170b703809077311160c720a6c0f00077411170b723809077511160c740a6c0f00077611170b743809077711160c760a6c0f00077811170b763809077911160c780a6c0f00077a11170b783809077b11160c7a0a6c0f00077c11170b7a3809077d11160c7c0a6c0f00077e11170b7c3809077f11160c7e0a6c0f0007800111170b7e380907810111160c80010a6c0f0007820111170b8001380907830111160c82010a6c0f0007840111170b8201380907850111160c84010a6c0f0007860111170b8401380907870111160c86010a6c0f0007880111170b8601380907890111160c88010a6c0f00078a0111170b88013809078b0111160c8a010a6c0f00078c0111170b8a013809078d0111160c8c010a6c0f00078e0111170b8c013809078f0111160c8e010a6c0f0007900111170b8e01380907910111160c90010a6c0f0007920111170b9001380907930111160c92010a6c0f0007940111170b9201380907950111160c94010a6c0f0007960111170b9401380907970111160c96010a6c0f0007980111170b9601380907990111160c98010a6c0f00079a0111170b98013809079b0111160c9a010a6c0f00079c0111170b9a013809079d0111160c9c010a6c0f00079e0111170b9c013809079f0111160c9e010a6c0f0007a00111170b9e01380907a10111160ca0010a6c0f0007a20111170ba001380907a30111160ca2010a6c0f0007a40111170ba201380907a50111160ca4010a6c0f0007a60111170ba401380907a70111160ca6010a6c0f0007a80111170ba601380907a90111160ca8010a6c0f0007aa0111170ba801380907ab0111160caa010a6c0f0007ac0111170baa01380907ad0111160cac010a6c0f0007ae0111170bac01380907af0111160cae010b6c0f0007b00111170bae0138090204010401001da7050a0011140c010a01070421030b0b00010701270a00111429002003140b0001070027380806504600000000000012000c020b000b022d000b012a000c0307b10111160c4c0a030f00070611170b4c380907b20111160c6d0a030f00070a11170b6d380907b30111160c780a030f00070c11170b78380907b40111160c83010a030f00070e11170b8301380907b50111160c8e010a030f00071011170b8e01380907b60111160c520a030f00071211170b52380907b70111160c5d0a030f00071611170b5d380907b80111160c650a030f00071a11170b65380907b90111160c660a030f00071e11170b66380907ba0111160c670a030f00072411170b67380907bb0111160c680a030f00072611170b68380907bc0111160c690a030f00072811170b69380907bd0111160c6a0a030f00072a11170b6a380907be0111160c6b0a030f00072c11170b6b380907bf0111160c6c0a030f00072e11170b6c380907c00111160c6e0a030f00073011170b6e380907c10111160c6f0a030f00073211170b6f380907c20111160c700a030f00073811170b70380907c30111160c710a030f00073e11170b71380907c40111160c720a030f00074011170b72380907c50111160c730a030f00074211170b73380907c60111160c740a030f00074411170b74380907c70111160c750a030f00074611170b75380907c80111160c760a030f00074811170b76380907c90111160c770a030f00074a11170b77380907ca0111160c790a030f00074c11170b79380907cb0111160c7a0a030f00074e11170b7a380907cc0111160c7b0a030f00075011170b7b380907cd0111160c7c0a030f00075211170b7c380907ce0111160c7d0a030f00075411170b7d380907cf0111160c7e0a030f00075611170b7e380907d00111160c7f0a030f00075811170b7f380907d10111160c80010a030f00075a11170b8001380907d20111160c81010a030f00075c11170b8101380907d30111160c82010a030f00075e11170b8201380907d40111160c84010a030f00076211170b8401380907d50111160c85010a030f00076411170b8501380907d60111160c86010a030f00076a11170b8601380907d70111160c87010a030f00076c11170b8701380907d80111160c88010a030f00076e11170b8801380907d90111160c89010a030f00077011170b8901380907da0111160c8a010a030f00077211170b8a01380907db0111160c8b010a030f00077411170b8b01380907dc0111160c8c010a030f00077611170b8c01380907dd0111160c8d010a030f00077811170b8d01380907de0111160c8f010a030f00077a11170b8f01380907df0111160c90010a030f00077c11170b9001380907e00111160c91010a030f00077e11170b9101380907e10111160c92010a030f0007820111170b9201380907e20111160c93010a030f0007840111170b9301380907e30111160c4d0a030f0007e40111170b4d380907e50111160c4e0a030f0007860111170b4e380907e60111160c4f0a030f00078c0111170b4f380907e70111160c500a030f00078e0111170b50380907e80111160c510a030f0007900111170b51380907e90111160c530a030f0007920111170b53380907ea0111160c540a030f0007940111170b54380907eb0111160c550a030f0007960111170b55380907ec0111160c560a030f0007980111170b56380907ed0111160c570a030f00079a0111170b57380907ee0111160c580a030f0007ef0111170b58380907f00111160c590a030f00079c0111170b59380907f10111160c5a0a030f00079e0111170b5a380907f20111160c5b0a030f0007a00111170b5b380907f30111160c5c0a030f0007a20111170b5c380907f40111160c5e0a030f0007a40111170b5e380907f50111160c5f0a030f0007a60111170b5f380907f60111160c600a030f0007a80111170b60380907f70111160c610a030f0007aa0111170b61380907f80111160c620a030f0007ac0111170b62380907f90111160c630a030f0007ae0111170b63380907fa0111160c640b030f0007b00111170b6438090205010401001e120a00111407042103090b00010701270b0011142a000c020b010b020f011502060000001f5d0a010a031f0305051c0a020a0026030a05110b020b0017090c070c0405170b000b0217080c070c040b040b070c060c05055a0a01031f05230a03200c080525090c080b080328052f0b000b0216080c0e0c0d05560b01200b031f0335053c0b000b0216090c0c0c0b05520a000a0226034105480b000b0217090c0a0c09054e0b020b0017080c0a0c090b090b0a0c0c0c0b0b0b0b0c0c0e0c0d0b0d0b0e0c060c050b050b060207000000205e0a010a031f03050508080c0705140a0120030c05100a03200c040512090c040b040c070b070317051e0b000b02160b010c060c05055b0b01032105250b03200c080527090c080b08032a05410a000a0224032f05360b000b0217080c0a0c09053c0b020b0017090c0a0c090b090b0a0c0e0c0d05570a020a00240346054d0b020b0017080c0c0c0b05530b000b0217090c0c0c0b0b0b0b0c0c0e0c0d0b0d0b0e0c060c050b050b060200000001010000"; - let res = run_binary_test("sample_price_oracle", code); - assert!(res.is_ok(), "{:?}", res) -} - -#[test] -fn sample_aptosd_swap() { - let code = "a11ceb0b050000000c0100160216300346ee0104b4022205d602960407ec06de0708ca0e40068a0f8b01109510f9010a8e12520ce012e80e0dc821160000010101020103010401050106010700080009000a000b0700000c0700000d0800000e0700000f07000a28040207000400042b0401060102380800083a0000063c070100000010000100001102010000120101000013030100001401010000150101000016020100001701040000180506000019010700001a020100001b020100001c010100001d000100001e020100001f02010000200001000021000100092f01090009300105000a310b0c02070604320e01010607330205000934010f0009350104000936010f000a37110f020704033900010100033b02010100093d0104000a3e1617020704063f180f01000640191a01000a411b1c02070409421d010005431f040005441f0400094501200009460104000947010f0009480901000a490125020704014a022601060a4b1128020704140a150d1a0a1b121c1315141e0a1f052005210a151e290a2a0d2a142a1e2b0a1b1303060c05030001060c02060c0301030105050303030303010a050c03030303030505070b0502050803070b0502050803070802070803070b0601080401020205080303070b050209000901090009010107090101080402070b060109000900010108070b05020508030501070b06010800030107080207080302060b05020900090109000108070108080108002d0b0901050b0901050b0901050c0b0901050b0901050b0901050b0901050b090105030303030303070b06010801070b06010801070b06010801070b0601080103070803070803070803070803070b0502050803070b0502050803070b0502050803070b0502050803070b090105070b090105070b090105070b09010503030b0901050b0901050b0901050b090105070802070802070802070802070802030301060b050209000901010b0901090001060b0901090001070b0901090001090002070b0502090009010900030709010b090109000b09010900020503010801020303010c04010103030a03030303030505070b0502050803070b0502050803070803070b0901050b090105070803070b0502050803070b0901050b0901050a050a0b0502050803060c030c0b060108040c0b060108000c0b060108010c010b050209000901010b060109000c0b0901050c070b0502050803050b090105070b06010801060803070b0502050803070b0901050b090105070802060c030609010b090109000b090109000d6170746f737061645f73776170076163636f756e740a6170746f735f636f696e04636f696e056576656e74066d6174683634066f7074696f6e067369676e65720d6170746f737061645f636f696e06636f6e6669670e6974657261626c655f7461626c65104269644170746f735061644576656e7417446973747269627574654170746f737061644576656e74114c61756e636850616452656769737472790f546f6b656e446973747269627574650e57686974654c6973744576656e740c61646457686974654c6973740c6173736572745f61646d696e136173736572745f6e6f5f656d657267656e63790b6269644170746f735061640d64697374726962757465416c6c0e64697374726962757465417470701064697374726962757465536561736f6e0f67657453776170546f74616c4269640c67657457686974654c6973740d67657457686974654c697374730a696e697469616c697a650f6c61756e6368506164536561736f6e09726566756e64416c6c0b726566756e644170746f730b7265736574536561736f6e0f77686974654c697374536561736f6e0d77697468647261774170746f731077697468647261774170746f73506164036361700362696408696e766573746f72106469737472696275746564546f6b656e06726566756e6409696e766573746f72730d4974657261626c655461626c6508746f74616c426964126269646170746f737061645f6576656e74730b4576656e7448616e646c6519646973747269627574656170746f737061645f6576656e74731077686974656c6973745f6576656e74730b64697374726962757465640c676574537761705374617465126765745265736f757263654164647265737317626f72726f775f6d75745f776974685f64656661756c740a656d69745f6576656e740a616464726573735f6f660b6973456d657267656e63791467657453776170436f6e6669674861726443617011697342797061737357686974654c69737408636f6e7461696e73094170746f73436f696e087472616e736665720c4170746f73506164436f696e087265676973746572064f7074696f6e1a67657453776170436f6e666967417074546f417074745261746508686561645f6b65790769735f736f6d6507657874726163740f626f72726f775f697465725f6d75740a6d696e7441747070546f036d696e036d6178116765745265736f757263655369676e65721467657453776170436f6e666967536f66744361701967657453776170436f6e666967456e61626c65526566756e640c736574537761705374617465036e6577106e65775f6576656e745f68616e646c650b626f72726f775f6974657241376d8231e6aedc29a19459e804b3770a250c3f367ac8d0f91e10842e8c906d0000000000000000000000000000000000000000000000000000000000000001030800e87648170000000308950100000000000003089a0100000000000003089b010000000000000308930100000000000003089801000000000000030896010000000000000308970100000000000003089901000000000000020104020105020101020103020102052041376d8231e6aedc29a19459e804b3770a250c3f367ac8d0f91e10842e8c906d126170746f733a3a6d657461646174615f7630e4010893010000000000000f4552525f5045524d495353494f4e530095010000000000000d4552525f454d455247454e4359009601000000000000104552525f534541534f4e5f454e444544009701000000000000144552525f534541534f4e5f4e4f545f5245534554009801000000000000114552525f534541534f4e5f414354495645009901000000000000104552525f534541534f4e5f5354415445009a01000000000000134552525f484152444341505f52454143484544009b01000000000000144552525f4e4f545f494e5f57484954454c4953540b6572726f7220636f64657300020322032303240501020522032303250326032405020205270b050205080329032a0b060108002c0b060108012d0b06010804030206220323032e03250326032405040206220323032e032503260324050001000102083c0b0011011112070d21030807082711132a020c0c0a0c0f000c0b0b0c0f010c0e0b0b0c0a0a010c090b010c080b0a0b090600000000000000000600000000000000000600000000000000000600000000000000000600000000000000000b08120338000c0d0b020a0d0f02150b0e0a0d1002140a0d1003140a0d1004140a0d1005140a0d1005140b0d10061412043801020100000001080b001116070e210307070427020200000001061117200305070127020301000102106111021112070c2103090b000107082711180c0611132a020c0811190c040a080f000a0011160c030c020b022e0b0338020c070b040b071e03250b00010b08010703270a081007140b062503310b00010b08010702270a081007140a01160a080f07150a080f080c050a0011130a0138030a0038040b080f000a00111607000600000000000000000600000000000000000600000000000000000600000000000000000b001116120338000c090b010a090f03150b050a091002140a091003140b091006141200380502040000010215a00311180c13111d0c2b11132a020c260b261007140c2c0b2c0a13250310055c11132a020c270a270f000c180b270f090c0f0a182e38060c010d010c1c0a1c2e3807032405550a180b1c380838090c22010c140a141003140a140f0a150a14100a140a2b180a140f04150a141006140a1410041411220a0f0a141002140a141003140a141004140a141005140b141006141201380a0d220c1c051f0b1c010b18010b0f01059f030b130c0a11132a020c2a0a2a0f000c1b0b2a0f090c120a1b2e38060c040d040c1f0a1f2e3807037205c3010a1b0b1f380838090c23010c170a171002140c0d0a171003140c0b0b0d0b0b11230a0a11230c090a0906000000000000000024038c0105b4010a090a170f0a150a090a2b180a170f04150b0a0b09170c0a0a171006140a1710041411220a120a171002140a171003140a171004140a171005140b171006141201380a05b6010b17010a0a0600000000000000002503bb0105c0010b1b010b120105c3010d230c1f056d0a0a0600000000000000002403c80105b30211132a020c280a280f000c190b280f090c100a192e38060c000d000c1d0a1d2e380703dc0105b3020a190b1d380838090c24010c150a151003140a15100a141706000000000000000011240a0a11230c200a200600000000000000002403f40105a4020a15100a140a20160a150f0a150a200a2b180c210a151004140a21160a150f04150b0a0b20170c0a0a151006140b2111220a100a151002140a151003140a151004140a151005140b151006141201380a05a6020b15010a0a0600000000000000002503ab0205b0020b19010b100105b3020d240c1d05d7010b0a0600000000000000002503b90206a1860100000000002711132a020c290a290f000c1a0b290f090c110a1a2e38060c020d020c1e0a1e2e380703cd020599030a1a0b1e380838090c25010c160a161003140c0c0a16100a140c0e0a0c0a0e2603e8020b1a010b16010b1101061127000000000000270b0c0b0e1706000000000000000011240a160f05150a161005140600000000000000002403f70205940311250c030e030a161006140a16100514110d0a110a161002140a161003140a161004140a161005140b161006141201380a0596030b16010d250c1e05c8020b1e010b1a010b1101020500000102211a11260c0211132a021007140c0311270c010b01030c05110b030b02230c000513090c000b0003160518110c05191104020601000102010f0b00110111021112070c210309070827070911281105070a1128020701000102010511132b02100714020801000102222511132a020f000c090b090c080a000c070b000c060b080b070600000000000000000600000000000000000600000000000000000600000000000000000600000000000000000b06120338000c0a0a0a1002140a0a1003140a0a100a140a0a1004140b0a100514020901000102232611132a020f000c03400500000000000000000c060a032e38060c000d000c040a042e3807031105200a030b04380838090c05010c020d060b0210061444050d050c04050c0b04010b03010b06020a01000024220b00110111250c0a0e0a0c02380b0c0111250c040e04380c0c0511250c060e06380d0c0711250c080e08380e0c090b020b010600000000000000000b070b090b0512022d02070b1128020b010000010b0b0011011112070d210308070827070c1128020c00000102274a11132a020c0a0a0a0f000c070b0a0f090c050a072e38060c000d000c0811250c010e010c0b0a082e3807031805410a070b0838080c030c020b022e0b03380f0c09010c060a0b0a061006140a06100314110d0a050a061002140a061003140a061004140a061005140b061006141201380a0d090c0805130b0b010b08010b07010b0501020d00000001050b000b010b023803020e010000010b0b0011011112070a210308070627070b1128020f010000010b0b0011011112070b210308070727070d1128021001000020090b00110111250c030e030b010b023803021101000020090b00110111250c030e030b010b02381002020002040300030103030304030502010202020303020000"; - let res = run_binary_test("sample_aptosd_swap", code); - assert!(res.is_ok(), "{:?}", res) -} - -#[test] -fn sample_router() { - let code = "a11ceb0b050000000a01000e020e0603148f0104a3012805cb018f0207da03f90208d30640069307a00110b3082b0cde08db110000010101020003000400050006010a0401000100070000000008010202000000090102020000020b050600050c060700050d050200030e0207020000040f02070200000410020a0200000111020c01000612000d000113020f01000414020a0200000115100f0100031611120200000117130201000418020d0200000519140d00041a1500020000041b020a020000041c020d020000051d140d00031e111202000006080609070907080808090b0b0e0c080d0b0e080f0b100812080f0e0809090e130914091209160802040403060c030300030404043501010101010103030404040404040404040b000109000b000109000b000109000b000109000b000109000b000109000b000109010b000109010b0001090103030303030303030404030301010404010404040503030303030301060c0105010102090009010209010900010301090001020104010901010b0001090002060c0308060c070b00010900070b00010901030301030302030302050b000109000305040106060c010303030432010103030404040404040404040b000109000b000109000b000109000b000109000b000109000b000109000b000109010b000109010b000109010303030303030404030301010404010404040505030303030303030306726f7574657204636f696e067369676e657203616d6d0b636c6f625f6d61726b657403666565047574696c0873696d706c69667918737761705f636f696e5f666f725f65786163745f636f696e18737761705f65786163745f636f696e5f666f725f636f696e04436f696e0a616464726573735f6f660a6665655f65786973747316696e697469616c697a655f6665655f64656661756c740b706f6f6c5f6578697374730d6d61726b65745f657869737473086c6f745f73697a6508646563696d616c7303657870047a65726f0c6e5f6269645f6c6576656c730877697468647261771d636f696e5f737761705f636f696e5f666f725f65786163745f636f696e076465706f7369740b626573745f6269645f61750c73756274726163745f66656516706c6163655f6f726465725f666f725f726f757465720c6e5f61736b5f6c6576656c730b626573745f61736b5f6175076164645f6665651d636f696e5f737761705f65786163745f636f696e5f666f725f636f696e49661cd59c0b89440313af587bc99c3d38614d9a52479eb3f7c7c766d580c30b00000000000000000000000000000000000000000000000000000000000000010308c9000000000000000308ca000000000000000308c800000000000000030804000000000000000308070000000000000003086500000000000000030866000000000000000308030000000000000003080200000000000000030864000000000000000308ffffffffffffffff0308050000000000000003080100000000000000030868000000000000000308670000000000000003080600000000000000126170746f733a3a6d657461646174615f7630170104000000000000000c45544553545f4641494c4544000001000003190a000c030a010c040a01320000000000000000000000000000000022030905120b000a01190c020b010c000b020c0105040b030a001a0b040b001a020101040004ec030a0011030c310a311104200308050a0a0011053800030d0510080c03051238010c030b030c2d38020c2a38030c290a2d0b291f031d05fb0138040c27320a000000000000000000000000000000380535110a0c0e0600000000000000000c320600000000000000000c3438060c1a0a340a0223032f05340a320a01230c060536090c060b06033905eb01380706000000000000000021033e055f0a000a010a321738080c140b000d140d1a0a010a32170a020a34170906000000000000000006000000000000000038090c210c1d0a310b14380a0b320b21160c320b340b1d160c3405eb01380b0c130a310a130811110c120a020a3417350a0e180a121a340c090b090a272303750596010a000a010a321738080c180b000d180d1a0a010a32170a020a34170906000000000000000006000000000000000038090c230c1f0a310b18380a0b320b23160c320b340b1f160c3405eb010a0e0a1211000c250c2b0a000a010a321738080c190a000d190d1a0a010a32170a020a3417080b2b340b253438090c240c200a310b19380a0b320b24160c320b340b20160c340a340a022303c20105c7010a320a01230c0805c901090c080b0803cc0105ea010a020a3417350a0e180b121a340c0a0a000907060b13340b0a3200000000000000000000000000000000380c0c2e0c0d0b320b0d34160c320b340b2e34160c34052a0b320b012503f1010707270b340b022103f7010708270b310b1a380d05eb030a2d0a2a1f03800205b203380e0c28320a000000000000000000000000000000380f35110a0c0f0600000000000000000c330600000000000000000c3538060c1b0a350a02230392020597020a330a01230c04059902090c040b04039c0205a20338100600000000000000002103a10205a402080c0505aa020a020a35170a28230c050b0503ad0205ce020a000a010a331738080c150b000d150d1b0a010a33170a020a35170906000000000000000006000000000000000038090c220c1e0a310b15380a0b330b22160c330b350b1e160c3505a20338110c110a310a110811150c100b100a0f11000c260c2c0a000a010a331738080c160a000d160d1b0a010a33170a020a3517080b2c340b263438090c360c370a310b16380a0b330b36160c330b350b37160c350a350a02230381030586030a330a01230c07058803090c070b07038b0305a1030a000807060b11340a020a3517320000000000000000000000000000000038120c2f0c0b0b330b2f34160c330b350b0b34160c35058d020b330b012503a8030707270b350b022103ae030708270b310b1b380d05eb030b2d03b50305cd030a000a0138080c1738060c1c0b000d170d1c0b010b0209060000000000000000060000000000000000380901010a310b17380a0b310b1c380d05eb030b2a03d00305e7030b00080705070a0a02320000000000000000000000000000000038120c300c0c0b0c340b022103e0030707270b30340b012503eb030708270b0001070c27020201040016d1030a0011030c2b0a2b1104200308050a0a0011053800030d0510080c03051238010c030b030c2738020c2438030c230a270a231f031d05b70138040c21320a000000000000000000000000000000380535110a0c0a0600000000000000000c2d0600000000000000000c2f38060c160a2d0a0123032f05a70138070600000000000000002103340537080c04053d0a010a2d170a21230c040b040340055f0a000a010a2d1738080c100b000d100d160a010a2d170600000000000000000906000000000000000006000000000000000038130c1c0c190a2b0b10380a0b2d0b1c160c2d0b2f0b19160c2f05a701380b0c0f0a2b0a0f0811110c0e0b0e0a0a11000c1f0c250a000a010a2d1738080c140a000d140d160a010a2d17060000000000000000080b25340b1f3438130c310c330a2b0b14380a0b2d0b31160c2d0b2f0b33160c2f0a2d0a012303900105a6010a000907060b0f340a010a2d173200000000000000000000000000000000380c0c280c080b2d0b0834160c2d0b2f0b2834160c2f052a0b2d0b012103ad010707270b2f0b022603b3010708270b2b0b16380d05d0030a270b241f03bc01059403380e0c22320a000000000000000000000000000000380f35110a0c0b0600000000000000000c2e0600000000000000000c3038060c180a2e0a012303ce0105840338100600000000000000002103d30105f2010a000a010a2e1738080c150b000d150d180a010a2e170600000000000000000906000000000000000006000000000000000038130c1d0c1a0a2b0b15380a0b2e0b1d160c2e0b300b1a160c3005840338110c0d0a2b0a0d0811150c0c0a010a2e17350a0b180a0c1a340c050b050a222303880205a7020a000a010a2e1738080c110b000d110d180a010a2e170600000000000000000906000000000000000006000000000000000038130c1e0c1b0a2b0b11380a0b2e0b1e160c2e0b300b1b160c300584030a0b0a0c11000c200c260a000a010a2e1738080c120a000d120d180a010a2e17060000000000000000080b26340b203438130c320c340a2b0b12380a0b2e0b32160c2e0b300b34160c300a2e0a012303d1020583030a010a2e17350a0b180b0c1a340c060a000807060b0d340a06320000000000000000000000000000000038120c2a0c070a07340b062503ee020b0001061111000000000000270a2a340a010a2e172503f9020b0001062222000000000000270b2e0b2a34160c2e0b300b0734160c3005c9010b2e0b0121038a030707270b300b02260390030708270b2b0b18380d05d0030b2703970305b2030a000a0138080c1338060c170a000d130d170b010b0209060000000000000000060000000000000000381301010b0011030c2c0a2c0b17380d0b2c0b13380a05d0030b2303b50305cc030b000907050600000000000000000a013200000000000000000000000000000000380c0c290c090b09340b012103c5030707270b29340b022603d0030708270b0001070c270200"; - let res = run_binary_test("sample_router", code); - assert!(res.is_ok(), "{:?}", res) -} - -#[test] -fn sample_pool() { - let code = "a11ceb0b050000000c010020022079039901c90204e2036605c804fd0507c50aa80c08ed166006cd17c101108e19bb020ac91bd4020c9d1eb3250dd043340000010101020103010401050106010701080109010a020b000c000d000e000f0010070000110600001206000013060000140600001508000000040000160800001708000018060000190600001a0600001b0600071d07000b2707000b3a0700053c040106010344040100010245080009470402030100010b480400084e0402030100010b6c07000e7807000e7b07000e7e07000e80010700001c000100001e020100001f030100002002010000210201000022020100002300010000240201000025040100002605010000280607000029080100002a090100002b0a0100002c0b01000658050d0008590f07020300045a101000085b1213020300045c101000035d15160100035e17010100035f1810010005601a0101060b611e1c000b621f06000b632010000b64212200096524010203000a66250101000867122a0203000a682c2d01000a672e2f01000967312a0203000b69320100096a3301020300036b340101000d6d393a000c6d393a0009593b070203000b6e1c3c000b6f3d10000b703d10000b713d0d0003723e16010007733f1d000d74393a000c74393a000975013302030408654401020300087501460203040176054701060b7706100008790f490203000e7a4b4a000e7c4c4d000f7d4e0101040e7f3951000e81010e5300100e1011121114141514161417191c231d1c17261728120e1e111f2b202b12302123232324141735173617371f1c201c27232c1417403023103031303111310e17453211320e32303345333733263319333533363328334035303511384d384a3851350e385303060c04030006060c040a050a080d0a080d0a0306060c04020303030b060c020a050a080d0a080d0a03030303030201060c01080e010103060c05080d02060c0407060c03030303030302060c05040b11010812070805070806070808010502050a0402060b150209000901090001030204080602070b15020900090109000107090101081202060c03010b1101090002070b110109000b1101090001060b1101090001080202070b100109000900070708050303070806070808080f0a080f01080f01080d0405080d080d030305080d080d0205080f03060c080f0301081402080f081403070b1302090009010900090102070a09000a0900010803030708050708060708080108041a06040604030b1101081205080d070a0405020307080503030303030307080803080f0a080f0b1302080f0814040302070a04010901010402060a090006090002010302070a0900030109000208000a0402070b130209000901090002060c0814010b13020900090102050b1101090001080c01080b0108092c03030303030816050405080d040302030a080f0303030503080d03070b1001080a020b11010812030307080503030303030303070806070b150204080603060816030503080f0a080f0503030303030602030303030302060b13020900090109000108160106081602070b1101090003010a0201080a2b03030303030816050405080d040302030a080f0303030503080d03070b1001080a020b110108120307080503030303030303070806070b150204080603060816030503080f0a080f08070805030303070806070808080f0a080f0d01050b1101081206080d060507080507040303070808080f0a080f0b1302080f081403070b15020900090109000901010801010b150209000901010b10010900080800030403060a040608060708080a0817010609010108170d05030305080d020303020a080f0304030405080d0a040a081701081802060c09000206080607080817030303020303030303020303030303020303030303030301081902060a0407080801081a04506f6f6c076163636f756e740a6170746f735f636f696e04636f696e056572726f72056576656e74067369676e657206737472696e67057461626c65117461626c655f776974685f6c656e67746806766563746f7205746f6b656e104578706f6e656e7469616c43757276650b4c696e6561724375727665054d6f64656c04566965770c436f6c6c656374696f6e49640f437265617465506f6f6c4576656e74144465706f736974436f696e506f6f6c4576656e74154465706f736974546f6b656e506f6f6c4576656e740d45646974506f6f6c4576656e740a4576656e7453746f726508506f6f6c4775696405506f6f6c730f52656d6f7665506f6f6c4576656e7409537761704576656e74155769746864726177436f696e506f6f6c4576656e74165769746864726177546f6b656e506f6f6c4576656e740b4465706f736974436f696e06537472696e670c4465706f736974546f6b656e0845646974506f6f6c0a52656d6f7665506f6f6c1753776170436f696e466f7253706563696669634e4654730f537761704e465473466f72436f696e0c5769746864726177436f696e0d5769746864726177546f6b656e066372656174650b696e69745f6d6f64756c650b546f6b656e4461746149640a69735f6572633131353515766965775f636f6c6c656374696f6e5f706f6f6c7309766965775f706f6f6c0f766965775f70726963655f63616c630f766965775f757365725f706f6f6c7312636f6c6c656374696f6e5f63726561746f720f636f6c6c656374696f6e5f6e616d650763726561746f7207706f6f6c5f69640a73706f745f70726963650563757276650564656c7461116c705f6665655f6d756c7469706c69657204747970650673656e646572136465706f7369745f636f696e5f616d6f756e7405636f696e7309746f6b656e5f69647307546f6b656e49640b6372656174655f706f6f6c0b4576656e7448616e646c650b72656d6f76655f706f6f6c126465706f7369745f746f6b656e5f706f6f6c116465706f7369745f636f696e5f706f6f6c1377697468647261775f746f6b656e5f706f6f6c1277697468647261775f636f696e5f706f6f6c09656469745f706f6f6c047377617004436f696e094170746f73436f696e06746f6b656e730f5461626c65576974684c656e67746805546f6b656e0c7472616e73616374696f6e7317746f74616c5f7472616e73616374696f6e5f76616c75650f6c705f6665655f6561726e696e677305636f756e7405706f6f6c73055461626c650a757365725f706f6f6c7310636f6c6c656374696f6e5f706f6f6c730b636f696e5f616d6f756e740c70726f746f636f6c5f6665650e70726f746f636f6c5f70617965650b726f79616c74795f6665650d726f79616c74795f7061796565066c705f6665651477697468647261775f636f696e5f616d6f756e740a616464726573735f6f6608636f6e7461696e7310696e76616c69645f617267756d656e740a626f72726f775f6d7574117065726d697373696f6e5f64656e696564087769746864726177056d657267650576616c75650a656d69745f6576656e74136372656174655f746f6b656e5f69645f726177146372656174655f746f6b656e5f646174615f69640a62616c616e63655f6f660e77697468647261775f746f6b656e0361646406617070656e640672656d6f766508696e6465785f6f660d6465706f7369745f746f6b656e0d64657374726f795f656d707479076465706f73697407526f79616c74790a676574427579496e666f0b6765745f726f79616c7479176765745f726f79616c74795f64656e6f6d696e61746f72156765745f726f79616c74795f6e756d657261746f72116765745f726f79616c74795f7061796565076578747261637404757466380b67657453656c6c496e666f036e6577106e65775f6576656e745f68616e646c65156765745f746f6b656e646174615f6d6178696d756d08506f6f6c5669657706626f72726f7709706f6f6c5f7669657713436f6c6c656374696f6e506f6f6c735669657715636f6c6c656374696f6e5f706f6f6c735f7669657704766965770d507269636543616c63566965770f70726963655f63616c635f766965770d55736572506f6f6c73566965770f757365725f706f6f6c735f76696577ecb44cec6276ddc5860a13b976262c786e06af8f7306923cabec17808dabf0940000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000303086600000000000000030869000000000000000308680000000000000003086e000000000000000308670000000000000003086a0000000000000003086b0000000000000003086c000000000000000308650000000000000003086d000000000000000520ecb44cec6276ddc5860a13b976262c786e06af8f7306923cabec17808dabf09403086400000000000000052000000000000000000000000000000000000000000000000000000000000000000a0204036275790a02050473656c6c126170746f733a3a6d657461646174615f7630a6020a6500000000000000074552525f4e554d006600000000000000134552525f444946465f434f4c4c454354494f4e006700000000000000124552525f4e4f545f45584953545f504f4f4c006800000000000000154552525f494e56414c49445f504f4f4c5f54595045006900000000000000154552525f494e56414c49445f504f4f4c5f41524753006a000000000000001c4552525f4e4f545f4558495453545f544f4b454e5f494e5f504f4f4c006b00000000000000124552525f4e4f545f484156455f544f4b454e006c00000000000000144552525f4e4f545f504f4f4c5f43524541544f52006d00000000000000184552525f504f4f4c5f4e4f545f454e4f5547485f434f494e006e00000000000000114552525f49535f313135355f544f4b454e000002022d052e080d0102092f0530042d052e080d3103320233033403350202020a360530042d052e080d37033803310332023303340303020a360530042d052e080d390a080f3803310332023303340304020730042d052e080d31033202330334030502083b0b100108013d0b100108093e0b100108033f0b10010802400b1001080c410b1001080b420b10010804430b1001080a06020e2f053103380b11010812460b1302080f08142d052e080d3202330334033502390a080f49034a044b030702014c040802034d0b15020408064f0b1502050a04500b150208000a0409020c2f0530042d052e080d3103320233033403350249034a044b030a0210360530042d052e080d310332023303390a080f510352035305540355055603380335080d0b020a360530042d052e080d5703380331033202330334030c020a360530042d052e080d390a080f380331033202330334030001000205080c61070a2a080c06070a2a050c040a0610000a00110f3800040d05160b00010b06010b040107041111270a0610010a013801041c05250b00010b06010b040107041111270b060f010a0138020c050a051002140a00110f210432053b0b00010b05010b040107071113270a000a0238030c030a050f030b0338040b040f040b00110f0b010a051005140a051006140b020a05100338050a051007140a051008140a051009140b05100a1412023806020101000205081bd801070a2a080c0a070a2a050c060a0a10000a00110f3800040d05160b00010b0a010b060107041111270a0a10010a013801041c05250b00010b0a010b060107041111270b0a0f010a0138020c09401c00000000000000000c0c0a091002140a00110f210434053d0b00010b09010b060107071113270e02410d0c080600000000000000000c070a070a082304b60105470e020a07420d0a09100521044f05580b00010b09010b060107001111270e030a07421d0a09100621046005690b00010b09010b060107001111270e020a07420d140e030a07421d140e040a07421d140e050a0742101411180c0b0e020a07420d140e030a07421d140e040a07421d141119110a20048c010595010b00010b09010b060107031111270d0c0a0b441c0a00110f0a0b111a0601000000000000002604a00105a9010b00010b09010b060107061111270a090f0b0a0b0a000b0b060100000000000000111b38070b07060100000000000000160c0705420a090f0c0a0c38080b060f0d0b00110f0b010a091005140a091006140b0c0a09100338050a091007140a091008140a091009140b09100a1412033809020201000205082759070a2a080c08070a2a050c060a0810000a00110f3800040d05160b00010b08010b060107041111270a0810010a013801041c05250b00010b08010b060107041111270b080f010a0138020c070a071002140b00110f21043205390b07010b060107071113270a020a070f08150a040a070f09150a030a070f07150a050a070f0a150b060f0e0b010a071005140b071006140b030b020b040b051204380a0203010002050829dc01070a2a080c17070a2a050c100a1710000a00110f3800040d05160b00010b17010b100107041111270a170f000a00110f380b0c1f0a1710010a0138010422052d0b1f010b00010b17010b100107041111270a170f010a01380c13060c150c1c0c1d010c1e0c160c0f0c0e0c0b0c0a0c1b0c090c180c0d0a0d0a00110f21044605510b1f010b00010b17010b100107071113270a1f0e010c062e0b06380d0c12010b1f0b12380e010b170f0f0a0a0a0b1200380f0c0c0a0c0e010c072e0b07380d0c13046d05760b00010b10010b0c0107051111270b0c0b13380e010600000000000000000c110e02410d0c14401c00000000000000000c1a0a110a142304a5010586010e020a11420d140e030a11421d140e040a11421d140e050a1142101411180c190d1a0a19441c0a000d1b0b19381011220b11060100000000000000160c110581010b1b38110e0938050c080a00110f0b0938120a100f100a0d0a010a0a0a0b0b1a0600000000000000000600000000000000003100060000000000000000060000000000000000120c38130a100f110b0d0a010a0a0a0b0b080600000000000000000600000000000000003100060000000000000000060000000000000000120b38140b100f120b00110f0b010b0a0b0b0b180b0e0b0f0b160b1e0b1d0b1c0b15120938150204010002050838d502070a2a080f010c2a070a2a050c210a2a0a010c102e0b103801040f05180b00010b2a010b210107041111270e02410d0c270b2a0a0138020c290a2910081431012104380a291007140a291009140a270a29100a14070b11250c0a0c090c080c070c060c1d055a0a29100814310221043f05480b00010b29010b210107021111270a291007140a291009140a270a29100a14070b11260c0a0c090c080c070c060c1d0b1d0b060b070b080b090b0a0c240c2b0c1f0c250c26310021046905720b00010b29010b21010701111127070c0600000000000000000600000000000000000c2f0c2d0c2e0b260a290f07150b250a290f0915401c00000000000000000c310a000a1f38030c1e0600000000000000000c220a220a272304f401058d010e020a22420d140e030a22421d140e040a22421d140e050a2242101411180c300a29100c0e3038160c2304a60105af010b00010b29010b210107051111270a290f0c0b233817010d310a30441c0a29100b0a30381804bd0105c6010b00010b29010b210107051111270a000a290f0b0a30381011220b3011280c0b0e0b0c2c0a2c11290c200a2c112a0c280b2c112b0c2e0a200600000000000000002204ef010a1f0a271a0b28180b201a0c2d0b2f0a2d160c2f0a2e0d1e0a2d381938120b22060100000000000000160c220588010a291013140a1f35160a290f13150a29101414060100000000000000160a290f1415070a0d1e0a2b381938120a290f030b1e38040b210f150c1c0b00110f0c0c0b010c0d0a291005140c0e0a291006140c0f0a291007140c110a291008140c120a291009140c130b310c140b1f0a2b160b2d160c150b2b0c160b2f0c170b2e0c180b240c19070d112d0c1a0b29100338050c1b0b1c0b0c0b0d0b0e0b0f0b110b120b130b140b150b16070a0b170b180b190b1b0b1a120a381a02050100020508418c03070a2a080f010c29070a2a050c200a290a010c102e0b103801040f05180b00010b29010b200107041111270e02410d0c250b290a0138020c280a2810081431012104380a281007140a281009140a250a28100a14070b112e0c0a0c090c080c070c060c1d055a0a28100814310221043f05480b00010b28010b200107021111270a281007140a281009140a250a28100a14070b112f0c0a0c090c080c070c060c1d0b1d0b060b070b080b090b0a0c220c2a0c270c230c24310021046905720b00010b28010b20010701111127070c0600000000000000000600000000000000000c2e0c2c0c2d401c00000000000000000c300a280f030a270a2a1738190c1e0600000000000000000c210a210a2523049a020588010e020a21420d0a281005210490010599010b00010b28010b200107001111270e030a21421d0a2810062104a10105aa010b00010b28010b200107001111270e020a21420d140e030a21421d140e040a21421d140e050a2142101411180c2f0e020a21420d140e030a21421d140e040a21421d141119110a2004cd0105d6010b00010b28010b200107031111270d300a2f441c0a00110f0a2f111a0601000000000000002604e10105ea010b00010b28010b200107061111270a280f0b0a2f0a000a2f060100000000000000111b38070b2f11280c0b0e0b0c2b0a2b11290c1f0a2b112a0c260b2b112b0c2d0a1f060000000000000000220495020a270a251a0b26180b1f1a0c2c0b2e0a2c160c2e0a2d0d1e0a2c381938120b21060100000000000000160c210583010a280f0c0a303808070a0a280f030a2a381938120b240a280f07150b230a280f09150a00110f0b1e38120a281013140a270a2a170b2e1735160a280f13150a28101414060100000000000000160a280f14150b200f150c1c0b00110f0c0c0b010c0d0a281005140c0e0a281006140c0f0a281007140c110a281008140c120a281009140c130b300c140b270a2a170a2c170c150b2a0c160b2c0c170b2d0c180b220c19070e112d0c1a0b28100338050c1b0b1c0b0c0b0d0b0e0b0f0b110b120b130b140b150b16070a0b170b180b190b1b0b1a120a381a020601000205082770070a2a080c05070a2a050c030a0510000a00110f3800040d05160b00010b05010b030107041111270a0510010a013801041c05250b00010b05010b030107041111270b050f010a0138020c040a041002140a00110f210432053b0b00010b04010b030107071113270a04100338050a02260442054b0b00010b04010b030107091111270a00110f0a040f030a02381938120b030f110b00110f0b010a041005140a041006140b020a04100338050a041007140a041008140a041009140b04100a14120b38140207010002050842a901070a2a080c0b070a2a050c060a0b10000a00110f3800040d05160b00010b0b010b060107041111270a0b10010a013801041c05250b00010b0b010b060107041111270b0b0f010a0138020c0a401c00000000000000000c0d0a0a1002140a00110f210434053d0b00010b0a010b060107071113270e02410d0c090600000000000000000c070a070a0923048b0105470e020a07420d140e030a07421d140e040a07421d140e050a0742101411180c0c0a0a100c0e0c38160c08046005690b00010b0a010b060107051111270a0a0f0c0b083817010d0d0a0c441c0a0a100b0a0c381804770580010b00010b0a010b060107051111270a000a0a0f0b0b0c381011220b07060100000000000000160c0705420b060f100b00110f0b010a0a1005140a0a1006140b0d0a0a100338050a0a1007140a0a1008140a0a1009140b0a100a14120c38130208010003050708439f02070a2a080c14070a2a070f160c11070a2a050c10381b0c170e02410d0c130a13060000000000000000240414051f0b00010b14010b11010b100107081111270e02060000000000000000420d0c0f0e03060000000000000000421d0c0e0a14100f0a0f140a0e141200381c20043a0a140f0f0a0f140a0e141200402b0000000000000000381d0a140f0f0a0f140a0e141200380f0a1114442b401c00000000000000000c160600000000000000000c120a120a132304b001054e0a0f0e020a12420d21045b0a0e0e030a12421d210c0b055d090c0b0b0b0460056f0b00010b14010b11010b10010b0f010b0e0107001111270e020a12420d140e030a12421d140e040a12421d141119110a20048001058f010b00010b14010b11010b10010b0f010b0e0107031111270e020a12420d140e030a12421d140e040a12421d140e050a1242101411180c150d160a15441c0d170a150a000b15060100000000000000111b38070b12060100000000000000160c1205490a100f0d0a00110f0a11140a0f140a0e140a160a060a070a010a080a09120338090a000a0638030c0d0a100f040a00110f0a11140a0f140a0e140a060b060a070a010a080a09120238060a140f010a11140a00110f0a070b0d0b170a0f140a0e140a010a080a090a0a0b1606000000000000000032000000000000000000000000000000000600000000000000001206381e0a140f000a00110f0c0c2e0b0c38002004ff010a140f000a00110f402b0000000000000000381f0b140f000a00110f380b0a1114442b0b100f170b00110f0a11140b0f140b0e140b070b010b080b090b0a120138200a11143201000000000000000000000000000000160b11150209000000011e0a0038213822382312082d080a00320000000000000000000000000000000012072d070a000a0038240a0038250a0038260a0038270a0038280a0038290a00382a0b00382b12052d05020a00000001060601000000000000000b0011342120020b010401084876070a2a080c090a010a0212000c030a09100f0a03381c040d05130b00010b0901063f05000000000000270a09100f0b03382c0c07404a00000000000000000c0a0a07412b0c060600000000000000000c040a040a0623046b05240a070a04422b140c050a0910010a053801042f05370b00010b09010b0701063f05000000000000270a0910010b05382d0c080d0a0a081002140a081007140a08100338050a081005140a081006140a081008140a081009140a08100a140a081018140a08100c140a081014140a081013140b081019141136444a0b04060100000000000000160c04051f0b09010b000b010b020b07140b0a1137382e020c010401084f40070a2a080c030a0310010a013801040905100b00010b030107041111270b0310010b01382d0c020b000a021002140a021007140a02100338050a021005140a021006140a021008140a021009140a02100a140a021018140a02100c140a021014140a021013140b021019141136382f020d0104005087010b010600000000000000002104380a020601000000000000002104150b030b040b050b06070b11250c090c080c070c180c170c16052b0b0206020000000000000021041a051f0b000107021111270b030b040b050b06070b11260c090c080c070c180c170c160b160b170b180b070b080b090c150c140c130c120c110c10056b0a020601000000000000002104490b030b040b050b06070b112e0c0f0c0e0c0d0c0c0c0b0c0a055f0b0206020000000000000021044e05530b000107021111270b030b040b050b06070b112f0c0f0c0e0c0d0c0c0c0b0c0a0b0a0b0b0b0c0b0d0b0e0b0f0c150c140c130c120c110c100b100b110b120b130b140b150c1a0c1d0c190c1b0c1c310021047a057e0b0001064705000000000000270b000b1c0b1b0b190b1d0b1a11393830020e01040108521b070a2a080c030a0310000a0138000409050f0b00010b0301063f05000000000000270b0310000a0138310c020b000b010b0214113a383202080108000600060205030604060506010606060706080603060a050205060802050405050501060c060b0507070005000609060d00"; - let res = run_binary_test("sample_pool", code); - assert!(res.is_ok(), "{:?}", res) -} - -#[test] -fn sample_farming() { - let code = "a11ceb0b050000000e01001e021e2603447c04c00158059802c80107e003bb04089b08a00106bb09e101109c0b780a940c3e0bd20c040cd60cd10d0da71a080eaf1a060000010101020103010401050106000700080209020a0309030a0409040a000b0800000c0e0200010001000d0c0200010001011106000513070002230401000107240000000e000100000f0201020000032104050001220607000525090a000e26010c0200000c26010c0200000a26010c0200000427001200022812140100022915160100022a17010100082b150101000d2c1a010200000b2c1a01020000092c1a010200000d2d1b010200000b2d1b01020000092d1b01020000062e011400050b050d050e050f05100511060b060d060e060f06100611070b070d070e070f0710071109130a130b1309180a180b1809190a190b190c130c180d0b0e0b0f0b0d0d0e0d0f0d0d0e0d100e0e0e100f0e0f10100b110b120b01060c0009060c0303030303030303020c080302060c0501080301060803010c2001010101010101010101030303030308040b050108060b050109000b050109010708000b0102090009010b0102090009010b020209000901070b020209000901050c0a0b0102090009010503030303010a0201080402090009010101020901090002080609000209000806020806090102090108060105010900010302060c03010b0501090002050b0501090001090101080603060c030305060c03030303010b010209000901076661726d696e67076163636f756e7404636f696e107265736f757263655f6163636f756e74067369676e657206737472696e670974696d657374616d700d6661756365745f746f6b656e73076c656e64696e6706726f7574657204737761700a4d6f64756c65446174610c506f736974696f6e496e666f0f506f736974696f6e496e666f4465780b696e69745f6d6f64756c65166c657665726167655f7969656c645f6661726d696e670a7369676e65725f636170105369676e65724361706162696c697479086465785f6e616d6506537472696e670b7369676e65725f616464720a637265617465645f617406737461747573086c657665726167650e737570706c79416d6f756e745f780e737570706c79416d6f756e745f790e737570706c79416d6f756e745f7a0e626f72726f77416d6f756e745f780e626f72726f77416d6f756e745f790e626f72726f77416d6f756e745f7a10706f736974696f6e496e666f5f70616e10706f736974696f6e496e666f5f6c697110706f736974696f6e496e666f5f6175781d72657472696576655f7265736f757263655f6163636f756e745f6361701d6372656174655f7369676e65725f776974685f6361706162696c69747904436f696e03455a4d04757466380f69735f706169725f637265617465640a616464726573735f6f660762616c616e6365087769746864726177076465706f73697406626f72726f7710737761705f65786163745f696e7075740d6164645f6c69717569646974790b6e6f775f7365636f6e64734d63574ba8d90a5926e2866d8291e57683108a47b96d884232a871fe4feddf4100000000000000000000000000000000000000000000000000000000000000015e40a5bf7ab741784d3a99d96d8e2ddc6706ee06e5f509a3314a74c9e53746f5b30dd6a14dd7626ac8a37bc964914f07e3dc38d629637f1087f9f7186f1e0909c4911c40cf758ec21c0ebf0e547933ef6bb0f53ad581c08d2ecc7ad11364be1b030804000000000000000520f67b2452fd82768002ec6c28568713b9359a596585dc1a4bf85fce6b0e3754020308020000000000000003080300000000000000030801000000000000000308ffffffffffffffff0410e80300000000000000000000000000000308000000000000000005204d63574ba8d90a5926e2866d8291e57683108a47b96d884232a871fe4feddf41052000000000000000000000000000000000000000000000000000000000000000000a020c0b50616e63616b65537761700a020b0a4c6971756964537761700a020d0c4155582045786368616e6765126170746f733a3a6d657461646174615f763064030100000000000000164552524f525f4e4f545f435245415445445f50414952000200000000000000184552524f525f494e53554646494349454e545f4153534554000300000000000000174552524f525f494e56414c49445f504152414d5f4445580000020110080301020b1208041405150316011703180319031a031b031c031d030202031e0a0b0102090009011f0a0b010209000901200a0b010209000901020b010b00000000030c0b00070111020c020e0211030c010e010b0212002d000201010402000208ee04070a1104010a010600000000000000002103080536070a11040c183800030e0511080c09051338010c090b0903190b00010704273802031c051f080c0b052138030c0b0b0b03270b00010704273804032a052d080c0c052f38050c0c0b0c03350b0001070427059f010a0106010000000000000021033b0569070b11040c18380603410544080c0d054638070c0d0b0d034c0b00010704273808034f0552080c0e055438090c0e0b0e035a0b0001070427380a035d0560080c0f0562380b0c0f0b0f03680b0001070427059f010a0106020000000000000021036e059b01070c11040c18380c03740577080c100579380d0c100b10037f0b0001070427380e038201058501080c11058701380f0c110b11038d010b00010704273810039001059301080c1205950138110c120b12039f010b00010704270b000107032707082a000c1c0b1c100011030c220e2211080c210a030600000000000000002403ae0105c1010a00110838120c160b160a032403ba010b00010702270a000a0338130c1a07080b1a38140a040600000000000000002403c60105d9010a00110838150c170b170a042403d2010b00010702270a000a0438160c1b07080b1b38170a050600000000000000002403de0105f1010a00110838180c150b150a052403ea010b00010702270a000a0538190c1907080b19381a0a060600000000000000002403f60105f9010e220a06381b0a070600000000000000002403fe010581020e220a07381c0a0806000000000000000024038502070838120c26070838150c280a030a06160602000000000000001a0600000000000000002403940205bd020a010600000000000000002103990205a2020e220a030a06160602000000000000001a060000000000000000381d05bd020a010601000000000000002103a70205b0020e220a030a06160602000000000000001a060000000000000000381e05bd020a010602000000000000002103b50205bd020e220a030a06160602000000000000001a060000000000000000381f0a040a07160602000000000000001a0600000000000000002403c60205ef020a010600000000000000002103cb0205d4020e220a040a07160602000000000000001a060000000000000000382005ef020a010601000000000000002103d90205e2020e220a040a07160602000000000000001a060000000000000000382105ef020a010602000000000000002103e70205ef020e220a040a07160602000000000000001a06000000000000000038220a050a08160602000000000000001a0600000000000000002403f80205b9030a010600000000000000002103fd02058e030e220a050a08160602000000000000001a06000000000000000038230e220a050a08160602000000000000001a060000000000000000382405b9030a010601000000000000002103930305a4030e220a050a08160602000000000000001a06000000000000000038250e220a050a08160602000000000000001a060000000000000000382605b9030a010602000000000000002103a90305b9030e220a050a08160602000000000000001a06000000000000000038270e220a050a08160602000000000000001a0600000000000000003828070838120c25070838150c270a030b25160b26170c130a040b27160b28170c140a130600000000000000002403d00305d5030a14060000000000000000240c0a05d703090c0a0b0a03da0305eb040a010600000000000000002103df0305e6030e220b130b14060000000000000000060000000000000000382905fd030a010601000000000000002103eb0305f2030e220b130b14060000000000000000060000000000000000382a05fd030a010602000000000000002103f70305fd030e220b130b14060000000000000000060000000000000000382b0b0011080c240a213b002003850405ba040b180b241113080b020b030b040b050b060b070b0839010c1d401c000000000000000001401c0000000000000000401c0000000000000000401c000000000000000039000c1f0a0106000000000000000021039e0405a3040d1f36000b1d441c05b6040a010601000000000000002103a80405ad040d1f36010b1d441c05b6040b010602000000000000002103b20405b6040d1f36020b1d441c0e220b1f3f0005ea040b213c000c200b180b241113080b020b030b040b050b060b070b0839010c1e0a010600000000000000002103cf0405d4040b2036000b1e441c05ea040a010601000000000000002103d90405de040b2036010b1e441c05ea040b010602000000000000002103e30405e8040b2036020b1e441c05ea040b200105ed040b0001020000020002010202010b020b030b00"; - let res = run_binary_test("sample_farming", code); - assert!(res.is_ok(), "{:?}", res) -} - -#[test] -fn sample_whitelist() { - let code = "a11ceb0b050000000c01000602060c03123a044c0805545707ab01660891024006d102988b0210e98d02d7010ac08f02090cc98f02a2470debd6020200000101010200030800020a04020301000100040001000005020100000603040000070201000008000100010b0203000204070102030002060a04020300020c010c02030402080d0e020300060607060806090602060c050001060c01050101020507080002050203070b010209000901090009010305070b010205020708000106080002060b0102090009010900010b01020502010b01020900090102070b01020900090109000109010977686974656c697374067369676e6572057461626c650957686974656c69737403616464086164645f6d616e7908636f6e7461696e730a696e697469616c697a650672656d6f766507656e7472696573055461626c650a616464726573735f6f66036e65774419523fdfa01e96fc7c18b67d900be8c863459e25383a5c661b9523631811c1000000000000000000000000000000000000000000000000000000000000000103082003000000000000030822030000000000000308210300000000000005204419523fdfa01e96fc7c18b67d900be8c863459e25383a5c661b9523631811c1052000000000000000000000000000000000000000000000000000000000000000000520000000000000000000000000000000000000000000000000000000000000000105200000000000000000000000000000000000000000000000000000000000000002052000000000000000000000000000000000000000000000000000000000000000030520000000000000000000000000000000000000000000000000000000000000000405200000000000000000000000000000000000000000000000000000000000000005052000000000000000000000000000000000000000000000000000000000000000060520000000000000000000000000000000000000000000000000000000000000000705200000000000000000000000000000000000000000000000000000000000000008052000000000000000000000000000000000000000000000000000000000000000090520000000000000000000000000000000000000000000000000000000000000001005200000000000000000000000000000000000000000000000000000000000000011052000000000000000000000000000000000000000000000000000000000000000120520000000000000000000000000000000000000000000000000000000000000001305200000000000000000000000000000000000000000000000000000000000000014052000000000000000000000000000000000000000000000000000000000000000150520000000000000000000000000000000000000000000000000000000000000001605200000000000000000000000000000000000000000000000000000000000000017052000000000000000000000000000000000000000000000000000000000000000180520000000000000000000000000000000000000000000000000000000000000001905200000000000000000000000000000000000000000000000000000000000000020052000000000000000000000000000000000000000000000000000000000000000210520000000000000000000000000000000000000000000000000000000000000002205200000000000000000000000000000000000000000000000000000000000000023052000000000000000000000000000000000000000000000000000000000000000240520000000000000000000000000000000000000000000000000000000000000002505200000000000000000000000000000000000000000000000000000000000000026052000000000000000000000000000000000000000000000000000000000000000270520000000000000000000000000000000000000000000000000000000000000002805200000000000000000000000000000000000000000000000000000000000000029052000000000000000000000000000000000000000000000000000000000000000300520000000000000000000000000000000000000000000000000000000000000003105200000000000000000000000000000000000000000000000000000000000000032052000000000000000000000000000000000000000000000000000000000000000330520000000000000000000000000000000000000000000000000000000000000003405200000000000000000000000000000000000000000000000000000000000000035052000000000000000000000000000000000000000000000000000000000000000360520000000000000000000000000000000000000000000000000000000000000003705200000000000000000000000000000000000000000000000000000000000000038052000000000000000000000000000000000000000000000000000000000000000390520000000000000000000000000000000000000000000000000000000000000004005200000000000000000000000000000000000000000000000000000000000000041052000000000000000000000000000000000000000000000000000000000000000420520000000000000000000000000000000000000000000000000000000000000004305200000000000000000000000000000000000000000000000000000000000000044052000000000000000000000000000000000000000000000000000000000000000450520000000000000000000000000000000000000000000000000000000000000004605200000000000000000000000000000000000000000000000000000000000000047052000000000000000000000000000000000000000000000000000000000000000480520000000000000000000000000000000000000000000000000000000000000004905200000000000000000000000000000000000000000000000000000000000000050052000000000000000000000000000000000000000000000000000000000000000510520000000000000000000000000000000000000000000000000000000000000005205200000000000000000000000000000000000000000000000000000000000000053052000000000000000000000000000000000000000000000000000000000000000540520000000000000000000000000000000000000000000000000000000000000005505200000000000000000000000000000000000000000000000000000000000000056052000000000000000000000000000000000000000000000000000000000000000570520000000000000000000000000000000000000000000000000000000000000005805200000000000000000000000000000000000000000000000000000000000000059052000000000000000000000000000000000000000000000000000000000000000600520000000000000000000000000000000000000000000000000000000000000006105200000000000000000000000000000000000000000000000000000000000000062052000000000000000000000000000000000000000000000000000000000000000630520000000000000000000000000000000000000000000000000000000000000006405200000000000000000000000000000000000000000000000000000000000000065052000000000000000000000000000000000000000000000000000000000000000660520000000000000000000000000000000000000000000000000000000000000006705200000000000000000000000000000000000000000000000000000000000000068052000000000000000000000000000000000000000000000000000000000000000690520000000000000000000000000000000000000000000000000000000000000007005200000000000000000000000000000000000000000000000000000000000000071052000000000000000000000000000000000000000000000000000000000000000720520000000000000000000000000000000000000000000000000000000000000007305200000000000000000000000000000000000000000000000000000000000000074052000000000000000000000000000000000000000000000000000000000000000750520000000000000000000000000000000000000000000000000000000000000007605200000000000000000000000000000000000000000000000000000000000000077052000000000000000000000000000000000000000000000000000000000000000780520000000000000000000000000000000000000000000000000000000000000007905200000000000000000000000000000000000000000000000000000000000000080052000000000000000000000000000000000000000000000000000000000000000810520000000000000000000000000000000000000000000000000000000000000008205200000000000000000000000000000000000000000000000000000000000000083052000000000000000000000000000000000000000000000000000000000000000840520000000000000000000000000000000000000000000000000000000000000008505200000000000000000000000000000000000000000000000000000000000000086052000000000000000000000000000000000000000000000000000000000000000870520000000000000000000000000000000000000000000000000000000000000008805200000000000000000000000000000000000000000000000000000000000000089052000000000000000000000000000000000000000000000000000000000000000900520000000000000000000000000000000000000000000000000000000000000009105200000000000000000000000000000000000000000000000000000000000000092052000000000000000000000000000000000000000000000000000000000000000930520000000000000000000000000000000000000000000000000000000000000009405200000000000000000000000000000000000000000000000000000000000000095052000000000000000000000000000000000000000000000000000000000000000960520000000000000000000000000000000000000000000000000000000000000009705200000000000000000000000000000000000000000000000000000000000000098052000000000000000000000000000000000000000000000000000000000000000990520000000000000000000000000000000000000000000000000000000000000010005200000000000000000000000000000000000000000000000000000000000000101052000000000000000000000000000000000000000000000000000000000000001020520000000000000000000000000000000000000000000000000000000000000010305200000000000000000000000000000000000000000000000000000000000000104052000000000000000000000000000000000000000000000000000000000000001050520000000000000000000000000000000000000000000000000000000000000010605200000000000000000000000000000000000000000000000000000000000000107052000000000000000000000000000000000000000000000000000000000000001080520000000000000000000000000000000000000000000000000000000000000010905200000000000000000000000000000000000000000000000000000000000000110052000000000000000000000000000000000000000000000000000000000000001110520000000000000000000000000000000000000000000000000000000000000011205200000000000000000000000000000000000000000000000000000000000000113052000000000000000000000000000000000000000000000000000000000000001140520000000000000000000000000000000000000000000000000000000000000011505200000000000000000000000000000000000000000000000000000000000000116052000000000000000000000000000000000000000000000000000000000000001170520000000000000000000000000000000000000000000000000000000000000011805200000000000000000000000000000000000000000000000000000000000000119052000000000000000000000000000000000000000000000000000000000000001200520000000000000000000000000000000000000000000000000000000000000012105200000000000000000000000000000000000000000000000000000000000000122052000000000000000000000000000000000000000000000000000000000000001230520000000000000000000000000000000000000000000000000000000000000012405200000000000000000000000000000000000000000000000000000000000000125052000000000000000000000000000000000000000000000000000000000000001260520000000000000000000000000000000000000000000000000000000000000012705200000000000000000000000000000000000000000000000000000000000000128052000000000000000000000000000000000000000000000000000000000000001290520000000000000000000000000000000000000000000000000000000000000013005200000000000000000000000000000000000000000000000000000000000000131052000000000000000000000000000000000000000000000000000000000000001320520000000000000000000000000000000000000000000000000000000000000013305200000000000000000000000000000000000000000000000000000000000000134052000000000000000000000000000000000000000000000000000000000000001350520000000000000000000000000000000000000000000000000000000000000013605200000000000000000000000000000000000000000000000000000000000000137052000000000000000000000000000000000000000000000000000000000000001380520000000000000000000000000000000000000000000000000000000000000013905200000000000000000000000000000000000000000000000000000000000000140052000000000000000000000000000000000000000000000000000000000000001410520000000000000000000000000000000000000000000000000000000000000014205200000000000000000000000000000000000000000000000000000000000000143052000000000000000000000000000000000000000000000000000000000000001440520000000000000000000000000000000000000000000000000000000000000014505200000000000000000000000000000000000000000000000000000000000000146052000000000000000000000000000000000000000000000000000000000000001470520000000000000000000000000000000000000000000000000000000000000014805200000000000000000000000000000000000000000000000000000000000000149052000000000000000000000000000000000000000000000000000000000000001500520000000000000000000000000000000000000000000000000000000000000015105200000000000000000000000000000000000000000000000000000000000000152052000000000000000000000000000000000000000000000000000000000000001530520000000000000000000000000000000000000000000000000000000000000015405200000000000000000000000000000000000000000000000000000000000000155052000000000000000000000000000000000000000000000000000000000000001560520000000000000000000000000000000000000000000000000000000000000015705200000000000000000000000000000000000000000000000000000000000000158052000000000000000000000000000000000000000000000000000000000000001590520000000000000000000000000000000000000000000000000000000000000016005200000000000000000000000000000000000000000000000000000000000000161052000000000000000000000000000000000000000000000000000000000000001620520000000000000000000000000000000000000000000000000000000000000016305200000000000000000000000000000000000000000000000000000000000000164052000000000000000000000000000000000000000000000000000000000000001650520000000000000000000000000000000000000000000000000000000000000016605200000000000000000000000000000000000000000000000000000000000000167052000000000000000000000000000000000000000000000000000000000000001680520000000000000000000000000000000000000000000000000000000000000016905200000000000000000000000000000000000000000000000000000000000000170052000000000000000000000000000000000000000000000000000000000000001710520000000000000000000000000000000000000000000000000000000000000017205200000000000000000000000000000000000000000000000000000000000000173052000000000000000000000000000000000000000000000000000000000000001740520000000000000000000000000000000000000000000000000000000000000017505200000000000000000000000000000000000000000000000000000000000000176052000000000000000000000000000000000000000000000000000000000000001770520000000000000000000000000000000000000000000000000000000000000017805200000000000000000000000000000000000000000000000000000000000000179052000000000000000000000000000000000000000000000000000000000000001800520000000000000000000000000000000000000000000000000000000000000018105200000000000000000000000000000000000000000000000000000000000000182052000000000000000000000000000000000000000000000000000000000000001830520000000000000000000000000000000000000000000000000000000000000018405200000000000000000000000000000000000000000000000000000000000000185052000000000000000000000000000000000000000000000000000000000000001860520000000000000000000000000000000000000000000000000000000000000018705200000000000000000000000000000000000000000000000000000000000000188052000000000000000000000000000000000000000000000000000000000000001890520000000000000000000000000000000000000000000000000000000000000019005200000000000000000000000000000000000000000000000000000000000000191052000000000000000000000000000000000000000000000000000000000000001920520000000000000000000000000000000000000000000000000000000000000019305200000000000000000000000000000000000000000000000000000000000000194052000000000000000000000000000000000000000000000000000000000000001950520000000000000000000000000000000000000000000000000000000000000019605200000000000000000000000000000000000000000000000000000000000000197052000000000000000000000000000000000000000000000000000000000000001980520000000000000000000000000000000000000000000000000000000000000019905200000000000000000000000000000000000000000000000000000000000000200052000000000000000000000000000000000000000000000000000000000000002010520000000000000000000000000000000000000000000000000000000000000020205200000000000000000000000000000000000000000000000000000000000000203052000000000000000000000000000000000000000000000000000000000000002040520000000000000000000000000000000000000000000000000000000000000020505200000000000000000000000000000000000000000000000000000000000000206052000000000000000000000000000000000000000000000000000000000000002070520000000000000000000000000000000000000000000000000000000000000020805200000000000000000000000000000000000000000000000000000000000000209052000000000000000000000000000000000000000000000000000000000000002100520000000000000000000000000000000000000000000000000000000000000021105200000000000000000000000000000000000000000000000000000000000000212052000000000000000000000000000000000000000000000000000000000000002130520000000000000000000000000000000000000000000000000000000000000021405200000000000000000000000000000000000000000000000000000000000000215052000000000000000000000000000000000000000000000000000000000000002160520000000000000000000000000000000000000000000000000000000000000021705200000000000000000000000000000000000000000000000000000000000000218052000000000000000000000000000000000000000000000000000000000000002190520000000000000000000000000000000000000000000000000000000000000022005200000000000000000000000000000000000000000000000000000000000000221052000000000000000000000000000000000000000000000000000000000000002220520000000000000000000000000000000000000000000000000000000000000022305200000000000000000000000000000000000000000000000000000000000000224052000000000000000000000000000000000000000000000000000000000000002250520000000000000000000000000000000000000000000000000000000000000022605200000000000000000000000000000000000000000000000000000000000000227052000000000000000000000000000000000000000000000000000000000000002280520000000000000000000000000000000000000000000000000000000000000022905200000000000000000000000000000000000000000000000000000000000000230052000000000000000000000000000000000000000000000000000000000000002310520000000000000000000000000000000000000000000000000000000000000023205200000000000000000000000000000000000000000000000000000000000000233052000000000000000000000000000000000000000000000000000000000000002340520000000000000000000000000000000000000000000000000000000000000023505200000000000000000000000000000000000000000000000000000000000000236052000000000000000000000000000000000000000000000000000000000000002370520000000000000000000000000000000000000000000000000000000000000023805200000000000000000000000000000000000000000000000000000000000000239052000000000000000000000000000000000000000000000000000000000000002400520000000000000000000000000000000000000000000000000000000000000024105200000000000000000000000000000000000000000000000000000000000000242052000000000000000000000000000000000000000000000000000000000000002430520000000000000000000000000000000000000000000000000000000000000024405200000000000000000000000000000000000000000000000000000000000000245052000000000000000000000000000000000000000000000000000000000000002460520000000000000000000000000000000000000000000000000000000000000024705200000000000000000000000000000000000000000000000000000000000000248052000000000000000000000000000000000000000000000000000000000000002490520000000000000000000000000000000000000000000000000000000000000025005200000000000000000000000000000000000000000000000000000000000000251052000000000000000000000000000000000000000000000000000000000000002520520000000000000000000000000000000000000000000000000000000000000025305200000000000000000000000000000000000000000000000000000000000000254052000000000000000000000000000000000000000000000000000000000000002550520000000000000000000000000000000000000000000000000000000000000025605200000000000000000000000000000000000000000000000000000000000000257052000000000000000000000000000000000000000000000000000000000000002580520000000000000000000000000000000000000000000000000000000000000025905200000000000000000000000000000000000000000000000000000000000000260052000000000000000000000000000000000000000000000000000000000000002610520000000000000000000000000000000000000000000000000000000000000026205200000000000000000000000000000000000000000000000000000000000000263052000000000000000000000000000000000000000000000000000000000000002640520000000000000000000000000000000000000000000000000000000000000026505200000000000000000000000000000000000000000000000000000000000000266052000000000000000000000000000000000000000000000000000000000000002670520000000000000000000000000000000000000000000000000000000000000026805200000000000000000000000000000000000000000000000000000000000000269052000000000000000000000000000000000000000000000000000000000000002700520000000000000000000000000000000000000000000000000000000000000027105200000000000000000000000000000000000000000000000000000000000000272052000000000000000000000000000000000000000000000000000000000000002730520000000000000000000000000000000000000000000000000000000000000027405200000000000000000000000000000000000000000000000000000000000000275052000000000000000000000000000000000000000000000000000000000000002760520000000000000000000000000000000000000000000000000000000000000027705200000000000000000000000000000000000000000000000000000000000000278052000000000000000000000000000000000000000000000000000000000000002790520000000000000000000000000000000000000000000000000000000000000028005200000000000000000000000000000000000000000000000000000000000000281052000000000000000000000000000000000000000000000000000000000000002820520000000000000000000000000000000000000000000000000000000000000028305200000000000000000000000000000000000000000000000000000000000000284052000000000000000000000000000000000000000000000000000000000000002850520000000000000000000000000000000000000000000000000000000000000028605200000000000000000000000000000000000000000000000000000000000000287052000000000000000000000000000000000000000000000000000000000000002880520000000000000000000000000000000000000000000000000000000000000028905200000000000000000000000000000000000000000000000000000000000000290052000000000000000000000000000000000000000000000000000000000000002910520000000000000000000000000000000000000000000000000000000000000029205200000000000000000000000000000000000000000000000000000000000000293052000000000000000000000000000000000000000000000000000000000000002940520000000000000000000000000000000000000000000000000000000000000029505200000000000000000000000000000000000000000000000000000000000000296052000000000000000000000000000000000000000000000000000000000000002970520000000000000000000000000000000000000000000000000000000000000029805200000000000000000000000000000000000000000000000000000000000000299052000000000000000000000000000000000000000000000000000000000000003000520000000000000000000000000000000000000000000000000000000000000030105200000000000000000000000000000000000000000000000000000000000000302052000000000000000000000000000000000000000000000000000000000000003030520000000000000000000000000000000000000000000000000000000000000030405200000000000000000000000000000000000000000000000000000000000000305052000000000000000000000000000000000000000000000000000000000000003060520000000000000000000000000000000000000000000000000000000000000030705200000000000000000000000000000000000000000000000000000000000000308052000000000000000000000000000000000000000000000000000000000000003090520000000000000000000000000000000000000000000000000000000000000031005200000000000000000000000000000000000000000000000000000000000000311052000000000000000000000000000000000000000000000000000000000000003120520000000000000000000000000000000000000000000000000000000000000031305200000000000000000000000000000000000000000000000000000000000000314052000000000000000000000000000000000000000000000000000000000000003150520000000000000000000000000000000000000000000000000000000000000031605200000000000000000000000000000000000000000000000000000000000000317052000000000000000000000000000000000000000000000000000000000000003180520000000000000000000000000000000000000000000000000000000000000031905200000000000000000000000000000000000000000000000000000000000000320052000000000000000000000000000000000000000000000000000000000000003210520000000000000000000000000000000000000000000000000000000000000032205200000000000000000000000000000000000000000000000000000000000000323052000000000000000000000000000000000000000000000000000000000000003240520000000000000000000000000000000000000000000000000000000000000032505200000000000000000000000000000000000000000000000000000000000000326052000000000000000000000000000000000000000000000000000000000000003270520000000000000000000000000000000000000000000000000000000000000032805200000000000000000000000000000000000000000000000000000000000000329052000000000000000000000000000000000000000000000000000000000000003300520000000000000000000000000000000000000000000000000000000000000033105200000000000000000000000000000000000000000000000000000000000000332052000000000000000000000000000000000000000000000000000000000000003330520000000000000000000000000000000000000000000000000000000000000033405200000000000000000000000000000000000000000000000000000000000000335052000000000000000000000000000000000000000000000000000000000000003360520000000000000000000000000000000000000000000000000000000000000033705200000000000000000000000000000000000000000000000000000000000000338052000000000000000000000000000000000000000000000000000000000000003390520000000000000000000000000000000000000000000000000000000000000034005200000000000000000000000000000000000000000000000000000000000000341052000000000000000000000000000000000000000000000000000000000000003420520000000000000000000000000000000000000000000000000000000000000034305200000000000000000000000000000000000000000000000000000000000000344052000000000000000000000000000000000000000000000000000000000000003450520000000000000000000000000000000000000000000000000000000000000034605200000000000000000000000000000000000000000000000000000000000000347052000000000000000000000000000000000000000000000000000000000000003480520000000000000000000000000000000000000000000000000000000000000034905200000000000000000000000000000000000000000000000000000000000000350052000000000000000000000000000000000000000000000000000000000000003510520000000000000000000000000000000000000000000000000000000000000035205200000000000000000000000000000000000000000000000000000000000000353052000000000000000000000000000000000000000000000000000000000000003540520000000000000000000000000000000000000000000000000000000000000035505200000000000000000000000000000000000000000000000000000000000000356052000000000000000000000000000000000000000000000000000000000000003570520000000000000000000000000000000000000000000000000000000000000035805200000000000000000000000000000000000000000000000000000000000000359052000000000000000000000000000000000000000000000000000000000000003600520000000000000000000000000000000000000000000000000000000000000036105200000000000000000000000000000000000000000000000000000000000000362052000000000000000000000000000000000000000000000000000000000000003630520000000000000000000000000000000000000000000000000000000000000036405200000000000000000000000000000000000000000000000000000000000000365052000000000000000000000000000000000000000000000000000000000000003660520000000000000000000000000000000000000000000000000000000000000036705200000000000000000000000000000000000000000000000000000000000000368052000000000000000000000000000000000000000000000000000000000000003690520000000000000000000000000000000000000000000000000000000000000037005200000000000000000000000000000000000000000000000000000000000000371052000000000000000000000000000000000000000000000000000000000000003720520000000000000000000000000000000000000000000000000000000000000037305200000000000000000000000000000000000000000000000000000000000000374052000000000000000000000000000000000000000000000000000000000000003750520000000000000000000000000000000000000000000000000000000000000037605200000000000000000000000000000000000000000000000000000000000000377052000000000000000000000000000000000000000000000000000000000000003780520000000000000000000000000000000000000000000000000000000000000037905200000000000000000000000000000000000000000000000000000000000000380052000000000000000000000000000000000000000000000000000000000000003810520000000000000000000000000000000000000000000000000000000000000038205200000000000000000000000000000000000000000000000000000000000000383052000000000000000000000000000000000000000000000000000000000000003840520000000000000000000000000000000000000000000000000000000000000038505200000000000000000000000000000000000000000000000000000000000000386052000000000000000000000000000000000000000000000000000000000000003870520000000000000000000000000000000000000000000000000000000000000038805200000000000000000000000000000000000000000000000000000000000000389052000000000000000000000000000000000000000000000000000000000000003900520000000000000000000000000000000000000000000000000000000000000039105200000000000000000000000000000000000000000000000000000000000000392052000000000000000000000000000000000000000000000000000000000000003930520000000000000000000000000000000000000000000000000000000000000039405200000000000000000000000000000000000000000000000000000000000000395052000000000000000000000000000000000000000000000000000000000000003960520000000000000000000000000000000000000000000000000000000000000039705200000000000000000000000000000000000000000000000000000000000000398052000000000000000000000000000000000000000000000000000000000000003990520000000000000000000000000000000000000000000000000000000000000040005200000000000000000000000000000000000000000000000000000000000000401052000000000000000000000000000000000000000000000000000000000000004020520000000000000000000000000000000000000000000000000000000000000040305200000000000000000000000000000000000000000000000000000000000000404052000000000000000000000000000000000000000000000000000000000000004050520000000000000000000000000000000000000000000000000000000000000040605200000000000000000000000000000000000000000000000000000000000000407052000000000000000000000000000000000000000000000000000000000000004080520000000000000000000000000000000000000000000000000000000000000040905200000000000000000000000000000000000000000000000000000000000000410052000000000000000000000000000000000000000000000000000000000000004110520000000000000000000000000000000000000000000000000000000000000041205200000000000000000000000000000000000000000000000000000000000000413052000000000000000000000000000000000000000000000000000000000000004140520000000000000000000000000000000000000000000000000000000000000041505200000000000000000000000000000000000000000000000000000000000000416052000000000000000000000000000000000000000000000000000000000000004170520000000000000000000000000000000000000000000000000000000000000041805200000000000000000000000000000000000000000000000000000000000000419052000000000000000000000000000000000000000000000000000000000000004200520000000000000000000000000000000000000000000000000000000000000042105200000000000000000000000000000000000000000000000000000000000000422052000000000000000000000000000000000000000000000000000000000000004230520000000000000000000000000000000000000000000000000000000000000042405200000000000000000000000000000000000000000000000000000000000000425052000000000000000000000000000000000000000000000000000000000000004260520000000000000000000000000000000000000000000000000000000000000042705200000000000000000000000000000000000000000000000000000000000000428052000000000000000000000000000000000000000000000000000000000000004290520000000000000000000000000000000000000000000000000000000000000043005200000000000000000000000000000000000000000000000000000000000000431052000000000000000000000000000000000000000000000000000000000000004320520000000000000000000000000000000000000000000000000000000000000043305200000000000000000000000000000000000000000000000000000000000000434052000000000000000000000000000000000000000000000000000000000000004350520000000000000000000000000000000000000000000000000000000000000043605200000000000000000000000000000000000000000000000000000000000000437052000000000000000000000000000000000000000000000000000000000000004380520000000000000000000000000000000000000000000000000000000000000043905200000000000000000000000000000000000000000000000000000000000000440052000000000000000000000000000000000000000000000000000000000000004410520000000000000000000000000000000000000000000000000000000000000044205200000000000000000000000000000000000000000000000000000000000000443052000000000000000000000000000000000000000000000000000000000000004440520000000000000000000000000000000000000000000000000000000000000044505200000000000000000000000000000000000000000000000000000000000000446052000000000000000000000000000000000000000000000000000000000000004470520000000000000000000000000000000000000000000000000000000000000044805200000000000000000000000000000000000000000000000000000000000000449052000000000000000000000000000000000000000000000000000000000000004500520000000000000000000000000000000000000000000000000000000000000045105200000000000000000000000000000000000000000000000000000000000000452052000000000000000000000000000000000000000000000000000000000000004530520000000000000000000000000000000000000000000000000000000000000045405200000000000000000000000000000000000000000000000000000000000000455052000000000000000000000000000000000000000000000000000000000000004560520000000000000000000000000000000000000000000000000000000000000045705200000000000000000000000000000000000000000000000000000000000000458052000000000000000000000000000000000000000000000000000000000000004590520000000000000000000000000000000000000000000000000000000000000046005200000000000000000000000000000000000000000000000000000000000000461052000000000000000000000000000000000000000000000000000000000000004620520000000000000000000000000000000000000000000000000000000000000046305200000000000000000000000000000000000000000000000000000000000000464052000000000000000000000000000000000000000000000000000000000000004650520000000000000000000000000000000000000000000000000000000000000046605200000000000000000000000000000000000000000000000000000000000000467052000000000000000000000000000000000000000000000000000000000000004680520000000000000000000000000000000000000000000000000000000000000046905200000000000000000000000000000000000000000000000000000000000000470052000000000000000000000000000000000000000000000000000000000000004710520000000000000000000000000000000000000000000000000000000000000047205200000000000000000000000000000000000000000000000000000000000000473052000000000000000000000000000000000000000000000000000000000000004740520000000000000000000000000000000000000000000000000000000000000047505200000000000000000000000000000000000000000000000000000000000000476052000000000000000000000000000000000000000000000000000000000000004770520000000000000000000000000000000000000000000000000000000000000047805200000000000000000000000000000000000000000000000000000000000000479052000000000000000000000000000000000000000000000000000000000000004800520000000000000000000000000000000000000000000000000000000000000048105200000000000000000000000000000000000000000000000000000000000000482052000000000000000000000000000000000000000000000000000000000000004830520000000000000000000000000000000000000000000000000000000000000048405200000000000000000000000000000000000000000000000000000000000000485052000000000000000000000000000000000000000000000000000000000000004860520000000000000000000000000000000000000000000000000000000000000048705200000000000000000000000000000000000000000000000000000000000000488052000000000000000000000000000000000000000000000000000000000000004890520000000000000000000000000000000000000000000000000000000000000049005200000000000000000000000000000000000000000000000000000000000000491052000000000000000000000000000000000000000000000000000000000000004920520000000000000000000000000000000000000000000000000000000000000049305200000000000000000000000000000000000000000000000000000000000000494052000000000000000000000000000000000000000000000000000000000000004950520000000000000000000000000000000000000000000000000000000000000049605200000000000000000000000000000000000000000000000000000000000000497052000000000000000000000000000000000000000000000000000000000000004980520000000000000000000000000000000000000000000000000000000000000049905200000000000000000000000000000000000000000000000000000000000000500052000000000000000000000000000000000000000000000000000000000000005010520000000000000000000000000000000000000000000000000000000000000050205200000000000000000000000000000000000000000000000000000000000000503052000000000000000000000000000000000000000000000000000000000000005040520000000000000000000000000000000000000000000000000000000000000050505200000000000000000000000000000000000000000000000000000000000000506052000000000000000000000000000000000000000000000000000000000000005070520000000000000000000000000000000000000000000000000000000000000050805200000000000000000000000000000000000000000000000000000000000000509052000000000000000000000000000000000000000000000000000000000000005100520000000000000000000000000000000000000000000000000000000000000051105200000000000000000000000000000000000000000000000000000000000000512052000000000000000000000000000000000000000000000000000000000000005130520000000000000000000000000000000000000000000000000000000000000051405200000000000000000000000000000000000000000000000000000000000000515052000000000000000000000000000000000000000000000000000000000000005160520000000000000000000000000000000000000000000000000000000000000051705200000000000000000000000000000000000000000000000000000000000000518052000000000000000000000000000000000000000000000000000000000000005190520000000000000000000000000000000000000000000000000000000000000052005200000000000000000000000000000000000000000000000000000000000000521052000000000000000000000000000000000000000000000000000000000000005220520000000000000000000000000000000000000000000000000000000000000052305200000000000000000000000000000000000000000000000000000000000000524052000000000000000000000000000000000000000000000000000000000000005250520000000000000000000000000000000000000000000000000000000000000052605200000000000000000000000000000000000000000000000000000000000000527052000000000000000000000000000000000000000000000000000000000000005280520000000000000000000000000000000000000000000000000000000000000052905200000000000000000000000000000000000000000000000000000000000000530052000000000000000000000000000000000000000000000000000000000000005310520000000000000000000000000000000000000000000000000000000000000053205200000000000000000000000000000000000000000000000000000000000000533052000000000000000000000000000000000000000000000000000000000000005340520000000000000000000000000000000000000000000000000000000000000053505200000000000000000000000000000000000000000000000000000000000000536052000000000000000000000000000000000000000000000000000000000000005370520000000000000000000000000000000000000000000000000000000000000053805200000000000000000000000000000000000000000000000000000000000000539052000000000000000000000000000000000000000000000000000000000000005400520000000000000000000000000000000000000000000000000000000000000054105200000000000000000000000000000000000000000000000000000000000000542052000000000000000000000000000000000000000000000000000000000000005430520000000000000000000000000000000000000000000000000000000000000054405200000000000000000000000000000000000000000000000000000000000000545052000000000000000000000000000000000000000000000000000000000000005460520000000000000000000000000000000000000000000000000000000000000054705200000000000000000000000000000000000000000000000000000000000000548052000000000000000000000000000000000000000000000000000000000000005490520000000000000000000000000000000000000000000000000000000000000055005200000000000000000000000000000000000000000000000000000000000000551052000000000000000000000000000000000000000000000000000000000000005520520000000000000000000000000000000000000000000000000000000000000055305200000000000000000000000000000000000000000000000000000000000000554052000000000000000000000000000000000000000000000000000000000000005550520000000000000000000000000000000000000000000000000000000000000055605200000000000000000000000000000000000000000000000000000000000000557052000000000000000000000000000000000000000000000000000000000000005580520000000000000000000000000000000000000000000000000000000000000055905200000000000000000000000000000000000000000000000000000000000000560052000000000000000000000000000000000000000000000000000000000000005610520000000000000000000000000000000000000000000000000000000000000056205200000000000000000000000000000000000000000000000000000000000000563052000000000000000000000000000000000000000000000000000000000000005640520000000000000000000000000000000000000000000000000000000000000056505200000000000000000000000000000000000000000000000000000000000000566052000000000000000000000000000000000000000000000000000000000000005670520000000000000000000000000000000000000000000000000000000000000056805200000000000000000000000000000000000000000000000000000000000000569052000000000000000000000000000000000000000000000000000000000000005700520000000000000000000000000000000000000000000000000000000000000057105200000000000000000000000000000000000000000000000000000000000000572052000000000000000000000000000000000000000000000000000000000000005730520000000000000000000000000000000000000000000000000000000000000057405200000000000000000000000000000000000000000000000000000000000000575052000000000000000000000000000000000000000000000000000000000000005760520000000000000000000000000000000000000000000000000000000000000057705200000000000000000000000000000000000000000000000000000000000000578052000000000000000000000000000000000000000000000000000000000000005790520000000000000000000000000000000000000000000000000000000000000058005200000000000000000000000000000000000000000000000000000000000000581052000000000000000000000000000000000000000000000000000000000000005820520000000000000000000000000000000000000000000000000000000000000058305200000000000000000000000000000000000000000000000000000000000000584052000000000000000000000000000000000000000000000000000000000000005850520000000000000000000000000000000000000000000000000000000000000058605200000000000000000000000000000000000000000000000000000000000000587052000000000000000000000000000000000000000000000000000000000000005880520000000000000000000000000000000000000000000000000000000000000058905200000000000000000000000000000000000000000000000000000000000000590052000000000000000000000000000000000000000000000000000000000000005910520000000000000000000000000000000000000000000000000000000000000059205200000000000000000000000000000000000000000000000000000000000000593052000000000000000000000000000000000000000000000000000000000000005940520000000000000000000000000000000000000000000000000000000000000059505200000000000000000000000000000000000000000000000000000000000000596052000000000000000000000000000000000000000000000000000000000000005970520000000000000000000000000000000000000000000000000000000000000059805200000000000000000000000000000000000000000000000000000000000000599052000000000000000000000000000000000000000000000000000000000000006000520000000000000000000000000000000000000000000000000000000000000060105200000000000000000000000000000000000000000000000000000000000000602052000000000000000000000000000000000000000000000000000000000000006030520000000000000000000000000000000000000000000000000000000000000060405200000000000000000000000000000000000000000000000000000000000000605052000000000000000000000000000000000000000000000000000000000000006060520000000000000000000000000000000000000000000000000000000000000060705200000000000000000000000000000000000000000000000000000000000000608052000000000000000000000000000000000000000000000000000000000000006090520000000000000000000000000000000000000000000000000000000000000061005200000000000000000000000000000000000000000000000000000000000000611052000000000000000000000000000000000000000000000000000000000000006120520000000000000000000000000000000000000000000000000000000000000061305200000000000000000000000000000000000000000000000000000000000000614052000000000000000000000000000000000000000000000000000000000000006150520000000000000000000000000000000000000000000000000000000000000061605200000000000000000000000000000000000000000000000000000000000000617052000000000000000000000000000000000000000000000000000000000000006180520000000000000000000000000000000000000000000000000000000000000061905200000000000000000000000000000000000000000000000000000000000000620052000000000000000000000000000000000000000000000000000000000000006210520000000000000000000000000000000000000000000000000000000000000062205200000000000000000000000000000000000000000000000000000000000000623052000000000000000000000000000000000000000000000000000000000000006240520000000000000000000000000000000000000000000000000000000000000062505200000000000000000000000000000000000000000000000000000000000000626052000000000000000000000000000000000000000000000000000000000000006270520000000000000000000000000000000000000000000000000000000000000062805200000000000000000000000000000000000000000000000000000000000000629052000000000000000000000000000000000000000000000000000000000000006300520000000000000000000000000000000000000000000000000000000000000063105200000000000000000000000000000000000000000000000000000000000000632052000000000000000000000000000000000000000000000000000000000000006330520000000000000000000000000000000000000000000000000000000000000063405200000000000000000000000000000000000000000000000000000000000000635052000000000000000000000000000000000000000000000000000000000000006360520000000000000000000000000000000000000000000000000000000000000063705200000000000000000000000000000000000000000000000000000000000000638052000000000000000000000000000000000000000000000000000000000000006390520000000000000000000000000000000000000000000000000000000000000064005200000000000000000000000000000000000000000000000000000000000000641052000000000000000000000000000000000000000000000000000000000000006420520000000000000000000000000000000000000000000000000000000000000064305200000000000000000000000000000000000000000000000000000000000000644052000000000000000000000000000000000000000000000000000000000000006450520000000000000000000000000000000000000000000000000000000000000064605200000000000000000000000000000000000000000000000000000000000000647052000000000000000000000000000000000000000000000000000000000000006480520000000000000000000000000000000000000000000000000000000000000064905200000000000000000000000000000000000000000000000000000000000000650052000000000000000000000000000000000000000000000000000000000000006510520000000000000000000000000000000000000000000000000000000000000065205200000000000000000000000000000000000000000000000000000000000000653052000000000000000000000000000000000000000000000000000000000000006540520000000000000000000000000000000000000000000000000000000000000065505200000000000000000000000000000000000000000000000000000000000000656052000000000000000000000000000000000000000000000000000000000000006570520000000000000000000000000000000000000000000000000000000000000065805200000000000000000000000000000000000000000000000000000000000000659052000000000000000000000000000000000000000000000000000000000000006600520000000000000000000000000000000000000000000000000000000000000066105200000000000000000000000000000000000000000000000000000000000000662052000000000000000000000000000000000000000000000000000000000000006630520000000000000000000000000000000000000000000000000000000000000066405200000000000000000000000000000000000000000000000000000000000000665052000000000000000000000000000000000000000000000000000000000000006660520000000000000000000000000000000000000000000000000000000000000066705200000000000000000000000000000000000000000000000000000000000000668052000000000000000000000000000000000000000000000000000000000000006690520000000000000000000000000000000000000000000000000000000000000067005200000000000000000000000000000000000000000000000000000000000000671052000000000000000000000000000000000000000000000000000000000000006720520000000000000000000000000000000000000000000000000000000000000067305200000000000000000000000000000000000000000000000000000000000000674052000000000000000000000000000000000000000000000000000000000000006750520000000000000000000000000000000000000000000000000000000000000067605200000000000000000000000000000000000000000000000000000000000000677052000000000000000000000000000000000000000000000000000000000000006780520000000000000000000000000000000000000000000000000000000000000067905200000000000000000000000000000000000000000000000000000000000000680052000000000000000000000000000000000000000000000000000000000000006810520000000000000000000000000000000000000000000000000000000000000068205200000000000000000000000000000000000000000000000000000000000000683052000000000000000000000000000000000000000000000000000000000000006840520000000000000000000000000000000000000000000000000000000000000068505200000000000000000000000000000000000000000000000000000000000000686052000000000000000000000000000000000000000000000000000000000000006870520000000000000000000000000000000000000000000000000000000000000068805200000000000000000000000000000000000000000000000000000000000000689052000000000000000000000000000000000000000000000000000000000000006900520000000000000000000000000000000000000000000000000000000000000069105200000000000000000000000000000000000000000000000000000000000000692052000000000000000000000000000000000000000000000000000000000000006930520000000000000000000000000000000000000000000000000000000000000069405200000000000000000000000000000000000000000000000000000000000000695052000000000000000000000000000000000000000000000000000000000000006960520000000000000000000000000000000000000000000000000000000000000069705200000000000000000000000000000000000000000000000000000000000000698052000000000000000000000000000000000000000000000000000000000000006990520000000000000000000000000000000000000000000000000000000000000070005200000000000000000000000000000000000000000000000000000000000000701052000000000000000000000000000000000000000000000000000000000000007020520000000000000000000000000000000000000000000000000000000000000070305200000000000000000000000000000000000000000000000000000000000000704052000000000000000000000000000000000000000000000000000000000000007050520000000000000000000000000000000000000000000000000000000000000070605200000000000000000000000000000000000000000000000000000000000000707052000000000000000000000000000000000000000000000000000000000000007080520000000000000000000000000000000000000000000000000000000000000070905200000000000000000000000000000000000000000000000000000000000000710052000000000000000000000000000000000000000000000000000000000000007110520000000000000000000000000000000000000000000000000000000000000071205200000000000000000000000000000000000000000000000000000000000000713052000000000000000000000000000000000000000000000000000000000000007140520000000000000000000000000000000000000000000000000000000000000071505200000000000000000000000000000000000000000000000000000000000000716052000000000000000000000000000000000000000000000000000000000000007170520000000000000000000000000000000000000000000000000000000000000071805200000000000000000000000000000000000000000000000000000000000000719052000000000000000000000000000000000000000000000000000000000000007200520000000000000000000000000000000000000000000000000000000000000072105200000000000000000000000000000000000000000000000000000000000000722052000000000000000000000000000000000000000000000000000000000000007230520000000000000000000000000000000000000000000000000000000000000072405200000000000000000000000000000000000000000000000000000000000000725052000000000000000000000000000000000000000000000000000000000000007260520000000000000000000000000000000000000000000000000000000000000072705200000000000000000000000000000000000000000000000000000000000000728052000000000000000000000000000000000000000000000000000000000000007290520000000000000000000000000000000000000000000000000000000000000073005200000000000000000000000000000000000000000000000000000000000000731052000000000000000000000000000000000000000000000000000000000000007320520000000000000000000000000000000000000000000000000000000000000073305200000000000000000000000000000000000000000000000000000000000000734052000000000000000000000000000000000000000000000000000000000000007350520000000000000000000000000000000000000000000000000000000000000073605200000000000000000000000000000000000000000000000000000000000000737052000000000000000000000000000000000000000000000000000000000000007380520000000000000000000000000000000000000000000000000000000000000073905200000000000000000000000000000000000000000000000000000000000000740052000000000000000000000000000000000000000000000000000000000000007410520000000000000000000000000000000000000000000000000000000000000074205200000000000000000000000000000000000000000000000000000000000000743052000000000000000000000000000000000000000000000000000000000000007440520000000000000000000000000000000000000000000000000000000000000074505200000000000000000000000000000000000000000000000000000000000000746052000000000000000000000000000000000000000000000000000000000000007470520000000000000000000000000000000000000000000000000000000000000074805200000000000000000000000000000000000000000000000000000000000000749052000000000000000000000000000000000000000000000000000000000000007500520000000000000000000000000000000000000000000000000000000000000075105200000000000000000000000000000000000000000000000000000000000000752052000000000000000000000000000000000000000000000000000000000000007530520000000000000000000000000000000000000000000000000000000000000075405200000000000000000000000000000000000000000000000000000000000000755052000000000000000000000000000000000000000000000000000000000000007560520000000000000000000000000000000000000000000000000000000000000075705200000000000000000000000000000000000000000000000000000000000000758052000000000000000000000000000000000000000000000000000000000000007590520000000000000000000000000000000000000000000000000000000000000076005200000000000000000000000000000000000000000000000000000000000000761052000000000000000000000000000000000000000000000000000000000000007620520000000000000000000000000000000000000000000000000000000000000076305200000000000000000000000000000000000000000000000000000000000000764052000000000000000000000000000000000000000000000000000000000000007650520000000000000000000000000000000000000000000000000000000000000076605200000000000000000000000000000000000000000000000000000000000000767052000000000000000000000000000000000000000000000000000000000000007680520000000000000000000000000000000000000000000000000000000000000076905200000000000000000000000000000000000000000000000000000000000000770052000000000000000000000000000000000000000000000000000000000000007710520000000000000000000000000000000000000000000000000000000000000077205200000000000000000000000000000000000000000000000000000000000000773052000000000000000000000000000000000000000000000000000000000000007740520000000000000000000000000000000000000000000000000000000000000077505200000000000000000000000000000000000000000000000000000000000000776052000000000000000000000000000000000000000000000000000000000000007770520000000000000000000000000000000000000000000000000000000000000077805200000000000000000000000000000000000000000000000000000000000000779052000000000000000000000000000000000000000000000000000000000000007800520000000000000000000000000000000000000000000000000000000000000078105200000000000000000000000000000000000000000000000000000000000000782052000000000000000000000000000000000000000000000000000000000000007830520000000000000000000000000000000000000000000000000000000000000078405200000000000000000000000000000000000000000000000000000000000000785052000000000000000000000000000000000000000000000000000000000000007860520000000000000000000000000000000000000000000000000000000000000078705200000000000000000000000000000000000000000000000000000000000000788052000000000000000000000000000000000000000000000000000000000000007890520000000000000000000000000000000000000000000000000000000000000079005200000000000000000000000000000000000000000000000000000000000000791052000000000000000000000000000000000000000000000000000000000000007920520000000000000000000000000000000000000000000000000000000000000079305200000000000000000000000000000000000000000000000000000000000000794052000000000000000000000000000000000000000000000000000000000000007950520000000000000000000000000000000000000000000000000000000000000079605200000000000000000000000000000000000000000000000000000000000000797052000000000000000000000000000000000000000000000000000000000000007980520000000000000000000000000000000000000000000000000000000000000079905200000000000000000000000000000000000000000000000000000000000000800052000000000000000000000000000000000000000000000000000000000000008010520000000000000000000000000000000000000000000000000000000000000080205200000000000000000000000000000000000000000000000000000000000000803052000000000000000000000000000000000000000000000000000000000000008040520000000000000000000000000000000000000000000000000000000000000080505200000000000000000000000000000000000000000000000000000000000000806052000000000000000000000000000000000000000000000000000000000000008070520000000000000000000000000000000000000000000000000000000000000080805200000000000000000000000000000000000000000000000000000000000000809052000000000000000000000000000000000000000000000000000000000000008100520000000000000000000000000000000000000000000000000000000000000081105200000000000000000000000000000000000000000000000000000000000000812052000000000000000000000000000000000000000000000000000000000000008130520000000000000000000000000000000000000000000000000000000000000081405200000000000000000000000000000000000000000000000000000000000000815052000000000000000000000000000000000000000000000000000000000000008160520000000000000000000000000000000000000000000000000000000000000081705200000000000000000000000000000000000000000000000000000000000000818052000000000000000000000000000000000000000000000000000000000000008190520000000000000000000000000000000000000000000000000000000000000082005200000000000000000000000000000000000000000000000000000000000000821052000000000000000000000000000000000000000000000000000000000000008220520000000000000000000000000000000000000000000000000000000000000082305200000000000000000000000000000000000000000000000000000000000000824052000000000000000000000000000000000000000000000000000000000000008250520000000000000000000000000000000000000000000000000000000000000082605200000000000000000000000000000000000000000000000000000000000000827052000000000000000000000000000000000000000000000000000000000000008280520000000000000000000000000000000000000000000000000000000000000082905200000000000000000000000000000000000000000000000000000000000000830052000000000000000000000000000000000000000000000000000000000000008310520000000000000000000000000000000000000000000000000000000000000083205200000000000000000000000000000000000000000000000000000000000000833052000000000000000000000000000000000000000000000000000000000000008340520000000000000000000000000000000000000000000000000000000000000083505200000000000000000000000000000000000000000000000000000000000000836052000000000000000000000000000000000000000000000000000000000000008370520000000000000000000000000000000000000000000000000000000000000083805200000000000000000000000000000000000000000000000000000000000000839052000000000000000000000000000000000000000000000000000000000000008400520000000000000000000000000000000000000000000000000000000000000084105200000000000000000000000000000000000000000000000000000000000000842052000000000000000000000000000000000000000000000000000000000000008430520000000000000000000000000000000000000000000000000000000000000084405200000000000000000000000000000000000000000000000000000000000000845052000000000000000000000000000000000000000000000000000000000000008460520000000000000000000000000000000000000000000000000000000000000084705200000000000000000000000000000000000000000000000000000000000000848052000000000000000000000000000000000000000000000000000000000000008490520000000000000000000000000000000000000000000000000000000000000085005200000000000000000000000000000000000000000000000000000000000000851052000000000000000000000000000000000000000000000000000000000000008520520000000000000000000000000000000000000000000000000000000000000085305200000000000000000000000000000000000000000000000000000000000000854052000000000000000000000000000000000000000000000000000000000000008550520000000000000000000000000000000000000000000000000000000000000085605200000000000000000000000000000000000000000000000000000000000000857052000000000000000000000000000000000000000000000000000000000000008580520000000000000000000000000000000000000000000000000000000000000085905200000000000000000000000000000000000000000000000000000000000000860052000000000000000000000000000000000000000000000000000000000000008610520000000000000000000000000000000000000000000000000000000000000086205200000000000000000000000000000000000000000000000000000000000000863052000000000000000000000000000000000000000000000000000000000000008640520000000000000000000000000000000000000000000000000000000000000086505200000000000000000000000000000000000000000000000000000000000000866052000000000000000000000000000000000000000000000000000000000000008670520000000000000000000000000000000000000000000000000000000000000086805200000000000000000000000000000000000000000000000000000000000000869052000000000000000000000000000000000000000000000000000000000000008700520000000000000000000000000000000000000000000000000000000000000087105200000000000000000000000000000000000000000000000000000000000000872052000000000000000000000000000000000000000000000000000000000000008730520000000000000000000000000000000000000000000000000000000000000087405200000000000000000000000000000000000000000000000000000000000000875052000000000000000000000000000000000000000000000000000000000000008760520000000000000000000000000000000000000000000000000000000000000087705200000000000000000000000000000000000000000000000000000000000000878052000000000000000000000000000000000000000000000000000000000000008790520000000000000000000000000000000000000000000000000000000000000088005200000000000000000000000000000000000000000000000000000000000000881052000000000000000000000000000000000000000000000000000000000000008820520000000000000000000000000000000000000000000000000000000000000088305200000000000000000000000000000000000000000000000000000000000000884052000000000000000000000000000000000000000000000000000000000000008850520000000000000000000000000000000000000000000000000000000000000088605200000000000000000000000000000000000000000000000000000000000000887052000000000000000000000000000000000000000000000000000000000000008880520000000000000000000000000000000000000000000000000000000000000088905200000000000000000000000000000000000000000000000000000000000000890052000000000000000000000000000000000000000000000000000000000000008910520000000000000000000000000000000000000000000000000000000000000089205200000000000000000000000000000000000000000000000000000000000000893052000000000000000000000000000000000000000000000000000000000000008940520000000000000000000000000000000000000000000000000000000000000089505200000000000000000000000000000000000000000000000000000000000000896052000000000000000000000000000000000000000000000000000000000000008970520000000000000000000000000000000000000000000000000000000000000089805200000000000000000000000000000000000000000000000000000000000000899052000000000000000000000000000000000000000000000000000000000000009000520000000000000000000000000000000000000000000000000000000000000090105200000000000000000000000000000000000000000000000000000000000000902052000000000000000000000000000000000000000000000000000000000000009030520000000000000000000000000000000000000000000000000000000000000090405200000000000000000000000000000000000000000000000000000000000000905052000000000000000000000000000000000000000000000000000000000000009060520000000000000000000000000000000000000000000000000000000000000090705200000000000000000000000000000000000000000000000000000000000000908052000000000000000000000000000000000000000000000000000000000000009090520000000000000000000000000000000000000000000000000000000000000091005200000000000000000000000000000000000000000000000000000000000000911052000000000000000000000000000000000000000000000000000000000000009120520000000000000000000000000000000000000000000000000000000000000091305200000000000000000000000000000000000000000000000000000000000000914052000000000000000000000000000000000000000000000000000000000000009150520000000000000000000000000000000000000000000000000000000000000091605200000000000000000000000000000000000000000000000000000000000000917052000000000000000000000000000000000000000000000000000000000000009180520000000000000000000000000000000000000000000000000000000000000091905200000000000000000000000000000000000000000000000000000000000000920052000000000000000000000000000000000000000000000000000000000000009210520000000000000000000000000000000000000000000000000000000000000092205200000000000000000000000000000000000000000000000000000000000000923052000000000000000000000000000000000000000000000000000000000000009240520000000000000000000000000000000000000000000000000000000000000092505200000000000000000000000000000000000000000000000000000000000000926052000000000000000000000000000000000000000000000000000000000000009270520000000000000000000000000000000000000000000000000000000000000092805200000000000000000000000000000000000000000000000000000000000000929052000000000000000000000000000000000000000000000000000000000000009300520000000000000000000000000000000000000000000000000000000000000093105200000000000000000000000000000000000000000000000000000000000000932052000000000000000000000000000000000000000000000000000000000000009330520000000000000000000000000000000000000000000000000000000000000093405200000000000000000000000000000000000000000000000000000000000000935052000000000000000000000000000000000000000000000000000000000000009360520000000000000000000000000000000000000000000000000000000000000093705200000000000000000000000000000000000000000000000000000000000000938052000000000000000000000000000000000000000000000000000000000000009390520000000000000000000000000000000000000000000000000000000000000094005200000000000000000000000000000000000000000000000000000000000000941052000000000000000000000000000000000000000000000000000000000000009420520000000000000000000000000000000000000000000000000000000000000094305200000000000000000000000000000000000000000000000000000000000000944052000000000000000000000000000000000000000000000000000000000000009450520000000000000000000000000000000000000000000000000000000000000094605200000000000000000000000000000000000000000000000000000000000000947052000000000000000000000000000000000000000000000000000000000000009480520000000000000000000000000000000000000000000000000000000000000094905200000000000000000000000000000000000000000000000000000000000000950052000000000000000000000000000000000000000000000000000000000000009510520000000000000000000000000000000000000000000000000000000000000095205200000000000000000000000000000000000000000000000000000000000000953052000000000000000000000000000000000000000000000000000000000000009540520000000000000000000000000000000000000000000000000000000000000095505200000000000000000000000000000000000000000000000000000000000000956052000000000000000000000000000000000000000000000000000000000000009570520000000000000000000000000000000000000000000000000000000000000095805200000000000000000000000000000000000000000000000000000000000000959052000000000000000000000000000000000000000000000000000000000000009600520000000000000000000000000000000000000000000000000000000000000096105200000000000000000000000000000000000000000000000000000000000000962052000000000000000000000000000000000000000000000000000000000000009630520000000000000000000000000000000000000000000000000000000000000096405200000000000000000000000000000000000000000000000000000000000000965052000000000000000000000000000000000000000000000000000000000000009660520000000000000000000000000000000000000000000000000000000000000096705200000000000000000000000000000000000000000000000000000000000000968052000000000000000000000000000000000000000000000000000000000000009690520000000000000000000000000000000000000000000000000000000000000097005200000000000000000000000000000000000000000000000000000000000000971052000000000000000000000000000000000000000000000000000000000000009720520000000000000000000000000000000000000000000000000000000000000097305200000000000000000000000000000000000000000000000000000000000000974052000000000000000000000000000000000000000000000000000000000000009750520000000000000000000000000000000000000000000000000000000000000097605200000000000000000000000000000000000000000000000000000000000000977052000000000000000000000000000000000000000000000000000000000000009780520000000000000000000000000000000000000000000000000000000000000097905200000000000000000000000000000000000000000000000000000000000000980052000000000000000000000000000000000000000000000000000000000000009810520000000000000000000000000000000000000000000000000000000000000098205200000000000000000000000000000000000000000000000000000000000000983052000000000000000000000000000000000000000000000000000000000000009840520000000000000000000000000000000000000000000000000000000000000098505200000000000000000000000000000000000000000000000000000000000000986052000000000000000000000000000000000000000000000000000000000000009870520000000000000000000000000000000000000000000000000000000000000098805200000000000000000000000000000000000000000000000000000000000000989052000000000000000000000000000000000000000000000000000000000000009900520000000000000000000000000000000000000000000000000000000000000099105200000000000000000000000000000000000000000000000000000000000000992052000000000000000000000000000000000000000000000000000000000000009930520000000000000000000000000000000000000000000000000000000000000099405200000000000000000000000000000000000000000000000000000000000000995052000000000000000000000000000000000000000000000000000000000000009960520000000000000000000000000000000000000000000000000000000000000099705200000000000000000000000000000000000000000000000000000000000000998052000000000000000000000000000000000000000000000000000000000000009990520e57eb8d10b6eed36a88a464538f8fcedbba7b1a71d6ed52124f77b835807d0fd05201c53ca351e7f26f963ced56cf18f9ebee56535170171b72a0addb4e1613776850520636b8e5a599cfe0833dbe141dbc093d65e0a497451ac21415fbf03698587c7b905204ea21cad94a85adb252b0a76b9826c67d7c697ca386d201752e38f19ed92a223126170746f733a3a6d657461646174615f7630c201032003000000000000134552525f414c52454144595f50524553454e542c4164647265737320697320616c72656164792070726573656e7420696e207468652077686974656c6973742e2103000000000000134552525f4e4f5f535543485f41444452455353214e6f2073756368206164647265737320696e207468652077686974656c6973742e2203000000000000134552525f4e4f545f494e495449414c495a45441d57686974656c697374206973206e6f7420696e697469616c697a65642e000201090b010205020001040100051d0b0011050c020b02070321030907012707032900030e0701270a01110220031407002707032a000c030b030f000b013101380002010104010008b01f0b0011050c010b01070321030907012707032a000c030b030f000c020a020704310138000a020705310138000a020706310138000a020707310138000a020708310138000a020709310138000a02070a310138000a02070b310138000a02070c310138000a02070d310138000a02070e310138000a02070f310138000a020710310138000a020711310138000a020712310138000a020713310138000a020714310138000a020715310138000a020716310138000a020717310138000a020718310138000a020719310138000a02071a310138000a02071b310138000a02071c310138000a02071d310138000a02071e310138000a02071f310138000a020720310138000a020721310138000a020722310138000a020723310138000a020724310138000a020725310138000a020726310138000a020727310138000a020728310138000a020729310138000a02072a310138000a02072b310138000a02072c310138000a02072d310138000a02072e310138000a02072f310138000a020730310138000a020731310138000a020732310138000a020733310138000a020734310138000a020735310138000a020736310138000a020737310138000a020738310138000a020739310138000a02073a310138000a02073b310138000a02073c310138000a02073d310138000a02073e310138000a02073f310138000a020740310138000a020741310138000a020742310138000a020743310138000a020744310138000a020745310138000a020746310138000a020747310138000a020748310138000a020749310138000a02074a310138000a02074b310138000a02074c310138000a02074d310138000a02074e310138000a02074f310138000a020750310138000a020751310138000a020752310138000a020753310138000a020754310138000a020755310138000a020756310138000a020757310138000a020758310138000a020759310138000a02075a310138000a02075b310138000a02075c310138000a02075d310138000a02075e310138000a02075f310138000a020760310138000a020761310138000a020762310138000a020763310138000a020764310138000a020765310138000a020766310138000a020767310138000a020768310138000a020769310138000a02076a310138000a02076b310138000a02076c310138000a02076d310138000a02076e310138000a02076f310138000a020770310138000a020771310138000a020772310138000a020773310138000a020774310138000a020775310138000a020776310138000a020777310138000a020778310138000a020779310138000a02077a310138000a02077b310138000a02077c310138000a02077d310138000a02077e310138000a02077f310138000a02078001310138000a02078101310138000a02078201310138000a02078301310138000a02078401310138000a02078501310138000a02078601310138000a02078701310138000a02078801310138000a02078901310138000a02078a01310138000a02078b01310138000a02078c01310138000a02078d01310138000a02078e01310138000a02078f01310138000a02079001310138000a02079101310138000a02079201310138000a02079301310138000a02079401310138000a02079501310138000a02079601310138000a02079701310138000a02079801310138000a02079901310138000a02079a01310138000a02079b01310138000a02079c01310138000a02079d01310138000a02079e01310138000a02079f01310138000a0207a001310138000a0207a101310138000a0207a201310138000a0207a301310138000a0207a401310138000a0207a501310138000a0207a601310138000a0207a701310138000a0207a801310138000a0207a901310138000a0207aa01310138000a0207ab01310138000a0207ac01310138000a0207ad01310138000a0207ae01310138000a0207af01310138000a0207b001310138000a0207b101310138000a0207b201310138000a0207b301310138000a0207b401310138000a0207b501310138000a0207b601310138000a0207b701310138000a0207b801310138000a0207b901310138000a0207ba01310138000a0207bb01310138000a0207bc01310138000a0207bd01310138000a0207be01310138000a0207bf01310138000a0207c001310138000a0207c101310138000a0207c201310138000a0207c301310138000a0207c401310138000a0207c501310138000a0207c601310138000a0207c701310138000a0207c801310138000a0207c901310138000a0207ca01310138000a0207cb01310138000a0207cc01310138000a0207cd01310138000a0207ce01310138000a0207cf01310138000a0207d001310138000a0207d101310138000a0207d201310138000a0207d301310138000a0207d401310138000a0207d501310138000a0207d601310138000a0207d701310138000a0207d801310138000a0207d901310138000a0207da01310138000a0207db01310138000a0207dc01310138000a0207dd01310138000a0207de01310138000a0207df01310138000a0207e001310138000a0207e101310138000a0207e201310138000a0207e301310138000a0207e401310138000a0207e501310138000a0207e601310138000a0207e701310138000a0207e801310138000a0207e901310138000a0207ea01310138000a0207eb01310138000a0207ec01310138000a0207ed01310138000a0207ee01310138000a0207ef01310138000a0207f001310138000a0207f101310138000a0207f201310138000a0207f301310138000a0207f401310138000a0207f501310138000a0207f601310138000a0207f701310138000a0207f801310138000a0207f901310138000a0207fa01310138000a0207fb01310138000a0207fc01310138000a0207fd01310138000a0207fe01310138000a0207ff01310138000a02078002310138000a02078102310138000a02078202310138000a02078302310138000a02078402310138000a02078502310138000a02078602310138000a02078702310138000a02078802310138000a02078902310138000a02078a02310138000a02078b02310138000a02078c02310138000a02078d02310138000a02078e02310138000a02078f02310138000a02079002310138000a02079102310138000a02079202310138000a02079302310138000a02079402310138000a02079502310138000a02079602310138000a02079702310138000a02079802310138000a02079902310138000a02079a02310138000a02079b02310138000a02079c02310138000a02079d02310138000a02079e02310138000a02079f02310138000a0207a002310138000a0207a102310138000a0207a202310138000a0207a302310138000a0207a402310138000a0207a502310138000a0207a602310138000a0207a702310138000a0207a802310138000a0207a902310138000a0207aa02310138000a0207ab02310138000a0207ac02310138000a0207ad02310138000a0207ae02310138000a0207af02310138000a0207b002310138000a0207b102310138000a0207b202310138000a0207b302310138000a0207b402310138000a0207b502310138000a0207b602310138000a0207b702310138000a0207b802310138000a0207b902310138000a0207ba02310138000a0207bb02310138000a0207bc02310138000a0207bd02310138000a0207be02310138000a0207bf02310138000a0207c002310138000a0207c102310138000a0207c202310138000a0207c302310138000a0207c402310138000a0207c502310138000a0207c602310138000a0207c702310138000a0207c802310138000a0207c902310138000a0207ca02310138000a0207cb02310138000a0207cc02310138000a0207cd02310138000a0207ce02310138000a0207cf02310138000a0207d002310138000a0207d102310138000a0207d202310138000a0207d302310138000a0207d402310138000a0207d502310138000a0207d602310138000a0207d702310138000a0207d802310138000a0207d902310138000a0207da02310138000a0207db02310138000a0207dc02310138000a0207dd02310138000a0207de02310138000a0207df02310138000a0207e002310138000a0207e102310138000a0207e202310138000a0207e302310138000a0207e402310138000a0207e502310138000a0207e602310138000a0207e702310138000a0207e802310138000a0207e902310138000a0207ea02310138000a0207eb02310138000a0207ec02310138000a0207ed02310138000a0207ee02310138000a0207ef02310138000a0207f002310138000a0207f102310138000a0207f202310138000a0207f302310138000a0207f402310138000a0207f502310138000a0207f602310138000a0207f702310138000a0207f802310138000a0207f902310138000a0207fa02310138000a0207fb02310138000a0207fc02310138000a0207fd02310138000a0207fe02310138000a0207ff02310138000a02078003310138000a02078103310138000a02078203310138000a02078303310138000a02078403310138000a02078503310138000a02078603310138000a02078703310138000a02078803310138000a02078903310138000a02078a03310138000a02078b03310138000a02078c03310138000a02078d03310138000a02078e03310138000a02078f03310138000a02079003310138000a02079103310138000a02079203310138000a02079303310138000a02079403310138000a02079503310138000a02079603310138000a02079703310138000a02079803310138000a02079903310138000a02079a03310138000a02079b03310138000a02079c03310138000a02079d03310138000a02079e03310138000a02079f03310138000a0207a003310138000a0207a103310138000a0207a203310138000a0207a303310138000a0207a403310138000a0207a503310138000a0207a603310138000a0207a703310138000a0207a803310138000a0207a903310138000a0207aa03310138000a0207ab03310138000a0207ac03310138000a0207ad03310138000a0207ae03310138000a0207af03310138000a0207b003310138000a0207b103310138000a0207b203310138000a0207b303310138000a0207b403310138000a0207b503310138000a0207b603310138000a0207b703310138000a0207b803310138000a0207b903310138000a0207ba03310138000a0207bb03310138000a0207bc03310138000a0207bd03310138000a0207be03310138000a0207bf03310138000a0207c003310138000a0207c103310138000a0207c203310138000a0207c303310138000a0207c403310138000a0207c503310138000a0207c603310138000a0207c703310138000a0207c803310138000a0207c903310138000a0207ca03310138000a0207cb03310138000a0207cc03310138000a0207cd03310138000a0207ce03310138000a0207cf03310138000a0207d003310138000a0207d103310138000a0207d203310138000a0207d303310138000a0207d403310138000a0207d503310138000a0207d603310138000a0207d703310138000a0207d803310138000a0207d903310138000a0207da03310138000a0207db03310138000a0207dc03310138000a0207dd03310138000a0207de03310138000a0207df03310138000a0207e003310138000a0207e103310138000a0207e203310138000a0207e303310138000a0207e403310138000a0207e503310138000a0207e603310138000a0207e703310138000a0207e803310138000a0207e903310138000a0207ea03310138000a0207eb03310138000a0207ec03310138000a0207ed03310138000a0207ee03310138000a0207ef03310138000a0207f003310138000a0207f103310138000a0207f203310138000a0207f303310138000a0207f403310138000a0207f503310138000a0207f603310138000a0207f703310138000a0207f803310138000a0207f903310138000a0207fa03310138000a0207fb03310138000a0207fc03310138000a0207fd03310138000a0207fe03310138000a0207ff03310138000a02078004310138000a02078104310138000a02078204310138000a02078304310138000a02078404310138000a02078504310138000a02078604310138000a02078704310138000a02078804310138000a02078904310138000a02078a04310138000a02078b04310138000a02078c04310138000a02078d04310138000a02078e04310138000a02078f04310138000a02079004310138000a02079104310138000a02079204310138000a02079304310138000a02079404310138000a02079504310138000a02079604310138000a02079704310138000a02079804310138000a02079904310138000a02079a04310138000a02079b04310138000a02079c04310138000a02079d04310138000a02079e04310138000a02079f04310138000a0207a004310138000a0207a104310138000a0207a204310138000a0207a304310138000a0207a404310138000a0207a504310138000a0207a604310138000a0207a704310138000a0207a804310138000a0207a904310138000a0207aa04310138000a0207ab04310138000a0207ac04310138000a0207ad04310138000a0207ae04310138000a0207af04310138000a0207b004310138000a0207b104310138000a0207b204310138000a0207b304310138000a0207b404310138000a0207b504310138000a0207b604310138000a0207b704310138000a0207b804310138000a0207b904310138000a0207ba04310138000a0207bb04310138000a0207bc04310138000a0207bd04310138000a0207be04310138000a0207bf04310138000a0207c004310138000a0207c104310138000a0207c204310138000a0207c304310138000a0207c404310138000a0207c504310138000a0207c604310138000a0207c704310138000a0207c804310138000a0207c904310138000a0207ca04310138000a0207cb04310138000a0207cc04310138000a0207cd04310138000a0207ce04310138000a0207cf04310138000a0207d004310138000a0207d104310138000a0207d204310138000a0207d304310138000a0207d404310138000a0207d504310138000a0207d604310138000a0207d704310138000a0207d804310138000a0207d904310138000a0207da04310138000a0207db04310138000a0207dc04310138000a0207dd04310138000a0207de04310138000a0207df04310138000a0207e004310138000a0207e104310138000a0207e204310138000a0207e304310138000a0207e404310138000a0207e504310138000a0207e604310138000a0207e704310138000a0207e804310138000a0207e904310138000a0207ea04310138000a0207eb04310138000a0207ec04310138000a0207ed04310138000a0207ee04310138000a0207ef04310138000a0207f004310138000a0207f104310138000a0207f204310138000a0207f304310138000a0207f404310138000a0207f504310138000a0207f604310138000a0207f704310138000a0207f804310138000a0207f904310138000a0207fa04310138000a0207fb04310138000a0207fc04310138000a0207fd04310138000a0207fe04310138000a0207ff04310138000a02078005310138000a02078105310138000a02078205310138000a02078305310138000a02078405310138000a02078505310138000a02078605310138000a02078705310138000a02078805310138000a02078905310138000a02078a05310138000a02078b05310138000a02078c05310138000a02078d05310138000a02078e05310138000a02078f05310138000a02079005310138000a02079105310138000a02079205310138000a02079305310138000a02079405310138000a02079505310138000a02079605310138000a02079705310138000a02079805310138000a02079905310138000a02079a05310138000a02079b05310138000a02079c05310138000a02079d05310138000a02079e05310138000a02079f05310138000a0207a005310138000a0207a105310138000a0207a205310138000a0207a305310138000a0207a405310138000a0207a505310138000a0207a605310138000a0207a705310138000a0207a805310138000a0207a905310138000a0207aa05310138000a0207ab05310138000a0207ac05310138000a0207ad05310138000a0207ae05310138000a0207af05310138000a0207b005310138000a0207b105310138000a0207b205310138000a0207b305310138000a0207b405310138000a0207b505310138000a0207b605310138000a0207b705310138000a0207b805310138000a0207b905310138000a0207ba05310138000a0207bb05310138000a0207bc05310138000a0207bd05310138000a0207be05310138000a0207bf05310138000a0207c005310138000a0207c105310138000a0207c205310138000a0207c305310138000a0207c405310138000a0207c505310138000a0207c605310138000a0207c705310138000a0207c805310138000a0207c905310138000a0207ca05310138000a0207cb05310138000a0207cc05310138000a0207cd05310138000a0207ce05310138000a0207cf05310138000a0207d005310138000a0207d105310138000a0207d205310138000a0207d305310138000a0207d405310138000a0207d505310138000a0207d605310138000a0207d705310138000a0207d805310138000a0207d905310138000a0207da05310138000a0207db05310138000a0207dc05310138000a0207dd05310138000a0207de05310138000a0207df05310138000a0207e005310138000a0207e105310138000a0207e205310138000a0207e305310138000a0207e405310138000a0207e505310138000a0207e605310138000a0207e705310138000a0207e805310138000a0207e905310138000a0207ea05310138000a0207eb05310138000a0207ec05310138000a0207ed05310138000a0207ee05310138000a0207ef05310138000a0207f005310138000a0207f105310138000a0207f205310138000a0207f305310138000a0207f405310138000a0207f505310138000a0207f605310138000a0207f705310138000a0207f805310138000a0207f905310138000a0207fa05310138000a0207fb05310138000a0207fc05310138000a0207fd05310138000a0207fe05310138000a0207ff05310138000a02078006310138000a02078106310138000a02078206310138000a02078306310138000a02078406310138000a02078506310138000a02078606310138000a02078706310138000a02078806310138000a02078906310138000a02078a06310138000a02078b06310138000a02078c06310138000a02078d06310138000a02078e06310138000a02078f06310138000a02079006310138000a02079106310138000a02079206310138000a02079306310138000a02079406310138000a02079506310138000a02079606310138000a02079706310138000a02079806310138000a02079906310138000a02079a06310138000a02079b06310138000a02079c06310138000a02079d06310138000a02079e06310138000a02079f06310138000a0207a006310138000a0207a106310138000a0207a206310138000a0207a306310138000a0207a406310138000a0207a506310138000a0207a606310138000a0207a706310138000a0207a806310138000a0207a906310138000a0207aa06310138000a0207ab06310138000a0207ac06310138000a0207ad06310138000a0207ae06310138000a0207af06310138000a0207b006310138000a0207b106310138000a0207b206310138000a0207b306310138000a0207b406310138000a0207b506310138000a0207b606310138000a0207b706310138000a0207b806310138000a0207b906310138000a0207ba06310138000a0207bb06310138000a0207bc06310138000a0207bd06310138000a0207be06310138000a0207bf06310138000a0207c006310138000a0207c106310138000a0207c206310138000a0207c306310138000a0207c406310138000a0207c506310138000a0207c606310138000a0207c706310138000a0207c806310138000a0207c906310138000a0207ca06310138000a0207cb06310138000a0207cc06310138000a0207cd06310138000a0207ce06310138000a0207cf06310138000a0207d006310138000a0207d106310138000a0207d206310138000a0207d306310138000a0207d406310138000a0207d506310138000a0207d606310138000a0207d706310138000a0207d806310138000a0207d906310138000a0207da06310138000a0207db06310138000a0207dc06310138000a0207dd06310138000a0207de06310138000a0207df06310138000a0207e006310138000a0207e106310138000a0207e206310138000a0207e306310138000a0207e406310138000a0207e506310138000a0207e606310138000a0207e706310138000a0207e806310138000a0207e906310138000a0207ea06310138000a0207eb06310138000a0207ec06310138000a0207ed06310138000a0207ee06310138000a0207ef06310138000a0207f006310138000a0207f106310138000a0207f206310138000a0207f306310138000a0207f406310138000a0207f506310138000a0207f606310138000a0207f706310138000a0207f806310138000a0207f906310138000a0207fa06310138000a0207fb06310138000a0207fc06310138000a0207fd06310138000a0207fe06310138000a0207ff06310138000a02078007310138000a02078107310138000a02078207310138000a02078307310138000a02078407310138000a02078507310138000a02078607310138000a02078707310138000a02078807310138000a02078907310138000a02078a07310138000a02078b07310138000a02078c07310138000a02078d07310138000a02078e07310138000a02078f07310138000a02079007310138000a02079107310138000a02079207310138000a02079307310138000a02079407310138000a02079507310138000a02079607310138000a02079707310138000a02079807310138000a02079907310138000a02079a07310138000a02079b07310138000a02079c07310138000a02079d07310138000a02079e07310138000a02079f07310138000a0207a007310138000a0207a107310138000a0207a207310138000a0207a307310138000a0207a407310138000a0207a507310138000a0207a607310138000a0207a707310138000a0207a807310138000a0207a907310138000a0207aa07310138000a0207ab07310138000a0207ac07310138000a0207ad07310138000a0207ae07310138000a0207af07310138000a0207b007310138000a0207b107310138000a0207b207310138000a0207b307310138000a0207b407310138000a0207b507310138000a0207b607310138000a0207b707310138000a0207b807310138000a0207b907310138000a0207ba07310138000a0207bb07310138000a0207bc07310138000a0207bd07310138000a0207be07310138000a0207bf07310138000a0207c007310138000a0207c107310138000a0207c207310138000a0207c307310138000a0207c407310138000a0207c507310138000a0207c607310138000a0207c707310138000a0207c807310138000a0207c907310138000a0207ca07310138000a0207cb07310138000a0207cc07310138000a0207cd07310138000a0207ce07310138000a0207cf07310138000a0207d007310138000a0207d107310138000a0207d207310138000a0207d307310138000a0207d407310138000a0207d507310138000a0207d607310138000a0207d707310138000a0207d807310138000a0207d907310138000a0207da07310138000a0207db07310138000a0207dc07310138000a0207dd07310138000a0207de07310138000a0207df07310138000a0207e007310138000a0207e107310138000a0207e207310138000a0207e307310138000a0207e407310138000a0207e507310138000a0207e607310138000a0207e707310138000a0207e807310138000a0207e907310138000a0207ea07310138000b0207eb0731013800020201000100090807032b000c010b0110000b00380102030100000b1f38020c010d0107ec07310138000d0107ed07310138000d0107ee07310138000d0107ef07310138000d01071a310138000d01071b310138000b000b0112002d00020401040100051c0b0011050c020b02070321030907012707032900030e0701270a011102031307022707032a000c030b030f000b0138030102000000"; - let res = run_binary_test("sample_whitelist", code); - assert!(res.is_ok(), "{:?}", res) -} - -#[test] -fn sample_coin_store() { - let code = "a11ceb0b050000000e01001e021e0c032acb0604f5065405c907a41207ed19e80908d523800206d5252c108126420ac326090bcc26040cd026fd86010dcdad01020ecfad01040000010101020103020402050306030704080509050a0607060b070c070d000e08010001011104010001000f00010200000010010201000012030101000013040103000000001404010300000000150401030000000016040103000000001704010300000000180401030000000019040103000000001a040103000000001b040103000000001c040103000000001d040103000000001e040103000000001f0401030000000020040103000000002104010300000000220401030000000023040103000000002404010300000000250401030000000026040103000000002704010300000000280401030000000029040103000000002a040103000000002b040103000000002c040103000000002d040103000000002e040103000000002f0401030000000030040103000000003104010300000000320401030000000033050103000000003405010300000000350501030000000036050103000000003705010300000000380501030000000039050103000000003a050103000000003b050103000000003c050103000000003d050103000000003e050103000000003f0501030000000040050103000000004105010300000000420501030000000043050103000000004405010300000000450501030000000046050103000000004705010300000000480501030000000049050103000000004a050103000000004b050103000000004c050103000000004d050103000000004e050103000000004f050103000000005005010300000000510601010000520701010000530801010000540901020000005509010200000056000102000000570a010200000058070102000000590a01020000005a0b01020000005b0001020000005c0c0103000000005d0c01020000005e0c01020000005f0701010000600701010000610201010000620701010000630d01010000640e010100006502030100006601030100006702030100016810020100016911010100096a0114020000046b0100020000016c16030100016d01030100090b1819020000040b1a1b020000016e030101000c6f011d0200000b70031e020000066b0100030000000771221e030000000872010202000008730102020000087424000200000e6a01140200000d0b261e020000037508400002760202000165070301000477014200057801430200000a790100020000060b1a1b03000000011226010100017a48030100580f590f5a135a155b135c0f5d175e135e1559175d0f5f155f136017611361156215600f6320632164216513661366156515671568136815691562136420671369136c0f6e136f135c17702070215817710f720f020303000103010b010109000d030403040404010101010404040d0304030404010101010404040402060c0b0101090002060c0301060c0b030403040404010104040403060c030304060c0303010a060c03040403030404010102050303060c050301090001060b0101090002070b010109000b01010900230b010109000b010109010403040b010109000403040404040b010109010403030304040b010109000b010109000b01010901070b00010900040404040b010109000b010109000b0101090104040b0101090104040209000901020404020901090002070b0101090003010901040b01010900040b0101090104040b010109000b010109010b010109000b01010901040b01010900030b0101090103020b010109000b01010901250303030403040b010109000403040404040b0101090103030304040b010109000b010109010b01010900070b000109000404040b010109000b0101090003040404030b0101090104030403030303010b0101090122040303040b010109000403040404040b0101090103030304040b010109000b010109000b01010901070b000109000404040b0101090003040b010109000404030b0101090104040309000901090203090109000902020b010109000323040404040b010109000403040404040b0101090103030304040b010109000b010109000b01010901070b000109000404050b01010900040b010109000b01010901040b0101090004040b0101090104040805070b01010900070b01010901030301040423040404040b010109000403040404040b0101090103030304040b010109000b010109010b01010900070b00010900040405040b0101090004040b010109000404040b01010901040402050b01010900240403040403040404040403030304040b010109000b010109010b01010900070b000109000b0101090104040504040b010109010b010109000b01010900040b01010900040b010109010b0101090104040b01010900200303030403030404030404040403030304040b010109000b010109010b01010900070b000109000b010109010404030b01010900040303040b010109001d040303030404030404040403030304040b010109000b010109010b01010900070b000109000b01010901040403040b0101090003040b010109001e040404030404030404040403030304040b010109000b010109010b01010900070b000109000b010109010404050b01010900040b010109000b01010901040b010109001e040404030404030404040403030304040b010109000b010109010b01010900070b000109000b0101090104040504040b0101090004040b010109002603030304030403040404040403030304040b010109010b01010900070b00010900040405030b010109000b0101090104040b01010900040b01010900030b01010901040b01010901040304200303030b010109000b010109010403030403040404040403030304040b010109010b01010900070b000109000404030b010109000b01010901040303041d0303030403030304030404040403030304040b01010900070b0001090004040303040303030421030303040404030404030404040403030304040b010109010b01010900070b000109000404050b01010900030b010109000b01010901040303041f0303030404040304030404040403030304040b010109010b01010900070b0001090004040503040403040304230403030403040404040403030304040b010109000b01010901070b0001090004040503040b01010901040b010109000b01010900040b01010900030b01010901040b0101090104041d0b010109000b01010901040303030403040404040403030304040b010109000b01010901070b00010900040403040b010109000b0101090103041e04040403030404030404040403030304040b010109000b01010901070b000109000404050b0101090003040b010109000b0101090103041c040404030304030404040403030304040b010109000b01010901070b00010900040405030404030404240404040403040404040403030304040b010109000b010109000b01010901070b000109000404050b01010901040b01010901040b010109010b010109000b01010900040b01010900040b010109010b0101090104041f04040b010109000b0101090104030403040404040403030304040b010109000b010109000b01010901070b000109000404050b01010901040b010109010b010109000b0101090104200404030303040304030404040403030304040b010109000b01010900070b000109000404050b01010901030b010109010b01010900040303041d040404030304030404040403030304040b010109000b01010900070b000109000404050b0101090103040b010109010b0101090003041e040404040404030404040403030304040b010109000b010109010b01010900070b000109000404050b01010901040b01010900040b010109010404240404040403040404040403030304040b010109000b010109000b01010901070b00010900040405040b010109000b0101090104040b01010900040b01010900040b01010901040b0101090104041f04040b010109000b0101090104030403040404040403030304040b010109000b010109000b01010901070b0001090004040504040b010109000b0101090104041f0404030303040304030404040403030304040b010109000b01010900070b00010900040405040304040303041c040404030304030404040403030304040b010109000b01010900070b000109000404050403040403041f04040404040404030404040403030304040b010109000b010109000b01010901070b000109000404050b01010900040b010109000b01010901040404010b0001090001050d05030403070b000109000b01010901040b01010900040303030b01010900040302010101011a0504040404070b00010900070b000109010404030303030b01010901040404040b010109000b010109000b010109000b010109000b010109010b010109010b010109010b010109010f03030305040404030b010109010b01010901040b0101090003030b010109000e04040305040404030b010109000b01010901040b010109010b010109010b010109000f030303030305040404030b010109010403030301070b01010900030b0101090003070b000109000a636f696e5f73746f726504636f696e056572726f72067369676e65720f416e696d6553776170506f6f6c563116416e696d6553776170506f6f6c56314c6962726172790e6c69717569646974795f706f6f6c06726f7574657203616d6d09546f6b656e537761700f546f6b656e53776170436f6e66696704737761700a616d6d5f726f7574657208616d6d5f737761700b4d79436f696e53746f726512616e696d65737761705f73746172737761700762616c616e636504436f696e076465706f736974066c3073307431066c3073317430066c3173307431066c3173307432066c3173307433066c3173307434066c3173307435066c3173317430066c3173317432066c3173317433066c3173317434066c3173317435066c3173327430066c3173327431066c3173327433066c3173327434066c3173327435066c3173337430066c3173337431066c3173337432066c3173337434066c3173337435066c3173347430066c3173347431066c3173347432066c3173347433066c3173347435066c3173357430066c3173357431066c3173357432066c3173357433066c3173357434066c3273307431066c3273307432066c3273307433066c3273307434066c3273307435066c3273317430066c3273317432066c3273317433066c3273317434066c3273317435066c3273327430066c3273327431066c3273327433066c3273327434066c3273327435066c3273337430066c3273337431066c3273337432066c3273337434066c3273337435066c3273347430066c3273347431066c3273347432066c3273347433066c3273347435066c3273357430066c3273357431066c3273357432066c3273357433066c3273357434036e65770d6e65775f66726f6d5f6d61696e0d6e65775f66726f6d5f7a65726f047330743104733174301073696d706c655f616e696d65737761701373696d706c655f616e696d65737761705f76320f73696d706c655f73746172737761701273696d706c655f73746172737761705f76321273696d706c655f73746172737761705f76331273746172737761705f616e696d657377617012737761705f61625f6c69717569647377617008737761705f61757810737761705f70616e63616b6573776170127472616e736665725f66726f6d5f6d61696e197472616e736665725f66726f6d5f6d61696e5f736372697074107472616e736665725f746f5f6d61696e177472616e736665725f746f5f6d61696e5f736372697074117472616e736665725f746f5f6f74686572187472616e736665725f746f5f6f746865725f7363726970740877697468647261770c77697468647261775f616c6c0c77697468647261775f616e790576616c7565056d657267650c6765745f7265736572766573116765745f72657365727665735f73697a650765787472616374047a65726f0c64657374726f795f7a65726f0e746f6b656e5f726573657276657321737761705f65786163745f785f746f5f795f6469726563745f65787465726e616c18737761705f65786163745f636f696e5f666f725f636f696e04785f617504795f61751c737761705f65786163745f636f696e5f666f725f636f696e5f6d75740a616464726573735f6f66117065726d697373696f6e5f64656e6965640e6765745f61646d696e5f6461746107636f6d70617265116765745f706f756e646167655f726174650b657874726163745f616c6cd1b58e44ea11ffd326a280c453b080fd8af294298815a00e65b6e2bffc48d6ac000000000000000000000000000000000000000000000000000000000000000116fe2df00ea7dde4a63409201f7f4e536bde7bb7335526a35d05111e68aa322c190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12bd35135844473187163ca197ca93b2ab014370587bb0ed3befff9e902d6bb541c755e4c8d7a6ab6d56f9289d97c43c1c94bde75ec09147c90d35cd1be61c8fb9c7efb4076dbe143cbcd98cfaaa929ecfc8f299203dfff63b95ccb6bfe19850faec42a352cc65eca17a9fa85d0fc602295897ed6b8b8af6a6c79ef490eb8f9eba0308915f0100000000000520d1b58e44ea11ffd326a280c453b080fd8af294298815a00e65b6e2bffc48d6ac126170746f733a3a6d657461646174615f76302e01915f010000000000234552524f525f5448455f4f55545055545f4c4553535f5448414e5f4d494e5f5245435600000201010b01010900000f001700010400010206ffffffffffffffff270101000100010507013c0037003800020201000100010607013c0036000b0038010203010400010206ffffffffffffffff2704010400010206ffffffffffffffff2705010400010206ffffffffffffffff2706010400010206ffffffffffffffff2707010400010206ffffffffffffffff2708010400010206ffffffffffffffff2709010400010206ffffffffffffffff270a010400010206ffffffffffffffff270b010400010206ffffffffffffffff270c010400010206ffffffffffffffff270d010400010206ffffffffffffffff270e010400010206ffffffffffffffff270f010400010206ffffffffffffffff2710010400010206ffffffffffffffff2711010400010206ffffffffffffffff2712010400010206ffffffffffffffff2713010400010206ffffffffffffffff2714010400010206ffffffffffffffff2715010400010206ffffffffffffffff2716010400010206ffffffffffffffff2717010400010206ffffffffffffffff2718010400010206ffffffffffffffff2719010400010206ffffffffffffffff271a010400010206ffffffffffffffff271b010400010206ffffffffffffffff271c010400010206ffffffffffffffff271d010400010206ffffffffffffffff271e010400010206ffffffffffffffff271f010400010206ffffffffffffffff2720010400010206ffffffffffffffff2721010400010206ffffffffffffffff2722010400010206ffffffffffffffff27230104010012f1010b05040638020c2c0c26050d38030c2b0c2e0b2b0c260b2e0c2c0b260b2c0c180c1738040c10350b10350c1f0c1e0a0432000000000000000000000000000000002104660a180a0c180a0a1a0a1f160c110a170a1f180a111a0c0f0a1e0a18180a0c180a0a1a0b111a0c110a0f0a11180a0b180a091a0c2f0a0f0a11180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c270a270a2f23045e054d0a270c2f0a0f0a11180a0b180a091a0a271a0b271632020000000000000000000000000000001a0c2705480b2f0b0f170a0b180a091a0c040a040b0b180c150b170b09180a15160c240b150b18180b241a320b000000000000000000000000000000170c130a130b0c180c160b1f0b0a180a16160c250b160b1e180b251a320b000000000000000000000000000000170c1a0a1a0a04170b0317010b04340c1407013c000c230a23370038000c1b0a2336000b1438050c200b0804ab010b200b133806320000000000000000000000000000000038070c190c120c2d0c2805b401380632000000000000000000000000000000000b200b1338080c120c190c280c2d0d280b1238010d2d0b1938090b2d0c220a2336000b283801380a0c290b0704cd010b220600000000000000000b290b1a34380b0c0d0c0e05d5010b290b1a340b22060000000000000000380c0c0e0c0d0b0e0b0d0c210c2a0a2336000b2138010b1b0b02160c1c0b23370038000c1d0a1d0a1c2404ea0105ee010b1c0b1d17270b2a380d0224010401001cef010b05040638020c2c0c26050d38030c2b0c2f0b2b0c260b2f0c2c0b260b2c0c190c180b060418380e0c0f0c0e0c0d0522380f0c300c290c2d0b290b2d0b300c0f0c0e0c0d0b0d0b0e0b0f010c11350b11350c1f0c1e0a04320000000000000000000000000000000021047a0a190a0c180a0a1a0a1f160c120a180a1f180a121a0c100a1e0a19180a0c180a0a1a0b121a0c120a100a12180a0b180a091a0c310a100a12180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c2a0a2a0a3123047205610a2a0c310a100a12180a0b180a091a0a2a1a0b2a1632020000000000000000000000000000001a0c2a055c0b310b10170a0b180a091a0c040a040b0b180c160b180b09180a16160c240b160b19180b241a320b000000000000000000000000000000170c140a140b0c180c170b1f0b0a180a17160c250b170b1e180b251a320b000000000000000000000000000000170a04170b0317010b04340c1507013c000c230a23370038000c1b0a2336000b1538050c200b0804bd010b200b143806320000000000000000000000000000000038070c1a0c130c2e0c2705c601380632000000000000000000000000000000000b200b1438080c130c1a0c270c2e0d270b1338010d2e0b1a38090b2e0c210a2336000b273801380a0c280b2138100c220a2336000b2238010b1b0b02160c1c0b23370038000c1d0a1d0a1c2404e80105ec010b1c0b1d17270b2838110225010401001fe8010b05040638020c2a0c24050d38030c290c2d0b290c240b2d0c2a0b240b2a0c170c160b06041738120c0f0c0e051e38130c260c2b0b260c0e0b2b0c0f0b0e350b0f350c1d0c1c0a0432000000000000000000000000000000002104720a170a0c180a0a1a0a1d160c100a160a1d180a101a0c0d0a1c0a17180a0c180a0a1a0b101a0c100a0d0a10180a0b180a091a0c2e0a0d0a10180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c270a270a2e23046a05590a270c2e0a0d0a10180a0b180a091a0a271a0b271632020000000000000000000000000000001a0c2705540b2e0b0d170a0b180a091a0c040a040b0b180c140b160b09180a14160c220b140b17180b221a320b000000000000000000000000000000170c120a120b0c180c150b1d0b0a180a15160c230b150b1c180b231a320b000000000000000000000000000000170a04170b0317010b04340c1307013c000c210a21370038000c190a2136000b1338050c1e0b0804b5010b1e0b123806320000000000000000000000000000000038070c180c110c2c0c2805be01380632000000000000000000000000000000000b1e0b1238080c110c180c280c2c0d280b1138010d2c0b1838090b2c0c200a2136000b283801380a0c250b2006000000000000000038140c1f0a2136000b1f38010b190b02160c1a0b21370038000c1b0a1b0a1a2404e10105e5010b1a0b1b17270b25381102260104010023f8010b05040638020c2c0c26050d38030c2b0c2e0b2b0c260b2e0c2c0b260b2c0c170c160b06041a3815353816350c0e0c0d05203817353818350c0e0c0d0b0d0b0e0c1d0c1c0a0432000000000000000000000000000000002104720a170a0c180a0a1a0a1d160c100a160a1d180a101a0c0f0a1c0a17180a0c180a0a1a0b101a0c100a0f0a10180a0b180a091a0c2f0a0f0a10180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c290a290a2f23046a05590a290c2f0a0f0a10180a0b180a091a0a291a0b291632020000000000000000000000000000001a0c2905540b2f0b0f170a0b180a091a0c040a040b0b180c140b160b09180a14160c220b140b17180b221a320b000000000000000000000000000000170c120a120b0c180c150b1d0b0a180a15160c230b150b1c180b231a320b000000000000000000000000000000170a04170b0317010b04340c1307010c240a243c000c210a21370038000c190a2136000b1338050c1e0b0804b7010b1e0a123806320000000000000000000000000000000038070c180c110c2d0c2a05c001380632000000000000000000000000000000000b1e0a1238080c110c180c2a0c2d0d2a0b1138010d2d0b1838090b2d0c200a2136000b2a3801380a0c270b240d200d270b12340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381901010b270c250b200c280b250c1f0a2136000b1f38010b190b02160c1a0b21370038000c1b0a1b0a1a2404f10105f5010b1a0b1b17270b28380d02270104010025e8010b05040638020c2b0c25050d38030c2a0c2e0b2a0c250b2e0c2b0b250b2b0c170c160b060417381a0c0e0c0d051e381b0c270c2c0b270b2c0c0e0c0d0b0d0b0e0c1d0c1c0a0432000000000000000000000000000000002104700a170a0c180a0a1a0a1d160c100a160a1d180a101a0c0f0a1c0a17180a0c180a0a1a0b101a0c100a0f0a10180a0b180a091a0c2f0a0f0a10180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c280a280a2f23046805570a280c2f0a0f0a10180a0b180a091a0a281a0b281632020000000000000000000000000000001a0c2805520b2f0b0f170a0b180a091a0c040a040b0b180c140b160b09180a14160c220b140b17180b221a320b000000000000000000000000000000170c120a120b0c180c150b1d0b0a180a15160c230b150b1c180b231a320b000000000000000000000000000000170a04170b0317010b04340c1307010c240a243c000c210a21370038000c190a2136000b1338050c1e0b0804b5010b1e0b123806320000000000000000000000000000000038070c180c110c2d0c2905be01380632000000000000000000000000000000000b1e0b1238080c110c180c290c2d0d290b1138010d2d0b1838090b2d0c1f0a2136000b293801380a0c260b240b1f381c0c200a2136000b2038010b190b02160c1a0b21370038000c1b0a1b0a1a2404e10105e5010b1a0b1b17270b26381102280104010027f20138040c0e350b0e350c150c140b06040d38020c2b0c24051438030c290c2e0b290c240b2e0c2b0b240b2b0c1b0c1a0a0432000000000000000000000000000000002104660a150a0c180a0a1a0a1b160c0f0a140a1b180a0f1a0c0d0a1a0a15180a0c180a0a1a0b0f1a0c0f0a0d0a0f180a0b180a091a0c2f0a0d0a0f180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a2f23045e054d0a250c2f0a0d0a0f180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c2505480b2f0b0d170a0b180a091a0c040a040b0b180c120b140b09180a12160c210b120b15180b211a320b000000000000000000000000000000170c100a100b0c180c130b1b0b0a180a13160c220b130b1a180b221a320b000000000000000000000000000000170c160a160a04170b0317010b04340c1107010c230a233c000c1f0a1f370038000c170a1f36000b1138050c1c0b0804ac010b1c06000000000000000038060b1034380c0c200c3005b40138060b10340b1c060000000000000000380b0c300c200b300b200c1d0c270b0704c4010b1d0b160b27320000000000000000000000000000000038080c280c2d0c2a0c2c05cd010b2732000000000000000000000000000000000b1d0b1638070c2d0c280c2c0c2a0d2a0b2838010d2c0b2d38090b2a0c1e0b2c0c260a1f36000b1e38010b170b02160c180b1f370038000c190a190a182404e80105ec010b180b1917270b233c0136010b26380902290104010028d90138040c11350b11350c190c180b06040e380e0c0f0c0e0c0d0518380f0c2a0c260c290b260b290b2a0c0f0c0e0c0d0b0d0b0e0b0f010c12350b12350c1e0c1d0a0432000000000000000000000000000000002104700a190a0c180a0a1a0a1e160c130a180a1e180a131a0c100a1d0a19180a0c180a0a1a0b131a0c130a100a13180a0b180a091a0c2b0a100a13180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c280a280a2b23046805570a280c2b0a100a13180a0b180a091a0a281a0b281632020000000000000000000000000000001a0c2805520b2b0b10170a0b180a091a0c040a040b0b180c160b180b09180a16160c240b160b19180b241a320b000000000000000000000000000000170c140a140b0c180c170b1e0b0a180a17160c250b170b1d180b251a320b000000000000000000000000000000170a04170b0317010b04340c1507013c000c220a22370038000c1a0a2236000b1538050c1f0b0804b2010b1f06000000000000000038060b1434380c0c230c2c05ba0138060b14340b1f060000000000000000380b0c2c0c230b2c0b230c200c270b2038100c210a2236000b2138010b1a0b02160c1b0b22370038000c1c0a1c0a1b2404d20105d6010b1b0b1c17270b273811022a0104010029d20138040c0f350b0f350c170c160b06040d38120c100c0e051438130c240c270b240c0e0b270c100b0e350b10350c1c0c1b0a0432000000000000000000000000000000002104680a170a0c180a0a1a0a1c160c110a160a1c180a111a0c0d0a1b0a17180a0c180a0a1a0b111a0c110a0d0a11180a0b180a091a0c280a0d0a11180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a28230460054f0a250c280a0d0a11180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c25054a0b280b0d170a0b180a091a0c040a040b0b180c140b160b09180a14160c220b140b17180b221a320b000000000000000000000000000000170c120a120b0c180c150b1c0b0a180a15160c230b150b1b180b231a320b000000000000000000000000000000170a04170b0317010b04340c1307013c000c200a20370038000c180a2036000b1338050c1d0b0804aa010b1d06000000000000000038060b1234380c0c210c2905b20138060b12340b1d060000000000000000380b0c290c210b290b210c1e0c260b1e06000000000000000038140c1f0a2036000b1f38010b180b02160c190b20370038000c1a0a1a0a192404cb0105cf010b190b1a17270b263811022b010401002ae20138040c10350b10350c170c160b0604103815353816350c0e0c0d05163817353818350c0e0c0d0b0d0b0e0c1c0c1b0a0432000000000000000000000000000000002104680a170a0c180a0a1a0a1c160c110a160a1c180a111a0c0f0a1b0a17180a0c180a0a1a0b111a0c110a0f0a11180a0b180a091a0c290a0f0a11180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c260a260a29230460054f0a260c290a0f0a11180a0b180a091a0a261a0b261632020000000000000000000000000000001a0c26054a0b290b0f170a0b180a091a0c040a040b0b180c140b160b09180a14160c220b140b17180b221a320b000000000000000000000000000000170c120a120b0c180c150b1c0b0a180a15160c230b150b1b180b231a320b000000000000000000000000000000170a04170b0317010b04340c1307010c240a243c000c200a20370038000c180a2036000b1338050c1d0b0804ac010b1d06000000000000000038060a1234380c0c210c2a05b40138060a12340b1d060000000000000000380b0c2a0c210b2a0b210c1e0c270b240d1e0d270b12340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381901010b270c250b1e0c280b250c1f0a2036000b1f38010b180b02160c190b20370038000c1a0a1a0a192404db0105df010b190b1a17270b28380d022c010401002bd20138040c10350b10350c170c160b06040d381a0c0e0c0d0514381b0c250c280b250b280c0e0c0d0b0d0b0e0c1c0c1b0a0432000000000000000000000000000000002104660a170a0c180a0a1a0a1c160c110a160a1c180a111a0c0f0a1b0a17180a0c180a0a1a0b111a0c110a0f0a11180a0b180a091a0c290a0f0a11180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c260a260a2923045e054d0a260c290a0f0a11180a0b180a091a0a261a0b261632020000000000000000000000000000001a0c2605480b290b0f170a0b180a091a0c040a040b0b180c140b160b09180a14160c220b140b17180b221a320b000000000000000000000000000000170c120a120b0c180c150b1c0b0a180a15160c230b150b1b180b231a320b000000000000000000000000000000170a04170b0317010b04340c1307010c240a243c000c200a20370038000c180a2036000b1338050c1d0b0804aa010b1d06000000000000000038060b1234380c0c210c2a05b20138060b12340b1d060000000000000000380b0c2a0c210b2a0b210c1e0c270b240b1e381c0c1f0a2036000b1f38010b180b02160c190b20370038000c1a0a1a0a192404cb0105cf010b190b1a17270b273811022d010401002cec010b050407380e0c0f0c0e0c0d0511380f0c310c240c2c0b240b2c0b310c0f0c0e0c0d0b0d0b0e0b0f010c11350b11350c170c160b06042138020c2e0c27052838030c2a0c300b2a0c270b300c2e0b270b2e0c1d0c1c0a04320000000000000000000000000000000021047a0a170a0c180a0a1a0a1d160c120a160a1d180a121a0c100a1c0a17180a0c180a0a1a0b121a0c120a100a12180a0b180a091a0c320a100a12180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c280a280a3223047205610a280c320a100a12180a0b180a091a0a281a0b281632020000000000000000000000000000001a0c28055c0b320b10170a0b180a091a0c040a040b0b180c140b160b09180a14160c210b140b17180b211a0b0c180c150b1d0b0a180a15160c220b150b1c180b221a0c180a180a04170b0317010b04340c1307010c230a233c000c200a20370038000c190a2036000b133805381d0c1e380a0c250b0704be010b1e0b180b25320000000000000000000000000000000038080c290c2f0c2b0c2d05c7010b2532000000000000000000000000000000000b1e0b1838070c2f0c290c2d0c2b0d2b0b2938010d2d0b2f38090b2b0c1f0b2d0c260a2036000b1f38010b190b02160c1a0b20370038000c1b0a1b0a1a2404e20105e6010b1a0b1b17270b233c0136010b263809022e010401002dd5010b050407380e0c0f0c0e0c0d0511380f0c2b0c260c2a0b260b2a0b2b0c0f0c0e0c0d0b0d0b0e0b0f010c13350b13350c1a0c1938040c14350b14350c200c1f0a0432000000000000000000000000000000002104700a1a0a0c180a0a1a0a20160c150a190a20180a151a0c120a1f0a1a180a0c180a0a1a0b151a0c150a120a15180a0b180a091a0c2c0a120a15180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c290a290a2c23046805570a290c2c0a120a15180a0b180a091a0a291a0b291632020000000000000000000000000000001a0c2905520b2c0b12170a0b180a091a0c040a040b0b180c170b190b09180a17160c240b170b1a180b241a0b0c180c180b200b0a180a18160c250b180b1f180b251a0c1b0a1b0a04170b0317010b04340c1607013c000c230a23370038000c1c0a2336000b163805381d0c21380a0c270b0704b1010b210600000000000000000b270b1b34380b0c100c1105b9010b270b1b340b21060000000000000000380c0c110c100b110b100c220c280a2336000b2238010b1c0b02160c1d0b23370038000c1e0a1e0a1d2404ce0105d2010b1d0b1e17270b28380d022f010401002ec6010b050407380e0c0f0c0e0c0d0511380f0c280c230c260b230b260b280c0f0c0e0c0d0b0d0b0e0b0f010c12350b12350c190c180b06042138120c130c11052838130c240c270b240c110b270c130b11350b13350c1e0c1d0a04320000000000000000000000000000000021047c0a190a0c180a0a1a0a1e160c140a180a1e180a141a0c100a1d0a19180a0c180a0a1a0b141a0c140a100a14180a0b180a091a0c290a100a14180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a2923047405630a250c290a100a14180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c25055e0b290b10170a0b180a091a0c040a040b0b180c160b180b09180a16160c210b160b19180b211a0b0c180c170b1e0b0a180a17160c220b170b1d180b221a0a04170b0317010b04340c1507013c000c200a20370038000c1a0a2036000b153805381d06000000000000000038140c1f0a2036000b1f38010b1a0b02160c1b0b20370038000c1c0a1c0a1b2404c10105c5010b1b0b1c17270230010401002fde010b050407380e0c0f0c0e0c0d0511380f0c2c0c270c2b0b270b2b0b2c0c0f0c0e0c0d0b0d0b0e0b0f010c13350b13350c1a0c190b0604243815353816350c110c10052a3817353818350c110c100b100b110c1f0c1e0a04320000000000000000000000000000000021047c0a1a0a0c180a0a1a0a1f160c140a190a1f180a141a0c120a1e0a1a180a0c180a0a1a0b141a0c140a120a14180a0b180a091a0c2d0a120a14180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c2a0a2a0a2d23047405630a2a0c2d0a120a14180a0b180a091a0a2a1a0b2a1632020000000000000000000000000000001a0c2a055e0b2d0b12170a0b180a091a0c040a040b0b180c170b190b09180a17160c230b170b1a180b231a0c150a150b0c180c180b1f0b0a180a18160c240b180b1e180b241a0a04170b0317010b04340c1607010c250a253c000c220a22370038000c1b0a2236000b163805381d0c20380a0c280b250d200d280b15340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381901010b280c260b200c290b260c210a2236000b2138010b1b0b02160c1c0b22370038000c1d0a1d0a1c2404d70105db010b1c0b1d17270b29380d02310104010030c8010b050407380e0c0f0c0e0c0d0511380f0c2a0c250c280b250b280b2a0c0f0c0e0c0d0b0d0b0e0b0f010c13350b13350c190c180b060421381a0c110c100528381b0c260c290b260b290c110c100b100b110c1e0c1d0a04320000000000000000000000000000000021047a0a190a0c180a0a1a0a1e160c140a180a1e180a141a0c120a1d0a19180a0c180a0a1a0b141a0c140a120a14180a0b180a091a0c2b0a120a14180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c270a270a2b23047205610a270c2b0a120a14180a0b180a091a0a271a0b271632020000000000000000000000000000001a0c27055c0b2b0b12170a0b180a091a0c040a040b0b180c160b180b09180a16160c220b160b19180b221a0b0c180c170b1e0b0a180a17160c230b170b1d180b231a0a04170b0317010b04340c1507010c240a243c000c210a21370038000c1a0a2136000b153805381d0c1f0b240b1f381c0c200a2136000b2038010b1a0b02160c1b0b21370038000c1c0a1c0a1b2404c30105c7010b1b0b1c172702320104010031e5010b05040638120c0f0c0e050d38130c220c2a0b220c0e0b2a0c0f0b0e350b0f350c150c140b06041938020c2c0c23052038030c280c2e0b280c230b2e0c2c0b230b2c0c1b0c1a0a0432000000000000000000000000000000002104720a150a0c180a0a1a0a1b160c100a140a1b180a101a0c0d0a1a0a15180a0c180a0a1a0b101a0c100a0d0a10180a0b180a091a0c2f0a0d0a10180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a2f23046a05590a250c2f0a0d0a10180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c2505540b2f0b0d170a0b180a091a0c040a040b0b180c120b140b09180a12160c1f0b120b15180b1f1a0b0c180c130b1b0b0a180a13160c200b130b1a180b201a0c160a160a04170b0317010b04340c1107010c210a213c000c1e0a1e370038000c170a1e36000b113805060000000000000000381e0c1d380a0c260b0704b7010b1d0b160b26320000000000000000000000000000000038080c270c2d0c290c2b05c0010b2632000000000000000000000000000000000b1d0b1638070c2d0c270c2b0c290d290b2738010d2b0b2d38090b290c1c0b2b0c240a1e36000b1c38010b170b02160c180b1e370038000c190a190a182404db0105df010b180b1917270b213c0136010b24380902330104010032ce010b05040638120c110c10050d38130c240c280b240c100b280c110b10350b11350c180c1738040c12350b12350c1e0c1d0a0432000000000000000000000000000000002104680a180a0c180a0a1a0a1e160c130a170a1e180a131a0c0f0a1d0a18180a0c180a0a1a0b131a0c130a0f0a13180a0b180a091a0c290a0f0a13180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a29230460054f0a250c290a0f0a13180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c25054a0b290b0f170a0b180a091a0c040a040b0b180c150b170b09180a15160c220b150b18180b221a0b0c180c160b1e0b0a180a16160c230b160b1d180b231a0c190a190a04170b0317010b04340c1407013c000c210a21370038000c1a0a2136000b143805060000000000000000381e0c20380a0c260b0704aa010b200600000000000000000b260b1934380b0c0d0c0e05b2010b260b19340b20060000000000000000380c0c0e0c0d0b0e0b0d0c1f0c270a2136000b1f38010b1a0b02160c1b0b21370038000c1c0a1c0a1b2404c70105cb010b1b0b1c17270b27380d0234010401002ec6010b05040638120c120c11050d38130c230c260b230c110b260c120b11350b12350c190c180b06041a380e0c0f0c0e0c0d0524380f0c280c240c270b240b270b280c0f0c0e0c0d0b0d0b0e0b0f010c13350b13350c1e0c1d0a04320000000000000000000000000000000021047c0a190a0c180a0a1a0a1e160c140a180a1e180a141a0c100a1d0a19180a0c180a0a1a0b141a0c140a100a14180a0b180a091a0c290a100a14180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a2923047405630a250c290a100a14180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c25055e0b290b10170a0b180a091a0c040a040b0b180c160b180b09180a16160c210b160b19180b211a0b0c180c170b1e0b0a180a17160c220b170b1d180b221a0a04170b0317010b04340c1507013c000c200a20370038000c1a0a2036000b153805060000000000000000381e38100c1f0a2036000b1f38010b1a0b02160c1b0b20370038000c1c0a1c0a1b2404c10105c5010b1b0b1c172702350104010033d7010b05040638120c110c10050d38130c250c290b250c100b290c110b10350b11350c180c170b06041c3815353816350c0e0c0d05223817353818350c0e0c0d0b0d0b0e0c1d0c1c0a0432000000000000000000000000000000002104740a180a0c180a0a1a0a1d160c120a170a1d180a121a0c0f0a1c0a18180a0c180a0a1a0b121a0c120a0f0a12180a0b180a091a0c2a0a0f0a12180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c260a260a2a23046c055b0a260c2a0a0f0a12180a0b180a091a0a261a0b261632020000000000000000000000000000001a0c2605560b2a0b0f170a0b180a091a0c040a040b0b180c150b170b09180a15160c210b150b18180b211a0c130a130b0c180c160b1d0b0a180a16160c220b160b1c180b221a0a04170b0317010b04340c1407010c230a233c000c200a20370038000c190a2036000b143805060000000000000000381e0c1f380a0c270b230d1f0d270b13340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381901010b270c240b1f0c280b240c1e0a2036000b1e38010b190b02160c1a0b20370038000c1b0a1b0a1a2404d00105d4010b1a0b1b17270b28380d02360104010034c1010b05040638120c110c10050d38130c230c260b230c100b260c110b10350b11350c170c160b060419381a0c0e0c0d0520381b0c240c270b240b270c0e0c0d0b0d0b0e0c1c0c1b0a0432000000000000000000000000000000002104720a170a0c180a0a1a0a1c160c120a160a1c180a121a0c0f0a1b0a17180a0c180a0a1a0b121a0c120a0f0a12180a0b180a091a0c280a0f0a12180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a2823046a05590a250c280a0f0a12180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c2505540b280b0f170a0b180a091a0c040a040b0b180c140b160b09180a14160c200b140b17180b201a0b0c180c150b1c0b0a180a15160c210b150b1b180b211a0a04170b0317010b04340c1307010c220a223c000c1f0a1f370038000c180a1f36000b133805060000000000000000381e0c1e0b220b1e381c0c1d0a1f36000b1d38010b180b02160c190b1f370038000c1a0a1a0a192404bc0105c0010b190b1a172702370104010035f9010b0504093815353816350c0e0c0d050f3817353818350c0e0c0d0b0d0b0e0c150c140b06041938020c2c0c24052038030c2a0c2f0b2a0c240b2f0c2c0b240b2c0c1b0c1a0a0432000000000000000000000000000000002104720a150a0c180a0a1a0a1b160c100a140a1b180a101a0c0f0a1a0a15180a0c180a0a1a0b101a0c100a0f0a10180a0b180a091a0c300a0f0a10180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c260a260a3023046a05590a260c300a0f0a10180a0b180a091a0a261a0b261632020000000000000000000000000000001a0c2605540b300b0f170a0b180a091a0c040a040b0b180c120b140b09180a12160c200b120b15180b201a320b000000000000000000000000000000170b0c180c130b1b0b0a180a13160c210b130b1a180b211a320b000000000000000000000000000000170c160a160a04170b0317010b04340c1107010c220a223c000c1f0a1f370038000c170a1f36000a1138050c1c38060c270a220d1c0d270b11340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381f01010b270c230b1c0c280b230c1e0b0704cb010b1e0b160b28320000000000000000000000000000000038080c290c2e0c2b0c2d05d4010b2832000000000000000000000000000000000b1e0b1638070c2e0c290c2d0c2b0d2b0b2938010d2d0b2e38090b2b0c1d0b2d0c250a1f36000b1d38010b170b02160c180b1f370038000c190a190a182404ef0105f3010b180b1917270b223c0136010b25380902380104010036e4010b0504093815353816350c0e0c0d050f3817353818350c0e0c0d0b0d0b0e0c180c1738040c12350b12350c1e0c1d0a0432000000000000000000000000000000002104680a180a0c180a0a1a0a1e160c130a170a1e180a131a0c110a1d0a18180a0c180a0a1a0b131a0c130a110a13180a0b180a091a0c2b0a110a13180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c270a270a2b230460054f0a270c2b0a110a13180a0b180a091a0a271a0b271632020000000000000000000000000000001a0c27054a0b2b0b11170a0b180a091a0c040a040b0b180c150b170b09180a15160c230b150b18180b231a320b000000000000000000000000000000170b0c180c160b1e0b0a180a16160c240b160b1d180b241a320b000000000000000000000000000000170c190a190a04170b0317010b04340c1407010c250a253c000c220a22370038000c1a0a2236000a1438050c1f38060c280b250d1f0d280b14340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381f01010b280c260b1f0c290b260c210b0704c0010b210600000000000000000b290b1934380b0c0f0c1005c8010b290b19340b21060000000000000000380c0c100c0f0b100b0f0c200c2a0a2236000b2038010b1a0b02160c1b0b22370038000c1c0a1c0a1b2404dd0105e1010b1b0b1c17270b2a380d02390104010037e0010b0504093815353816350c0e0c0d050f3817353818350c0e0c0d0b0d0b0e0c190c180b06041a380e0c110c100c0f0524380f0c2b0c260c2a0b260b2a0b2b0c110c100c0f0b0f0b100b11010c13350b13350c1e0c1d0a04320000000000000000000000000000000021047c0a190a0c180a0a1a0a1e160c140a180a1e180a141a0c120a1d0a19180a0c180a0a1a0b141a0c140a120a14180a0b180a091a0c2c0a120a14180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c290a290a2c23047405630a290c2c0a120a14180a0b180a091a0a291a0b291632020000000000000000000000000000001a0c29055e0b2c0b12170a0b180a091a0c040a040b0b180c160b180b09180a16160c220b160b19180b221a320b000000000000000000000000000000170b0c180c170b1e0b0a180a17160c230b170b1d180b231a320b000000000000000000000000000000170a04170b0317010b04340c1507010c240a243c000c210a21370038000c1a0a2136000a1538050c1f38060c270b240d1f0d270b15340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381f01010b270c250b1f0c280b2538100c200a2136000b2038010b1a0b02160c1b0b21370038000c1c0a1c0a1b2404d90105dd010b1b0b1c17270b283811023a0104010038d9010b0504093815353816350c0e0c0d050f3817353818350c0e0c0d0b0d0b0e0c170c160b06041938120c110c10052038130c240c280b240c100b280c110b10350b11350c1c0c1b0a0432000000000000000000000000000000002104740a170a0c180a0a1a0a1c160c120a160a1c180a121a0c0f0a1b0a17180a0c180a0a1a0b121a0c120a0f0a12180a0b180a091a0c290a0f0a12180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a2923046c055b0a250c290a0f0a12180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c2505560b290b0f170a0b180a091a0c040a040b0b180c140b160b09180a14160c200b140b17180b201a320b000000000000000000000000000000170b0c180c150b1c0b0a180a15160c210b150b1b180b211a320b000000000000000000000000000000170a04170b0317010b04340c1307010c220a223c000c1f0a1f370038000c180a1f36000a1338050c1d38060c260b220d1d0d260b13340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381f01010b260c230b1d0c270b2306000000000000000038140c1e0a1f36000b1e38010b180b02160c190b1f370038000c1a0a1a0a192404d20105d6010b190b1a17270b273811023b0104010039d9010b0504093815353816350c0e0c0d050f3817353818350c0e0c0d0b0d0b0e0c170c160b060419381a0c100c0f0520381b0c250c290b250b290c100c0f0b0f0b100c1c0c1b0a0432000000000000000000000000000000002104720a170a0c180a0a1a0a1c160c120a160a1c180a121a0c110a1b0a17180a0c180a0a1a0b121a0c120a110a12180a0b180a091a0c2a0a110a12180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c270a270a2a23046a05590a270c2a0a110a12180a0b180a091a0a271a0b271632020000000000000000000000000000001a0c2705540b2a0b11170a0b180a091a0c040a040b0b180c140b160b09180a14160c210b140b17180b211a320b000000000000000000000000000000170b0c180c150b1c0b0a180a15160c220b150b1b180b221a320b000000000000000000000000000000170a04170b0317010b04340c1307010c230a233c000c200a20370038000c180a2036000a1338050c1d38060c280a230d1d0d280b13340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381f01010b280c240b1d0c260b240c1e0b230b1e381c0c1f0a2036000b1f38010b180b02160c190b20370038000c1a0a1a0a192404d20105d6010b190b1a17270b263811023c010401003ae5010b050406381a0c0e0c0d050d381b0c230c2b0b230b2b0c0e0c0d0b0d0b0e0c150c140b06041738020c2d0c26051e38030c290c2f0b290c260b2f0c2d0b260b2d0c1b0c1a0a0432000000000000000000000000000000002104700a150a0c180a0a1a0a1b160c100a140a1b180a101a0c0f0a1a0a15180a0c180a0a1a0b101a0c100a0f0a10180a0b180a091a0c300a0f0a10180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c270a270a3023046805570a270c300a0f0a10180a0b180a091a0a271a0b271632020000000000000000000000000000001a0c2705520b300b0f170a0b180a091a0c040a040b0b180c120b140b09180a12160c200b120b15180b201a0b0c180c130b1b0b0a180a13160c210b130b1a180b211a0c160a160a04170b0317010b04340c1107010c220a223c000c1f0a1f370038000c170a1f36000b1138050c1c0a220b1c38200c1e380a0c240b0704b7010b1e0b160b24320000000000000000000000000000000038080c280c2e0c2a0c2c05c0010b2432000000000000000000000000000000000b1e0b1638070c2e0c280c2c0c2a0d2a0b2838010d2c0b2e38090b2a0c1d0b2c0c250a1f36000b1d38010b170b02160c180b1f370038000c190a190a182404db0105df010b180b1917270b223c0136010b253809023d010401003bd0010b050406381a0c0e0c0d050d381b0c260c2a0b260b2a0c0e0c0d0b0d0b0e0c180c1738040c12350b12350c1e0c1d0a0432000000000000000000000000000000002104660a180a0c180a0a1a0a1e160c130a170a1e180a131a0c110a1d0a18180a0c180a0a1a0b131a0c130a110a13180a0b180a091a0c2b0a110a13180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c270a270a2b23045e054d0a270c2b0a110a13180a0b180a091a0a271a0b271632020000000000000000000000000000001a0c2705480b2b0b11170a0b180a091a0c040a040b0b180c150b170b09180a15160c230b150b18180b231a0b0c180c160b1e0b0a180a16160c240b160b1d180b241a0c190a190a04170b0317010b04340c1407010c250a253c000c220a22370038000c1a0a2236000b1438050c1f0b250b1f38200c21380a0c280b0704ac010b210600000000000000000b280b1934380b0c0f0c1005b4010b280b19340b21060000000000000000380c0c100c0f0b100b0f0c200c290a2236000b2038010b1a0b02160c1b0b22370038000c1c0a1c0a1b2404c90105cd010b1b0b1c17270b29380d023e010401003cc8010b050406381a0c0e0c0d050d381b0c250c280b250b280c0e0c0d0b0d0b0e0c190c180b060418380e0c110c100c0f0522380f0c2a0c260c290b260b290b2a0c110c100c0f0b0f0b100b11010c13350b13350c1e0c1d0a04320000000000000000000000000000000021047a0a190a0c180a0a1a0a1e160c140a180a1e180a141a0c120a1d0a19180a0c180a0a1a0b141a0c140a120a14180a0b180a091a0c2b0a120a14180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c270a270a2b23047205610a270c2b0a120a14180a0b180a091a0a271a0b271632020000000000000000000000000000001a0c27055c0b2b0b12170a0b180a091a0c040a040b0b180c160b180b09180a16160c220b160b19180b221a0b0c180c170b1e0b0a180a17160c230b170b1d180b231a0a04170b0317010b04340c1507010c240a243c000c210a21370038000c1a0a2136000b1538050c1f0b240b1f382038100c200a2136000b2038010b1a0b02160c1b0b21370038000c1c0a1c0a1b2404c30105c7010b1b0b1c1727023f010401003dc1010b050406381a0c0e0c0d050d381b0c230c260b230b260c0e0c0d0b0d0b0e0c170c160b06041738120c110c10051e38130c240c270b240c100b270c110b10350b11350c1c0c1b0a0432000000000000000000000000000000002104720a170a0c180a0a1a0a1c160c120a160a1c180a121a0c0f0a1b0a17180a0c180a0a1a0b121a0c120a0f0a12180a0b180a091a0c280a0f0a12180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a2823046a05590a250c280a0f0a12180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c2505540b280b0f170a0b180a091a0c040a040b0b180c140b160b09180a14160c200b140b17180b201a0b0c180c150b1c0b0a180a15160c210b150b1b180b211a0a04170b0317010b04340c1307010c220a223c000c1f0a1f370038000c180a1f36000b1338050c1d0b220b1d382006000000000000000038140c1e0a1f36000b1e38010b180b02160c190b1f370038000c1a0a1a0a192404bc0105c0010b190b1a17270240010401003ed7010b050406381a0c0e0c0d050d381b0c260c2a0b260b2a0c0e0c0d0b0d0b0e0c180c170b06041a3815353816350c100c0f05203817353818350c100c0f0b0f0b100c1d0c1c0a0432000000000000000000000000000000002104720a180a0c180a0a1a0a1d160c120a170a1d180a121a0c110a1c0a18180a0c180a0a1a0b121a0c120a110a12180a0b180a091a0c2b0a110a12180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c290a290a2b23046a05590a290c2b0a110a12180a0b180a091a0a291a0b291632020000000000000000000000000000001a0c2905540b2b0b11170a0b180a091a0c040a040b0b180c150b170b09180a15160c220b150b18180b221a0c130a130b0c180c160b1d0b0a180a16160c230b160b1c180b231a0a04170b0317010b04340c1407010c240a243c000c210a21370038000c190a2136000b1438050c1e0a240b1e38200c20380a0c270b240d200d270b13340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381901010b270c250b200c280b250c1f0a2136000b1f38010b190b02160c1a0b21370038000c1b0a1b0a1a2404d00105d4010b1a0b1b17270b28380d02410300003f070b0139000c020b000b023f0002420104003f140a00116a0701210406050b0b0001060000000000000000116b270a000b01382139000c020b000b023f0002430104003f120a00116a0701210406050b0b0001060000000000000000116b27380a39000c010b000b013f000244010400010206ffffffffffffffff2745010400010206ffffffffffffffff27460104000102060000000000000000274701040100415b0b00116a0c030a030701210408050b060000000000000000116b270a033c000c070a0736000b0138050c0a0e0a38000c04116d0101010c0e38040c0d0c0c0b04350610270000000000000b0e1735180c050a050b0d35180c0b0b0c353210270000000000000000000000000000180b05160c090b0b0b091a340c060a060b0226043c05400b07010700273822044a0b0a06000000000000000038060b06380c0c080c0f055138060b060b0a060000000000000000380b0c0f0c080b0736000b0f38010b033c0136010b0838090248010400010206000000000000000027490104000102060000000000000000274a010401004493010b00116a0c040a040701210408050b060000000000000000116b270b03044f38020c140c1238230c0d0c0f0a01350a0d0b0f1735180c050b120b0d35180a05160c0b0b050b14180b0b1a0c070a070b023524042e05300700270a043c000c090a0936000b0138050b073806320000000000000000000000000000000038070c1c0c180c1a0c160d160b1838010d1a0b1c38090b0936000b1638010b043c0136010b1a380905920138020c130c1538230c0e0c100a01350a0e0b101735180c060b130b0e35180a06160c0c0b060b15180b0c1a0c080a080b023524047005720700270a043c010c0a0a0a36010b0138240c11380a32000000000000000000000000000000000b110b0838070c1d0c190c1b0c170d170b1938010d1b0b1d38090b0a36010b1b38090b043c0036000b173801024b010400010206ffffffffffffffff274c0104010045650b00116a0c0d0a0d0701210408050b060000000000000000116b270b08041138120c0b0c0a051838130c160c170b160c0a0b170c0b0b0a350b0b350c100c0f0b030b07180c0e0b0f0b06180a0e160c140b0e0b10180b141a340c0c0a0c0a0526043405380b050b0c17270a0d3c0036000b0438050c150b0904480b1506000000000000000038060b0c38250c130c18054f38060b0c0b1506000000000000000038260c180c130b180b130c1238110e1238270c110a110a0524045b055f0b050b1117270b0d3c0136010b123809024d0104010046650b00116a0c0d0a0d0701210408050b060000000000000000116b270b0804143815353816350c0b0c0a051a3817353818350c0b0c0a0b0a0b0b0c100c0f0b030b07180c0e0b0f0b06180a0e160c140b0e0b10180b141a340c0c0a0c0a0526043405380b050b0c17270a0d3c0036000a0438050c1238060c160a0d0d120d160b040600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381f01010b160c150b120c170b150c130e1338270c110a110a05240459055d0b050b1117270b0d3c0136010b1338090b173811024e0104010047590b00116a0c0f0a0f0701210408050b060000000000000000116b270b080412380e0c0c0c0b0c0a051c380f0c180c160c170b160b170b180c0c0c0b0c0a0b0a0b0b0b0c010c0d350b0d350c120c110b030b07180c100b110b06180a10160c150b100b12180b151a340c0e0a0e0a0526043c05400b050b0e17270a0f3c0036000b043805381d0c140e1438270c130a130a0524044f05530b050b1317270b0f3c0136010b143809024f03000100030a0b000b0138210c0207013c0036000b02380102500004010026170a00116a0c020a020701210408050d0b0001060000000000000000116b270b000b0138210c030b023c0036000b033801025103000100260c07010c010a013c0036000b0038050c020b010b02382802520004010026150b00116a0c020a020701210408050b060000000000000000116b270a023c0036000b0138050c030b020b033828025303000100030a07013c0036000b0138050c020b000b02382802540004010026150b00116a0c030a030701210408050b060000000000000000116b270b033c0036000b0238050c040b010b043828025503000100010607013c0036000b003805025603000100010507013c0036003829025703000100491707013c000c030a03370038000c020a000b022404110b0336000b0038050c0105150b03360038290c010b01020000000f001700"; - let res = run_binary_test("sample_coin_store", code); - assert!(res.is_ok(), "{:?}", res) -} - -#[test] -fn sample_liquidity_pool() { - let code = "a11ceb0b050000000e0100240224ab0103cf01b6030485056405e905eb0507d40bde0d08b2196006921ab80110ca1bd8070aa223ef010b9125160ca725c9120df0372a0e9a38280000010101020103010401050106000700080009000a000b000c000d000e000f021002110012080300010001000100130003000100010001001406030001000100010015060300010001000100160803000100010001001706030001000100010018060300010001000100190800001a0603000100010001001b0603000100010001001c0603000100010001001d06030001000100010220040100010d210003000100010001033804010601024f05010001025105010001015b0600105e0700027305010001057407001185010700001e00010100001f01010300000000220203030000000023040503000000002401060300000000250107030000000026010403000000002701040300000000280107030000000029010403000000002a010403000000002b080100002c010903000000002d010903000000002e030203000000002f0a0b01000030050103000000003108010300000000320c010300000000330c010300000000340d010300000000350e030300000000360d0103000000085f010901000f6011120010611314000862010901001063151200106407120010651612000766010902000002671c0701000768011501000e691e0700026a1f200100022221010100036b230101060a6c010100046d0828000c6e0827000b2b0801000a2b0801000e6f0415000e7015070002712a010100022e2b2001000e722e070007750101010008760101010001773334000778013503000000022b36370100027938010100027a011401000e7b140700027c012001000b7d010701000b7e0107000931080103000000017f083a01060b80010128000b81010701000b82010701000983014101030000000684010107001186010444001187014415000e88010b150017101a101e1a01181f1b201b1f101f1d2210221d1618231b2422051808182c102c1d2d1b242c0f300030141824312f102f1d30303218331b341b17303510351d3710371d38303a183b393b2c3b223b3b3b313b3c3b3d3b3e2439243e243d3f18243b243c0603030404040400010b0c010b0d03090009010902020b0c0109000b0c010901020303030b0c0109000b0c0109010b010309000901090203040403010301060c010105030303030302040402060c0303070b04030900090109020303040b0c010900030b0c0109010307020208120812081204081201090004040304030108120206081206081201020104020812081201060b0403090009010902030900090109020b0103070b000309000901090204070b04030900090109020b0c01090003030b0c01090103030209000901010b0d0309000901090201060b0c0109000109010304040402070b0c01090003010b0c010900020b0c010900060b10010900010b050309000901090202070b0e01090009000601070b040309000901090203030b0c0109000b0c01090104030404060b040309000901090203060b0403090009010902030301081101050e0303070b0003090009010902030b0c010b0d0309000901090204070b04030900090109020303030303030302070b0c0109000b0c0109000203060b0f010900010b030309000901090206040404040404030303030b01070b0003090009010902070b04030900090109020303040303030403010902010b02030900090109020b0b00030900090109020b10010b0d030900090109020b13010b0d030900090109020b0f010b0d03090009010902081408140b04030900090109020c060807030301060811010c020814081405060c081408140201030b100109000b130109000b0f010900010b13010900010b0803090009010902010b0e010900010b0903090009010902010b0603090009010902010b0b03090009010902010b0a0309000901090202070b0003090009010902070b040309000901090208030303030b0c010900030b0c0109010303050b0c0109000b0c010901100103030303070b0e010b0903090009010902070b0003090009010902070b04030900090109020304030b0c0109000304030b0c01090108010103070b0003090009010902030404040108150e6c69717569646974795f706f6f6c076163636f756e7404636f696e056576656e74067369676e657206737472696e670974696d657374616d700b636f696e5f68656c706572066375727665730b64616f5f73746f7261676509656d657267656e63790d676c6f62616c5f636f6e6669670a6c705f6163636f756e74076c705f636f696e046d6174680c737461626c655f6375727665047532353607757136347836340b4576656e747353746f726509466c6173686c6f616e0e466c6173686c6f616e4576656e74134c697175696469747941646465644576656e740d4c6971756964697479506f6f6c154c697175696469747952656d6f7665644576656e74124f7261636c65557064617465644576656e7415506f6f6c4163636f756e744361706162696c69747910506f6f6c437265617465644576656e7409537761704576656e741155706461746544414f4665654576656e740e5570646174654665654576656e741c6173736572745f6c705f76616c75655f69735f696e63726561736564146173736572745f706f6f6c5f756e6c6f636b656404436f696e024c50046275726e09666c6173686c6f616e156765745f63756d756c61746976655f7072696365730b6765745f64616f5f666565136765745f64616f5f666565735f636f6e666967136765745f646563696d616c735f7363616c6573076765745f6665650f6765745f666565735f636f6e666967116765745f72657365727665735f73697a650a696e697469616c697a650e69735f706f6f6c5f6578697374730e69735f706f6f6c5f6c6f636b6564046d696e741e6e65775f72657365727665735f61667465725f666565735f7363616c65640d7061795f666c6173686c6f616e0872656769737465720b7365745f64616f5f666565077365745f6665651073706c69745f6665655f746f5f64616f04737761700d7570646174655f6f7261636c6513706f6f6c5f637265617465645f68616e646c650b4576656e7448616e646c65166c69717569646974795f61646465645f68616e646c65186c69717569646974795f72656d6f7665645f68616e646c650b737761705f68616e646c6510666c6173686c6f616e5f68616e646c65156f7261636c655f757064617465645f68616e646c65117570646174655f6665655f68616e646c65157570646174655f64616f5f6665655f68616e646c6506785f6c6f616e06795f6c6f616e04785f696e05785f6f757404795f696e05795f6f75740b61646465645f785f76616c0b61646465645f795f76616c126c705f746f6b656e735f72656365697665640e636f696e5f785f726573657276650e636f696e5f795f72657365727665146c6173745f626c6f636b5f74696d657374616d70176c6173745f70726963655f785f63756d756c6174697665176c6173745f70726963655f795f63756d756c61746976650b6c705f6d696e745f6361700e4d696e744361706162696c6974790b6c705f6275726e5f6361700e4275726e4361706162696c69747907785f7363616c6507795f7363616c65066c6f636b6564036665650764616f5f6665650e72657475726e65645f785f76616c0e72657475726e65645f795f76616c106c705f746f6b656e735f6275726e65640a7369676e65725f636170105369676e65724361706162696c6974790763726561746f72076e65775f66656504553235360969735f737461626c65086c705f76616c756507636f6d706172650f69735f756e636f7272656c617465640966726f6d5f753132380866726f6d5f753634036d756c0969735f736f727465640576616c756506737570706c790c6d756c5f6469765f7531323807657874726163740a656d69745f6576656e74136173736572745f6e6f5f656d657267656e63790a616464726573735f6f661372657472696576655f7369676e65725f6361700b6d756c5f746f5f753132380473717274056d65726765076d756c5f64697610467265657a654361706162696c69747906537472696e670e6173736572745f69735f636f696e126173736572745f76616c69645f63757276651d6372656174655f7369676e65725f776974685f6361706162696c6974791b67656e65726174655f6c705f6e616d655f616e645f73796d626f6c1264657374726f795f667265657a655f63617008646563696d616c7306706f775f3130047a65726f0f6765745f64656661756c745f666565136765745f64656661756c745f64616f5f666565106e65775f6576656e745f68616e646c650d6765745f6665655f61646d696e146173736572745f76616c69645f64616f5f666565106173736572745f76616c69645f666565076465706f7369740b6e6f775f7365636f6e64730755513634783634086672616374696f6e07746f5f753132380c6f766572666c6f775f61646449bcc662ad23bb4f134aad8c8117c03f238bf3f03f324afe91ce231a559e8a6b00000000000000000000000000000000000000000000000000000000000000014e9fce03284c0ce0b86c88dd5a46f050cad2f4f33c4cdd29d98f501868558c81030864000000000000000308680000000000000003086e0000000000000003086a000000000000000308690000000000000003087000000000000000030866000000000000000308670000000000000003086d0000000000000003086b000000000000000308650000000000000003086f0000000000000003086c00000000000000030810270000000000000308e803000000000000052049bcc662ad23bb4f134aad8c8117c03f238bf3f03f324afe91ce231a559e8a6b126170746f733a3a6d657461646174615f7630c3070d6400000000000000174552525f57524f4e475f504149525f4f52444552494e47335768656e20636f696e73207573656420746f20637265617465207061697220686176652077726f6e67206f72646572696e672e6500000000000000184552525f504f4f4c5f4558495354535f464f525f50414952245768656e207061697220616c726561647920657869737473206f6e206163636f756e742e6600000000000000204552525f4e4f545f454e4f5547485f494e495449414c5f4c4951554944495459215768656e206e6f7420656e6f756768206c6971756964697479206d696e7465642e6700000000000000184552525f4e4f545f454e4f5547485f4c4951554944495459215768656e206e6f7420656e6f756768206c6971756964697479206d696e7465642e6800000000000000114552525f454d5054595f434f494e5f494e335768656e20626f7468205820616e6420592070726f766964656420666f7220737761702061726520657175616c207a65726f2e6900000000000000124552525f494e434f52524543545f535741504b5768656e20696e636f727265637420494e732f4f55547320617267756d656e74732070617373656420647572696e67207377617020616e64206d61746820646f65736e277420776f726b2e6a00000000000000194552525f494e434f52524543545f4255524e5f56414c5545531d496e636f7272656374206c7020636f696e206275726e2076616c7565736b00000000000000174552525f504f4f4c5f444f45535f4e4f545f4558495354225768656e20706f6f6c20646f65736e27742065786973747320666f7220706169722e6c000000000000000f4552525f554e524541434841424c451353686f756c64206e65766572206f636375722e6d00000000000000284552525f4e4f545f454e4f5547485f5045524d495353494f4e535f544f5f494e495449414c495a45525768656e2060696e697469616c697a65282960207472616e73616374696f6e206973207369676e6564207769746820616e79206163636f756e74206f74686572207468616e20406c6971756964737761702e6e00000000000000134552525f454d5054595f434f494e5f4c4f414e385768656e20626f7468205820616e6420592070726f766964656420666f7220666c6173686c6f616e2061726520657175616c207a65726f2e6f00000000000000124552525f504f4f4c5f49535f4c4f434b4544145768656e20706f6f6c206973206c6f636b65642e70000000000000000d4552525f4e4f545f41444d494e165768656e2075736572206973206e6f742061646d696e000208370b0e010b0803090009010902390b0e010b03030900090109023a0b0e010b05030900090109023b0b0e010b09030900090109023c0b0e010b02030900090109023d0b0e010b06030900090109023e0b0e010b0b030900090109023f0b0e010b0a0309000901090201020240034103020204420343034403450303020346034703480304020c490b0c0109004a0b0c0109014b034c044d044e0b0f010b0d03090009010902500b10010b0d03090009010902520353035401550356030502035703580359030602024c044d040702015a08110802015c0509020442034303440345030a02015d030b02015d0304180018051801180318021808180a180b1809180618000000000f3c38000303051a0b020a000b030a0111180c0a0b040b000b050b0111180c080e080e0a11190c060b063102210319070427053b3801031d05390b020b03180c0b0b0b111b070d070d18111c111d0c0c0b04111b0b05111b111d0c090e090e0c11190c070b07310221033b070427070c27020100000104170c070f3d000c000b003700140921030b070b2702020100020004195938020304070027070f3b00030907092738030e0038040c02070f3c000c0538050c040a05370138060c070a05370238070c0a0a02350a07350a0411210c080a02350a0a350b0411210c0b0a0806000000000000000024032d05320a0b060000000000000000240c010534090c010b01033a0b05010703270a0536010a0838080c060a0536020a0b38090c090a050b070b0a380a0b000b053703380b070f3c010c030b0336040b080b0b0b023902380c0b060b0902030100020004243e112538020305070027070f3b00030a07092738030a000600000000000000002403100513080c0205170a01060000000000000000240c020b02031b070227070f3c000c030a03370138060c040a03370238070c050a0336010a0038080c060a0336020a0138090c07080a033600150b030b040b05380a0b060b070b000b013903020401000104251e112538020305070027070f3b00030a0709273803070f3d000c030a033705140c010a033706140c020b033707140c000b010b020b00020501000104171038020304070027070f3b000309070927070f3d000c000b003708140206010001040103380d0700020701000104171338020304070027070f3b000309070927070f3d000c000a003709140b00370a14020801000104171038020304070027070f3b000309070927070f3d000c000b00370b140209010001040103380e070d020a010001042619112538020305070027070f3b00030a0709273803070f3d000c000a00370138060c010b00370238070c020b010b02020b01040027150a001126070f2103090b00010708270a0011270c010a000b0112072d070a0011280b001129020c010000010738020304070027070f3b00020d01000104171038020304070027070f3b000309070927070f3d000c000b00370014020e01000200042976112538020305070027070f3b00030a070927380338050c07070f3c000c080a08370138060c0c0a08370238070c0f0e0038060c0b0e0138070c0e0a07320000000000000000000000000000000021032305350a0b0a0e112a112b0c050a05070e2403300b08010706270b05070e170c03054f0a0b350a070a0c3511210c0a0a0e350b070a0f3511210c0d0a0a0a0d230348054b0b0a0c02054d0b0d0c020b020c030b030c090a090600000000000000002403590b08010707270a0836010b00380f0a0836020b0138100a090a08370c38110c060b080b0c0b0f380a070f3c010c040b04360d0b0b0b0e0b09390438120b06020f0000002d3b38010303050c0b00070d112a0b020a04112a170c06051a38000310070c270b000b020a04070d112e17350c050b050c060b060c093801031f05280b01070d112a0b030b04112a170c0805363800032c070c270b010b030b04070d112e17350c070b070c080b080c0a0b090b0a021001000200042f6e112538020305070027070f3b00030a0709270b023a030c0b0c070e0038060c060e0138070c0a0a06060000000000000000240319051c080c0305200a0a060000000000000000240c030b030324070127070f3c000c050a05370138060c090a05370238070c0d0b090a07160c090b0d0a0b160c0d0a0536010b00380f0a0536020b0138100a05370138060a05370238070a060a0a0a05370b1438130c0c0c080a053709140a05370a140b09350b0d350b080b0c38140a050a060a0a3815090b05360015070f3c010c040b04360e0b060b070b0a0b0b390538160211010001073263112538173818380203090b00010700273819070f3b002003120b0001070a27070f2b070c090b09100f11310c08381a0c060c050e080b050b06310608381b0c040c030c020b03381c0600000000000000000c0a0600000000000000000c0b381d032e0534381e11360c0a381f11360c0b38203821060000000000000000320000000000000000000000000000000032000000000000000000000000000000000b040b020b0a0b0b093822113939000c070e080b073f000e0838230e0838240e0838250e0838260e0838270e0838280e0838290e08382a0e08382b39010c010d01360f0b0011263906382c0e080b013f01021201040200043f27380203060b0001070027070f3b00030d0b000107092738030b001126113c2103150705270a01113d070f3c000c030a010b03360815070f3c010c020b0236100b013907382d021301040200043f27380203060b0001070027070f3b00030d0b000107092738030b001126113c2103150705270a01113e070f3c000c030a010b03360b15070f3c010c020b0236110b013908382e0214000000403b0a00370b140c0a0a003708140c040a0a0a0418070019060000000000000000220311051a0b0a0b041807001a060100000000000000160c0305200b0a0b041807001a0c030b030c050b010a05070d112e0c060b020b05070d112e0c080a0036010b0638080c070b0036020b0838090c09070f0b070b09382f02150100020004427b112538020305070027070f3b00030a07092738030e0038060c0c0e0238070c100a0c0600000000000000002403160519080c04051d0a10060000000000000000240c040b040321070127070f3c000c0b0a0b370138060c0e0a0b370238070c120a0b36010b00380f0a0b36020b0238100a0b36010a0138080c0f0a0b36020a0338090c130a0b370138060a0b370238070a0c0a100a0b370b1438130c110c0d0a0b3709140a0b370a140a0e350a12350b0d350b113538140a0b0a0c0a1038150b0b0b0e0b12380a070f3c010c0a0b0a36120c090b0c0c050b100c060b010c070b030c080b090b050b070b060b08390938300b0f0b1302160000010043540a003707140c0711400c050a050b0717350c0a0a0a320000000000000000000000000000000024031005150a01060000000000000000220c030517090c030b03031a051f0a02060000000000000000220c040521090c040b040324054f0a020a01114111420a0a180c080b010b02114111420b0a180c090a003705140b0811430a003605150a003706140b0911430a00360615070f3c010c060b0636130a003705140a00370614390a38310b050b003607150204090400040104060002040304040402040b04070408040a04050001000407000000000700060003000500180118021803180418051806180718081809180a180b180c180d180e181018111812181318141800"; - let res = run_binary_test("sample_liquidity_pool", code); - assert!(res.is_ok(), "{:?}", res) -} diff --git a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/bounds_tests.proptest-regressions b/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/bounds_tests.proptest-regressions deleted file mode 100644 index 3945bd370c9..00000000000 --- a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/bounds_tests.proptest-regressions +++ /dev/null @@ -1,10 +0,0 @@ -# Seeds for failure cases proptest has generated in the past. It is -# automatically read and these particular cases re-run before any -# novel cases are generated. -# -# It is recommended to check this file in to source control so that -# everyone who runs the test benefits from these saved cases. -cc 2beb0a0e65962432af560e626fa109d269b07db8807968413425f0bb14bb3667 # shrinks to module = CompiledModule: { datatype_handles: [ DatatypeHandle { module: ModuleHandleIndex(0), name: IdentifierIndex(0), is_resource: false }, DatatypeHandle { module: ModuleHandleIndex(0), name: IdentifierIndex(0), is_resource: false },] function_handles: [ FunctionHandle { module: ModuleHandleIndex(0), name: IdentifierIndex(0), signature: FunctionSignatureIndex(0) }, FunctionHandle { module: ModuleHandleIndex(0), name: IdentifierIndex(0), signature: FunctionSignatureIndex(1) },] struct_defs: [ StructDefinition { struct_handle: 1, access: 0x4, field_count: 0, fields: 0 },] field_defs: [] function_defs: [ FunctionDefinition { function: 1, access: 0x2, code: CodeUnit { max_stack_size: 0, locals: 0 code: [] } },] type_signatures: [ TypeSignature(Unit),] function_signatures: [ FunctionSignature { return_type: Unit, arg_types: [] }, FunctionSignature { return_type: Unit, arg_types: [] },] locals_signatures: [ LocalsSignature([]),] string_pool: [ "",] address_pool: [ Address([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),] } -cc c14ae393a6eefae82c0f4ede2acaa0aa0e993c1bba3fe3e5958e6e31cb5d2957 # shrinks to module = CompiledModule: { module_handles: [ ModuleHandle { address: AddressPoolIndex(0), name: IdentifierIndex(0) },] datatype_handles: [ DatatypeHandle { module: ModuleHandleIndex(0), name: IdentifierIndex(0), is_resource: false }, DatatypeHandle { module: ModuleHandleIndex(0), name: IdentifierIndex(0), is_resource: false },] function_handles: [ FunctionHandle { module: ModuleHandleIndex(0), name: IdentifierIndex(0), signature: FunctionSignatureIndex(0) }, FunctionHandle { module: ModuleHandleIndex(0), name: IdentifierIndex(0), signature: FunctionSignatureIndex(1) },] struct_defs: [ StructDefinition { struct_handle: 1, access: 0x4, field_count: 0, fields: 0 },] field_defs: [] function_defs: [ FunctionDefinition { function: 1, access: 0x2, code: CodeUnit { max_stack_size: 0, locals: 0 code: [] } },] type_signatures: [ TypeSignature(Unit),] function_signatures: [ FunctionSignature { return_type: Unit, arg_types: [] }, FunctionSignature { return_type: Unit, arg_types: [] },] locals_signatures: [ LocalsSignature([]),] string_pool: [ "",] address_pool: [ Address([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),] } , oob_mutations = [] -cc 88615e15ef42d29405cd91d6d0a573ccbeb833d0c7471f718ee794bc5ba399ca # shrinks to module = CompiledModule: { module_handles: [ ModuleHandle { address: AddressPoolIndex(0), name: IdentifierIndex(0) },] datatype_handles: [ DatatypeHandle { module: ModuleHandleIndex(0), name: IdentifierIndex(0), is_resource: false }, DatatypeHandle { module: ModuleHandleIndex(0), name: IdentifierIndex(0), is_resource: false }, DatatypeHandle { module: ModuleHandleIndex(0), name: IdentifierIndex(0), is_resource: false },] function_handles: [ FunctionHandle { module: ModuleHandleIndex(0), name: IdentifierIndex(0), signature: FunctionSignatureIndex(0) }, FunctionHandle { module: ModuleHandleIndex(0), name: IdentifierIndex(0), signature: FunctionSignatureIndex(1) },] struct_defs: [ StructDefinition { struct_handle: 1, access: 0x4, field_count: 0, fields: 0 }, StructDefinition { struct_handle: 2, access: 0x4, field_count: 0, fields: 0 },] field_defs: [] function_defs: [ FunctionDefinition { function: 1, access: 0x2, code: CodeUnit { max_stack_size: 0, locals: 0 code: [] } },] type_signatures: [ TypeSignature(Unit),] function_signatures: [ FunctionSignature { return_type: Unit, arg_types: [] }, FunctionSignature { return_type: Unit, arg_types: [] },] locals_signatures: [ LocalsSignature([]),] string_pool: [ "",] address_pool: [ Address([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),] } , oob_mutations = [OutOfBoundsMutation { src_kind: StructDefinition, src_idx: Index(0), dst_kind: FieldDefinition, offset: 0 }] -cc a34039f5d57751762a6eacf3ca3a2857781fb0bd0af0b7a06a9427f896f29aa9 # shrinks to module = CompiledModule: { module_handles: [ ModuleHandle { address: AddressPoolIndex(0), name: IdentifierIndex(0) },] datatype_handles: [ DatatypeHandle { module: ModuleHandleIndex(0), name: IdentifierIndex(0), is_resource: false }, DatatypeHandle { module: ModuleHandleIndex(0), name: IdentifierIndex(0), is_resource: false },] function_handles: [ FunctionHandle { module: ModuleHandleIndex(0), name: IdentifierIndex(0), signature: FunctionSignatureIndex(0) }, FunctionHandle { module: ModuleHandleIndex(0), name: IdentifierIndex(0), signature: FunctionSignatureIndex(1) },] struct_defs: [ StructDefinition { struct_handle: 1, access: 0x2, field_count: 0, fields: 0 },] field_defs: [] function_defs: [ FunctionDefinition { function: 1, access: 0x0, code: CodeUnit { max_stack_size: 0, locals: 0 code: [ BrTrue(1),] } },] type_signatures: [ TypeSignature(Unit), TypeSignature(Unit),] function_signatures: [ FunctionSignature { return_type: Unit, arg_types: [] }, FunctionSignature { return_type: Unit, arg_types: [] },] locals_signatures: [ LocalsSignature([]),] string_pool: [ "",] address_pool: [ Address([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),] } , oob_mutations = [] diff --git a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/bounds_tests.rs b/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/bounds_tests.rs deleted file mode 100644 index bdd3dd765f3..00000000000 --- a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/bounds_tests.rs +++ /dev/null @@ -1,363 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use move_binary_format::{check_bounds::BoundsChecker, file_format::*, file_format_common}; -use move_core_types::vm_status::StatusCode; - -#[test] -fn empty_module_no_errors() { - BoundsChecker::verify_module(&basic_test_module()).unwrap(); -} - -#[test] -fn invalid_default_module() { - BoundsChecker::verify_module(&CompiledModule { - version: file_format_common::VERSION_MAX, - ..Default::default() - }) - .unwrap_err(); -} - -#[test] -fn invalid_self_module_handle_index() { - let mut m = basic_test_module(); - m.self_module_handle_idx = ModuleHandleIndex(12); - assert_eq!( - BoundsChecker::verify_module(&m).unwrap_err().major_status(), - StatusCode::INDEX_OUT_OF_BOUNDS - ); -} - -#[test] -fn invalid_type_param_in_fn_return_() { - use SignatureToken::*; - - let mut m = basic_test_module(); - m.function_handles[0].return_ = SignatureIndex(1); - m.signatures.push(Signature(vec![TypeParameter(0)])); - assert_eq!(m.signatures.len(), 2); - assert_eq!( - BoundsChecker::verify_module(&m).unwrap_err().major_status(), - StatusCode::INDEX_OUT_OF_BOUNDS - ); -} - -#[test] -fn invalid_type_param_in_fn_parameters() { - use SignatureToken::*; - - let mut m = basic_test_module(); - m.function_handles[0].parameters = SignatureIndex(1); - m.signatures.push(Signature(vec![TypeParameter(0)])); - assert_eq!( - BoundsChecker::verify_module(&m).unwrap_err().major_status(), - StatusCode::INDEX_OUT_OF_BOUNDS - ); -} - -#[test] -fn invalid_struct_in_fn_return_() { - use SignatureToken::*; - - let mut m = basic_test_module(); - m.function_handles[0].return_ = SignatureIndex(1); - m.signatures - .push(Signature(vec![Datatype(DatatypeHandleIndex::new(1))])); - assert_eq!( - BoundsChecker::verify_module(&m).unwrap_err().major_status(), - StatusCode::INDEX_OUT_OF_BOUNDS - ); -} - -#[test] -fn invalid_type_param_in_field() { - use SignatureToken::*; - - let mut m = basic_test_module(); - match &mut m.struct_defs[0].field_information { - StructFieldInformation::Declared(ref mut fields) => { - fields[0].signature.0 = TypeParameter(0); - assert_eq!( - BoundsChecker::verify_module(&m).unwrap_err().major_status(), - StatusCode::INDEX_OUT_OF_BOUNDS - ); - } - _ => panic!("attempt to change a field that does not exist"), - } -} - -#[test] -fn invalid_struct_in_field() { - use SignatureToken::*; - - let mut m = basic_test_module(); - match &mut m.struct_defs[0].field_information { - StructFieldInformation::Declared(ref mut fields) => { - fields[0].signature.0 = Datatype(DatatypeHandleIndex::new(3)); - assert_eq!( - BoundsChecker::verify_module(&m).unwrap_err().major_status(), - StatusCode::INDEX_OUT_OF_BOUNDS - ); - } - _ => panic!("attempt to change a field that does not exist"), - } -} - -#[test] -fn invalid_struct_with_actuals_in_field() { - use SignatureToken::*; - - let mut m = basic_test_module(); - match &mut m.struct_defs[0].field_information { - StructFieldInformation::Declared(ref mut fields) => { - fields[0].signature.0 = DatatypeInstantiation(Box::new(( - DatatypeHandleIndex::new(0), - vec![TypeParameter(0)], - ))); - assert_eq!( - BoundsChecker::verify_module(&m).unwrap_err().major_status(), - StatusCode::NUMBER_OF_TYPE_ARGUMENTS_MISMATCH - ); - } - _ => panic!("attempt to change a field that does not exist"), - } -} - -#[test] -fn invalid_locals_id_in_call() { - use Bytecode::*; - - let mut m = basic_test_module(); - m.function_instantiations.push(FunctionInstantiation { - handle: FunctionHandleIndex::new(0), - type_parameters: SignatureIndex::new(1), - }); - let func_inst_idx = FunctionInstantiationIndex(m.function_instantiations.len() as u16 - 1); - m.function_defs[0].code.as_mut().unwrap().code = vec![CallGeneric(func_inst_idx)]; - assert_eq!( - BoundsChecker::verify_module(&m).unwrap_err().major_status(), - StatusCode::INDEX_OUT_OF_BOUNDS - ); -} - -#[test] -fn invalid_type_param_in_call() { - use Bytecode::*; - use SignatureToken::*; - - let mut m = basic_test_module(); - m.signatures.push(Signature(vec![TypeParameter(0)])); - m.function_instantiations.push(FunctionInstantiation { - handle: FunctionHandleIndex::new(0), - type_parameters: SignatureIndex::new(1), - }); - let func_inst_idx = FunctionInstantiationIndex(m.function_instantiations.len() as u16 - 1); - m.function_defs[0].code.as_mut().unwrap().code = vec![CallGeneric(func_inst_idx)]; - assert_eq!( - BoundsChecker::verify_module(&m).unwrap_err().major_status(), - StatusCode::INDEX_OUT_OF_BOUNDS - ); -} - -#[test] -fn invalid_struct_as_type_actual_in_exists() { - use Bytecode::*; - use SignatureToken::*; - - let mut m = basic_test_module(); - m.signatures - .push(Signature(vec![Datatype(DatatypeHandleIndex::new(3))])); - m.function_instantiations.push(FunctionInstantiation { - handle: FunctionHandleIndex::new(0), - type_parameters: SignatureIndex::new(1), - }); - let func_inst_idx = FunctionInstantiationIndex(m.function_instantiations.len() as u16 - 1); - m.function_defs[0].code.as_mut().unwrap().code = vec![CallGeneric(func_inst_idx)]; - assert_eq!( - BoundsChecker::verify_module(&m).unwrap_err().major_status(), - StatusCode::INDEX_OUT_OF_BOUNDS - ); -} - -#[test] -fn invalid_friend_module_address() { - let mut m = basic_test_module(); - m.friend_decls.push(ModuleHandle { - address: AddressIdentifierIndex::new(m.address_identifiers.len() as TableIndex), - name: IdentifierIndex::new(0), - }); - assert_eq!( - BoundsChecker::verify_module(&m).unwrap_err().major_status(), - StatusCode::INDEX_OUT_OF_BOUNDS - ); -} - -#[test] -fn invalid_friend_module_name() { - let mut m = basic_test_module(); - m.friend_decls.push(ModuleHandle { - address: AddressIdentifierIndex::new(0), - name: IdentifierIndex::new(m.identifiers.len() as TableIndex), - }); - assert_eq!( - BoundsChecker::verify_module(&m).unwrap_err().major_status(), - StatusCode::INDEX_OUT_OF_BOUNDS - ); -} - -#[test] -fn invalid_signature_for_vector_operation() { - use Bytecode::*; - - let skeleton = basic_test_module(); - let sig_index = SignatureIndex(skeleton.signatures.len() as u16); - for bytecode in [ - VecPack(sig_index, 0), - VecLen(sig_index), - VecImmBorrow(sig_index), - VecMutBorrow(sig_index), - VecPushBack(sig_index), - VecPopBack(sig_index), - VecUnpack(sig_index, 0), - VecSwap(sig_index), - ] { - let mut m = skeleton.clone(); - m.function_defs[0].code.as_mut().unwrap().code = vec![bytecode]; - assert_eq!( - BoundsChecker::verify_module(&m).unwrap_err().major_status(), - StatusCode::INDEX_OUT_OF_BOUNDS - ); - } -} - -#[test] -fn invalid_struct_for_vector_operation() { - use Bytecode::*; - use SignatureToken::*; - - let mut skeleton = basic_test_module(); - skeleton - .signatures - .push(Signature(vec![Datatype(DatatypeHandleIndex::new(3))])); - let sig_index = SignatureIndex((skeleton.signatures.len() - 1) as u16); - for bytecode in [ - VecPack(sig_index, 0), - VecLen(sig_index), - VecImmBorrow(sig_index), - VecMutBorrow(sig_index), - VecPushBack(sig_index), - VecPopBack(sig_index), - VecUnpack(sig_index, 0), - VecSwap(sig_index), - ] { - let mut m = skeleton.clone(); - m.function_defs[0].code.as_mut().unwrap().code = vec![bytecode]; - assert_eq!( - BoundsChecker::verify_module(&m).unwrap_err().major_status(), - StatusCode::INDEX_OUT_OF_BOUNDS - ); - } -} - -#[test] -fn invalid_type_param_for_vector_operation() { - use Bytecode::*; - use SignatureToken::*; - - let mut skeleton = basic_test_module(); - skeleton.signatures.push(Signature(vec![TypeParameter(0)])); - let sig_index = SignatureIndex((skeleton.signatures.len() - 1) as u16); - for bytecode in [ - VecPack(sig_index, 0), - VecLen(sig_index), - VecImmBorrow(sig_index), - VecMutBorrow(sig_index), - VecPushBack(sig_index), - VecPopBack(sig_index), - VecUnpack(sig_index, 0), - VecSwap(sig_index), - ] { - let mut m = skeleton.clone(); - m.function_defs[0].code.as_mut().unwrap().code = vec![bytecode]; - assert_eq!( - BoundsChecker::verify_module(&m).unwrap_err().major_status(), - StatusCode::INDEX_OUT_OF_BOUNDS - ); - } -} - -#[test] -fn invalid_variant_handle_index_for_enum_operation() { - use Bytecode::*; - - let skeleton = basic_test_module(); - let variant_handle_index = VariantHandleIndex(skeleton.variant_handles.len() as u16); - let variant_handle_inst_index = - VariantInstantiationHandleIndex(skeleton.variant_instantiation_handles.len() as u16); - for bytecode in [ - PackVariant(variant_handle_index), - UnpackVariant(variant_handle_index), - UnpackVariantImmRef(variant_handle_index), - UnpackVariantMutRef(variant_handle_index), - PackVariantGeneric(variant_handle_inst_index), - UnpackVariantGeneric(variant_handle_inst_index), - UnpackVariantGenericImmRef(variant_handle_inst_index), - UnpackVariantGenericMutRef(variant_handle_inst_index), - ] { - let mut m = skeleton.clone(); - m.function_defs[0].code.as_mut().unwrap().code = vec![bytecode]; - assert_eq!( - BoundsChecker::verify_module(&m).unwrap_err().major_status(), - StatusCode::INDEX_OUT_OF_BOUNDS - ); - } -} - -#[test] -fn invalid_variant_jump_table_index() { - use Bytecode::*; - - let skeleton = basic_test_module(); - let jt_index = VariantJumpTableIndex( - skeleton.function_defs[0] - .code - .as_ref() - .map(|c| c.jump_tables.len() as u16) - .unwrap_or(0u16), - ); - let mut m = skeleton.clone(); - m.function_defs[0].code.as_mut().unwrap().code = vec![VariantSwitch(jt_index)]; - assert_eq!( - BoundsChecker::verify_module(&m).unwrap_err().major_status(), - StatusCode::INDEX_OUT_OF_BOUNDS - ); -} - -#[test] -fn invalid_variant_jump_table_code_offset() { - use Bytecode::*; - - let mut skeleton = basic_test_module_with_enum(); - let enum_index = EnumDefinitionIndex(0); - skeleton.function_defs[0].code.as_mut().unwrap().code = vec![LdU64(0), Pop, Ret]; - skeleton.function_defs[0].code.as_mut().unwrap().jump_tables = vec![VariantJumpTable { - head_enum: enum_index, - jump_table: JumpTableInner::Full(vec![100]), - }]; - - let jt_index = VariantJumpTableIndex( - skeleton.function_defs[0] - .code - .as_ref() - .map(|c| c.jump_tables.len() as u16) - .unwrap_or(0u16), - ); - let mut m = skeleton.clone(); - m.function_defs[0].code.as_mut().unwrap().code = vec![VariantSwitch(jt_index)]; - assert_eq!( - BoundsChecker::verify_module(&m).unwrap_err().major_status(), - StatusCode::INDEX_OUT_OF_BOUNDS - ); -} diff --git a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/catch_unwind.rs b/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/catch_unwind.rs deleted file mode 100644 index 6b9fc629db0..00000000000 --- a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/catch_unwind.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use std::panic::{self, PanicInfo}; - -use fail::FailScenario; -use move_binary_format::file_format::empty_module; -use move_core_types::{ - state::{self, VMState}, - vm_status::StatusCode, -}; -use move_vm_config::verifier::VerifierConfig; - -#[ignore] -#[test] -fn test_unwind() { - let scenario = FailScenario::setup(); - fail::cfg("verifier-failpoint-panic", "panic").unwrap(); - - panic::set_hook(Box::new(move |_: &PanicInfo<'_>| { - assert_eq!(state::get_state(), VMState::VERIFIER); - })); - - let m = empty_module(); - let res = move_bytecode_verifier::verify_module_with_config(&VerifierConfig::unbounded(), &m) - .unwrap_err(); - assert_eq!(res.major_status(), StatusCode::VERIFIER_INVARIANT_VIOLATION); - scenario.teardown(); -} diff --git a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/code_unit_tests.rs b/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/code_unit_tests.rs deleted file mode 100644 index b380560a91a..00000000000 --- a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/code_unit_tests.rs +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use move_binary_format::file_format::Bytecode; -use move_bytecode_verifier::{ability_cache::AbilityCache, code_unit_verifier}; -use move_bytecode_verifier_meter::dummy::DummyMeter; -use move_core_types::vm_status::StatusCode; -use move_vm_config::verifier::VerifierConfig; - -use crate::support::dummy_procedure_module; - -#[test] -fn invalid_fallthrough_br_true() { - let module = &dummy_procedure_module(vec![Bytecode::LdFalse, Bytecode::BrTrue(1)]); - let ability_cache = &mut AbilityCache::new(module); - let result = code_unit_verifier::verify_module( - &Default::default(), - module, - ability_cache, - &mut DummyMeter, - ); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::INVALID_FALL_THROUGH - ); -} - -#[test] -fn invalid_fallthrough_br_false() { - let module = &dummy_procedure_module(vec![Bytecode::LdTrue, Bytecode::BrFalse(1)]); - let ability_cache = &mut AbilityCache::new(module); - let result = code_unit_verifier::verify_module( - &Default::default(), - module, - ability_cache, - &mut DummyMeter, - ); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::INVALID_FALL_THROUGH - ); -} - -// all non-branch instructions should trigger invalid fallthrough; just check -// one of them -#[test] -fn invalid_fallthrough_non_branch() { - let module = &dummy_procedure_module(vec![Bytecode::LdTrue, Bytecode::Pop]); - let ability_cache = &mut AbilityCache::new(module); - let result = code_unit_verifier::verify_module( - &Default::default(), - module, - ability_cache, - &mut DummyMeter, - ); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::INVALID_FALL_THROUGH - ); -} - -#[test] -fn valid_fallthrough_branch() { - let module = &dummy_procedure_module(vec![Bytecode::Branch(0)]); - let ability_cache = &mut AbilityCache::new(module); - let result = code_unit_verifier::verify_module( - &Default::default(), - module, - ability_cache, - &mut DummyMeter, - ); - assert!(result.is_ok()); -} - -#[test] -fn valid_fallthrough_ret() { - let module = &dummy_procedure_module(vec![Bytecode::Ret]); - let ability_cache = &mut AbilityCache::new(module); - let result = code_unit_verifier::verify_module( - &Default::default(), - module, - ability_cache, - &mut DummyMeter, - ); - assert!(result.is_ok()); -} - -#[test] -fn valid_fallthrough_abort() { - let module = &dummy_procedure_module(vec![Bytecode::LdU64(7), Bytecode::Abort]); - let ability_cache = &mut AbilityCache::new(module); - let result = code_unit_verifier::verify_module( - &Default::default(), - module, - ability_cache, - &mut DummyMeter, - ); - assert!(result.is_ok()); -} - -#[test] -fn test_max_number_of_bytecode() { - let mut nops = vec![]; - for _ in 0..u16::MAX - 1 { - nops.push(Bytecode::Nop); - } - nops.push(Bytecode::Ret); - let module = &dummy_procedure_module(nops); - let ability_cache = &mut AbilityCache::new(module); - - let result = code_unit_verifier::verify_module( - &VerifierConfig::default(), - module, - ability_cache, - &mut DummyMeter, - ); - assert!(result.is_ok()); -} - -#[test] -fn test_max_basic_blocks() { - let mut code = (0..17) - .map(|idx| Bytecode::Branch(idx + 1)) - .collect::>(); - code.push(Bytecode::Ret); - let module = &dummy_procedure_module(code); - let ability_cache = &mut AbilityCache::new(module); - - let result = code_unit_verifier::verify_module( - &VerifierConfig { - max_basic_blocks: Some(16), - ..Default::default() - }, - module, - ability_cache, - &mut DummyMeter, - ); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::TOO_MANY_BASIC_BLOCKS - ); -} diff --git a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/constants_tests.rs b/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/constants_tests.rs deleted file mode 100644 index 1dc747b5af0..00000000000 --- a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/constants_tests.rs +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use move_binary_format::file_format::{Constant, SignatureToken, empty_module}; -use move_bytecode_verifier::constants; -use move_core_types::vm_status::StatusCode; - -#[test] -fn valid_primitives() { - let mut module = empty_module(); - module.constant_pool = vec![ - Constant { - type_: SignatureToken::Bool, - data: vec![0], - }, - Constant { - type_: SignatureToken::U8, - data: vec![0], - }, - Constant { - type_: SignatureToken::U16, - data: vec![0, 0], - }, - Constant { - type_: SignatureToken::U32, - data: vec![0, 0, 0, 0], - }, - Constant { - type_: SignatureToken::U64, - data: vec![0, 0, 0, 0, 0, 0, 0, 0], - }, - Constant { - type_: SignatureToken::U128, - data: vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - }, - Constant { - type_: SignatureToken::U256, - data: vec![ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - ], - }, - Constant { - type_: SignatureToken::Address, - data: vec![ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - ], - }, - ]; - assert!(constants::verify_module(&module).is_ok()); -} - -#[test] -fn invalid_primitives() { - malformed(SignatureToken::U8, vec![0, 0]); - malformed(SignatureToken::U16, vec![0, 0, 0, 0]); - malformed(SignatureToken::U32, vec![0, 0, 0]); - malformed(SignatureToken::U64, vec![0]); - malformed(SignatureToken::U128, vec![0]); - malformed(SignatureToken::U256, vec![0, 0]); - let data = vec![ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - ]; - malformed(SignatureToken::Address, data); -} - -#[test] -fn valid_vectors() { - let double_vec = |item: Vec| -> Vec { - let mut items = vec![2]; - items.extend(item.clone()); - items.extend(item); - items - }; - let large_vec = |item: Vec| -> Vec { - let mut items = vec![0xFF, 0xFF, 3]; - (0..0xFFFF).for_each(|_| items.extend(item.clone())); - items - }; - let mut module = empty_module(); - module.constant_pool = vec![ - // empty - Constant { - type_: tvec(SignatureToken::Bool), - data: vec![0], - }, - Constant { - type_: tvec(tvec(SignatureToken::Bool)), - data: vec![0], - }, - Constant { - type_: tvec(tvec(tvec(tvec(SignatureToken::Bool)))), - data: vec![0], - }, - Constant { - type_: tvec(tvec(tvec(tvec(SignatureToken::Bool)))), - data: double_vec(vec![0]), - }, - // small - Constant { - type_: tvec(SignatureToken::Bool), - data: vec![9, 1, 1, 1, 1, 1, 1, 1, 1, 1], - }, - Constant { - type_: tvec(SignatureToken::U8), - data: vec![9, 1, 1, 1, 1, 1, 1, 1, 1, 1], - }, - // large - Constant { - type_: tvec(SignatureToken::Bool), - data: large_vec(vec![0]), - }, - Constant { - type_: tvec(SignatureToken::U8), - data: large_vec(vec![0]), - }, - Constant { - type_: tvec(SignatureToken::U16), - data: large_vec(vec![0, 0]), - }, - Constant { - type_: tvec(SignatureToken::U32), - data: large_vec(vec![0, 0, 0, 0]), - }, - Constant { - type_: tvec(SignatureToken::U64), - data: large_vec(vec![0, 0, 0, 0, 0, 0, 0, 0]), - }, - Constant { - type_: tvec(SignatureToken::U128), - data: large_vec(vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - }, - Constant { - type_: tvec(SignatureToken::U256), - data: large_vec(vec![ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - ]), - }, - Constant { - type_: tvec(SignatureToken::Address), - data: large_vec(vec![ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - ]), - }, - // double large - Constant { - type_: tvec(tvec(SignatureToken::Bool)), - data: double_vec(large_vec(vec![0])), - }, - Constant { - type_: tvec(tvec(SignatureToken::U8)), - data: double_vec(large_vec(vec![0])), - }, - Constant { - type_: tvec(tvec(SignatureToken::U16)), - data: double_vec(large_vec(vec![0, 0])), - }, - Constant { - type_: tvec(tvec(SignatureToken::U32)), - data: double_vec(large_vec(vec![0, 0, 0, 0])), - }, - Constant { - type_: tvec(tvec(SignatureToken::U64)), - data: double_vec(large_vec(vec![0, 0, 0, 0, 0, 0, 0, 0])), - }, - Constant { - type_: tvec(tvec(SignatureToken::U128)), - data: double_vec(large_vec(vec![ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ])), - }, - Constant { - type_: tvec(tvec(SignatureToken::U256)), - data: double_vec(large_vec(vec![ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - ])), - }, - Constant { - type_: tvec(tvec(SignatureToken::Address)), - data: double_vec(large_vec(vec![ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - ])), - }, - ]; - assert!(constants::verify_module(&module).is_ok()); -} - -#[test] -fn invalid_vectors() { - let double_vec = |item: Vec| -> Vec { - let mut items = vec![2]; - items.extend(item.clone()); - items.extend(item); - items - }; - let too_large_vec = |item: Vec| -> Vec { - let mut items = vec![0xFF, 0xFF, 3]; - (0..(0xFFFF + 1)).for_each(|_| items.extend(item.clone())); - items - }; - // wrong inner - malformed(tvec(SignatureToken::U16), vec![1, 0]); - malformed(tvec(SignatureToken::U32), vec![1, 0]); - malformed(tvec(SignatureToken::U64), vec![1, 0]); - malformed(tvec(SignatureToken::Address), vec![ - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - ]); - // wrong lens - malformed(tvec(SignatureToken::U8), vec![0, 0]); - malformed(tvec(SignatureToken::U8), vec![0, 1]); - malformed(tvec(SignatureToken::U8), vec![2, 1, 1, 1]); - malformed(tvec(tvec(SignatureToken::U8)), double_vec(vec![0, 0])); - // too large - malformed(tvec(SignatureToken::U8), too_large_vec(vec![0])); -} - -#[test] -fn invalid_types() { - invalid_type(SignatureToken::TypeParameter(0), vec![0]); - invalid_type(SignatureToken::TypeParameter(0xFA), vec![0]); - invalid_type(tvec(SignatureToken::TypeParameter(0)), vec![0]); - invalid_type(tvec(SignatureToken::TypeParameter(0xAF)), vec![0]); - - invalid_type(SignatureToken::Signer, vec![0]); - invalid_type(tvec(SignatureToken::Signer), vec![0]); - - // TODO cannot check structs are banned currently. This can be handled by IR - // and source lang tests - // invalid_type(SignatureToken::Datatype(DatatypeHandleIndex(0)), vec![0]); -} - -fn tvec(s: SignatureToken) -> SignatureToken { - SignatureToken::Vector(Box::new(s)) -} - -fn malformed(type_: SignatureToken, data: Vec) { - error(type_, data, StatusCode::MALFORMED_CONSTANT_DATA) -} - -fn invalid_type(type_: SignatureToken, data: Vec) { - error(type_, data, StatusCode::INVALID_CONSTANT_TYPE) -} - -fn error(type_: SignatureToken, data: Vec, code: StatusCode) { - let mut module = empty_module(); - module.constant_pool = vec![Constant { type_, data }]; - assert!( - constants::verify_module(&module) - .unwrap_err() - .major_status() - == code - ) -} diff --git a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/control_flow_tests.rs b/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/control_flow_tests.rs deleted file mode 100644 index 2f5d9070bf1..00000000000 --- a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/control_flow_tests.rs +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use move_binary_format::{ - errors::PartialVMResult, - file_format::{Bytecode, CompiledModule, FunctionDefinitionIndex, TableIndex}, -}; -use move_bytecode_verifier::control_flow; -use move_bytecode_verifier_meter::dummy::DummyMeter; -use move_core_types::vm_status::StatusCode; -use move_vm_config::verifier::VerifierConfig; - -use crate::support::dummy_procedure_module; - -fn verify_module(verifier_config: &VerifierConfig, module: &CompiledModule) -> PartialVMResult<()> { - for (idx, function_definition) in module - .function_defs() - .iter() - .enumerate() - .filter(|(_, def)| !def.is_native()) - { - let current_function = FunctionDefinitionIndex(idx as TableIndex); - let code = function_definition - .code - .as_ref() - .expect("unexpected native function"); - - control_flow::verify_function( - verifier_config, - module, - current_function, - function_definition, - code, - &mut DummyMeter, - )?; - } - Ok(()) -} - -//************************************************************************************************** -// Simple cases - Copied from code unit verifier -//************************************************************************************************** - -#[test] -fn empty_bytecode() { - let module = dummy_procedure_module(vec![]); - let result = verify_module(&Default::default(), &module); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::EMPTY_CODE_UNIT, - ); -} - -#[test] -fn empty_bytecode_v5() { - let mut module = dummy_procedure_module(vec![]); - module.version = 5; - - let result = verify_module(&Default::default(), &module); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::EMPTY_CODE_UNIT, - ); -} - -#[test] -fn invalid_fallthrough_br_true() { - let module = dummy_procedure_module(vec![Bytecode::LdFalse, Bytecode::BrTrue(1)]); - let result = verify_module(&Default::default(), &module); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::INVALID_FALL_THROUGH - ); -} - -#[test] -fn invalid_fallthrough_br_false() { - let module = dummy_procedure_module(vec![Bytecode::LdTrue, Bytecode::BrFalse(1)]); - let result = verify_module(&Default::default(), &module); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::INVALID_FALL_THROUGH - ); -} - -// all non-branch instructions should trigger invalid fallthrough; just check -// one of them -#[test] -fn invalid_fallthrough_non_branch() { - let module = dummy_procedure_module(vec![Bytecode::LdTrue, Bytecode::Pop]); - let result = verify_module(&Default::default(), &module); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::INVALID_FALL_THROUGH - ); -} - -#[test] -fn valid_fallthrough_branch() { - let module = dummy_procedure_module(vec![Bytecode::Branch(0)]); - let result = verify_module(&Default::default(), &module); - assert!(result.is_ok()); -} - -#[test] -fn valid_fallthrough_ret() { - let module = dummy_procedure_module(vec![Bytecode::Ret]); - let result = verify_module(&Default::default(), &module); - assert!(result.is_ok()); -} - -#[test] -fn valid_fallthrough_abort() { - let module = dummy_procedure_module(vec![Bytecode::LdU64(7), Bytecode::Abort]); - let result = verify_module(&Default::default(), &module); - assert!(result.is_ok()); -} - -#[test] -fn nested_loops_max_depth() { - let module = dummy_procedure_module(vec![ - Bytecode::LdFalse, - Bytecode::LdFalse, - Bytecode::BrFalse(1), - Bytecode::BrFalse(0), - Bytecode::Ret, - ]); - let result = verify_module( - &VerifierConfig { - max_loop_depth: Some(2), - ..VerifierConfig::default() - }, - &module, - ); - assert!(result.is_ok()); -} - -#[test] -fn nested_loops_exceed_max_depth() { - let module = dummy_procedure_module(vec![ - Bytecode::LdFalse, - Bytecode::LdFalse, - Bytecode::LdFalse, - Bytecode::BrFalse(2), - Bytecode::BrFalse(1), - Bytecode::BrFalse(0), - Bytecode::Ret, - ]); - let result = verify_module( - &VerifierConfig { - max_loop_depth: Some(2), - ..VerifierConfig::default() - }, - &module, - ); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::LOOP_MAX_DEPTH_REACHED - ); -} - -#[test] -fn non_loop_backward_jump() { - let module = dummy_procedure_module(vec![ - Bytecode::Branch(2), - Bytecode::Ret, - Bytecode::Branch(1), - ]); - let result = verify_module(&Default::default(), &module); - assert!(result.is_ok()); -} - -#[test] -fn non_loop_backward_jump_v5() { - let mut module = dummy_procedure_module(vec![ - Bytecode::Branch(2), - Bytecode::Ret, - Bytecode::Branch(1), - ]); - - module.version = 5; - let result = verify_module(&Default::default(), &module); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::INVALID_LOOP_SPLIT, - ); -} - -#[test] -fn irreducible_control_flow_graph() { - let module = dummy_procedure_module(vec![ - Bytecode::LdTrue, - Bytecode::BrTrue(3), - Bytecode::Nop, - Bytecode::LdFalse, - Bytecode::BrFalse(2), - Bytecode::Ret, - ]); - let result = verify_module(&Default::default(), &module); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::INVALID_LOOP_SPLIT, - ); -} - -#[test] -fn nested_loop_break() { - let module = dummy_procedure_module(vec![ - Bytecode::LdFalse, - Bytecode::LdFalse, - Bytecode::LdFalse, - Bytecode::Branch(7), - Bytecode::BrFalse(2), - Bytecode::BrFalse(1), - Bytecode::BrFalse(0), - Bytecode::Ret, - ]); - let result = verify_module(&Default::default(), &module); - assert!(result.is_ok()); -} - -#[test] -fn nested_loop_break_v5() { - let mut module = dummy_procedure_module(vec![ - Bytecode::LdFalse, - Bytecode::LdFalse, - Bytecode::LdFalse, - Bytecode::Branch(7), - Bytecode::BrFalse(2), - Bytecode::BrFalse(1), - Bytecode::BrFalse(0), - Bytecode::Ret, - ]); - - module.version = 5; - let result = verify_module(&Default::default(), &module); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::INVALID_LOOP_BREAK, - ); -} diff --git a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/duplication_tests.rs b/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/duplication_tests.rs deleted file mode 100644 index 5c40fa75adb..00000000000 --- a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/duplication_tests.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use move_binary_format::file_format::*; -use move_bytecode_verifier::DuplicationChecker; - -#[test] -fn duplicated_friend_decls() { - let mut m = basic_test_module(); - let handle = ModuleHandle { - address: AddressIdentifierIndex::new(0), - name: IdentifierIndex::new(0), - }; - m.friend_decls.push(handle.clone()); - m.friend_decls.push(handle); - DuplicationChecker::verify_module(&m).unwrap_err(); -} - -#[test] -fn duplicated_variant_handles() { - let mut m = basic_test_module_with_enum(); - m.variant_handles.push(m.variant_handles[0].clone()); - DuplicationChecker::verify_module(&m).unwrap_err(); -} diff --git a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/generic_ops_tests.rs b/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/generic_ops_tests.rs deleted file mode 100644 index c45ad03375d..00000000000 --- a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/generic_ops_tests.rs +++ /dev/null @@ -1,478 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use move_binary_format::file_format::*; -use move_bytecode_verifier::InstructionConsistency; -use move_core_types::{ - account_address::AccountAddress, identifier::Identifier, vm_status::StatusCode, -}; - -// Make a Module with 2 structs and 2 resources with one field each, and 2 -// functions. One of the struct/resource and one of the function is generic, the -// other "normal". Also make a test function whose body will be filled by given -// test cases. -fn make_module() -> CompiledModule { - CompiledModule { - version: move_binary_format::file_format_common::VERSION_MAX, - module_handles: vec![ - // only self module - ModuleHandle { - address: AddressIdentifierIndex(0), - name: IdentifierIndex(0), - }, - ], - self_module_handle_idx: ModuleHandleIndex(0), - identifiers: vec![ - Identifier::new("M").unwrap(), // Module name - Identifier::new("S").unwrap(), // Struct name - Identifier::new("GS").unwrap(), // Generic struct name - Identifier::new("R").unwrap(), // Resource name - Identifier::new("GR").unwrap(), // Generic resource name - Identifier::new("f").unwrap(), // Field name - Identifier::new("fn").unwrap(), // Function name - Identifier::new("g_fn").unwrap(), // Generic function name - Identifier::new("test_fn").unwrap(), // Test function name - ], - address_identifiers: vec![ - AccountAddress::ZERO, // Module address - ], - datatype_handles: vec![ - DatatypeHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(1), - abilities: AbilitySet::PRIMITIVES, - type_parameters: vec![], - }, - DatatypeHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(2), - abilities: AbilitySet::PRIMITIVES, - type_parameters: vec![DatatypeTyParameter { - constraints: AbilitySet::PRIMITIVES, - is_phantom: false, - }], - }, - DatatypeHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(3), - abilities: AbilitySet::EMPTY | Ability::Key, - type_parameters: vec![], - }, - DatatypeHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(4), - abilities: AbilitySet::EMPTY | Ability::Key, - type_parameters: vec![DatatypeTyParameter { - constraints: AbilitySet::PRIMITIVES, - is_phantom: false, - }], - }, - ], - struct_defs: vec![ - // struct S { f: u64 } - StructDefinition { - struct_handle: DatatypeHandleIndex(0), - field_information: StructFieldInformation::Declared(vec![FieldDefinition { - name: IdentifierIndex(5), - signature: TypeSignature(SignatureToken::U64), - }]), - }, - // struct GS { f: T } - StructDefinition { - struct_handle: DatatypeHandleIndex(1), - field_information: StructFieldInformation::Declared(vec![FieldDefinition { - name: IdentifierIndex(5), - signature: TypeSignature(SignatureToken::TypeParameter(0)), - }]), - }, - // struct R has key { f: u64 } - StructDefinition { - struct_handle: DatatypeHandleIndex(2), - field_information: StructFieldInformation::Declared(vec![FieldDefinition { - name: IdentifierIndex(5), - signature: TypeSignature(SignatureToken::U64), - }]), - }, - // struct GR has key { f: T } - StructDefinition { - struct_handle: DatatypeHandleIndex(3), - field_information: StructFieldInformation::Declared(vec![FieldDefinition { - name: IdentifierIndex(5), - signature: TypeSignature(SignatureToken::TypeParameter(0)), - }]), - }, - ], - function_handles: vec![ - // fun fn() - FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(6), - parameters: SignatureIndex(0), - return_: SignatureIndex(0), - type_parameters: vec![], - }, - // fun g_fn() - FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(7), - parameters: SignatureIndex(0), - return_: SignatureIndex(0), - type_parameters: vec![AbilitySet::EMPTY | Ability::Key], - }, - // fun test_fn(Sender) - FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(8), - parameters: SignatureIndex(1), - return_: SignatureIndex(0), - type_parameters: vec![], - }, - ], - function_defs: vec![ - // public fun fn() { return; } - FunctionDefinition { - function: FunctionHandleIndex(0), - visibility: Visibility::Public, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![Bytecode::Ret], - jump_tables: vec![], - }), - }, - // fun g_fn() { return; } - FunctionDefinition { - function: FunctionHandleIndex(1), - visibility: Visibility::Private, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![Bytecode::Ret], - jump_tables: vec![], - }), - }, - // fun test_fn() { ... } - tests will fill up the code - FunctionDefinition { - function: FunctionHandleIndex(2), - visibility: Visibility::Private, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![], - jump_tables: vec![], - }), - }, - ], - signatures: vec![ - Signature(vec![]), // void - Signature(vec![SignatureToken::Signer]), // Signer - ], - constant_pool: vec![ - // an address - Constant { - type_: SignatureToken::Address, - data: AccountAddress::random().to_vec(), - }, - ], - metadata: vec![], - field_handles: vec![], - friend_decls: vec![], - struct_def_instantiations: vec![], - function_instantiations: vec![], - field_instantiations: vec![], - enum_defs: vec![], - enum_def_instantiations: vec![], - variant_handles: vec![], - variant_instantiation_handles: vec![], - } -} - -#[test] -fn generic_call_to_non_generic_func() { - let mut module = make_module(); - // bogus `CallGeneric fn()` - module.function_defs[2].code = Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![ - Bytecode::CallGeneric(FunctionInstantiationIndex(0)), - Bytecode::Ret, - ], - jump_tables: vec![], - }); - module.function_instantiations.push(FunctionInstantiation { - handle: FunctionHandleIndex(0), - type_parameters: SignatureIndex(2), - }); - module.signatures.push(Signature(vec![SignatureToken::U64])); - let err = InstructionConsistency::verify_module(&module) - .expect_err("CallGeneric to non generic function must fail"); - assert_eq!( - err.major_status(), - StatusCode::GENERIC_MEMBER_OPCODE_MISMATCH - ); -} - -#[test] -fn non_generic_call_to_generic_func() { - let mut module = make_module(); - // bogus `Call g_fn()` - module.function_defs[2].code = Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![Bytecode::Call(FunctionHandleIndex(1)), Bytecode::Ret], - jump_tables: vec![], - }); - let err = InstructionConsistency::verify_module(&module) - .expect_err("Call to generic function must fail"); - assert_eq!( - err.major_status(), - StatusCode::GENERIC_MEMBER_OPCODE_MISMATCH - ); -} - -#[test] -fn generic_pack_on_non_generic_struct() { - let mut module = make_module(); - // bogus `PackGeneric S` - module.function_defs[2].code = Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![ - Bytecode::LdU64(10), - Bytecode::PackGeneric(StructDefInstantiationIndex(0)), - Bytecode::Pop, - Bytecode::Ret, - ], - jump_tables: vec![], - }); - module - .struct_def_instantiations - .push(StructDefInstantiation { - def: StructDefinitionIndex(0), - type_parameters: SignatureIndex(2), - }); - module.signatures.push(Signature(vec![SignatureToken::U64])); - let err = InstructionConsistency::verify_module(&module) - .expect_err("PackGeneric to non generic struct must fail"); - assert_eq!( - err.major_status(), - StatusCode::GENERIC_MEMBER_OPCODE_MISMATCH - ); -} - -#[test] -fn non_generic_pack_on_generic_struct() { - let mut module = make_module(); - // bogus `Pack GS` - module.function_defs[2].code = Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![ - Bytecode::LdU64(10), - Bytecode::Pack(StructDefinitionIndex(1)), - Bytecode::Pop, - Bytecode::Ret, - ], - jump_tables: vec![], - }); - let err = InstructionConsistency::verify_module(&module) - .expect_err("Pack to generic struct must fail"); - assert_eq!( - err.major_status(), - StatusCode::GENERIC_MEMBER_OPCODE_MISMATCH - ); -} - -#[test] -fn generic_unpack_on_non_generic_struct() { - let mut module = make_module(); - // bogus `UnpackGeneric S` - module.function_defs[2].code = Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![ - Bytecode::LdU64(10), - Bytecode::Pack(StructDefinitionIndex(0)), - Bytecode::UnpackGeneric(StructDefInstantiationIndex(0)), - Bytecode::Pop, - Bytecode::Ret, - ], - jump_tables: vec![], - }); - module - .struct_def_instantiations - .push(StructDefInstantiation { - def: StructDefinitionIndex(0), - type_parameters: SignatureIndex(2), - }); - module.signatures.push(Signature(vec![SignatureToken::U64])); - let err = InstructionConsistency::verify_module(&module) - .expect_err("UnpackGeneric to non generic struct must fail"); - assert_eq!( - err.major_status(), - StatusCode::GENERIC_MEMBER_OPCODE_MISMATCH - ); -} - -#[test] -fn non_generic_unpack_on_generic_struct() { - let mut module = make_module(); - // bogus `Unpack GS` - module.function_defs[2].code = Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![ - Bytecode::LdU64(10), - Bytecode::PackGeneric(StructDefInstantiationIndex(0)), - Bytecode::Unpack(StructDefinitionIndex(1)), - Bytecode::Pop, - Bytecode::Ret, - ], - jump_tables: vec![], - }); - module - .struct_def_instantiations - .push(StructDefInstantiation { - def: StructDefinitionIndex(1), - type_parameters: SignatureIndex(2), - }); - module.signatures.push(Signature(vec![SignatureToken::U64])); - let err = InstructionConsistency::verify_module(&module) - .expect_err("Unpack to generic struct must fail"); - assert_eq!( - err.major_status(), - StatusCode::GENERIC_MEMBER_OPCODE_MISMATCH - ); -} - -#[test] -fn generic_mut_borrow_field_on_non_generic_struct() { - let mut module = make_module(); - // bogus `MutBorrowFieldGeneric S.t` - module.function_defs[2].code = Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![ - Bytecode::LdU64(10), - Bytecode::Pack(StructDefinitionIndex(0)), - Bytecode::MutBorrowFieldGeneric(FieldInstantiationIndex(0)), - Bytecode::Pop, - Bytecode::Ret, - ], - jump_tables: vec![], - }); - module.field_instantiations.push(FieldInstantiation { - handle: FieldHandleIndex(0), - type_parameters: SignatureIndex(2), - }); - module.field_handles.push(FieldHandle { - owner: StructDefinitionIndex(0), - field: 0, - }); - module.signatures.push(Signature(vec![SignatureToken::U64])); - let err = InstructionConsistency::verify_module(&module) - .expect_err("MutBorrowFieldGeneric to non generic struct must fail"); - assert_eq!( - err.major_status(), - StatusCode::GENERIC_MEMBER_OPCODE_MISMATCH - ); -} - -#[test] -fn non_generic_mut_borrow_field_on_generic_struct() { - let mut module = make_module(); - // bogus `MutBorrowField GS.f` - module.function_defs[2].code = Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![ - Bytecode::LdU64(10), - Bytecode::PackGeneric(StructDefInstantiationIndex(0)), - Bytecode::MutBorrowField(FieldHandleIndex(0)), - Bytecode::Pop, - Bytecode::Ret, - ], - jump_tables: vec![], - }); - module - .struct_def_instantiations - .push(StructDefInstantiation { - def: StructDefinitionIndex(1), - type_parameters: SignatureIndex(2), - }); - module.field_handles.push(FieldHandle { - owner: StructDefinitionIndex(1), - field: 0, - }); - module.signatures.push(Signature(vec![SignatureToken::U64])); - let err = InstructionConsistency::verify_module(&module) - .expect_err("MutBorrowField to generic struct must fail"); - assert_eq!( - err.major_status(), - StatusCode::GENERIC_MEMBER_OPCODE_MISMATCH - ); -} - -#[test] -fn generic_borrow_field_on_non_generic_struct() { - let mut module = make_module(); - // bogus `ImmBorrowFieldGeneric S.f` - module.function_defs[2].code = Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![ - Bytecode::LdU64(10), - Bytecode::Pack(StructDefinitionIndex(0)), - Bytecode::ImmBorrowFieldGeneric(FieldInstantiationIndex(0)), - Bytecode::Pop, - Bytecode::Ret, - ], - jump_tables: vec![], - }); - module.field_instantiations.push(FieldInstantiation { - handle: FieldHandleIndex(0), - type_parameters: SignatureIndex(2), - }); - module.field_handles.push(FieldHandle { - owner: StructDefinitionIndex(0), - field: 0, - }); - module.signatures.push(Signature(vec![SignatureToken::U64])); - let err = InstructionConsistency::verify_module(&module) - .expect_err("ImmBorrowFieldGeneric to non generic struct must fail"); - assert_eq!( - err.major_status(), - StatusCode::GENERIC_MEMBER_OPCODE_MISMATCH - ); -} - -#[test] -fn non_generic_borrow_field_on_generic_struct() { - let mut module = make_module(); - // bogus `ImmBorrowField GS.f` - module.function_defs[2].code = Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![ - Bytecode::LdU64(10), - Bytecode::PackGeneric(StructDefInstantiationIndex(0)), - Bytecode::ImmBorrowField(FieldHandleIndex(0)), - Bytecode::Pop, - Bytecode::Ret, - ], - jump_tables: vec![], - }); - module - .struct_def_instantiations - .push(StructDefInstantiation { - def: StructDefinitionIndex(1), - type_parameters: SignatureIndex(2), - }); - module.field_handles.push(FieldHandle { - owner: StructDefinitionIndex(1), - field: 0, - }); - module.signatures.push(Signature(vec![SignatureToken::U64])); - let err = InstructionConsistency::verify_module(&module) - .expect_err("ImmBorrowField to generic struct must fail"); - assert_eq!( - err.major_status(), - StatusCode::GENERIC_MEMBER_OPCODE_MISMATCH - ); -} diff --git a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/large_type_test.rs b/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/large_type_test.rs deleted file mode 100644 index 3b565fa979b..00000000000 --- a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/large_type_test.rs +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use move_binary_format::file_format::{ - empty_module, Bytecode, CodeUnit, FunctionDefinition, FunctionHandle, FunctionHandleIndex, - IdentifierIndex, ModuleHandleIndex, Signature, SignatureIndex, SignatureToken, - Visibility::Public, -}; -use move_bytecode_verifier_meter::bound::BoundMeter; -use move_core_types::{identifier::Identifier, vm_status::StatusCode}; - -use crate::unit_tests::production_config; - -const NUM_LOCALS: u8 = 64; -const NUM_CALLS: u16 = 77; -const NUM_FUNCTIONS: u16 = 177; - -fn get_nested_vec_type(len: usize) -> SignatureToken { - let mut ret = SignatureToken::Bool; - for _ in 0..len { - ret = SignatureToken::Vector(Box::new(ret)); - } - ret -} - -#[test] -fn test_large_types() { - // See also: github.com/aptos-labs/aptos-core/security/advisories/ - // GHSA-37qw-jfpw-8899 - let mut m = empty_module(); - - m.signatures.push(Signature( - std::iter::repeat(SignatureToken::Reference(Box::new(get_nested_vec_type(64)))) - .take(NUM_LOCALS as usize) - .collect(), - )); - - m.function_handles.push(FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(0), - parameters: SignatureIndex(0), - return_: SignatureIndex(0), - type_parameters: vec![], - }); - m.function_defs.push(FunctionDefinition { - function: FunctionHandleIndex(0), - visibility: Public, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![Bytecode::Call(FunctionHandleIndex(0)), Bytecode::Ret], - jump_tables: vec![], - }), - }); - - // returns_vecs - m.identifiers.push(Identifier::new("returns_vecs").unwrap()); - m.function_handles.push(FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(1), - parameters: SignatureIndex(0), - return_: SignatureIndex(1), - type_parameters: vec![], - }); - m.function_defs.push(FunctionDefinition { - function: FunctionHandleIndex(1), - visibility: Public, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![Bytecode::Call(FunctionHandleIndex(1)), Bytecode::Ret], - jump_tables: vec![], - }), - }); - - // takes_and_returns_vecs - m.identifiers - .push(Identifier::new("takes_and_returns_vecs").unwrap()); - m.function_handles.push(FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(2), - parameters: SignatureIndex(1), - return_: SignatureIndex(1), - type_parameters: vec![], - }); - m.function_defs.push(FunctionDefinition { - function: FunctionHandleIndex(2), - visibility: Public, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![Bytecode::Call(FunctionHandleIndex(1)), Bytecode::Ret], - jump_tables: vec![], - }), - }); - - // takes_vecs - m.identifiers.push(Identifier::new("takes_vecs").unwrap()); - m.function_handles.push(FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(3), - parameters: SignatureIndex(1), - return_: SignatureIndex(0), - type_parameters: vec![], - }); - m.function_defs.push(FunctionDefinition { - function: FunctionHandleIndex(3), - visibility: Public, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![Bytecode::Ret], - jump_tables: vec![], - }), - }); - - // other fcts - for i in 0..NUM_FUNCTIONS { - m.identifiers - .push(Identifier::new(format!("f{}", i)).unwrap()); - m.function_handles.push(FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(i + 4), - parameters: SignatureIndex(0), - return_: SignatureIndex(0), - type_parameters: vec![], - }); - m.function_defs.push(FunctionDefinition { - function: FunctionHandleIndex(i + 4), - visibility: Public, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![], - jump_tables: vec![], - }), - }); - - let code = &mut m.function_defs[i as usize + 4].code.as_mut().unwrap().code; - code.clear(); - code.push(Bytecode::Call(FunctionHandleIndex(1))); - for _ in 0..NUM_CALLS { - code.push(Bytecode::Call(FunctionHandleIndex(2))); - } - code.push(Bytecode::Call(FunctionHandleIndex(3))); - code.push(Bytecode::Ret); - } - - let (verifier_config, meter_config) = production_config(); - let mut meter = BoundMeter::new(meter_config); - let result = move_bytecode_verifier::verify_module_with_config_for_test( - "test_large_types", - &verifier_config, - &m, - &mut meter, - ); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::CONSTRAINT_NOT_SATISFIED, - ); -} diff --git a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/limit_tests.rs b/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/limit_tests.rs deleted file mode 100644 index 271e1cf955e..00000000000 --- a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/limit_tests.rs +++ /dev/null @@ -1,827 +0,0 @@ -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use move_binary_format::file_format::*; -use move_bytecode_verifier::{limits::LimitsVerifier, verify_module_with_config_for_test}; -use move_bytecode_verifier_meter::dummy::DummyMeter; -use move_core_types::{ - account_address::AccountAddress, identifier::Identifier, vm_status::StatusCode, -}; -use move_vm_config::verifier::{VerifierConfig, DEFAULT_MAX_IDENTIFIER_LENGTH}; - -use crate::unit_tests::production_config; - -#[test] -fn test_function_handle_type_instantiation() { - let mut m = basic_test_module(); - m.function_handles.push(FunctionHandle { - module: ModuleHandleIndex::new(0), - name: IdentifierIndex::new(0), - parameters: SignatureIndex(0), - return_: SignatureIndex(0), - type_parameters: std::iter::repeat(AbilitySet::ALL).take(10).collect(), - }); - - assert_eq!( - LimitsVerifier::verify_module( - &VerifierConfig { - max_generic_instantiation_length: Some(9), - ..Default::default() - }, - &m - ) - .unwrap_err() - .major_status(), - StatusCode::TOO_MANY_TYPE_PARAMETERS - ); -} - -#[test] -fn test_struct_handle_type_instantiation() { - let mut m = basic_test_module(); - m.datatype_handles.push(DatatypeHandle { - module: ModuleHandleIndex::new(0), - name: IdentifierIndex::new(0), - abilities: AbilitySet::ALL, - type_parameters: std::iter::repeat(DatatypeTyParameter { - constraints: AbilitySet::ALL, - is_phantom: false, - }) - .take(10) - .collect(), - }); - - assert_eq!( - LimitsVerifier::verify_module( - &VerifierConfig { - max_generic_instantiation_length: Some(9), - ..Default::default() - }, - &m - ) - .unwrap_err() - .major_status(), - StatusCode::TOO_MANY_TYPE_PARAMETERS - ); -} - -#[test] -fn test_function_handle_parameters() { - let mut m = basic_test_module(); - m.signatures.push(Signature( - std::iter::repeat(SignatureToken::Bool).take(10).collect(), - )); - m.function_handles.push(FunctionHandle { - module: ModuleHandleIndex::new(0), - name: IdentifierIndex::new(0), - parameters: SignatureIndex(1), - return_: SignatureIndex(0), - type_parameters: vec![], - }); - - assert_eq!( - LimitsVerifier::verify_module( - &VerifierConfig { - max_function_parameters: Some(9), - ..Default::default() - }, - &m - ) - .unwrap_err() - .major_status(), - StatusCode::TOO_MANY_PARAMETERS - ); -} - -#[test] -fn big_vec_unpacks() { - const N_TYPE_PARAMS: usize = 16; - let mut st = SignatureToken::Vector(Box::new(SignatureToken::U8)); - let type_params = vec![st; N_TYPE_PARAMS]; - st = SignatureToken::DatatypeInstantiation(Box::new((DatatypeHandleIndex(0), type_params))); - const N_VEC_PUSH: u16 = 1000; - let mut code = vec![]; - // 1. CopyLoc: ... -> ... st - // 2. VecPack: ... st -> ... Vec - // 3. VecUnpack: ... Vec -> ... st, st, st, ... st - for _ in 0..N_VEC_PUSH { - code.push(Bytecode::CopyLoc(0)); - code.push(Bytecode::VecPack(SignatureIndex(1), 1)); - code.push(Bytecode::VecUnpack(SignatureIndex(1), 1 << 15)); - } - // 1. VecPack: ... st, st, st, ... st -> ... Vec - // 2. Pop: ... Vec -> ... - for _ in 0..N_VEC_PUSH { - code.push(Bytecode::VecPack(SignatureIndex(1), 1 << 15)); - code.push(Bytecode::Pop); - } - code.push(Bytecode::Ret); - let type_param_constraints = DatatypeTyParameter { - constraints: AbilitySet::EMPTY, - is_phantom: false, - }; - let module = CompiledModule { - version: 5, - self_module_handle_idx: ModuleHandleIndex(0), - module_handles: vec![ModuleHandle { - address: AddressIdentifierIndex(0), - name: IdentifierIndex(0), - }], - datatype_handles: vec![DatatypeHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(1), - abilities: AbilitySet::ALL, - type_parameters: vec![type_param_constraints; N_TYPE_PARAMS], - }], - function_handles: vec![FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(0), - parameters: SignatureIndex(1), - return_: SignatureIndex(0), - type_parameters: vec![], - }], - field_handles: vec![], - friend_decls: vec![], - struct_def_instantiations: vec![], - function_instantiations: vec![], - field_instantiations: vec![], - signatures: vec![Signature(vec![]), Signature(vec![st])], - identifiers: vec![ - Identifier::new("f").unwrap(), - Identifier::new("generic_struct").unwrap(), - ], - address_identifiers: vec![AccountAddress::ONE], - constant_pool: vec![], - metadata: vec![], - struct_defs: vec![StructDefinition { - struct_handle: DatatypeHandleIndex(0), - field_information: StructFieldInformation::Native, - }], - function_defs: vec![FunctionDefinition { - function: FunctionHandleIndex(0), - visibility: Visibility::Public, - is_entry: true, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(0), - code, - jump_tables: vec![], - }), - }], - enum_defs: vec![], - enum_def_instantiations: vec![], - variant_handles: vec![], - variant_instantiation_handles: vec![], - }; - - // save module and verify that it can ser/de - let mut mvbytes = vec![]; - module.serialize(&mut mvbytes).unwrap(); - let module = CompiledModule::deserialize_with_defaults(&mvbytes).unwrap(); - - let res = verify_module_with_config_for_test( - "big_vec_unpacks", - &VerifierConfig { - max_loop_depth: Some(5), - max_generic_instantiation_length: Some(32), - max_function_parameters: Some(128), - max_basic_blocks: Some(1024), - max_push_size: Some(10000), - ..Default::default() - }, - &module, - &mut DummyMeter, - ); - assert_eq!( - res.unwrap_err().major_status(), - StatusCode::VALUE_STACK_PUSH_OVERFLOW - ); -} - -const MAX_STRUCTS: usize = 200; -const MAX_FIELDS: usize = 30; -const MAX_FUNCTIONS: usize = 1000; - -#[test] -fn max_struct_test() { - let config = VerifierConfig { - max_data_definitions: Some(MAX_STRUCTS), - max_fields_in_struct: Some(MAX_FIELDS), - max_function_definitions: Some(MAX_FUNCTIONS), - ..Default::default() - }; - let mut module = leaf_module("M"); - multi_struct(&mut module, 0); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!(res, Ok(())); - multi_struct(&mut module, 1); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!(res, Ok(())); - let mut module = leaf_module("M"); - multi_struct(&mut module, MAX_STRUCTS / 2); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!(res, Ok(())); - let mut module = leaf_module("M"); - multi_struct(&mut module, MAX_STRUCTS); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!(res, Ok(())); - let mut module = leaf_module("M"); - multi_struct(&mut module, MAX_STRUCTS * 2); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!( - res.unwrap_err().major_status(), - StatusCode::MAX_STRUCT_DEFINITIONS_REACHED, - ); - let mut module = leaf_module("M"); - multi_struct(&mut module, MAX_STRUCTS + 1); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!( - res.unwrap_err().major_status(), - StatusCode::MAX_STRUCT_DEFINITIONS_REACHED, - ); -} - -#[test] -fn max_fields_test() { - let config = VerifierConfig { - max_data_definitions: Some(MAX_STRUCTS), - max_fields_in_struct: Some(MAX_FIELDS), - max_function_definitions: Some(MAX_FUNCTIONS), - ..Default::default() - }; - let mut module = leaf_module("M"); - multi_struct(&mut module, 1); - multi_fields(&mut module, MAX_FIELDS / 2); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!(res, Ok(())); - let mut module = leaf_module("M"); - multi_struct(&mut module, 10); - multi_fields(&mut module, MAX_FIELDS - 1); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!(res, Ok(())); - let mut module = leaf_module("M"); - multi_struct(&mut module, 50); - multi_fields(&mut module, MAX_FIELDS); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!(res, Ok(())); - let mut module = leaf_module("M"); - multi_struct(&mut module, 100); - multi_fields(&mut module, MAX_FIELDS + 1); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!( - res.unwrap_err().major_status(), - StatusCode::MAX_FIELD_DEFINITIONS_REACHED, - ); - let mut module = leaf_module("M"); - multi_struct(&mut module, 2); - multi_fields(&mut module, MAX_FIELDS * 2); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!( - res.unwrap_err().major_status(), - StatusCode::MAX_FIELD_DEFINITIONS_REACHED, - ); - let mut module = leaf_module("M"); - multi_struct(&mut module, 50); - multi_fields_except_one(&mut module, 0, 2, MAX_FIELDS + 1); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!( - res.unwrap_err().major_status(), - StatusCode::MAX_FIELD_DEFINITIONS_REACHED, - ); - let mut module = leaf_module("M"); - multi_struct(&mut module, 20); - multi_fields_except_one(&mut module, 19, MAX_FIELDS, MAX_FIELDS + 1); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!( - res.unwrap_err().major_status(), - StatusCode::MAX_FIELD_DEFINITIONS_REACHED, - ); - let mut module = leaf_module("M"); - multi_struct(&mut module, 100); - multi_fields_except_one(&mut module, 50, 1, MAX_FIELDS * 2); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!( - res.unwrap_err().major_status(), - StatusCode::MAX_FIELD_DEFINITIONS_REACHED, - ); -} - -#[test] -fn max_functions_test() { - let config = VerifierConfig { - max_data_definitions: Some(MAX_STRUCTS), - max_fields_in_struct: Some(MAX_FIELDS), - max_function_definitions: Some(MAX_FUNCTIONS), - ..Default::default() - }; - let mut module = leaf_module("M"); - multi_struct(&mut module, 1); - multi_functions(&mut module, 1); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!(res, Ok(())); - let mut module = leaf_module("M"); - multi_struct(&mut module, 10); - multi_functions(&mut module, MAX_FUNCTIONS / 2); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!(res, Ok(())); - let mut module = leaf_module("M"); - multi_struct(&mut module, 5); - multi_functions(&mut module, MAX_FUNCTIONS); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!(res, Ok(())); - let mut module = leaf_module("M"); - multi_struct(&mut module, 5); - multi_functions(&mut module, MAX_FUNCTIONS - 1); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!(res, Ok(())); - let mut module = leaf_module("M"); - multi_struct(&mut module, 5); - multi_functions(&mut module, MAX_FUNCTIONS + 1); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!( - res.unwrap_err().major_status(), - StatusCode::MAX_FUNCTION_DEFINITIONS_REACHED, - ); - let mut module = leaf_module("M"); - multi_functions(&mut module, MAX_FUNCTIONS * 2); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!( - res.unwrap_err().major_status(), - StatusCode::MAX_FUNCTION_DEFINITIONS_REACHED, - ); -} - -#[test] -fn max_mixed_config_test() { - let config = VerifierConfig { - max_data_definitions: Some(MAX_STRUCTS), - max_fields_in_struct: Some(MAX_FIELDS), - max_function_definitions: Some(MAX_FUNCTIONS), - ..Default::default() - }; - let mut module = leaf_module("M"); - multi_struct(&mut module, MAX_STRUCTS); - multi_fields(&mut module, MAX_FIELDS); - multi_functions(&mut module, MAX_FUNCTIONS); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!(res, Ok(())); - - let config = VerifierConfig { - max_function_definitions: None, - max_data_definitions: None, - max_fields_in_struct: None, - ..Default::default() - }; - let mut module = leaf_module("M"); - multi_struct(&mut module, 1); - multi_fields(&mut module, 1); - multi_functions(&mut module, 1); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!(res, Ok(())); - let mut module = leaf_module("M"); - multi_struct(&mut module, MAX_STRUCTS); - multi_fields(&mut module, MAX_FIELDS); - multi_functions(&mut module, MAX_FUNCTIONS); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!(res, Ok(())); - let mut module = leaf_module("M"); - multi_struct(&mut module, MAX_STRUCTS * 2); - multi_fields(&mut module, MAX_FIELDS * 2); - multi_functions(&mut module, MAX_FUNCTIONS * 2); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!(res, Ok(())); - let mut module = leaf_module("M"); - multi_struct(&mut module, MAX_STRUCTS + 1); - multi_fields(&mut module, MAX_FIELDS + 1); - multi_functions(&mut module, MAX_FUNCTIONS + 1); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!(res, Ok(())); - - let config = VerifierConfig { - max_data_definitions: Some(MAX_STRUCTS), - max_fields_in_struct: Some(MAX_FIELDS), - ..Default::default() - }; - let mut module = leaf_module("M"); - multi_struct(&mut module, MAX_STRUCTS); - multi_fields(&mut module, MAX_FIELDS); - multi_functions(&mut module, MAX_FUNCTIONS); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!(res, Ok(())); - let mut module = leaf_module("M"); - multi_struct(&mut module, MAX_STRUCTS); - multi_fields(&mut module, MAX_FIELDS); - multi_functions(&mut module, MAX_FUNCTIONS + 10); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!(res, Ok(())); - let mut module = leaf_module("M"); - multi_struct(&mut module, MAX_STRUCTS); - multi_fields(&mut module, MAX_FIELDS); - multi_functions(&mut module, MAX_FUNCTIONS * 3); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!(res, Ok(())); - let mut module = leaf_module("M"); - multi_struct(&mut module, MAX_STRUCTS * 2); - multi_fields(&mut module, MAX_FIELDS); - multi_functions(&mut module, MAX_FUNCTIONS + 1); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!( - res.unwrap_err().major_status(), - StatusCode::MAX_STRUCT_DEFINITIONS_REACHED, - ); - let mut module = leaf_module("M"); - multi_struct(&mut module, MAX_STRUCTS); - multi_fields(&mut module, MAX_FIELDS * 2); - multi_functions(&mut module, MAX_FUNCTIONS * 3); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!( - res.unwrap_err().major_status(), - StatusCode::MAX_FIELD_DEFINITIONS_REACHED, - ); - - let config = VerifierConfig { - max_data_definitions: Some(MAX_STRUCTS), - max_function_definitions: Some(MAX_FUNCTIONS), - ..Default::default() - }; - let mut module = leaf_module("M"); - multi_struct(&mut module, MAX_STRUCTS); - multi_fields(&mut module, MAX_FIELDS); - multi_functions(&mut module, MAX_FUNCTIONS); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!(res, Ok(())); - let mut module = leaf_module("M"); - multi_struct(&mut module, MAX_STRUCTS); - multi_fields(&mut module, MAX_FIELDS + 1); - multi_functions(&mut module, MAX_FUNCTIONS); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!(res, Ok(())); - let mut module = leaf_module("M"); - multi_struct(&mut module, MAX_STRUCTS); - multi_fields(&mut module, MAX_FIELDS * 3); - multi_functions(&mut module, MAX_FUNCTIONS); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!(res, Ok(())); - let mut module = leaf_module("M"); - multi_struct(&mut module, MAX_STRUCTS * 2); - multi_fields(&mut module, MAX_FIELDS * 3); - multi_functions(&mut module, MAX_FUNCTIONS); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!( - res.unwrap_err().major_status(), - StatusCode::MAX_STRUCT_DEFINITIONS_REACHED, - ); - let mut module = leaf_module("M"); - multi_struct(&mut module, MAX_STRUCTS); - multi_fields(&mut module, MAX_FIELDS * 2); - multi_functions(&mut module, MAX_FUNCTIONS * 2); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!( - res.unwrap_err().major_status(), - StatusCode::MAX_FUNCTION_DEFINITIONS_REACHED, - ); - - let config = VerifierConfig { - max_fields_in_struct: Some(MAX_FIELDS), - max_function_definitions: Some(MAX_FUNCTIONS), - ..Default::default() - }; - let mut module = leaf_module("M"); - multi_struct(&mut module, MAX_STRUCTS); - multi_fields(&mut module, MAX_FIELDS); - multi_functions(&mut module, MAX_FUNCTIONS); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!(res, Ok(())); - let mut module = leaf_module("M"); - multi_struct(&mut module, MAX_STRUCTS * 3); - multi_fields(&mut module, MAX_FIELDS); - multi_functions(&mut module, MAX_FUNCTIONS); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!(res, Ok(())); - let mut module = leaf_module("M"); - multi_struct(&mut module, MAX_STRUCTS + 1); - multi_fields(&mut module, MAX_FIELDS); - multi_functions(&mut module, MAX_FUNCTIONS); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!(res, Ok(())); - let mut module = leaf_module("M"); - multi_struct(&mut module, MAX_STRUCTS + 1); - multi_fields(&mut module, MAX_FIELDS * 3); - multi_functions(&mut module, MAX_FUNCTIONS); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!( - res.unwrap_err().major_status(), - StatusCode::MAX_FIELD_DEFINITIONS_REACHED, - ); - let mut module = leaf_module("M"); - multi_struct(&mut module, MAX_STRUCTS * 2); - multi_fields(&mut module, MAX_FIELDS); - multi_functions(&mut module, MAX_FUNCTIONS * 2); - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!( - res.unwrap_err().major_status(), - StatusCode::MAX_FUNCTION_DEFINITIONS_REACHED, - ); -} - -#[test] -fn max_identifier_len() { - let (config, _) = production_config(); - let max_ident = "z".repeat( - config - .max_identifier_len - .unwrap_or(DEFAULT_MAX_IDENTIFIER_LENGTH) as usize, - ); - let good_module = leaf_module(&max_ident); - - let res = LimitsVerifier::verify_module(&config, &good_module); - assert!(res.is_ok()); - - let max_ident = "z".repeat( - (config - .max_identifier_len - .unwrap_or(DEFAULT_MAX_IDENTIFIER_LENGTH) as usize) - / 2, - ); - let good_module = leaf_module(&max_ident); - - let res = LimitsVerifier::verify_module(&config, &good_module); - assert!(res.is_ok()); - - let over_max_ident = "z".repeat( - 1 + config - .max_identifier_len - .unwrap_or(DEFAULT_MAX_IDENTIFIER_LENGTH) as usize, - ); - let bad_module = leaf_module(&over_max_ident); - let res = LimitsVerifier::verify_module(&config, &bad_module); - - assert_eq!( - res.unwrap_err().major_status(), - StatusCode::IDENTIFIER_TOO_LONG, - ); - - let over_max_ident = "zx".repeat( - 1 + config - .max_identifier_len - .unwrap_or(DEFAULT_MAX_IDENTIFIER_LENGTH) as usize, - ); - let bad_module = leaf_module(&over_max_ident); - let res = LimitsVerifier::verify_module(&config, &bad_module); - - assert_eq!( - res.unwrap_err().major_status(), - StatusCode::IDENTIFIER_TOO_LONG, - ); -} - -#[test] -fn max_vec_len() { - let config = VerifierConfig { - max_constant_vector_len: Some(0xFFFF - 1), - ..Default::default() - }; - let double_vec = |item: Vec| -> Vec { - let mut items = vec![2]; - items.extend(item.clone()); - items.extend(item); - items - }; - let large_vec = |item: Vec| -> Vec { - let mut items = vec![0xFF, 0xFF, 3]; - (0..0xFFFF).for_each(|_| items.extend(item.clone())); - items - }; - fn tvec(s: SignatureToken) -> SignatureToken { - SignatureToken::Vector(Box::new(s)) - } - - let mut module = empty_module(); - module.constant_pool = vec![Constant { - type_: tvec(SignatureToken::Bool), - data: large_vec(vec![0]), - }]; - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!( - res.unwrap_err().major_status(), - StatusCode::TOO_MANY_VECTOR_ELEMENTS, - ); - - let mut module = empty_module(); - module.constant_pool = vec![Constant { - type_: tvec(SignatureToken::U256), - data: large_vec(vec![ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, - ]), - }]; - let res = LimitsVerifier::verify_module(&config, &module); - assert_eq!( - res.unwrap_err().major_status(), - StatusCode::TOO_MANY_VECTOR_ELEMENTS, - ); - - let config = VerifierConfig { - max_constant_vector_len: Some(0xFFFF), - ..Default::default() - }; - - let mut module = empty_module(); - module.constant_pool = vec![ - // empty - Constant { - type_: tvec(SignatureToken::Bool), - data: vec![0], - }, - Constant { - type_: tvec(tvec(SignatureToken::Bool)), - data: vec![0], - }, - Constant { - type_: tvec(tvec(tvec(tvec(SignatureToken::Bool)))), - data: vec![0], - }, - Constant { - type_: tvec(tvec(tvec(tvec(SignatureToken::Bool)))), - data: double_vec(vec![0]), - }, - // small - Constant { - type_: tvec(SignatureToken::Bool), - data: vec![9, 1, 1, 1, 1, 1, 1, 1, 1, 1], - }, - Constant { - type_: tvec(SignatureToken::U8), - data: vec![9, 1, 1, 1, 1, 1, 1, 1, 1, 1], - }, - // large - Constant { - type_: tvec(SignatureToken::Bool), - data: large_vec(vec![0]), - }, - Constant { - type_: tvec(SignatureToken::U8), - data: large_vec(vec![0]), - }, - Constant { - type_: tvec(SignatureToken::U16), - data: large_vec(vec![0, 0]), - }, - Constant { - type_: tvec(SignatureToken::U32), - data: large_vec(vec![0, 0, 0, 0]), - }, - Constant { - type_: tvec(SignatureToken::U64), - data: large_vec(vec![0, 0, 0, 0, 0, 0, 0, 0]), - }, - Constant { - type_: tvec(SignatureToken::U128), - data: large_vec(vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - }, - Constant { - type_: tvec(SignatureToken::U256), - data: large_vec(vec![ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - ]), - }, - Constant { - type_: tvec(SignatureToken::Address), - data: large_vec(vec![ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - ]), - }, - // double large - Constant { - type_: tvec(tvec(SignatureToken::Bool)), - data: double_vec(large_vec(vec![0])), - }, - Constant { - type_: tvec(tvec(SignatureToken::U8)), - data: double_vec(large_vec(vec![0])), - }, - Constant { - type_: tvec(tvec(SignatureToken::U16)), - data: double_vec(large_vec(vec![0, 0])), - }, - Constant { - type_: tvec(tvec(SignatureToken::U32)), - data: double_vec(large_vec(vec![0, 0, 0, 0])), - }, - Constant { - type_: tvec(tvec(SignatureToken::U64)), - data: double_vec(large_vec(vec![0, 0, 0, 0, 0, 0, 0, 0])), - }, - Constant { - type_: tvec(tvec(SignatureToken::U128)), - data: double_vec(large_vec(vec![ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ])), - }, - Constant { - type_: tvec(tvec(SignatureToken::U256)), - data: double_vec(large_vec(vec![ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - ])), - }, - Constant { - type_: tvec(tvec(SignatureToken::Address)), - data: double_vec(large_vec(vec![ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - ])), - }, - ]; - let res = LimitsVerifier::verify_module(&config, &module); - - assert!(res.is_ok()); -} - -fn multi_struct(module: &mut CompiledModule, count: usize) { - for i in 0..count { - module - .identifiers - .push(Identifier::new(format!("A_{}", i)).unwrap()); - module.datatype_handles.push(DatatypeHandle { - module: module.self_module_handle_idx, - name: IdentifierIndex((module.identifiers.len() - 1) as u16), - abilities: AbilitySet::EMPTY, - type_parameters: vec![], - }); - module.struct_defs.push(StructDefinition { - struct_handle: DatatypeHandleIndex((module.datatype_handles.len() - 1) as u16), - field_information: StructFieldInformation::Declared(vec![]), - }); - } -} - -fn multi_fields(module: &mut CompiledModule, count: usize) { - for def in &mut module.struct_defs { - let mut fields = vec![]; - for i in 0..count { - module - .identifiers - .push(Identifier::new(format!("f_{}", i)).unwrap()); - fields.push(FieldDefinition { - name: Default::default(), - signature: TypeSignature(SignatureToken::U8), - }); - } - def.field_information = StructFieldInformation::Declared(fields); - } -} - -fn multi_fields_except_one(module: &mut CompiledModule, idx: usize, count: usize, one: usize) { - for (struct_idx, def) in module.struct_defs.iter_mut().enumerate() { - let mut fields = vec![]; - let count = if struct_idx == idx { one } else { count }; - for i in 0..count { - module - .identifiers - .push(Identifier::new(format!("f_{}", i)).unwrap()); - fields.push(FieldDefinition { - name: Default::default(), - signature: TypeSignature(SignatureToken::U8), - }); - } - def.field_information = StructFieldInformation::Declared(fields); - } -} - -fn multi_functions(module: &mut CompiledModule, count: usize) { - module.signatures.push(Signature(vec![])); - for i in 0..count { - module - .identifiers - .push(Identifier::new(format!("func_{}", i)).unwrap()); - module.function_handles.push(FunctionHandle { - module: module.self_module_handle_idx, - name: IdentifierIndex((module.identifiers.len() - 1) as u16), - parameters: SignatureIndex((module.signatures.len() - 1) as u16), - return_: SignatureIndex((module.signatures.len() - 1) as u16), - type_parameters: vec![], - }); - module.function_defs.push(FunctionDefinition { - function: FunctionHandleIndex((module.function_handles.len() - 1) as u16), - visibility: Visibility::Public, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex((module.signatures.len() - 1) as u16), - code: vec![Bytecode::Ret], - jump_tables: vec![], - }), - }); - } -} - -fn leaf_module(name: &str) -> CompiledModule { - let mut module = empty_module(); - module.identifiers[0] = Identifier::new(name).unwrap(); - module.address_identifiers[0] = AccountAddress::ONE; - module -} diff --git a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/locals.rs b/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/locals.rs deleted file mode 100644 index 4789fd9131d..00000000000 --- a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/locals.rs +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use move_binary_format::file_format::{ - empty_module, Bytecode, CodeUnit, FunctionDefinition, FunctionHandle, FunctionHandleIndex, - IdentifierIndex, ModuleHandleIndex, Signature, SignatureIndex, SignatureToken, - Visibility::Public, -}; -use move_bytecode_verifier_meter::bound::BoundMeter; -use move_core_types::{identifier::Identifier, vm_status::StatusCode}; - -use crate::unit_tests::production_config; - -#[test] -fn test_locals() { - // See also: github.com/aptos-labs/aptos-core/security/advisories/ - // GHSA-jjqw-f9pc-525j - let mut m = empty_module(); - - const MAX_BASIC_BLOCKS: u16 = 1024; - const MAX_LOCALS: u8 = 255; - const NUM_FUNCTIONS: u16 = 16; - - m.function_handles.push(FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(0), - parameters: SignatureIndex(0), - return_: SignatureIndex(0), - type_parameters: vec![], - }); - - m.function_defs.push(FunctionDefinition { - function: FunctionHandleIndex(0), - visibility: Public, - is_entry: true, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![Bytecode::Ret], - jump_tables: vec![], - }), - }); - - // signature of locals in f1..f - m.signatures.push(Signature( - std::iter::repeat(SignatureToken::U8) - .take(MAX_LOCALS as usize) - .collect(), - )); - - m.identifiers.push(Identifier::new("pwn").unwrap()); - - // create returns_bool_and_u64 - m.signatures - .push(Signature(vec![SignatureToken::Bool, SignatureToken::U8])); - m.identifiers - .push(Identifier::new("returns_bool_and_u64").unwrap()); - m.function_handles.push(FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(1), - parameters: SignatureIndex(0), - return_: SignatureIndex(2), - type_parameters: vec![], - }); - m.function_defs.push(FunctionDefinition { - function: FunctionHandleIndex(1), - visibility: Public, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![Bytecode::LdTrue, Bytecode::LdU8(0), Bytecode::Ret], - jump_tables: vec![], - }), - }); - - // create other functions - for i in 1..(NUM_FUNCTIONS + 1) { - m.identifiers - .push(Identifier::new(format!("f{}", i)).unwrap()); - m.function_handles.push(FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(i + 1), // the +1 accounts for returns_bool_and_u64 - parameters: SignatureIndex(0), - return_: SignatureIndex(0), - type_parameters: vec![], - }); - m.function_defs.push(FunctionDefinition { - function: FunctionHandleIndex(i + 1), - visibility: Public, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(1), - code: vec![], - jump_tables: vec![], - }), - }); - - let code = &mut m.function_defs[i as usize + 1].code.as_mut().unwrap().code; - - for _ in 0..(MAX_BASIC_BLOCKS / 2 - MAX_LOCALS as u16 - 3) { - code.push(Bytecode::LdTrue); - code.push(Bytecode::BrTrue((code.len() + 2) as u16)); - code.push(Bytecode::Ret); - code.push(Bytecode::LdTrue); - code.push(Bytecode::BrTrue(0)); - } - for i in 0..MAX_LOCALS { - code.push(Bytecode::Call(FunctionHandleIndex(1))); // calls returns_bool_and_u64 - code.push(Bytecode::StLoc(i)); // i'th local is now available for the first time - code.push(Bytecode::BrTrue(0)); - } - code.push(Bytecode::Ret); - } - - let (verifier_config, meter_config) = production_config(); - let mut meter = BoundMeter::new(meter_config); - let result = move_bytecode_verifier::verify_module_with_config_for_test( - "test_locals", - &verifier_config, - &m, - &mut meter, - ); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::CONSTRAINT_NOT_SATISFIED - ); -} diff --git a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/loop_summary_tests.rs b/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/loop_summary_tests.rs deleted file mode 100644 index bae3df1a339..00000000000 --- a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/loop_summary_tests.rs +++ /dev/null @@ -1,468 +0,0 @@ -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use move_abstract_interpreter::control_flow_graph::VMControlFlowGraph; -use move_binary_format::file_format::Bytecode; -use move_bytecode_verifier::loop_summary::{LoopPartition, LoopSummary}; - -macro_rules! assert_node { - ( $summary:ident, $node:expr ; $block:expr, $preds:expr, $descs:expr, $backs:expr ) => { - let (s, n) = (&$summary, $node); - assert_eq!(s.block(n), $block, "Block"); - - let descs = $descs; - for d in descs { - assert!(s.is_descendant(n, *d), "{:?} -> {:?}", n, d) - } - - assert_eq!(s.pred_edges(n), $preds, "Predecessor Edges"); - assert_eq!(s.back_edges(n), $backs, "Back Edges"); - }; -} - -#[test] -fn linear_summary() { - let summary = { - use Bytecode::*; - LoopSummary::new(&VMControlFlowGraph::new( - &[ - // B0, L0 - Nop, - // - Branch(2), - // B2, L1 - Nop, - // - Branch(4), - // B4, L2 - Ret, - ], - &[], - )) - }; - - let n: Vec<_> = summary.preorder().collect(); - - assert_eq!(n.len(), 3); - - assert_node!( - summary, n[0]; - /* block */ 0, - /* preds */ &[], - /* descs */ &[n[1], n[2]], - /* backs */ &[] - ); - - assert_node!( - summary, n[1]; - /* block */ 2, - /* preds */ &[n[0]], - /* descs */ &[n[2]], - /* backs */ &[] - ); - - assert_node!( - summary, n[2]; - /* block */ 4, - /* preds */ &[n[1]], - /* descs */ &[], - /* backs */ &[] - ); -} - -#[test] -fn non_loop_back_branch_summary() { - let summary = { - use Bytecode::*; - LoopSummary::new(&VMControlFlowGraph::new( - &[ - // B0, L0 - Nop, - // - Branch(3), - // B2, L2 - Ret, - // B3, L1 - Branch(2), - ], - &[], - )) - }; - - let n: Vec<_> = summary.preorder().collect(); - - assert_eq!(n.len(), 3); - - assert_node!( - summary, n[0]; - /* block */ 0, - /* preds */ &[], - /* descs */ &[n[1], n[2]], - /* backs */ &[] - ); - - assert_node!( - summary, n[1]; - /* block */ 3, - /* preds */ &[n[0]], - /* descs */ &[n[2]], - /* backs */ &[] - ); - - assert_node!( - summary, n[2]; - /* block */ 2, - /* preds */ &[n[1]], - /* descs */ &[], - /* backs */ &[] - ); -} - -#[test] -fn branching_summary() { - let summary = { - use Bytecode::*; - LoopSummary::new(&VMControlFlowGraph::new( - &[ - // B0, L0 - LdTrue, - // - BrTrue(3), - // B2, L2 - Nop, - // B3, L1 - Ret, - ], - &[], - )) - }; - - let n: Vec<_> = summary.preorder().collect(); - - assert_eq!(n.len(), 3); - - assert_node!( - summary, n[0]; - /* block */ 0, - /* preds */ &[], - /* descs */ &[n[1], n[2]], - /* backs */ &[] - ); - - assert_node!( - summary, n[1]; - /* block */ 3, - /* preds */ &[n[0], n[2]], - /* descs */ &[], - /* backs */ &[] - ); - - assert_node!( - summary, n[2]; - /* block */ 2, - /* preds */ &[n[0]], - /* descs */ &[], - /* backs */ &[] - ); - - // Although L2 -> L1 is an edge in the CFG, it's not an edge in the DFST, so L2 - // is said to have no descendants. - assert!(!summary.is_descendant(n[2], n[1])); -} - -#[test] -fn looping_summary() { - let summary = { - use Bytecode::*; - LoopSummary::new(&VMControlFlowGraph::new( - &[ - // B0, L0 - LdTrue, - // - BrTrue(4), - // B2, L2 - Nop, - // - Branch(0), - // B4, L1 - Ret, - ], - &[], - )) - }; - - let n: Vec<_> = summary.preorder().collect(); - - assert_eq!(n.len(), 3); - - assert_node!( - summary, n[0]; - /* block */ 0, - /* preds */ &[], - /* descs */ &[n[1], n[2]], - /* backs */ &[n[2]] - ); - - assert_node!( - summary, n[1]; - /* block */ 4, - /* preds */ &[n[0]], - /* descs */ &[], - /* backs */ &[] - ); - - assert_node!( - summary, n[2]; - /* block */ 2, - /* preds */ &[n[0]], - /* descs */ &[], - /* backs */ &[] - ); -} - -#[test] -fn branches_in_loops_summary() { - let summary = { - use Bytecode::*; - LoopSummary::new(&VMControlFlowGraph::new( - &[ - // B0, L0 - LdTrue, - // - BrTrue(3), - // B2, L3 - Nop, - // B3, L1 - LdFalse, - // - BrFalse(0), - // B5, L2 - Ret, - ], - &[], - )) - }; - - let n: Vec<_> = summary.preorder().collect(); - - assert_eq!(n.len(), 4); - - assert_node!( - summary, n[0]; - /* block */ 0, - /* preds */ &[], - /* descs */ &[n[1], n[2], n[3]], - /* backs */ &[n[1]] - ); - - assert_node!( - summary, n[1]; - /* block */ 3, - /* preds */ &[n[0], n[3]], - /* descs */ &[n[2]], - /* backs */ &[] - ); - - assert_node!( - summary, n[2]; - /* block */ 5, - /* preds */ &[n[1]], - /* descs */ &[], - /* backs */ &[] - ); - - assert_node!( - summary, n[3]; - /* block */ 2, - /* preds */ &[n[0]], - /* descs */ &[], - /* backs */ &[] - ); -} - -#[test] -fn loops_in_branches_summary() { - let summary = { - use Bytecode::*; - LoopSummary::new(&VMControlFlowGraph::new( - &[ - // B0, L0 - LdTrue, - // - BrTrue(8), - // B2, L5 - Nop, - // B3, L6 - LdFalse, - // - BrFalse(3), - // B5, L7 - LdTrue, - // - BrTrue(2), - // B7, L8 - Branch(13), - // B8, L1 - Nop, - // B9, L2 - LdTrue, - // - BrTrue(8), - // B11, L3 - LdFalse, - // - BrFalse(9), - // B13, L4 - Ret, - ], - &[], - )) - }; - - let n: Vec<_> = summary.preorder().collect(); - - assert_eq!(n.len(), 9); - - assert_node!( - summary, n[0]; - /* block */ 0, - /* preds */ &[], - /* descs */ &[n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[8]], - /* backs */ &[] - ); - - assert_node!( - summary, n[1]; - /* block */ 8, - /* preds */ &[n[0]], - /* descs */ &[n[2], n[3], n[4]], - /* backs */ &[n[2]] - ); - - assert_node!( - summary, n[2]; - /* block */ 9, - /* preds */ &[n[1]], - /* descs */ &[n[3], n[4]], - /* backs */ &[n[3]] - ); - - assert_node!( - summary, n[3]; - /* block */ 11, - /* preds */ &[n[2]], - /* descs */ &[n[4]], - /* backs */ &[] - ); - - assert_node!( - summary, n[4]; - /* block */ 13, - /* preds */ &[n[3], n[8]], - /* descs */ &[], - /* backs */ &[] - ); - - assert_node!( - summary, n[5]; - /* block */ 2, - /* preds */ &[n[0]], - /* descs */ &[n[6], n[7], n[8]], - /* backs */ &[n[7]] - ); - - assert_node!( - summary, n[6]; - /* block */ 3, - /* preds */ &[n[5]], - /* descs */ &[n[7], n[8]], - /* backs */ &[n[6]] - ); - - assert_node!( - summary, n[7]; - /* block */ 5, - /* preds */ &[n[6]], - /* descs */ &[n[8]], - /* backs */ &[] - ); - - assert_node!( - summary, n[8]; - /* block */ 7, - /* preds */ &[n[7]], - /* descs */ &[], - /* backs */ &[] - ); -} - -#[test] -fn loop_collapsing() { - let summary = { - use Bytecode::*; - LoopSummary::new(&VMControlFlowGraph::new( - &[ - // B0, L0 - LdTrue, - // - BrTrue(4), - // B2, L2 - Nop, - // - Branch(0), - // B4, L1 - Ret, - ], - &[], - )) - }; - - let mut partition = LoopPartition::new(&summary); - let n: Vec<_> = summary.preorder().collect(); - - for id in &n { - assert_eq!(*id, partition.containing_loop(*id), "Self-parent {:?}", id); - } - - assert_eq!(partition.collapse_loop(n[0], &[n[2]].into()), 1); - assert_eq!(partition.containing_loop(n[0]), n[0]); - assert_eq!(partition.containing_loop(n[1]), n[1]); - assert_eq!(partition.containing_loop(n[2]), n[0]); -} - -#[test] -fn nested_loop_collapsing() { - let summary = { - use Bytecode::*; - LoopSummary::new(&VMControlFlowGraph::new( - &[ - // B0, L0 - Nop, - // B1, L1 - LdTrue, - // - BrTrue(1), - // B3, L2 - LdFalse, - // - BrFalse(0), - // B5, L3 - LdTrue, - // - BrTrue(0), - // B7, L4 - Ret, - ], - &[], - )) - }; - - let mut partition = LoopPartition::new(&summary); - let n: Vec<_> = summary.preorder().collect(); - - // Self-loop is a special case -- its depth should still be bumped. - assert_eq!(partition.collapse_loop(n[1], &[].into()), 1); - assert_eq!(partition.collapse_loop(n[0], &[n[1], n[2]].into()), 2); - assert_eq!(partition.collapse_loop(n[0], &[n[0], n[3]].into()), 3); -} diff --git a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/many_back_edges.rs b/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/many_back_edges.rs deleted file mode 100644 index b8b488cbafb..00000000000 --- a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/many_back_edges.rs +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use move_binary_format::file_format::{ - empty_module, Bytecode, CodeUnit, FunctionDefinition, FunctionHandle, FunctionHandleIndex, - IdentifierIndex, ModuleHandleIndex, Signature, SignatureIndex, SignatureToken, - Visibility::Public, -}; -use move_bytecode_verifier_meter::bound::BoundMeter; -use move_core_types::{identifier::Identifier, vm_status::StatusCode}; - -use crate::unit_tests::production_config; - -const MAX_BASIC_BLOCKS: u16 = 1024; -const MAX_LOCALS: u8 = 255; - -const NUM_FUNCTIONS: u16 = 16; - -#[test] -fn many_backedges() { - let mut m = empty_module(); - - // signature of locals in f1..f - m.signatures.push(Signature( - std::iter::repeat(SignatureToken::U8) - .take(MAX_LOCALS as usize) - .collect(), - )); - - // create returns_bool_and_u64 - m.signatures - .push(Signature(vec![SignatureToken::Bool, SignatureToken::U8])); - m.identifiers - .push(Identifier::new("returns_bool_and_u64").unwrap()); - m.function_handles.push(FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(1), - parameters: SignatureIndex(0), - return_: SignatureIndex(2), - type_parameters: vec![], - }); - m.function_defs.push(FunctionDefinition { - function: FunctionHandleIndex(0), - visibility: Public, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![Bytecode::LdTrue, Bytecode::LdU8(0), Bytecode::Ret], - jump_tables: vec![], - }), - }); - - // create other functions - for i in 1..(NUM_FUNCTIONS + 1) { - m.identifiers - .push(Identifier::new(format!("f{}", i)).unwrap()); - m.function_handles.push(FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(i + 1), // the +1 accounts for returns_bool_and_u64 - parameters: SignatureIndex(0), - return_: SignatureIndex(0), - type_parameters: vec![], - }); - m.function_defs.push(FunctionDefinition { - function: FunctionHandleIndex(i), - visibility: Public, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(1), - code: vec![], - jump_tables: vec![], - }), - }); - - let code = &mut m.function_defs[i as usize].code.as_mut().unwrap().code; - - for _ in 0..(MAX_BASIC_BLOCKS - MAX_LOCALS as u16 - 2) { - code.push(Bytecode::LdTrue); - code.push(Bytecode::BrTrue(0)); - } - for i in 0..MAX_LOCALS { - code.push(Bytecode::Call(FunctionHandleIndex(0))); // calls returns_bool_and_u64 - code.push(Bytecode::StLoc(i)); // i'th local is now available for the first time - code.push(Bytecode::BrTrue(0)); - } - code.push(Bytecode::Ret); - } - - let (verifier_config, meter_config) = production_config(); - let mut meter = BoundMeter::new(meter_config); - let result = move_bytecode_verifier::verify_module_with_config_for_test( - "many_backedges", - &verifier_config, - &m, - &mut meter, - ); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::CONSTRAINT_NOT_SATISFIED - ); -} diff --git a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/mod.rs b/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/mod.rs deleted file mode 100644 index 4ed2fb574f7..00000000000 --- a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/mod.rs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use move_binary_format::file_format_common::VERSION_MAX; -use move_vm_config::verifier::{ - MeterConfig, VerifierConfig, DEFAULT_MAX_CONSTANT_VECTOR_LEN, DEFAULT_MAX_IDENTIFIER_LENGTH, - DEFAULT_MAX_VARIANTS, -}; - -pub mod binary_samples; -pub mod bounds_tests; -pub mod code_unit_tests; -pub mod constants_tests; -pub mod control_flow_tests; -pub mod duplication_tests; -pub mod generic_ops_tests; -pub mod large_type_test; -pub mod limit_tests; -pub mod locals; -pub mod loop_summary_tests; -pub mod many_back_edges; -pub mod negative_stack_size_tests; -pub mod reference_safety_tests; -pub mod signature_tests; -pub mod vec_pack_tests; - -/// Configuration used in production. -pub(crate) fn production_config() -> (VerifierConfig, MeterConfig) { - ( - VerifierConfig { - max_loop_depth: Some(5), - max_generic_instantiation_length: Some(32), - max_function_parameters: Some(128), - max_basic_blocks: Some(1024), - max_basic_blocks_in_script: Some(1024), - max_value_stack_size: 1024, - max_type_nodes: Some(256), - max_push_size: Some(10000), - max_dependency_depth: Some(100), - max_data_definitions: Some(200), - max_fields_in_struct: Some(30), - max_function_definitions: Some(1000), - - // Do not use back edge constraints as they are superseded by metering - max_back_edges_per_function: None, - max_back_edges_per_module: None, - - max_constant_vector_len: Some(DEFAULT_MAX_CONSTANT_VECTOR_LEN), - max_identifier_len: Some(DEFAULT_MAX_IDENTIFIER_LENGTH), - bytecode_version: VERSION_MAX, - max_variants_in_enum: Some(DEFAULT_MAX_VARIANTS), - }, - MeterConfig::old_default(), - ) -} diff --git a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/negative_stack_size_tests.rs b/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/negative_stack_size_tests.rs deleted file mode 100644 index 56844c517a1..00000000000 --- a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/negative_stack_size_tests.rs +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use move_binary_format::file_format::Bytecode; -use move_bytecode_verifier::{ability_cache::AbilityCache, code_unit_verifier}; -use move_bytecode_verifier_meter::dummy::DummyMeter; -use move_core_types::vm_status::StatusCode; - -use crate::support::dummy_procedure_module; - -#[test] -fn one_pop_no_push() { - let module = &dummy_procedure_module(vec![Bytecode::Pop, Bytecode::Ret]); - let ability_cache = &mut AbilityCache::new(module); - let result = code_unit_verifier::verify_module( - &Default::default(), - module, - ability_cache, - &mut DummyMeter, - ); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::NEGATIVE_STACK_SIZE_WITHIN_BLOCK - ); -} - -#[test] -fn one_pop_one_push() { - // Height: 0 + (-1 + 1) = 0 would have passed original usage verifier - let module = &dummy_procedure_module(vec![Bytecode::ReadRef, Bytecode::Ret]); - let ability_cache = &mut AbilityCache::new(module); - let result = code_unit_verifier::verify_module( - &Default::default(), - module, - ability_cache, - &mut DummyMeter, - ); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::NEGATIVE_STACK_SIZE_WITHIN_BLOCK - ); -} - -#[test] -fn two_pop_one_push() { - // Height: 0 + 1 + (-2 + 1) = 0 would have passed original usage verifier - let module = &dummy_procedure_module(vec![Bytecode::LdU64(0), Bytecode::Add, Bytecode::Ret]); - let ability_cache = &mut AbilityCache::new(module); - let result = code_unit_verifier::verify_module( - &Default::default(), - module, - ability_cache, - &mut DummyMeter, - ); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::NEGATIVE_STACK_SIZE_WITHIN_BLOCK - ); -} - -#[test] -fn two_pop_no_push() { - let module = &dummy_procedure_module(vec![Bytecode::WriteRef, Bytecode::Ret]); - let ability_cache = &mut AbilityCache::new(module); - let result = code_unit_verifier::verify_module( - &Default::default(), - module, - ability_cache, - &mut DummyMeter, - ); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::NEGATIVE_STACK_SIZE_WITHIN_BLOCK - ); -} diff --git a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/reference_safety_tests.rs b/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/reference_safety_tests.rs deleted file mode 100644 index 8be4f8a621b..00000000000 --- a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/reference_safety_tests.rs +++ /dev/null @@ -1,454 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use move_binary_format::file_format::{ - empty_module, Bytecode, CodeUnit, FunctionDefinition, FunctionHandle, FunctionHandleIndex, - IdentifierIndex, ModuleHandleIndex, Signature, SignatureIndex, SignatureToken, - Visibility::Public, -}; -use move_bytecode_verifier_meter::bound::BoundMeter; -use move_core_types::{identifier::Identifier, vm_status::StatusCode}; - -use crate::unit_tests::production_config; - -#[test] -fn test_bicliques() { - // See also: github.com/aptos-labs/aptos-core/security/advisories/ - // GHSA-xm6p-ffcq-5p2v - const NUM_LOCALS: u8 = 128; - const NUM_CALLS: u16 = 76; - const NUM_FUNCTIONS: u16 = 1; - - let mut m = empty_module(); - - m.function_handles.push(FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(0), - parameters: SignatureIndex(0), - return_: SignatureIndex(0), - type_parameters: vec![], - }); - m.function_defs.push(FunctionDefinition { - function: FunctionHandleIndex(0), - visibility: Public, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![Bytecode::Call(FunctionHandleIndex(0)), Bytecode::Ret], - jump_tables: vec![], - }), - }); - - // create take_and_return_references - m.signatures.push(Signature( - std::iter::repeat(SignatureToken::Reference(Box::new(SignatureToken::U64))) - .take(NUM_LOCALS as usize) - .collect(), - )); - m.identifiers - .push(Identifier::new("take_and_return_references").unwrap()); - m.function_handles.push(FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(1), - parameters: SignatureIndex(1), - return_: SignatureIndex(1), - type_parameters: vec![], - }); - m.function_defs.push(FunctionDefinition { - function: FunctionHandleIndex(1), - visibility: Public, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![], - jump_tables: vec![], - }), - }); - let code = &mut m.function_defs[1].code.as_mut().unwrap().code; - for i in 0..NUM_LOCALS { - code.push(Bytecode::MoveLoc(i)); - } - code.push(Bytecode::Ret); - - // create swallow_references - m.identifiers - .push(Identifier::new("swallow_references").unwrap()); - m.function_handles.push(FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(2), - parameters: SignatureIndex(1), - return_: SignatureIndex(0), - type_parameters: vec![], - }); - m.function_defs.push(FunctionDefinition { - function: FunctionHandleIndex(2), - visibility: Public, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![Bytecode::Ret], - jump_tables: vec![], - }), - }); - - // create other functions - for i in 1..(NUM_FUNCTIONS + 1) { - m.identifiers - .push(Identifier::new(format!("f{}", i)).unwrap()); - m.function_handles.push(FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(i + 2), - parameters: SignatureIndex(1), - return_: SignatureIndex(0), - type_parameters: vec![], - }); - m.function_defs.push(FunctionDefinition { - function: FunctionHandleIndex(i + 2), - visibility: Public, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![], - jump_tables: vec![], - }), - }); - let code = &mut m.function_defs[i as usize + 2].code.as_mut().unwrap().code; - for j in 0..NUM_LOCALS { - code.push(Bytecode::CopyLoc(j)); - } - for _ in 0..NUM_CALLS { - code.push(Bytecode::Call(FunctionHandleIndex(1))); - } - code.push(Bytecode::Call(FunctionHandleIndex(2))); - code.push(Bytecode::Ret); - } - - let (verifier_config, meter_config) = production_config(); - let mut meter = BoundMeter::new(meter_config); - let result = move_bytecode_verifier::verify_module_with_config_for_test( - "test_bicliques", - &verifier_config, - &m, - &mut meter, - ); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::CONSTRAINT_NOT_SATISFIED - ); -} - -#[test] -fn test_merge_state_large_graph() { - // See also: github.com/aptos-labs/aptos-core/security/advisories/ - // GHSA-g8v8-fw4c-8h82 - const N: u8 = 127; - const NUM_NOP_BLOCKS: u16 = 950; - const NUM_FUNCTIONS: u16 = 18; - - let mut m = empty_module(); - - m.function_handles.push(FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(0), - parameters: SignatureIndex(0), - return_: SignatureIndex(0), - type_parameters: vec![], - }); - m.function_defs.push(FunctionDefinition { - function: FunctionHandleIndex(0), - visibility: Public, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![Bytecode::Call(FunctionHandleIndex(0)), Bytecode::Ret], - jump_tables: vec![], - }), - }); - - m.signatures.push(Signature( - std::iter::repeat(SignatureToken::Reference(Box::new(SignatureToken::U8))) - .take(N as usize) - .collect(), - )); - - m.identifiers.push(Identifier::new("return_refs").unwrap()); - m.function_handles.push(FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(1), - parameters: SignatureIndex(0), - return_: SignatureIndex(1), - type_parameters: vec![], - }); - m.function_defs.push(FunctionDefinition { - function: FunctionHandleIndex(1), - visibility: Public, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![Bytecode::Call(FunctionHandleIndex(1)), Bytecode::Ret], - jump_tables: vec![], - }), - }); - - m.identifiers - .push(Identifier::new("take_and_return_refs").unwrap()); - m.function_handles.push(FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(2), - parameters: SignatureIndex(1), - return_: SignatureIndex(1), - type_parameters: vec![], - }); - m.function_defs.push(FunctionDefinition { - function: FunctionHandleIndex(2), - visibility: Public, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![Bytecode::Call(FunctionHandleIndex(1)), Bytecode::Ret], - jump_tables: vec![], - }), - }); - - for i in 0..NUM_FUNCTIONS { - m.identifiers - .push(Identifier::new(format!("f{}", i)).unwrap()); - m.function_handles.push(FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(i + 3), - parameters: SignatureIndex(1), - return_: SignatureIndex(0), - type_parameters: vec![], - }); - m.function_defs.push(FunctionDefinition { - function: FunctionHandleIndex(i + 3), - visibility: Public, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(1), - code: vec![], - jump_tables: vec![], - }), - }); - let code = &mut m.function_defs[i as usize + 3].code.as_mut().unwrap().code; - for j in 0..N { - code.push(Bytecode::CopyLoc(j)); - } - code.push(Bytecode::Call(FunctionHandleIndex(2))); - for j in 0..N { - code.push(Bytecode::StLoc(N + j)); - } - for _ in 0..NUM_NOP_BLOCKS { - code.push(Bytecode::LdTrue); - code.push(Bytecode::BrTrue(0)); - } - - code.push(Bytecode::Ret); - } - - let (verifier_config, meter_config) = production_config(); - let mut meter = BoundMeter::new(meter_config); - let result = move_bytecode_verifier::verify_module_with_config_for_test( - "test_merge_state_large_graph", - &verifier_config, - &m, - &mut meter, - ); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::CONSTRAINT_NOT_SATISFIED - ); -} - -#[test] -fn test_merge_state() { - // See also: github.com/aptos-labs/aptos-core/security/advisories/ - // GHSA-g8v8-fw4c-8h82 - const NUM_NOP_BLOCKS: u16 = 965; - const NUM_LOCALS: u8 = 32; - const NUM_FUNCTIONS: u16 = 21; - - let mut m = empty_module(); - - m.function_handles.push(FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(0), - parameters: SignatureIndex(0), - return_: SignatureIndex(0), - type_parameters: vec![], - }); - m.function_defs.push(FunctionDefinition { - function: FunctionHandleIndex(0), - visibility: Public, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![Bytecode::Call(FunctionHandleIndex(0)), Bytecode::Ret], - jump_tables: vec![], - }), - }); - - m.signatures - .push(Signature(vec![SignatureToken::Reference(Box::new( - SignatureToken::U8, - ))])); - m.signatures.push(Signature( - std::iter::repeat(SignatureToken::Reference(Box::new(SignatureToken::U8))) - .take(NUM_LOCALS as usize - 1) - .collect(), - )); - - for i in 0..NUM_FUNCTIONS { - m.identifiers - .push(Identifier::new(format!("f{}", i)).unwrap()); - m.function_handles.push(FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(i + 1), - parameters: SignatureIndex(1), - return_: SignatureIndex(0), - type_parameters: vec![], - }); - m.function_defs.push(FunctionDefinition { - function: FunctionHandleIndex(i + 1), - visibility: Public, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(2), - code: vec![], - jump_tables: vec![], - }), - }); - let code = &mut m.function_defs[i as usize + 1].code.as_mut().unwrap().code; - // create reference id - code.push(Bytecode::CopyLoc(0)); - code.push(Bytecode::StLoc(1)); - // create a path of length NUM_LOCALS - 1 in the borrow graph - for j in 0..(NUM_LOCALS - 2) { - // create Ref(new_id) and factor in empty-path edge id -> new_id - code.push(Bytecode::CopyLoc(1)); - // can't leave those references on stack since basic blocks need to be - // stack-neutral - code.push(Bytecode::StLoc(j + 2)); - } - for _ in 0..NUM_NOP_BLOCKS { - code.push(Bytecode::LdTrue); - // create back edge to first block - code.push(Bytecode::BrTrue(0)); - } - - code.push(Bytecode::Ret); - } - - let (verifier_config, meter_config) = production_config(); - let mut meter = BoundMeter::new(meter_config); - let result = move_bytecode_verifier::verify_module_with_config_for_test( - "test_merge_state", - &verifier_config, - &m, - &mut meter, - ); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::CONSTRAINT_NOT_SATISFIED - ); -} - -#[test] -fn test_copyloc_pop() { - // See also: github.com/aptos-labs/aptos-core/security/advisories/ - // GHSA-2qvr-c9qp-wch7 - const NUM_COPYLOCS: u16 = 1880; - const NUM_CHILDREN: u16 = 1020; - const NUM_FUNCTIONS: u16 = 2; - - let mut m = empty_module(); - - // parameters of f0, f1, ... - m.signatures - .push(Signature(vec![SignatureToken::Reference(Box::new( - SignatureToken::Vector(Box::new(SignatureToken::U8)), - ))])); - // locals of f0, f1, ... - m.signatures.push(Signature(vec![ - SignatureToken::Reference(Box::new(SignatureToken::Vector(Box::new( - SignatureToken::U8, - )))), - SignatureToken::U8, /* ignore this, it's just here because I don't want to fix indices - * and the TypeParameter after removing the collision */ - ])); - // for VecImmBorrow - m.signatures.push(Signature( - std::iter::repeat(SignatureToken::U8).take(1).collect(), - )); - m.signatures - .push(Signature(vec![SignatureToken::TypeParameter(0)])); - - for i in 0..NUM_FUNCTIONS { - m.identifiers - .push(Identifier::new(format!("f{}", i)).unwrap()); - m.function_handles.push(FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(i), - parameters: SignatureIndex(1), - return_: SignatureIndex(0), - type_parameters: vec![], - }); - m.function_defs.push(FunctionDefinition { - function: FunctionHandleIndex(i), - visibility: Public, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(2), - code: vec![], - jump_tables: vec![], - }), - }); - let code = &mut m.function_defs[i as usize].code.as_mut().unwrap().code; - - // create reference id - code.push(Bytecode::CopyLoc(0)); - code.push(Bytecode::StLoc(1)); - // create NUM_CHLIDREN children of id - for _ in 0..NUM_CHILDREN { - code.push(Bytecode::CopyLoc(1)); - code.push(Bytecode::LdU64(0)); - code.push(Bytecode::VecImmBorrow(SignatureIndex(3))); - } - // then do a whole lot of copylocs on that reference - for _ in 0..NUM_COPYLOCS { - code.push(Bytecode::CopyLoc(1)); - code.push(Bytecode::Pop); - } - for _ in 0..NUM_CHILDREN { - code.push(Bytecode::Pop); - } - - code.push(Bytecode::Ret); - } - - let (verifier_config, meter_config) = production_config(); - let mut meter = BoundMeter::new(meter_config); - let result = move_bytecode_verifier::verify_module_with_config_for_test( - "test_copyloc_pop", - &verifier_config, - &m, - &mut meter, - ); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::CONSTRAINT_NOT_SATISFIED - ); -} diff --git a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/signature_tests.rs b/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/signature_tests.rs deleted file mode 100644 index 5e9ad8923fc..00000000000 --- a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/signature_tests.rs +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use move_binary_format::file_format::{ - Bytecode::*, CompiledModule, SignatureToken::*, Visibility::Public, *, -}; -use move_bytecode_verifier::{ - ability_cache::AbilityCache, verify_module_unmetered, verify_module_with_config_for_test, - SignatureChecker, -}; -use move_bytecode_verifier_meter::dummy::DummyMeter; -use move_core_types::{ - account_address::AccountAddress, identifier::Identifier, vm_status::StatusCode, -}; - -use crate::unit_tests::production_config; - -#[test] -fn test_reference_of_reference() { - let mut m = basic_test_module(); - m.signatures[0] = Signature(vec![Reference(Box::new(Reference(Box::new( - SignatureToken::Bool, - ))))]); - let ability_cache = &mut AbilityCache::new(&m); - let errors = SignatureChecker::verify_module(&m, ability_cache, &mut DummyMeter); - assert!(errors.is_err()); -} - -#[test] -fn no_verify_locals_good() { - let compiled_module_good = CompiledModule { - version: move_binary_format::file_format_common::VERSION_MAX, - module_handles: vec![ModuleHandle { - address: AddressIdentifierIndex(0), - name: IdentifierIndex(0), - }], - self_module_handle_idx: ModuleHandleIndex(0), - datatype_handles: vec![], - signatures: vec![ - Signature(vec![Address]), - Signature(vec![U64]), - Signature(vec![]), - ], - function_handles: vec![ - FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(1), - return_: SignatureIndex(2), - parameters: SignatureIndex(0), - type_parameters: vec![], - }, - FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(2), - return_: SignatureIndex(2), - parameters: SignatureIndex(1), - type_parameters: vec![], - }, - ], - field_handles: vec![], - friend_decls: vec![], - struct_def_instantiations: vec![], - function_instantiations: vec![], - field_instantiations: vec![], - identifiers: vec![ - Identifier::new("Bad").unwrap(), - Identifier::new("blah").unwrap(), - Identifier::new("foo").unwrap(), - ], - address_identifiers: vec![AccountAddress::new([0; AccountAddress::LENGTH])], - constant_pool: vec![], - metadata: vec![], - struct_defs: vec![], - function_defs: vec![ - FunctionDefinition { - function: FunctionHandleIndex(0), - visibility: Visibility::Public, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![Ret], - jump_tables: vec![], - }), - }, - FunctionDefinition { - function: FunctionHandleIndex(1), - visibility: Visibility::Public, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(1), - code: vec![Ret], - jump_tables: vec![], - }), - }, - ], - enum_defs: vec![], - enum_def_instantiations: vec![], - variant_handles: vec![], - variant_instantiation_handles: vec![], - }; - assert!(verify_module_unmetered(&compiled_module_good).is_ok()); -} - -#[test] -fn big_signature_test() { - const N_TYPE_PARAMS: usize = 5; - const INSTANTIATION_DEPTH: usize = 3; - const VECTOR_DEPTH: usize = 250; - let mut st = SignatureToken::U8; - for _ in 0..VECTOR_DEPTH { - st = SignatureToken::Vector(Box::new(st)); - } - for _ in 0..INSTANTIATION_DEPTH { - let type_params = vec![st; N_TYPE_PARAMS]; - st = SignatureToken::DatatypeInstantiation(Box::new((DatatypeHandleIndex(0), type_params))); - } - - const N_READPOP: u16 = 7500; - - let mut code = vec![]; - // 1. ImmBorrowLoc: ... ref - // 2. ReadRef: ... value - // 3. Pop: ... - for _ in 0..N_READPOP { - code.push(Bytecode::ImmBorrowLoc(0)); - code.push(Bytecode::ReadRef); - code.push(Bytecode::Pop); - } - code.push(Bytecode::Ret); - - let type_param_constraints = DatatypeTyParameter { - constraints: AbilitySet::EMPTY, - is_phantom: false, - }; - - let module = CompiledModule { - version: 5, - self_module_handle_idx: ModuleHandleIndex(0), - module_handles: vec![ModuleHandle { - address: AddressIdentifierIndex(0), - name: IdentifierIndex(0), - }], - datatype_handles: vec![DatatypeHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(1), - abilities: AbilitySet::ALL, - type_parameters: vec![type_param_constraints; N_TYPE_PARAMS], - }], - function_handles: vec![FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(0), - parameters: SignatureIndex(1), - return_: SignatureIndex(0), - type_parameters: vec![], - }], - field_handles: vec![], - friend_decls: vec![], - struct_def_instantiations: vec![], - function_instantiations: vec![], - field_instantiations: vec![], - signatures: vec![Signature(vec![]), Signature(vec![st])], - identifiers: vec![ - Identifier::new("f").unwrap(), - Identifier::new("generic_struct").unwrap(), - ], - address_identifiers: vec![AccountAddress::ONE], - constant_pool: vec![], - metadata: vec![], - struct_defs: vec![StructDefinition { - struct_handle: DatatypeHandleIndex(0), - field_information: StructFieldInformation::Native, - }], - function_defs: vec![FunctionDefinition { - function: FunctionHandleIndex(0), - visibility: Public, - is_entry: true, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(0), - code, - jump_tables: vec![], - }), - }], - enum_def_instantiations: vec![], - enum_defs: vec![], - variant_handles: vec![], - variant_instantiation_handles: vec![], - }; - - // save module and verify that it can ser/de - let mut mvbytes = vec![]; - module.serialize(&mut mvbytes).unwrap(); - let module = CompiledModule::deserialize_with_defaults(&mvbytes).unwrap(); - - let res = verify_module_with_config_for_test( - "big_signature_test", - &production_config().0, - &module, - &mut DummyMeter, - ) - .unwrap_err(); - assert_eq!(res.major_status(), StatusCode::TOO_MANY_TYPE_NODES); -} diff --git a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/vec_pack_tests.rs b/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/vec_pack_tests.rs deleted file mode 100644 index 1f7c54d8991..00000000000 --- a/external-crates/move/move-execution/v0/crates/bytecode-verifier-tests/src/unit_tests/vec_pack_tests.rs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use move_binary_format::file_format::{ - empty_module, Bytecode, CodeUnit, FunctionDefinition, FunctionHandle, FunctionHandleIndex, - IdentifierIndex, ModuleHandleIndex, Signature, SignatureIndex, SignatureToken, Visibility, -}; -use move_bytecode_verifier_meter::dummy::DummyMeter; -use move_core_types::{identifier::Identifier, vm_status::StatusCode}; - -use crate::unit_tests::production_config; - -fn vec_sig(len: usize) -> SignatureToken { - if len > 0 { - SignatureToken::Vector(Box::new(vec_sig(len - 1))) - } else { - SignatureToken::U8 - } -} - -#[test] -fn test_vec_pack() { - let mut m = empty_module(); - - let sig = SignatureIndex(m.signatures.len() as u16); - m.signatures.push(Signature(vec![vec_sig(255)])); - - m.function_defs.push(FunctionDefinition { - function: FunctionHandleIndex(0), - visibility: Visibility::Private, - is_entry: false, - acquires_global_resources: vec![], - code: Some(CodeUnit { - locals: SignatureIndex(0), - code: vec![], - jump_tables: vec![], - }), - }); - - m.function_handles.push(FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(m.identifiers.len() as u16), - parameters: SignatureIndex(0), - return_: SignatureIndex(0), - type_parameters: vec![], - }); - m.identifiers - .push(Identifier::new("foo".to_string()).unwrap()); - - const COUNT: usize = 3000; - - m.function_defs[0].code.as_mut().unwrap().code = - std::iter::once(&[Bytecode::VecPack(sig, 0)][..]) - .chain( - std::iter::repeat( - &[Bytecode::VecUnpack(sig, 1024), Bytecode::VecPack(sig, 1024)][..], - ) - .take(COUNT), - ) - .chain(std::iter::once(&[Bytecode::Pop, Bytecode::Ret][..])) - .flatten() - .cloned() - .collect(); - - let res = move_bytecode_verifier::verify_module_with_config_for_test( - "test_vec_pack", - &production_config().0, - &m, - &mut DummyMeter, - ) - .unwrap_err(); - assert_eq!(res.major_status(), StatusCode::VALUE_STACK_PUSH_OVERFLOW); -} diff --git a/external-crates/move/move-execution/v0/crates/move-abstract-interpreter/Cargo.toml b/external-crates/move/move-execution/v0/crates/move-abstract-interpreter/Cargo.toml deleted file mode 100644 index b0dd9fc240b..00000000000 --- a/external-crates/move/move-execution/v0/crates/move-abstract-interpreter/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "move-abstract-interpreter-v0" -version = "0.1.0" -authors = ["The Move Contributors"] -edition = "2021" -license = "Apache-2.0" -publish = false -description = "Move abstract interpreter" - -[dependencies] -move-binary-format.workspace = true -move-bytecode-verifier-meter.workspace = true - -[dev-dependencies] -itertools.workspace = true - -[features] -default = [] diff --git a/external-crates/move/move-execution/v0/crates/move-abstract-interpreter/src/absint.rs b/external-crates/move/move-execution/v0/crates/move-abstract-interpreter/src/absint.rs deleted file mode 100644 index 480ff082c60..00000000000 --- a/external-crates/move/move-execution/v0/crates/move-abstract-interpreter/src/absint.rs +++ /dev/null @@ -1,236 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use std::collections::BTreeMap; - -use move_binary_format::{ - errors::PartialVMResult, - file_format::{ - AbilitySet, Bytecode, CodeOffset, CodeUnit, FunctionDefinitionIndex, FunctionHandle, - Signature, - }, - CompiledModule, -}; -use move_bytecode_verifier_meter::{Meter, Scope}; - -use crate::control_flow_graph::{BlockId, ControlFlowGraph, VMControlFlowGraph}; - -/// A `FunctionContext` holds all the information needed by the verifier for -/// `FunctionDefinition`.` A control flow graph is built for a function when the -/// `FunctionContext` is created. -pub struct FunctionContext<'a> { - index: Option, - code: &'a CodeUnit, - parameters: &'a Signature, - return_: &'a Signature, - locals: &'a Signature, - type_parameters: &'a [AbilitySet], - cfg: VMControlFlowGraph, -} - -/// Trait for finite-height abstract domains. Infinite height domains would -/// require a more complex trait with widening and a partial order. -pub trait AbstractDomain: Clone + Sized { - fn join( - &mut self, - other: &Self, - meter: &mut (impl Meter + ?Sized), - ) -> PartialVMResult; -} - -#[derive(Debug)] -pub enum JoinResult { - Changed, - Unchanged, -} - -#[allow(dead_code)] -#[derive(Clone)] -pub struct BlockInvariant { - /// Precondition of the block - pre: State, -} - -/// A map from block id's to the pre/post of each block after a fixed point is -/// reached. -#[allow(dead_code)] -pub type InvariantMap = BTreeMap>; - -/// Costs for metered verification -const ANALYZE_FUNCTION_BASE_COST: u128 = 10; -const EXECUTE_BLOCK_BASE_COST: u128 = 10; -const PER_BACKEDGE_COST: u128 = 10; -const PER_SUCCESSOR_COST: u128 = 10; - -/// Take a pre-state + instruction and mutate it to produce a post-state -/// Auxiliary data can be stored in self. -pub trait TransferFunctions { - type State: AbstractDomain; - type Error; - - /// Execute local@instr found at index local@index in the current basic - /// block from pre-state local@pre. - /// Should return an AnalysisError if executing the instruction is - /// unsuccessful, and () if the effects of successfully executing - /// local@instr have been reflected by mutatating local@pre. - /// Auxiliary data from the analysis that is not part of the abstract state - /// can be collected by mutating local@self. - /// The last instruction index in the current block is local@last_index. - /// Knowing this information allows clients to detect the end of a basic - /// block and special-case appropriately (e.g., normalizing the abstract - /// state before a join). - fn execute( - &mut self, - pre: &mut Self::State, - instr: &Bytecode, - index: CodeOffset, - last_index: CodeOffset, - meter: &mut (impl Meter + ?Sized), - ) -> PartialVMResult<()>; -} - -pub trait AbstractInterpreter: TransferFunctions { - /// Analyze procedure local@function_context starting from pre-state - /// local@initial_state. - fn analyze_function( - &mut self, - initial_state: Self::State, - function_context: &FunctionContext, - meter: &mut (impl Meter + ?Sized), - ) -> PartialVMResult<()> { - meter.add(Scope::Function, ANALYZE_FUNCTION_BASE_COST)?; - let mut inv_map = InvariantMap::new(); - let entry_block_id = function_context.cfg().entry_block_id(); - let mut next_block = Some(entry_block_id); - inv_map.insert(entry_block_id, BlockInvariant { pre: initial_state }); - - while let Some(block_id) = next_block { - let block_invariant = match inv_map.get_mut(&block_id) { - Some(invariant) => invariant, - None => { - // This can only happen when all predecessors have errors, - // so skip the block and move on to the next one - next_block = function_context.cfg().next_block(block_id); - continue; - } - }; - - let pre_state = &block_invariant.pre; - // Note: this will stop analysis after the first error occurs, to avoid the risk - // of subsequent crashes - let post_state = self.execute_block(block_id, pre_state, function_context, meter)?; - - let mut next_block_candidate = function_context.cfg().next_block(block_id); - // propagate postcondition of this block to successor blocks - for successor_block_id in function_context.cfg().successors(block_id) { - meter.add(Scope::Function, PER_SUCCESSOR_COST)?; - match inv_map.get_mut(successor_block_id) { - Some(next_block_invariant) => { - let join_result = { - let old_pre = &mut next_block_invariant.pre; - old_pre.join(&post_state, meter) - }?; - match join_result { - JoinResult::Unchanged => { - // Pre is the same after join. Reanalyzing this - // block would produce - // the same post - } - JoinResult::Changed => { - // If the cur->successor is a back edge, jump back to the beginning - // of the loop, instead of the normal next block - if function_context - .cfg() - .is_back_edge(block_id, *successor_block_id) - { - meter.add(Scope::Function, PER_BACKEDGE_COST)?; - next_block_candidate = Some(*successor_block_id); - break; - } - } - } - } - None => { - // Haven't visited the next block yet. Use the post of the current block as - // its pre - inv_map.insert( - *successor_block_id, - BlockInvariant { - pre: post_state.clone(), - }, - ); - } - } - } - next_block = next_block_candidate; - } - Ok(()) - } - - fn execute_block( - &mut self, - block_id: BlockId, - pre_state: &Self::State, - function_context: &FunctionContext, - meter: &mut (impl Meter + ?Sized), - ) -> PartialVMResult { - meter.add(Scope::Function, EXECUTE_BLOCK_BASE_COST)?; - let mut state_acc = pre_state.clone(); - let block_end = function_context.cfg().block_end(block_id); - for offset in function_context.cfg().instr_indexes(block_id) { - let instr = &function_context.code().code[offset as usize]; - self.execute(&mut state_acc, instr, offset, block_end, meter)? - } - Ok(state_acc) - } -} - -impl<'a> FunctionContext<'a> { - // Creates a `FunctionContext` for a module function. - pub fn new( - module: &'a CompiledModule, - index: FunctionDefinitionIndex, - code: &'a CodeUnit, - function_handle: &'a FunctionHandle, - ) -> Self { - Self { - index: Some(index), - code, - parameters: module.signature_at(function_handle.parameters), - return_: module.signature_at(function_handle.return_), - locals: module.signature_at(code.locals), - type_parameters: &function_handle.type_parameters, - cfg: VMControlFlowGraph::new(&code.code, &code.jump_tables), - } - } - - pub fn index(&self) -> Option { - self.index - } - - pub fn code(&self) -> &'a CodeUnit { - self.code - } - - pub fn parameters(&self) -> &'a Signature { - self.parameters - } - - pub fn return_(&self) -> &'a Signature { - self.return_ - } - - pub fn locals(&self) -> &'a Signature { - self.locals - } - - pub fn type_parameters(&self) -> &'a [AbilitySet] { - self.type_parameters - } - - pub fn cfg(&self) -> &VMControlFlowGraph { - &self.cfg - } -} diff --git a/external-crates/move/move-execution/v0/crates/move-abstract-interpreter/src/control_flow_graph.rs b/external-crates/move/move-execution/v0/crates/move-abstract-interpreter/src/control_flow_graph.rs deleted file mode 100644 index 1ee2a267829..00000000000 --- a/external-crates/move/move-execution/v0/crates/move-abstract-interpreter/src/control_flow_graph.rs +++ /dev/null @@ -1,353 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -//! This module defines the control-flow graph uses for bytecode verification. -use move_binary_format::file_format::{Bytecode, CodeOffset, VariantJumpTable}; -use std::collections::{btree_map::Entry, BTreeMap, BTreeSet}; - -// BTree/Hash agnostic type wrappers -type Map = BTreeMap; -type Set = BTreeSet; - -pub type BlockId = CodeOffset; - -/// A trait that specifies the basic requirements for a CFG -pub trait ControlFlowGraph { - /// Start index of the block ID in the bytecode vector - fn block_start(&self, block_id: BlockId) -> CodeOffset; - - /// End index of the block ID in the bytecode vector - fn block_end(&self, block_id: BlockId) -> CodeOffset; - - /// Successors of the block ID in the bytecode vector - fn successors(&self, block_id: BlockId) -> &Vec; - - /// Return the next block in traversal order - fn next_block(&self, block_id: BlockId) -> Option; - - /// Iterator over the indexes of instructions in this block - fn instr_indexes(&self, block_id: BlockId) -> Box>; - - /// Return an iterator over the blocks of the CFG - fn blocks(&self) -> Vec; - - /// Return the number of blocks (vertices) in the control flow graph - fn num_blocks(&self) -> u16; - - /// Return the id of the entry block for this control-flow graph - /// Note: even a CFG with no instructions has an (empty) entry block. - fn entry_block_id(&self) -> BlockId; - - /// Checks if the block ID is a loop head - fn is_loop_head(&self, block_id: BlockId) -> bool; - - /// Checks if the edge from cur->next is a back edge - /// returns false if the edge is not in the cfg - fn is_back_edge(&self, cur: BlockId, next: BlockId) -> bool; - - /// Return the number of back edges in the cfg - fn num_back_edges(&self) -> usize; -} - -struct BasicBlock { - exit: CodeOffset, - successors: Vec, -} - -/// The control flow graph that we build from the bytecode. -pub struct VMControlFlowGraph { - /// The basic blocks - blocks: Map, - /// Basic block ordering for traversal - traversal_successors: Map, - /// Map of loop heads with all of their back edges - loop_heads: Map>, -} - -impl BasicBlock { - pub fn display(&self, entry: BlockId) { - println!("+=======================+"); - println!("| Enter: {} |", entry); - println!("+-----------------------+"); - println!("==> Children: {:?}", self.successors); - println!("+-----------------------+"); - println!("| Exit: {} |", self.exit); - println!("+=======================+"); - } -} - -const ENTRY_BLOCK_ID: BlockId = 0; - -impl VMControlFlowGraph { - pub fn new(code: &[Bytecode], jump_tables: &[VariantJumpTable]) -> Self { - let code_len = code.len() as CodeOffset; - // First go through and collect block ids, i.e., offsets that begin basic - // blocks. Need to do this first in order to handle backwards edges. - let mut block_ids = Set::new(); - block_ids.insert(ENTRY_BLOCK_ID); - for pc in 0..code.len() { - VMControlFlowGraph::record_block_ids( - pc as CodeOffset, - code, - jump_tables, - &mut block_ids, - ); - } - - // Create basic blocks - let mut blocks = Map::new(); - let mut entry = 0; - let mut exit_to_entry = Map::new(); - for pc in 0..code.len() { - let co_pc = pc as CodeOffset; - - // Create a basic block - if Self::is_end_of_block(co_pc, code, &block_ids) { - let exit = co_pc; - exit_to_entry.insert(exit, entry); - let successors = Bytecode::get_successors(co_pc, code, jump_tables); - let bb = BasicBlock { exit, successors }; - blocks.insert(entry, bb); - entry = co_pc + 1; - } - } - let blocks = blocks; - assert_eq!(entry, code_len); - - // # Loop analysis - // - // This section identifies loops in the control-flow graph, picks a back edge - // and loop head (the basic block the back edge returns to), and decides - // the order that blocks are traversed during abstract interpretation - // (reverse post-order). - // - // The implementation is based on the algorithm for finding widening points in - // Section 4.1, "Depth-first numbering" of Bourdoncle [1993], "Efficient - // chaotic iteration strategies with widenings." - // - // NB. The comments below refer to a block's sub-graph -- the reflexive - // transitive closure of its successor edges, modulo cycles. - - #[derive(Copy, Clone)] - enum Exploration { - InProgress, - Done, - } - - let mut exploration: Map = Map::new(); - let mut stack = vec![ENTRY_BLOCK_ID]; - - // For every loop in the CFG that is reachable from the entry block, there is an - // entry in `loop_heads` mapping to all the back edges pointing to it, - // and vice versa. - // - // Entry in `loop_heads` implies loop in the CFG is justified by the comments in - // the loop below. Loop in the CFG implies entry in `loop_heads` is - // justified by considering the point at which the first node in that - // loop, `F` is added to the `exploration` map: - // - // - By definition `F` is part of a loop, meaning there is a block `L` such - // that: - // - // F - ... -> L -> F - // - // - `F` will not transition to `Done` until all the nodes reachable from it - // (including `L`) have been visited. - // - Because `F` is the first node seen in the loop, all the other nodes in the - // loop (including `L`) will be visited while `F` is `InProgress`. - // - Therefore, we will process the `L -> F` edge while `F` is `InProgress`. - // - Therefore, we will record a back edge to it. - let mut loop_heads: Map> = Map::new(); - - // Blocks appear in `post_order` after all the blocks in their (non-reflexive) - // sub-graph. - let mut post_order = Vec::with_capacity(blocks.len()); - - while let Some(block) = stack.pop() { - match exploration.entry(block) { - Entry::Vacant(entry) => { - // Record the fact that exploration of this block and its sub-graph has started. - entry.insert(Exploration::InProgress); - - // Push the block back on the stack to finish processing it, and mark it as done - // once its sub-graph has been traversed. - stack.push(block); - - for succ in &blocks[&block].successors { - match exploration.get(succ) { - // This successor has never been visited before, add it to the stack to - // be explored before `block` gets marked `Done`. - None => stack.push(*succ), - - // This block's sub-graph was being explored, meaning it is a (reflexive - // transitive) predecessor of `block` as well as being a successor, - // implying a loop has been detected -- greedily choose the successor - // block as the loop head. - Some(Exploration::InProgress) => { - loop_heads.entry(*succ).or_default().insert(block); - } - - // Cross-edge detected, this block and its entire sub-graph (modulo - // cycles) has already been explored via a different path, and is - // already present in `post_order`. - Some(Exploration::Done) => { /* skip */ } - }; - } - } - - Entry::Occupied(mut entry) => match entry.get() { - // Already traversed the sub-graph reachable from this block, so skip it. - Exploration::Done => continue, - - // Finish up the traversal by adding this block to the post-order traversal - // after its sub-graph (modulo cycles). - Exploration::InProgress => { - post_order.push(block); - entry.insert(Exploration::Done); - } - }, - } - } - - let traversal_order = { - // This reverse post order is akin to a topological sort (ignoring cycles) and - // is different from a pre-order in the presence of diamond patterns - // in the graph. - post_order.reverse(); - post_order - }; - - // build a mapping from a block id to the next block id in the traversal order - let traversal_successors = traversal_order - .windows(2) - .map(|window| { - debug_assert!(window.len() == 2); - (window[0], window[1]) - }) - .collect(); - - VMControlFlowGraph { - blocks, - traversal_successors, - loop_heads, - } - } - - pub fn display(&self) { - for (entry, block) in &self.blocks { - block.display(*entry); - } - println!("Traversal: {:#?}", self.traversal_successors); - } - - fn is_end_of_block(pc: CodeOffset, code: &[Bytecode], block_ids: &Set) -> bool { - pc + 1 == (code.len() as CodeOffset) || block_ids.contains(&(pc + 1)) - } - - fn record_block_ids( - pc: CodeOffset, - code: &[Bytecode], - jump_tables: &[VariantJumpTable], - block_ids: &mut Set, - ) { - let bytecode = &code[pc as usize]; - - block_ids.extend(bytecode.offsets(jump_tables)); - - if bytecode.is_branch() && pc + 1 < (code.len() as CodeOffset) { - block_ids.insert(pc + 1); - } - } - - /// A utility function that implements BFS-reachability from block_id with - /// respect to get_targets function - fn traverse_by(&self, block_id: BlockId) -> Vec { - let mut ret = Vec::new(); - // We use this index to keep track of our frontier. - let mut index = 0; - // Guard against cycles - let mut seen = Set::new(); - - ret.push(block_id); - seen.insert(&block_id); - - while index < ret.len() { - let block_id = ret[index]; - index += 1; - let successors = self.successors(block_id); - for block_id in successors.iter() { - if !seen.contains(&block_id) { - ret.push(*block_id); - seen.insert(block_id); - } - } - } - - ret - } - - pub fn reachable_from(&self, block_id: BlockId) -> Vec { - self.traverse_by(block_id) - } -} - -impl ControlFlowGraph for VMControlFlowGraph { - // Note: in the following procedures, it's safe not to check bounds because: - // - Every CFG (even one with no instructions) has a block at ENTRY_BLOCK_ID - // - The only way to acquire new BlockId's is via block_successors() - // - block_successors only() returns valid BlockId's - // Note: it is still possible to get a BlockId from one CFG and use it in - // another CFG where it is not valid. The design does not attempt to prevent - // this abuse of the API. - - fn block_start(&self, block_id: BlockId) -> CodeOffset { - block_id - } - - fn block_end(&self, block_id: BlockId) -> CodeOffset { - self.blocks[&block_id].exit - } - - fn successors(&self, block_id: BlockId) -> &Vec { - &self.blocks[&block_id].successors - } - - fn next_block(&self, block_id: BlockId) -> Option { - debug_assert!(self.blocks.contains_key(&block_id)); - self.traversal_successors.get(&block_id).copied() - } - - fn instr_indexes(&self, block_id: BlockId) -> Box> { - Box::new(self.block_start(block_id)..=self.block_end(block_id)) - } - - fn blocks(&self) -> Vec { - self.blocks.keys().cloned().collect() - } - - fn num_blocks(&self) -> u16 { - self.blocks.len() as u16 - } - - fn entry_block_id(&self) -> BlockId { - ENTRY_BLOCK_ID - } - - fn is_loop_head(&self, block_id: BlockId) -> bool { - self.loop_heads.contains_key(&block_id) - } - - fn is_back_edge(&self, cur: BlockId, next: BlockId) -> bool { - self.loop_heads - .get(&next) - .map_or(false, |back_edges| back_edges.contains(&cur)) - } - - fn num_back_edges(&self) -> usize { - self.loop_heads - .iter() - .fold(0, |acc, (_, edges)| acc + edges.len()) - } -} diff --git a/external-crates/move/move-execution/v0/crates/move-abstract-interpreter/src/lib.rs b/external-crates/move/move-execution/v0/crates/move-abstract-interpreter/src/lib.rs deleted file mode 100644 index e103979117e..00000000000 --- a/external-crates/move/move-execution/v0/crates/move-abstract-interpreter/src/lib.rs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -pub mod absint; -pub mod control_flow_graph; - -#[cfg(test)] -mod unit_tests; diff --git a/external-crates/move/move-execution/v0/crates/move-abstract-interpreter/src/unit_tests/control_flow_graph_tests.rs b/external-crates/move/move-execution/v0/crates/move-abstract-interpreter/src/unit_tests/control_flow_graph_tests.rs deleted file mode 100644 index 83cb0ca6fe3..00000000000 --- a/external-crates/move/move-execution/v0/crates/move-abstract-interpreter/src/unit_tests/control_flow_graph_tests.rs +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use itertools::Itertools; - -use crate::control_flow_graph::{BlockId, ControlFlowGraph, VMControlFlowGraph}; - -use move_binary_format::file_format::{ - Bytecode, EnumDefinitionIndex, JumpTableInner, VariantJumpTable, VariantJumpTableIndex, -}; - -#[test] -fn traversal_no_loops() { - let cfg = { - use Bytecode::*; - VMControlFlowGraph::new( - &[ - /* L0 */ LdTrue, - /* */ BrTrue(3), - /* L2 */ Branch(3), - /* L3 */ Ret, - ], - &[], - ) - }; - - cfg.display(); - assert_eq!(cfg.num_blocks(), 3); - assert_eq!(traversal(&cfg), vec![0, 2, 3]); -} - -#[test] -fn traversal_no_loops_with_switch() { - let cfg = { - use Bytecode::*; - VMControlFlowGraph::new( - &[ - /* L0 */ VariantSwitch(VariantJumpTableIndex::new(0)), - /* */ Nop, - /* */ Nop, - /* */ Nop, - /* */ Nop, - /* */ Nop, - /* */ BrTrue(8), - /* L2 */ Branch(8), - /* L3 */ Ret, - ], - &[VariantJumpTable { - // Doesn't matter - head_enum: EnumDefinitionIndex::new(0), - jump_table: JumpTableInner::Full(vec![1, 8, 2, 4]), - }], - ) - }; - - cfg.display(); - assert_eq!(cfg.num_blocks(), 6); - assert_eq!(dbg!(traversal(&cfg)), vec![0, 1, 2, 4, 7, 8]); -} - -#[test] -fn traversal_loops() { - let cfg = { - use Bytecode::*; - VMControlFlowGraph::new( - &[ - /* L0: Outer head */ LdTrue, - /* Outer break */ BrTrue(6), - /* L2: Inner head */ LdTrue, - /* Inner break */ BrTrue(5), - /* L4: Inner continue */ Branch(2), - /* Outer continue */ Branch(0), - /* L6: */ Ret, - ], - &[], - ) - }; - - cfg.display(); - assert_eq!(cfg.num_blocks(), 5); - assert_eq!(traversal(&cfg), vec![0, 2, 4, 5, 6]); -} - -#[test] -fn traversal_loops_with_switch() { - let cfg = { - use Bytecode::*; - VMControlFlowGraph::new( - &[ - /* L0: Outer head */ LdTrue, - /* Outer break */ BrTrue(4), - /* L2: Inner head */ VariantSwitch(VariantJumpTableIndex::new(0)), - /* Outer continue */ Branch(0), - /* L6: */ Ret, - ], - &[VariantJumpTable { - // Doesn't matter - head_enum: EnumDefinitionIndex::new(0), - jump_table: JumpTableInner::Full(vec![ - /* Inner break */ 3, /* Inner continue */ 2, - ]), - }], - ) - }; - - cfg.display(); - assert_eq!(cfg.num_blocks(), 4); - assert_eq!(traversal(&cfg), vec![0, 2, 3, 4]); -} - -#[test] -fn traversal_non_loop_back_branch() { - let cfg = { - use Bytecode::*; - VMControlFlowGraph::new( - &[ - /* L0 */ Branch(2), - /* L1 */ Ret, - /* L2 */ Branch(1), - ], - &[], - ) - }; - - cfg.display(); - assert_eq!(cfg.num_blocks(), 3); - assert_eq!(traversal(&cfg), vec![0, 2, 1]); -} - -#[test] -fn traversal_non_loop_back_branch_variant_switch() { - let cfg = { - use Bytecode::*; - VMControlFlowGraph::new( - &[ - /* L0 */ VariantSwitch(VariantJumpTableIndex::new(0)), - /* L1 */ Ret, - /* L2 */ Branch(1), - ], - &[VariantJumpTable { - // Doesn't matter - head_enum: EnumDefinitionIndex::new(0), - jump_table: JumpTableInner::Full(vec![2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]), - }], - ) - }; - - cfg.display(); - assert_eq!(cfg.num_blocks(), 3); - assert_eq!(traversal(&cfg), vec![0, 2, 1]); -} - -#[test] -fn out_of_order_blocks_variant_switch() { - const PERMUTATION_BOUND: usize = 2000; - - let blocks = (0..=127) - .map(|i| { - ( - i, - vec![ - Bytecode::Pop, // Pop the value from the variant switch - Bytecode::LdU16(i), // Ld the number so we can track what block this is canonically - Bytecode::Pop, // Then pop it - Bytecode::Ret, // Then ret - ], - ) - }) - .collect::>(); - - let block_len = blocks.last().unwrap().1.len() as u16; - - let (canonical_blocks, canonical_traversal) = { - let jump_table = - JumpTableInner::Full(blocks.iter().map(|(i, _)| 1 + *i * block_len).collect()); - let mut start_block = vec![Bytecode::VariantSwitch(VariantJumpTableIndex::new(0))]; - start_block.extend(blocks.clone().into_iter().flat_map(|(_, block)| block)); - - let cfg = VMControlFlowGraph::new( - &start_block, - &[VariantJumpTable { - // Doesn't matter - head_enum: EnumDefinitionIndex::new(0), - jump_table, - }], - ); - - cfg.display(); - (cfg.num_blocks(), traversal(&cfg)) - }; - - assert_eq!(canonical_blocks, 129); - assert_eq!(canonical_traversal.len(), 129); - - for permutation in blocks.into_iter().permutations(128).take(PERMUTATION_BOUND) { - // orig index => new_index - // identity permutation == perm[i] == i; - let mut perm = vec![]; - let mut blocks = vec![Bytecode::VariantSwitch(VariantJumpTableIndex::new(0))]; - for (index, mut block) in permutation.into_iter() { - perm.push(index); - blocks.append(&mut block); - } - - let jump_table = JumpTableInner::Full(perm.iter().map(|i| 1 + *i * block_len).collect()); - - let cfg = VMControlFlowGraph::new( - &blocks, - &[VariantJumpTable { - // Doesn't matter - head_enum: EnumDefinitionIndex::new(0), - jump_table, - }], - ); - assert_eq!( - cfg.num_blocks(), - canonical_blocks, - "num blocks differ: Permutation: {:?}", - perm - ); - assert_eq!( - traversal(&cfg), - canonical_traversal, - "traversal differs: Permutation: {:?}", - perm - ); - } -} - -/// Return a vector containing the `BlockId`s from `cfg` in the order suggested by successively -/// calling `ControlFlowGraph::next_block` starting from the entry block. -fn traversal(cfg: &dyn ControlFlowGraph) -> Vec { - let mut order = Vec::with_capacity(cfg.num_blocks() as usize); - let mut next = Some(cfg.entry_block_id()); - - while let Some(block) = next { - order.push(block); - next = cfg.next_block(block); - } - - order -} diff --git a/external-crates/move/move-execution/v0/crates/move-abstract-interpreter/src/unit_tests/mod.rs b/external-crates/move/move-execution/v0/crates/move-abstract-interpreter/src/unit_tests/mod.rs deleted file mode 100644 index 46e078986ad..00000000000 --- a/external-crates/move/move-execution/v0/crates/move-abstract-interpreter/src/unit_tests/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -mod control_flow_graph_tests; diff --git a/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/Cargo.toml b/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/Cargo.toml deleted file mode 100644 index 66e4d921646..00000000000 --- a/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "move-bytecode-verifier-v0" -version = "0.1.0" -authors = ["IOTA Foundation "] -edition = "2021" -license = "Apache-2.0" -publish = false -description = "Move bytecode verifier" - -[dependencies] -petgraph.workspace = true - -move-abstract-interpreter.workspace = true -move-abstract-stack.workspace = true -move-binary-format.workspace = true -move-borrow-graph.workspace = true -move-bytecode-verifier-meter.workspace = true -move-core-types.workspace = true -move-vm-config.workspace = true - -[features] -default = [] diff --git a/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/README.md b/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/README.md deleted file mode 100644 index f062b48a66f..00000000000 --- a/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/README.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -id: bytecode-verifier -title: Bytecode Verifier -custom_edit_url: https://github.com/move-language/move/edit/main/language/move-bytecode-verifier/README.md ---- - -## Overview - -The bytecode verifier contains a static analysis tool for rejecting invalid Move bytecode. It checks the safety of stack usage, types, resources, and references. - -The body of each function in a compiled module is verified separately while trusting the correctness of function signatures in the module. Checking that each function signature matches its definition is a separate responsibility. The body of a function is a sequence of bytecode instructions. This instruction sequence is checked in several phases described below. - -## CFG Construction - -A control-flow graph is constructed by decomposing the instruction sequence into a collection of basic blocks. Each basic block contains a contiguous sequence of instructions; the set of all instructions is partitioned among the blocks. Each block ends with a branch or return instruction. The decomposition into blocks guarantees that branch targets land only at the beginning of some block. The decomposition also attempts to ensure that the generated blocks are maximal. However, the soundness of the analysis does not depend on maximality. - -## Stack Safety - -The execution of a block happens in the context of a stack and an array of local variables. The parameters of the function are a prefix of the array of local variables. Arguments and return values are passed across function calls via the stack. When a function starts executing, its arguments are already loaded into its parameters. Suppose the stack height is _n_ when a function starts executing; then valid bytecode must enforce the invariant that when execution lands at the beginning of a basic block, the stack height is _n_. Furthermore, at a return instruction, the stack height must be _n_+_k_ where _k_, s.t. _k_>=0 is the number of return values. The first phase of the analysis checks that this invariant is maintained by analyzing each block separately, calculating the effect of each instruction in the block on the stack height, checking that the height does not go below _n_, and that is left either at _n_ or _n_+_k_ (depending on the final instruction of the block and the return type of the function) at the end of the block. - -## Type Safety - -The second phase of the analysis checks that each operation, primitive or defined function, is invoked with arguments of appropriate types. The operands of an operation are values located either in a local variable or on the stack. The types of local variables of a function are already provided in the bytecode. However, the types of stack values are inferred. This inference and the type checking of each operation can be done separately for each block. Since the stack height at the beginning of each block is _n_ and does not go below _n_ during the execution of the block, we only need to model the suffix of the stack starting at _n_ for type checking the block instructions. We model this suffix using a stack of types on which types are pushed and popped as the instruction stream in a block is processed. Only the type stack and the statically-known types of local variables are needed to type check each instruction. - -## Resource Safety - -Resources represent the assets of the blockchain. As such, there are certain restrictions on these types that do not apply to normal values. Intuitively, resource values cannot be copied and must be used by the end of the transaction (this means that they are moved to global storage or destroyed). Concretely, the following restrictions apply: - -- `CopyLoc` and `StLoc` require that the type of local is not of resource kind. -- `WriteRef`, `Eq`, and `Neq` require that the type of the reference is not of resource kind. -- At the end of a function (when `Ret` is reached), no local whose type is of resource kind must be empty, i.e., the value must have been moved out of the local. - -As mentioned above, this last rule around `Ret` implies that the resource _must_ have been either: - -- Moved to global storage via `MoveTo`. -- Destroyed via `Unpack`. - -Both `MoveTo` and `Unpack` are internal to the module in which the resource is declared. - -## Reference Safety - -References are first-class in the bytecode language. Fresh references become available to a function in several ways: - -- Inputting parameters. -- Taking the address of the value in a local variable. -- Taking the address of the globally published value in an address. -- Taking the address of a field from a reference to the containing struct. -- Returning value from a function. - -The goal of reference safety checking is to ensure that there are no dangling references. Here are some examples of dangling references: - -- Local variable `y` contains a reference to the value in a local variable `x`; `x` is then moved. -- Local variable `y` contains a reference to the value in a local variable `x`; `x` is then bound to a new value. -- Reference is taken to a local variable that has not been initialized. -- Reference to a value in a local variable is returned from a function. -- Reference `r` is taken to a globally published value `v`; `v` is then unpublished. - -References can be either exclusive or shared; the latter allow read-only access. A secondary goal of reference safety checking is to ensure that in the execution context of the bytecode program, including the entire evaluation stack and all function frames, if there are two distinct storage locations containing references `r1` and `r2` such that `r2` extends `r1`, then both of the following conditions hold: - -- If `r1` is tagged as exclusive, then it must be inactive, i.e. it is impossible to reach a control location where `r1` is dereferenced or mutated. -- If `r1` is shared, then `r2` is shared. - -The two conditions above establish the property of referential transparency, important for scalable program verification, which looks roughly as follows: consider the piece of code `v1 = *r; S; v2 = *r`, where `S` is an arbitrary computation that does not perform any write through the syntactic reference `r` (and no writes to any `r'` that extends `r`). Then `v1 == v2`. - -### Analysis Setup - -The reference safety analysis is set up as a flow analysis (or abstract interpretation). An abstract state is defined for abstractly executing the code of a basic block. A map is maintained from basic blocks to abstract states. Given an abstract state _S_ at the beginning of a basic block _B_, the abstract execution of _B_ results in state _S'_. This state _S'_ is propagated to all successors of _B_ and recorded in the map. If a state already existed for a block, the freshly propagated state is “joined” with the existing state. If the join fails an error is reported. If the join succeeds but the abstract state remains unchanged, no further propagation is done. Otherwise, the state is updated and propagated again through the block. An error may also be reported when an instruction is processed during the propagation of abstract state through a block. - -**Errors.** As mentioned earlier, an error is reported by the checker in one of the following situations: - -- An instruction cannot be proven to be safe during the propagation of the abstract state through a block. -- Join of abstract states propagated via different incoming edges into a block fails. - -## How is this module organized? - -```text -* -├── invalid-mutations # Library used by proptests -├── src # Core bytecode verifier files -├── tests # Proptests -``` diff --git a/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/src/ability_cache.rs b/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/src/ability_cache.rs deleted file mode 100644 index 9f9a61b9329..00000000000 --- a/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/src/ability_cache.rs +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use move_binary_format::{ - errors::PartialVMResult, - file_format::{AbilitySet, DatatypeHandleIndex, SignatureToken}, - safe_unwrap, CompiledModule, -}; -use move_bytecode_verifier_meter::{Meter, Scope}; -use std::{ - cmp::max, - collections::{btree_map::Entry, BTreeMap}, -}; - -const TYPE_ARG_COST: u128 = 1; - -pub struct AbilityCache<'a> { - module: &'a CompiledModule, - vector_results: BTreeMap, - datatype_results: BTreeMap, AbilitySet>>, -} - -impl<'a> AbilityCache<'a> { - pub fn new(module: &'a CompiledModule) -> Self { - Self { - module, - vector_results: BTreeMap::new(), - datatype_results: BTreeMap::new(), - } - } - - pub fn abilities( - &mut self, - scope: Scope, - meter: &mut (impl Meter + ?Sized), - type_parameter_abilities: &[AbilitySet], - ty: &SignatureToken, - ) -> PartialVMResult { - use SignatureToken as S; - - Ok(match ty { - S::Bool | S::U8 | S::U16 | S::U32 | S::U64 | S::U128 | S::U256 | S::Address => { - AbilitySet::PRIMITIVES - } - - S::Reference(_) | S::MutableReference(_) => AbilitySet::REFERENCES, - S::Signer => AbilitySet::SIGNER, - S::TypeParameter(idx) => *safe_unwrap!(type_parameter_abilities.get(*idx as usize)), - S::Datatype(idx) => { - let sh = self.module.datatype_handle_at(*idx); - sh.abilities - } - S::Vector(inner) => { - let inner_abilities = - self.abilities(scope, meter, type_parameter_abilities, inner)?; - let entry = self.vector_results.entry(inner_abilities); - match entry { - Entry::Occupied(entry) => *entry.get(), - Entry::Vacant(entry) => { - meter.add(scope, TYPE_ARG_COST)?; - let abilities = AbilitySet::polymorphic_abilities( - AbilitySet::VECTOR, - vec![false], - vec![inner_abilities], - )?; - entry.insert(abilities); - abilities - } - } - } - S::DatatypeInstantiation(inst) => { - let (idx, type_args) = &**inst; - let type_arg_abilities = type_args - .iter() - .map(|arg| self.abilities(scope, meter, type_parameter_abilities, arg)) - .collect::>>()?; - let entry = self - .datatype_results - .entry(*idx) - .or_default() - .entry(type_arg_abilities.clone()); - match entry { - Entry::Occupied(entry) => *entry.get(), - Entry::Vacant(entry) => { - meter.add_items(scope, TYPE_ARG_COST, max(type_args.len(), 1))?; - let sh = self.module.datatype_handle_at(*idx); - let declared_abilities = sh.abilities; - let abilities = AbilitySet::polymorphic_abilities( - declared_abilities, - sh.type_parameters.iter().map(|param| param.is_phantom), - type_arg_abilities, - )?; - entry.insert(abilities); - abilities - } - } - } - }) - } -} diff --git a/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/src/ability_field_requirements.rs b/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/src/ability_field_requirements.rs deleted file mode 100644 index a7dd938c6eb..00000000000 --- a/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/src/ability_field_requirements.rs +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -//! This module implements a checker for verifying that all of the struct's -//! fields satisfy the abilities required by the struct's abilities -use move_binary_format::{ - errors::{verification_error, Location, PartialVMResult, VMResult}, - file_format::{AbilitySet, CompiledModule, StructFieldInformation, TableIndex}, - IndexKind, -}; -use move_bytecode_verifier_meter::{Meter, Scope}; -use move_core_types::vm_status::StatusCode; - -use crate::ability_cache::AbilityCache; - -pub fn verify_module<'env>( - module: &'env CompiledModule, - ability_cache: &mut AbilityCache<'env>, - meter: &mut (impl Meter + ?Sized), -) -> VMResult<()> { - verify_module_impl(module, ability_cache, meter) - .map_err(|e| e.finish(Location::Module(module.self_id()))) -} - -fn verify_module_impl<'env>( - module: &'env CompiledModule, - ability_cache: &mut AbilityCache<'env>, - meter: &mut (impl Meter + ?Sized), -) -> PartialVMResult<()> { - for (idx, struct_def) in module.struct_defs().iter().enumerate() { - let sh = module.datatype_handle_at(struct_def.struct_handle); - let fields = match &struct_def.field_information { - StructFieldInformation::Native => continue, - StructFieldInformation::Declared(fields) => fields, - }; - let required_abilities = sh - .abilities - .into_iter() - .map(|a| a.requires()) - .fold(AbilitySet::EMPTY, |acc, required| acc | required); - // Assume type parameters have all abilities, as the struct's abilities will be - // dependent on them - let type_parameter_abilities = sh - .type_parameters - .iter() - .map(|_| AbilitySet::ALL) - .collect::>(); - for field in fields { - let field_abilities = ability_cache.abilities( - Scope::Module, - meter, - &type_parameter_abilities, - &field.signature.0, - )?; - if !required_abilities.is_subset(field_abilities) { - return Err(verification_error( - StatusCode::FIELD_MISSING_TYPE_ABILITY, - IndexKind::StructDefinition, - idx as TableIndex, - )); - } - } - } - - for (idx, enum_def) in module.enum_defs().iter().enumerate() { - let sh = module.datatype_handle_at(enum_def.enum_handle); - let required_abilities = sh - .abilities - .into_iter() - .map(|a| a.requires()) - .fold(AbilitySet::EMPTY, |acc, required| acc | required); - // Assume type parameters have all abilities, as the enum's abilities will be - // dependent on them - let type_parameter_abilities = sh - .type_parameters - .iter() - .map(|_| AbilitySet::ALL) - .collect::>(); - for (i, variant) in enum_def.variants.iter().enumerate() { - for (fi, field) in variant.fields.iter().enumerate() { - let field_abilities = ability_cache.abilities( - Scope::Module, - meter, - &type_parameter_abilities, - &field.signature.0, - )?; - if !required_abilities.is_subset(field_abilities) { - return Err(verification_error( - StatusCode::FIELD_MISSING_TYPE_ABILITY, - IndexKind::EnumDefinition, - idx as TableIndex, - ) - .at_index(IndexKind::VariantTag, i as TableIndex) - .at_index(IndexKind::FieldDefinition, fi as TableIndex)); - } - } - } - } - Ok(()) -} diff --git a/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/src/acquires_list_verifier.rs b/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/src/acquires_list_verifier.rs deleted file mode 100644 index 9c94d58cd8a..00000000000 --- a/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/src/acquires_list_verifier.rs +++ /dev/null @@ -1,235 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -//! This module implements a checker for verifying properties about the acquires list on function -//! definitions. Function definitions must annotate the global resources (declared in that module) -//! accesssed by `BorrowGlobal`, `MoveFrom`, and any transitive function calls -//! The list of acquired resources (stored in `FunctionDefinition`'s `acquires_global_resources` -//! field) must have: -//! - No duplicate resources (checked by `check_duplication`) -//! - No missing resources (any resource acquired must be present) -//! - No additional resources (no extraneous resources not actually acquired) - -use std::collections::{BTreeSet, HashMap}; - -use move_binary_format::{ - errors::{PartialVMError, PartialVMResult}, - file_format::{ - Bytecode, CodeOffset, CompiledModule, FunctionDefinition, FunctionDefinitionIndex, - FunctionHandle, FunctionHandleIndex, StructDefinitionIndex, - }, - safe_unwrap, -}; -use move_bytecode_verifier_meter::Meter; -use move_core_types::vm_status::StatusCode; - -pub(crate) struct AcquiresVerifier<'a> { - module: &'a CompiledModule, - current_function: FunctionDefinitionIndex, - annotated_acquires: BTreeSet, - actual_acquires: BTreeSet, - handle_to_def: HashMap, -} - -impl<'a> AcquiresVerifier<'a> { - pub(crate) fn verify( - module: &'a CompiledModule, - index: FunctionDefinitionIndex, - function_definition: &'a FunctionDefinition, - _meter: &mut (impl Meter + ?Sized), // currently unused - ) -> PartialVMResult<()> { - let annotated_acquires: BTreeSet<_> = function_definition - .acquires_global_resources - .iter() - .cloned() - .collect(); - let mut handle_to_def = HashMap::new(); - for func_def in module.function_defs() { - handle_to_def.insert(func_def.function, func_def); - } - let mut verifier = Self { - module, - current_function: index, - annotated_acquires, - actual_acquires: BTreeSet::new(), - handle_to_def, - }; - - for (offset, instruction) in safe_unwrap!(function_definition.code.as_ref()) - .code - .iter() - .enumerate() - { - verifier.verify_instruction(instruction, offset as CodeOffset)? - } - - for annotation in verifier.annotated_acquires { - if !verifier.actual_acquires.contains(&annotation) { - return Err(PartialVMError::new( - StatusCode::EXTRANEOUS_ACQUIRES_ANNOTATION, - )); - } - - let struct_def = safe_unwrap!(module.struct_defs().get(annotation.0 as usize)); - let struct_handle = module.datatype_handle_at(struct_def.struct_handle); - if !struct_handle.abilities.has_key() { - return Err(PartialVMError::new(StatusCode::INVALID_ACQUIRES_ANNOTATION)); - } - } - - Ok(()) - } - - fn verify_instruction( - &mut self, - instruction: &Bytecode, - offset: CodeOffset, - ) -> PartialVMResult<()> { - match instruction { - Bytecode::Call(idx) => self.call_acquire(*idx, offset), - Bytecode::CallGeneric(idx) => { - let fi = self.module.function_instantiation_at(*idx); - self.call_acquire(fi.handle, offset) - } - Bytecode::MoveFromDeprecated(idx) - | Bytecode::MutBorrowGlobalDeprecated(idx) - | Bytecode::ImmBorrowGlobalDeprecated(idx) => self.struct_acquire(*idx, offset), - Bytecode::MoveFromGenericDeprecated(idx) - | Bytecode::MutBorrowGlobalGenericDeprecated(idx) - | Bytecode::ImmBorrowGlobalGenericDeprecated(idx) => { - let si = self.module.struct_instantiation_at(*idx); - self.struct_acquire(si.def, offset) - } - - Bytecode::Pop - | Bytecode::BrTrue(_) - | Bytecode::BrFalse(_) - | Bytecode::Abort - | Bytecode::Branch(_) - | Bytecode::Nop - | Bytecode::Ret - | Bytecode::StLoc(_) - | Bytecode::MoveLoc(_) - | Bytecode::CopyLoc(_) - | Bytecode::ImmBorrowLoc(_) - | Bytecode::MutBorrowLoc(_) - | Bytecode::FreezeRef - | Bytecode::MutBorrowField(_) - | Bytecode::MutBorrowFieldGeneric(_) - | Bytecode::ImmBorrowField(_) - | Bytecode::ImmBorrowFieldGeneric(_) - | Bytecode::LdU8(_) - | Bytecode::LdU16(_) - | Bytecode::LdU32(_) - | Bytecode::LdU64(_) - | Bytecode::LdU128(_) - | Bytecode::LdU256(_) - | Bytecode::LdConst(_) - | Bytecode::LdTrue - | Bytecode::LdFalse - | Bytecode::Pack(_) - | Bytecode::PackGeneric(_) - | Bytecode::Unpack(_) - | Bytecode::UnpackGeneric(_) - | Bytecode::ReadRef - | Bytecode::WriteRef - | Bytecode::CastU8 - | Bytecode::CastU16 - | Bytecode::CastU32 - | Bytecode::CastU64 - | Bytecode::CastU128 - | Bytecode::CastU256 - | Bytecode::Add - | Bytecode::Sub - | Bytecode::Mul - | Bytecode::Mod - | Bytecode::Div - | Bytecode::BitOr - | Bytecode::BitAnd - | Bytecode::Xor - | Bytecode::Shl - | Bytecode::Shr - | Bytecode::Or - | Bytecode::And - | Bytecode::Not - | Bytecode::Eq - | Bytecode::Neq - | Bytecode::Lt - | Bytecode::Gt - | Bytecode::Le - | Bytecode::Ge - | Bytecode::ExistsDeprecated(_) - | Bytecode::ExistsGenericDeprecated(_) - | Bytecode::MoveToDeprecated(_) - | Bytecode::MoveToGenericDeprecated(_) - | Bytecode::VecPack(..) - | Bytecode::VecLen(_) - | Bytecode::VecImmBorrow(_) - | Bytecode::VecMutBorrow(_) - | Bytecode::VecPushBack(_) - | Bytecode::VecPopBack(_) - | Bytecode::VecUnpack(..) - | Bytecode::VecSwap(_) - | Bytecode::PackVariant(_) - | Bytecode::PackVariantGeneric(_) - | Bytecode::UnpackVariant(_) - | Bytecode::UnpackVariantImmRef(_) - | Bytecode::UnpackVariantMutRef(_) - | Bytecode::UnpackVariantGeneric(_) - | Bytecode::UnpackVariantGenericImmRef(_) - | Bytecode::UnpackVariantGenericMutRef(_) - | Bytecode::VariantSwitch(_) => Ok(()), - } - } - - fn call_acquire( - &mut self, - fh_idx: FunctionHandleIndex, - offset: CodeOffset, - ) -> PartialVMResult<()> { - let function_handle = self.module.function_handle_at(fh_idx); - let mut function_acquired_resources = - self.function_acquired_resources(function_handle, fh_idx); - for acquired_resource in &function_acquired_resources { - if !self.annotated_acquires.contains(acquired_resource) { - return Err(self.error(StatusCode::MISSING_ACQUIRES_ANNOTATION, offset)); - } - } - self.actual_acquires - .append(&mut function_acquired_resources); - Ok(()) - } - - fn struct_acquire( - &mut self, - sd_idx: StructDefinitionIndex, - offset: CodeOffset, - ) -> PartialVMResult<()> { - if self.annotated_acquires.contains(&sd_idx) { - self.actual_acquires.insert(sd_idx); - Ok(()) - } else { - Err(self.error(StatusCode::MISSING_ACQUIRES_ANNOTATION, offset)) - } - } - - fn function_acquired_resources( - &self, - function_handle: &FunctionHandle, - fh_idx: FunctionHandleIndex, - ) -> BTreeSet { - if function_handle.module != self.module.self_handle_idx() { - return BTreeSet::new(); - } - match self.handle_to_def.get(&fh_idx) { - Some(func_def) => func_def.acquires_global_resources.iter().cloned().collect(), - None => BTreeSet::new(), - } - } - - fn error(&self, status: StatusCode, offset: CodeOffset) -> PartialVMError { - PartialVMError::new(status).at_code_offset(self.current_function, offset) - } -} diff --git a/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/src/check_duplication.rs b/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/src/check_duplication.rs deleted file mode 100644 index cf320d91782..00000000000 --- a/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/src/check_duplication.rs +++ /dev/null @@ -1,417 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -//! This module implements a checker for verifying that each vector in a -//! CompiledModule contains distinct values. Successful verification implies -//! that an index in vector can be used to uniquely name the entry at that -//! index. Additionally, the checker also verifies the following: -//! - struct and field definitions are consistent -//! - the handles in struct and function definitions point to the self module -//! index -//! - all struct and function handles pointing to the self module index have a -//! definition -use std::{collections::HashSet, hash::Hash}; - -use move_binary_format::{ - errors::{verification_error, Location, PartialVMResult, VMResult}, - file_format::{ - CompiledModule, Constant, DatatypeHandle, DatatypeHandleIndex, FunctionHandle, - FunctionHandleIndex, FunctionInstantiation, ModuleHandle, Signature, - StructFieldInformation, TableIndex, VariantHandle, - }, - IndexKind, -}; -use move_core_types::{ - account_address::AccountAddress, identifier::Identifier, vm_status::StatusCode, -}; - -pub struct DuplicationChecker<'a> { - module: &'a CompiledModule, -} - -impl<'a> DuplicationChecker<'a> { - pub fn verify_module(module: &'a CompiledModule) -> VMResult<()> { - Self::verify_module_impl(module).map_err(|e| e.finish(Location::Module(module.self_id()))) - } - - fn verify_module_impl(module: &'a CompiledModule) -> PartialVMResult<()> { - Self::check_identifiers(module.identifiers())?; - Self::check_address_identifiers(module.address_identifiers())?; - Self::check_constants(module.constant_pool())?; - Self::check_signatures(module.signatures())?; - Self::check_module_handles(module.module_handles())?; - Self::check_module_handles(module.friend_decls())?; - Self::check_datatype_handles(module.datatype_handles())?; - Self::check_function_handles(module.function_handles())?; - Self::check_function_instantiations(module.function_instantiations())?; - Self::check_variant_handles(module.variant_handles())?; - - let checker = Self { module }; - checker.check_field_handles()?; - checker.check_field_instantiations()?; - checker.check_function_definitions()?; - checker.check_struct_definitions()?; - checker.check_struct_instantiations()?; - checker.check_enum_definitions()?; - checker.check_enum_instantiations()?; - checker.check_datatype_handles_implemented() - } - - fn check_identifiers(identifiers: &[Identifier]) -> PartialVMResult<()> { - match Self::first_duplicate_element(identifiers) { - Some(idx) => Err(verification_error( - StatusCode::DUPLICATE_ELEMENT, - IndexKind::Identifier, - idx, - )), - None => Ok(()), - } - } - - fn check_address_identifiers(address_identifiers: &[AccountAddress]) -> PartialVMResult<()> { - match Self::first_duplicate_element(address_identifiers) { - Some(idx) => Err(verification_error( - StatusCode::DUPLICATE_ELEMENT, - IndexKind::AddressIdentifier, - idx, - )), - None => Ok(()), - } - } - - fn check_constants(constant_pool: &[Constant]) -> PartialVMResult<()> { - match Self::first_duplicate_element(constant_pool) { - Some(idx) => Err(verification_error( - StatusCode::DUPLICATE_ELEMENT, - IndexKind::ConstantPool, - idx, - )), - None => Ok(()), - } - } - - fn check_signatures(signatures: &[Signature]) -> PartialVMResult<()> { - match Self::first_duplicate_element(signatures) { - Some(idx) => Err(verification_error( - StatusCode::DUPLICATE_ELEMENT, - IndexKind::Signature, - idx, - )), - None => Ok(()), - } - } - - fn check_module_handles(module_handles: &[ModuleHandle]) -> PartialVMResult<()> { - match Self::first_duplicate_element(module_handles) { - Some(idx) => Err(verification_error( - StatusCode::DUPLICATE_ELEMENT, - IndexKind::ModuleHandle, - idx, - )), - None => Ok(()), - } - } - - // DatatypeHandles - module and name define uniqueness - fn check_datatype_handles(datatype_handles: &[DatatypeHandle]) -> PartialVMResult<()> { - match Self::first_duplicate_element(datatype_handles.iter().map(|x| (x.module, x.name))) { - Some(idx) => Err(verification_error( - StatusCode::DUPLICATE_ELEMENT, - IndexKind::DatatypeHandle, - idx, - )), - None => Ok(()), - } - } - - fn check_variant_handles(variant_handles: &[VariantHandle]) -> PartialVMResult<()> { - match Self::first_duplicate_element(variant_handles.iter().map(|x| (x.enum_def, x.variant))) - { - Some(idx) => Err(verification_error( - StatusCode::DUPLICATE_ELEMENT, - IndexKind::VariantHandle, - idx, - )), - None => Ok(()), - } - } - - fn check_function_instantiations( - function_instantiations: &[FunctionInstantiation], - ) -> PartialVMResult<()> { - match Self::first_duplicate_element(function_instantiations) { - Some(idx) => Err(verification_error( - StatusCode::DUPLICATE_ELEMENT, - IndexKind::FunctionInstantiation, - idx, - )), - None => Ok(()), - } - } - - // FunctionHandles - module and name define uniqueness - fn check_function_handles(function_handles: &[FunctionHandle]) -> PartialVMResult<()> { - match Self::first_duplicate_element(function_handles.iter().map(|x| (x.module, x.name))) { - Some(idx) => Err(verification_error( - StatusCode::DUPLICATE_ELEMENT, - IndexKind::FunctionHandle, - idx, - )), - None => Ok(()), - } - } - - // Module only code - // - - fn check_field_handles(&self) -> PartialVMResult<()> { - match Self::first_duplicate_element(self.module.field_handles()) { - Some(idx) => Err(verification_error( - StatusCode::DUPLICATE_ELEMENT, - IndexKind::FieldHandle, - idx, - )), - None => Ok(()), - } - } - - fn check_struct_instantiations(&self) -> PartialVMResult<()> { - match Self::first_duplicate_element(self.module.struct_instantiations()) { - Some(idx) => Err(verification_error( - StatusCode::DUPLICATE_ELEMENT, - IndexKind::StructDefInstantiation, - idx, - )), - None => Ok(()), - } - } - - fn check_enum_instantiations(&self) -> PartialVMResult<()> { - match Self::first_duplicate_element(self.module.enum_instantiations()) { - Some(idx) => Err(verification_error( - StatusCode::DUPLICATE_ELEMENT, - IndexKind::EnumDefInstantiation, - idx, - )), - None => Ok(()), - } - } - - fn check_field_instantiations(&self) -> PartialVMResult<()> { - if let Some(idx) = Self::first_duplicate_element(self.module.field_instantiations()) { - return Err(verification_error( - StatusCode::DUPLICATE_ELEMENT, - IndexKind::FieldInstantiation, - idx, - )); - } - Ok(()) - } - - fn check_struct_definitions(&self) -> PartialVMResult<()> { - // StructDefinition - contained DatatypeHandle defines uniqueness - if let Some(idx) = - Self::first_duplicate_element(self.module.struct_defs().iter().map(|x| x.struct_handle)) - { - return Err(verification_error( - StatusCode::DUPLICATE_ELEMENT, - IndexKind::StructDefinition, - idx, - )); - } - // Field names in structs must be unique - for (struct_idx, struct_def) in self.module.struct_defs().iter().enumerate() { - let fields = match &struct_def.field_information { - StructFieldInformation::Native => continue, - StructFieldInformation::Declared(fields) => fields, - }; - if fields.is_empty() { - return Err(verification_error( - StatusCode::ZERO_SIZED_STRUCT, - IndexKind::StructDefinition, - struct_idx as TableIndex, - )); - } - if let Some(idx) = Self::first_duplicate_element(fields.iter().map(|x| x.name)) { - return Err(verification_error( - StatusCode::DUPLICATE_ELEMENT, - IndexKind::FieldDefinition, - idx, - )); - } - } - // Check that each struct definition is pointing to the self module - if let Some(idx) = self.module.struct_defs().iter().position(|x| { - self.module.datatype_handle_at(x.struct_handle).module != self.module.self_handle_idx() - }) { - return Err(verification_error( - StatusCode::INVALID_MODULE_HANDLE, - IndexKind::StructDefinition, - idx as TableIndex, - )); - } - Ok(()) - } - - fn check_datatype_handles_implemented(&self) -> PartialVMResult<()> { - let implemented_datatype_handles: HashSet = self - .module - .struct_defs() - .iter() - .map(|x| x.struct_handle) - .chain(self.module.enum_defs().iter().map(|x| x.enum_handle)) - .collect(); - if let Some(idx) = (0..self.module.datatype_handles().len()).position(|x| { - let y = DatatypeHandleIndex::new(x as u16); - self.module.datatype_handle_at(y).module == self.module.self_handle_idx() - && !implemented_datatype_handles.contains(&y) - }) { - return Err(verification_error( - StatusCode::UNIMPLEMENTED_HANDLE, - IndexKind::DatatypeHandle, - idx as TableIndex, - )); - } - Ok(()) - } - - fn check_enum_definitions(&self) -> PartialVMResult<()> { - // EnumDefinition - contained DatatypeHandle defines uniqueness - // NB: We check uniqueness across both enum and struct handles at this point to - // make sure data definitions are not duplicated across struct and - // enums. - if let Some(idx) = Self::first_duplicate_element( - self.module - .struct_defs() - .iter() - .map(|x| x.struct_handle) - .chain(self.module.enum_defs().iter().map(|x| x.enum_handle)), - ) { - return Err(verification_error( - StatusCode::DUPLICATE_ELEMENT, - IndexKind::EnumDefinition, - idx, - )); - } - // Variant names in enums must be unique - // Field names in each variant must be unique - for (enum_idx, enum_def) in self.module.enum_defs().iter().enumerate() { - let variants = &enum_def.variants; - if variants.is_empty() { - return Err(verification_error( - StatusCode::ZERO_SIZED_ENUM, - IndexKind::EnumDefinition, - enum_idx as TableIndex, - )); - } - if let Some(idx) = - Self::first_duplicate_element(variants.iter().map(|x| x.variant_name)) - { - return Err(verification_error( - StatusCode::DUPLICATE_ELEMENT, - IndexKind::EnumDefinition, - enum_idx as TableIndex, - ) - .at_index(IndexKind::VariantTag, idx as TableIndex)); - } - - // NB: we allow zero-sized variants: since we require non-empty enums we always - // have a tag and therefore a variant with no fields is still - // non-zero sized whereas a struct with zero fields is zero-sized. - for (tag, variant) in variants.iter().enumerate() { - if let Some(idx) = - Self::first_duplicate_element(variant.fields.iter().map(|x| x.name)) - { - return Err(verification_error( - StatusCode::DUPLICATE_ELEMENT, - IndexKind::FieldDefinition, - idx, - ) - .at_index(IndexKind::VariantTag, tag as TableIndex) - .at_index(IndexKind::EnumDefinition, enum_idx as TableIndex)); - } - } - } - // Check that each enum definition is pointing to the self module - if let Some(idx) = self.module.enum_defs().iter().position(|x| { - self.module.datatype_handle_at(x.enum_handle).module != self.module.self_handle_idx() - }) { - return Err(verification_error( - StatusCode::INVALID_MODULE_HANDLE, - IndexKind::EnumDefinition, - idx as TableIndex, - )); - } - Ok(()) - } - - fn check_function_definitions(&self) -> PartialVMResult<()> { - // FunctionDefinition - contained FunctionHandle defines uniqueness - if let Some(idx) = - Self::first_duplicate_element(self.module.function_defs().iter().map(|x| x.function)) - { - return Err(verification_error( - StatusCode::DUPLICATE_ELEMENT, - IndexKind::FunctionDefinition, - idx, - )); - } - // Acquires in function declarations contain unique struct definitions - for (idx, function_def) in self.module.function_defs().iter().enumerate() { - let acquires = function_def.acquires_global_resources.iter(); - if Self::first_duplicate_element(acquires).is_some() { - return Err(verification_error( - StatusCode::DUPLICATE_ACQUIRES_ANNOTATION, - IndexKind::FunctionDefinition, - idx as TableIndex, - )); - } - } - // Check that each function definition is pointing to the self module - if let Some(idx) = self.module.function_defs().iter().position(|x| { - self.module.function_handle_at(x.function).module != self.module.self_handle_idx() - }) { - return Err(verification_error( - StatusCode::INVALID_MODULE_HANDLE, - IndexKind::FunctionDefinition, - idx as TableIndex, - )); - } - // Check that each function handle in self module is implemented (has a - // declaration) - let implemented_function_handles: HashSet = self - .module - .function_defs() - .iter() - .map(|x| x.function) - .collect(); - if let Some(idx) = (0..self.module.function_handles().len()).position(|x| { - let y = FunctionHandleIndex::new(x as u16); - self.module.function_handle_at(y).module == self.module.self_handle_idx() - && !implemented_function_handles.contains(&y) - }) { - return Err(verification_error( - StatusCode::UNIMPLEMENTED_HANDLE, - IndexKind::FunctionHandle, - idx as TableIndex, - )); - } - Ok(()) - } - - fn first_duplicate_element(iter: T) -> Option - where - T: IntoIterator, - T::Item: Eq + Hash, - { - let mut uniq = HashSet::new(); - for (i, x) in iter.into_iter().enumerate() { - if !uniq.insert(x) { - return Some(i as TableIndex); - } - } - None - } -} diff --git a/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/src/code_unit_verifier.rs b/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/src/code_unit_verifier.rs deleted file mode 100644 index 8e4a1eebe54..00000000000 --- a/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/src/code_unit_verifier.rs +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -//! This module implements the checker for verifying correctness of function bodies. -//! The overall verification is split between stack_usage_verifier.rs and -//! abstract_interpreter.rs. CodeUnitVerifier simply orchestrates calls into these two files. -use crate::{ - ability_cache::AbilityCache, acquires_list_verifier::AcquiresVerifier, control_flow, - locals_safety, reference_safety, stack_usage_verifier::StackUsageVerifier, type_safety, -}; -use move_abstract_interpreter::{absint::FunctionContext, control_flow_graph::ControlFlowGraph}; -use move_binary_format::{ - errors::{Location, PartialVMError, PartialVMResult, VMResult}, - file_format::{ - CompiledModule, FunctionDefinition, FunctionDefinitionIndex, IdentifierIndex, TableIndex, - }, - IndexKind, -}; -use move_bytecode_verifier_meter::{Meter, Scope}; -use move_core_types::vm_status::StatusCode; -use move_vm_config::verifier::VerifierConfig; -use std::collections::HashMap; - -pub struct CodeUnitVerifier<'env, 'a> { - module: &'env CompiledModule, - function_context: FunctionContext<'env>, - name_def_map: &'a HashMap, -} - -pub fn verify_module<'env>( - verifier_config: &VerifierConfig, - module: &'env CompiledModule, - ability_cache: &mut AbilityCache<'env>, - meter: &mut (impl Meter + ?Sized), -) -> VMResult<()> { - verify_module_impl(verifier_config, module, ability_cache, meter) - .map_err(|e| e.finish(Location::Module(module.self_id()))) -} - -fn verify_module_impl<'env>( - verifier_config: &VerifierConfig, - module: &'env CompiledModule, - ability_cache: &mut AbilityCache<'env>, - meter: &mut (impl Meter + ?Sized), -) -> PartialVMResult<()> { - let mut name_def_map = HashMap::new(); - for (idx, func_def) in module.function_defs().iter().enumerate() { - let fh = module.function_handle_at(func_def.function); - name_def_map.insert(fh.name, FunctionDefinitionIndex(idx as u16)); - } - let mut total_back_edges = 0; - for (idx, function_definition) in module.function_defs().iter().enumerate() { - let index = FunctionDefinitionIndex(idx as TableIndex); - let num_back_edges = verify_function( - verifier_config, - index, - function_definition, - module, - ability_cache, - &name_def_map, - meter, - ) - .map_err(|err| err.at_index(IndexKind::FunctionDefinition, index.0))?; - total_back_edges += num_back_edges; - } - if let Some(limit) = verifier_config.max_back_edges_per_module { - if total_back_edges > limit { - return Err(PartialVMError::new(StatusCode::TOO_MANY_BACK_EDGES)); - } - } - Ok(()) -} - -fn verify_function<'env>( - verifier_config: &VerifierConfig, - index: FunctionDefinitionIndex, - function_definition: &'env FunctionDefinition, - module: &'env CompiledModule, - ability_cache: &mut AbilityCache<'env>, - name_def_map: &HashMap, - meter: &mut (impl Meter + ?Sized), -) -> PartialVMResult { - meter.enter_scope( - module - .identifier_at(module.function_handle_at(function_definition.function).name) - .as_str(), - Scope::Function, - ); - // nothing to verify for native function - let code = match &function_definition.code { - Some(code) => code, - None => return Ok(0), - }; - - // create `FunctionContext` and `BinaryIndexedView` - let function_context = control_flow::verify_function( - verifier_config, - module, - index, - function_definition, - code, - meter, - )?; - - if let Some(limit) = verifier_config.max_basic_blocks { - if function_context.cfg().blocks().len() > limit { - return Err( - PartialVMError::new(StatusCode::TOO_MANY_BASIC_BLOCKS).at_code_offset(index, 0) - ); - } - } - - let num_back_edges = function_context.cfg().num_back_edges(); - if let Some(limit) = verifier_config.max_back_edges_per_function { - if num_back_edges > limit { - return Err( - PartialVMError::new(StatusCode::TOO_MANY_BACK_EDGES).at_code_offset(index, 0) - ); - } - } - - // verify - let code_unit_verifier = CodeUnitVerifier { - module, - function_context, - name_def_map, - }; - code_unit_verifier.verify_common(verifier_config, ability_cache, meter)?; - AcquiresVerifier::verify(module, index, function_definition, meter)?; - - meter.transfer(Scope::Function, Scope::Module, 1.0)?; - - Ok(num_back_edges) -} - -impl<'env, 'a> CodeUnitVerifier<'env, 'a> { - fn verify_common( - &self, - verifier_config: &VerifierConfig, - ability_cache: &mut AbilityCache<'env>, - meter: &mut (impl Meter + ?Sized), - ) -> PartialVMResult<()> { - StackUsageVerifier::verify(verifier_config, self.module, &self.function_context, meter)?; - type_safety::verify(self.module, &self.function_context, ability_cache, meter)?; - locals_safety::verify(self.module, &self.function_context, ability_cache, meter)?; - reference_safety::verify( - self.module, - &self.function_context, - self.name_def_map, - meter, - ) - } -} diff --git a/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/src/constants.rs b/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/src/constants.rs deleted file mode 100644 index fe14ea9eb3f..00000000000 --- a/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/src/constants.rs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -//! This module implements a checker for verifying that -//! - a constant's type only refers to primitive types -//! - a constant's data serializes correctly for that type -use move_binary_format::{ - errors::{verification_error, Location, PartialVMResult, VMResult}, - file_format::{CompiledModule, Constant, SignatureToken, TableIndex}, - IndexKind, -}; -use move_core_types::vm_status::StatusCode; - -pub fn verify_module(module: &CompiledModule) -> VMResult<()> { - verify_module_impl(module).map_err(|e| e.finish(Location::Module(module.self_id()))) -} - -fn verify_module_impl(module: &CompiledModule) -> PartialVMResult<()> { - for (idx, constant) in module.constant_pool().iter().enumerate() { - verify_constant(idx, constant)? - } - Ok(()) -} - -fn verify_constant(idx: usize, constant: &Constant) -> PartialVMResult<()> { - verify_constant_type(idx, &constant.type_)?; - verify_constant_data(idx, constant) -} - -fn verify_constant_type(idx: usize, type_: &SignatureToken) -> PartialVMResult<()> { - if type_.is_valid_for_constant() { - Ok(()) - } else { - Err(verification_error( - StatusCode::INVALID_CONSTANT_TYPE, - IndexKind::ConstantPool, - idx as TableIndex, - )) - } -} - -fn verify_constant_data(idx: usize, constant: &Constant) -> PartialVMResult<()> { - match constant.deserialize_constant() { - Some(_) => Ok(()), - None => Err(verification_error( - StatusCode::MALFORMED_CONSTANT_DATA, - IndexKind::ConstantPool, - idx as TableIndex, - )), - } -} diff --git a/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/src/control_flow.rs b/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/src/control_flow.rs deleted file mode 100644 index e66039afd94..00000000000 --- a/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/src/control_flow.rs +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -//! This module implements control flow checks. -//! -//! For bytecode versions 6 and up, the following properties are ensured: -//! - The CFG is not empty and the last block ends in an unconditional jump, so -//! it's not possible to fall off the end of a function. -//! - The CFG is reducible (and optionally max loop depth is bounded), to limit -//! the potential for pathologically long abstract interpretation runtimes -//! (through poor choice of loop heads and back edges). -//! -//! For bytecode versions 5 and below, delegates to `control_flow_v5`. -use crate::{ - control_flow_v5, - loop_summary::{LoopPartition, LoopSummary}, -}; -use move_abstract_interpreter::absint::FunctionContext; -use move_binary_format::{ - errors::{PartialVMError, PartialVMResult}, - file_format::{CodeOffset, CodeUnit, FunctionDefinition, FunctionDefinitionIndex}, - CompiledModule, -}; -use move_bytecode_verifier_meter::Meter; -use move_core_types::vm_status::StatusCode; -use move_vm_config::verifier::VerifierConfig; -use std::collections::BTreeSet; - -/// Perform control flow verification on the compiled function, returning its -/// `FunctionContext` if verification was successful. -pub fn verify_function<'env>( - verifier_config: &VerifierConfig, - module: &'env CompiledModule, - index: FunctionDefinitionIndex, - function_definition: &'env FunctionDefinition, - code: &'env CodeUnit, - _meter: &mut (impl Meter + ?Sized), // TODO: metering -) -> PartialVMResult> { - let function_handle = module.function_handle_at(function_definition.function); - - if module.version() <= 5 { - control_flow_v5::verify(verifier_config, Some(index), code)?; - Ok(FunctionContext::new(module, index, code, function_handle)) - } else { - verify_fallthrough(Some(index), code)?; - let function_context = FunctionContext::new(module, index, code, function_handle); - verify_reducibility(verifier_config, &function_context)?; - Ok(function_context) - } -} - -/// Check to make sure that the bytecode vector is non-empty and ends with a -/// branching instruction. -fn verify_fallthrough( - current_function_opt: Option, - code: &CodeUnit, -) -> PartialVMResult<()> { - let current_function = current_function_opt.unwrap_or(FunctionDefinitionIndex(0)); - match code.code.last() { - None => Err(PartialVMError::new(StatusCode::EMPTY_CODE_UNIT)), - Some(last) if !last.is_unconditional_branch() => { - Err(PartialVMError::new(StatusCode::INVALID_FALL_THROUGH) - .at_code_offset(current_function, (code.code.len() - 1) as CodeOffset)) - } - Some(_) => Ok(()), - } -} - -/// Test that `function_context`'s control-flow graph is reducible using -/// Tarjan's algorithm [1]. Optionally test loop depth bounded by -/// `verifier_config.max_loop_depth`. -/// -/// A CFG, `G`, with starting block `s` is reducible if and only if [2] any of -/// the following equivalent properties hold: -/// -/// 1. G has a unique set of back-edges `u -> v` where `v` dominates `u`, that -/// corresponds to the set of back-edges for any depth-first spanning tree -/// of G. -/// -/// 2. Every loop in G contains a unique node `h` (the "head") which dominates -/// all other nodes in the loop. -/// -/// 3. G has a unique maximal (in terms of number of edges) acyclic sub-graph. -/// -/// 4. G can be reduced to a CFG containing just `s` through a sequence of the -/// following two operations: a. Delete a cyclic edge `v -> v` b. For an -/// edge `e: u -> v` where `e` is the only incident edge to `v`, collapse -/// `v` into `u` by deleting `e` and `v` and replacing all `v -> w` edges -/// with `u -> w` edges. -/// -/// Reducibility means that a control-flow graph can be decomposed into a series -/// of nested loops (strongly connected subgraphs), which leads to more -/// predictable abstract interpretation performance. -/// -/// ## References -/// -/// 1. Tarjan, R. 1974. Testing Flow Graph Reducibility. -/// 2. Hecht, M. S., Ullman J. D. 1974. Characterizations of Reducible Flow -/// Graphs. -fn verify_reducibility<'a>( - verifier_config: &VerifierConfig, - function_context: &'a FunctionContext<'a>, -) -> PartialVMResult<()> { - let current_function = function_context - .index() - .unwrap_or(FunctionDefinitionIndex(0)); - let err = move |code: StatusCode, offset: CodeOffset| { - Err(PartialVMError::new(code).at_code_offset(current_function, offset)) - }; - - let summary = LoopSummary::new(function_context.cfg()); - let mut partition = LoopPartition::new(&summary); - - // Iterate through nodes in reverse pre-order so more deeply nested loops (which - // would appear later in the pre-order) are processed first. - for head in summary.preorder().rev() { - // If a node has no back edges, it is not a loop head, so doesn't need to be - // processed. - let back = summary.back_edges(head); - if back.is_empty() { - continue; - } - - // Collect the rest of the nodes in `head`'s loop, in `body`. Start with the - // nodes that jump back to the head, and grow `body` by repeatedly - // following predecessor edges until `head` is found again. - - let mut body = BTreeSet::new(); - for node in back { - let node = partition.containing_loop(*node); - - if node != head { - body.insert(node); - } - } - - let mut frontier: Vec<_> = body.iter().copied().collect(); - while let Some(node) = frontier.pop() { - for pred in summary.pred_edges(node) { - let pred = partition.containing_loop(*pred); - - // `pred` can eventually jump back to `head`, so is part of its body. If it is - // not a descendant of `head`, it implies that `head` does not - // dominate a node in its loop, therefore the CFG is not - // reducible, according to Property 1 (see doc comment). - if !summary.is_descendant(/* ancestor */ head, /* descendant */ pred) { - return err(StatusCode::INVALID_LOOP_SPLIT, summary.block(pred)); - } - - let body_extended = pred != head && body.insert(pred); - if body_extended { - frontier.push(pred); - } - } - } - - // Collapse all the nodes in `body` into `head`, so it appears as one node when - // processing outer loops (this performs a sequence of Operation 4(b), - // followed by a 4(a)). - let depth = partition.collapse_loop(head, &body); - if let Some(max_depth) = verifier_config.max_loop_depth { - if depth as usize > max_depth { - return err(StatusCode::LOOP_MAX_DEPTH_REACHED, summary.block(head)); - } - } - } - - Ok(()) -} diff --git a/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/src/control_flow_v5.rs b/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/src/control_flow_v5.rs deleted file mode 100644 index ce1a55b3a14..00000000000 --- a/external-crates/move/move-execution/v0/crates/move-bytecode-verifier/src/control_flow_v5.rs +++ /dev/null @@ -1,287 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// Modifications Copyright (c) 2024 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -//! This module implements a checker to verify control flow in bytecode version -//! 5 and below. The following properties are ensured: -//! - All forward jumps do not enter into the middle of a loop -//! - All "breaks" (forward, loop-exiting jumps) go to the "end" of the loop -//! - All "continues" (back jumps in a loop) are only to the current loop -use std::{collections::HashSet, convert::TryInto}; - -use move_binary_format::{ - errors::{PartialVMError, PartialVMResult}, - file_format::{Bytecode, CodeOffset, CodeUnit, FunctionDefinitionIndex}, - safe_unwrap, -}; -use move_core_types::vm_status::StatusCode; -use move_vm_config::verifier::VerifierConfig; - -pub fn verify( - verifier_config: &VerifierConfig, - current_function_opt: Option, - code: &CodeUnit, -) -> PartialVMResult<()> { - let current_function = current_function_opt.unwrap_or(FunctionDefinitionIndex(0)); - - // check fallthrough - verify_fallthrough(current_function, &code.code)?; - - // check jumps - let context = &ControlFlowVerifier { - current_function, - code: &code.code, - }; - let labels = instruction_labels(context); - check_jumps(verifier_config, context, labels) -} - -fn verify_fallthrough( - current_function: FunctionDefinitionIndex, - code: &[Bytecode], -) -> PartialVMResult<()> { - // Check to make sure that the bytecode vector ends with a branching - // instruction. - match code.last() { - None => Err(PartialVMError::new(StatusCode::EMPTY_CODE_UNIT)), - Some(last) if !last.is_unconditional_branch() => { - Err(PartialVMError::new(StatusCode::INVALID_FALL_THROUGH) - .at_code_offset(current_function, (code.len() - 1) as CodeOffset)) - } - Some(_) => Ok(()), - } -} - -#[derive(Clone, Copy)] -enum Label { - Loop { last_continue: u16 }, - Code, -} - -struct ControlFlowVerifier<'a> { - current_function: FunctionDefinitionIndex, - code: &'a Vec, -} - -impl<'a> ControlFlowVerifier<'a> { - fn code(&self) -> impl Iterator { - self.code - .iter() - .enumerate() - .map(|(idx, instr)| (idx.try_into().unwrap(), instr)) - } - - fn labeled_code<'b: 'a>( - &self, - labels: &'b [Label], - ) -> impl Iterator { - self.code() - .zip(labels) - .map(|((i, instr), lbl)| (i, instr, lbl)) - } - - fn error(&self, status: StatusCode, offset: CodeOffset) -> PartialVMError { - PartialVMError::new(status).at_code_offset(self.current_function, offset) - } -} - -fn instruction_labels(context: &ControlFlowVerifier) -> Vec