From d5d95b66b64cf5dd18288b8254185a5cb44d10e9 Mon Sep 17 00:00:00 2001 From: nk_ysg Date: Tue, 28 Feb 2023 21:55:50 +0800 Subject: [PATCH] Revert "Cherry pick from bytecode verifier" (#53) * Revert "[bytecode verifier] Meter type instantiations (#64)" This reverts commit 803d4d1f8cd20b0fb00d33cbc93275468ab5c9cd. * Revert "[bytecode verifer] Adjust metering to decrease runtime of some tests. (#62)" This reverts commit 459029f247d0c6cceac5f7e86faa3653bfdd2ba5. * Revert "[bytecode-verifier] Add metering logic and apply to absint based analysis (#58)" This reverts commit 14d624d3d381224c12e38a9abe8e85e91937c51c. * Revert "copyloc-pop test (#54)" This reverts commit 443c45a085b057a70a2412ca26e5f87c497f2782. * Revert "[verifier] fix incorrect error code for per-module back edge limit check" This reverts commit 1926f1ae8080fd3d4f29304563738bbeb3c8db1d. * Revert "[verifier] limit the number of back edges" This reverts commit ef2f4d45629785fbc57e5a4d6181975c28202e5a. * Revert "[language] add catch_unwind panic handling (#750)" This reverts commit b1108273c4716a7b50e8f8a1cc9905164875d5e8. --- Cargo.lock | 3 - .../src/control_flow_graph.rs | 9 - .../move-binary-format/src/deserializer.rs | 20 +- language/move-borrow-graph/src/graph.rs | 8 - language/move-bytecode-verifier/Cargo.toml | 1 - .../bytecode-verifier-tests/Cargo.toml | 6 +- .../bytecode-verifier-tests/METER_TESTING.md | 5 - .../src/unit_tests/binary_samples.rs | 83 ---- .../src/unit_tests/catch_unwind.rs | 29 -- .../src/unit_tests/code_unit_tests.rs | 2 +- .../src/unit_tests/constants_tests.rs | 5 - .../src/unit_tests/control_flow_tests.rs | 3 +- .../src/unit_tests/large_type_test.rs | 155 ------- .../src/unit_tests/limit_tests.rs | 8 +- .../src/unit_tests/locals.rs | 120 ----- .../src/unit_tests/many_back_edges.rs | 96 ---- .../src/unit_tests/mod.rs | 34 -- .../src/unit_tests/reference_safety_tests.rs | 422 ------------------ .../src/unit_tests/signature_tests.rs | 26 +- .../src/unit_tests/vec_pack_tests.rs | 19 +- language/move-bytecode-verifier/src/absint.rs | 14 +- .../src/acquires_list_verifier.rs | 4 +- .../src/code_unit_verifier.rs | 87 +--- .../src/control_flow.rs | 2 - language/move-bytecode-verifier/src/lib.rs | 5 +- .../src/locals_safety/abstract_state.rs | 22 +- .../src/locals_safety/mod.rs | 15 +- language/move-bytecode-verifier/src/meter.rs | 143 ------ .../src/reference_safety/abstract_state.rs | 76 +--- .../src/reference_safety/mod.rs | 30 +- .../src/stack_usage_verifier.rs | 3 +- .../move-bytecode-verifier/src/type_safety.rs | 223 +++------ .../move-bytecode-verifier/src/verifier.rs | 133 ++---- .../call_function_with_many_acquires.exp | 10 - .../call_function_with_many_acquires.move | 416 ----------------- language/move-compiler/src/expansion/ast.rs | 2 - .../src/expansion/dependency_ordering.rs | 1 - .../move-core/types/src/account_address.rs | 9 - language/move-core/types/src/lib.rs | 1 - language/move-core/types/src/state.rs | 25 -- language/move-core/types/src/vm_status.rs | 8 - .../src/unit_tests/function_tests.rs | 5 +- .../tests/concrete_check/bcs.move | 2 - .../src/tests/loader_tests.rs | 3 +- 44 files changed, 192 insertions(+), 2101 deletions(-) delete mode 100644 language/move-bytecode-verifier/bytecode-verifier-tests/METER_TESTING.md delete mode 100644 language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/binary_samples.rs delete mode 100644 language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/catch_unwind.rs delete mode 100644 language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/large_type_test.rs delete mode 100644 language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/locals.rs delete mode 100644 language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/many_back_edges.rs delete mode 100644 language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/reference_safety_tests.rs delete mode 100644 language/move-bytecode-verifier/src/meter.rs delete mode 100644 language/move-bytecode-verifier/transactional-tests/tests/reference_safety/call_function_with_many_acquires.exp delete mode 100644 language/move-bytecode-verifier/transactional-tests/tests/reference_safety/call_function_with_many_acquires.move delete mode 100644 language/move-core/types/src/state.rs diff --git a/Cargo.lock b/Cargo.lock index bcf118d1a5b..d63035b2758 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -603,8 +603,6 @@ dependencies = [ name = "bytecode-verifier-tests" version = "0.1.0" dependencies = [ - "fail", - "hex", "invalid-mutations", "move-binary-format", "move-bytecode-verifier", @@ -3132,7 +3130,6 @@ name = "move-bytecode-verifier" version = "0.1.0" dependencies = [ "anyhow", - "fail", "hex-literal", "invalid-mutations", "move-binary-format", diff --git a/language/move-binary-format/src/control_flow_graph.rs b/language/move-binary-format/src/control_flow_graph.rs index 63ac1e0a295..42d5bee49a0 100644 --- a/language/move-binary-format/src/control_flow_graph.rs +++ b/language/move-binary-format/src/control_flow_graph.rs @@ -45,9 +45,6 @@ pub trait ControlFlowGraph { /// Checks if the 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 { @@ -328,10 +325,4 @@ impl ControlFlowGraph for VMControlFlowGraph { .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/language/move-binary-format/src/deserializer.rs b/language/move-binary-format/src/deserializer.rs index 33ca0600093..68c357ebec0 100644 --- a/language/move-binary-format/src/deserializer.rs +++ b/language/move-binary-format/src/deserializer.rs @@ -4,7 +4,7 @@ use crate::{check_bounds::BoundsChecker, errors::*, file_format::*, file_format_common::*}; use move_core_types::{ - account_address::AccountAddress, identifier::Identifier, metadata::Metadata, state::VMState, + account_address::AccountAddress, identifier::Identifier, metadata::Metadata, vm_status::StatusCode, }; use std::{collections::HashSet, convert::TryInto, io::Read}; @@ -43,21 +43,9 @@ impl CompiledModule { binary: &[u8], max_binary_format_version: u32, ) -> BinaryLoaderResult { - let prev_state = move_core_types::state::set_state(VMState::DESERIALIZER); - let result = std::panic::catch_unwind(|| { - let module = deserialize_compiled_module(binary, max_binary_format_version)?; - BoundsChecker::verify_module(&module)?; - - Ok(module) - }) - .unwrap_or_else(|_| { - Err(PartialVMError::new( - StatusCode::VERIFIER_INVARIANT_VIOLATION, - )) - }); - move_core_types::state::set_state(prev_state); - - result + let module = deserialize_compiled_module(binary, max_binary_format_version)?; + BoundsChecker::verify_module(&module)?; + Ok(module) } // exposed as a public function to enable testing the deserializer diff --git a/language/move-borrow-graph/src/graph.rs b/language/move-borrow-graph/src/graph.rs index 517baa14631..6c888417e62 100644 --- a/language/move-borrow-graph/src/graph.rs +++ b/language/move-borrow-graph/src/graph.rs @@ -26,14 +26,6 @@ impl BorrowGraph { Self(BTreeMap::new()) } - /// Returns the graph size, that is the number of nodes + number of edges - pub fn graph_size(&self) -> usize { - self.0 - .values() - .map(|r| 1 + r.borrowed_by.0.values().map(|e| e.len()).sum::()) - .sum() - } - /// checks if the given reference is mutable or not pub fn is_mutable(&self, id: RefID) -> bool { self.0.get(&id).unwrap().mutable diff --git a/language/move-bytecode-verifier/Cargo.toml b/language/move-bytecode-verifier/Cargo.toml index 2b1bab73d00..bc53165c9a9 100644 --- a/language/move-bytecode-verifier/Cargo.toml +++ b/language/move-bytecode-verifier/Cargo.toml @@ -12,7 +12,6 @@ edition = "2021" [dependencies] anyhow = "1.0.52" petgraph = "0.5.1" -fail = "0.4.0" move-borrow-graph = { path = "../move-borrow-graph" } move-binary-format = { path = "../move-binary-format" } diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/Cargo.toml b/language/move-bytecode-verifier/bytecode-verifier-tests/Cargo.toml index 902cb2340df..8b256d6d883 100644 --- a/language/move-bytecode-verifier/bytecode-verifier-tests/Cargo.toml +++ b/language/move-bytecode-verifier/bytecode-verifier-tests/Cargo.toml @@ -12,13 +12,11 @@ edition = "2021" [dev-dependencies] petgraph = "0.5.1" proptest = "1.0.0" -fail = { version = "0.4.0", features = ['failpoints']} -hex = "0.4.3" + move-bytecode-verifier = { path = "../" } invalid-mutations = { path = "../invalid-mutations" } move-core-types = { path = "../../move-core/types" } -move-binary-format = { path = "../../move-binary-format", features = ["fuzzing" ] } +move-binary-format = { path = "../../move-binary-format", features = ["fuzzing"] } [features] fuzzing = ["move-binary-format/fuzzing"] -address32 = ["move-core-types/address32"] diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/METER_TESTING.md b/language/move-bytecode-verifier/bytecode-verifier-tests/METER_TESTING.md deleted file mode 100644 index cd5ae0f4215..00000000000 --- a/language/move-bytecode-verifier/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 --features=address32 -- --nocapture 1>/dev/null -``` diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/binary_samples.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/binary_samples.rs deleted file mode 100644 index 9da0b1c9898..00000000000 --- a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/binary_samples.rs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) The Move Contributors -// 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 crate::unit_tests::production_config; -use move_binary_format::{errors::VMResult, CompiledModule}; -use move_bytecode_verifier::verifier; - -#[allow(unused)] -fn run_binary_test(name: &str, bytes: &str) -> VMResult<()> { - let bytes = hex::decode(bytes).expect("invalid hex string"); - let m = CompiledModule::deserialize(&bytes).expect("invalid module"); - verifier::verify_module_with_config_for_test(name, &production_config(), &m) -} - -#[cfg(feature = "address32")] -#[test] -fn sample_price_oracle() { - let code = - "a11ceb0b050000000c01001602162003368a0104c0011405d401a80607fc07f90308f50b6006d50c9b3210f03e770ae73f170cfe3f951e0d935e060000010101020103010401050006020702080209020a000b0800000c0800080d070004170402030100010318070009190700071c0700000e000100000f0201010000100201010000110302000012030200001304020000140506000015050600080f080900071d0a0100081e080900071f0a0b0007200a010006210c01000122020f01000123020c01000424110b020300042511120203000a261314000527020f0100022803180004290219020304092a1a1b00032b1a0f00042c1c02020302020e0e0e0f0e10101110130e1016111615101810020608020201030001060c02060c0304030103010203010908060303080603010301030106080201080601060806010101020502060800080508040802010900010804020804080502060b0302090009010900010609010208050301080202080406080102080403ae010a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a02080508000708000a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050105010b030209000901010a0201080503070b0302090009010900090193010508000708000a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a02080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805010708000b03030101010301030103010b01030101010301030103010c70726963655f6f7261636c6504636f696e067369676e657206737472696e67057461626c6509747970655f696e666f046d617468036936340570726963651070726963655f6964656e74696669657204707974681250726963654964656e7469666965724d61700e54657374507269636553746f72650550726963650c666f726d61745f7072696365096765745f7072696365126765745f70726963655f666f725f746573740a696e697469616c697a6512696e697469616c697a655f746573746e6574127365745f7468726573686f6c645f73656373107369676e65645f7536345f6d696e75730f7369676e65645f7536345f706c757304696e666f055461626c6506537472696e670f50726963654964656e7469666965720e7468726573686f6c645f736563730b70726963655f7461626c6503493634196765745f6d61676e69747564655f69665f706f736974697665086765745f6578706f0f6765745f69735f6e65676174697665196765745f6d61676e69747564655f69665f6e6567617469766506706f775f31300673796d626f6c08646563696d616c7308636f6e7461696e7306626f72726f77176765745f70726963655f6e6f5f6f6c6465725f7468616e09747970655f6e616d650a616464726573735f6f66036e65770d66726f6d5f627974655f76656304757466380675707365727414812adfd8ba2f589c0fe48c5170fa287cd36050dd487d17e2f4a765101f70ed00000000000000000000000000000000000000000000000000000000000000017e783b349d3e89cf5931af376ebeadbfab855b3fa239b7ada8f5a92fbea6b3870308700000000000000003086d0000000000000003086e0000000000000003081000000000000000052014812adfd8ba2f589c0fe48c5170fa287cd36050dd487d17e2f4a765101f70ed0a0221202b9ab1e972a281585084148ba1389800799bd4be63b957507db1349314e474450a020504414156450a022120bd640cddb72063e2ede34c6a0baf6699759b9837fcb06aa0e2fbcecb9b65fde70a02040341434d0a0221202a01deaec9e51a579277b34b122399984d0bbf57e2458a7e42fecd2829867a0d0a0204034144410a022120fa17ceaf30d19ba51112fdcc750cc83454776f47fb0112e4af07f15f4bb1ebc00a020504414c474f0a0221206d0af467543fc7daedf7abed96423877560c8d03725f3e5c87516774982a679c0a020403414e430a02212015add95022ae13563a11992e727c91bdb6b55bc183d9d747436c80a483d8c8640a0204034150450a02212003ae4db29ed4ae33d323568895aa00337e658e348b37509f5372ae51f0af00d50a0204034150540a022120b881c6dad5dd3dc9a83222f8032fb439859288119afc742d43adc305cef151cc0a0204034153520a022120681e0eb7acf9a2a3384927684d932560fb6f67c6beb21baa0f110e993b2653860a02060541544c41530a0221208ff1200345393bb25be4f4eeb2d97234e91f7e6213f3745a694b1436e700f2710a02040341544d0a022120b00b60f88b03a6a625a8d1c048c3f66653edf217439983d037e7222c4e6128190a02050441544f4d0a0221204cbd623d7aa47003fff1cd75c3f96cb24a660014b697d91cfb7adcd204b952020a020504415553540a02212093da3352f9f1d105fdfe4971cfa80e9dd777bfc5d0f683ebb6e1294b92137bb70a020504415641580a022120b7e3904c08ddd9c0c10c6d207d390fd19e87eb6aab96304f571ed94caebdefa00a0204034158530a0221209d23a47f843f5c9284832ae6e76e4aa067dc6072a58f151d39a65a4cc792ef9f0a0204034241520a0221203dd2b63686a450ec7290df3a1e0b583c0481f651351edfa7636f39aed55cf8a30a0204034243480a0221207f981f906d7cfe93f618804f1de89e0199ead306edc022d3230b3e8305f391b00a020504424554480a0221202f95862b045670cd22bee3114c39763a4a08beeb663b145d283c31d7d1101c4f0a020403424e420a0221201ce9069708fb49e2f1b062fa4f1be0bb151475ca506939d6d8c14386d49f43dc0a02040342525a0a022120e62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b430a0204034254430a022120097d687437374051c75160d648800f021086bc8edf469f11284491fda81923150a0204034254540a0221205bc91f13e412c07599167bae86f07543f076a638962b8d6017ec19dab4a828140a020504425553440a0221202dd14c7c38aa7066c7a508aac299ebcde5165b07d5d9f2d94dfbfe41f0bc5f2e0a0204034339380a0221202356af9529a1064d41e32d617e2ce1dca5733afa901daba9e2b68dee5d53ecf90a02050443414b450a02212015ecddd26d49e1a8f1de9376ebebc03916ede873447c1255d2d5891b92ce57170a02060543424554480a022120bd4dbcbfd90e6bc6c583e07ffcb5cb6d09a0c7b1221805211ace08c8378596270a0204034348520a022120e799f456b358a2534aa1b45141d454ac04b444ed23b1440b778549bb758f2b5c0a02040343485a0a0221209c479b12a2b2c1051715d4d462dd7a6abbb6dccabf3af31a53f6130a1cd88efc0a020504434954590a0221208517b35589b5f1f6ad626da2379ff592d5101b63aa661d75b7a883fdbda023f00a020504434f50450a0221204e53c6ef1f2f9952facdcf64551edb6d2a550985484ccce6a0477cae4c1bca3e0a020403434f570a0221208f218655050a1476b780185e89f19d2b1e1f49e9bd629efad6ac547a946bf6ab0a020504435553440a022120b0948a5e5313200c632b51bb5ca32f6de0d36e9950a942d19751e833f70dabfd0a0204034441490a022120dcef50dd0a4cd2dcc17e45df1676dcb336a11a61c69df7a0299b0150c672d25c0a020504444f47450a022120ca3eed9b267293f6595901c734c7525ce8ef49adafe8284606ceb307afa2ca5b0a020403444f540a022120ff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace0a0204034554480a022120c80657b7f6f3eac27218d09d5a4e54e47b25768d9f5e10ac15fe2cf9008814000a020504464944410a0221202fb245b9a84554a0f15aa123cbb5f64cd263b59e9a87d80148cbffab50c69f300a020504464c4f570a0221205c6c0d2386e3352356c3ab84434fafb5ea067ac2678a38a338c4a69ddc4bdb0c0a02040346544d0a0221206c75e52531ec5fd3ef253f6062956a8508a2f03fa0a209fb7fbc51efd9d35f880a0204034654540a022120301377b122716cee1a498e7930a1836c0b1db84667cc78bbbcbad6c330ea6afb0a02040347414c0a0221200781209c28fda797616212b7f94d77af3a01f3e94a5d421760aef020cf2bcb510a02050447414c410a022120baa284eaf23edf975b371ba2818772f93dbae72836bbdea28b07d40f3cf8b4850a020403474d540a0221206034b1f68b9363dff2cf9d53b1a88fb4d0929c65f34d532db53738853efc00ad0a020504474f46580a02212095609d32c98a467a72ac419f2e64bb2b8dbd5b00b74f3a0fd72f42343af1743d0a0205044858524f0a0221207a5bc1d2b56ad029048cd63964b3ad2776eadf812edc1a43a31406cb54bff5920a020403494e4a0a022120a4702f0f5818258783a1e47f453cb20b0fbec32ca67260e1d19dfcdd6a4d0ebb0a020605494e5445520a02212081a21b01c15b8d01f6cdfed65e00987cc4c901858c821b2089344987de3102e90a0204034a45540a022120ee42016c303126bd9263724e00f83a8114e84518c6e8ffc9738c001cc301daff0a0204034a53540a022120abe4f2b264560a397f38eec024369356e5c1ea4f7aab94729369f144b3d977790a0204034a55560a022120d1d95644ffc11ca502f21e067a7814144c56b37018515ced4335a886a827a3050a0206054c415a494f0a0221206e3f3fa8253588df9326580180233eb791e03b443a3ba7a1d892e73874e19a540a0204034c54430a022120e6ccd3f878cf338e6732bf59f60943e8ca2c28402fc4d9c258503b2edbe74a310a0205044c554e410a0221204456d442a152fd1f972b18459263ef467d3c29fb9d667e30c463b086691fbc790a0205044c554e430a0221205de33a9112c2b700b8d30b8a3402c103578ccfa2765696471cc672bd5cf6ac520a0206054d415449430a0221201888f463c27997174f97d2a36af29bf4648b61a5f69e67c45505a80f826bb7850a0205044d424f580a02212027d108eb764c912f49d3453a21dd95516619b1c45d0b607ee58a137ac8a6f32d0a0205044d45414e0a022120dfaeafde7f8ad3cb9ddbcc85ed7ae7e53910e7ab377fd75921920f97c80a8edc0a0204034d45520a0221200b46c1c04e9c914037cc4e0561a7e6787f6db0b89b7b65281f0f6fea1ce45a740a0204034d49520a0221205b70af49d639eefe11f20df47a0c0760123291bb5bc55053faf797d1ff9059830a0205044d4e474f0a022120c2289a6a43d2ce91c6f55caec370f4acc38a2ed477f58813334c6d03749ff2a40a0205044d534f4c0a022120c415de8d2eba7db216527dff4b60e8f3a5311c740dadb233e13e12547e2267500a0205044e4541520a02212005934526b94a9fbe4c4ce0c3792213032f086ee4bf58f2168a7085361af9bdc10a0203024f470a022120c572690504b42b57a3f7aed6bd4aae08cbeeebdadcf130646a692fe73ec1e0090a0204034f4e450a02212037505261e557e251290b8c8899453064e8d760ed5c65a779726f2490980da74c0a0205044f5243410a0221200afa3199e0899270a74ddcf5cc960d3c6c4414b4ca71024af1a62786dd24f52a0a020504504f52540a02212088e2d5cbd2474766abffb2a67a58755a2cc19beb3b309e1ded1e357253aa36230a020605504f52544f0a0221203d253019d38099c0fe918291bd08c9b887f4306a44d7d472c8031529141f275a0a0204035053470a022120fd0690232b0fae5efdc402c1b9aac74176383ff7daf87d021554bda24a38e0ec0a020504524143410a02212091568baa8beb53db23eb3fb7f22c6e8bd303d103919e19733f2bb642d3e7987a0a0204035241590a0221206ed3c7c4427ae2f91707495fc5a891b30795d93dbb3931782ddd77a5d8cb6db70a0204035342520a0221201021a42d623ab4fe0bf8c47fd21cc10636e39e07f91e9b2478551e137d512aaa0a02070653434e534f4c0a022120f8d030e4ef460b91ad23eabbbb27aec463e3c30ecc8d5c4b71e92f54a36ccdbd0a020504534c4e440a0221209fb0bd29fe51481b61df41e650346cc374b13c2bab2e3610364cd834a592025a0a020403534e590a022120ef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d0a020403534f4c0a02212023245bb74254e65a98cc3ff4a37443d79f527e44e449750ad304538b006f21bc0a02040353524d0a022120a1a6465f4c2ebf244c31d80bc95c27345a3424e428c2def33eced9e90d3f701b0a0206055354534f4c0a0221204457960559b812558bb0f8cb7912f8bcb843eb801a3133ef45be998630ff8c050a020403544c4d0a022120433faaa801ecdb6618e3897177a118b273a8e18cc3ff545aadfc207d58d028f70a020504545553440a022120eaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a0a020504555344430a0221202b89b9dc8fdf9f34709a5b106b472f0f39bb6ca9ce04b0fd7f2e971688e2e53b0a020504555344540a022120ef94acc2fb09eb976c6eb3000bab898cab891d5b800702cd1dc88e61d7c3c5e60a020504555354430a0221207507a4629ad0143550666bce2e7cae0b961a0f624f821feaab642fe1be632f5c0a0204035641490a022120b216f7ca372b318985903866e0b6dc44a14564828c49f36d0d363805aa76335c0a02040357494e0a022120b82449fd728133488d2d41131cffe763f9c1693b73c544d9ef6aaa371060dd250a020403574f4f0a022120831624f51c7bd4499fe5e0f16dfa2fd22584ae4bdc496bbbbe9ba831b2d9bce90a0204035856530a02212026852e2d0696e25e6adaad2d7ca3a1f2f15aab68d317ace14d41b4128a7e780f0a0204035a42430a022120d6b3bc030a8bbb7dd9de46fb564c34bb7f860dead8985eb16a49cdc62f8ab3a50a02212073dc009953c83c944690037ea477df627657f45c14f16ad3a61089c5a3f9f4f20a02212008f781a893bc9340140c5f89c8a96f438bcfae4d1474cc0f688e3a52892c73180a0221204204a764d9e0ca8db0fd43b62728265bf82671ce8a8b4bfedba13672be12de620a022120cb1743d0e3e3eace7e84b8230dc082829813e3ab04e91b503c08e9a441c0ea8b0a02212044a93dddd8effa54ea51076c4e851b6cbbfd938e82eb90197de38fe8876bb66e0a022120c11efd88a9b2c96bc84bccd6ce4aa05bebad7aa760dbe5f2f00ef90c4abd50cc0a02212061226d39beea19d334f17c2febce27e12646d84675924ebb02b9cdaea68727e30a022120d7566a3ba7f7286ed54f4ae7e983f4420ae0b1e0f3892e11f9c4ab107bbad7b90a02212030029479598797290e3638a1712c29bde2367d0eca794f778b25b5a472f192de0a022120fc309467defa4b198c6b5bd59c08db4b9dfb27ddbcc32f31560f217b4ff8fc2b0a022120ecf553770d9b10965f8fb64771e93f5690a182edc32be4a3236e0caaa6e0581a0a022120457064c555edae5b6b89267e992be4c58be5375f0e9ca9749391c7094f7d90330a022120f9c0172ba10dfa4d19088d94f5bf61d3b54d5bd7483a322a982e1373ee8ea31b0a022120eb3b5720301b36fa074260e6e27e2cfff3a7c6bbb47564eb218a9a7f2a8c01930a02212006c532524fabd49cc142815502d785e4f34ec3bd035480efb770568d423f46c60a022120c098773aa18ebb7e84d5ee7ea7d97105ab2015a329f670012398cd2c8f5cc6ca0a0221200d10b9ccdc9af1d65cd4bafabf4e34db01c0ce83abba190230eaf26d7592cd210a022120970541e943e11d1bf1d4d763bc8e70995f613dc682f727045a866312312a63760a02212013ac8c71e4e1c61dece57bea76163d393bf75cd0db8e52981e1564fa592698cb0a022120b59d65c2e10af17c0d6f7d10be8d64c0c13dd15d957c4c39763b4cc55e5919370a02212087a67534df591d2dd5ec577ab3c75668a8e3d35e92e27bf29d9e2e52df8de4120a02212031775e1d6897129e8a84eeba975778fb50015b88039e9bc140bbd839694ac0ae0a02212036032e522b810babd8e3148e9f0d588af9e95e93b97ffb58566b837fdbd31f7f0a022120ca80ba6dc32e08d06f1aa886011eed1d77c77be9eb761cc10d72b7d0a2fd57a60a0221206660d7629213995af8aa169ad6a1cf1a725765d3741b7e7a27825f884a701b960a022120aa67a6594d0e1578faa3bba80bec5b31e461b945e4fbab59eeab38ece09335fb0a0221209b7bfd7654cbb80099d5edc0a29159afc9e9b4636c811cf8c3b95bd11dd8e3dd0a0221200184a60a47ab7c23fcb828d727b05748ef52433fb5ae96f775cc98c9049d8c2c0a0221206354d685c247f1efc36f967617beffa2ebd5a95d8ffe17de4498505c923067b80a02212021adabf73ad61903c1872fa220f84d3b1b9990cec2047f8317e2a67efcd1764e0a022120c999fe8a75bf9528931deb832e2934dd1ac138757d7f2c1398675b6f521d556f0a02212087fd5a8d0bf026239f98b53311d2cec2ee171e853f545e1ad742e092a97ef8600a02212051ae9b785e6aeb288955720faef15f63ee3ae21af38114ade8b3fc3d3831b5ad0a0221202d9315a88f3019f8efa88dfe9c0f0843712da0bac814461e27733f6b83eb51b30a0221202245aec1db780b8dc9f710173256996164f0a65f25a975453e4202a54371d2ea0a022120077e345652cb98edba89815a63a0ede724eba12d7a10c8498e0e762d581aca6b0a022120997e0bf451cb36b4aea096e6b5c254d700922211dd933d9d17c467f0d6f343210a022120677dbbf4f68b5cb996a40dfae338b87d5efb2e12a9b2686d1ca16d69b3d7f2040a0221206de025a4cf28124f8ea6cb8085f860096dbc36d9c40002e221fc449337e065b20a022120d2c2c1f2bba8e0964f9589e060c2ee97f5e19057267ac3284caef3bd50bd2cb50a02212070bf2974182b6ebf4eac64977170074315e7a07d7b58a963758060924ee9a1920a0221209f2acb902ee5c3a8e41c643164a498ed3089c99df3477189babd3682801340750a02212052800482aa2666c0d2621f8f0a8c19ee6e5e5039a65524e268315501b3355fbb0a0221202f317bea04ce89adb8acc85a1a68d20d6e89976d5e86306570a0bb3107e4916a0a022120b5366e5ded52c3db5d81635a624a39d81eb8c639427fc79c539e5c91e17c84940a0221207f57ca775216655022daa88e41c380529211cde01a1517735dbcf30e4a02bdaa0a02212027e867f0f4f61076456d1a73b14c7edc1cf5cef4f4d6193a33424288f11bd0f40a0221209b245faf19d2f3306b58821ef60b194d7b67eb5250635059d8eaae4a36337b280a02212085dafbfa99c733fdd33649551666958ca8f82fd0d849746e093b770caab249d20a0221206b86b78584e182c61729267d73593f48b6a929f3218234769281513cbe5e87ee0a0204035041490a0221201e761bb4e6b1e4d7899b618d389516ddbdfbdb858018b71c45cb6ade57c96f620a0221207730809b4a4656325b7fbc8157fd803c3da170727c541afc4db37773246258b10a022120cb9372930932694b8a74dd5599c0f9e236575f434faf05141d95803a91f044ed0a022120341d9502b1e6bc445036fd76f57bc824c09254a754289878b52a40eb067d2a0b0a022120f9917668f24038a383e51c0b019f5d9645d6785c6bf9a0d48483edf82ba5caec0a022120dd51a67a1b4d0702abf5b5385631b7d3e586993eadacf2e0d900c0a81edcffdd0a022120b5d2cee0b86bb0571db898ae7b9f288c5e272fa486d41a5bf375b52a0249d94c0a022120fe650f0367d4a7ef9815a593ea15d36593f0643aaaf0149bb04be67ab851decd0a02212078ec25615d53d2486db101e829f77615c4408cbbd543088714b9f267da44591a0a022120b718e659619a031b41c6ea9122f146859a82d4a7edc17c55b1e5188e8b4c1d1c0a020504535445500a02212013f7925c9186b8cca50dde4bbf2d4fa9705052cceb6f2fc79df827e2b37d6f3b0a0221200adbf6463e27f60f171bcc498703a4282d1954ec3a85e1f6698b48ecde18c00e0a0221201bd1c59cd425aebf8a931c1b2a902b9a11e7d18dc68021e4a35a5cf24220a6c70a02212041f3625971ca2ed2263e78573fe5ce23e13d2558ed3f2e47ab0f84fb9e7ae7220a0221201fc18861232290221461220bd4e2acd1dcdfbc89c84092c93c18bdc7756c15880a022120026d1f1cf9f1c0ee92eb55696d3bd2393075b611c4f468ae5b967175edc4c25c0a022120eca4f9c5ce7cbef8a349fa9f6c12b23ac45b9ad91c4d1808c6a2dda841f95a020a022120834d3f05278b6f5c963670f437a2267c160914707328f888418902106bcd13d70a022120bf517e0f7ccfc307f0b2fa93b99a737641933989af6af769c928725989c21e660a0221206ff709bf1f0fdb46d991ae6839163df1e050d143429d737fc650b6b2143478080a02212064abe8a459058c60d55427f62be3dc4942c0ba93d1eb5cb85117b70b8e4651ad126170746f733a3a6d657461646174615f763063036d000000000000001a4552525f4e4f545f454e4f5547485f5045524d495353494f4e53006e00000000000000134552525f544f4b454e5f4e4f545f464f554e44007000000000000000174552525f414c52454144595f494e495449414c495a454400000202160b0302080408051a030102011b0b03020804030000000007440a0011080c020e0211090c080b00110a0c050600000000000000000c0a090c090b0a0b0907030911070c090c0a0e05110b0c070a07031a051e0e05110c0c0305210e0511090c030b030c060b0a0b090b060b0711070c090c0a0b0a0b090b01340911060c090c0a0b090335053c0b080b0a33110d1a0c0405420b080b0a33110d180c040b04020101000200010d26070429010304050638000238010c0338020c0007042b000c010a0110000a03380303160b01010702270a0110000b033804140c020b020b0110011411120c040e040b001100020200000101151438050c0007042b010c010a0110020a003806030e0b01010702270b0110020b0038071402030104010017a4060a00111407042103090b00010701270a00111429002003120b00010700273808063c0000000000000012000c6b0a000b6b2d000b0011142a000c6c070511160c020a6c0f00070611170b023809070711160c040a6c0f00070811170b043809070911160c060a6c0f00070a11170b063809070b11160c080a6c0f00070c11170b083809070d11160c0a0a6c0f00070e11170b0a3809070f11160c0c0a6c0f00071011170b0c3809071111160c0e0a6c0f00071211170b0e3809071311160c100a6c0f00071411170b103809071511160c120a6c0f00071611170b123809071711160c140a6c0f00071811170b143809071911160c160a6c0f00071a11170b163809071b11160c180a6c0f00071c11170b183809071d11160c1a0a6c0f00071e11170b1a3809071f11160c1c0a6c0f00072011170b1c3809072111160c1e0a6c0f00072211170b1e3809072311160c200a6c0f00072411170b203809072511160c220a6c0f00072611170b223809072711160c240a6c0f00072811170b243809072911160c260a6c0f00072a11170b263809072b11160c280a6c0f00072c11170b283809072d11160c2a0a6c0f00072e11170b2a3809072f11160c2c0a6c0f00073011170b2c3809073111160c2e0a6c0f00073211170b2e3809073311160c300a6c0f00073411170b303809073511160c320a6c0f00073611170b323809073711160c340a6c0f00073811170b343809073911160c360a6c0f00073a11170b363809073b11160c380a6c0f00073c11170b383809073d11160c3a0a6c0f00073e11170b3a3809073f11160c3c0a6c0f00074011170b3c3809074111160c3e0a6c0f00074211170b3e3809074311160c400a6c0f00074411170b403809074511160c420a6c0f00074611170b423809074711160c440a6c0f00074811170b443809074911160c460a6c0f00074a11170b463809074b11160c480a6c0f00074c11170b483809074d11160c4a0a6c0f00074e11170b4a3809074f11160c4c0a6c0f00075011170b4c3809075111160c4e0a6c0f00075211170b4e3809075311160c500a6c0f00075411170b503809075511160c520a6c0f00075611170b523809075711160c540a6c0f00075811170b543809075911160c560a6c0f00075a11170b563809075b11160c580a6c0f00075c11170b583809075d11160c5a0a6c0f00075e11170b5a3809075f11160c5c0a6c0f00076011170b5c3809076111160c5e0a6c0f00076211170b5e3809076311160c600a6c0f00076411170b603809076511160c620a6c0f00076611170b623809076711160c640a6c0f00076811170b643809076911160c660a6c0f00076a11170b663809076b11160c680a6c0f00076c11170b683809076d11160c6a0a6c0f00076e11170b6a3809076f11160c6e0a6c0f00077011170b6e3809077111160c700a6c0f00077211170b703809077311160c720a6c0f00077411170b723809077511160c740a6c0f00077611170b743809077711160c760a6c0f00077811170b763809077911160c780a6c0f00077a11170b783809077b11160c7a0a6c0f00077c11170b7a3809077d11160c7c0a6c0f00077e11170b7c3809077f11160c7e0a6c0f0007800111170b7e380907810111160c80010a6c0f0007820111170b8001380907830111160c82010a6c0f0007840111170b8201380907850111160c84010a6c0f0007860111170b8401380907870111160c86010a6c0f0007880111170b8601380907890111160c88010a6c0f00078a0111170b88013809078b0111160c8a010a6c0f00078c0111170b8a013809078d0111160c8c010a6c0f00078e0111170b8c013809078f0111160c8e010a6c0f0007900111170b8e01380907910111160c90010a6c0f0007920111170b9001380907930111160c92010a6c0f0007940111170b9201380907950111160c94010a6c0f0007960111170b9401380907970111160c96010a6c0f0007980111170b9601380907990111160c98010a6c0f00079a0111170b98013809079b0111160c9a010a6c0f00079c0111170b9a013809079d0111160c9c010a6c0f00079e0111170b9c013809079f0111160c9e010a6c0f0007a00111170b9e01380907a10111160ca0010a6c0f0007a20111170ba001380907a30111160ca2010a6c0f0007a40111170ba201380907a50111160ca4010a6c0f0007a60111170ba401380907a70111160ca6010a6c0f0007a80111170ba601380907a90111160ca8010a6c0f0007aa0111170ba801380907ab0111160caa010a6c0f0007ac0111170baa01380907ad0111160cac010a6c0f0007ae0111170bac01380907af0111160cae010b6c0f0007b00111170bae0138090204010401001da7050a0011140c010a01070421030b0b00010701270a00111429002003140b0001070027380806504600000000000012000c020b000b022d000b012a000c0307b10111160c4c0a030f00070611170b4c380907b20111160c6d0a030f00070a11170b6d380907b30111160c780a030f00070c11170b78380907b40111160c83010a030f00070e11170b8301380907b50111160c8e010a030f00071011170b8e01380907b60111160c520a030f00071211170b52380907b70111160c5d0a030f00071611170b5d380907b80111160c650a030f00071a11170b65380907b90111160c660a030f00071e11170b66380907ba0111160c670a030f00072411170b67380907bb0111160c680a030f00072611170b68380907bc0111160c690a030f00072811170b69380907bd0111160c6a0a030f00072a11170b6a380907be0111160c6b0a030f00072c11170b6b380907bf0111160c6c0a030f00072e11170b6c380907c00111160c6e0a030f00073011170b6e380907c10111160c6f0a030f00073211170b6f380907c20111160c700a030f00073811170b70380907c30111160c710a030f00073e11170b71380907c40111160c720a030f00074011170b72380907c50111160c730a030f00074211170b73380907c60111160c740a030f00074411170b74380907c70111160c750a030f00074611170b75380907c80111160c760a030f00074811170b76380907c90111160c770a030f00074a11170b77380907ca0111160c790a030f00074c11170b79380907cb0111160c7a0a030f00074e11170b7a380907cc0111160c7b0a030f00075011170b7b380907cd0111160c7c0a030f00075211170b7c380907ce0111160c7d0a030f00075411170b7d380907cf0111160c7e0a030f00075611170b7e380907d00111160c7f0a030f00075811170b7f380907d10111160c80010a030f00075a11170b8001380907d20111160c81010a030f00075c11170b8101380907d30111160c82010a030f00075e11170b8201380907d40111160c84010a030f00076211170b8401380907d50111160c85010a030f00076411170b8501380907d60111160c86010a030f00076a11170b8601380907d70111160c87010a030f00076c11170b8701380907d80111160c88010a030f00076e11170b8801380907d90111160c89010a030f00077011170b8901380907da0111160c8a010a030f00077211170b8a01380907db0111160c8b010a030f00077411170b8b01380907dc0111160c8c010a030f00077611170b8c01380907dd0111160c8d010a030f00077811170b8d01380907de0111160c8f010a030f00077a11170b8f01380907df0111160c90010a030f00077c11170b9001380907e00111160c91010a030f00077e11170b9101380907e10111160c92010a030f0007820111170b9201380907e20111160c93010a030f0007840111170b9301380907e30111160c4d0a030f0007e40111170b4d380907e50111160c4e0a030f0007860111170b4e380907e60111160c4f0a030f00078c0111170b4f380907e70111160c500a030f00078e0111170b50380907e80111160c510a030f0007900111170b51380907e90111160c530a030f0007920111170b53380907ea0111160c540a030f0007940111170b54380907eb0111160c550a030f0007960111170b55380907ec0111160c560a030f0007980111170b56380907ed0111160c570a030f00079a0111170b57380907ee0111160c580a030f0007ef0111170b58380907f00111160c590a030f00079c0111170b59380907f10111160c5a0a030f00079e0111170b5a380907f20111160c5b0a030f0007a00111170b5b380907f30111160c5c0a030f0007a20111170b5c380907f40111160c5e0a030f0007a40111170b5e380907f50111160c5f0a030f0007a60111170b5f380907f60111160c600a030f0007a80111170b60380907f70111160c610a030f0007aa0111170b61380907f80111160c620a030f0007ac0111170b62380907f90111160c630a030f0007ae0111170b63380907fa0111160c640b030f0007b00111170b6438090205010401001e120a00111407042103090b00010701270b0011142a000c020b010b020f011502060000001f5d0a010a031f0305051c0a020a0026030a05110b020b0017090c070c0405170b000b0217080c070c040b040b070c060c05055a0a01031f05230a03200c080525090c080b080328052f0b000b0216080c0e0c0d05560b01200b031f0335053c0b000b0216090c0c0c0b05520a000a0226034105480b000b0217090c0a0c09054e0b020b0017080c0a0c090b090b0a0c0c0c0b0b0b0b0c0c0e0c0d0b0d0b0e0c060c050b050b060207000000205e0a010a031f03050508080c0705140a0120030c05100a03200c040512090c040b040c070b070317051e0b000b02160b010c060c05055b0b01032105250b03200c080527090c080b08032a05410a000a0224032f05360b000b0217080c0a0c09053c0b020b0017090c0a0c090b090b0a0c0e0c0d05570a020a00240346054d0b020b0017080c0c0c0b05530b000b0217090c0c0c0b0b0b0b0c0c0e0c0d0b0d0b0e0c060c050b050b060200000001010000"; - let res = run_binary_test("sample_price_oracle", code); - assert!(res.is_ok(), "{:?}", res) -} - -#[cfg(feature = "address32")] -#[test] -fn sample_aptosd_swap() { - let code = "a11ceb0b050000000c0100160216300346ee0104b4022205d602960407ec06de0708ca0e40068a0f8b01109510f9010a8e12520ce012e80e0dc821160000010101020103010401050106010700080009000a000b0700000c0700000d0800000e0700000f07000a28040207000400042b0401060102380800083a0000063c070100000010000100001102010000120101000013030100001401010000150101000016020100001701040000180506000019010700001a020100001b020100001c010100001d000100001e020100001f02010000200001000021000100092f01090009300105000a310b0c02070604320e01010607330205000934010f0009350104000936010f000a37110f020704033900010100033b02010100093d0104000a3e1617020704063f180f01000640191a01000a411b1c02070409421d010005431f040005441f0400094501200009460104000947010f0009480901000a490125020704014a022601060a4b1128020704140a150d1a0a1b121c1315141e0a1f052005210a151e290a2a0d2a142a1e2b0a1b1303060c05030001060c02060c0301030105050303030303010a050c03030303030505070b0502050803070b0502050803070802070803070b0601080401020205080303070b050209000901090009010107090101080402070b060109000900010108070b05020508030501070b06010800030107080207080302060b05020900090109000108070108080108002d0b0901050b0901050b0901050c0b0901050b0901050b0901050b0901050b090105030303030303070b06010801070b06010801070b06010801070b0601080103070803070803070803070803070b0502050803070b0502050803070b0502050803070b0502050803070b090105070b090105070b090105070b09010503030b0901050b0901050b0901050b090105070802070802070802070802070802030301060b050209000901010b0901090001060b0901090001070b0901090001090002070b0502090009010900030709010b090109000b09010900020503010801020303010c04010103030a03030303030505070b0502050803070b0502050803070803070b0901050b090105070803070b0502050803070b0901050b0901050a050a0b0502050803060c030c0b060108040c0b060108000c0b060108010c010b050209000901010b060109000c0b0901050c070b0502050803050b090105070b06010801060803070b0502050803070b0901050b090105070802060c030609010b090109000b090109000d6170746f737061645f73776170076163636f756e740a6170746f735f636f696e04636f696e056576656e74066d6174683634066f7074696f6e067369676e65720d6170746f737061645f636f696e06636f6e6669670e6974657261626c655f7461626c65104269644170746f735061644576656e7417446973747269627574654170746f737061644576656e74114c61756e636850616452656769737472790f546f6b656e446973747269627574650e57686974654c6973744576656e740c61646457686974654c6973740c6173736572745f61646d696e136173736572745f6e6f5f656d657267656e63790b6269644170746f735061640d64697374726962757465416c6c0e64697374726962757465417470701064697374726962757465536561736f6e0f67657453776170546f74616c4269640c67657457686974654c6973740d67657457686974654c697374730a696e697469616c697a650f6c61756e6368506164536561736f6e09726566756e64416c6c0b726566756e644170746f730b7265736574536561736f6e0f77686974654c697374536561736f6e0d77697468647261774170746f731077697468647261774170746f73506164036361700362696408696e766573746f72106469737472696275746564546f6b656e06726566756e6409696e766573746f72730d4974657261626c655461626c6508746f74616c426964126269646170746f737061645f6576656e74730b4576656e7448616e646c6519646973747269627574656170746f737061645f6576656e74731077686974656c6973745f6576656e74730b64697374726962757465640c676574537761705374617465126765745265736f757263654164647265737317626f72726f775f6d75745f776974685f64656661756c740a656d69745f6576656e740a616464726573735f6f660b6973456d657267656e63791467657453776170436f6e6669674861726443617011697342797061737357686974654c69737408636f6e7461696e73094170746f73436f696e087472616e736665720c4170746f73506164436f696e087265676973746572064f7074696f6e1a67657453776170436f6e666967417074546f417074745261746508686561645f6b65790769735f736f6d6507657874726163740f626f72726f775f697465725f6d75740a6d696e7441747070546f036d696e036d6178116765745265736f757263655369676e65721467657453776170436f6e666967536f66744361701967657453776170436f6e666967456e61626c65526566756e640c736574537761705374617465036e6577106e65775f6576656e745f68616e646c650b626f72726f775f6974657241376d8231e6aedc29a19459e804b3770a250c3f367ac8d0f91e10842e8c906d0000000000000000000000000000000000000000000000000000000000000001030800e87648170000000308950100000000000003089a0100000000000003089b010000000000000308930100000000000003089801000000000000030896010000000000000308970100000000000003089901000000000000020104020105020101020103020102052041376d8231e6aedc29a19459e804b3770a250c3f367ac8d0f91e10842e8c906d126170746f733a3a6d657461646174615f7630e4010893010000000000000f4552525f5045524d495353494f4e530095010000000000000d4552525f454d455247454e4359009601000000000000104552525f534541534f4e5f454e444544009701000000000000144552525f534541534f4e5f4e4f545f5245534554009801000000000000114552525f534541534f4e5f414354495645009901000000000000104552525f534541534f4e5f5354415445009a01000000000000134552525f484152444341505f52454143484544009b01000000000000144552525f4e4f545f494e5f57484954454c4953540b6572726f7220636f64657300020322032303240501020522032303250326032405020205270b050205080329032a0b060108002c0b060108012d0b06010804030206220323032e03250326032405040206220323032e032503260324050001000102083c0b0011011112070d21030807082711132a020c0c0a0c0f000c0b0b0c0f010c0e0b0b0c0a0a010c090b010c080b0a0b090600000000000000000600000000000000000600000000000000000600000000000000000600000000000000000b08120338000c0d0b020a0d0f02150b0e0a0d1002140a0d1003140a0d1004140a0d1005140a0d1005140b0d10061412043801020100000001080b001116070e210307070427020200000001061117200305070127020301000102106111021112070c2103090b000107082711180c0611132a020c0811190c040a080f000a0011160c030c020b022e0b0338020c070b040b071e03250b00010b08010703270a081007140b062503310b00010b08010702270a081007140a01160a080f07150a080f080c050a0011130a0138030a0038040b080f000a00111607000600000000000000000600000000000000000600000000000000000600000000000000000b001116120338000c090b010a090f03150b050a091002140a091003140b091006141200380502040000010215a00311180c13111d0c2b11132a020c260b261007140c2c0b2c0a13250310055c11132a020c270a270f000c180b270f090c0f0a182e38060c010d010c1c0a1c2e3807032405550a180b1c380838090c22010c140a141003140a140f0a150a14100a140a2b180a140f04150a141006140a1410041411220a0f0a141002140a141003140a141004140a141005140b141006141201380a0d220c1c051f0b1c010b18010b0f01059f030b130c0a11132a020c2a0a2a0f000c1b0b2a0f090c120a1b2e38060c040d040c1f0a1f2e3807037205c3010a1b0b1f380838090c23010c170a171002140c0d0a171003140c0b0b0d0b0b11230a0a11230c090a0906000000000000000024038c0105b4010a090a170f0a150a090a2b180a170f04150b0a0b09170c0a0a171006140a1710041411220a120a171002140a171003140a171004140a171005140b171006141201380a05b6010b17010a0a0600000000000000002503bb0105c0010b1b010b120105c3010d230c1f056d0a0a0600000000000000002403c80105b30211132a020c280a280f000c190b280f090c100a192e38060c000d000c1d0a1d2e380703dc0105b3020a190b1d380838090c24010c150a151003140a15100a141706000000000000000011240a0a11230c200a200600000000000000002403f40105a4020a15100a140a20160a150f0a150a200a2b180c210a151004140a21160a150f04150b0a0b20170c0a0a151006140b2111220a100a151002140a151003140a151004140a151005140b151006141201380a05a6020b15010a0a0600000000000000002503ab0205b0020b19010b100105b3020d240c1d05d7010b0a0600000000000000002503b90206a1860100000000002711132a020c290a290f000c1a0b290f090c110a1a2e38060c020d020c1e0a1e2e380703cd020599030a1a0b1e380838090c25010c160a161003140c0c0a16100a140c0e0a0c0a0e2603e8020b1a010b16010b1101061127000000000000270b0c0b0e1706000000000000000011240a160f05150a161005140600000000000000002403f70205940311250c030e030a161006140a16100514110d0a110a161002140a161003140a161004140a161005140b161006141201380a0596030b16010d250c1e05c8020b1e010b1a010b1101020500000102211a11260c0211132a021007140c0311270c010b01030c05110b030b02230c000513090c000b0003160518110c05191104020601000102010f0b00110111021112070c210309070827070911281105070a1128020701000102010511132b02100714020801000102222511132a020f000c090b090c080a000c070b000c060b080b070600000000000000000600000000000000000600000000000000000600000000000000000600000000000000000b06120338000c0a0a0a1002140a0a1003140a0a100a140a0a1004140b0a100514020901000102232611132a020f000c03400500000000000000000c060a032e38060c000d000c040a042e3807031105200a030b04380838090c05010c020d060b0210061444050d050c04050c0b04010b03010b06020a01000024220b00110111250c0a0e0a0c02380b0c0111250c040e04380c0c0511250c060e06380d0c0711250c080e08380e0c090b020b010600000000000000000b070b090b0512022d02070b1128020b010000010b0b0011011112070d210308070827070c1128020c00000102274a11132a020c0a0a0a0f000c070b0a0f090c050a072e38060c000d000c0811250c010e010c0b0a082e3807031805410a070b0838080c030c020b022e0b03380f0c09010c060a0b0a061006140a06100314110d0a050a061002140a061003140a061004140a061005140b061006141201380a0d090c0805130b0b010b08010b07010b0501020d00000001050b000b010b023803020e010000010b0b0011011112070a210308070627070b1128020f010000010b0b0011011112070b210308070727070d1128021001000020090b00110111250c030e030b010b023803021101000020090b00110111250c030e030b010b02381002020002040300030103030304030502010202020303020000"; - let res = run_binary_test("sample_aptosd_swap", code); - assert!(res.is_ok(), "{:?}", res) -} - -#[cfg(feature = "address32")] -#[test] -fn sample_router() { - let code = "a11ceb0b050000000a01000e020e0603148f0104a3012805cb018f0207da03f90208d30640069307a00110b3082b0cde08db110000010101020003000400050006010a0401000100070000000008010202000000090102020000020b050600050c060700050d050200030e0207020000040f02070200000410020a0200000111020c01000612000d000113020f01000414020a0200000115100f0100031611120200000117130201000418020d0200000519140d00041a1500020000041b020a020000041c020d020000051d140d00031e111202000006080609070907080808090b0b0e0c080d0b0e080f0b100812080f0e0809090e130914091209160802040403060c030300030404043501010101010103030404040404040404040b000109000b000109000b000109000b000109000b000109000b000109000b000109010b000109010b0001090103030303030303030404030301010404010404040503030303030301060c0105010102090009010209010900010301090001020104010901010b0001090002060c0308060c070b00010900070b00010901030301030302030302050b000109000305040106060c010303030432010103030404040404040404040b000109000b000109000b000109000b000109000b000109000b000109000b000109010b000109010b000109010303030303030404030301010404010404040505030303030303030306726f7574657204636f696e067369676e657203616d6d0b636c6f625f6d61726b657403666565047574696c0873696d706c69667918737761705f636f696e5f666f725f65786163745f636f696e18737761705f65786163745f636f696e5f666f725f636f696e04436f696e0a616464726573735f6f660a6665655f65786973747316696e697469616c697a655f6665655f64656661756c740b706f6f6c5f6578697374730d6d61726b65745f657869737473086c6f745f73697a6508646563696d616c7303657870047a65726f0c6e5f6269645f6c6576656c730877697468647261771d636f696e5f737761705f636f696e5f666f725f65786163745f636f696e076465706f7369740b626573745f6269645f61750c73756274726163745f66656516706c6163655f6f726465725f666f725f726f757465720c6e5f61736b5f6c6576656c730b626573745f61736b5f6175076164645f6665651d636f696e5f737761705f65786163745f636f696e5f666f725f636f696e49661cd59c0b89440313af587bc99c3d38614d9a52479eb3f7c7c766d580c30b00000000000000000000000000000000000000000000000000000000000000010308c9000000000000000308ca000000000000000308c800000000000000030804000000000000000308070000000000000003086500000000000000030866000000000000000308030000000000000003080200000000000000030864000000000000000308ffffffffffffffff0308050000000000000003080100000000000000030868000000000000000308670000000000000003080600000000000000126170746f733a3a6d657461646174615f7630170104000000000000000c45544553545f4641494c4544000001000003190a000c030a010c040a01320000000000000000000000000000000022030905120b000a01190c020b010c000b020c0105040b030a001a0b040b001a020101040004ec030a0011030c310a311104200308050a0a0011053800030d0510080c03051238010c030b030c2d38020c2a38030c290a2d0b291f031d05fb0138040c27320a000000000000000000000000000000380535110a0c0e0600000000000000000c320600000000000000000c3438060c1a0a340a0223032f05340a320a01230c060536090c060b06033905eb01380706000000000000000021033e055f0a000a010a321738080c140b000d140d1a0a010a32170a020a34170906000000000000000006000000000000000038090c210c1d0a310b14380a0b320b21160c320b340b1d160c3405eb01380b0c130a310a130811110c120a020a3417350a0e180a121a340c090b090a272303750596010a000a010a321738080c180b000d180d1a0a010a32170a020a34170906000000000000000006000000000000000038090c230c1f0a310b18380a0b320b23160c320b340b1f160c3405eb010a0e0a1211000c250c2b0a000a010a321738080c190a000d190d1a0a010a32170a020a3417080b2b340b253438090c240c200a310b19380a0b320b24160c320b340b20160c340a340a022303c20105c7010a320a01230c0805c901090c080b0803cc0105ea010a020a3417350a0e180b121a340c0a0a000907060b13340b0a3200000000000000000000000000000000380c0c2e0c0d0b320b0d34160c320b340b2e34160c34052a0b320b012503f1010707270b340b022103f7010708270b310b1a380d05eb030a2d0a2a1f03800205b203380e0c28320a000000000000000000000000000000380f35110a0c0f0600000000000000000c330600000000000000000c3538060c1b0a350a02230392020597020a330a01230c04059902090c040b04039c0205a20338100600000000000000002103a10205a402080c0505aa020a020a35170a28230c050b0503ad0205ce020a000a010a331738080c150b000d150d1b0a010a33170a020a35170906000000000000000006000000000000000038090c220c1e0a310b15380a0b330b22160c330b350b1e160c3505a20338110c110a310a110811150c100b100a0f11000c260c2c0a000a010a331738080c160a000d160d1b0a010a33170a020a3517080b2c340b263438090c360c370a310b16380a0b330b36160c330b350b37160c350a350a02230381030586030a330a01230c07058803090c070b07038b0305a1030a000807060b11340a020a3517320000000000000000000000000000000038120c2f0c0b0b330b2f34160c330b350b0b34160c35058d020b330b012503a8030707270b350b022103ae030708270b310b1b380d05eb030b2d03b50305cd030a000a0138080c1738060c1c0b000d170d1c0b010b0209060000000000000000060000000000000000380901010a310b17380a0b310b1c380d05eb030b2a03d00305e7030b00080705070a0a02320000000000000000000000000000000038120c300c0c0b0c340b022103e0030707270b30340b012503eb030708270b0001070c27020201040016d1030a0011030c2b0a2b1104200308050a0a0011053800030d0510080c03051238010c030b030c2738020c2438030c230a270a231f031d05b70138040c21320a000000000000000000000000000000380535110a0c0a0600000000000000000c2d0600000000000000000c2f38060c160a2d0a0123032f05a70138070600000000000000002103340537080c04053d0a010a2d170a21230c040b040340055f0a000a010a2d1738080c100b000d100d160a010a2d170600000000000000000906000000000000000006000000000000000038130c1c0c190a2b0b10380a0b2d0b1c160c2d0b2f0b19160c2f05a701380b0c0f0a2b0a0f0811110c0e0b0e0a0a11000c1f0c250a000a010a2d1738080c140a000d140d160a010a2d17060000000000000000080b25340b1f3438130c310c330a2b0b14380a0b2d0b31160c2d0b2f0b33160c2f0a2d0a012303900105a6010a000907060b0f340a010a2d173200000000000000000000000000000000380c0c280c080b2d0b0834160c2d0b2f0b2834160c2f052a0b2d0b012103ad010707270b2f0b022603b3010708270b2b0b16380d05d0030a270b241f03bc01059403380e0c22320a000000000000000000000000000000380f35110a0c0b0600000000000000000c2e0600000000000000000c3038060c180a2e0a012303ce0105840338100600000000000000002103d30105f2010a000a010a2e1738080c150b000d150d180a010a2e170600000000000000000906000000000000000006000000000000000038130c1d0c1a0a2b0b15380a0b2e0b1d160c2e0b300b1a160c3005840338110c0d0a2b0a0d0811150c0c0a010a2e17350a0b180a0c1a340c050b050a222303880205a7020a000a010a2e1738080c110b000d110d180a010a2e170600000000000000000906000000000000000006000000000000000038130c1e0c1b0a2b0b11380a0b2e0b1e160c2e0b300b1b160c300584030a0b0a0c11000c200c260a000a010a2e1738080c120a000d120d180a010a2e17060000000000000000080b26340b203438130c320c340a2b0b12380a0b2e0b32160c2e0b300b34160c300a2e0a012303d1020583030a010a2e17350a0b180b0c1a340c060a000807060b0d340a06320000000000000000000000000000000038120c2a0c070a07340b062503ee020b0001061111000000000000270a2a340a010a2e172503f9020b0001062222000000000000270b2e0b2a34160c2e0b300b0734160c3005c9010b2e0b0121038a030707270b300b02260390030708270b2b0b18380d05d0030b2703970305b2030a000a0138080c1338060c170a000d130d170b010b0209060000000000000000060000000000000000381301010b0011030c2c0a2c0b17380d0b2c0b13380a05d0030b2303b50305cc030b000907050600000000000000000a013200000000000000000000000000000000380c0c290c090b09340b012103c5030707270b29340b022603d0030708270b0001070c270200"; - let res = run_binary_test("sample_router", code); - assert!(res.is_ok(), "{:?}", res) -} - -#[cfg(feature = "address32")] -#[test] -fn sample_pool() { - let code = "a11ceb0b050000000c010020022079039901c90204e2036605c804fd0507c50aa80c08ed166006cd17c101108e19bb020ac91bd4020c9d1eb3250dd043340000010101020103010401050106010701080109010a020b000c000d000e000f0010070000110600001206000013060000140600001508000000040000160800001708000018060000190600001a0600001b0600071d07000b2707000b3a0700053c040106010344040100010245080009470402030100010b480400084e0402030100010b6c07000e7807000e7b07000e7e07000e80010700001c000100001e020100001f030100002002010000210201000022020100002300010000240201000025040100002605010000280607000029080100002a090100002b0a0100002c0b01000658050d0008590f07020300045a101000085b1213020300045c101000035d15160100035e17010100035f1810010005601a0101060b611e1c000b621f06000b632010000b64212200096524010203000a66250101000867122a0203000a682c2d01000a672e2f01000967312a0203000b69320100096a3301020300036b340101000d6d393a000c6d393a0009593b070203000b6e1c3c000b6f3d10000b703d10000b713d0d0003723e16010007733f1d000d74393a000c74393a000975013302030408654401020300087501460203040176054701060b7706100008790f490203000e7a4b4a000e7c4c4d000f7d4e0101040e7f3951000e81010e5300100e1011121114141514161417191c231d1c17261728120e1e111f2b202b12302123232324141735173617371f1c201c27232c1417403023103031303111310e17453211320e32303345333733263319333533363328334035303511384d384a3851350e385303060c04030006060c040a050a080d0a080d0a0306060c04020303030b060c020a050a080d0a080d0a03030303030201060c01080e010103060c05080d02060c0407060c03030303030302060c05040b11010812070805070806070808010502050a0402060b150209000901090001030204080602070b15020900090109000107090101081202060c03010b1101090002070b110109000b1101090001060b1101090001080202070b100109000900070708050303070806070808080f0a080f01080f01080d0405080d080d030305080d080d0205080f03060c080f0301081402080f081403070b1302090009010900090102070a09000a0900010803030708050708060708080108041a06040604030b1101081205080d070a0405020307080503030303030307080803080f0a080f0b1302080f0814040302070a04010901010402060a090006090002010302070a0900030109000208000a0402070b130209000901090002060c0814010b13020900090102050b1101090001080c01080b0108092c03030303030816050405080d040302030a080f0303030503080d03070b1001080a020b11010812030307080503030303030303070806070b150204080603060816030503080f0a080f0503030303030602030303030302060b13020900090109000108160106081602070b1101090003010a0201080a2b03030303030816050405080d040302030a080f0303030503080d03070b1001080a020b110108120307080503030303030303070806070b150204080603060816030503080f0a080f08070805030303070806070808080f0a080f0d01050b1101081206080d060507080507040303070808080f0a080f0b1302080f081403070b15020900090109000901010801010b150209000901010b10010900080800030403060a040608060708080a0817010609010108170d05030305080d020303020a080f0304030405080d0a040a081701081802060c09000206080607080817030303020303030303020303030303020303030303030301081902060a0407080801081a04506f6f6c076163636f756e740a6170746f735f636f696e04636f696e056572726f72056576656e74067369676e657206737472696e67057461626c65117461626c655f776974685f6c656e67746806766563746f7205746f6b656e104578706f6e656e7469616c43757276650b4c696e6561724375727665054d6f64656c04566965770c436f6c6c656374696f6e49640f437265617465506f6f6c4576656e74144465706f736974436f696e506f6f6c4576656e74154465706f736974546f6b656e506f6f6c4576656e740d45646974506f6f6c4576656e740a4576656e7453746f726508506f6f6c4775696405506f6f6c730f52656d6f7665506f6f6c4576656e7409537761704576656e74155769746864726177436f696e506f6f6c4576656e74165769746864726177546f6b656e506f6f6c4576656e740b4465706f736974436f696e06537472696e670c4465706f736974546f6b656e0845646974506f6f6c0a52656d6f7665506f6f6c1753776170436f696e466f7253706563696669634e4654730f537761704e465473466f72436f696e0c5769746864726177436f696e0d5769746864726177546f6b656e066372656174650b696e69745f6d6f64756c650b546f6b656e4461746149640a69735f6572633131353515766965775f636f6c6c656374696f6e5f706f6f6c7309766965775f706f6f6c0f766965775f70726963655f63616c630f766965775f757365725f706f6f6c7312636f6c6c656374696f6e5f63726561746f720f636f6c6c656374696f6e5f6e616d650763726561746f7207706f6f6c5f69640a73706f745f70726963650563757276650564656c7461116c705f6665655f6d756c7469706c69657204747970650673656e646572136465706f7369745f636f696e5f616d6f756e7405636f696e7309746f6b656e5f69647307546f6b656e49640b6372656174655f706f6f6c0b4576656e7448616e646c650b72656d6f76655f706f6f6c126465706f7369745f746f6b656e5f706f6f6c116465706f7369745f636f696e5f706f6f6c1377697468647261775f746f6b656e5f706f6f6c1277697468647261775f636f696e5f706f6f6c09656469745f706f6f6c047377617004436f696e094170746f73436f696e06746f6b656e730f5461626c65576974684c656e67746805546f6b656e0c7472616e73616374696f6e7317746f74616c5f7472616e73616374696f6e5f76616c75650f6c705f6665655f6561726e696e677305636f756e7405706f6f6c73055461626c650a757365725f706f6f6c7310636f6c6c656374696f6e5f706f6f6c730b636f696e5f616d6f756e740c70726f746f636f6c5f6665650e70726f746f636f6c5f70617965650b726f79616c74795f6665650d726f79616c74795f7061796565066c705f6665651477697468647261775f636f696e5f616d6f756e740a616464726573735f6f6608636f6e7461696e7310696e76616c69645f617267756d656e740a626f72726f775f6d7574117065726d697373696f6e5f64656e696564087769746864726177056d657267650576616c75650a656d69745f6576656e74136372656174655f746f6b656e5f69645f726177146372656174655f746f6b656e5f646174615f69640a62616c616e63655f6f660e77697468647261775f746f6b656e0361646406617070656e640672656d6f766508696e6465785f6f660d6465706f7369745f746f6b656e0d64657374726f795f656d707479076465706f73697407526f79616c74790a676574427579496e666f0b6765745f726f79616c7479176765745f726f79616c74795f64656e6f6d696e61746f72156765745f726f79616c74795f6e756d657261746f72116765745f726f79616c74795f7061796565076578747261637404757466380b67657453656c6c496e666f036e6577106e65775f6576656e745f68616e646c65156765745f746f6b656e646174615f6d6178696d756d08506f6f6c5669657706626f72726f7709706f6f6c5f7669657713436f6c6c656374696f6e506f6f6c735669657715636f6c6c656374696f6e5f706f6f6c735f7669657704766965770d507269636543616c63566965770f70726963655f63616c635f766965770d55736572506f6f6c73566965770f757365725f706f6f6c735f76696577ecb44cec6276ddc5860a13b976262c786e06af8f7306923cabec17808dabf0940000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000303086600000000000000030869000000000000000308680000000000000003086e000000000000000308670000000000000003086a0000000000000003086b0000000000000003086c000000000000000308650000000000000003086d000000000000000520ecb44cec6276ddc5860a13b976262c786e06af8f7306923cabec17808dabf09403086400000000000000052000000000000000000000000000000000000000000000000000000000000000000a0204036275790a02050473656c6c126170746f733a3a6d657461646174615f7630a6020a6500000000000000074552525f4e554d006600000000000000134552525f444946465f434f4c4c454354494f4e006700000000000000124552525f4e4f545f45584953545f504f4f4c006800000000000000154552525f494e56414c49445f504f4f4c5f54595045006900000000000000154552525f494e56414c49445f504f4f4c5f41524753006a000000000000001c4552525f4e4f545f4558495453545f544f4b454e5f494e5f504f4f4c006b00000000000000124552525f4e4f545f484156455f544f4b454e006c00000000000000144552525f4e4f545f504f4f4c5f43524541544f52006d00000000000000184552525f504f4f4c5f4e4f545f454e4f5547485f434f494e006e00000000000000114552525f49535f313135355f544f4b454e000002022d052e080d0102092f0530042d052e080d3103320233033403350202020a360530042d052e080d37033803310332023303340303020a360530042d052e080d390a080f3803310332023303340304020730042d052e080d31033202330334030502083b0b100108013d0b100108093e0b100108033f0b10010802400b1001080c410b1001080b420b10010804430b1001080a06020e2f053103380b11010812460b1302080f08142d052e080d3202330334033502390a080f49034a044b030702014c040802034d0b15020408064f0b1502050a04500b150208000a0409020c2f0530042d052e080d3103320233033403350249034a044b030a0210360530042d052e080d310332023303390a080f510352035305540355055603380335080d0b020a360530042d052e080d5703380331033202330334030c020a360530042d052e080d390a080f380331033202330334030001000205080c61070a2a080c06070a2a050c040a0610000a00110f3800040d05160b00010b06010b040107041111270a0610010a013801041c05250b00010b06010b040107041111270b060f010a0138020c050a051002140a00110f210432053b0b00010b05010b040107071113270a000a0238030c030a050f030b0338040b040f040b00110f0b010a051005140a051006140b020a05100338050a051007140a051008140a051009140b05100a1412023806020101000205081bd801070a2a080c0a070a2a050c060a0a10000a00110f3800040d05160b00010b0a010b060107041111270a0a10010a013801041c05250b00010b0a010b060107041111270b0a0f010a0138020c09401c00000000000000000c0c0a091002140a00110f210434053d0b00010b09010b060107071113270e02410d0c080600000000000000000c070a070a082304b60105470e020a07420d0a09100521044f05580b00010b09010b060107001111270e030a07421d0a09100621046005690b00010b09010b060107001111270e020a07420d140e030a07421d140e040a07421d140e050a0742101411180c0b0e020a07420d140e030a07421d140e040a07421d141119110a20048c010595010b00010b09010b060107031111270d0c0a0b441c0a00110f0a0b111a0601000000000000002604a00105a9010b00010b09010b060107061111270a090f0b0a0b0a000b0b060100000000000000111b38070b07060100000000000000160c0705420a090f0c0a0c38080b060f0d0b00110f0b010a091005140a091006140b0c0a09100338050a091007140a091008140a091009140b09100a1412033809020201000205082759070a2a080c08070a2a050c060a0810000a00110f3800040d05160b00010b08010b060107041111270a0810010a013801041c05250b00010b08010b060107041111270b080f010a0138020c070a071002140b00110f21043205390b07010b060107071113270a020a070f08150a040a070f09150a030a070f07150a050a070f0a150b060f0e0b010a071005140b071006140b030b020b040b051204380a0203010002050829dc01070a2a080c17070a2a050c100a1710000a00110f3800040d05160b00010b17010b100107041111270a170f000a00110f380b0c1f0a1710010a0138010422052d0b1f010b00010b17010b100107041111270a170f010a01380c13060c150c1c0c1d010c1e0c160c0f0c0e0c0b0c0a0c1b0c090c180c0d0a0d0a00110f21044605510b1f010b00010b17010b100107071113270a1f0e010c062e0b06380d0c12010b1f0b12380e010b170f0f0a0a0a0b1200380f0c0c0a0c0e010c072e0b07380d0c13046d05760b00010b10010b0c0107051111270b0c0b13380e010600000000000000000c110e02410d0c14401c00000000000000000c1a0a110a142304a5010586010e020a11420d140e030a11421d140e040a11421d140e050a1142101411180c190d1a0a19441c0a000d1b0b19381011220b11060100000000000000160c110581010b1b38110e0938050c080a00110f0b0938120a100f100a0d0a010a0a0a0b0b1a0600000000000000000600000000000000003100060000000000000000060000000000000000120c38130a100f110b0d0a010a0a0a0b0b080600000000000000000600000000000000003100060000000000000000060000000000000000120b38140b100f120b00110f0b010b0a0b0b0b180b0e0b0f0b160b1e0b1d0b1c0b15120938150204010002050838d502070a2a080f010c2a070a2a050c210a2a0a010c102e0b103801040f05180b00010b2a010b210107041111270e02410d0c270b2a0a0138020c290a2910081431012104380a291007140a291009140a270a29100a14070b11250c0a0c090c080c070c060c1d055a0a29100814310221043f05480b00010b29010b210107021111270a291007140a291009140a270a29100a14070b11260c0a0c090c080c070c060c1d0b1d0b060b070b080b090b0a0c240c2b0c1f0c250c26310021046905720b00010b29010b21010701111127070c0600000000000000000600000000000000000c2f0c2d0c2e0b260a290f07150b250a290f0915401c00000000000000000c310a000a1f38030c1e0600000000000000000c220a220a272304f401058d010e020a22420d140e030a22421d140e040a22421d140e050a2242101411180c300a29100c0e3038160c2304a60105af010b00010b29010b210107051111270a290f0c0b233817010d310a30441c0a29100b0a30381804bd0105c6010b00010b29010b210107051111270a000a290f0b0a30381011220b3011280c0b0e0b0c2c0a2c11290c200a2c112a0c280b2c112b0c2e0a200600000000000000002204ef010a1f0a271a0b28180b201a0c2d0b2f0a2d160c2f0a2e0d1e0a2d381938120b22060100000000000000160c220588010a291013140a1f35160a290f13150a29101414060100000000000000160a290f1415070a0d1e0a2b381938120a290f030b1e38040b210f150c1c0b00110f0c0c0b010c0d0a291005140c0e0a291006140c0f0a291007140c110a291008140c120a291009140c130b310c140b1f0a2b160b2d160c150b2b0c160b2f0c170b2e0c180b240c19070d112d0c1a0b29100338050c1b0b1c0b0c0b0d0b0e0b0f0b110b120b130b140b150b16070a0b170b180b190b1b0b1a120a381a02050100020508418c03070a2a080f010c29070a2a050c200a290a010c102e0b103801040f05180b00010b29010b200107041111270e02410d0c250b290a0138020c280a2810081431012104380a281007140a281009140a250a28100a14070b112e0c0a0c090c080c070c060c1d055a0a28100814310221043f05480b00010b28010b200107021111270a281007140a281009140a250a28100a14070b112f0c0a0c090c080c070c060c1d0b1d0b060b070b080b090b0a0c220c2a0c270c230c24310021046905720b00010b28010b20010701111127070c0600000000000000000600000000000000000c2e0c2c0c2d401c00000000000000000c300a280f030a270a2a1738190c1e0600000000000000000c210a210a2523049a020588010e020a21420d0a281005210490010599010b00010b28010b200107001111270e030a21421d0a2810062104a10105aa010b00010b28010b200107001111270e020a21420d140e030a21421d140e040a21421d140e050a2142101411180c2f0e020a21420d140e030a21421d140e040a21421d141119110a2004cd0105d6010b00010b28010b200107031111270d300a2f441c0a00110f0a2f111a0601000000000000002604e10105ea010b00010b28010b200107061111270a280f0b0a2f0a000a2f060100000000000000111b38070b2f11280c0b0e0b0c2b0a2b11290c1f0a2b112a0c260b2b112b0c2d0a1f060000000000000000220495020a270a251a0b26180b1f1a0c2c0b2e0a2c160c2e0a2d0d1e0a2c381938120b21060100000000000000160c210583010a280f0c0a303808070a0a280f030a2a381938120b240a280f07150b230a280f09150a00110f0b1e38120a281013140a270a2a170b2e1735160a280f13150a28101414060100000000000000160a280f14150b200f150c1c0b00110f0c0c0b010c0d0a281005140c0e0a281006140c0f0a281007140c110a281008140c120a281009140c130b300c140b270a2a170a2c170c150b2a0c160b2c0c170b2d0c180b220c19070e112d0c1a0b28100338050c1b0b1c0b0c0b0d0b0e0b0f0b110b120b130b140b150b16070a0b170b180b190b1b0b1a120a381a020601000205082770070a2a080c05070a2a050c030a0510000a00110f3800040d05160b00010b05010b030107041111270a0510010a013801041c05250b00010b05010b030107041111270b050f010a0138020c040a041002140a00110f210432053b0b00010b04010b030107071113270a04100338050a02260442054b0b00010b04010b030107091111270a00110f0a040f030a02381938120b030f110b00110f0b010a041005140a041006140b020a04100338050a041007140a041008140a041009140b04100a14120b38140207010002050842a901070a2a080c0b070a2a050c060a0b10000a00110f3800040d05160b00010b0b010b060107041111270a0b10010a013801041c05250b00010b0b010b060107041111270b0b0f010a0138020c0a401c00000000000000000c0d0a0a1002140a00110f210434053d0b00010b0a010b060107071113270e02410d0c090600000000000000000c070a070a0923048b0105470e020a07420d140e030a07421d140e040a07421d140e050a0742101411180c0c0a0a100c0e0c38160c08046005690b00010b0a010b060107051111270a0a0f0c0b083817010d0d0a0c441c0a0a100b0a0c381804770580010b00010b0a010b060107051111270a000a0a0f0b0b0c381011220b07060100000000000000160c0705420b060f100b00110f0b010a0a1005140a0a1006140b0d0a0a100338050a0a1007140a0a1008140a0a1009140b0a100a14120c38130208010003050708439f02070a2a080c14070a2a070f160c11070a2a050c10381b0c170e02410d0c130a13060000000000000000240414051f0b00010b14010b11010b100107081111270e02060000000000000000420d0c0f0e03060000000000000000421d0c0e0a14100f0a0f140a0e141200381c20043a0a140f0f0a0f140a0e141200402b0000000000000000381d0a140f0f0a0f140a0e141200380f0a1114442b401c00000000000000000c160600000000000000000c120a120a132304b001054e0a0f0e020a12420d21045b0a0e0e030a12421d210c0b055d090c0b0b0b0460056f0b00010b14010b11010b10010b0f010b0e0107001111270e020a12420d140e030a12421d140e040a12421d141119110a20048001058f010b00010b14010b11010b10010b0f010b0e0107031111270e020a12420d140e030a12421d140e040a12421d140e050a1242101411180c150d160a15441c0d170a150a000b15060100000000000000111b38070b12060100000000000000160c1205490a100f0d0a00110f0a11140a0f140a0e140a160a060a070a010a080a09120338090a000a0638030c0d0a100f040a00110f0a11140a0f140a0e140a060b060a070a010a080a09120238060a140f010a11140a00110f0a070b0d0b170a0f140a0e140a010a080a090a0a0b1606000000000000000032000000000000000000000000000000000600000000000000001206381e0a140f000a00110f0c0c2e0b0c38002004ff010a140f000a00110f402b0000000000000000381f0b140f000a00110f380b0a1114442b0b100f170b00110f0a11140b0f140b0e140b070b010b080b090b0a120138200a11143201000000000000000000000000000000160b11150209000000011e0a0038213822382312082d080a00320000000000000000000000000000000012072d070a000a0038240a0038250a0038260a0038270a0038280a0038290a00382a0b00382b12052d05020a00000001060601000000000000000b0011342120020b010401084876070a2a080c090a010a0212000c030a09100f0a03381c040d05130b00010b0901063f05000000000000270a09100f0b03382c0c07404a00000000000000000c0a0a07412b0c060600000000000000000c040a040a0623046b05240a070a04422b140c050a0910010a053801042f05370b00010b09010b0701063f05000000000000270a0910010b05382d0c080d0a0a081002140a081007140a08100338050a081005140a081006140a081008140a081009140a08100a140a081018140a08100c140a081014140a081013140b081019141136444a0b04060100000000000000160c04051f0b09010b000b010b020b07140b0a1137382e020c010401084f40070a2a080c030a0310010a013801040905100b00010b030107041111270b0310010b01382d0c020b000a021002140a021007140a02100338050a021005140a021006140a021008140a021009140a02100a140a021018140a02100c140a021014140a021013140b021019141136382f020d0104005087010b010600000000000000002104380a020601000000000000002104150b030b040b050b06070b11250c090c080c070c180c170c16052b0b0206020000000000000021041a051f0b000107021111270b030b040b050b06070b11260c090c080c070c180c170c160b160b170b180b070b080b090c150c140c130c120c110c10056b0a020601000000000000002104490b030b040b050b06070b112e0c0f0c0e0c0d0c0c0c0b0c0a055f0b0206020000000000000021044e05530b000107021111270b030b040b050b06070b112f0c0f0c0e0c0d0c0c0c0b0c0a0b0a0b0b0b0c0b0d0b0e0b0f0c150c140c130c120c110c100b100b110b120b130b140b150c1a0c1d0c190c1b0c1c310021047a057e0b0001064705000000000000270b000b1c0b1b0b190b1d0b1a11393830020e01040108521b070a2a080c030a0310000a0138000409050f0b00010b0301063f05000000000000270b0310000a0138310c020b000b010b0214113a383202080108000600060205030604060506010606060706080603060a050205060802050405050501060c060b0507070005000609060d00"; - let res = run_binary_test("sample_pool", code); - assert!(res.is_ok(), "{:?}", res) -} - -#[cfg(feature = "address32")] -#[test] -fn sample_farming() { - let code = "a11ceb0b050000000e01001e021e2603447c04c00158059802c80107e003bb04089b08a00106bb09e101109c0b780a940c3e0bd20c040cd60cd10d0da71a080eaf1a060000010101020103010401050106000700080209020a0309030a0409040a000b0800000c0e0200010001000d0c0200010001011106000513070002230401000107240000000e000100000f0201020000032104050001220607000525090a000e26010c0200000c26010c0200000a26010c0200000427001200022812140100022915160100022a17010100082b150101000d2c1a010200000b2c1a01020000092c1a010200000d2d1b010200000b2d1b01020000092d1b01020000062e011400050b050d050e050f05100511060b060d060e060f06100611070b070d070e070f0710071109130a130b1309180a180b1809190a190b190c130c180d0b0e0b0f0b0d0d0e0d0f0d0d0e0d100e0e0e100f0e0f10100b110b120b01060c0009060c0303030303030303020c080302060c0501080301060803010c2001010101010101010101030303030308040b050108060b050109000b050109010708000b0102090009010b0102090009010b020209000901070b020209000901050c0a0b0102090009010503030303010a0201080402090009010101020901090002080609000209000806020806090102090108060105010900010302060c03010b0501090002050b0501090001090101080603060c030305060c03030303010b010209000901076661726d696e67076163636f756e7404636f696e107265736f757263655f6163636f756e74067369676e657206737472696e670974696d657374616d700d6661756365745f746f6b656e73076c656e64696e6706726f7574657204737761700a4d6f64756c65446174610c506f736974696f6e496e666f0f506f736974696f6e496e666f4465780b696e69745f6d6f64756c65166c657665726167655f7969656c645f6661726d696e670a7369676e65725f636170105369676e65724361706162696c697479086465785f6e616d6506537472696e670b7369676e65725f616464720a637265617465645f617406737461747573086c657665726167650e737570706c79416d6f756e745f780e737570706c79416d6f756e745f790e737570706c79416d6f756e745f7a0e626f72726f77416d6f756e745f780e626f72726f77416d6f756e745f790e626f72726f77416d6f756e745f7a10706f736974696f6e496e666f5f70616e10706f736974696f6e496e666f5f6c697110706f736974696f6e496e666f5f6175781d72657472696576655f7265736f757263655f6163636f756e745f6361701d6372656174655f7369676e65725f776974685f6361706162696c69747904436f696e03455a4d04757466380f69735f706169725f637265617465640a616464726573735f6f660762616c616e6365087769746864726177076465706f73697406626f72726f7710737761705f65786163745f696e7075740d6164645f6c69717569646974790b6e6f775f7365636f6e64734d63574ba8d90a5926e2866d8291e57683108a47b96d884232a871fe4feddf4100000000000000000000000000000000000000000000000000000000000000015e40a5bf7ab741784d3a99d96d8e2ddc6706ee06e5f509a3314a74c9e53746f5b30dd6a14dd7626ac8a37bc964914f07e3dc38d629637f1087f9f7186f1e0909c4911c40cf758ec21c0ebf0e547933ef6bb0f53ad581c08d2ecc7ad11364be1b030804000000000000000520f67b2452fd82768002ec6c28568713b9359a596585dc1a4bf85fce6b0e3754020308020000000000000003080300000000000000030801000000000000000308ffffffffffffffff0410e80300000000000000000000000000000308000000000000000005204d63574ba8d90a5926e2866d8291e57683108a47b96d884232a871fe4feddf41052000000000000000000000000000000000000000000000000000000000000000000a020c0b50616e63616b65537761700a020b0a4c6971756964537761700a020d0c4155582045786368616e6765126170746f733a3a6d657461646174615f763064030100000000000000164552524f525f4e4f545f435245415445445f50414952000200000000000000184552524f525f494e53554646494349454e545f4153534554000300000000000000174552524f525f494e56414c49445f504152414d5f4445580000020110080301020b1208041405150316011703180319031a031b031c031d030202031e0a0b0102090009011f0a0b010209000901200a0b010209000901020b010b00000000030c0b00070111020c020e0211030c010e010b0212002d000201010402000208ee04070a1104010a010600000000000000002103080536070a11040c183800030e0511080c09051338010c090b0903190b00010704273802031c051f080c0b052138030c0b0b0b03270b00010704273804032a052d080c0c052f38050c0c0b0c03350b0001070427059f010a0106010000000000000021033b0569070b11040c18380603410544080c0d054638070c0d0b0d034c0b00010704273808034f0552080c0e055438090c0e0b0e035a0b0001070427380a035d0560080c0f0562380b0c0f0b0f03680b0001070427059f010a0106020000000000000021036e059b01070c11040c18380c03740577080c100579380d0c100b10037f0b0001070427380e038201058501080c11058701380f0c110b11038d010b00010704273810039001059301080c1205950138110c120b12039f010b00010704270b000107032707082a000c1c0b1c100011030c220e2211080c210a030600000000000000002403ae0105c1010a00110838120c160b160a032403ba010b00010702270a000a0338130c1a07080b1a38140a040600000000000000002403c60105d9010a00110838150c170b170a042403d2010b00010702270a000a0438160c1b07080b1b38170a050600000000000000002403de0105f1010a00110838180c150b150a052403ea010b00010702270a000a0538190c1907080b19381a0a060600000000000000002403f60105f9010e220a06381b0a070600000000000000002403fe010581020e220a07381c0a0806000000000000000024038502070838120c26070838150c280a030a06160602000000000000001a0600000000000000002403940205bd020a010600000000000000002103990205a2020e220a030a06160602000000000000001a060000000000000000381d05bd020a010601000000000000002103a70205b0020e220a030a06160602000000000000001a060000000000000000381e05bd020a010602000000000000002103b50205bd020e220a030a06160602000000000000001a060000000000000000381f0a040a07160602000000000000001a0600000000000000002403c60205ef020a010600000000000000002103cb0205d4020e220a040a07160602000000000000001a060000000000000000382005ef020a010601000000000000002103d90205e2020e220a040a07160602000000000000001a060000000000000000382105ef020a010602000000000000002103e70205ef020e220a040a07160602000000000000001a06000000000000000038220a050a08160602000000000000001a0600000000000000002403f80205b9030a010600000000000000002103fd02058e030e220a050a08160602000000000000001a06000000000000000038230e220a050a08160602000000000000001a060000000000000000382405b9030a010601000000000000002103930305a4030e220a050a08160602000000000000001a06000000000000000038250e220a050a08160602000000000000001a060000000000000000382605b9030a010602000000000000002103a90305b9030e220a050a08160602000000000000001a06000000000000000038270e220a050a08160602000000000000001a0600000000000000003828070838120c25070838150c270a030b25160b26170c130a040b27160b28170c140a130600000000000000002403d00305d5030a14060000000000000000240c0a05d703090c0a0b0a03da0305eb040a010600000000000000002103df0305e6030e220b130b14060000000000000000060000000000000000382905fd030a010601000000000000002103eb0305f2030e220b130b14060000000000000000060000000000000000382a05fd030a010602000000000000002103f70305fd030e220b130b14060000000000000000060000000000000000382b0b0011080c240a213b002003850405ba040b180b241113080b020b030b040b050b060b070b0839010c1d401c000000000000000001401c0000000000000000401c0000000000000000401c000000000000000039000c1f0a0106000000000000000021039e0405a3040d1f36000b1d441c05b6040a010601000000000000002103a80405ad040d1f36010b1d441c05b6040b010602000000000000002103b20405b6040d1f36020b1d441c0e220b1f3f0005ea040b213c000c200b180b241113080b020b030b040b050b060b070b0839010c1e0a010600000000000000002103cf0405d4040b2036000b1e441c05ea040a010601000000000000002103d90405de040b2036010b1e441c05ea040b010602000000000000002103e30405e8040b2036020b1e441c05ea040b200105ed040b0001020000020002010202010b020b030b00"; - let res = run_binary_test("sample_farming", code); - assert!(res.is_ok(), "{:?}", res) -} - -#[cfg(feature = "address32")] -#[test] -fn sample_whitelist() { - let code = "a11ceb0b050000000c01000602060c03123a044c0805545707ab01660891024006d102988b0210e98d02d7010ac08f02090cc98f02a2470debd6020200000101010200030800020a04020301000100040001000005020100000603040000070201000008000100010b0203000204070102030002060a04020300020c010c02030402080d0e020300060607060806090602060c050001060c01050101020507080002050203070b010209000901090009010305070b010205020708000106080002060b0102090009010900010b01020502010b01020900090102070b01020900090109000109010977686974656c697374067369676e6572057461626c650957686974656c69737403616464086164645f6d616e7908636f6e7461696e730a696e697469616c697a650672656d6f766507656e7472696573055461626c650a616464726573735f6f66036e65774419523fdfa01e96fc7c18b67d900be8c863459e25383a5c661b9523631811c1000000000000000000000000000000000000000000000000000000000000000103082003000000000000030822030000000000000308210300000000000005204419523fdfa01e96fc7c18b67d900be8c863459e25383a5c661b9523631811c1052000000000000000000000000000000000000000000000000000000000000000000520000000000000000000000000000000000000000000000000000000000000000105200000000000000000000000000000000000000000000000000000000000000002052000000000000000000000000000000000000000000000000000000000000000030520000000000000000000000000000000000000000000000000000000000000000405200000000000000000000000000000000000000000000000000000000000000005052000000000000000000000000000000000000000000000000000000000000000060520000000000000000000000000000000000000000000000000000000000000000705200000000000000000000000000000000000000000000000000000000000000008052000000000000000000000000000000000000000000000000000000000000000090520000000000000000000000000000000000000000000000000000000000000001005200000000000000000000000000000000000000000000000000000000000000011052000000000000000000000000000000000000000000000000000000000000000120520000000000000000000000000000000000000000000000000000000000000001305200000000000000000000000000000000000000000000000000000000000000014052000000000000000000000000000000000000000000000000000000000000000150520000000000000000000000000000000000000000000000000000000000000001605200000000000000000000000000000000000000000000000000000000000000017052000000000000000000000000000000000000000000000000000000000000000180520000000000000000000000000000000000000000000000000000000000000001905200000000000000000000000000000000000000000000000000000000000000020052000000000000000000000000000000000000000000000000000000000000000210520000000000000000000000000000000000000000000000000000000000000002205200000000000000000000000000000000000000000000000000000000000000023052000000000000000000000000000000000000000000000000000000000000000240520000000000000000000000000000000000000000000000000000000000000002505200000000000000000000000000000000000000000000000000000000000000026052000000000000000000000000000000000000000000000000000000000000000270520000000000000000000000000000000000000000000000000000000000000002805200000000000000000000000000000000000000000000000000000000000000029052000000000000000000000000000000000000000000000000000000000000000300520000000000000000000000000000000000000000000000000000000000000003105200000000000000000000000000000000000000000000000000000000000000032052000000000000000000000000000000000000000000000000000000000000000330520000000000000000000000000000000000000000000000000000000000000003405200000000000000000000000000000000000000000000000000000000000000035052000000000000000000000000000000000000000000000000000000000000000360520000000000000000000000000000000000000000000000000000000000000003705200000000000000000000000000000000000000000000000000000000000000038052000000000000000000000000000000000000000000000000000000000000000390520000000000000000000000000000000000000000000000000000000000000004005200000000000000000000000000000000000000000000000000000000000000041052000000000000000000000000000000000000000000000000000000000000000420520000000000000000000000000000000000000000000000000000000000000004305200000000000000000000000000000000000000000000000000000000000000044052000000000000000000000000000000000000000000000000000000000000000450520000000000000000000000000000000000000000000000000000000000000004605200000000000000000000000000000000000000000000000000000000000000047052000000000000000000000000000000000000000000000000000000000000000480520000000000000000000000000000000000000000000000000000000000000004905200000000000000000000000000000000000000000000000000000000000000050052000000000000000000000000000000000000000000000000000000000000000510520000000000000000000000000000000000000000000000000000000000000005205200000000000000000000000000000000000000000000000000000000000000053052000000000000000000000000000000000000000000000000000000000000000540520000000000000000000000000000000000000000000000000000000000000005505200000000000000000000000000000000000000000000000000000000000000056052000000000000000000000000000000000000000000000000000000000000000570520000000000000000000000000000000000000000000000000000000000000005805200000000000000000000000000000000000000000000000000000000000000059052000000000000000000000000000000000000000000000000000000000000000600520000000000000000000000000000000000000000000000000000000000000006105200000000000000000000000000000000000000000000000000000000000000062052000000000000000000000000000000000000000000000000000000000000000630520000000000000000000000000000000000000000000000000000000000000006405200000000000000000000000000000000000000000000000000000000000000065052000000000000000000000000000000000000000000000000000000000000000660520000000000000000000000000000000000000000000000000000000000000006705200000000000000000000000000000000000000000000000000000000000000068052000000000000000000000000000000000000000000000000000000000000000690520000000000000000000000000000000000000000000000000000000000000007005200000000000000000000000000000000000000000000000000000000000000071052000000000000000000000000000000000000000000000000000000000000000720520000000000000000000000000000000000000000000000000000000000000007305200000000000000000000000000000000000000000000000000000000000000074052000000000000000000000000000000000000000000000000000000000000000750520000000000000000000000000000000000000000000000000000000000000007605200000000000000000000000000000000000000000000000000000000000000077052000000000000000000000000000000000000000000000000000000000000000780520000000000000000000000000000000000000000000000000000000000000007905200000000000000000000000000000000000000000000000000000000000000080052000000000000000000000000000000000000000000000000000000000000000810520000000000000000000000000000000000000000000000000000000000000008205200000000000000000000000000000000000000000000000000000000000000083052000000000000000000000000000000000000000000000000000000000000000840520000000000000000000000000000000000000000000000000000000000000008505200000000000000000000000000000000000000000000000000000000000000086052000000000000000000000000000000000000000000000000000000000000000870520000000000000000000000000000000000000000000000000000000000000008805200000000000000000000000000000000000000000000000000000000000000089052000000000000000000000000000000000000000000000000000000000000000900520000000000000000000000000000000000000000000000000000000000000009105200000000000000000000000000000000000000000000000000000000000000092052000000000000000000000000000000000000000000000000000000000000000930520000000000000000000000000000000000000000000000000000000000000009405200000000000000000000000000000000000000000000000000000000000000095052000000000000000000000000000000000000000000000000000000000000000960520000000000000000000000000000000000000000000000000000000000000009705200000000000000000000000000000000000000000000000000000000000000098052000000000000000000000000000000000000000000000000000000000000000990520000000000000000000000000000000000000000000000000000000000000010005200000000000000000000000000000000000000000000000000000000000000101052000000000000000000000000000000000000000000000000000000000000001020520000000000000000000000000000000000000000000000000000000000000010305200000000000000000000000000000000000000000000000000000000000000104052000000000000000000000000000000000000000000000000000000000000001050520000000000000000000000000000000000000000000000000000000000000010605200000000000000000000000000000000000000000000000000000000000000107052000000000000000000000000000000000000000000000000000000000000001080520000000000000000000000000000000000000000000000000000000000000010905200000000000000000000000000000000000000000000000000000000000000110052000000000000000000000000000000000000000000000000000000000000001110520000000000000000000000000000000000000000000000000000000000000011205200000000000000000000000000000000000000000000000000000000000000113052000000000000000000000000000000000000000000000000000000000000001140520000000000000000000000000000000000000000000000000000000000000011505200000000000000000000000000000000000000000000000000000000000000116052000000000000000000000000000000000000000000000000000000000000001170520000000000000000000000000000000000000000000000000000000000000011805200000000000000000000000000000000000000000000000000000000000000119052000000000000000000000000000000000000000000000000000000000000001200520000000000000000000000000000000000000000000000000000000000000012105200000000000000000000000000000000000000000000000000000000000000122052000000000000000000000000000000000000000000000000000000000000001230520000000000000000000000000000000000000000000000000000000000000012405200000000000000000000000000000000000000000000000000000000000000125052000000000000000000000000000000000000000000000000000000000000001260520000000000000000000000000000000000000000000000000000000000000012705200000000000000000000000000000000000000000000000000000000000000128052000000000000000000000000000000000000000000000000000000000000001290520000000000000000000000000000000000000000000000000000000000000013005200000000000000000000000000000000000000000000000000000000000000131052000000000000000000000000000000000000000000000000000000000000001320520000000000000000000000000000000000000000000000000000000000000013305200000000000000000000000000000000000000000000000000000000000000134052000000000000000000000000000000000000000000000000000000000000001350520000000000000000000000000000000000000000000000000000000000000013605200000000000000000000000000000000000000000000000000000000000000137052000000000000000000000000000000000000000000000000000000000000001380520000000000000000000000000000000000000000000000000000000000000013905200000000000000000000000000000000000000000000000000000000000000140052000000000000000000000000000000000000000000000000000000000000001410520000000000000000000000000000000000000000000000000000000000000014205200000000000000000000000000000000000000000000000000000000000000143052000000000000000000000000000000000000000000000000000000000000001440520000000000000000000000000000000000000000000000000000000000000014505200000000000000000000000000000000000000000000000000000000000000146052000000000000000000000000000000000000000000000000000000000000001470520000000000000000000000000000000000000000000000000000000000000014805200000000000000000000000000000000000000000000000000000000000000149052000000000000000000000000000000000000000000000000000000000000001500520000000000000000000000000000000000000000000000000000000000000015105200000000000000000000000000000000000000000000000000000000000000152052000000000000000000000000000000000000000000000000000000000000001530520000000000000000000000000000000000000000000000000000000000000015405200000000000000000000000000000000000000000000000000000000000000155052000000000000000000000000000000000000000000000000000000000000001560520000000000000000000000000000000000000000000000000000000000000015705200000000000000000000000000000000000000000000000000000000000000158052000000000000000000000000000000000000000000000000000000000000001590520000000000000000000000000000000000000000000000000000000000000016005200000000000000000000000000000000000000000000000000000000000000161052000000000000000000000000000000000000000000000000000000000000001620520000000000000000000000000000000000000000000000000000000000000016305200000000000000000000000000000000000000000000000000000000000000164052000000000000000000000000000000000000000000000000000000000000001650520000000000000000000000000000000000000000000000000000000000000016605200000000000000000000000000000000000000000000000000000000000000167052000000000000000000000000000000000000000000000000000000000000001680520000000000000000000000000000000000000000000000000000000000000016905200000000000000000000000000000000000000000000000000000000000000170052000000000000000000000000000000000000000000000000000000000000001710520000000000000000000000000000000000000000000000000000000000000017205200000000000000000000000000000000000000000000000000000000000000173052000000000000000000000000000000000000000000000000000000000000001740520000000000000000000000000000000000000000000000000000000000000017505200000000000000000000000000000000000000000000000000000000000000176052000000000000000000000000000000000000000000000000000000000000001770520000000000000000000000000000000000000000000000000000000000000017805200000000000000000000000000000000000000000000000000000000000000179052000000000000000000000000000000000000000000000000000000000000001800520000000000000000000000000000000000000000000000000000000000000018105200000000000000000000000000000000000000000000000000000000000000182052000000000000000000000000000000000000000000000000000000000000001830520000000000000000000000000000000000000000000000000000000000000018405200000000000000000000000000000000000000000000000000000000000000185052000000000000000000000000000000000000000000000000000000000000001860520000000000000000000000000000000000000000000000000000000000000018705200000000000000000000000000000000000000000000000000000000000000188052000000000000000000000000000000000000000000000000000000000000001890520000000000000000000000000000000000000000000000000000000000000019005200000000000000000000000000000000000000000000000000000000000000191052000000000000000000000000000000000000000000000000000000000000001920520000000000000000000000000000000000000000000000000000000000000019305200000000000000000000000000000000000000000000000000000000000000194052000000000000000000000000000000000000000000000000000000000000001950520000000000000000000000000000000000000000000000000000000000000019605200000000000000000000000000000000000000000000000000000000000000197052000000000000000000000000000000000000000000000000000000000000001980520000000000000000000000000000000000000000000000000000000000000019905200000000000000000000000000000000000000000000000000000000000000200052000000000000000000000000000000000000000000000000000000000000002010520000000000000000000000000000000000000000000000000000000000000020205200000000000000000000000000000000000000000000000000000000000000203052000000000000000000000000000000000000000000000000000000000000002040520000000000000000000000000000000000000000000000000000000000000020505200000000000000000000000000000000000000000000000000000000000000206052000000000000000000000000000000000000000000000000000000000000002070520000000000000000000000000000000000000000000000000000000000000020805200000000000000000000000000000000000000000000000000000000000000209052000000000000000000000000000000000000000000000000000000000000002100520000000000000000000000000000000000000000000000000000000000000021105200000000000000000000000000000000000000000000000000000000000000212052000000000000000000000000000000000000000000000000000000000000002130520000000000000000000000000000000000000000000000000000000000000021405200000000000000000000000000000000000000000000000000000000000000215052000000000000000000000000000000000000000000000000000000000000002160520000000000000000000000000000000000000000000000000000000000000021705200000000000000000000000000000000000000000000000000000000000000218052000000000000000000000000000000000000000000000000000000000000002190520000000000000000000000000000000000000000000000000000000000000022005200000000000000000000000000000000000000000000000000000000000000221052000000000000000000000000000000000000000000000000000000000000002220520000000000000000000000000000000000000000000000000000000000000022305200000000000000000000000000000000000000000000000000000000000000224052000000000000000000000000000000000000000000000000000000000000002250520000000000000000000000000000000000000000000000000000000000000022605200000000000000000000000000000000000000000000000000000000000000227052000000000000000000000000000000000000000000000000000000000000002280520000000000000000000000000000000000000000000000000000000000000022905200000000000000000000000000000000000000000000000000000000000000230052000000000000000000000000000000000000000000000000000000000000002310520000000000000000000000000000000000000000000000000000000000000023205200000000000000000000000000000000000000000000000000000000000000233052000000000000000000000000000000000000000000000000000000000000002340520000000000000000000000000000000000000000000000000000000000000023505200000000000000000000000000000000000000000000000000000000000000236052000000000000000000000000000000000000000000000000000000000000002370520000000000000000000000000000000000000000000000000000000000000023805200000000000000000000000000000000000000000000000000000000000000239052000000000000000000000000000000000000000000000000000000000000002400520000000000000000000000000000000000000000000000000000000000000024105200000000000000000000000000000000000000000000000000000000000000242052000000000000000000000000000000000000000000000000000000000000002430520000000000000000000000000000000000000000000000000000000000000024405200000000000000000000000000000000000000000000000000000000000000245052000000000000000000000000000000000000000000000000000000000000002460520000000000000000000000000000000000000000000000000000000000000024705200000000000000000000000000000000000000000000000000000000000000248052000000000000000000000000000000000000000000000000000000000000002490520000000000000000000000000000000000000000000000000000000000000025005200000000000000000000000000000000000000000000000000000000000000251052000000000000000000000000000000000000000000000000000000000000002520520000000000000000000000000000000000000000000000000000000000000025305200000000000000000000000000000000000000000000000000000000000000254052000000000000000000000000000000000000000000000000000000000000002550520000000000000000000000000000000000000000000000000000000000000025605200000000000000000000000000000000000000000000000000000000000000257052000000000000000000000000000000000000000000000000000000000000002580520000000000000000000000000000000000000000000000000000000000000025905200000000000000000000000000000000000000000000000000000000000000260052000000000000000000000000000000000000000000000000000000000000002610520000000000000000000000000000000000000000000000000000000000000026205200000000000000000000000000000000000000000000000000000000000000263052000000000000000000000000000000000000000000000000000000000000002640520000000000000000000000000000000000000000000000000000000000000026505200000000000000000000000000000000000000000000000000000000000000266052000000000000000000000000000000000000000000000000000000000000002670520000000000000000000000000000000000000000000000000000000000000026805200000000000000000000000000000000000000000000000000000000000000269052000000000000000000000000000000000000000000000000000000000000002700520000000000000000000000000000000000000000000000000000000000000027105200000000000000000000000000000000000000000000000000000000000000272052000000000000000000000000000000000000000000000000000000000000002730520000000000000000000000000000000000000000000000000000000000000027405200000000000000000000000000000000000000000000000000000000000000275052000000000000000000000000000000000000000000000000000000000000002760520000000000000000000000000000000000000000000000000000000000000027705200000000000000000000000000000000000000000000000000000000000000278052000000000000000000000000000000000000000000000000000000000000002790520000000000000000000000000000000000000000000000000000000000000028005200000000000000000000000000000000000000000000000000000000000000281052000000000000000000000000000000000000000000000000000000000000002820520000000000000000000000000000000000000000000000000000000000000028305200000000000000000000000000000000000000000000000000000000000000284052000000000000000000000000000000000000000000000000000000000000002850520000000000000000000000000000000000000000000000000000000000000028605200000000000000000000000000000000000000000000000000000000000000287052000000000000000000000000000000000000000000000000000000000000002880520000000000000000000000000000000000000000000000000000000000000028905200000000000000000000000000000000000000000000000000000000000000290052000000000000000000000000000000000000000000000000000000000000002910520000000000000000000000000000000000000000000000000000000000000029205200000000000000000000000000000000000000000000000000000000000000293052000000000000000000000000000000000000000000000000000000000000002940520000000000000000000000000000000000000000000000000000000000000029505200000000000000000000000000000000000000000000000000000000000000296052000000000000000000000000000000000000000000000000000000000000002970520000000000000000000000000000000000000000000000000000000000000029805200000000000000000000000000000000000000000000000000000000000000299052000000000000000000000000000000000000000000000000000000000000003000520000000000000000000000000000000000000000000000000000000000000030105200000000000000000000000000000000000000000000000000000000000000302052000000000000000000000000000000000000000000000000000000000000003030520000000000000000000000000000000000000000000000000000000000000030405200000000000000000000000000000000000000000000000000000000000000305052000000000000000000000000000000000000000000000000000000000000003060520000000000000000000000000000000000000000000000000000000000000030705200000000000000000000000000000000000000000000000000000000000000308052000000000000000000000000000000000000000000000000000000000000003090520000000000000000000000000000000000000000000000000000000000000031005200000000000000000000000000000000000000000000000000000000000000311052000000000000000000000000000000000000000000000000000000000000003120520000000000000000000000000000000000000000000000000000000000000031305200000000000000000000000000000000000000000000000000000000000000314052000000000000000000000000000000000000000000000000000000000000003150520000000000000000000000000000000000000000000000000000000000000031605200000000000000000000000000000000000000000000000000000000000000317052000000000000000000000000000000000000000000000000000000000000003180520000000000000000000000000000000000000000000000000000000000000031905200000000000000000000000000000000000000000000000000000000000000320052000000000000000000000000000000000000000000000000000000000000003210520000000000000000000000000000000000000000000000000000000000000032205200000000000000000000000000000000000000000000000000000000000000323052000000000000000000000000000000000000000000000000000000000000003240520000000000000000000000000000000000000000000000000000000000000032505200000000000000000000000000000000000000000000000000000000000000326052000000000000000000000000000000000000000000000000000000000000003270520000000000000000000000000000000000000000000000000000000000000032805200000000000000000000000000000000000000000000000000000000000000329052000000000000000000000000000000000000000000000000000000000000003300520000000000000000000000000000000000000000000000000000000000000033105200000000000000000000000000000000000000000000000000000000000000332052000000000000000000000000000000000000000000000000000000000000003330520000000000000000000000000000000000000000000000000000000000000033405200000000000000000000000000000000000000000000000000000000000000335052000000000000000000000000000000000000000000000000000000000000003360520000000000000000000000000000000000000000000000000000000000000033705200000000000000000000000000000000000000000000000000000000000000338052000000000000000000000000000000000000000000000000000000000000003390520000000000000000000000000000000000000000000000000000000000000034005200000000000000000000000000000000000000000000000000000000000000341052000000000000000000000000000000000000000000000000000000000000003420520000000000000000000000000000000000000000000000000000000000000034305200000000000000000000000000000000000000000000000000000000000000344052000000000000000000000000000000000000000000000000000000000000003450520000000000000000000000000000000000000000000000000000000000000034605200000000000000000000000000000000000000000000000000000000000000347052000000000000000000000000000000000000000000000000000000000000003480520000000000000000000000000000000000000000000000000000000000000034905200000000000000000000000000000000000000000000000000000000000000350052000000000000000000000000000000000000000000000000000000000000003510520000000000000000000000000000000000000000000000000000000000000035205200000000000000000000000000000000000000000000000000000000000000353052000000000000000000000000000000000000000000000000000000000000003540520000000000000000000000000000000000000000000000000000000000000035505200000000000000000000000000000000000000000000000000000000000000356052000000000000000000000000000000000000000000000000000000000000003570520000000000000000000000000000000000000000000000000000000000000035805200000000000000000000000000000000000000000000000000000000000000359052000000000000000000000000000000000000000000000000000000000000003600520000000000000000000000000000000000000000000000000000000000000036105200000000000000000000000000000000000000000000000000000000000000362052000000000000000000000000000000000000000000000000000000000000003630520000000000000000000000000000000000000000000000000000000000000036405200000000000000000000000000000000000000000000000000000000000000365052000000000000000000000000000000000000000000000000000000000000003660520000000000000000000000000000000000000000000000000000000000000036705200000000000000000000000000000000000000000000000000000000000000368052000000000000000000000000000000000000000000000000000000000000003690520000000000000000000000000000000000000000000000000000000000000037005200000000000000000000000000000000000000000000000000000000000000371052000000000000000000000000000000000000000000000000000000000000003720520000000000000000000000000000000000000000000000000000000000000037305200000000000000000000000000000000000000000000000000000000000000374052000000000000000000000000000000000000000000000000000000000000003750520000000000000000000000000000000000000000000000000000000000000037605200000000000000000000000000000000000000000000000000000000000000377052000000000000000000000000000000000000000000000000000000000000003780520000000000000000000000000000000000000000000000000000000000000037905200000000000000000000000000000000000000000000000000000000000000380052000000000000000000000000000000000000000000000000000000000000003810520000000000000000000000000000000000000000000000000000000000000038205200000000000000000000000000000000000000000000000000000000000000383052000000000000000000000000000000000000000000000000000000000000003840520000000000000000000000000000000000000000000000000000000000000038505200000000000000000000000000000000000000000000000000000000000000386052000000000000000000000000000000000000000000000000000000000000003870520000000000000000000000000000000000000000000000000000000000000038805200000000000000000000000000000000000000000000000000000000000000389052000000000000000000000000000000000000000000000000000000000000003900520000000000000000000000000000000000000000000000000000000000000039105200000000000000000000000000000000000000000000000000000000000000392052000000000000000000000000000000000000000000000000000000000000003930520000000000000000000000000000000000000000000000000000000000000039405200000000000000000000000000000000000000000000000000000000000000395052000000000000000000000000000000000000000000000000000000000000003960520000000000000000000000000000000000000000000000000000000000000039705200000000000000000000000000000000000000000000000000000000000000398052000000000000000000000000000000000000000000000000000000000000003990520000000000000000000000000000000000000000000000000000000000000040005200000000000000000000000000000000000000000000000000000000000000401052000000000000000000000000000000000000000000000000000000000000004020520000000000000000000000000000000000000000000000000000000000000040305200000000000000000000000000000000000000000000000000000000000000404052000000000000000000000000000000000000000000000000000000000000004050520000000000000000000000000000000000000000000000000000000000000040605200000000000000000000000000000000000000000000000000000000000000407052000000000000000000000000000000000000000000000000000000000000004080520000000000000000000000000000000000000000000000000000000000000040905200000000000000000000000000000000000000000000000000000000000000410052000000000000000000000000000000000000000000000000000000000000004110520000000000000000000000000000000000000000000000000000000000000041205200000000000000000000000000000000000000000000000000000000000000413052000000000000000000000000000000000000000000000000000000000000004140520000000000000000000000000000000000000000000000000000000000000041505200000000000000000000000000000000000000000000000000000000000000416052000000000000000000000000000000000000000000000000000000000000004170520000000000000000000000000000000000000000000000000000000000000041805200000000000000000000000000000000000000000000000000000000000000419052000000000000000000000000000000000000000000000000000000000000004200520000000000000000000000000000000000000000000000000000000000000042105200000000000000000000000000000000000000000000000000000000000000422052000000000000000000000000000000000000000000000000000000000000004230520000000000000000000000000000000000000000000000000000000000000042405200000000000000000000000000000000000000000000000000000000000000425052000000000000000000000000000000000000000000000000000000000000004260520000000000000000000000000000000000000000000000000000000000000042705200000000000000000000000000000000000000000000000000000000000000428052000000000000000000000000000000000000000000000000000000000000004290520000000000000000000000000000000000000000000000000000000000000043005200000000000000000000000000000000000000000000000000000000000000431052000000000000000000000000000000000000000000000000000000000000004320520000000000000000000000000000000000000000000000000000000000000043305200000000000000000000000000000000000000000000000000000000000000434052000000000000000000000000000000000000000000000000000000000000004350520000000000000000000000000000000000000000000000000000000000000043605200000000000000000000000000000000000000000000000000000000000000437052000000000000000000000000000000000000000000000000000000000000004380520000000000000000000000000000000000000000000000000000000000000043905200000000000000000000000000000000000000000000000000000000000000440052000000000000000000000000000000000000000000000000000000000000004410520000000000000000000000000000000000000000000000000000000000000044205200000000000000000000000000000000000000000000000000000000000000443052000000000000000000000000000000000000000000000000000000000000004440520000000000000000000000000000000000000000000000000000000000000044505200000000000000000000000000000000000000000000000000000000000000446052000000000000000000000000000000000000000000000000000000000000004470520000000000000000000000000000000000000000000000000000000000000044805200000000000000000000000000000000000000000000000000000000000000449052000000000000000000000000000000000000000000000000000000000000004500520000000000000000000000000000000000000000000000000000000000000045105200000000000000000000000000000000000000000000000000000000000000452052000000000000000000000000000000000000000000000000000000000000004530520000000000000000000000000000000000000000000000000000000000000045405200000000000000000000000000000000000000000000000000000000000000455052000000000000000000000000000000000000000000000000000000000000004560520000000000000000000000000000000000000000000000000000000000000045705200000000000000000000000000000000000000000000000000000000000000458052000000000000000000000000000000000000000000000000000000000000004590520000000000000000000000000000000000000000000000000000000000000046005200000000000000000000000000000000000000000000000000000000000000461052000000000000000000000000000000000000000000000000000000000000004620520000000000000000000000000000000000000000000000000000000000000046305200000000000000000000000000000000000000000000000000000000000000464052000000000000000000000000000000000000000000000000000000000000004650520000000000000000000000000000000000000000000000000000000000000046605200000000000000000000000000000000000000000000000000000000000000467052000000000000000000000000000000000000000000000000000000000000004680520000000000000000000000000000000000000000000000000000000000000046905200000000000000000000000000000000000000000000000000000000000000470052000000000000000000000000000000000000000000000000000000000000004710520000000000000000000000000000000000000000000000000000000000000047205200000000000000000000000000000000000000000000000000000000000000473052000000000000000000000000000000000000000000000000000000000000004740520000000000000000000000000000000000000000000000000000000000000047505200000000000000000000000000000000000000000000000000000000000000476052000000000000000000000000000000000000000000000000000000000000004770520000000000000000000000000000000000000000000000000000000000000047805200000000000000000000000000000000000000000000000000000000000000479052000000000000000000000000000000000000000000000000000000000000004800520000000000000000000000000000000000000000000000000000000000000048105200000000000000000000000000000000000000000000000000000000000000482052000000000000000000000000000000000000000000000000000000000000004830520000000000000000000000000000000000000000000000000000000000000048405200000000000000000000000000000000000000000000000000000000000000485052000000000000000000000000000000000000000000000000000000000000004860520000000000000000000000000000000000000000000000000000000000000048705200000000000000000000000000000000000000000000000000000000000000488052000000000000000000000000000000000000000000000000000000000000004890520000000000000000000000000000000000000000000000000000000000000049005200000000000000000000000000000000000000000000000000000000000000491052000000000000000000000000000000000000000000000000000000000000004920520000000000000000000000000000000000000000000000000000000000000049305200000000000000000000000000000000000000000000000000000000000000494052000000000000000000000000000000000000000000000000000000000000004950520000000000000000000000000000000000000000000000000000000000000049605200000000000000000000000000000000000000000000000000000000000000497052000000000000000000000000000000000000000000000000000000000000004980520000000000000000000000000000000000000000000000000000000000000049905200000000000000000000000000000000000000000000000000000000000000500052000000000000000000000000000000000000000000000000000000000000005010520000000000000000000000000000000000000000000000000000000000000050205200000000000000000000000000000000000000000000000000000000000000503052000000000000000000000000000000000000000000000000000000000000005040520000000000000000000000000000000000000000000000000000000000000050505200000000000000000000000000000000000000000000000000000000000000506052000000000000000000000000000000000000000000000000000000000000005070520000000000000000000000000000000000000000000000000000000000000050805200000000000000000000000000000000000000000000000000000000000000509052000000000000000000000000000000000000000000000000000000000000005100520000000000000000000000000000000000000000000000000000000000000051105200000000000000000000000000000000000000000000000000000000000000512052000000000000000000000000000000000000000000000000000000000000005130520000000000000000000000000000000000000000000000000000000000000051405200000000000000000000000000000000000000000000000000000000000000515052000000000000000000000000000000000000000000000000000000000000005160520000000000000000000000000000000000000000000000000000000000000051705200000000000000000000000000000000000000000000000000000000000000518052000000000000000000000000000000000000000000000000000000000000005190520000000000000000000000000000000000000000000000000000000000000052005200000000000000000000000000000000000000000000000000000000000000521052000000000000000000000000000000000000000000000000000000000000005220520000000000000000000000000000000000000000000000000000000000000052305200000000000000000000000000000000000000000000000000000000000000524052000000000000000000000000000000000000000000000000000000000000005250520000000000000000000000000000000000000000000000000000000000000052605200000000000000000000000000000000000000000000000000000000000000527052000000000000000000000000000000000000000000000000000000000000005280520000000000000000000000000000000000000000000000000000000000000052905200000000000000000000000000000000000000000000000000000000000000530052000000000000000000000000000000000000000000000000000000000000005310520000000000000000000000000000000000000000000000000000000000000053205200000000000000000000000000000000000000000000000000000000000000533052000000000000000000000000000000000000000000000000000000000000005340520000000000000000000000000000000000000000000000000000000000000053505200000000000000000000000000000000000000000000000000000000000000536052000000000000000000000000000000000000000000000000000000000000005370520000000000000000000000000000000000000000000000000000000000000053805200000000000000000000000000000000000000000000000000000000000000539052000000000000000000000000000000000000000000000000000000000000005400520000000000000000000000000000000000000000000000000000000000000054105200000000000000000000000000000000000000000000000000000000000000542052000000000000000000000000000000000000000000000000000000000000005430520000000000000000000000000000000000000000000000000000000000000054405200000000000000000000000000000000000000000000000000000000000000545052000000000000000000000000000000000000000000000000000000000000005460520000000000000000000000000000000000000000000000000000000000000054705200000000000000000000000000000000000000000000000000000000000000548052000000000000000000000000000000000000000000000000000000000000005490520000000000000000000000000000000000000000000000000000000000000055005200000000000000000000000000000000000000000000000000000000000000551052000000000000000000000000000000000000000000000000000000000000005520520000000000000000000000000000000000000000000000000000000000000055305200000000000000000000000000000000000000000000000000000000000000554052000000000000000000000000000000000000000000000000000000000000005550520000000000000000000000000000000000000000000000000000000000000055605200000000000000000000000000000000000000000000000000000000000000557052000000000000000000000000000000000000000000000000000000000000005580520000000000000000000000000000000000000000000000000000000000000055905200000000000000000000000000000000000000000000000000000000000000560052000000000000000000000000000000000000000000000000000000000000005610520000000000000000000000000000000000000000000000000000000000000056205200000000000000000000000000000000000000000000000000000000000000563052000000000000000000000000000000000000000000000000000000000000005640520000000000000000000000000000000000000000000000000000000000000056505200000000000000000000000000000000000000000000000000000000000000566052000000000000000000000000000000000000000000000000000000000000005670520000000000000000000000000000000000000000000000000000000000000056805200000000000000000000000000000000000000000000000000000000000000569052000000000000000000000000000000000000000000000000000000000000005700520000000000000000000000000000000000000000000000000000000000000057105200000000000000000000000000000000000000000000000000000000000000572052000000000000000000000000000000000000000000000000000000000000005730520000000000000000000000000000000000000000000000000000000000000057405200000000000000000000000000000000000000000000000000000000000000575052000000000000000000000000000000000000000000000000000000000000005760520000000000000000000000000000000000000000000000000000000000000057705200000000000000000000000000000000000000000000000000000000000000578052000000000000000000000000000000000000000000000000000000000000005790520000000000000000000000000000000000000000000000000000000000000058005200000000000000000000000000000000000000000000000000000000000000581052000000000000000000000000000000000000000000000000000000000000005820520000000000000000000000000000000000000000000000000000000000000058305200000000000000000000000000000000000000000000000000000000000000584052000000000000000000000000000000000000000000000000000000000000005850520000000000000000000000000000000000000000000000000000000000000058605200000000000000000000000000000000000000000000000000000000000000587052000000000000000000000000000000000000000000000000000000000000005880520000000000000000000000000000000000000000000000000000000000000058905200000000000000000000000000000000000000000000000000000000000000590052000000000000000000000000000000000000000000000000000000000000005910520000000000000000000000000000000000000000000000000000000000000059205200000000000000000000000000000000000000000000000000000000000000593052000000000000000000000000000000000000000000000000000000000000005940520000000000000000000000000000000000000000000000000000000000000059505200000000000000000000000000000000000000000000000000000000000000596052000000000000000000000000000000000000000000000000000000000000005970520000000000000000000000000000000000000000000000000000000000000059805200000000000000000000000000000000000000000000000000000000000000599052000000000000000000000000000000000000000000000000000000000000006000520000000000000000000000000000000000000000000000000000000000000060105200000000000000000000000000000000000000000000000000000000000000602052000000000000000000000000000000000000000000000000000000000000006030520000000000000000000000000000000000000000000000000000000000000060405200000000000000000000000000000000000000000000000000000000000000605052000000000000000000000000000000000000000000000000000000000000006060520000000000000000000000000000000000000000000000000000000000000060705200000000000000000000000000000000000000000000000000000000000000608052000000000000000000000000000000000000000000000000000000000000006090520000000000000000000000000000000000000000000000000000000000000061005200000000000000000000000000000000000000000000000000000000000000611052000000000000000000000000000000000000000000000000000000000000006120520000000000000000000000000000000000000000000000000000000000000061305200000000000000000000000000000000000000000000000000000000000000614052000000000000000000000000000000000000000000000000000000000000006150520000000000000000000000000000000000000000000000000000000000000061605200000000000000000000000000000000000000000000000000000000000000617052000000000000000000000000000000000000000000000000000000000000006180520000000000000000000000000000000000000000000000000000000000000061905200000000000000000000000000000000000000000000000000000000000000620052000000000000000000000000000000000000000000000000000000000000006210520000000000000000000000000000000000000000000000000000000000000062205200000000000000000000000000000000000000000000000000000000000000623052000000000000000000000000000000000000000000000000000000000000006240520000000000000000000000000000000000000000000000000000000000000062505200000000000000000000000000000000000000000000000000000000000000626052000000000000000000000000000000000000000000000000000000000000006270520000000000000000000000000000000000000000000000000000000000000062805200000000000000000000000000000000000000000000000000000000000000629052000000000000000000000000000000000000000000000000000000000000006300520000000000000000000000000000000000000000000000000000000000000063105200000000000000000000000000000000000000000000000000000000000000632052000000000000000000000000000000000000000000000000000000000000006330520000000000000000000000000000000000000000000000000000000000000063405200000000000000000000000000000000000000000000000000000000000000635052000000000000000000000000000000000000000000000000000000000000006360520000000000000000000000000000000000000000000000000000000000000063705200000000000000000000000000000000000000000000000000000000000000638052000000000000000000000000000000000000000000000000000000000000006390520000000000000000000000000000000000000000000000000000000000000064005200000000000000000000000000000000000000000000000000000000000000641052000000000000000000000000000000000000000000000000000000000000006420520000000000000000000000000000000000000000000000000000000000000064305200000000000000000000000000000000000000000000000000000000000000644052000000000000000000000000000000000000000000000000000000000000006450520000000000000000000000000000000000000000000000000000000000000064605200000000000000000000000000000000000000000000000000000000000000647052000000000000000000000000000000000000000000000000000000000000006480520000000000000000000000000000000000000000000000000000000000000064905200000000000000000000000000000000000000000000000000000000000000650052000000000000000000000000000000000000000000000000000000000000006510520000000000000000000000000000000000000000000000000000000000000065205200000000000000000000000000000000000000000000000000000000000000653052000000000000000000000000000000000000000000000000000000000000006540520000000000000000000000000000000000000000000000000000000000000065505200000000000000000000000000000000000000000000000000000000000000656052000000000000000000000000000000000000000000000000000000000000006570520000000000000000000000000000000000000000000000000000000000000065805200000000000000000000000000000000000000000000000000000000000000659052000000000000000000000000000000000000000000000000000000000000006600520000000000000000000000000000000000000000000000000000000000000066105200000000000000000000000000000000000000000000000000000000000000662052000000000000000000000000000000000000000000000000000000000000006630520000000000000000000000000000000000000000000000000000000000000066405200000000000000000000000000000000000000000000000000000000000000665052000000000000000000000000000000000000000000000000000000000000006660520000000000000000000000000000000000000000000000000000000000000066705200000000000000000000000000000000000000000000000000000000000000668052000000000000000000000000000000000000000000000000000000000000006690520000000000000000000000000000000000000000000000000000000000000067005200000000000000000000000000000000000000000000000000000000000000671052000000000000000000000000000000000000000000000000000000000000006720520000000000000000000000000000000000000000000000000000000000000067305200000000000000000000000000000000000000000000000000000000000000674052000000000000000000000000000000000000000000000000000000000000006750520000000000000000000000000000000000000000000000000000000000000067605200000000000000000000000000000000000000000000000000000000000000677052000000000000000000000000000000000000000000000000000000000000006780520000000000000000000000000000000000000000000000000000000000000067905200000000000000000000000000000000000000000000000000000000000000680052000000000000000000000000000000000000000000000000000000000000006810520000000000000000000000000000000000000000000000000000000000000068205200000000000000000000000000000000000000000000000000000000000000683052000000000000000000000000000000000000000000000000000000000000006840520000000000000000000000000000000000000000000000000000000000000068505200000000000000000000000000000000000000000000000000000000000000686052000000000000000000000000000000000000000000000000000000000000006870520000000000000000000000000000000000000000000000000000000000000068805200000000000000000000000000000000000000000000000000000000000000689052000000000000000000000000000000000000000000000000000000000000006900520000000000000000000000000000000000000000000000000000000000000069105200000000000000000000000000000000000000000000000000000000000000692052000000000000000000000000000000000000000000000000000000000000006930520000000000000000000000000000000000000000000000000000000000000069405200000000000000000000000000000000000000000000000000000000000000695052000000000000000000000000000000000000000000000000000000000000006960520000000000000000000000000000000000000000000000000000000000000069705200000000000000000000000000000000000000000000000000000000000000698052000000000000000000000000000000000000000000000000000000000000006990520000000000000000000000000000000000000000000000000000000000000070005200000000000000000000000000000000000000000000000000000000000000701052000000000000000000000000000000000000000000000000000000000000007020520000000000000000000000000000000000000000000000000000000000000070305200000000000000000000000000000000000000000000000000000000000000704052000000000000000000000000000000000000000000000000000000000000007050520000000000000000000000000000000000000000000000000000000000000070605200000000000000000000000000000000000000000000000000000000000000707052000000000000000000000000000000000000000000000000000000000000007080520000000000000000000000000000000000000000000000000000000000000070905200000000000000000000000000000000000000000000000000000000000000710052000000000000000000000000000000000000000000000000000000000000007110520000000000000000000000000000000000000000000000000000000000000071205200000000000000000000000000000000000000000000000000000000000000713052000000000000000000000000000000000000000000000000000000000000007140520000000000000000000000000000000000000000000000000000000000000071505200000000000000000000000000000000000000000000000000000000000000716052000000000000000000000000000000000000000000000000000000000000007170520000000000000000000000000000000000000000000000000000000000000071805200000000000000000000000000000000000000000000000000000000000000719052000000000000000000000000000000000000000000000000000000000000007200520000000000000000000000000000000000000000000000000000000000000072105200000000000000000000000000000000000000000000000000000000000000722052000000000000000000000000000000000000000000000000000000000000007230520000000000000000000000000000000000000000000000000000000000000072405200000000000000000000000000000000000000000000000000000000000000725052000000000000000000000000000000000000000000000000000000000000007260520000000000000000000000000000000000000000000000000000000000000072705200000000000000000000000000000000000000000000000000000000000000728052000000000000000000000000000000000000000000000000000000000000007290520000000000000000000000000000000000000000000000000000000000000073005200000000000000000000000000000000000000000000000000000000000000731052000000000000000000000000000000000000000000000000000000000000007320520000000000000000000000000000000000000000000000000000000000000073305200000000000000000000000000000000000000000000000000000000000000734052000000000000000000000000000000000000000000000000000000000000007350520000000000000000000000000000000000000000000000000000000000000073605200000000000000000000000000000000000000000000000000000000000000737052000000000000000000000000000000000000000000000000000000000000007380520000000000000000000000000000000000000000000000000000000000000073905200000000000000000000000000000000000000000000000000000000000000740052000000000000000000000000000000000000000000000000000000000000007410520000000000000000000000000000000000000000000000000000000000000074205200000000000000000000000000000000000000000000000000000000000000743052000000000000000000000000000000000000000000000000000000000000007440520000000000000000000000000000000000000000000000000000000000000074505200000000000000000000000000000000000000000000000000000000000000746052000000000000000000000000000000000000000000000000000000000000007470520000000000000000000000000000000000000000000000000000000000000074805200000000000000000000000000000000000000000000000000000000000000749052000000000000000000000000000000000000000000000000000000000000007500520000000000000000000000000000000000000000000000000000000000000075105200000000000000000000000000000000000000000000000000000000000000752052000000000000000000000000000000000000000000000000000000000000007530520000000000000000000000000000000000000000000000000000000000000075405200000000000000000000000000000000000000000000000000000000000000755052000000000000000000000000000000000000000000000000000000000000007560520000000000000000000000000000000000000000000000000000000000000075705200000000000000000000000000000000000000000000000000000000000000758052000000000000000000000000000000000000000000000000000000000000007590520000000000000000000000000000000000000000000000000000000000000076005200000000000000000000000000000000000000000000000000000000000000761052000000000000000000000000000000000000000000000000000000000000007620520000000000000000000000000000000000000000000000000000000000000076305200000000000000000000000000000000000000000000000000000000000000764052000000000000000000000000000000000000000000000000000000000000007650520000000000000000000000000000000000000000000000000000000000000076605200000000000000000000000000000000000000000000000000000000000000767052000000000000000000000000000000000000000000000000000000000000007680520000000000000000000000000000000000000000000000000000000000000076905200000000000000000000000000000000000000000000000000000000000000770052000000000000000000000000000000000000000000000000000000000000007710520000000000000000000000000000000000000000000000000000000000000077205200000000000000000000000000000000000000000000000000000000000000773052000000000000000000000000000000000000000000000000000000000000007740520000000000000000000000000000000000000000000000000000000000000077505200000000000000000000000000000000000000000000000000000000000000776052000000000000000000000000000000000000000000000000000000000000007770520000000000000000000000000000000000000000000000000000000000000077805200000000000000000000000000000000000000000000000000000000000000779052000000000000000000000000000000000000000000000000000000000000007800520000000000000000000000000000000000000000000000000000000000000078105200000000000000000000000000000000000000000000000000000000000000782052000000000000000000000000000000000000000000000000000000000000007830520000000000000000000000000000000000000000000000000000000000000078405200000000000000000000000000000000000000000000000000000000000000785052000000000000000000000000000000000000000000000000000000000000007860520000000000000000000000000000000000000000000000000000000000000078705200000000000000000000000000000000000000000000000000000000000000788052000000000000000000000000000000000000000000000000000000000000007890520000000000000000000000000000000000000000000000000000000000000079005200000000000000000000000000000000000000000000000000000000000000791052000000000000000000000000000000000000000000000000000000000000007920520000000000000000000000000000000000000000000000000000000000000079305200000000000000000000000000000000000000000000000000000000000000794052000000000000000000000000000000000000000000000000000000000000007950520000000000000000000000000000000000000000000000000000000000000079605200000000000000000000000000000000000000000000000000000000000000797052000000000000000000000000000000000000000000000000000000000000007980520000000000000000000000000000000000000000000000000000000000000079905200000000000000000000000000000000000000000000000000000000000000800052000000000000000000000000000000000000000000000000000000000000008010520000000000000000000000000000000000000000000000000000000000000080205200000000000000000000000000000000000000000000000000000000000000803052000000000000000000000000000000000000000000000000000000000000008040520000000000000000000000000000000000000000000000000000000000000080505200000000000000000000000000000000000000000000000000000000000000806052000000000000000000000000000000000000000000000000000000000000008070520000000000000000000000000000000000000000000000000000000000000080805200000000000000000000000000000000000000000000000000000000000000809052000000000000000000000000000000000000000000000000000000000000008100520000000000000000000000000000000000000000000000000000000000000081105200000000000000000000000000000000000000000000000000000000000000812052000000000000000000000000000000000000000000000000000000000000008130520000000000000000000000000000000000000000000000000000000000000081405200000000000000000000000000000000000000000000000000000000000000815052000000000000000000000000000000000000000000000000000000000000008160520000000000000000000000000000000000000000000000000000000000000081705200000000000000000000000000000000000000000000000000000000000000818052000000000000000000000000000000000000000000000000000000000000008190520000000000000000000000000000000000000000000000000000000000000082005200000000000000000000000000000000000000000000000000000000000000821052000000000000000000000000000000000000000000000000000000000000008220520000000000000000000000000000000000000000000000000000000000000082305200000000000000000000000000000000000000000000000000000000000000824052000000000000000000000000000000000000000000000000000000000000008250520000000000000000000000000000000000000000000000000000000000000082605200000000000000000000000000000000000000000000000000000000000000827052000000000000000000000000000000000000000000000000000000000000008280520000000000000000000000000000000000000000000000000000000000000082905200000000000000000000000000000000000000000000000000000000000000830052000000000000000000000000000000000000000000000000000000000000008310520000000000000000000000000000000000000000000000000000000000000083205200000000000000000000000000000000000000000000000000000000000000833052000000000000000000000000000000000000000000000000000000000000008340520000000000000000000000000000000000000000000000000000000000000083505200000000000000000000000000000000000000000000000000000000000000836052000000000000000000000000000000000000000000000000000000000000008370520000000000000000000000000000000000000000000000000000000000000083805200000000000000000000000000000000000000000000000000000000000000839052000000000000000000000000000000000000000000000000000000000000008400520000000000000000000000000000000000000000000000000000000000000084105200000000000000000000000000000000000000000000000000000000000000842052000000000000000000000000000000000000000000000000000000000000008430520000000000000000000000000000000000000000000000000000000000000084405200000000000000000000000000000000000000000000000000000000000000845052000000000000000000000000000000000000000000000000000000000000008460520000000000000000000000000000000000000000000000000000000000000084705200000000000000000000000000000000000000000000000000000000000000848052000000000000000000000000000000000000000000000000000000000000008490520000000000000000000000000000000000000000000000000000000000000085005200000000000000000000000000000000000000000000000000000000000000851052000000000000000000000000000000000000000000000000000000000000008520520000000000000000000000000000000000000000000000000000000000000085305200000000000000000000000000000000000000000000000000000000000000854052000000000000000000000000000000000000000000000000000000000000008550520000000000000000000000000000000000000000000000000000000000000085605200000000000000000000000000000000000000000000000000000000000000857052000000000000000000000000000000000000000000000000000000000000008580520000000000000000000000000000000000000000000000000000000000000085905200000000000000000000000000000000000000000000000000000000000000860052000000000000000000000000000000000000000000000000000000000000008610520000000000000000000000000000000000000000000000000000000000000086205200000000000000000000000000000000000000000000000000000000000000863052000000000000000000000000000000000000000000000000000000000000008640520000000000000000000000000000000000000000000000000000000000000086505200000000000000000000000000000000000000000000000000000000000000866052000000000000000000000000000000000000000000000000000000000000008670520000000000000000000000000000000000000000000000000000000000000086805200000000000000000000000000000000000000000000000000000000000000869052000000000000000000000000000000000000000000000000000000000000008700520000000000000000000000000000000000000000000000000000000000000087105200000000000000000000000000000000000000000000000000000000000000872052000000000000000000000000000000000000000000000000000000000000008730520000000000000000000000000000000000000000000000000000000000000087405200000000000000000000000000000000000000000000000000000000000000875052000000000000000000000000000000000000000000000000000000000000008760520000000000000000000000000000000000000000000000000000000000000087705200000000000000000000000000000000000000000000000000000000000000878052000000000000000000000000000000000000000000000000000000000000008790520000000000000000000000000000000000000000000000000000000000000088005200000000000000000000000000000000000000000000000000000000000000881052000000000000000000000000000000000000000000000000000000000000008820520000000000000000000000000000000000000000000000000000000000000088305200000000000000000000000000000000000000000000000000000000000000884052000000000000000000000000000000000000000000000000000000000000008850520000000000000000000000000000000000000000000000000000000000000088605200000000000000000000000000000000000000000000000000000000000000887052000000000000000000000000000000000000000000000000000000000000008880520000000000000000000000000000000000000000000000000000000000000088905200000000000000000000000000000000000000000000000000000000000000890052000000000000000000000000000000000000000000000000000000000000008910520000000000000000000000000000000000000000000000000000000000000089205200000000000000000000000000000000000000000000000000000000000000893052000000000000000000000000000000000000000000000000000000000000008940520000000000000000000000000000000000000000000000000000000000000089505200000000000000000000000000000000000000000000000000000000000000896052000000000000000000000000000000000000000000000000000000000000008970520000000000000000000000000000000000000000000000000000000000000089805200000000000000000000000000000000000000000000000000000000000000899052000000000000000000000000000000000000000000000000000000000000009000520000000000000000000000000000000000000000000000000000000000000090105200000000000000000000000000000000000000000000000000000000000000902052000000000000000000000000000000000000000000000000000000000000009030520000000000000000000000000000000000000000000000000000000000000090405200000000000000000000000000000000000000000000000000000000000000905052000000000000000000000000000000000000000000000000000000000000009060520000000000000000000000000000000000000000000000000000000000000090705200000000000000000000000000000000000000000000000000000000000000908052000000000000000000000000000000000000000000000000000000000000009090520000000000000000000000000000000000000000000000000000000000000091005200000000000000000000000000000000000000000000000000000000000000911052000000000000000000000000000000000000000000000000000000000000009120520000000000000000000000000000000000000000000000000000000000000091305200000000000000000000000000000000000000000000000000000000000000914052000000000000000000000000000000000000000000000000000000000000009150520000000000000000000000000000000000000000000000000000000000000091605200000000000000000000000000000000000000000000000000000000000000917052000000000000000000000000000000000000000000000000000000000000009180520000000000000000000000000000000000000000000000000000000000000091905200000000000000000000000000000000000000000000000000000000000000920052000000000000000000000000000000000000000000000000000000000000009210520000000000000000000000000000000000000000000000000000000000000092205200000000000000000000000000000000000000000000000000000000000000923052000000000000000000000000000000000000000000000000000000000000009240520000000000000000000000000000000000000000000000000000000000000092505200000000000000000000000000000000000000000000000000000000000000926052000000000000000000000000000000000000000000000000000000000000009270520000000000000000000000000000000000000000000000000000000000000092805200000000000000000000000000000000000000000000000000000000000000929052000000000000000000000000000000000000000000000000000000000000009300520000000000000000000000000000000000000000000000000000000000000093105200000000000000000000000000000000000000000000000000000000000000932052000000000000000000000000000000000000000000000000000000000000009330520000000000000000000000000000000000000000000000000000000000000093405200000000000000000000000000000000000000000000000000000000000000935052000000000000000000000000000000000000000000000000000000000000009360520000000000000000000000000000000000000000000000000000000000000093705200000000000000000000000000000000000000000000000000000000000000938052000000000000000000000000000000000000000000000000000000000000009390520000000000000000000000000000000000000000000000000000000000000094005200000000000000000000000000000000000000000000000000000000000000941052000000000000000000000000000000000000000000000000000000000000009420520000000000000000000000000000000000000000000000000000000000000094305200000000000000000000000000000000000000000000000000000000000000944052000000000000000000000000000000000000000000000000000000000000009450520000000000000000000000000000000000000000000000000000000000000094605200000000000000000000000000000000000000000000000000000000000000947052000000000000000000000000000000000000000000000000000000000000009480520000000000000000000000000000000000000000000000000000000000000094905200000000000000000000000000000000000000000000000000000000000000950052000000000000000000000000000000000000000000000000000000000000009510520000000000000000000000000000000000000000000000000000000000000095205200000000000000000000000000000000000000000000000000000000000000953052000000000000000000000000000000000000000000000000000000000000009540520000000000000000000000000000000000000000000000000000000000000095505200000000000000000000000000000000000000000000000000000000000000956052000000000000000000000000000000000000000000000000000000000000009570520000000000000000000000000000000000000000000000000000000000000095805200000000000000000000000000000000000000000000000000000000000000959052000000000000000000000000000000000000000000000000000000000000009600520000000000000000000000000000000000000000000000000000000000000096105200000000000000000000000000000000000000000000000000000000000000962052000000000000000000000000000000000000000000000000000000000000009630520000000000000000000000000000000000000000000000000000000000000096405200000000000000000000000000000000000000000000000000000000000000965052000000000000000000000000000000000000000000000000000000000000009660520000000000000000000000000000000000000000000000000000000000000096705200000000000000000000000000000000000000000000000000000000000000968052000000000000000000000000000000000000000000000000000000000000009690520000000000000000000000000000000000000000000000000000000000000097005200000000000000000000000000000000000000000000000000000000000000971052000000000000000000000000000000000000000000000000000000000000009720520000000000000000000000000000000000000000000000000000000000000097305200000000000000000000000000000000000000000000000000000000000000974052000000000000000000000000000000000000000000000000000000000000009750520000000000000000000000000000000000000000000000000000000000000097605200000000000000000000000000000000000000000000000000000000000000977052000000000000000000000000000000000000000000000000000000000000009780520000000000000000000000000000000000000000000000000000000000000097905200000000000000000000000000000000000000000000000000000000000000980052000000000000000000000000000000000000000000000000000000000000009810520000000000000000000000000000000000000000000000000000000000000098205200000000000000000000000000000000000000000000000000000000000000983052000000000000000000000000000000000000000000000000000000000000009840520000000000000000000000000000000000000000000000000000000000000098505200000000000000000000000000000000000000000000000000000000000000986052000000000000000000000000000000000000000000000000000000000000009870520000000000000000000000000000000000000000000000000000000000000098805200000000000000000000000000000000000000000000000000000000000000989052000000000000000000000000000000000000000000000000000000000000009900520000000000000000000000000000000000000000000000000000000000000099105200000000000000000000000000000000000000000000000000000000000000992052000000000000000000000000000000000000000000000000000000000000009930520000000000000000000000000000000000000000000000000000000000000099405200000000000000000000000000000000000000000000000000000000000000995052000000000000000000000000000000000000000000000000000000000000009960520000000000000000000000000000000000000000000000000000000000000099705200000000000000000000000000000000000000000000000000000000000000998052000000000000000000000000000000000000000000000000000000000000009990520e57eb8d10b6eed36a88a464538f8fcedbba7b1a71d6ed52124f77b835807d0fd05201c53ca351e7f26f963ced56cf18f9ebee56535170171b72a0addb4e1613776850520636b8e5a599cfe0833dbe141dbc093d65e0a497451ac21415fbf03698587c7b905204ea21cad94a85adb252b0a76b9826c67d7c697ca386d201752e38f19ed92a223126170746f733a3a6d657461646174615f7630c201032003000000000000134552525f414c52454144595f50524553454e542c4164647265737320697320616c72656164792070726573656e7420696e207468652077686974656c6973742e2103000000000000134552525f4e4f5f535543485f41444452455353214e6f2073756368206164647265737320696e207468652077686974656c6973742e2203000000000000134552525f4e4f545f494e495449414c495a45441d57686974656c697374206973206e6f7420696e697469616c697a65642e000201090b010205020001040100051d0b0011050c020b02070321030907012707032900030e0701270a01110220031407002707032a000c030b030f000b013101380002010104010008b01f0b0011050c010b01070321030907012707032a000c030b030f000c020a020704310138000a020705310138000a020706310138000a020707310138000a020708310138000a020709310138000a02070a310138000a02070b310138000a02070c310138000a02070d310138000a02070e310138000a02070f310138000a020710310138000a020711310138000a020712310138000a020713310138000a020714310138000a020715310138000a020716310138000a020717310138000a020718310138000a020719310138000a02071a310138000a02071b310138000a02071c310138000a02071d310138000a02071e310138000a02071f310138000a020720310138000a020721310138000a020722310138000a020723310138000a020724310138000a020725310138000a020726310138000a020727310138000a020728310138000a020729310138000a02072a310138000a02072b310138000a02072c310138000a02072d310138000a02072e310138000a02072f310138000a020730310138000a020731310138000a020732310138000a020733310138000a020734310138000a020735310138000a020736310138000a020737310138000a020738310138000a020739310138000a02073a310138000a02073b310138000a02073c310138000a02073d310138000a02073e310138000a02073f310138000a020740310138000a020741310138000a020742310138000a020743310138000a020744310138000a020745310138000a020746310138000a020747310138000a020748310138000a020749310138000a02074a310138000a02074b310138000a02074c310138000a02074d310138000a02074e310138000a02074f310138000a020750310138000a020751310138000a020752310138000a020753310138000a020754310138000a020755310138000a020756310138000a020757310138000a020758310138000a020759310138000a02075a310138000a02075b310138000a02075c310138000a02075d310138000a02075e310138000a02075f310138000a020760310138000a020761310138000a020762310138000a020763310138000a020764310138000a020765310138000a020766310138000a020767310138000a020768310138000a020769310138000a02076a310138000a02076b310138000a02076c310138000a02076d310138000a02076e310138000a02076f310138000a020770310138000a020771310138000a020772310138000a020773310138000a020774310138000a020775310138000a020776310138000a020777310138000a020778310138000a020779310138000a02077a310138000a02077b310138000a02077c310138000a02077d310138000a02077e310138000a02077f310138000a02078001310138000a02078101310138000a02078201310138000a02078301310138000a02078401310138000a02078501310138000a02078601310138000a02078701310138000a02078801310138000a02078901310138000a02078a01310138000a02078b01310138000a02078c01310138000a02078d01310138000a02078e01310138000a02078f01310138000a02079001310138000a02079101310138000a02079201310138000a02079301310138000a02079401310138000a02079501310138000a02079601310138000a02079701310138000a02079801310138000a02079901310138000a02079a01310138000a02079b01310138000a02079c01310138000a02079d01310138000a02079e01310138000a02079f01310138000a0207a001310138000a0207a101310138000a0207a201310138000a0207a301310138000a0207a401310138000a0207a501310138000a0207a601310138000a0207a701310138000a0207a801310138000a0207a901310138000a0207aa01310138000a0207ab01310138000a0207ac01310138000a0207ad01310138000a0207ae01310138000a0207af01310138000a0207b001310138000a0207b101310138000a0207b201310138000a0207b301310138000a0207b401310138000a0207b501310138000a0207b601310138000a0207b701310138000a0207b801310138000a0207b901310138000a0207ba01310138000a0207bb01310138000a0207bc01310138000a0207bd01310138000a0207be01310138000a0207bf01310138000a0207c001310138000a0207c101310138000a0207c201310138000a0207c301310138000a0207c401310138000a0207c501310138000a0207c601310138000a0207c701310138000a0207c801310138000a0207c901310138000a0207ca01310138000a0207cb01310138000a0207cc01310138000a0207cd01310138000a0207ce01310138000a0207cf01310138000a0207d001310138000a0207d101310138000a0207d201310138000a0207d301310138000a0207d401310138000a0207d501310138000a0207d601310138000a0207d701310138000a0207d801310138000a0207d901310138000a0207da01310138000a0207db01310138000a0207dc01310138000a0207dd01310138000a0207de01310138000a0207df01310138000a0207e001310138000a0207e101310138000a0207e201310138000a0207e301310138000a0207e401310138000a0207e501310138000a0207e601310138000a0207e701310138000a0207e801310138000a0207e901310138000a0207ea01310138000a0207eb01310138000a0207ec01310138000a0207ed01310138000a0207ee01310138000a0207ef01310138000a0207f001310138000a0207f101310138000a0207f201310138000a0207f301310138000a0207f401310138000a0207f501310138000a0207f601310138000a0207f701310138000a0207f801310138000a0207f901310138000a0207fa01310138000a0207fb01310138000a0207fc01310138000a0207fd01310138000a0207fe01310138000a0207ff01310138000a02078002310138000a02078102310138000a02078202310138000a02078302310138000a02078402310138000a02078502310138000a02078602310138000a02078702310138000a02078802310138000a02078902310138000a02078a02310138000a02078b02310138000a02078c02310138000a02078d02310138000a02078e02310138000a02078f02310138000a02079002310138000a02079102310138000a02079202310138000a02079302310138000a02079402310138000a02079502310138000a02079602310138000a02079702310138000a02079802310138000a02079902310138000a02079a02310138000a02079b02310138000a02079c02310138000a02079d02310138000a02079e02310138000a02079f02310138000a0207a002310138000a0207a102310138000a0207a202310138000a0207a302310138000a0207a402310138000a0207a502310138000a0207a602310138000a0207a702310138000a0207a802310138000a0207a902310138000a0207aa02310138000a0207ab02310138000a0207ac02310138000a0207ad02310138000a0207ae02310138000a0207af02310138000a0207b002310138000a0207b102310138000a0207b202310138000a0207b302310138000a0207b402310138000a0207b502310138000a0207b602310138000a0207b702310138000a0207b802310138000a0207b902310138000a0207ba02310138000a0207bb02310138000a0207bc02310138000a0207bd02310138000a0207be02310138000a0207bf02310138000a0207c002310138000a0207c102310138000a0207c202310138000a0207c302310138000a0207c402310138000a0207c502310138000a0207c602310138000a0207c702310138000a0207c802310138000a0207c902310138000a0207ca02310138000a0207cb02310138000a0207cc02310138000a0207cd02310138000a0207ce02310138000a0207cf02310138000a0207d002310138000a0207d102310138000a0207d202310138000a0207d302310138000a0207d402310138000a0207d502310138000a0207d602310138000a0207d702310138000a0207d802310138000a0207d902310138000a0207da02310138000a0207db02310138000a0207dc02310138000a0207dd02310138000a0207de02310138000a0207df02310138000a0207e002310138000a0207e102310138000a0207e202310138000a0207e302310138000a0207e402310138000a0207e502310138000a0207e602310138000a0207e702310138000a0207e802310138000a0207e902310138000a0207ea02310138000a0207eb02310138000a0207ec02310138000a0207ed02310138000a0207ee02310138000a0207ef02310138000a0207f002310138000a0207f102310138000a0207f202310138000a0207f302310138000a0207f402310138000a0207f502310138000a0207f602310138000a0207f702310138000a0207f802310138000a0207f902310138000a0207fa02310138000a0207fb02310138000a0207fc02310138000a0207fd02310138000a0207fe02310138000a0207ff02310138000a02078003310138000a02078103310138000a02078203310138000a02078303310138000a02078403310138000a02078503310138000a02078603310138000a02078703310138000a02078803310138000a02078903310138000a02078a03310138000a02078b03310138000a02078c03310138000a02078d03310138000a02078e03310138000a02078f03310138000a02079003310138000a02079103310138000a02079203310138000a02079303310138000a02079403310138000a02079503310138000a02079603310138000a02079703310138000a02079803310138000a02079903310138000a02079a03310138000a02079b03310138000a02079c03310138000a02079d03310138000a02079e03310138000a02079f03310138000a0207a003310138000a0207a103310138000a0207a203310138000a0207a303310138000a0207a403310138000a0207a503310138000a0207a603310138000a0207a703310138000a0207a803310138000a0207a903310138000a0207aa03310138000a0207ab03310138000a0207ac03310138000a0207ad03310138000a0207ae03310138000a0207af03310138000a0207b003310138000a0207b103310138000a0207b203310138000a0207b303310138000a0207b403310138000a0207b503310138000a0207b603310138000a0207b703310138000a0207b803310138000a0207b903310138000a0207ba03310138000a0207bb03310138000a0207bc03310138000a0207bd03310138000a0207be03310138000a0207bf03310138000a0207c003310138000a0207c103310138000a0207c203310138000a0207c303310138000a0207c403310138000a0207c503310138000a0207c603310138000a0207c703310138000a0207c803310138000a0207c903310138000a0207ca03310138000a0207cb03310138000a0207cc03310138000a0207cd03310138000a0207ce03310138000a0207cf03310138000a0207d003310138000a0207d103310138000a0207d203310138000a0207d303310138000a0207d403310138000a0207d503310138000a0207d603310138000a0207d703310138000a0207d803310138000a0207d903310138000a0207da03310138000a0207db03310138000a0207dc03310138000a0207dd03310138000a0207de03310138000a0207df03310138000a0207e003310138000a0207e103310138000a0207e203310138000a0207e303310138000a0207e403310138000a0207e503310138000a0207e603310138000a0207e703310138000a0207e803310138000a0207e903310138000a0207ea03310138000a0207eb03310138000a0207ec03310138000a0207ed03310138000a0207ee03310138000a0207ef03310138000a0207f003310138000a0207f103310138000a0207f203310138000a0207f303310138000a0207f403310138000a0207f503310138000a0207f603310138000a0207f703310138000a0207f803310138000a0207f903310138000a0207fa03310138000a0207fb03310138000a0207fc03310138000a0207fd03310138000a0207fe03310138000a0207ff03310138000a02078004310138000a02078104310138000a02078204310138000a02078304310138000a02078404310138000a02078504310138000a02078604310138000a02078704310138000a02078804310138000a02078904310138000a02078a04310138000a02078b04310138000a02078c04310138000a02078d04310138000a02078e04310138000a02078f04310138000a02079004310138000a02079104310138000a02079204310138000a02079304310138000a02079404310138000a02079504310138000a02079604310138000a02079704310138000a02079804310138000a02079904310138000a02079a04310138000a02079b04310138000a02079c04310138000a02079d04310138000a02079e04310138000a02079f04310138000a0207a004310138000a0207a104310138000a0207a204310138000a0207a304310138000a0207a404310138000a0207a504310138000a0207a604310138000a0207a704310138000a0207a804310138000a0207a904310138000a0207aa04310138000a0207ab04310138000a0207ac04310138000a0207ad04310138000a0207ae04310138000a0207af04310138000a0207b004310138000a0207b104310138000a0207b204310138000a0207b304310138000a0207b404310138000a0207b504310138000a0207b604310138000a0207b704310138000a0207b804310138000a0207b904310138000a0207ba04310138000a0207bb04310138000a0207bc04310138000a0207bd04310138000a0207be04310138000a0207bf04310138000a0207c004310138000a0207c104310138000a0207c204310138000a0207c304310138000a0207c404310138000a0207c504310138000a0207c604310138000a0207c704310138000a0207c804310138000a0207c904310138000a0207ca04310138000a0207cb04310138000a0207cc04310138000a0207cd04310138000a0207ce04310138000a0207cf04310138000a0207d004310138000a0207d104310138000a0207d204310138000a0207d304310138000a0207d404310138000a0207d504310138000a0207d604310138000a0207d704310138000a0207d804310138000a0207d904310138000a0207da04310138000a0207db04310138000a0207dc04310138000a0207dd04310138000a0207de04310138000a0207df04310138000a0207e004310138000a0207e104310138000a0207e204310138000a0207e304310138000a0207e404310138000a0207e504310138000a0207e604310138000a0207e704310138000a0207e804310138000a0207e904310138000a0207ea04310138000a0207eb04310138000a0207ec04310138000a0207ed04310138000a0207ee04310138000a0207ef04310138000a0207f004310138000a0207f104310138000a0207f204310138000a0207f304310138000a0207f404310138000a0207f504310138000a0207f604310138000a0207f704310138000a0207f804310138000a0207f904310138000a0207fa04310138000a0207fb04310138000a0207fc04310138000a0207fd04310138000a0207fe04310138000a0207ff04310138000a02078005310138000a02078105310138000a02078205310138000a02078305310138000a02078405310138000a02078505310138000a02078605310138000a02078705310138000a02078805310138000a02078905310138000a02078a05310138000a02078b05310138000a02078c05310138000a02078d05310138000a02078e05310138000a02078f05310138000a02079005310138000a02079105310138000a02079205310138000a02079305310138000a02079405310138000a02079505310138000a02079605310138000a02079705310138000a02079805310138000a02079905310138000a02079a05310138000a02079b05310138000a02079c05310138000a02079d05310138000a02079e05310138000a02079f05310138000a0207a005310138000a0207a105310138000a0207a205310138000a0207a305310138000a0207a405310138000a0207a505310138000a0207a605310138000a0207a705310138000a0207a805310138000a0207a905310138000a0207aa05310138000a0207ab05310138000a0207ac05310138000a0207ad05310138000a0207ae05310138000a0207af05310138000a0207b005310138000a0207b105310138000a0207b205310138000a0207b305310138000a0207b405310138000a0207b505310138000a0207b605310138000a0207b705310138000a0207b805310138000a0207b905310138000a0207ba05310138000a0207bb05310138000a0207bc05310138000a0207bd05310138000a0207be05310138000a0207bf05310138000a0207c005310138000a0207c105310138000a0207c205310138000a0207c305310138000a0207c405310138000a0207c505310138000a0207c605310138000a0207c705310138000a0207c805310138000a0207c905310138000a0207ca05310138000a0207cb05310138000a0207cc05310138000a0207cd05310138000a0207ce05310138000a0207cf05310138000a0207d005310138000a0207d105310138000a0207d205310138000a0207d305310138000a0207d405310138000a0207d505310138000a0207d605310138000a0207d705310138000a0207d805310138000a0207d905310138000a0207da05310138000a0207db05310138000a0207dc05310138000a0207dd05310138000a0207de05310138000a0207df05310138000a0207e005310138000a0207e105310138000a0207e205310138000a0207e305310138000a0207e405310138000a0207e505310138000a0207e605310138000a0207e705310138000a0207e805310138000a0207e905310138000a0207ea05310138000a0207eb05310138000a0207ec05310138000a0207ed05310138000a0207ee05310138000a0207ef05310138000a0207f005310138000a0207f105310138000a0207f205310138000a0207f305310138000a0207f405310138000a0207f505310138000a0207f605310138000a0207f705310138000a0207f805310138000a0207f905310138000a0207fa05310138000a0207fb05310138000a0207fc05310138000a0207fd05310138000a0207fe05310138000a0207ff05310138000a02078006310138000a02078106310138000a02078206310138000a02078306310138000a02078406310138000a02078506310138000a02078606310138000a02078706310138000a02078806310138000a02078906310138000a02078a06310138000a02078b06310138000a02078c06310138000a02078d06310138000a02078e06310138000a02078f06310138000a02079006310138000a02079106310138000a02079206310138000a02079306310138000a02079406310138000a02079506310138000a02079606310138000a02079706310138000a02079806310138000a02079906310138000a02079a06310138000a02079b06310138000a02079c06310138000a02079d06310138000a02079e06310138000a02079f06310138000a0207a006310138000a0207a106310138000a0207a206310138000a0207a306310138000a0207a406310138000a0207a506310138000a0207a606310138000a0207a706310138000a0207a806310138000a0207a906310138000a0207aa06310138000a0207ab06310138000a0207ac06310138000a0207ad06310138000a0207ae06310138000a0207af06310138000a0207b006310138000a0207b106310138000a0207b206310138000a0207b306310138000a0207b406310138000a0207b506310138000a0207b606310138000a0207b706310138000a0207b806310138000a0207b906310138000a0207ba06310138000a0207bb06310138000a0207bc06310138000a0207bd06310138000a0207be06310138000a0207bf06310138000a0207c006310138000a0207c106310138000a0207c206310138000a0207c306310138000a0207c406310138000a0207c506310138000a0207c606310138000a0207c706310138000a0207c806310138000a0207c906310138000a0207ca06310138000a0207cb06310138000a0207cc06310138000a0207cd06310138000a0207ce06310138000a0207cf06310138000a0207d006310138000a0207d106310138000a0207d206310138000a0207d306310138000a0207d406310138000a0207d506310138000a0207d606310138000a0207d706310138000a0207d806310138000a0207d906310138000a0207da06310138000a0207db06310138000a0207dc06310138000a0207dd06310138000a0207de06310138000a0207df06310138000a0207e006310138000a0207e106310138000a0207e206310138000a0207e306310138000a0207e406310138000a0207e506310138000a0207e606310138000a0207e706310138000a0207e806310138000a0207e906310138000a0207ea06310138000a0207eb06310138000a0207ec06310138000a0207ed06310138000a0207ee06310138000a0207ef06310138000a0207f006310138000a0207f106310138000a0207f206310138000a0207f306310138000a0207f406310138000a0207f506310138000a0207f606310138000a0207f706310138000a0207f806310138000a0207f906310138000a0207fa06310138000a0207fb06310138000a0207fc06310138000a0207fd06310138000a0207fe06310138000a0207ff06310138000a02078007310138000a02078107310138000a02078207310138000a02078307310138000a02078407310138000a02078507310138000a02078607310138000a02078707310138000a02078807310138000a02078907310138000a02078a07310138000a02078b07310138000a02078c07310138000a02078d07310138000a02078e07310138000a02078f07310138000a02079007310138000a02079107310138000a02079207310138000a02079307310138000a02079407310138000a02079507310138000a02079607310138000a02079707310138000a02079807310138000a02079907310138000a02079a07310138000a02079b07310138000a02079c07310138000a02079d07310138000a02079e07310138000a02079f07310138000a0207a007310138000a0207a107310138000a0207a207310138000a0207a307310138000a0207a407310138000a0207a507310138000a0207a607310138000a0207a707310138000a0207a807310138000a0207a907310138000a0207aa07310138000a0207ab07310138000a0207ac07310138000a0207ad07310138000a0207ae07310138000a0207af07310138000a0207b007310138000a0207b107310138000a0207b207310138000a0207b307310138000a0207b407310138000a0207b507310138000a0207b607310138000a0207b707310138000a0207b807310138000a0207b907310138000a0207ba07310138000a0207bb07310138000a0207bc07310138000a0207bd07310138000a0207be07310138000a0207bf07310138000a0207c007310138000a0207c107310138000a0207c207310138000a0207c307310138000a0207c407310138000a0207c507310138000a0207c607310138000a0207c707310138000a0207c807310138000a0207c907310138000a0207ca07310138000a0207cb07310138000a0207cc07310138000a0207cd07310138000a0207ce07310138000a0207cf07310138000a0207d007310138000a0207d107310138000a0207d207310138000a0207d307310138000a0207d407310138000a0207d507310138000a0207d607310138000a0207d707310138000a0207d807310138000a0207d907310138000a0207da07310138000a0207db07310138000a0207dc07310138000a0207dd07310138000a0207de07310138000a0207df07310138000a0207e007310138000a0207e107310138000a0207e207310138000a0207e307310138000a0207e407310138000a0207e507310138000a0207e607310138000a0207e707310138000a0207e807310138000a0207e907310138000a0207ea07310138000b0207eb0731013800020201000100090807032b000c010b0110000b00380102030100000b1f38020c010d0107ec07310138000d0107ed07310138000d0107ee07310138000d0107ef07310138000d01071a310138000d01071b310138000b000b0112002d00020401040100051c0b0011050c020b02070321030907012707032900030e0701270a011102031307022707032a000c030b030f000b0138030102000000"; - let res = run_binary_test("sample_whitelist", code); - assert!(res.is_ok(), "{:?}", res) -} - -#[cfg(feature = "address32")] -#[test] -fn sample_coin_store() { - let code = "a11ceb0b050000000e01001e021e0c032acb0604f5065405c907a41207ed19e80908d523800206d5252c108126420ac326090bcc26040cd026fd86010dcdad01020ecfad01040000010101020103020402050306030704080509050a0607060b070c070d000e08010001011104010001000f00010200000010010201000012030101000013040103000000001404010300000000150401030000000016040103000000001704010300000000180401030000000019040103000000001a040103000000001b040103000000001c040103000000001d040103000000001e040103000000001f0401030000000020040103000000002104010300000000220401030000000023040103000000002404010300000000250401030000000026040103000000002704010300000000280401030000000029040103000000002a040103000000002b040103000000002c040103000000002d040103000000002e040103000000002f0401030000000030040103000000003104010300000000320401030000000033050103000000003405010300000000350501030000000036050103000000003705010300000000380501030000000039050103000000003a050103000000003b050103000000003c050103000000003d050103000000003e050103000000003f0501030000000040050103000000004105010300000000420501030000000043050103000000004405010300000000450501030000000046050103000000004705010300000000480501030000000049050103000000004a050103000000004b050103000000004c050103000000004d050103000000004e050103000000004f050103000000005005010300000000510601010000520701010000530801010000540901020000005509010200000056000102000000570a010200000058070102000000590a01020000005a0b01020000005b0001020000005c0c0103000000005d0c01020000005e0c01020000005f0701010000600701010000610201010000620701010000630d01010000640e010100006502030100006601030100006702030100016810020100016911010100096a0114020000046b0100020000016c16030100016d01030100090b1819020000040b1a1b020000016e030101000c6f011d0200000b70031e020000066b0100030000000771221e030000000872010202000008730102020000087424000200000e6a01140200000d0b261e020000037508400002760202000165070301000477014200057801430200000a790100020000060b1a1b03000000011226010100017a48030100580f590f5a135a155b135c0f5d175e135e1559175d0f5f155f136017611361156215600f6320632164216513661366156515671568136815691562136420671369136c0f6e136f135c17702070215817710f720f020303000103010b010109000d030403040404010101010404040d0304030404010101010404040402060c0b0101090002060c0301060c0b030403040404010104040403060c030304060c0303010a060c03040403030404010102050303060c050301090001060b0101090002070b010109000b01010900230b010109000b010109010403040b010109000403040404040b010109010403030304040b010109000b010109000b01010901070b00010900040404040b010109000b010109000b0101090104040b0101090104040209000901020404020901090002070b0101090003010901040b01010900040b0101090104040b010109000b010109010b010109000b01010901040b01010900030b0101090103020b010109000b01010901250303030403040b010109000403040404040b0101090103030304040b010109000b010109010b01010900070b000109000404040b010109000b0101090003040404030b0101090104030403030303010b0101090122040303040b010109000403040404040b0101090103030304040b010109000b010109000b01010901070b000109000404040b0101090003040b010109000404030b0101090104040309000901090203090109000902020b010109000323040404040b010109000403040404040b0101090103030304040b010109000b010109000b01010901070b000109000404050b01010900040b010109000b01010901040b0101090004040b0101090104040805070b01010900070b01010901030301040423040404040b010109000403040404040b0101090103030304040b010109000b010109010b01010900070b00010900040405040b0101090004040b010109000404040b01010901040402050b01010900240403040403040404040403030304040b010109000b010109010b01010900070b000109000b0101090104040504040b010109010b010109000b01010900040b01010900040b010109010b0101090104040b01010900200303030403030404030404040403030304040b010109000b010109010b01010900070b000109000b010109010404030b01010900040303040b010109001d040303030404030404040403030304040b010109000b010109010b01010900070b000109000b01010901040403040b0101090003040b010109001e040404030404030404040403030304040b010109000b010109010b01010900070b000109000b010109010404050b01010900040b010109000b01010901040b010109001e040404030404030404040403030304040b010109000b010109010b01010900070b000109000b0101090104040504040b0101090004040b010109002603030304030403040404040403030304040b010109010b01010900070b00010900040405030b010109000b0101090104040b01010900040b01010900030b01010901040b01010901040304200303030b010109000b010109010403030403040404040403030304040b010109010b01010900070b000109000404030b010109000b01010901040303041d0303030403030304030404040403030304040b01010900070b0001090004040303040303030421030303040404030404030404040403030304040b010109010b01010900070b000109000404050b01010900030b010109000b01010901040303041f0303030404040304030404040403030304040b010109010b01010900070b0001090004040503040403040304230403030403040404040403030304040b010109000b01010901070b0001090004040503040b01010901040b010109000b01010900040b01010900030b01010901040b0101090104041d0b010109000b01010901040303030403040404040403030304040b010109000b01010901070b00010900040403040b010109000b0101090103041e04040403030404030404040403030304040b010109000b01010901070b000109000404050b0101090003040b010109000b0101090103041c040404030304030404040403030304040b010109000b01010901070b00010900040405030404030404240404040403040404040403030304040b010109000b010109000b01010901070b000109000404050b01010901040b01010901040b010109010b010109000b01010900040b01010900040b010109010b0101090104041f04040b010109000b0101090104030403040404040403030304040b010109000b010109000b01010901070b000109000404050b01010901040b010109010b010109000b0101090104200404030303040304030404040403030304040b010109000b01010900070b000109000404050b01010901030b010109010b01010900040303041d040404030304030404040403030304040b010109000b01010900070b000109000404050b0101090103040b010109010b0101090003041e040404040404030404040403030304040b010109000b010109010b01010900070b000109000404050b01010901040b01010900040b010109010404240404040403040404040403030304040b010109000b010109000b01010901070b00010900040405040b010109000b0101090104040b01010900040b01010900040b01010901040b0101090104041f04040b010109000b0101090104030403040404040403030304040b010109000b010109000b01010901070b0001090004040504040b010109000b0101090104041f0404030303040304030404040403030304040b010109000b01010900070b00010900040405040304040303041c040404030304030404040403030304040b010109000b01010900070b000109000404050403040403041f04040404040404030404040403030304040b010109000b010109000b01010901070b000109000404050b01010900040b010109000b01010901040404010b0001090001050d05030403070b000109000b01010901040b01010900040303030b01010900040302010101011a0504040404070b00010900070b000109010404030303030b01010901040404040b010109000b010109000b010109000b010109000b010109010b010109010b010109010b010109010f03030305040404030b010109010b01010901040b0101090003030b010109000e04040305040404030b010109000b01010901040b010109010b010109010b010109000f030303030305040404030b010109010403030301070b01010900030b0101090003070b000109000a636f696e5f73746f726504636f696e056572726f72067369676e65720f416e696d6553776170506f6f6c563116416e696d6553776170506f6f6c56314c6962726172790e6c69717569646974795f706f6f6c06726f7574657203616d6d09546f6b656e537761700f546f6b656e53776170436f6e66696704737761700a616d6d5f726f7574657208616d6d5f737761700b4d79436f696e53746f726512616e696d65737761705f73746172737761700762616c616e636504436f696e076465706f736974066c3073307431066c3073317430066c3173307431066c3173307432066c3173307433066c3173307434066c3173307435066c3173317430066c3173317432066c3173317433066c3173317434066c3173317435066c3173327430066c3173327431066c3173327433066c3173327434066c3173327435066c3173337430066c3173337431066c3173337432066c3173337434066c3173337435066c3173347430066c3173347431066c3173347432066c3173347433066c3173347435066c3173357430066c3173357431066c3173357432066c3173357433066c3173357434066c3273307431066c3273307432066c3273307433066c3273307434066c3273307435066c3273317430066c3273317432066c3273317433066c3273317434066c3273317435066c3273327430066c3273327431066c3273327433066c3273327434066c3273327435066c3273337430066c3273337431066c3273337432066c3273337434066c3273337435066c3273347430066c3273347431066c3273347432066c3273347433066c3273347435066c3273357430066c3273357431066c3273357432066c3273357433066c3273357434036e65770d6e65775f66726f6d5f6d61696e0d6e65775f66726f6d5f7a65726f047330743104733174301073696d706c655f616e696d65737761701373696d706c655f616e696d65737761705f76320f73696d706c655f73746172737761701273696d706c655f73746172737761705f76321273696d706c655f73746172737761705f76331273746172737761705f616e696d657377617012737761705f61625f6c69717569647377617008737761705f61757810737761705f70616e63616b6573776170127472616e736665725f66726f6d5f6d61696e197472616e736665725f66726f6d5f6d61696e5f736372697074107472616e736665725f746f5f6d61696e177472616e736665725f746f5f6d61696e5f736372697074117472616e736665725f746f5f6f74686572187472616e736665725f746f5f6f746865725f7363726970740877697468647261770c77697468647261775f616c6c0c77697468647261775f616e790576616c7565056d657267650c6765745f7265736572766573116765745f72657365727665735f73697a650765787472616374047a65726f0c64657374726f795f7a65726f0e746f6b656e5f726573657276657321737761705f65786163745f785f746f5f795f6469726563745f65787465726e616c18737761705f65786163745f636f696e5f666f725f636f696e04785f617504795f61751c737761705f65786163745f636f696e5f666f725f636f696e5f6d75740a616464726573735f6f66117065726d697373696f6e5f64656e6965640e6765745f61646d696e5f6461746107636f6d70617265116765745f706f756e646167655f726174650b657874726163745f616c6cd1b58e44ea11ffd326a280c453b080fd8af294298815a00e65b6e2bffc48d6ac000000000000000000000000000000000000000000000000000000000000000116fe2df00ea7dde4a63409201f7f4e536bde7bb7335526a35d05111e68aa322c190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12bd35135844473187163ca197ca93b2ab014370587bb0ed3befff9e902d6bb541c755e4c8d7a6ab6d56f9289d97c43c1c94bde75ec09147c90d35cd1be61c8fb9c7efb4076dbe143cbcd98cfaaa929ecfc8f299203dfff63b95ccb6bfe19850faec42a352cc65eca17a9fa85d0fc602295897ed6b8b8af6a6c79ef490eb8f9eba0308915f0100000000000520d1b58e44ea11ffd326a280c453b080fd8af294298815a00e65b6e2bffc48d6ac126170746f733a3a6d657461646174615f76302e01915f010000000000234552524f525f5448455f4f55545055545f4c4553535f5448414e5f4d494e5f5245435600000201010b01010900000f001700010400010206ffffffffffffffff270101000100010507013c0037003800020201000100010607013c0036000b0038010203010400010206ffffffffffffffff2704010400010206ffffffffffffffff2705010400010206ffffffffffffffff2706010400010206ffffffffffffffff2707010400010206ffffffffffffffff2708010400010206ffffffffffffffff2709010400010206ffffffffffffffff270a010400010206ffffffffffffffff270b010400010206ffffffffffffffff270c010400010206ffffffffffffffff270d010400010206ffffffffffffffff270e010400010206ffffffffffffffff270f010400010206ffffffffffffffff2710010400010206ffffffffffffffff2711010400010206ffffffffffffffff2712010400010206ffffffffffffffff2713010400010206ffffffffffffffff2714010400010206ffffffffffffffff2715010400010206ffffffffffffffff2716010400010206ffffffffffffffff2717010400010206ffffffffffffffff2718010400010206ffffffffffffffff2719010400010206ffffffffffffffff271a010400010206ffffffffffffffff271b010400010206ffffffffffffffff271c010400010206ffffffffffffffff271d010400010206ffffffffffffffff271e010400010206ffffffffffffffff271f010400010206ffffffffffffffff2720010400010206ffffffffffffffff2721010400010206ffffffffffffffff2722010400010206ffffffffffffffff27230104010012f1010b05040638020c2c0c26050d38030c2b0c2e0b2b0c260b2e0c2c0b260b2c0c180c1738040c10350b10350c1f0c1e0a0432000000000000000000000000000000002104660a180a0c180a0a1a0a1f160c110a170a1f180a111a0c0f0a1e0a18180a0c180a0a1a0b111a0c110a0f0a11180a0b180a091a0c2f0a0f0a11180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c270a270a2f23045e054d0a270c2f0a0f0a11180a0b180a091a0a271a0b271632020000000000000000000000000000001a0c2705480b2f0b0f170a0b180a091a0c040a040b0b180c150b170b09180a15160c240b150b18180b241a320b000000000000000000000000000000170c130a130b0c180c160b1f0b0a180a16160c250b160b1e180b251a320b000000000000000000000000000000170c1a0a1a0a04170b0317010b04340c1407013c000c230a23370038000c1b0a2336000b1438050c200b0804ab010b200b133806320000000000000000000000000000000038070c190c120c2d0c2805b401380632000000000000000000000000000000000b200b1338080c120c190c280c2d0d280b1238010d2d0b1938090b2d0c220a2336000b283801380a0c290b0704cd010b220600000000000000000b290b1a34380b0c0d0c0e05d5010b290b1a340b22060000000000000000380c0c0e0c0d0b0e0b0d0c210c2a0a2336000b2138010b1b0b02160c1c0b23370038000c1d0a1d0a1c2404ea0105ee010b1c0b1d17270b2a380d0224010401001cef010b05040638020c2c0c26050d38030c2b0c2f0b2b0c260b2f0c2c0b260b2c0c190c180b060418380e0c0f0c0e0c0d0522380f0c300c290c2d0b290b2d0b300c0f0c0e0c0d0b0d0b0e0b0f010c11350b11350c1f0c1e0a04320000000000000000000000000000000021047a0a190a0c180a0a1a0a1f160c120a180a1f180a121a0c100a1e0a19180a0c180a0a1a0b121a0c120a100a12180a0b180a091a0c310a100a12180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c2a0a2a0a3123047205610a2a0c310a100a12180a0b180a091a0a2a1a0b2a1632020000000000000000000000000000001a0c2a055c0b310b10170a0b180a091a0c040a040b0b180c160b180b09180a16160c240b160b19180b241a320b000000000000000000000000000000170c140a140b0c180c170b1f0b0a180a17160c250b170b1e180b251a320b000000000000000000000000000000170a04170b0317010b04340c1507013c000c230a23370038000c1b0a2336000b1538050c200b0804bd010b200b143806320000000000000000000000000000000038070c1a0c130c2e0c2705c601380632000000000000000000000000000000000b200b1438080c130c1a0c270c2e0d270b1338010d2e0b1a38090b2e0c210a2336000b273801380a0c280b2138100c220a2336000b2238010b1b0b02160c1c0b23370038000c1d0a1d0a1c2404e80105ec010b1c0b1d17270b2838110225010401001fe8010b05040638020c2a0c24050d38030c290c2d0b290c240b2d0c2a0b240b2a0c170c160b06041738120c0f0c0e051e38130c260c2b0b260c0e0b2b0c0f0b0e350b0f350c1d0c1c0a0432000000000000000000000000000000002104720a170a0c180a0a1a0a1d160c100a160a1d180a101a0c0d0a1c0a17180a0c180a0a1a0b101a0c100a0d0a10180a0b180a091a0c2e0a0d0a10180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c270a270a2e23046a05590a270c2e0a0d0a10180a0b180a091a0a271a0b271632020000000000000000000000000000001a0c2705540b2e0b0d170a0b180a091a0c040a040b0b180c140b160b09180a14160c220b140b17180b221a320b000000000000000000000000000000170c120a120b0c180c150b1d0b0a180a15160c230b150b1c180b231a320b000000000000000000000000000000170a04170b0317010b04340c1307013c000c210a21370038000c190a2136000b1338050c1e0b0804b5010b1e0b123806320000000000000000000000000000000038070c180c110c2c0c2805be01380632000000000000000000000000000000000b1e0b1238080c110c180c280c2c0d280b1138010d2c0b1838090b2c0c200a2136000b283801380a0c250b2006000000000000000038140c1f0a2136000b1f38010b190b02160c1a0b21370038000c1b0a1b0a1a2404e10105e5010b1a0b1b17270b25381102260104010023f8010b05040638020c2c0c26050d38030c2b0c2e0b2b0c260b2e0c2c0b260b2c0c170c160b06041a3815353816350c0e0c0d05203817353818350c0e0c0d0b0d0b0e0c1d0c1c0a0432000000000000000000000000000000002104720a170a0c180a0a1a0a1d160c100a160a1d180a101a0c0f0a1c0a17180a0c180a0a1a0b101a0c100a0f0a10180a0b180a091a0c2f0a0f0a10180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c290a290a2f23046a05590a290c2f0a0f0a10180a0b180a091a0a291a0b291632020000000000000000000000000000001a0c2905540b2f0b0f170a0b180a091a0c040a040b0b180c140b160b09180a14160c220b140b17180b221a320b000000000000000000000000000000170c120a120b0c180c150b1d0b0a180a15160c230b150b1c180b231a320b000000000000000000000000000000170a04170b0317010b04340c1307010c240a243c000c210a21370038000c190a2136000b1338050c1e0b0804b7010b1e0a123806320000000000000000000000000000000038070c180c110c2d0c2a05c001380632000000000000000000000000000000000b1e0a1238080c110c180c2a0c2d0d2a0b1138010d2d0b1838090b2d0c200a2136000b2a3801380a0c270b240d200d270b12340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381901010b270c250b200c280b250c1f0a2136000b1f38010b190b02160c1a0b21370038000c1b0a1b0a1a2404f10105f5010b1a0b1b17270b28380d02270104010025e8010b05040638020c2b0c25050d38030c2a0c2e0b2a0c250b2e0c2b0b250b2b0c170c160b060417381a0c0e0c0d051e381b0c270c2c0b270b2c0c0e0c0d0b0d0b0e0c1d0c1c0a0432000000000000000000000000000000002104700a170a0c180a0a1a0a1d160c100a160a1d180a101a0c0f0a1c0a17180a0c180a0a1a0b101a0c100a0f0a10180a0b180a091a0c2f0a0f0a10180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c280a280a2f23046805570a280c2f0a0f0a10180a0b180a091a0a281a0b281632020000000000000000000000000000001a0c2805520b2f0b0f170a0b180a091a0c040a040b0b180c140b160b09180a14160c220b140b17180b221a320b000000000000000000000000000000170c120a120b0c180c150b1d0b0a180a15160c230b150b1c180b231a320b000000000000000000000000000000170a04170b0317010b04340c1307010c240a243c000c210a21370038000c190a2136000b1338050c1e0b0804b5010b1e0b123806320000000000000000000000000000000038070c180c110c2d0c2905be01380632000000000000000000000000000000000b1e0b1238080c110c180c290c2d0d290b1138010d2d0b1838090b2d0c1f0a2136000b293801380a0c260b240b1f381c0c200a2136000b2038010b190b02160c1a0b21370038000c1b0a1b0a1a2404e10105e5010b1a0b1b17270b26381102280104010027f20138040c0e350b0e350c150c140b06040d38020c2b0c24051438030c290c2e0b290c240b2e0c2b0b240b2b0c1b0c1a0a0432000000000000000000000000000000002104660a150a0c180a0a1a0a1b160c0f0a140a1b180a0f1a0c0d0a1a0a15180a0c180a0a1a0b0f1a0c0f0a0d0a0f180a0b180a091a0c2f0a0d0a0f180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a2f23045e054d0a250c2f0a0d0a0f180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c2505480b2f0b0d170a0b180a091a0c040a040b0b180c120b140b09180a12160c210b120b15180b211a320b000000000000000000000000000000170c100a100b0c180c130b1b0b0a180a13160c220b130b1a180b221a320b000000000000000000000000000000170c160a160a04170b0317010b04340c1107010c230a233c000c1f0a1f370038000c170a1f36000b1138050c1c0b0804ac010b1c06000000000000000038060b1034380c0c200c3005b40138060b10340b1c060000000000000000380b0c300c200b300b200c1d0c270b0704c4010b1d0b160b27320000000000000000000000000000000038080c280c2d0c2a0c2c05cd010b2732000000000000000000000000000000000b1d0b1638070c2d0c280c2c0c2a0d2a0b2838010d2c0b2d38090b2a0c1e0b2c0c260a1f36000b1e38010b170b02160c180b1f370038000c190a190a182404e80105ec010b180b1917270b233c0136010b26380902290104010028d90138040c11350b11350c190c180b06040e380e0c0f0c0e0c0d0518380f0c2a0c260c290b260b290b2a0c0f0c0e0c0d0b0d0b0e0b0f010c12350b12350c1e0c1d0a0432000000000000000000000000000000002104700a190a0c180a0a1a0a1e160c130a180a1e180a131a0c100a1d0a19180a0c180a0a1a0b131a0c130a100a13180a0b180a091a0c2b0a100a13180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c280a280a2b23046805570a280c2b0a100a13180a0b180a091a0a281a0b281632020000000000000000000000000000001a0c2805520b2b0b10170a0b180a091a0c040a040b0b180c160b180b09180a16160c240b160b19180b241a320b000000000000000000000000000000170c140a140b0c180c170b1e0b0a180a17160c250b170b1d180b251a320b000000000000000000000000000000170a04170b0317010b04340c1507013c000c220a22370038000c1a0a2236000b1538050c1f0b0804b2010b1f06000000000000000038060b1434380c0c230c2c05ba0138060b14340b1f060000000000000000380b0c2c0c230b2c0b230c200c270b2038100c210a2236000b2138010b1a0b02160c1b0b22370038000c1c0a1c0a1b2404d20105d6010b1b0b1c17270b273811022a0104010029d20138040c0f350b0f350c170c160b06040d38120c100c0e051438130c240c270b240c0e0b270c100b0e350b10350c1c0c1b0a0432000000000000000000000000000000002104680a170a0c180a0a1a0a1c160c110a160a1c180a111a0c0d0a1b0a17180a0c180a0a1a0b111a0c110a0d0a11180a0b180a091a0c280a0d0a11180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a28230460054f0a250c280a0d0a11180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c25054a0b280b0d170a0b180a091a0c040a040b0b180c140b160b09180a14160c220b140b17180b221a320b000000000000000000000000000000170c120a120b0c180c150b1c0b0a180a15160c230b150b1b180b231a320b000000000000000000000000000000170a04170b0317010b04340c1307013c000c200a20370038000c180a2036000b1338050c1d0b0804aa010b1d06000000000000000038060b1234380c0c210c2905b20138060b12340b1d060000000000000000380b0c290c210b290b210c1e0c260b1e06000000000000000038140c1f0a2036000b1f38010b180b02160c190b20370038000c1a0a1a0a192404cb0105cf010b190b1a17270b263811022b010401002ae20138040c10350b10350c170c160b0604103815353816350c0e0c0d05163817353818350c0e0c0d0b0d0b0e0c1c0c1b0a0432000000000000000000000000000000002104680a170a0c180a0a1a0a1c160c110a160a1c180a111a0c0f0a1b0a17180a0c180a0a1a0b111a0c110a0f0a11180a0b180a091a0c290a0f0a11180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c260a260a29230460054f0a260c290a0f0a11180a0b180a091a0a261a0b261632020000000000000000000000000000001a0c26054a0b290b0f170a0b180a091a0c040a040b0b180c140b160b09180a14160c220b140b17180b221a320b000000000000000000000000000000170c120a120b0c180c150b1c0b0a180a15160c230b150b1b180b231a320b000000000000000000000000000000170a04170b0317010b04340c1307010c240a243c000c200a20370038000c180a2036000b1338050c1d0b0804ac010b1d06000000000000000038060a1234380c0c210c2a05b40138060a12340b1d060000000000000000380b0c2a0c210b2a0b210c1e0c270b240d1e0d270b12340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381901010b270c250b1e0c280b250c1f0a2036000b1f38010b180b02160c190b20370038000c1a0a1a0a192404db0105df010b190b1a17270b28380d022c010401002bd20138040c10350b10350c170c160b06040d381a0c0e0c0d0514381b0c250c280b250b280c0e0c0d0b0d0b0e0c1c0c1b0a0432000000000000000000000000000000002104660a170a0c180a0a1a0a1c160c110a160a1c180a111a0c0f0a1b0a17180a0c180a0a1a0b111a0c110a0f0a11180a0b180a091a0c290a0f0a11180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c260a260a2923045e054d0a260c290a0f0a11180a0b180a091a0a261a0b261632020000000000000000000000000000001a0c2605480b290b0f170a0b180a091a0c040a040b0b180c140b160b09180a14160c220b140b17180b221a320b000000000000000000000000000000170c120a120b0c180c150b1c0b0a180a15160c230b150b1b180b231a320b000000000000000000000000000000170a04170b0317010b04340c1307010c240a243c000c200a20370038000c180a2036000b1338050c1d0b0804aa010b1d06000000000000000038060b1234380c0c210c2a05b20138060b12340b1d060000000000000000380b0c2a0c210b2a0b210c1e0c270b240b1e381c0c1f0a2036000b1f38010b180b02160c190b20370038000c1a0a1a0a192404cb0105cf010b190b1a17270b273811022d010401002cec010b050407380e0c0f0c0e0c0d0511380f0c310c240c2c0b240b2c0b310c0f0c0e0c0d0b0d0b0e0b0f010c11350b11350c170c160b06042138020c2e0c27052838030c2a0c300b2a0c270b300c2e0b270b2e0c1d0c1c0a04320000000000000000000000000000000021047a0a170a0c180a0a1a0a1d160c120a160a1d180a121a0c100a1c0a17180a0c180a0a1a0b121a0c120a100a12180a0b180a091a0c320a100a12180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c280a280a3223047205610a280c320a100a12180a0b180a091a0a281a0b281632020000000000000000000000000000001a0c28055c0b320b10170a0b180a091a0c040a040b0b180c140b160b09180a14160c210b140b17180b211a0b0c180c150b1d0b0a180a15160c220b150b1c180b221a0c180a180a04170b0317010b04340c1307010c230a233c000c200a20370038000c190a2036000b133805381d0c1e380a0c250b0704be010b1e0b180b25320000000000000000000000000000000038080c290c2f0c2b0c2d05c7010b2532000000000000000000000000000000000b1e0b1838070c2f0c290c2d0c2b0d2b0b2938010d2d0b2f38090b2b0c1f0b2d0c260a2036000b1f38010b190b02160c1a0b20370038000c1b0a1b0a1a2404e20105e6010b1a0b1b17270b233c0136010b263809022e010401002dd5010b050407380e0c0f0c0e0c0d0511380f0c2b0c260c2a0b260b2a0b2b0c0f0c0e0c0d0b0d0b0e0b0f010c13350b13350c1a0c1938040c14350b14350c200c1f0a0432000000000000000000000000000000002104700a1a0a0c180a0a1a0a20160c150a190a20180a151a0c120a1f0a1a180a0c180a0a1a0b151a0c150a120a15180a0b180a091a0c2c0a120a15180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c290a290a2c23046805570a290c2c0a120a15180a0b180a091a0a291a0b291632020000000000000000000000000000001a0c2905520b2c0b12170a0b180a091a0c040a040b0b180c170b190b09180a17160c240b170b1a180b241a0b0c180c180b200b0a180a18160c250b180b1f180b251a0c1b0a1b0a04170b0317010b04340c1607013c000c230a23370038000c1c0a2336000b163805381d0c21380a0c270b0704b1010b210600000000000000000b270b1b34380b0c100c1105b9010b270b1b340b21060000000000000000380c0c110c100b110b100c220c280a2336000b2238010b1c0b02160c1d0b23370038000c1e0a1e0a1d2404ce0105d2010b1d0b1e17270b28380d022f010401002ec6010b050407380e0c0f0c0e0c0d0511380f0c280c230c260b230b260b280c0f0c0e0c0d0b0d0b0e0b0f010c12350b12350c190c180b06042138120c130c11052838130c240c270b240c110b270c130b11350b13350c1e0c1d0a04320000000000000000000000000000000021047c0a190a0c180a0a1a0a1e160c140a180a1e180a141a0c100a1d0a19180a0c180a0a1a0b141a0c140a100a14180a0b180a091a0c290a100a14180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a2923047405630a250c290a100a14180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c25055e0b290b10170a0b180a091a0c040a040b0b180c160b180b09180a16160c210b160b19180b211a0b0c180c170b1e0b0a180a17160c220b170b1d180b221a0a04170b0317010b04340c1507013c000c200a20370038000c1a0a2036000b153805381d06000000000000000038140c1f0a2036000b1f38010b1a0b02160c1b0b20370038000c1c0a1c0a1b2404c10105c5010b1b0b1c17270230010401002fde010b050407380e0c0f0c0e0c0d0511380f0c2c0c270c2b0b270b2b0b2c0c0f0c0e0c0d0b0d0b0e0b0f010c13350b13350c1a0c190b0604243815353816350c110c10052a3817353818350c110c100b100b110c1f0c1e0a04320000000000000000000000000000000021047c0a1a0a0c180a0a1a0a1f160c140a190a1f180a141a0c120a1e0a1a180a0c180a0a1a0b141a0c140a120a14180a0b180a091a0c2d0a120a14180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c2a0a2a0a2d23047405630a2a0c2d0a120a14180a0b180a091a0a2a1a0b2a1632020000000000000000000000000000001a0c2a055e0b2d0b12170a0b180a091a0c040a040b0b180c170b190b09180a17160c230b170b1a180b231a0c150a150b0c180c180b1f0b0a180a18160c240b180b1e180b241a0a04170b0317010b04340c1607010c250a253c000c220a22370038000c1b0a2236000b163805381d0c20380a0c280b250d200d280b15340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381901010b280c260b200c290b260c210a2236000b2138010b1b0b02160c1c0b22370038000c1d0a1d0a1c2404d70105db010b1c0b1d17270b29380d02310104010030c8010b050407380e0c0f0c0e0c0d0511380f0c2a0c250c280b250b280b2a0c0f0c0e0c0d0b0d0b0e0b0f010c13350b13350c190c180b060421381a0c110c100528381b0c260c290b260b290c110c100b100b110c1e0c1d0a04320000000000000000000000000000000021047a0a190a0c180a0a1a0a1e160c140a180a1e180a141a0c120a1d0a19180a0c180a0a1a0b141a0c140a120a14180a0b180a091a0c2b0a120a14180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c270a270a2b23047205610a270c2b0a120a14180a0b180a091a0a271a0b271632020000000000000000000000000000001a0c27055c0b2b0b12170a0b180a091a0c040a040b0b180c160b180b09180a16160c220b160b19180b221a0b0c180c170b1e0b0a180a17160c230b170b1d180b231a0a04170b0317010b04340c1507010c240a243c000c210a21370038000c1a0a2136000b153805381d0c1f0b240b1f381c0c200a2136000b2038010b1a0b02160c1b0b21370038000c1c0a1c0a1b2404c30105c7010b1b0b1c172702320104010031e5010b05040638120c0f0c0e050d38130c220c2a0b220c0e0b2a0c0f0b0e350b0f350c150c140b06041938020c2c0c23052038030c280c2e0b280c230b2e0c2c0b230b2c0c1b0c1a0a0432000000000000000000000000000000002104720a150a0c180a0a1a0a1b160c100a140a1b180a101a0c0d0a1a0a15180a0c180a0a1a0b101a0c100a0d0a10180a0b180a091a0c2f0a0d0a10180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a2f23046a05590a250c2f0a0d0a10180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c2505540b2f0b0d170a0b180a091a0c040a040b0b180c120b140b09180a12160c1f0b120b15180b1f1a0b0c180c130b1b0b0a180a13160c200b130b1a180b201a0c160a160a04170b0317010b04340c1107010c210a213c000c1e0a1e370038000c170a1e36000b113805060000000000000000381e0c1d380a0c260b0704b7010b1d0b160b26320000000000000000000000000000000038080c270c2d0c290c2b05c0010b2632000000000000000000000000000000000b1d0b1638070c2d0c270c2b0c290d290b2738010d2b0b2d38090b290c1c0b2b0c240a1e36000b1c38010b170b02160c180b1e370038000c190a190a182404db0105df010b180b1917270b213c0136010b24380902330104010032ce010b05040638120c110c10050d38130c240c280b240c100b280c110b10350b11350c180c1738040c12350b12350c1e0c1d0a0432000000000000000000000000000000002104680a180a0c180a0a1a0a1e160c130a170a1e180a131a0c0f0a1d0a18180a0c180a0a1a0b131a0c130a0f0a13180a0b180a091a0c290a0f0a13180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a29230460054f0a250c290a0f0a13180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c25054a0b290b0f170a0b180a091a0c040a040b0b180c150b170b09180a15160c220b150b18180b221a0b0c180c160b1e0b0a180a16160c230b160b1d180b231a0c190a190a04170b0317010b04340c1407013c000c210a21370038000c1a0a2136000b143805060000000000000000381e0c20380a0c260b0704aa010b200600000000000000000b260b1934380b0c0d0c0e05b2010b260b19340b20060000000000000000380c0c0e0c0d0b0e0b0d0c1f0c270a2136000b1f38010b1a0b02160c1b0b21370038000c1c0a1c0a1b2404c70105cb010b1b0b1c17270b27380d0234010401002ec6010b05040638120c120c11050d38130c230c260b230c110b260c120b11350b12350c190c180b06041a380e0c0f0c0e0c0d0524380f0c280c240c270b240b270b280c0f0c0e0c0d0b0d0b0e0b0f010c13350b13350c1e0c1d0a04320000000000000000000000000000000021047c0a190a0c180a0a1a0a1e160c140a180a1e180a141a0c100a1d0a19180a0c180a0a1a0b141a0c140a100a14180a0b180a091a0c290a100a14180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a2923047405630a250c290a100a14180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c25055e0b290b10170a0b180a091a0c040a040b0b180c160b180b09180a16160c210b160b19180b211a0b0c180c170b1e0b0a180a17160c220b170b1d180b221a0a04170b0317010b04340c1507013c000c200a20370038000c1a0a2036000b153805060000000000000000381e38100c1f0a2036000b1f38010b1a0b02160c1b0b20370038000c1c0a1c0a1b2404c10105c5010b1b0b1c172702350104010033d7010b05040638120c110c10050d38130c250c290b250c100b290c110b10350b11350c180c170b06041c3815353816350c0e0c0d05223817353818350c0e0c0d0b0d0b0e0c1d0c1c0a0432000000000000000000000000000000002104740a180a0c180a0a1a0a1d160c120a170a1d180a121a0c0f0a1c0a18180a0c180a0a1a0b121a0c120a0f0a12180a0b180a091a0c2a0a0f0a12180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c260a260a2a23046c055b0a260c2a0a0f0a12180a0b180a091a0a261a0b261632020000000000000000000000000000001a0c2605560b2a0b0f170a0b180a091a0c040a040b0b180c150b170b09180a15160c210b150b18180b211a0c130a130b0c180c160b1d0b0a180a16160c220b160b1c180b221a0a04170b0317010b04340c1407010c230a233c000c200a20370038000c190a2036000b143805060000000000000000381e0c1f380a0c270b230d1f0d270b13340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381901010b270c240b1f0c280b240c1e0a2036000b1e38010b190b02160c1a0b20370038000c1b0a1b0a1a2404d00105d4010b1a0b1b17270b28380d02360104010034c1010b05040638120c110c10050d38130c230c260b230c100b260c110b10350b11350c170c160b060419381a0c0e0c0d0520381b0c240c270b240b270c0e0c0d0b0d0b0e0c1c0c1b0a0432000000000000000000000000000000002104720a170a0c180a0a1a0a1c160c120a160a1c180a121a0c0f0a1b0a17180a0c180a0a1a0b121a0c120a0f0a12180a0b180a091a0c280a0f0a12180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a2823046a05590a250c280a0f0a12180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c2505540b280b0f170a0b180a091a0c040a040b0b180c140b160b09180a14160c200b140b17180b201a0b0c180c150b1c0b0a180a15160c210b150b1b180b211a0a04170b0317010b04340c1307010c220a223c000c1f0a1f370038000c180a1f36000b133805060000000000000000381e0c1e0b220b1e381c0c1d0a1f36000b1d38010b180b02160c190b1f370038000c1a0a1a0a192404bc0105c0010b190b1a172702370104010035f9010b0504093815353816350c0e0c0d050f3817353818350c0e0c0d0b0d0b0e0c150c140b06041938020c2c0c24052038030c2a0c2f0b2a0c240b2f0c2c0b240b2c0c1b0c1a0a0432000000000000000000000000000000002104720a150a0c180a0a1a0a1b160c100a140a1b180a101a0c0f0a1a0a15180a0c180a0a1a0b101a0c100a0f0a10180a0b180a091a0c300a0f0a10180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c260a260a3023046a05590a260c300a0f0a10180a0b180a091a0a261a0b261632020000000000000000000000000000001a0c2605540b300b0f170a0b180a091a0c040a040b0b180c120b140b09180a12160c200b120b15180b201a320b000000000000000000000000000000170b0c180c130b1b0b0a180a13160c210b130b1a180b211a320b000000000000000000000000000000170c160a160a04170b0317010b04340c1107010c220a223c000c1f0a1f370038000c170a1f36000a1138050c1c38060c270a220d1c0d270b11340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381f01010b270c230b1c0c280b230c1e0b0704cb010b1e0b160b28320000000000000000000000000000000038080c290c2e0c2b0c2d05d4010b2832000000000000000000000000000000000b1e0b1638070c2e0c290c2d0c2b0d2b0b2938010d2d0b2e38090b2b0c1d0b2d0c250a1f36000b1d38010b170b02160c180b1f370038000c190a190a182404ef0105f3010b180b1917270b223c0136010b25380902380104010036e4010b0504093815353816350c0e0c0d050f3817353818350c0e0c0d0b0d0b0e0c180c1738040c12350b12350c1e0c1d0a0432000000000000000000000000000000002104680a180a0c180a0a1a0a1e160c130a170a1e180a131a0c110a1d0a18180a0c180a0a1a0b131a0c130a110a13180a0b180a091a0c2b0a110a13180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c270a270a2b230460054f0a270c2b0a110a13180a0b180a091a0a271a0b271632020000000000000000000000000000001a0c27054a0b2b0b11170a0b180a091a0c040a040b0b180c150b170b09180a15160c230b150b18180b231a320b000000000000000000000000000000170b0c180c160b1e0b0a180a16160c240b160b1d180b241a320b000000000000000000000000000000170c190a190a04170b0317010b04340c1407010c250a253c000c220a22370038000c1a0a2236000a1438050c1f38060c280b250d1f0d280b14340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381f01010b280c260b1f0c290b260c210b0704c0010b210600000000000000000b290b1934380b0c0f0c1005c8010b290b19340b21060000000000000000380c0c100c0f0b100b0f0c200c2a0a2236000b2038010b1a0b02160c1b0b22370038000c1c0a1c0a1b2404dd0105e1010b1b0b1c17270b2a380d02390104010037e0010b0504093815353816350c0e0c0d050f3817353818350c0e0c0d0b0d0b0e0c190c180b06041a380e0c110c100c0f0524380f0c2b0c260c2a0b260b2a0b2b0c110c100c0f0b0f0b100b11010c13350b13350c1e0c1d0a04320000000000000000000000000000000021047c0a190a0c180a0a1a0a1e160c140a180a1e180a141a0c120a1d0a19180a0c180a0a1a0b141a0c140a120a14180a0b180a091a0c2c0a120a14180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c290a290a2c23047405630a290c2c0a120a14180a0b180a091a0a291a0b291632020000000000000000000000000000001a0c29055e0b2c0b12170a0b180a091a0c040a040b0b180c160b180b09180a16160c220b160b19180b221a320b000000000000000000000000000000170b0c180c170b1e0b0a180a17160c230b170b1d180b231a320b000000000000000000000000000000170a04170b0317010b04340c1507010c240a243c000c210a21370038000c1a0a2136000a1538050c1f38060c270b240d1f0d270b15340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381f01010b270c250b1f0c280b2538100c200a2136000b2038010b1a0b02160c1b0b21370038000c1c0a1c0a1b2404d90105dd010b1b0b1c17270b283811023a0104010038d9010b0504093815353816350c0e0c0d050f3817353818350c0e0c0d0b0d0b0e0c170c160b06041938120c110c10052038130c240c280b240c100b280c110b10350b11350c1c0c1b0a0432000000000000000000000000000000002104740a170a0c180a0a1a0a1c160c120a160a1c180a121a0c0f0a1b0a17180a0c180a0a1a0b121a0c120a0f0a12180a0b180a091a0c290a0f0a12180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a2923046c055b0a250c290a0f0a12180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c2505560b290b0f170a0b180a091a0c040a040b0b180c140b160b09180a14160c200b140b17180b201a320b000000000000000000000000000000170b0c180c150b1c0b0a180a15160c210b150b1b180b211a320b000000000000000000000000000000170a04170b0317010b04340c1307010c220a223c000c1f0a1f370038000c180a1f36000a1338050c1d38060c260b220d1d0d260b13340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381f01010b260c230b1d0c270b2306000000000000000038140c1e0a1f36000b1e38010b180b02160c190b1f370038000c1a0a1a0a192404d20105d6010b190b1a17270b273811023b0104010039d9010b0504093815353816350c0e0c0d050f3817353818350c0e0c0d0b0d0b0e0c170c160b060419381a0c100c0f0520381b0c250c290b250b290c100c0f0b0f0b100c1c0c1b0a0432000000000000000000000000000000002104720a170a0c180a0a1a0a1c160c120a160a1c180a121a0c110a1b0a17180a0c180a0a1a0b121a0c120a110a12180a0b180a091a0c2a0a110a12180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c270a270a2a23046a05590a270c2a0a110a12180a0b180a091a0a271a0b271632020000000000000000000000000000001a0c2705540b2a0b11170a0b180a091a0c040a040b0b180c140b160b09180a14160c210b140b17180b211a320b000000000000000000000000000000170b0c180c150b1c0b0a180a15160c220b150b1b180b221a320b000000000000000000000000000000170a04170b0317010b04340c1307010c230a233c000c200a20370038000c180a2036000a1338050c1d38060c280a230d1d0d280b13340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381f01010b280c240b1d0c260b240c1e0b230b1e381c0c1f0a2036000b1f38010b180b02160c190b20370038000c1a0a1a0a192404d20105d6010b190b1a17270b263811023c010401003ae5010b050406381a0c0e0c0d050d381b0c230c2b0b230b2b0c0e0c0d0b0d0b0e0c150c140b06041738020c2d0c26051e38030c290c2f0b290c260b2f0c2d0b260b2d0c1b0c1a0a0432000000000000000000000000000000002104700a150a0c180a0a1a0a1b160c100a140a1b180a101a0c0f0a1a0a15180a0c180a0a1a0b101a0c100a0f0a10180a0b180a091a0c300a0f0a10180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c270a270a3023046805570a270c300a0f0a10180a0b180a091a0a271a0b271632020000000000000000000000000000001a0c2705520b300b0f170a0b180a091a0c040a040b0b180c120b140b09180a12160c200b120b15180b201a0b0c180c130b1b0b0a180a13160c210b130b1a180b211a0c160a160a04170b0317010b04340c1107010c220a223c000c1f0a1f370038000c170a1f36000b1138050c1c0a220b1c38200c1e380a0c240b0704b7010b1e0b160b24320000000000000000000000000000000038080c280c2e0c2a0c2c05c0010b2432000000000000000000000000000000000b1e0b1638070c2e0c280c2c0c2a0d2a0b2838010d2c0b2e38090b2a0c1d0b2c0c250a1f36000b1d38010b170b02160c180b1f370038000c190a190a182404db0105df010b180b1917270b223c0136010b253809023d010401003bd0010b050406381a0c0e0c0d050d381b0c260c2a0b260b2a0c0e0c0d0b0d0b0e0c180c1738040c12350b12350c1e0c1d0a0432000000000000000000000000000000002104660a180a0c180a0a1a0a1e160c130a170a1e180a131a0c110a1d0a18180a0c180a0a1a0b131a0c130a110a13180a0b180a091a0c2b0a110a13180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c270a270a2b23045e054d0a270c2b0a110a13180a0b180a091a0a271a0b271632020000000000000000000000000000001a0c2705480b2b0b11170a0b180a091a0c040a040b0b180c150b170b09180a15160c230b150b18180b231a0b0c180c160b1e0b0a180a16160c240b160b1d180b241a0c190a190a04170b0317010b04340c1407010c250a253c000c220a22370038000c1a0a2236000b1438050c1f0b250b1f38200c21380a0c280b0704ac010b210600000000000000000b280b1934380b0c0f0c1005b4010b280b19340b21060000000000000000380c0c100c0f0b100b0f0c200c290a2236000b2038010b1a0b02160c1b0b22370038000c1c0a1c0a1b2404c90105cd010b1b0b1c17270b29380d023e010401003cc8010b050406381a0c0e0c0d050d381b0c250c280b250b280c0e0c0d0b0d0b0e0c190c180b060418380e0c110c100c0f0522380f0c2a0c260c290b260b290b2a0c110c100c0f0b0f0b100b11010c13350b13350c1e0c1d0a04320000000000000000000000000000000021047a0a190a0c180a0a1a0a1e160c140a180a1e180a141a0c120a1d0a19180a0c180a0a1a0b141a0c140a120a14180a0b180a091a0c2b0a120a14180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c270a270a2b23047205610a270c2b0a120a14180a0b180a091a0a271a0b271632020000000000000000000000000000001a0c27055c0b2b0b12170a0b180a091a0c040a040b0b180c160b180b09180a16160c220b160b19180b221a0b0c180c170b1e0b0a180a17160c230b170b1d180b231a0a04170b0317010b04340c1507010c240a243c000c210a21370038000c1a0a2136000b1538050c1f0b240b1f382038100c200a2136000b2038010b1a0b02160c1b0b21370038000c1c0a1c0a1b2404c30105c7010b1b0b1c1727023f010401003dc1010b050406381a0c0e0c0d050d381b0c230c260b230b260c0e0c0d0b0d0b0e0c170c160b06041738120c110c10051e38130c240c270b240c100b270c110b10350b11350c1c0c1b0a0432000000000000000000000000000000002104720a170a0c180a0a1a0a1c160c120a160a1c180a121a0c0f0a1b0a17180a0c180a0a1a0b121a0c120a0f0a12180a0b180a091a0c280a0f0a12180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a2823046a05590a250c280a0f0a12180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c2505540b280b0f170a0b180a091a0c040a040b0b180c140b160b09180a14160c200b140b17180b201a0b0c180c150b1c0b0a180a15160c210b150b1b180b211a0a04170b0317010b04340c1307010c220a223c000c1f0a1f370038000c180a1f36000b1338050c1d0b220b1d382006000000000000000038140c1e0a1f36000b1e38010b180b02160c190b1f370038000c1a0a1a0a192404bc0105c0010b190b1a17270240010401003ed7010b050406381a0c0e0c0d050d381b0c260c2a0b260b2a0c0e0c0d0b0d0b0e0c180c170b06041a3815353816350c100c0f05203817353818350c100c0f0b0f0b100c1d0c1c0a0432000000000000000000000000000000002104720a180a0c180a0a1a0a1d160c120a170a1d180a121a0c110a1c0a18180a0c180a0a1a0b121a0c120a110a12180a0b180a091a0c2b0a110a12180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c290a290a2b23046a05590a290c2b0a110a12180a0b180a091a0a291a0b291632020000000000000000000000000000001a0c2905540b2b0b11170a0b180a091a0c040a040b0b180c150b170b09180a15160c220b150b18180b221a0c130a130b0c180c160b1d0b0a180a16160c230b160b1c180b231a0a04170b0317010b04340c1407010c240a243c000c210a21370038000c190a2136000b1438050c1e0a240b1e38200c20380a0c270b240d200d270b13340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381901010b270c250b200c280b250c1f0a2136000b1f38010b190b02160c1a0b21370038000c1b0a1b0a1a2404d00105d4010b1a0b1b17270b28380d02410300003f070b0139000c020b000b023f0002420104003f140a00116a0701210406050b0b0001060000000000000000116b270a000b01382139000c020b000b023f0002430104003f120a00116a0701210406050b0b0001060000000000000000116b27380a39000c010b000b013f000244010400010206ffffffffffffffff2745010400010206ffffffffffffffff27460104000102060000000000000000274701040100415b0b00116a0c030a030701210408050b060000000000000000116b270a033c000c070a0736000b0138050c0a0e0a38000c04116d0101010c0e38040c0d0c0c0b04350610270000000000000b0e1735180c050a050b0d35180c0b0b0c353210270000000000000000000000000000180b05160c090b0b0b091a340c060a060b0226043c05400b07010700273822044a0b0a06000000000000000038060b06380c0c080c0f055138060b060b0a060000000000000000380b0c0f0c080b0736000b0f38010b033c0136010b0838090248010400010206000000000000000027490104000102060000000000000000274a010401004493010b00116a0c040a040701210408050b060000000000000000116b270b03044f38020c140c1238230c0d0c0f0a01350a0d0b0f1735180c050b120b0d35180a05160c0b0b050b14180b0b1a0c070a070b023524042e05300700270a043c000c090a0936000b0138050b073806320000000000000000000000000000000038070c1c0c180c1a0c160d160b1838010d1a0b1c38090b0936000b1638010b043c0136010b1a380905920138020c130c1538230c0e0c100a01350a0e0b101735180c060b130b0e35180a06160c0c0b060b15180b0c1a0c080a080b023524047005720700270a043c010c0a0a0a36010b0138240c11380a32000000000000000000000000000000000b110b0838070c1d0c190c1b0c170d170b1938010d1b0b1d38090b0a36010b1b38090b043c0036000b173801024b010400010206ffffffffffffffff274c0104010045650b00116a0c0d0a0d0701210408050b060000000000000000116b270b08041138120c0b0c0a051838130c160c170b160c0a0b170c0b0b0a350b0b350c100c0f0b030b07180c0e0b0f0b06180a0e160c140b0e0b10180b141a340c0c0a0c0a0526043405380b050b0c17270a0d3c0036000b0438050c150b0904480b1506000000000000000038060b0c38250c130c18054f38060b0c0b1506000000000000000038260c180c130b180b130c1238110e1238270c110a110a0524045b055f0b050b1117270b0d3c0136010b123809024d0104010046650b00116a0c0d0a0d0701210408050b060000000000000000116b270b0804143815353816350c0b0c0a051a3817353818350c0b0c0a0b0a0b0b0c100c0f0b030b07180c0e0b0f0b06180a0e160c140b0e0b10180b141a340c0c0a0c0a0526043405380b050b0c17270a0d3c0036000a0438050c1238060c160a0d0d120d160b040600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381f01010b160c150b120c170b150c130e1338270c110a110a05240459055d0b050b1117270b0d3c0136010b1338090b173811024e0104010047590b00116a0c0f0a0f0701210408050b060000000000000000116b270b080412380e0c0c0c0b0c0a051c380f0c180c160c170b160b170b180c0c0c0b0c0a0b0a0b0b0b0c010c0d350b0d350c120c110b030b07180c100b110b06180a10160c150b100b12180b151a340c0e0a0e0a0526043c05400b050b0e17270a0f3c0036000b043805381d0c140e1438270c130a130a0524044f05530b050b1317270b0f3c0136010b143809024f03000100030a0b000b0138210c0207013c0036000b02380102500004010026170a00116a0c020a020701210408050d0b0001060000000000000000116b270b000b0138210c030b023c0036000b033801025103000100260c07010c010a013c0036000b0038050c020b010b02382802520004010026150b00116a0c020a020701210408050b060000000000000000116b270a023c0036000b0138050c030b020b033828025303000100030a07013c0036000b0138050c020b000b02382802540004010026150b00116a0c030a030701210408050b060000000000000000116b270b033c0036000b0238050c040b010b043828025503000100010607013c0036000b003805025603000100010507013c0036003829025703000100491707013c000c030a03370038000c020a000b022404110b0336000b0038050c0105150b03360038290c010b01020000000f001700"; - let res = run_binary_test("sample_coin_store", code); - assert!(res.is_ok(), "{:?}", res) -} - -#[cfg(feature = "address32")] -#[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/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/catch_unwind.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/catch_unwind.rs deleted file mode 100644 index b248c8584f0..00000000000 --- a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/catch_unwind.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) The Move Contributors -// SPDX-License-Identifier: Apache-2.0 -use fail::FailScenario; -use move_binary_format::file_format::empty_module; -use move_bytecode_verifier::VerifierConfig; -use move_core_types::{ - state::{self, VMState}, - vm_status::StatusCode, -}; -use std::panic::{self, PanicInfo}; - -// TODO: this tests must run in its own process since otherwise any crashing test here -// secondary-crashes in the panic handler. -#[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/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/code_unit_tests.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/code_unit_tests.rs index cc172e3fa0c..c49c7c9030c 100644 --- a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/code_unit_tests.rs +++ b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/code_unit_tests.rs @@ -68,7 +68,7 @@ fn test_max_number_of_bytecode() { nops.push(Bytecode::Ret); let module = dummy_procedure_module(nops); - let result = CodeUnitVerifier::verify_module(&VerifierConfig::unbounded(), &module); + let result = CodeUnitVerifier::verify_module(&Default::default(), &module); assert!(result.is_ok()); } diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/constants_tests.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/constants_tests.rs index f74e2653a13..7ccd7a7be5e 100644 --- a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/constants_tests.rs +++ b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/constants_tests.rs @@ -14,7 +14,6 @@ proptest! { } #[test] -#[cfg(not(feature = "address32"))] fn valid_primitives() { let mut module = empty_module(); module.constant_pool = vec![ @@ -58,7 +57,6 @@ fn valid_primitives() { } #[test] -#[cfg(not(feature = "address32"))] fn invalid_primitives() { malformed(SignatureToken::U8, vec![0, 0]); malformed(SignatureToken::U16, vec![0, 0, 0, 0]); @@ -74,7 +72,6 @@ fn invalid_primitives() { } #[test] -#[cfg(not(feature = "address32"))] fn valid_vectors() { let double_vec = |item: Vec| -> Vec { let mut items = vec![2]; @@ -196,7 +193,6 @@ fn valid_vectors() { } #[test] -#[cfg(not(feature = "address32"))] fn invalid_vectors() { let double_vec = |item: Vec| -> Vec { let mut items = vec![2]; @@ -248,7 +244,6 @@ fn tvec(s: SignatureToken) -> SignatureToken { SignatureToken::Vector(Box::new(s)) } -#[allow(unused)] fn malformed(type_: SignatureToken, data: Vec) { error(type_, data, StatusCode::MALFORMED_CONSTANT_DATA) } diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/control_flow_tests.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/control_flow_tests.rs index 447ef51d943..7ac1e7e3d86 100644 --- a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/control_flow_tests.rs +++ b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/control_flow_tests.rs @@ -8,7 +8,7 @@ use move_binary_format::{ errors::PartialVMResult, file_format::{Bytecode, CompiledModule, FunctionDefinitionIndex, TableIndex}, }; -use move_bytecode_verifier::{control_flow, meter::DummyMeter, VerifierConfig}; +use move_bytecode_verifier::{control_flow, VerifierConfig}; use move_core_types::vm_status::StatusCode; fn verify_module(verifier_config: &VerifierConfig, module: &CompiledModule) -> PartialVMResult<()> { @@ -30,7 +30,6 @@ fn verify_module(verifier_config: &VerifierConfig, module: &CompiledModule) -> P current_function, function_definition, code, - &mut DummyMeter, )?; } Ok(()) diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/large_type_test.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/large_type_test.rs deleted file mode 100644 index c8499625e8c..00000000000 --- a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/large_type_test.rs +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright (c) The Move Contributors -// SPDX-License-Identifier: Apache-2.0 - -use crate::unit_tests::production_config; -use move_binary_format::file_format::{ - empty_module, Bytecode, CodeUnit, FunctionDefinition, FunctionHandle, FunctionHandleIndex, - IdentifierIndex, ModuleHandleIndex, Signature, SignatureIndex, SignatureToken, - Visibility::Public, -}; -use move_core_types::{identifier::Identifier, vm_status::StatusCode}; - -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], - }), - }); - - // 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], - }), - }); - - // 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], - }), - }); - - // 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], - }), - }); - - // 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![], - }), - }); - - 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 result = move_bytecode_verifier::verify_module_with_config_for_test( - "test_large_types", - &production_config(), - &m, - ); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::CONSTRAINT_NOT_SATISFIED, - ); -} diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/limit_tests.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/limit_tests.rs index 88333315429..7536f94c8d9 100644 --- a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/limit_tests.rs +++ b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/limit_tests.rs @@ -2,9 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use move_binary_format::file_format::*; -use move_bytecode_verifier::{ - limits::LimitsVerifier, verify_module_with_config_for_test, VerifierConfig, -}; +use move_bytecode_verifier::{limits::LimitsVerifier, verify_module_with_config, VerifierConfig}; use move_core_types::{ account_address::AccountAddress, identifier::Identifier, vm_status::StatusCode, }; @@ -245,8 +243,8 @@ fn big_vec_unpacks() { module.serialize(&mut mvbytes).unwrap(); let module = CompiledModule::deserialize(&mvbytes).unwrap(); - let res = verify_module_with_config_for_test( - "big_vec_unpacks", + // run with mainnet aptos config + let res = verify_module_with_config( &VerifierConfig { max_loop_depth: Some(5), max_generic_instantiation_length: Some(32), diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/locals.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/locals.rs deleted file mode 100644 index efca3030802..00000000000 --- a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/locals.rs +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) The Move Contributors -// SPDX-License-Identifier: Apache-2.0 - -use crate::unit_tests::production_config; -use move_binary_format::file_format::{ - empty_module, Bytecode, CodeUnit, FunctionDefinition, FunctionHandle, FunctionHandleIndex, - IdentifierIndex, ModuleHandleIndex, Signature, SignatureIndex, SignatureToken, - Visibility::Public, -}; -use move_core_types::{identifier::Identifier, vm_status::StatusCode}; - -#[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], - }), - }); - - // 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], - }), - }); - - // 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![], - }), - }); - - 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 as u8)); // i'th local is now available for the first time - code.push(Bytecode::BrTrue(0)); - } - code.push(Bytecode::Ret); - } - - let result = move_bytecode_verifier::verify_module_with_config_for_test( - "test_locals", - &production_config(), - &m, - ); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::CONSTRAINT_NOT_SATISFIED - ); -} diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/many_back_edges.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/many_back_edges.rs deleted file mode 100644 index cb9a7ac47fd..00000000000 --- a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/many_back_edges.rs +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) The Move Contributors -// SPDX-License-Identifier: Apache-2.0 - -use crate::unit_tests::production_config; -use move_binary_format::file_format::{ - empty_module, Bytecode, CodeUnit, FunctionDefinition, FunctionHandle, FunctionHandleIndex, - IdentifierIndex, ModuleHandleIndex, Signature, SignatureIndex, SignatureToken, - Visibility::Public, -}; -use move_core_types::{identifier::Identifier, vm_status::StatusCode}; - -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], - }), - }); - - // 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![], - }), - }); - - 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 as u8)); // i'th local is now available for the first time - code.push(Bytecode::BrTrue(0)); - } - code.push(Bytecode::Ret); - } - - let result = move_bytecode_verifier::verify_module_with_config_for_test( - "many_backedges", - &production_config(), - &m, - ); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::CONSTRAINT_NOT_SATISFIED - ); -} diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/mod.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/mod.rs index 325cdddcba7..49f60e9e5f6 100644 --- a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/mod.rs +++ b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/mod.rs @@ -2,52 +2,18 @@ // Copyright (c) The Move Contributors // SPDX-License-Identifier: Apache-2.0 -use move_bytecode_verifier::VerifierConfig; - pub mod ability_field_requirements_tests; -pub mod binary_samples; pub mod bounds_tests; -pub mod catch_unwind; pub mod code_unit_tests; pub mod constants_tests; pub mod control_flow_tests; pub mod dependencies_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 multi_pass_tests; pub mod negative_stack_size_tests; -pub mod reference_safety_tests; pub mod signature_tests; pub mod struct_defs_tests; pub mod vec_pack_tests; - -/// Configuration used in production. -pub(crate) fn production_config() -> VerifierConfig { - 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_struct_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, - - // Same as the default. - max_per_fun_meter_units: Some(1000 * 8000), - max_per_mod_meter_units: Some(1000 * 8000), - } -} diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/reference_safety_tests.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/reference_safety_tests.rs deleted file mode 100644 index e063280d8fd..00000000000 --- a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/reference_safety_tests.rs +++ /dev/null @@ -1,422 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// SPDX-License-Identifier: Apache-2.0 - -use crate::unit_tests::production_config; -use move_binary_format::file_format::{ - empty_module, Bytecode, CodeUnit, FunctionDefinition, FunctionHandle, FunctionHandleIndex, - IdentifierIndex, ModuleHandleIndex, Signature, SignatureIndex, SignatureToken, - Visibility::Public, -}; -use move_core_types::{identifier::Identifier, vm_status::StatusCode}; - -#[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], - }), - }); - - // 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![], - }), - }); - 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], - }), - }); - - // 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![], - }), - }); - 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 result = move_bytecode_verifier::verify_module_with_config_for_test( - "test_bicliques", - &production_config(), - &m, - ); - 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], - }), - }); - - 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], - }), - }); - - 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], - }), - }); - - 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![], - }), - }); - 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 res = move_bytecode_verifier::verify_module_with_config_for_test( - "test_merge_state_large_graph", - &production_config(), - &m, - ); - assert_eq!( - res.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], - }), - }); - - 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![], - }), - }); - 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 res = move_bytecode_verifier::verify_module_with_config_for_test( - "test_merge_state", - &production_config(), - &m, - ); - assert_eq!( - res.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![], - }), - }); - 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 result = move_bytecode_verifier::verify_module_with_config_for_test( - "test_copyloc_pop", - &production_config(), - &m, - ); - assert_eq!( - result.unwrap_err().major_status(), - StatusCode::CONSTRAINT_NOT_SATISFIED - ); -} diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/signature_tests.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/signature_tests.rs index 30729e5a17b..b451fc2f854 100644 --- a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/signature_tests.rs +++ b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/signature_tests.rs @@ -2,12 +2,13 @@ // Copyright (c) The Move Contributors // SPDX-License-Identifier: Apache-2.0 -use crate::unit_tests::production_config; use invalid_mutations::signature::{FieldRefMutation, SignatureRefMutation}; use move_binary_format::file_format::{ Bytecode::*, CompiledModule, SignatureToken::*, Visibility::Public, *, }; -use move_bytecode_verifier::{verify_module, verify_module_with_config_for_test, SignatureChecker}; +use move_bytecode_verifier::{ + verify_module, verify_module_with_config, SignatureChecker, VerifierConfig, +}; use move_core_types::{ account_address::AccountAddress, identifier::Identifier, vm_status::StatusCode, }; @@ -213,8 +214,23 @@ fn big_signature_test() { module.serialize(&mut mvbytes).unwrap(); let module = CompiledModule::deserialize(&mvbytes).unwrap(); - let res = - verify_module_with_config_for_test("big_signature_test", &production_config(), &module) - .unwrap_err(); + // run with mainnet aptos config + let res = verify_module_with_config( + &VerifierConfig { + max_loop_depth: Some(5), + max_generic_instantiation_length: Some(32), + max_function_parameters: Some(128), + max_basic_blocks: Some(1024), + max_value_stack_size: 1024, + max_type_nodes: Some(256), + max_push_size: Some(10000), + max_dependency_depth: Some(100), + max_struct_definitions: Some(200), + max_fields_in_struct: Some(30), + max_function_definitions: Some(1000), + }, + &module, + ) + .unwrap_err(); assert_eq!(res.major_status(), StatusCode::TOO_MANY_TYPE_NODES); } diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/vec_pack_tests.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/vec_pack_tests.rs index 8a1b5b27f96..07d9eb5dc38 100644 --- a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/vec_pack_tests.rs +++ b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/vec_pack_tests.rs @@ -1,11 +1,11 @@ // Copyright (c) The Move Contributors // SPDX-License-Identifier: Apache-2.0 -use crate::unit_tests::production_config; use move_binary_format::file_format::{ empty_module, Bytecode, CodeUnit, FunctionDefinition, FunctionHandle, FunctionHandleIndex, IdentifierIndex, ModuleHandleIndex, Signature, SignatureIndex, SignatureToken, Visibility, }; +use move_bytecode_verifier::VerifierConfig; use move_core_types::{identifier::Identifier, vm_status::StatusCode}; fn vec_sig(len: usize) -> SignatureToken { @@ -59,9 +59,20 @@ fn test_vec_pack() { .cloned() .collect(); - let res = move_bytecode_verifier::verify_module_with_config_for_test( - "test_vec_pack", - &production_config(), + let res = move_bytecode_verifier::verify_module_with_config( + &VerifierConfig { + max_loop_depth: Some(5), + max_generic_instantiation_length: Some(32), + max_function_parameters: Some(128), + max_basic_blocks: Some(1024), + max_value_stack_size: 1024, + max_type_nodes: Some(256), + max_push_size: Some(10000), + max_dependency_depth: Some(100), + max_struct_definitions: Some(200), + max_fields_in_struct: Some(30), + max_function_definitions: Some(1000), + }, &m, ) .unwrap_err(); diff --git a/language/move-bytecode-verifier/src/absint.rs b/language/move-bytecode-verifier/src/absint.rs index b8abec21afa..d43870c011d 100644 --- a/language/move-bytecode-verifier/src/absint.rs +++ b/language/move-bytecode-verifier/src/absint.rs @@ -2,7 +2,6 @@ // Copyright (c) The Move Contributors // SPDX-License-Identifier: Apache-2.0 -use crate::meter::Meter; use move_binary_format::{ binary_views::FunctionView, control_flow_graph::{BlockId, ControlFlowGraph}, @@ -14,7 +13,7 @@ use std::collections::BTreeMap; /// 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) -> PartialVMResult; + fn join(&mut self, other: &Self) -> JoinResult; } #[derive(Debug)] @@ -55,7 +54,6 @@ pub trait TransferFunctions { instr: &Bytecode, index: CodeOffset, last_index: CodeOffset, - meter: &mut impl Meter, ) -> PartialVMResult<()>; } @@ -65,7 +63,6 @@ pub trait AbstractInterpreter: TransferFunctions { &mut self, initial_state: Self::State, function_view: &FunctionView, - meter: &mut impl Meter, ) -> PartialVMResult<()> { let mut inv_map = InvariantMap::new(); let entry_block_id = function_view.cfg().entry_block_id(); @@ -86,7 +83,7 @@ pub trait AbstractInterpreter: TransferFunctions { 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_view, meter)?; + let post_state = self.execute_block(block_id, pre_state, function_view)?; let mut next_block_candidate = function_view.cfg().next_block(block_id); // propagate postcondition of this block to successor blocks @@ -95,8 +92,8 @@ pub trait AbstractInterpreter: TransferFunctions { Some(next_block_invariant) => { let join_result = { let old_pre = &mut next_block_invariant.pre; - old_pre.join(&post_state, meter) - }?; + old_pre.join(&post_state) + }; match join_result { JoinResult::Unchanged => { // Pre is the same after join. Reanalyzing this block would produce @@ -136,13 +133,12 @@ pub trait AbstractInterpreter: TransferFunctions { block_id: BlockId, pre_state: &Self::State, function_view: &FunctionView, - meter: &mut impl Meter, ) -> PartialVMResult { let mut state_acc = pre_state.clone(); let block_end = function_view.cfg().block_end(block_id); for offset in function_view.cfg().instr_indexes(block_id) { let instr = &function_view.code().code[offset as usize]; - self.execute(&mut state_acc, instr, offset, block_end, meter)? + self.execute(&mut state_acc, instr, offset, block_end)? } Ok(state_acc) } diff --git a/language/move-bytecode-verifier/src/acquires_list_verifier.rs b/language/move-bytecode-verifier/src/acquires_list_verifier.rs index 9bad9e57310..8454c56eb88 100644 --- a/language/move-bytecode-verifier/src/acquires_list_verifier.rs +++ b/language/move-bytecode-verifier/src/acquires_list_verifier.rs @@ -13,7 +13,6 @@ use std::collections::{BTreeSet, HashMap}; -use crate::meter::Meter; use move_binary_format::{ access::ModuleAccess, errors::{PartialVMError, PartialVMResult}, @@ -38,9 +37,8 @@ impl<'a> AcquiresVerifier<'a> { module: &'a CompiledModule, index: FunctionDefinitionIndex, function_definition: &'a FunctionDefinition, - _meter: &mut impl Meter, // currently unused ) -> PartialVMResult<()> { - let annotated_acquires: BTreeSet<_> = function_definition + let annotated_acquires = function_definition .acquires_global_resources .iter() .cloned() diff --git a/language/move-bytecode-verifier/src/code_unit_verifier.rs b/language/move-bytecode-verifier/src/code_unit_verifier.rs index 265d86f3c2e..d6387c4ad7a 100644 --- a/language/move-bytecode-verifier/src/code_unit_verifier.rs +++ b/language/move-bytecode-verifier/src/code_unit_verifier.rs @@ -6,13 +6,8 @@ //! The overall verification is split between stack_usage_verifier.rs and //! abstract_interpreter.rs. CodeUnitVerifier simply orchestrates calls into these two files. use crate::{ - acquires_list_verifier::AcquiresVerifier, - control_flow, locals_safety, - meter::{BoundMeter, Meter, Scope}, - reference_safety, - stack_usage_verifier::StackUsageVerifier, - type_safety, - verifier::VerifierConfig, + acquires_list_verifier::AcquiresVerifier, control_flow, locals_safety, reference_safety, + stack_usage_verifier::StackUsageVerifier, type_safety, verifier::VerifierConfig, }; use move_binary_format::{ access::ModuleAccess, @@ -47,30 +42,21 @@ impl<'a> CodeUnitVerifier<'a> { verifier_config: &VerifierConfig, module: &CompiledModule, ) -> PartialVMResult<()> { - let mut meter = BoundMeter::new(verifier_config); 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 = Self::verify_function( + Self::verify_function( verifier_config, index, function_definition, module, &name_def_map, - &mut 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)); - } + .map_err(|err| err.at_index(IndexKind::FunctionDefinition, index.0))? } Ok(()) } @@ -86,32 +72,17 @@ impl<'a> CodeUnitVerifier<'a> { verifier_config: &VerifierConfig, script: &'a CompiledScript, ) -> PartialVMResult<()> { - let mut meter = BoundMeter::new(verifier_config); // create `FunctionView` and `BinaryIndexedView` let function_view = control_flow::verify_script(verifier_config, script)?; let resolver = BinaryIndexedView::Script(script); let name_def_map = HashMap::new(); - - if let Some(limit) = verifier_config.max_basic_blocks_in_script { - if function_view.cfg().blocks().len() > limit { - return Err(PartialVMError::new(StatusCode::TOO_MANY_BASIC_BLOCKS)); - } - } - - if let Some(limit) = verifier_config.max_back_edges_per_function { - if function_view.cfg().num_back_edges() > limit { - return Err(PartialVMError::new(StatusCode::TOO_MANY_BACK_EDGES)); - } - } - //verify - meter.enter_scope("script", Scope::Function); let code_unit_verifier = CodeUnitVerifier { resolver, function_view, name_def_map: &name_def_map, }; - code_unit_verifier.verify_common(verifier_config, &mut meter) + code_unit_verifier.verify_common(verifier_config) } fn verify_function( @@ -120,18 +91,11 @@ impl<'a> CodeUnitVerifier<'a> { function_definition: &FunctionDefinition, module: &CompiledModule, name_def_map: &HashMap, - meter: &mut impl Meter, - ) -> PartialVMResult { - meter.enter_scope( - module - .identifier_at(module.function_handle_at(function_definition.function).name) - .as_str(), - Scope::Function, - ); + ) -> PartialVMResult<()> { // nothing to verify for native function let code = match &function_definition.code { Some(code) => code, - None => return Ok(0), + None => return Ok(()), }; // create `FunctionView` and `BinaryIndexedView` @@ -141,7 +105,6 @@ impl<'a> CodeUnitVerifier<'a> { index, function_definition, code, - meter, )?; if let Some(limit) = verifier_config.max_basic_blocks { @@ -152,15 +115,6 @@ impl<'a> CodeUnitVerifier<'a> { } } - let num_back_edges = function_view.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) - ); - } - } - let resolver = BinaryIndexedView::Module(module); // verify let code_unit_verifier = CodeUnitVerifier { @@ -168,27 +122,14 @@ impl<'a> CodeUnitVerifier<'a> { function_view, name_def_map, }; - code_unit_verifier.verify_common(verifier_config, meter)?; - AcquiresVerifier::verify(module, index, function_definition, meter)?; - - meter.transfer(Scope::Function, Scope::Module, 1.0)?; - - Ok(num_back_edges) + code_unit_verifier.verify_common(verifier_config)?; + AcquiresVerifier::verify(module, index, function_definition) } - fn verify_common( - &self, - verifier_config: &VerifierConfig, - meter: &mut impl Meter, - ) -> PartialVMResult<()> { - StackUsageVerifier::verify(verifier_config, &self.resolver, &self.function_view, meter)?; - type_safety::verify(&self.resolver, &self.function_view, meter)?; - locals_safety::verify(&self.resolver, &self.function_view, meter)?; - reference_safety::verify( - &self.resolver, - &self.function_view, - self.name_def_map, - meter, - ) + fn verify_common(&self, verifier_config: &VerifierConfig) -> PartialVMResult<()> { + StackUsageVerifier::verify(verifier_config, &self.resolver, &self.function_view)?; + type_safety::verify(&self.resolver, &self.function_view)?; + locals_safety::verify(&self.resolver, &self.function_view)?; + reference_safety::verify(&self.resolver, &self.function_view, self.name_def_map) } } diff --git a/language/move-bytecode-verifier/src/control_flow.rs b/language/move-bytecode-verifier/src/control_flow.rs index 6012684be1a..737485da80c 100644 --- a/language/move-bytecode-verifier/src/control_flow.rs +++ b/language/move-bytecode-verifier/src/control_flow.rs @@ -15,7 +15,6 @@ use crate::{ control_flow_v5, loop_summary::{LoopPartition, LoopSummary}, - meter::Meter, verifier::VerifierConfig, }; use move_binary_format::{ @@ -38,7 +37,6 @@ pub fn verify_function<'a>( index: FunctionDefinitionIndex, function_definition: &'a FunctionDefinition, code: &'a CodeUnit, - _meter: &mut impl Meter, // TODO: metering ) -> PartialVMResult> { let function_handle = module.function_handle_at(function_definition.function); diff --git a/language/move-bytecode-verifier/src/lib.rs b/language/move-bytecode-verifier/src/lib.rs index 11fd9eb90da..f1254ff0930 100644 --- a/language/move-bytecode-verifier/src/lib.rs +++ b/language/move-bytecode-verifier/src/lib.rs @@ -35,13 +35,12 @@ pub use script_signature::{ pub use signature::SignatureChecker; pub use struct_defs::RecursiveStructDefChecker; pub use verifier::{ - verify_module, verify_module_with_config, verify_module_with_config_for_test, verify_script, - verify_script_with_config, VerifierConfig, + verify_module, verify_module_with_config, verify_script, verify_script_with_config, + VerifierConfig, }; mod acquires_list_verifier; mod locals_safety; -pub mod meter; mod reference_safety; mod regression_tests; mod stack_usage_verifier; diff --git a/language/move-bytecode-verifier/src/locals_safety/abstract_state.rs b/language/move-bytecode-verifier/src/locals_safety/abstract_state.rs index 099a679ad72..7e43a7962a0 100644 --- a/language/move-bytecode-verifier/src/locals_safety/abstract_state.rs +++ b/language/move-bytecode-verifier/src/locals_safety/abstract_state.rs @@ -23,14 +23,8 @@ pub(crate) enum LocalState { /// The local has a value Available, } -use crate::meter::{Meter, Scope}; use LocalState::*; -pub(crate) const STEP_BASE_COST: u128 = 15; -pub(crate) const RET_PER_LOCAL_COST: u128 = 30; -pub(crate) const JOIN_BASE_COST: u128 = 10; -pub(crate) const JOIN_PER_LOCAL_COST: u128 = 5; - #[derive(Clone, Debug, Eq, PartialEq)] pub(crate) struct AbstractState { current_function: Option, @@ -136,17 +130,7 @@ impl AbstractState { impl AbstractDomain for AbstractState { /// attempts to join state to self and returns the result - fn join( - &mut self, - state: &AbstractState, - meter: &mut impl Meter, - ) -> PartialVMResult { - meter.add(Scope::Function, JOIN_BASE_COST)?; - meter.add_items( - Scope::Function, - JOIN_PER_LOCAL_COST, - state.local_states.len(), - )?; + fn join(&mut self, state: &AbstractState) -> JoinResult { let joined = Self::join_(self, state); assert!(self.local_states.len() == joined.local_states.len()); let locals_unchanged = self @@ -155,10 +139,10 @@ impl AbstractDomain for AbstractState { .zip(&joined.local_states) .all(|(self_state, other_state)| self_state == other_state); if locals_unchanged { - Ok(JoinResult::Unchanged) + JoinResult::Unchanged } else { *self = joined; - Ok(JoinResult::Changed) + JoinResult::Changed } } } diff --git a/language/move-bytecode-verifier/src/locals_safety/mod.rs b/language/move-bytecode-verifier/src/locals_safety/mod.rs index 896bc8970b7..e552b887b3e 100644 --- a/language/move-bytecode-verifier/src/locals_safety/mod.rs +++ b/language/move-bytecode-verifier/src/locals_safety/mod.rs @@ -8,11 +8,7 @@ mod abstract_state; -use crate::{ - absint::{AbstractInterpreter, TransferFunctions}, - locals_safety::abstract_state::{RET_PER_LOCAL_COST, STEP_BASE_COST}, - meter::{Meter, Scope}, -}; +use crate::absint::{AbstractInterpreter, TransferFunctions}; use abstract_state::{AbstractState, LocalState}; use move_binary_format::{ binary_views::{BinaryIndexedView, FunctionView}, @@ -24,19 +20,16 @@ use move_core_types::vm_status::StatusCode; pub(crate) fn verify<'a>( resolver: &BinaryIndexedView, function_view: &'a FunctionView<'a>, - meter: &mut impl Meter, ) -> PartialVMResult<()> { let initial_state = AbstractState::new(resolver, function_view)?; - LocalsSafetyAnalysis().analyze_function(initial_state, function_view, meter) + LocalsSafetyAnalysis().analyze_function(initial_state, function_view) } fn execute_inner( state: &mut AbstractState, bytecode: &Bytecode, offset: CodeOffset, - meter: &mut impl Meter, ) -> PartialVMResult<()> { - meter.add(Scope::Function, STEP_BASE_COST)?; match bytecode { Bytecode::StLoc(idx) => match state.local_state(*idx) { LocalState::MaybeAvailable | LocalState::Available @@ -72,7 +65,6 @@ fn execute_inner( Bytecode::Ret => { let local_states = state.local_states(); - meter.add_items(Scope::Function, RET_PER_LOCAL_COST, local_states.len())?; let all_local_abilities = state.all_local_abilities(); assert!(local_states.len() == all_local_abilities.len()); for (local_state, local_abilities) in local_states.iter().zip(all_local_abilities) { @@ -175,9 +167,8 @@ impl TransferFunctions for LocalsSafetyAnalysis { bytecode: &Bytecode, index: CodeOffset, _last_index: CodeOffset, - meter: &mut impl Meter, ) -> PartialVMResult<()> { - execute_inner(state, bytecode, index, meter) + execute_inner(state, bytecode, index) } } diff --git a/language/move-bytecode-verifier/src/meter.rs b/language/move-bytecode-verifier/src/meter.rs deleted file mode 100644 index 2e53fdadd04..00000000000 --- a/language/move-bytecode-verifier/src/meter.rs +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright (c) The Move Contributors -// SPDX-License-Identifier: Apache-2.0 - -use crate::VerifierConfig; -use move_binary_format::errors::{PartialVMError, PartialVMResult}; -use move_core_types::vm_status::StatusCode; -use std::ops::Mul; - -/// Scope of meterinng -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub enum Scope { - // Metering is for module level - Module, - // Metering is for function level - Function, -} - -/// Trait for a metering verification. -pub trait Meter { - /// Indicates the begin of a new scope. - fn enter_scope(&mut self, name: &str, scope: Scope); - - /// Transfer the amount of metering from once scope to the next. If the current scope has - /// metered N units, the target scope will be charged with N*factor. - fn transfer(&mut self, from: Scope, to: Scope, factor: f32) -> PartialVMResult<()>; - - /// Add the number of units to the meter, returns an error if a limit is hit. - fn add(&mut self, scope: Scope, units: u128) -> PartialVMResult<()>; - - /// Adds the number of items. - fn add_items( - &mut self, - scope: Scope, - units_per_item: u128, - items: usize, - ) -> PartialVMResult<()> { - if items == 0 { - return Ok(()); - } - self.add(scope, units_per_item.saturating_mul(items as u128)) - } - - /// Adds the number of items with growth factor - fn add_items_with_growth( - &mut self, - scope: Scope, - mut units_per_item: u128, - items: usize, - growth_factor: f32, - ) -> PartialVMResult<()> { - if items == 0 { - return Ok(()); - } - for _ in 0..items { - self.add(scope, units_per_item)?; - units_per_item = growth_factor.mul(units_per_item as f32) as u128; - } - Ok(()) - } -} - -pub struct BoundMeter { - mod_bounds: Bounds, - fun_bounds: Bounds, -} - -struct Bounds { - name: String, - units: u128, - max: Option, -} - -impl Meter for BoundMeter { - fn enter_scope(&mut self, name: &str, scope: Scope) { - let bounds = self.get_bounds(scope); - bounds.name = name.into(); - bounds.units = 0; - } - - fn transfer(&mut self, from: Scope, to: Scope, factor: f32) -> PartialVMResult<()> { - let units = (self.get_bounds(from).units as f32 * factor) as u128; - self.add(to, units) - } - - fn add(&mut self, scope: Scope, units: u128) -> PartialVMResult<()> { - self.get_bounds(scope).add(units) - } -} - -impl Bounds { - fn add(&mut self, units: u128) -> PartialVMResult<()> { - if let Some(max) = self.max { - let new_units = self.units.saturating_add(units); - if new_units > max { - // TODO: change to a new status PROGRAM_TOO_COMPLEX once this is rolled out. For - // now we use an existing code to avoid breaking changes on potential rollback. - return Err(PartialVMError::new(StatusCode::CONSTRAINT_NOT_SATISFIED) - .with_message(format!( - "program too complex (in `{}` with `{} current + {} new > {} max`)", - self.name, self.units, units, max - ))); - } - self.units = new_units; - } - Ok(()) - } -} - -impl BoundMeter { - pub fn new(config: &VerifierConfig) -> Self { - Self { - mod_bounds: Bounds { - name: "".to_string(), - units: 0, - max: config.max_per_fun_meter_units, - }, - fun_bounds: Bounds { - name: "".to_string(), - units: 0, - max: config.max_per_fun_meter_units, - }, - } - } - - fn get_bounds(&mut self, scope: Scope) -> &mut Bounds { - if scope == Scope::Module { - &mut self.mod_bounds - } else { - &mut self.fun_bounds - } - } -} - -pub struct DummyMeter; -impl Meter for DummyMeter { - fn enter_scope(&mut self, _name: &str, _scope: Scope) {} - fn transfer(&mut self, _from: Scope, _to: Scope, _factor: f32) -> PartialVMResult<()> { - Ok(()) - } - fn add(&mut self, _scope: Scope, _units: u128) -> PartialVMResult<()> { - Ok(()) - } -} diff --git a/language/move-bytecode-verifier/src/reference_safety/abstract_state.rs b/language/move-bytecode-verifier/src/reference_safety/abstract_state.rs index 7a0a627db37..db148f0f258 100644 --- a/language/move-bytecode-verifier/src/reference_safety/abstract_state.rs +++ b/language/move-bytecode-verifier/src/reference_safety/abstract_state.rs @@ -3,10 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 //! This module defines the abstract state for the type and memory safety analysis. -use crate::{ - absint::{AbstractDomain, JoinResult}, - meter::{Meter, Scope}, -}; +use crate::absint::{AbstractDomain, JoinResult}; use move_binary_format::{ binary_views::FunctionView, errors::{PartialVMError, PartialVMResult}, @@ -72,20 +69,6 @@ impl std::fmt::Display for Label { } } -pub(crate) const STEP_BASE_COST: u128 = 10; -pub(crate) const STEP_PER_LOCAL_COST: u128 = 20; -pub(crate) const STEP_PER_GRAPH_ITEM_COST: u128 = 50; -pub(crate) const JOIN_BASE_COST: u128 = 100; -pub(crate) const JOIN_PER_LOCAL_COST: u128 = 10; -pub(crate) const JOIN_PER_GRAPH_ITEM_COST: u128 = 50; - -// The cost for an edge from an input reference parameter to output reference. -pub(crate) const REF_PARAM_EDGE_COST: u128 = 100; -pub(crate) const REF_PARAM_EDGE_COST_GROWTH: f32 = 1.5; - -// The cost of an acquires in a call. -pub(crate) const CALL_PER_ACQUIRES_COST: u128 = 100; - /// AbstractState is the analysis state over which abstract interpretation is performed. #[derive(Clone, Debug, PartialEq, Eq)] pub(crate) struct AbstractState { @@ -129,14 +112,6 @@ impl AbstractState { state } - pub(crate) fn local_count(&self) -> usize { - self.locals.len() - } - - pub(crate) fn graph_size(&self) -> usize { - self.borrow_graph.graph_size() - } - /// returns the frame root id fn frame_root(&self) -> RefID { RefID::new(self.num_locals) @@ -522,13 +497,7 @@ impl AbstractState { arguments: Vec, acquired_resources: &BTreeSet, return_: &Signature, - meter: &mut impl Meter, ) -> PartialVMResult> { - meter.add_items( - Scope::Function, - CALL_PER_ACQUIRES_COST, - acquired_resources.len(), - )?; // Check acquires for acquired_resource in acquired_resources { if self.is_global_borrowed(*acquired_resource) { @@ -552,7 +521,6 @@ impl AbstractState { } // Track borrow relationships of return values on inputs - let mut returned_refs = 0; let return_values = return_ .0 .iter() @@ -562,7 +530,6 @@ impl AbstractState { for parent in &mutable_references_to_borrow_from { self.add_borrow(*parent, id); } - returned_refs += 1; AbstractValue::Reference(id) } SignatureToken::Reference(_) => { @@ -570,23 +537,12 @@ impl AbstractState { for parent in &all_references_to_borrow_from { self.add_borrow(*parent, id); } - returned_refs += 1; AbstractValue::Reference(id) } _ => AbstractValue::NonReference, }) .collect(); - // Meter usage of reference edges - meter.add_items_with_growth( - Scope::Function, - REF_PARAM_EDGE_COST, - all_references_to_borrow_from - .len() - .saturating_mul(returned_refs), - REF_PARAM_EDGE_COST_GROWTH, - )?; - // Release input references for id in all_references_to_borrow_from { self.release(id) @@ -730,33 +686,19 @@ impl AbstractState { impl AbstractDomain for AbstractState { /// attempts to join state to self and returns the result - fn join( - &mut self, - state: &AbstractState, - meter: &mut impl Meter, - ) -> PartialVMResult { + fn join(&mut self, state: &AbstractState) -> JoinResult { let joined = Self::join_(self, state); assert!(joined.is_canonical()); - assert!(self.locals.len() == joined.locals.len()); - meter.add(Scope::Function, JOIN_BASE_COST)?; - meter.add_items(Scope::Function, JOIN_PER_LOCAL_COST, self.locals.len())?; - meter.add_items( - Scope::Function, - JOIN_PER_GRAPH_ITEM_COST, - self.borrow_graph.graph_size(), - )?; + assert!(self.num_locals == joined.num_locals); let locals_unchanged = self - .locals - .iter() - .zip(&joined.locals) - .all(|(self_value, joined_value)| self_value == joined_value); - // locals unchanged and borrow graph covered, return unchanged - // else mark as changed and update the state - if locals_unchanged && self.borrow_graph.leq(&joined.borrow_graph) { - Ok(JoinResult::Unchanged) + .iter_locals() + .all(|idx| self.locals.get(&idx) == joined.locals.get(&idx)); + let borrow_graph_unchanged = self.borrow_graph.leq(&joined.borrow_graph); + if locals_unchanged && borrow_graph_unchanged { + JoinResult::Unchanged } else { *self = joined; - Ok(JoinResult::Changed) + JoinResult::Changed } } } diff --git a/language/move-bytecode-verifier/src/reference_safety/mod.rs b/language/move-bytecode-verifier/src/reference_safety/mod.rs index 724c036e2ab..dfd77df3841 100644 --- a/language/move-bytecode-verifier/src/reference_safety/mod.rs +++ b/language/move-bytecode-verifier/src/reference_safety/mod.rs @@ -10,13 +10,7 @@ mod abstract_state; -use crate::{ - absint::{AbstractInterpreter, TransferFunctions}, - meter::{Meter, Scope}, - reference_safety::abstract_state::{ - STEP_BASE_COST, STEP_PER_GRAPH_ITEM_COST, STEP_PER_LOCAL_COST, - }, -}; +use crate::absint::{AbstractInterpreter, TransferFunctions}; use abstract_state::{AbstractState, AbstractValue}; use move_binary_format::{ binary_views::{BinaryIndexedView, FunctionView}, @@ -56,12 +50,11 @@ pub(crate) fn verify<'a>( resolver: &'a BinaryIndexedView<'a>, function_view: &FunctionView, name_def_map: &'a HashMap, - meter: &mut impl Meter, ) -> PartialVMResult<()> { let initial_state = AbstractState::new(function_view); let mut verifier = ReferenceSafetyAnalysis::new(resolver, function_view, name_def_map); - verifier.analyze_function(initial_state, function_view, meter) + verifier.analyze_function(initial_state, function_view) } fn call( @@ -69,7 +62,6 @@ fn call( state: &mut AbstractState, offset: CodeOffset, function_handle: &FunctionHandle, - meter: &mut impl Meter, ) -> PartialVMResult<()> { let parameters = verifier.resolver.signature_at(function_handle.parameters); let arguments = parameters @@ -92,7 +84,7 @@ fn call( None => BTreeSet::new(), }; let return_ = verifier.resolver.signature_at(function_handle.return_); - let values = state.call(offset, arguments, &acquired_resources, return_, meter)?; + let values = state.call(offset, arguments, &acquired_resources, return_)?; for value in values { verifier.stack.push(value) } @@ -147,16 +139,7 @@ fn execute_inner( state: &mut AbstractState, bytecode: &Bytecode, offset: CodeOffset, - meter: &mut impl Meter, ) -> PartialVMResult<()> { - meter.add(Scope::Function, STEP_BASE_COST)?; - meter.add_items(Scope::Function, STEP_PER_LOCAL_COST, state.local_count())?; - meter.add_items( - Scope::Function, - STEP_PER_GRAPH_ITEM_COST, - state.graph_size(), - )?; - match bytecode { Bytecode::Pop => state.release_value(safe_unwrap!(verifier.stack.pop())), @@ -266,12 +249,12 @@ fn execute_inner( Bytecode::Call(idx) => { let function_handle = verifier.resolver.function_handle_at(*idx); - call(verifier, state, offset, function_handle, meter)? + call(verifier, state, offset, function_handle)? } Bytecode::CallGeneric(idx) => { let func_inst = verifier.resolver.function_instantiation_at(*idx); let function_handle = verifier.resolver.function_handle_at(func_inst.handle); - call(verifier, state, offset, function_handle, meter)? + call(verifier, state, offset, function_handle)? } Bytecode::Ret => { @@ -433,9 +416,8 @@ impl<'a> TransferFunctions for ReferenceSafetyAnalysis<'a> { bytecode: &Bytecode, index: CodeOffset, last_index: CodeOffset, - meter: &mut impl Meter, ) -> PartialVMResult<()> { - execute_inner(self, state, bytecode, index, meter)?; + execute_inner(self, state, bytecode, index)?; if index == last_index { safe_assert!(self.stack.is_empty()); *state = state.construct_canonical_state() diff --git a/language/move-bytecode-verifier/src/stack_usage_verifier.rs b/language/move-bytecode-verifier/src/stack_usage_verifier.rs index b0a84298b27..bb4b112e5c1 100644 --- a/language/move-bytecode-verifier/src/stack_usage_verifier.rs +++ b/language/move-bytecode-verifier/src/stack_usage_verifier.rs @@ -9,7 +9,7 @@ //! the stack height by the number of values returned by the function as indicated in its //! signature. Additionally, the stack height must not dip below that at the beginning of the //! block for any basic block. -use crate::{meter::Meter, VerifierConfig}; +use crate::VerifierConfig; use move_binary_format::{ binary_views::{BinaryIndexedView, FunctionView}, control_flow_graph::{BlockId, ControlFlowGraph}, @@ -30,7 +30,6 @@ impl<'a> StackUsageVerifier<'a> { config: &VerifierConfig, resolver: &'a BinaryIndexedView<'a>, function_view: &'a FunctionView, - _meter: &mut impl Meter, // TODO: metering ) -> PartialVMResult<()> { let verifier = Self { resolver, diff --git a/language/move-bytecode-verifier/src/type_safety.rs b/language/move-bytecode-verifier/src/type_safety.rs index 605b2a6d84c..eb1ed2df188 100644 --- a/language/move-bytecode-verifier/src/type_safety.rs +++ b/language/move-bytecode-verifier/src/type_safety.rs @@ -5,7 +5,6 @@ //! This module defines the transfer functions for verifying type safety of a procedure body. //! It does not utilize control flow, but does check each block independently -use crate::meter::{Meter, Scope}; use move_binary_format::{ binary_views::{BinaryIndexedView, FunctionView}, control_flow_graph::ControlFlowGraph, @@ -25,8 +24,6 @@ struct Locals<'a> { locals: &'a Signature, } -const TYPE_NODE_COST: u128 = 30; - impl<'a> Locals<'a> { fn new(parameters: &'a Signature, locals: &'a Signature) -> Self { Self { @@ -81,44 +78,18 @@ impl<'a> TypeSafetyChecker<'a> { offset, ) } - - fn push(&mut self, meter: &mut impl Meter, ty: SignatureToken) -> PartialVMResult<()> { - self.charge_ty(meter, &ty)?; - self.stack.push(ty); - Ok(()) - } - - fn charge_ty(&mut self, meter: &mut impl Meter, ty: &SignatureToken) -> PartialVMResult<()> { - meter.add_items( - Scope::Function, - TYPE_NODE_COST, - ty.preorder_traversal().count(), - ) - } - - fn charge_tys( - &mut self, - meter: &mut impl Meter, - tys: &[SignatureToken], - ) -> PartialVMResult<()> { - for ty in tys { - self.charge_ty(meter, ty)? - } - Ok(()) - } } pub(crate) fn verify<'a>( resolver: &'a BinaryIndexedView<'a>, function_view: &'a FunctionView<'a>, - meter: &mut impl Meter, // currently unused ) -> PartialVMResult<()> { let verifier = &mut TypeSafetyChecker::new(resolver, function_view); for block_id in function_view.cfg().blocks() { for offset in function_view.cfg().instr_indexes(block_id) { let instr = &verifier.function_view.code().code[offset as usize]; - verify_instr(verifier, instr, offset, meter)? + verify_instr(verifier, instr, offset)? } } @@ -128,7 +99,6 @@ pub(crate) fn verify<'a>( // helper for both `ImmBorrowField` and `MutBorrowField` fn borrow_field( verifier: &mut TypeSafetyChecker, - meter: &mut impl Meter, offset: CodeOffset, mut_: bool, field_handle_index: FieldHandleIndex, @@ -163,21 +133,17 @@ fn borrow_field( } }; let field_type = Box::new(instantiate(&field_def.signature.0, type_args)); - verifier.push( - meter, - if mut_ { - ST::MutableReference(field_type) - } else { - ST::Reference(field_type) - }, - )?; + verifier.stack.push(if mut_ { + ST::MutableReference(field_type) + } else { + ST::Reference(field_type) + }); Ok(()) } // helper for both `ImmBorrowLoc` and `MutBorrowLoc` fn borrow_loc( verifier: &mut TypeSafetyChecker, - meter: &mut impl Meter, offset: CodeOffset, mut_: bool, idx: LocalIndex, @@ -188,20 +154,16 @@ fn borrow_loc( return Err(verifier.error(StatusCode::BORROWLOC_REFERENCE_ERROR, offset)); } - verifier.push( - meter, - if mut_ { - ST::MutableReference(Box::new(loc_signature)) - } else { - ST::Reference(Box::new(loc_signature)) - }, - )?; + verifier.stack.push(if mut_ { + ST::MutableReference(Box::new(loc_signature)) + } else { + ST::Reference(Box::new(loc_signature)) + }); Ok(()) } fn borrow_global( verifier: &mut TypeSafetyChecker, - meter: &mut impl Meter, offset: CodeOffset, mut_: bool, idx: StructDefinitionIndex, @@ -220,20 +182,16 @@ fn borrow_global( } let struct_type = materialize_type(struct_def.struct_handle, type_args); - verifier.push( - meter, - if mut_ { - ST::MutableReference(Box::new(struct_type)) - } else { - ST::Reference(Box::new(struct_type)) - }, - )?; + verifier.stack.push(if mut_ { + ST::MutableReference(Box::new(struct_type)) + } else { + ST::Reference(Box::new(struct_type)) + }); Ok(()) } fn call( verifier: &mut TypeSafetyChecker, - meter: &mut impl Meter, offset: CodeOffset, function_handle: &FunctionHandle, type_actuals: &Signature, @@ -241,21 +199,18 @@ fn call( let parameters = verifier.resolver.signature_at(function_handle.parameters); for parameter in parameters.0.iter().rev() { let arg = safe_unwrap!(verifier.stack.pop()); - if (type_actuals.is_empty() && &arg != parameter) - || (!type_actuals.is_empty() && arg != instantiate(parameter, type_actuals)) - { + if arg != instantiate(parameter, type_actuals) { return Err(verifier.error(StatusCode::CALL_TYPE_MISMATCH_ERROR, offset)); } } for return_type in &verifier.resolver.signature_at(function_handle.return_).0 { - verifier.push(meter, instantiate(return_type, type_actuals))? + verifier.stack.push(instantiate(return_type, type_actuals)) } Ok(()) } fn type_fields_signature( verifier: &mut TypeSafetyChecker, - _meter: &mut impl Meter, // TODO: metering offset: CodeOffset, struct_def: &StructDefinition, type_args: &Signature, @@ -277,13 +232,12 @@ fn type_fields_signature( fn pack( verifier: &mut TypeSafetyChecker, - meter: &mut impl Meter, offset: CodeOffset, struct_def: &StructDefinition, type_args: &Signature, ) -> PartialVMResult<()> { let struct_type = materialize_type(struct_def.struct_handle, type_args); - let field_sig = type_fields_signature(verifier, meter, offset, struct_def, type_args)?; + let field_sig = type_fields_signature(verifier, offset, struct_def, type_args)?; for sig in field_sig.0.iter().rev() { let arg = safe_unwrap!(verifier.stack.pop()); if &arg != sig { @@ -291,13 +245,12 @@ fn pack( } } - verifier.push(meter, struct_type)?; + verifier.stack.push(struct_type); Ok(()) } fn unpack( verifier: &mut TypeSafetyChecker, - meter: &mut impl Meter, offset: CodeOffset, struct_def: &StructDefinition, type_args: &Signature, @@ -311,16 +264,15 @@ fn unpack( return Err(verifier.error(StatusCode::UNPACK_TYPE_MISMATCH_ERROR, offset)); } - let field_sig = type_fields_signature(verifier, meter, offset, struct_def, type_args)?; + let field_sig = type_fields_signature(verifier, offset, struct_def, type_args)?; for sig in field_sig.0 { - verifier.push(meter, sig)? + verifier.stack.push(sig) } Ok(()) } fn exists( verifier: &mut TypeSafetyChecker, - meter: &mut impl Meter, offset: CodeOffset, struct_def: &StructDefinition, type_args: &Signature, @@ -342,13 +294,12 @@ fn exists( )); } - verifier.push(meter, ST::Bool)?; + verifier.stack.push(ST::Bool); Ok(()) } fn move_from( verifier: &mut TypeSafetyChecker, - meter: &mut impl Meter, offset: CodeOffset, struct_def: &StructDefinition, type_args: &Signature, @@ -364,7 +315,7 @@ fn move_from( return Err(verifier.error(StatusCode::MOVEFROM_TYPE_MISMATCH_ERROR, offset)); } - verifier.push(meter, struct_type)?; + verifier.stack.push(struct_type); Ok(()) } @@ -396,7 +347,6 @@ fn move_to( fn borrow_vector_element( verifier: &mut TypeSafetyChecker, - meter: &mut impl Meter, declared_element_type: &SignatureToken, offset: CodeOffset, mut_ref_only: bool, @@ -419,7 +369,7 @@ fn borrow_vector_element( } else { ST::Reference(Box::new(element_type)) }; - verifier.push(meter, element_ref_type)?; + verifier.stack.push(element_ref_type); Ok(()) } @@ -428,7 +378,6 @@ fn verify_instr( verifier: &mut TypeSafetyChecker, bytecode: &Bytecode, offset: CodeOffset, - meter: &mut impl Meter, ) -> PartialVMResult<()> { match bytecode { Bytecode::Pop => { @@ -477,14 +426,13 @@ fn verify_instr( Bytecode::FreezeRef => { let operand = safe_unwrap!(verifier.stack.pop()); match operand { - ST::MutableReference(inner) => verifier.push(meter, ST::Reference(inner))?, + ST::MutableReference(inner) => verifier.stack.push(ST::Reference(inner)), _ => return Err(verifier.error(StatusCode::FREEZEREF_TYPE_MISMATCH_ERROR, offset)), } } Bytecode::MutBorrowField(field_handle_index) => borrow_field( verifier, - meter, offset, true, *field_handle_index, @@ -496,13 +444,11 @@ fn verify_instr( .resolver .field_instantiation_at(*field_inst_index)?; let type_inst = verifier.resolver.signature_at(field_inst.type_parameters); - verifier.charge_tys(meter, &type_inst.0)?; - borrow_field(verifier, meter, offset, true, field_inst.handle, type_inst)? + borrow_field(verifier, offset, true, field_inst.handle, type_inst)? } Bytecode::ImmBorrowField(field_handle_index) => borrow_field( verifier, - meter, offset, false, *field_handle_index, @@ -514,41 +460,40 @@ fn verify_instr( .resolver .field_instantiation_at(*field_inst_index)?; let type_inst = verifier.resolver.signature_at(field_inst.type_parameters); - verifier.charge_tys(meter, &type_inst.0)?; - borrow_field(verifier, meter, offset, false, field_inst.handle, type_inst)? + borrow_field(verifier, offset, false, field_inst.handle, type_inst)? } Bytecode::LdU8(_) => { - verifier.push(meter, ST::U8)?; + verifier.stack.push(ST::U8); } Bytecode::LdU16(_) => { - verifier.push(meter, ST::U16)?; + verifier.stack.push(ST::U16); } Bytecode::LdU32(_) => { - verifier.push(meter, ST::U32)?; + verifier.stack.push(ST::U32); } Bytecode::LdU64(_) => { - verifier.push(meter, ST::U64)?; + verifier.stack.push(ST::U64); } Bytecode::LdU128(_) => { - verifier.push(meter, ST::U128)?; + verifier.stack.push(ST::U128); } Bytecode::LdU256(_) => { - verifier.push(meter, ST::U256)?; + verifier.stack.push(ST::U256); } Bytecode::LdConst(idx) => { let signature = verifier.resolver.constant_at(*idx).type_.clone(); - verifier.push(meter, signature)?; + verifier.stack.push(signature); } Bytecode::LdTrue | Bytecode::LdFalse => { - verifier.push(meter, ST::Bool)?; + verifier.stack.push(ST::Bool); } Bytecode::CopyLoc(idx) => { @@ -560,67 +505,52 @@ fn verify_instr( { return Err(verifier.error(StatusCode::COPYLOC_WITHOUT_COPY_ABILITY, offset)); } - verifier.push(meter, local_signature)? + verifier.stack.push(local_signature) } Bytecode::MoveLoc(idx) => { let local_signature = verifier.local_at(*idx).clone(); - verifier.push(meter, local_signature)? + verifier.stack.push(local_signature) } - Bytecode::MutBorrowLoc(idx) => borrow_loc(verifier, meter, offset, true, *idx)?, + Bytecode::MutBorrowLoc(idx) => borrow_loc(verifier, offset, true, *idx)?, - Bytecode::ImmBorrowLoc(idx) => borrow_loc(verifier, meter, offset, false, *idx)?, + Bytecode::ImmBorrowLoc(idx) => borrow_loc(verifier, offset, false, *idx)?, Bytecode::Call(idx) => { let function_handle = verifier.resolver.function_handle_at(*idx); - call(verifier, meter, offset, function_handle, &Signature(vec![]))? + call(verifier, offset, function_handle, &Signature(vec![]))? } Bytecode::CallGeneric(idx) => { let func_inst = verifier.resolver.function_instantiation_at(*idx); let func_handle = verifier.resolver.function_handle_at(func_inst.handle); let type_args = &verifier.resolver.signature_at(func_inst.type_parameters); - verifier.charge_tys(meter, &type_args.0)?; - call(verifier, meter, offset, func_handle, type_args)? + call(verifier, offset, func_handle, type_args)? } Bytecode::Pack(idx) => { let struct_definition = verifier.resolver.struct_def_at(*idx)?; - pack( - verifier, - meter, - offset, - struct_definition, - &Signature(vec![]), - )? + pack(verifier, offset, struct_definition, &Signature(vec![]))? } Bytecode::PackGeneric(idx) => { let struct_inst = verifier.resolver.struct_instantiation_at(*idx)?; let struct_def = verifier.resolver.struct_def_at(struct_inst.def)?; let type_args = verifier.resolver.signature_at(struct_inst.type_parameters); - verifier.charge_tys(meter, &type_args.0)?; - pack(verifier, meter, offset, struct_def, type_args)? + pack(verifier, offset, struct_def, type_args)? } Bytecode::Unpack(idx) => { let struct_definition = verifier.resolver.struct_def_at(*idx)?; - unpack( - verifier, - meter, - offset, - struct_definition, - &Signature(vec![]), - )? + unpack(verifier, offset, struct_definition, &Signature(vec![]))? } Bytecode::UnpackGeneric(idx) => { let struct_inst = verifier.resolver.struct_instantiation_at(*idx)?; let struct_def = verifier.resolver.struct_def_at(struct_inst.def)?; let type_args = verifier.resolver.signature_at(struct_inst.type_parameters); - verifier.charge_tys(meter, &type_args.0)?; - unpack(verifier, meter, offset, struct_def, type_args)? + unpack(verifier, offset, struct_def, type_args)? } Bytecode::ReadRef => { @@ -632,7 +562,7 @@ fn verify_instr( verifier.error(StatusCode::READREF_WITHOUT_COPY_ABILITY, offset) ); } - verifier.push(meter, *inner)?; + verifier.stack.push(*inner); } _ => return Err(verifier.error(StatusCode::READREF_TYPE_MISMATCH_ERROR, offset)), } @@ -663,21 +593,21 @@ fn verify_instr( if !operand.is_integer() { return Err(verifier.error(StatusCode::INTEGER_OP_TYPE_MISMATCH_ERROR, offset)); } - verifier.push(meter, ST::U8)?; + verifier.stack.push(ST::U8); } Bytecode::CastU64 => { let operand = safe_unwrap!(verifier.stack.pop()); if !operand.is_integer() { return Err(verifier.error(StatusCode::INTEGER_OP_TYPE_MISMATCH_ERROR, offset)); } - verifier.push(meter, ST::U64)?; + verifier.stack.push(ST::U64); } Bytecode::CastU128 => { let operand = safe_unwrap!(verifier.stack.pop()); if !operand.is_integer() { return Err(verifier.error(StatusCode::INTEGER_OP_TYPE_MISMATCH_ERROR, offset)); } - verifier.push(meter, ST::U128)?; + verifier.stack.push(ST::U128); } Bytecode::Add @@ -691,7 +621,7 @@ fn verify_instr( let operand1 = safe_unwrap!(verifier.stack.pop()); let operand2 = safe_unwrap!(verifier.stack.pop()); if operand1.is_integer() && operand1 == operand2 { - verifier.push(meter, operand1)?; + verifier.stack.push(operand1); } else { return Err(verifier.error(StatusCode::INTEGER_OP_TYPE_MISMATCH_ERROR, offset)); } @@ -701,7 +631,7 @@ fn verify_instr( let operand1 = safe_unwrap!(verifier.stack.pop()); let operand2 = safe_unwrap!(verifier.stack.pop()); if operand2.is_integer() && operand1 == ST::U8 { - verifier.push(meter, operand2)?; + verifier.stack.push(operand2); } else { return Err(verifier.error(StatusCode::INTEGER_OP_TYPE_MISMATCH_ERROR, offset)); } @@ -711,7 +641,7 @@ fn verify_instr( let operand1 = safe_unwrap!(verifier.stack.pop()); let operand2 = safe_unwrap!(verifier.stack.pop()); if operand1 == ST::Bool && operand2 == ST::Bool { - verifier.push(meter, ST::Bool)?; + verifier.stack.push(ST::Bool); } else { return Err(verifier.error(StatusCode::BOOLEAN_OP_TYPE_MISMATCH_ERROR, offset)); } @@ -720,7 +650,7 @@ fn verify_instr( Bytecode::Not => { let operand = safe_unwrap!(verifier.stack.pop()); if operand == ST::Bool { - verifier.push(meter, ST::Bool)?; + verifier.stack.push(ST::Bool); } else { return Err(verifier.error(StatusCode::BOOLEAN_OP_TYPE_MISMATCH_ERROR, offset)); } @@ -730,7 +660,7 @@ fn verify_instr( let operand1 = safe_unwrap!(verifier.stack.pop()); let operand2 = safe_unwrap!(verifier.stack.pop()); if verifier.abilities(&operand1)?.has_drop() && operand1 == operand2 { - verifier.push(meter, ST::Bool)?; + verifier.stack.push(ST::Bool); } else { return Err(verifier.error(StatusCode::EQUALITY_OP_TYPE_MISMATCH_ERROR, offset)); } @@ -740,58 +670,54 @@ fn verify_instr( let operand1 = safe_unwrap!(verifier.stack.pop()); let operand2 = safe_unwrap!(verifier.stack.pop()); if operand1.is_integer() && operand1 == operand2 { - verifier.push(meter, ST::Bool)? + verifier.stack.push(ST::Bool) } else { return Err(verifier.error(StatusCode::INTEGER_OP_TYPE_MISMATCH_ERROR, offset)); } } Bytecode::MutBorrowGlobal(idx) => { - borrow_global(verifier, meter, offset, true, *idx, &Signature(vec![]))? + borrow_global(verifier, offset, true, *idx, &Signature(vec![]))? } Bytecode::MutBorrowGlobalGeneric(idx) => { let struct_inst = verifier.resolver.struct_instantiation_at(*idx)?; let type_inst = verifier.resolver.signature_at(struct_inst.type_parameters); - verifier.charge_tys(meter, &type_inst.0)?; - borrow_global(verifier, meter, offset, true, struct_inst.def, type_inst)? + borrow_global(verifier, offset, true, struct_inst.def, type_inst)? } Bytecode::ImmBorrowGlobal(idx) => { - borrow_global(verifier, meter, offset, false, *idx, &Signature(vec![]))? + borrow_global(verifier, offset, false, *idx, &Signature(vec![]))? } Bytecode::ImmBorrowGlobalGeneric(idx) => { let struct_inst = verifier.resolver.struct_instantiation_at(*idx)?; let type_inst = verifier.resolver.signature_at(struct_inst.type_parameters); - verifier.charge_tys(meter, &type_inst.0)?; - borrow_global(verifier, meter, offset, false, struct_inst.def, type_inst)? + borrow_global(verifier, offset, false, struct_inst.def, type_inst)? } Bytecode::Exists(idx) => { let struct_def = verifier.resolver.struct_def_at(*idx)?; - exists(verifier, meter, offset, struct_def, &Signature(vec![]))? + exists(verifier, offset, struct_def, &Signature(vec![]))? } Bytecode::ExistsGeneric(idx) => { let struct_inst = verifier.resolver.struct_instantiation_at(*idx)?; let struct_def = verifier.resolver.struct_def_at(struct_inst.def)?; let type_args = verifier.resolver.signature_at(struct_inst.type_parameters); - verifier.charge_tys(meter, &type_args.0)?; - exists(verifier, meter, offset, struct_def, type_args)? + exists(verifier, offset, struct_def, type_args)? } Bytecode::MoveFrom(idx) => { let struct_def = verifier.resolver.struct_def_at(*idx)?; - move_from(verifier, meter, offset, struct_def, &Signature(vec![]))? + move_from(verifier, offset, struct_def, &Signature(vec![]))? } Bytecode::MoveFromGeneric(idx) => { let struct_inst = verifier.resolver.struct_instantiation_at(*idx)?; let struct_def = verifier.resolver.struct_def_at(struct_inst.def)?; let type_args = verifier.resolver.signature_at(struct_inst.type_parameters); - verifier.charge_tys(meter, &type_args.0)?; - move_from(verifier, meter, offset, struct_def, type_args)? + move_from(verifier, offset, struct_def, type_args)? } Bytecode::MoveTo(idx) => { @@ -803,7 +729,6 @@ fn verify_instr( let struct_inst = verifier.resolver.struct_instantiation_at(*idx)?; let struct_def = verifier.resolver.struct_def_at(struct_inst.def)?; let type_args = verifier.resolver.signature_at(struct_inst.type_parameters); - verifier.charge_tys(meter, &type_args.0)?; move_to(verifier, offset, struct_def, type_args)? } @@ -825,7 +750,7 @@ fn verify_instr( let declared_element_type = &verifier.resolver.signature_at(*idx).0[0]; match get_vector_element_type(operand, false) { Some(derived_element_type) if &derived_element_type == declared_element_type => { - verifier.push(meter, ST::U64)?; + verifier.stack.push(ST::U64); } _ => return Err(verifier.error(StatusCode::TYPE_MISMATCH, offset)), }; @@ -833,11 +758,11 @@ fn verify_instr( Bytecode::VecImmBorrow(idx) => { let declared_element_type = &verifier.resolver.signature_at(*idx).0[0]; - borrow_vector_element(verifier, meter, declared_element_type, offset, false)? + borrow_vector_element(verifier, declared_element_type, offset, false)? } Bytecode::VecMutBorrow(idx) => { let declared_element_type = &verifier.resolver.signature_at(*idx).0[0]; - borrow_vector_element(verifier, meter, declared_element_type, offset, true)? + borrow_vector_element(verifier, declared_element_type, offset, true)? } Bytecode::VecPushBack(idx) => { @@ -858,7 +783,7 @@ fn verify_instr( let declared_element_type = &verifier.resolver.signature_at(*idx).0[0]; match get_vector_element_type(operand_vec, true) { Some(derived_element_type) if &derived_element_type == declared_element_type => { - verifier.push(meter, derived_element_type)?; + verifier.stack.push(derived_element_type); } _ => return Err(verifier.error(StatusCode::TYPE_MISMATCH, offset)), }; @@ -871,7 +796,7 @@ fn verify_instr( return Err(verifier.error(StatusCode::TYPE_MISMATCH, offset)); } for _ in 0..*num { - verifier.push(meter, declared_element_type.clone())?; + verifier.stack.push(declared_element_type.clone()); } } @@ -893,21 +818,21 @@ fn verify_instr( if !operand.is_integer() { return Err(verifier.error(StatusCode::INTEGER_OP_TYPE_MISMATCH_ERROR, offset)); } - verifier.push(meter, ST::U16)?; + verifier.stack.push(ST::U16); } Bytecode::CastU32 => { let operand = safe_unwrap!(verifier.stack.pop()); if !operand.is_integer() { return Err(verifier.error(StatusCode::INTEGER_OP_TYPE_MISMATCH_ERROR, offset)); } - verifier.push(meter, ST::U32)?; + verifier.stack.push(ST::U32); } Bytecode::CastU256 => { let operand = safe_unwrap!(verifier.stack.pop()); if !operand.is_integer() { return Err(verifier.error(StatusCode::INTEGER_OP_TYPE_MISMATCH_ERROR, offset)); } - verifier.push(meter, ST::U256)?; + verifier.stack.push(ST::U256); } }; Ok(()) @@ -928,10 +853,6 @@ fn materialize_type(struct_handle: StructHandleIndex, type_args: &Signature) -> fn instantiate(token: &SignatureToken, subst: &Signature) -> SignatureToken { use SignatureToken::*; - if subst.0.is_empty() { - return token.clone(); - } - match token { Bool => Bool, U8 => U8, diff --git a/language/move-bytecode-verifier/src/verifier.rs b/language/move-bytecode-verifier/src/verifier.rs index c1dafda57f2..a103d3313db 100644 --- a/language/move-bytecode-verifier/src/verifier.rs +++ b/language/move-bytecode-verifier/src/verifier.rs @@ -13,11 +13,9 @@ use crate::{ }; use move_binary_format::{ check_bounds::BoundsChecker, - errors::{Location, PartialVMError, VMResult}, + errors::{Location, VMResult}, file_format::{CompiledModule, CompiledScript}, }; -use move_core_types::{state::VMState, vm_status::StatusCode}; -use std::time::Instant; #[derive(Debug, Clone)] pub struct VerifierConfig { @@ -32,11 +30,6 @@ pub struct VerifierConfig { pub max_struct_definitions: Option, pub max_fields_in_struct: Option, pub max_function_definitions: Option, - pub max_back_edges_per_function: Option, - pub max_back_edges_per_module: Option, - pub max_basic_blocks_in_script: Option, - pub max_per_fun_meter_units: Option, - pub max_per_mod_meter_units: Option, } /// Helper for a "canonical" verification of a module. @@ -53,69 +46,23 @@ pub fn verify_module(module: &CompiledModule) -> VMResult<()> { verify_module_with_config(&VerifierConfig::default(), module) } -pub fn verify_module_with_config_for_test( - name: &str, - config: &VerifierConfig, - module: &CompiledModule, -) -> VMResult<()> { - const MAX_MODULE_SIZE: usize = 65355; - let mut bytes = vec![]; - module.serialize(&mut bytes).unwrap(); - let now = Instant::now(); - let result = verify_module_with_config(config, module); - eprintln!( - "--> {}: verification time: {:.3}ms, result: {}, size: {}kb", - name, - (now.elapsed().as_micros() as f64) / 1000.0, - if let Err(e) = &result { - format!("{:?}", e.major_status()) - } else { - "Ok".to_string() - }, - bytes.len() / 1000 - ); - // Also check whether the module actually fits into our payload size - assert!( - bytes.len() <= MAX_MODULE_SIZE, - "test module exceeds size limit {} (given size {})", - MAX_MODULE_SIZE, - bytes.len() - ); - result -} - pub fn verify_module_with_config(config: &VerifierConfig, module: &CompiledModule) -> VMResult<()> { - let prev_state = move_core_types::state::set_state(VMState::VERIFIER); - let result = std::panic::catch_unwind(|| { - BoundsChecker::verify_module(module).map_err(|e| { - // We can't point the error at the module, because if bounds-checking - // failed, we cannot safely index into module's handle to itself. - e.finish(Location::Undefined) - })?; - LimitsVerifier::verify_module(config, module)?; - DuplicationChecker::verify_module(module)?; - SignatureChecker::verify_module(module)?; - InstructionConsistency::verify_module(module)?; - constants::verify_module(module)?; - friends::verify_module(module)?; - ability_field_requirements::verify_module(module)?; - RecursiveStructDefChecker::verify_module(module)?; - InstantiationLoopChecker::verify_module(module)?; - CodeUnitVerifier::verify_module(config, module)?; - - // Add the failpoint injection to test the catch_unwind behavior. - fail::fail_point!("verifier-failpoint-panic"); - - script_signature::verify_module(module, no_additional_script_signature_checks) - }) - .unwrap_or_else(|_| { - Err( - PartialVMError::new(StatusCode::VERIFIER_INVARIANT_VIOLATION) - .finish(Location::Undefined), - ) - }); - move_core_types::state::set_state(prev_state); - result + BoundsChecker::verify_module(module).map_err(|e| { + // We can't point the error at the module, because if bounds-checking + // failed, we cannot safely index into module's handle to itself. + e.finish(Location::Undefined) + })?; + LimitsVerifier::verify_module(config, module)?; + DuplicationChecker::verify_module(module)?; + SignatureChecker::verify_module(module)?; + InstructionConsistency::verify_module(module)?; + constants::verify_module(module)?; + friends::verify_module(module)?; + ability_field_requirements::verify_module(module)?; + RecursiveStructDefChecker::verify_module(module)?; + InstantiationLoopChecker::verify_module(module)?; + CodeUnitVerifier::verify_module(config, module)?; + script_signature::verify_module(module, no_additional_script_signature_checks) } /// Helper for a "canonical" verification of a script. @@ -133,26 +80,14 @@ pub fn verify_script(script: &CompiledScript) -> VMResult<()> { } pub fn verify_script_with_config(config: &VerifierConfig, script: &CompiledScript) -> VMResult<()> { - let prev_state = move_core_types::state::set_state(VMState::VERIFIER); - let result = std::panic::catch_unwind(|| { - BoundsChecker::verify_script(script).map_err(|e| e.finish(Location::Script))?; - LimitsVerifier::verify_script(config, script)?; - DuplicationChecker::verify_script(script)?; - SignatureChecker::verify_script(script)?; - InstructionConsistency::verify_script(script)?; - constants::verify_script(script)?; - CodeUnitVerifier::verify_script(config, script)?; - script_signature::verify_script(script, no_additional_script_signature_checks) - }) - .unwrap_or_else(|_| { - Err( - PartialVMError::new(StatusCode::VERIFIER_INVARIANT_VIOLATION) - .finish(Location::Undefined), - ) - }); - move_core_types::state::set_state(prev_state); - - result + BoundsChecker::verify_script(script).map_err(|e| e.finish(Location::Script))?; + LimitsVerifier::verify_script(config, script)?; + DuplicationChecker::verify_script(script)?; + SignatureChecker::verify_script(script)?; + InstructionConsistency::verify_script(script)?; + constants::verify_script(script)?; + CodeUnitVerifier::verify_script(config, script)?; + script_signature::verify_script(script, no_additional_script_signature_checks) } impl Default for VerifierConfig { @@ -181,24 +116,6 @@ impl Default for VerifierConfig { // max_struct_definitions: Some(200), // max_fields_in_struct: Some(30), // max_function_definitions: Some(1000), - max_back_edges_per_function: None, - max_back_edges_per_module: None, - max_basic_blocks_in_script: None, - /// General metering for the verifier. This defaults to a bound which should align - /// with production, so all existing test cases apply it. - max_per_fun_meter_units: Some(1000 * 8000), - max_per_mod_meter_units: Some(1000 * 8000), - } - } -} - -impl VerifierConfig { - /// Returns truly unbounded config, even relaxing metering. - pub fn unbounded() -> Self { - Self { - max_per_fun_meter_units: None, - max_per_mod_meter_units: None, - ..VerifierConfig::default() } } } diff --git a/language/move-bytecode-verifier/transactional-tests/tests/reference_safety/call_function_with_many_acquires.exp b/language/move-bytecode-verifier/transactional-tests/tests/reference_safety/call_function_with_many_acquires.exp deleted file mode 100644 index 17556441230..00000000000 --- a/language/move-bytecode-verifier/transactional-tests/tests/reference_safety/call_function_with_many_acquires.exp +++ /dev/null @@ -1,10 +0,0 @@ -processed 1 task - -task 0 'publish'. lines 2-416: -Error: Unable to publish module '00000000000000000000000000000042::pwn'. Got VMError: { - major_status: CONSTRAINT_NOT_SATISFIED, - sub_status: None, - location: 0x42::pwn, - indices: [(FunctionDefinition, 2)], - offsets: [], -} diff --git a/language/move-bytecode-verifier/transactional-tests/tests/reference_safety/call_function_with_many_acquires.move b/language/move-bytecode-verifier/transactional-tests/tests/reference_safety/call_function_with_many_acquires.move deleted file mode 100644 index ad72e381c00..00000000000 --- a/language/move-bytecode-verifier/transactional-tests/tests/reference_safety/call_function_with_many_acquires.move +++ /dev/null @@ -1,416 +0,0 @@ -// See also: github.com/aptos-labs/aptos-core/security/advisories/GHSA-7v29-m9hj-jxjf -//# publish -module 0x42::pwn { - struct R1 has key {f:u8} - struct R2 has key {f:u8} - struct R3 has key {f:u8} - struct R4 has key {f:u8} - struct R5 has key {f:u8} - struct R6 has key {f:u8} - struct R7 has key {f:u8} - struct R8 has key {f:u8} - struct R9 has key {f:u8} - struct R10 has key {f:u8} - struct R11 has key {f:u8} - struct R12 has key {f:u8} - struct R13 has key {f:u8} - struct R14 has key {f:u8} - struct R15 has key {f:u8} - struct R16 has key {f:u8} - struct R17 has key {f:u8} - struct R18 has key {f:u8} - struct R19 has key {f:u8} - struct R20 has key {f:u8} - struct R21 has key {f:u8} - struct R22 has key {f:u8} - struct R23 has key {f:u8} - struct R24 has key {f:u8} - struct R25 has key {f:u8} - struct R26 has key {f:u8} - struct R27 has key {f:u8} - struct R28 has key {f:u8} - struct R29 has key {f:u8} - struct R30 has key {f:u8} - struct R31 has key {f:u8} - struct R32 has key {f:u8} - struct R33 has key {f:u8} - struct R34 has key {f:u8} - struct R35 has key {f:u8} - struct R36 has key {f:u8} - struct R37 has key {f:u8} - struct R38 has key {f:u8} - struct R39 has key {f:u8} - struct R40 has key {f:u8} - struct R41 has key {f:u8} - struct R42 has key {f:u8} - struct R43 has key {f:u8} - struct R44 has key {f:u8} - struct R45 has key {f:u8} - struct R46 has key {f:u8} - struct R47 has key {f:u8} - struct R48 has key {f:u8} - struct R49 has key {f:u8} - struct R50 has key {f:u8} - struct R51 has key {f:u8} - struct R52 has key {f:u8} - struct R53 has key {f:u8} - struct R54 has key {f:u8} - struct R55 has key {f:u8} - struct R56 has key {f:u8} - struct R57 has key {f:u8} - struct R58 has key {f:u8} - struct R59 has key {f:u8} - struct R60 has key {f:u8} - struct R61 has key {f:u8} - struct R62 has key {f:u8} - struct R63 has key {f:u8} - struct R64 has key {f:u8} - struct R65 has key {f:u8} - struct R66 has key {f:u8} - struct R67 has key {f:u8} - struct R68 has key {f:u8} - struct R69 has key {f:u8} - struct R70 has key {f:u8} - struct R71 has key {f:u8} - struct R72 has key {f:u8} - struct R73 has key {f:u8} - struct R74 has key {f:u8} - struct R75 has key {f:u8} - struct R76 has key {f:u8} - struct R77 has key {f:u8} - struct R78 has key {f:u8} - struct R79 has key {f:u8} - struct R80 has key {f:u8} - struct R81 has key {f:u8} - struct R82 has key {f:u8} - struct R83 has key {f:u8} - struct R84 has key {f:u8} - struct R85 has key {f:u8} - struct R86 has key {f:u8} - struct R87 has key {f:u8} - struct R88 has key {f:u8} - struct R89 has key {f:u8} - struct R90 has key {f:u8} - struct R91 has key {f:u8} - struct R92 has key {f:u8} - struct R93 has key {f:u8} - struct R94 has key {f:u8} - struct R95 has key {f:u8} - struct R96 has key {f:u8} - struct R97 has key {f:u8} - struct R98 has key {f:u8} - struct R99 has key {f:u8} - struct R100 has key {f:u8} - struct R101 has key {f:u8} - struct R102 has key {f:u8} - struct R103 has key {f:u8} - struct R104 has key {f:u8} - struct R105 has key {f:u8} - struct R106 has key {f:u8} - struct R107 has key {f:u8} - struct R108 has key {f:u8} - struct R109 has key {f:u8} - struct R110 has key {f:u8} - struct R111 has key {f:u8} - struct R112 has key {f:u8} - struct R113 has key {f:u8} - struct R114 has key {f:u8} - struct R115 has key {f:u8} - struct R116 has key {f:u8} - struct R117 has key {f:u8} - struct R118 has key {f:u8} - struct R119 has key {f:u8} - struct R120 has key {f:u8} - struct R121 has key {f:u8} - struct R122 has key {f:u8} - struct R123 has key {f:u8} - struct R124 has key {f:u8} - struct R125 has key {f:u8} - struct R126 has key {f:u8} - struct R127 has key {f:u8} - struct R128 has key {f:u8} - struct R129 has key {f:u8} - struct R130 has key {f:u8} - struct R131 has key {f:u8} - struct R132 has key {f:u8} - struct R133 has key {f:u8} - struct R134 has key {f:u8} - struct R135 has key {f:u8} - struct R136 has key {f:u8} - struct R137 has key {f:u8} - struct R138 has key {f:u8} - struct R139 has key {f:u8} - struct R140 has key {f:u8} - struct R141 has key {f:u8} - struct R142 has key {f:u8} - struct R143 has key {f:u8} - struct R144 has key {f:u8} - struct R145 has key {f:u8} - struct R146 has key {f:u8} - struct R147 has key {f:u8} - struct R148 has key {f:u8} - struct R149 has key {f:u8} - struct R150 has key {f:u8} - struct R151 has key {f:u8} - struct R152 has key {f:u8} - struct R153 has key {f:u8} - struct R154 has key {f:u8} - struct R155 has key {f:u8} - struct R156 has key {f:u8} - struct R157 has key {f:u8} - struct R158 has key {f:u8} - struct R159 has key {f:u8} - struct R160 has key {f:u8} - struct R161 has key {f:u8} - struct R162 has key {f:u8} - struct R163 has key {f:u8} - struct R164 has key {f:u8} - struct R165 has key {f:u8} - struct R166 has key {f:u8} - struct R167 has key {f:u8} - struct R168 has key {f:u8} - struct R169 has key {f:u8} - struct R170 has key {f:u8} - struct R171 has key {f:u8} - struct R172 has key {f:u8} - struct R173 has key {f:u8} - struct R174 has key {f:u8} - struct R175 has key {f:u8} - struct R176 has key {f:u8} - struct R177 has key {f:u8} - struct R178 has key {f:u8} - struct R179 has key {f:u8} - struct R180 has key {f:u8} - struct R181 has key {f:u8} - struct R182 has key {f:u8} - struct R183 has key {f:u8} - struct R184 has key {f:u8} - struct R185 has key {f:u8} - struct R186 has key {f:u8} - struct R187 has key {f:u8} - struct R188 has key {f:u8} - struct R189 has key {f:u8} - struct R190 has key {f:u8} - struct R191 has key {f:u8} - struct R192 has key {f:u8} - struct R193 has key {f:u8} - struct R194 has key {f:u8} - struct R195 has key {f:u8} - struct R196 has key {f:u8} - struct R197 has key {f:u8} - struct R198 has key {f:u8} - struct R199 has key {f:u8} - - const ADDRESS: address = @0x0; - - public fun get_address(): address { - ADDRESS - } - - public fun f() acquires R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31, R32, R33, R34, R35, R36, R37, R38, R39, R40, R41, R42, R43, R44, R45, R46, R47, R48, R49, R50, R51, R52, R53, R54, R55, R56, R57, R58, R59, R60, R61, R62, R63, R64, R65, R66, R67, R68, R69, R70, R71, R72, R73, R74, R75, R76, R77, R78, R79, R80, R81, R82, R83, R84, R85, R86, R87, R88, R89, R90, R91, R92, R93, R94, R95, R96, R97, R98, R99, R100, R101, R102, R103, R104, R105, R106, R107, R108, R109, R110, R111, R112, R113, R114, R115, R116, R117, R118, R119, R120, R121, R122, R123, R124, R125, R126, R127, R128, R129, R130, R131, R132, R133, R134, R135, R136, R137, R138, R139, R140, R141, R142, R143, R144, R145, R146, R147, R148, R149, R150, R151, R152, R153, R154, R155, R156, R157, R158, R159, R160, R161, R162, R163, R164, R165, R166, R167, R168, R169, R170, R171, R172, R173, R174, R175, R176, R177, R178, R179, R180, R181, R182, R183, R184, R185, R186, R187, R188, R189, R190, R191, R192, R193, R194, R195, R196, R197, R198, R199 { - let a = get_address(); - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - borrow_global(a).f; - } - - public fun pwn() acquires R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31, R32, R33, R34, R35, R36, R37, R38, R39, R40, R41, R42, R43, R44, R45, R46, R47, R48, R49, R50, R51, R52, R53, R54, R55, R56, R57, R58, R59, R60, R61, R62, R63, R64, R65, R66, R67, R68, R69, R70, R71, R72, R73, R74, R75, R76, R77, R78, R79, R80, R81, R82, R83, R84, R85, R86, R87, R88, R89, R90, R91, R92, R93, R94, R95, R96, R97, R98, R99, R100, R101, R102, R103, R104, R105, R106, R107, R108, R109, R110, R111, R112, R113, R114, R115, R116, R117, R118, R119, R120, R121, R122, R123, R124, R125, R126, R127, R128, R129, R130, R131, R132, R133, R134, R135, R136, R137, R138, R139, R140, R141, R142, R143, R144, R145, R146, R147, R148, R149, R150, R151, R152, R153, R154, R155, R156, R157, R158, R159, R160, R161, R162, R163, R164, R165, R166, R167, R168, R169, R170, R171, R172, R173, R174, R175, R176, R177, R178, R179, R180, R181, R182, R183, R184, R185, R186, R187, R188, R189, R190, R191, R192, R193, R194, R195, R196, R197, R198, R199 { - f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f();f(); - } -} diff --git a/language/move-compiler/src/expansion/ast.rs b/language/move-compiler/src/expansion/ast.rs index 8ce89ea01ce..584bb5faace 100644 --- a/language/move-compiler/src/expansion/ast.rs +++ b/language/move-compiler/src/expansion/ast.rs @@ -36,7 +36,6 @@ pub struct Program { //************************************************************************************************** #[derive(Debug, Clone, PartialEq, Eq)] -#[allow(clippy::large_enum_variant)] pub enum AttributeValue_ { Value(Value), Module(ModuleIdent), @@ -327,7 +326,6 @@ pub enum PragmaValue { pub struct AbilitySet(UniqueSet); #[derive(Debug, Clone, PartialEq, Eq)] -#[allow(clippy::large_enum_variant)] pub enum ModuleAccess_ { Name(Name), ModuleAccess(ModuleIdent, Name), diff --git a/language/move-compiler/src/expansion/dependency_ordering.rs b/language/move-compiler/src/expansion/dependency_ordering.rs index 4836efceb0f..3d336d9f35f 100644 --- a/language/move-compiler/src/expansion/dependency_ordering.rs +++ b/language/move-compiler/src/expansion/dependency_ordering.rs @@ -78,7 +78,6 @@ enum DepType { } #[derive(Clone, Eq, PartialEq, Ord, PartialOrd)] -#[allow(clippy::large_enum_variant)] enum NodeIdent { Module(ModuleIdent), Script(Symbol), diff --git a/language/move-core/types/src/account_address.rs b/language/move-core/types/src/account_address.rs index 6fa8c274fd9..2a5a4a70aa2 100644 --- a/language/move-core/types/src/account_address.rs +++ b/language/move-core/types/src/account_address.rs @@ -55,21 +55,12 @@ impl AccountAddress { /// Hex address: 0x1 pub const ONE: Self = Self::get_hex_address_one(); - /// Hex address: 0x2 - pub const TWO: Self = Self::get_hex_address_two(); - const fn get_hex_address_one() -> Self { let mut addr = [0u8; AccountAddress::LENGTH]; addr[AccountAddress::LENGTH - 1] = 1u8; Self(addr) } - const fn get_hex_address_two() -> Self { - let mut addr = [0u8; AccountAddress::LENGTH]; - addr[AccountAddress::LENGTH - 1] = 2u8; - Self(addr) - } - pub fn random() -> Self { let mut rng = OsRng; let buf: [u8; Self::LENGTH] = rng.gen(); diff --git a/language/move-core/types/src/lib.rs b/language/move-core/types/src/lib.rs index f457d2544f2..4df60d6730f 100644 --- a/language/move-core/types/src/lib.rs +++ b/language/move-core/types/src/lib.rs @@ -17,7 +17,6 @@ pub mod parser; #[cfg(any(test, feature = "fuzzing"))] pub mod proptest_types; pub mod resolver; -pub mod state; pub mod transaction_argument; pub mod u256; #[cfg(test)] diff --git a/language/move-core/types/src/state.rs b/language/move-core/types/src/state.rs deleted file mode 100644 index 6d94c574a9d..00000000000 --- a/language/move-core/types/src/state.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// SPDX-License-Identifier: Apache-2.0 - -use std::cell::RefCell; - -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum VMState { - DESERIALIZER, - VERIFIER, - RUNTIME, - OTHER, -} - -thread_local! { - static STATE: RefCell = RefCell::new(VMState::OTHER); -} - -pub fn set_state(state: VMState) -> VMState { - STATE.with(|s| s.replace(state)) -} - -pub fn get_state() -> VMState { - STATE.with(|s| *s.borrow()) -} diff --git a/language/move-core/types/src/vm_status.rs b/language/move-core/types/src/vm_status.rs index 3fb417fc88f..56213a3aa16 100644 --- a/language/move-core/types/src/vm_status.rs +++ b/language/move-core/types/src/vm_status.rs @@ -641,14 +641,6 @@ pub enum StatusCode { MAX_STRUCT_DEFINITIONS_REACHED = 1120, MAX_FIELD_DEFINITIONS_REACHED = 1121, - // Reserved error code for future use - TOO_MANY_BACK_EDGES = 1122, - RESERVED_VERIFICATION_ERROR_1 = 1123, - RESERVED_VERIFICATION_ERROR_2 = 1124, - RESERVED_VERIFICATION_ERROR_3 = 1125, - RESERVED_VERIFICATION_ERROR_4 = 1126, - RESERVED_VERIFICATION_ERROR_5 = 1127, - // These are errors that the VM might raise if a violation of internal // invariants takes place. // Invariant Violation Errors: 2000-2999 diff --git a/language/move-ir-compiler/src/unit_tests/function_tests.rs b/language/move-ir-compiler/src/unit_tests/function_tests.rs index a5af5b05534..42dc9cecc98 100644 --- a/language/move-ir-compiler/src/unit_tests/function_tests.rs +++ b/language/move-ir-compiler/src/unit_tests/function_tests.rs @@ -43,9 +43,8 @@ fn compile_module_with_large_frame() { ", ); - // Default metering in place, so use reasonable values. This may need to be changed - // when the metering changes, and gives a useful signal. - code.push_str(&generate_function("foo_func", 64, 90)); + // Max number of locals (formals + local variables) is u8::max_value(). + code.push_str(&generate_function("foo_func", 128, 127)); code.push('}'); diff --git a/language/move-prover/interpreter-testsuite/tests/concrete_check/bcs.move b/language/move-prover/interpreter-testsuite/tests/concrete_check/bcs.move index c6087dbd209..d0eecca9f38 100644 --- a/language/move-prover/interpreter-testsuite/tests/concrete_check/bcs.move +++ b/language/move-prover/interpreter-testsuite/tests/concrete_check/bcs.move @@ -4,11 +4,9 @@ module 0x2::A { #[test] public fun bcs_ops() { // address - /* deactivate because of variable address size let addr = @0x89b9f9d1fadc027cf9532d6f99041522; let expected_output = x"89b9f9d1fadc027cf9532d6f99041522"; assert!(bcs::to_bytes(&addr) == expected_output, 8001); - */ // bool let b = true; diff --git a/language/move-vm/integration-tests/src/tests/loader_tests.rs b/language/move-vm/integration-tests/src/tests/loader_tests.rs index a61b0a550e1..1a78443a4e4 100644 --- a/language/move-vm/integration-tests/src/tests/loader_tests.rs +++ b/language/move-vm/integration-tests/src/tests/loader_tests.rs @@ -21,7 +21,8 @@ use move_vm_types::gas::UnmeteredGasMeter; use std::{path::PathBuf, sync::Arc, thread}; -const WORKING_ACCOUNT: AccountAddress = AccountAddress::TWO; +const WORKING_ACCOUNT: AccountAddress = + AccountAddress::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]); struct Adapter { store: InMemoryStorage,